Milling API reference (developers)¶
This page documents the milling public API and the internal structure of
mfgparams.processes.machining.milling for contributors adding or extending
milling behaviour. For end-user CLI guidance see Milling calculations (user guide).
Public entry points¶
All four names are importable directly from mfgparams.
calculate_end_milling(...)calculate_end_milling( diameter, axial_depth_of_cut, radial_depth_of_cut, feed_per_tooth, number_of_teeth, length_of_cut, material, tool, unit_system=UnitSystem.METRIC, available_power=None, config_path=None, locale="en", materials_config_path=None, mode=CalculationMode.STANDARD, target_rpm=None, ) -> CalculationResult
calculate_face_milling(...)Identical, except that
radial_depth_of_cutis namedwidth_of_cut.list_end_mill_tools(config_path=None) -> list[str]Names of the available end-mill tools, in catalog order.
list_face_mill_tools(config_path=None) -> list[str]Names of the available face-mill tools, in catalog order.
Length inputs (diameter, the depths/width, feed_per_tooth and
length_of_cut) are interpreted in the caller’s unit_system: mm under
METRIC and inches under IMPERIAL. They are converted to canonical
millimetres internally and the results converted back, so a metric call and
the equivalent imperial call describe the same physical cut.
Results and errors¶
Both functions return a CalculationResult and
never raise for an expected validation failure. On success every numeric
field is populated, including material_removal_rate (cm³/min under
metric, in³/min under imperial). On failure error is an
ErrorInfo with a stable code and a
translated message, and every numeric field — including
material_removal_rate — is None.
Error codes reused from drilling: INVALID_DIAMETER,
MISSING_MATERIAL, MISSING_TOOL, UNUSABLE_MATERIAL. Codes specific
to milling: INVALID_DEPTH_OF_CUT, INVALID_ENGAGEMENT,
INVALID_FEED_PER_TOOTH, INVALID_TOOTH_COUNT,
INVALID_LENGTH_OF_CUT. Codes reused from drilling’s calculation modes
(002-constrained-calculation-modes): INFEASIBLE_POWER_BUDGET,
INVALID_TARGET_RPM, MODE_CONFLICT (see “Calculation modes” below).
Two codes are new in 010-milling-calculation-modes:
INVALID_AVAILABLE_POWER (a non-numeric, non-finite, or non-positive
available_power supplied as the optional advisory value in
STANDARD or FIXED_RPM mode — see “Calculation modes” below for
the distinct POWER_CONSTRAINED error mapping) and
CALCULATION_OVERFLOW (an otherwise-valid extreme input that overflows
an intermediate calculation).
Validation runs in a fixed order, so a call with several invalid inputs
always reports the same first failure. material and tool presence are
checked first, then the material and tool are resolved, then the geometry,
then — last — the mode/target_rpm combination.
Calculation modes¶
Both entry points accept the same mode/target_rpm/available_power
arguments as mfgparams.calculate() (drilling), added by
010-milling-calculation-modes:
CalculationMode.STANDARD(default)Unconstrained calculation, unchanged from
009-milling-calculations.available_powerremains optional/advisory: an exceeded budget setsfeasibility_warningwithout altering the result. A supplied but non-numeric, non-finite, or non-positiveavailable_powerreturnsINVALID_AVAILABLE_POWER;None(omitted) is always valid.CalculationMode.POWER_CONSTRAINEDavailable_powerbecomes required: a missing value (None) returnsMODE_CONFLICT, the same as also supplyingtarget_rpmin this mode. A supplied but invalid (non-numeric, non-finite, zero, or negative)available_powerreturnsINFEASIBLE_POWER_BUDGET— notINVALID_AVAILABLE_POWER, which is reserved for the advisory-power path inSTANDARD/FIXED_RPM— since no spindle speed could ever meet it either way. If it is at least the STANDARD-mode power requirement the result is a no-op (identical to STANDARD, onlymodediffers). Otherwise the spindle speed is reduced so thatpower_requiredmatchesavailable_powerexactly (withinmath.isclose(rel_tol=1e-9)); torque is unaffected, since it does not depend on spindle speed. An otherwise-valid extreme input that overflows an intermediate calculation returnsCALCULATION_OVERFLOW.CalculationMode.FIXED_RPMtarget_rpmbecomes required and is echoed back exactly asspindle_speed_rpm; every dependent field is recomputed at that spindle speed.available_powerstays optional/advisory here too, with the sameINVALID_AVAILABLE_POWERcheck asSTANDARDmode’s advisory power. A missing, non-numeric, non-positive or non-finitetarget_rpmreturnsINVALID_TARGET_RPM. An otherwise-valid extreme input that overflows an intermediate calculation returnsCALCULATION_OVERFLOW.
Supplying both target_rpm and POWER_CONSTRAINED mode is rejected as
MODE_CONFLICT (FR-009) rather than silently picking one.
Package layout¶
mfgparams/processes/machining/milling/
_shared.py formulas common to both sub-operations
_tool_registry.py MillingTool base + build_registry()
_calculate.py shared validate/convert/assemble orchestration
end_milling/
__init__.py calculate_end_milling / list_end_mill_tools
formulas.py EndMillingMetrics wrapper over _shared
tools.py EndMillTool registry
data/tools.toml bundled end-mill catalog
face_milling/ same shape, for face milling
Both sub-operations are peers: neither imports the other, and neither imports
processes.machining.drilling. Everything shared between operations lives in the
top-level modules (config, models, units, validation,
registry, i18n). This boundary is enforced statically by
tests/contract/test_library_api_milling.py.
_calculate.calculate_milling() holds the single copy of the validation,
unit-conversion and result-assembly sequence. It stays generic over the two
sub-operations by taking four injection points:
resolve_toolLooks a tool name up in that sub-operation’s registry.
computeThe sub-operation’s own
formulas.pyadapter. Routing through it — not straight to_shared— is what keeps each sub-operation’s module boundary meaningful, so a sub-operation can diverge from the shared model without touching the other.engagement_label_keyThe message-catalog key naming the radial input, so validation errors say “Radial depth of cut” for end milling and “Width of cut” for face milling.
compute_at_rpmThe sub-operation’s
formulas.pyat-RPM adapter, used instead ofcomputewhenmodeisPOWER_CONSTRAINEDorFIXED_RPM(010-milling-calculation-modes), so each sub-operation supplies its own fixed-spindle-speed metrics rather than sharing one implementation across both.
The compute callable returns anything satisfying the
MillingMetricsLike protocol. Its members are declared as read-only
properties because the concrete metrics types are frozen dataclasses.
Adding a milling sub-operation¶
Create
processes/machining/milling/<name>/with__init__.py,formulas.py,tools.pyanddata/tools.toml.Give the TOML catalog a table key unique across all operations (drilling uses
tools, end millingend_mill_tools, face millingface_mill_tools). Reusing another operation’s key will make that operation’s loader try to parse your entries.Register the data file in
pyproject.toml’s[tool.setuptools.package-data].Build the registry with
_tool_registry.build_registry()and implementformulas.pyas a thin adapter over_shared.Implement the entry point by delegating to
_calculate.calculate_milling()with yourresolve_tool,computeandengagement_label_key.Add the sub-operation to
MillingSubOperation, add its prompts tomfgparams/console/locales/en.py(the console’s own catalog), and wire a session function intoconsole/cli.py.Re-export the entry point from
mfgparams/__init__.py.
Every user-facing string must be a catalog key, never inlined — prompts and
labels in the console’s catalog, error/warning/notice text in
mfgparams/locales/en.py (see the README’s “Adding or changing a
user-facing string” section) — and every formula must cite its source in a
docstring.
Formulas¶
_shared.py implements, in order: cutting speed to spindle speed, feed
rate from feed per tooth and tooth count, machining time from length of cut,
material removal rate from the engaged cross-section and feed rate, cutting
power from the specific cutting force (kc) and removal rate, and
torque from power and spindle speed. The engagement model is full and
symmetric, with no radial chip-thinning compensation. Sources are cited per
function; see specs/009-milling-calculations/research.md for the
decisions behind them.