Turning API reference (developers)

This page documents the turning public API and the internal structure of mfgparams.processes.machining.turning for contributors adding or extending turning behaviour. For end-user text-GUI guidance see Turning calculations (user guide).

Public entry points

Both names are importable directly from mfgparams.

calculate_turning(...)
calculate_turning(
    diameter,
    depth_of_cut,
    length_of_cut,
    material,
    tool,
    unit_system=UnitSystem.METRIC,
    available_power=None,
    config_path=None,
    locale="en",
    mode=CalculationMode.STANDARD,
    target_rpm=None,
    materials_config_path=None,
    target_feed_rate=None,
) -> CalculationResult
list_turning_tools(config_path=None) -> list[str]

Names of the available turning tools, in catalog order.

Length inputs (diameter, depth_of_cut, length_of_cut, target_feed_rate) are interpreted in the caller’s unit_system: mm (mm/rev for target_feed_rate) under METRIC and inches (in/rev) under IMPERIAL. They are converted to canonical millimetres internally and the results converted back. available_power follows the same per-unit_system convention: kW under METRIC, HP under IMPERIAL. cutting_force is reported in newtons under METRIC and lbf under IMPERIAL; feed_per_rotation (specs/020-turning-feed-per-rotation) in mm/rev under METRIC and in/rev under IMPERIAL.

Results and errors

calculate_turning returns a CalculationResult and never raises for an expected validation failure. On success every numeric field is populated, including cutting_force and feed_per_rotation; material_removal_rate stays None (that field is specific to milling). feed_per_rotation is purely additive: it does not change feed_rate’s own meaning or value, which stay exactly as they were before this field existed. On failure error is an ErrorInfo with a stable code and a translated message, and every numeric field — including cutting_force and feed_per_rotation — is None.

Error codes: turning has one turning-specific error code beyond what it originally shipped with — INVALID_TARGET_FEED_RATE (a supplied target_feed_rate that is zero, negative, non-numeric, or non-finite, or missing when mode is FEED_RATE_CONSTRAINED, ROTATION_AND_FEED_CONSTRAINED, or POWER_AND_FEED_CONSTRAINED). Every other validation failure reuses an existing code — INVALID_DIAMETER, INVALID_DEPTH_OF_CUT (including a depth-of-cut-exceeds-workpiece-radius case, a new message under the same code), INVALID_LENGTH_OF_CUT (reused verbatim from milling’s own length_of_cut input), MISSING_MATERIAL, MISSING_TOOL, UNUSABLE_MATERIAL, INVALID_TARGET_RPM, MODE_CONFLICT, and INFEASIBLE_POWER_BUDGET (also, for drilling and milling, UNSUPPORTED_MODE — see below). MODE_CONFLICT also covers, relative to the selected mode: supplying target_feed_rate together with target_rpm under FEED_RATE_CONSTRAINED specifically (which derives spindle speed and does not accept one directly – not a conflict under ROTATION_AND_FEED_CONSTRAINED, which requires both together as its own valid input); supplying target_feed_rate under any mode other than FEED_RATE_CONSTRAINED/ROTATION_AND_FEED_CONSTRAINED/ POWER_AND_FEED_CONSTRAINED; a target_rpm supplied under POWER_AND_FEED_CONSTRAINED (which solves for spindle speed rather than accepting one directly); or a missing available_power under POWER_AND_FEED_CONSTRAINED (an invalid-but-present one is INFEASIBLE_POWER_BUDGET instead, identical to POWER_CONSTRAINED’s own treatment).

Validation runs in the same fixed order as drilling: material and tool presence, then resolution, then geometry (diameter, then depth of cut — including the radius check — then length of cut), then — last — the mode/target_rpm/target_feed_rate combination.

Each of validate_turning_diameter_mm, validate_turning_depth_of_cut_mm, and validate_turning_length_of_cut_mm (in mfgparams.validation) checks its own turning-specific Configuration bound (max_turning_diameter_mm, max_turning_depth_of_cut_mm, max_turning_length_of_cut_mm) — distinct fields from drilling’s and milling’s own bounds, following the exact precedent validate_mill_diameter_mm/max_mill_diameter_mm already set alongside drilling’s validate_diameter_mm/max_diameter_mm.

Calculation modes

calculate_turning accepts the identical mode/target_rpm/ available_power contract drilling’s and milling’s entry points do (see Drilling API reference (developers)’s “Calculation modes” section for the full description). The only turning-specific detail: cutting force (like torque) is independent of spindle speed, so POWER_CONSTRAINED mode’s closed-form, non-iterative spindle-speed reduction carries over unchanged from drilling’s derivation, and FIXED_RPM mode’s cutting_force and torque values are identical to standard mode’s for the same geometry.

Turning also has three further modes, only calculate_turning implements. Drilling’s and milling’s own dispatch never construct these members, but since they live on the shared CalculationMode enum, a caller can still pass one directly to calculate()/ calculate_end_milling()/calculate_face_milling() — all three explicitly reject it with a structured UNSUPPORTED_MODE error rather than silently falling through to a standard-mode result mislabeled with that mode.

CalculationMode.FEED_RATE_CONSTRAINED (specs/020-turning-feed-per-rotation) derives spindle speed exactly as STANDARD (from cutting speed and diameter), then computes every dependent metric from the caller-supplied target_feed_rate instead of the material/tool’s reference feed value — so, unlike FIXED_RPM’s cutting_force/torque (unchanged from the nominal value), this mode’s cutting_force, torque, and power_required do change, since turning’s cutting force depends directly on feed per revolution (Fc = Kc * ap * fn).

CalculationMode.ROTATION_AND_FEED_CONSTRAINED and CalculationMode.POWER_AND_FEED_CONSTRAINED (specs/021-turning-combined-constraints) each reuse calculate_turning’s existing target_rpm/ available_power/target_feed_rate parameters — no new parameter, no new CalculationResult field. ROTATION_AND_FEED_CONSTRAINED requires both target_rpm and target_feed_rate supplied directly, neither derived — it is a direct call to calculate_turning_metrics_at_rpm() with both arguments supplied, no new formula function. POWER_AND_FEED_CONSTRAINED requires both available_power (a hard constraint, exactly as POWER_CONSTRAINED treats it) and target_feed_rate; spindle speed is solved to the highest value feasible within that power at that feed, using the same closed-form linear-scaling derivation POWER_CONSTRAINED uses, seeded from the caller-supplied feed instead of the material/tool-derived one – but never solved above the cutting-speed-derived reference speed at that feed (the same reference speed standard mode uses): a surplus of available power beyond what that reference speed requires does not raise the recommended spindle speed further, identical to POWER_CONSTRAINED’s own ceiling.

Package layout

mfgparams/processes/machining/turning/
    __init__.py         calculate_turning() and its validate/convert/assemble orchestration
    formulas.py          calculate_turning_metrics / calculate_turning_metrics_at_rpm /
                          calculate_turning_power_constrained_metrics /
                          calculate_turning_feed_rate_constrained_metrics
    tools.py              TurningTool registry
    data/tools.toml       bundled turning-tool catalog (HSS, Cobalt, Carbide)

Like drilling, turning has a single sub-operation, so it needs no shared orchestration layer analogous to milling’s _calculate.py — __init__.py implements calculate_turning() directly, mirroring processes/machining/drilling/__init__.py’s shape.

Formulas

formulas.py implements, in order: cutting speed to spindle speed (calculate_turning_metrics), feed rate from spindle speed and feed per revolution, machining time from length of cut and feed rate (no point-engagement allowance — a single-point turning tool has no drill-point geometry to account for), cutting force from the specific cutting force (kc), depth of cut, and feed per revolution — independent of spindle speed — torque from cutting force acting at the workpiece radius, and power from torque and spindle speed (calculate_turning_metrics_at_rpm). calculate_turning_power_constrained_metrics reuses the fact that torque is independent of spindle speed to solve for the reduced spindle speed algebraically, byte-for-byte the same derivation drilling’s calculate_power_constrained_metrics uses. calculate_turning_feed_rate_constrained_metrics derives spindle speed the same way, then calls calculate_turning_metrics_at_rpm with an explicit feed_per_rev_mm override instead of letting it derive that value from the material/tool — the same helper every other mode uses, extended with one optional parameter rather than duplicated. Sources are cited per function; see specs/019-turning-calculations/research.md and specs/020-turning-feed-per-rotation/research.md for the decisions behind them.