Entry points¶
Build a drawing¶
build_drawing(step_file, out=None, title=None, number='DWG-001', tolerance=None, drawn_by='', scale=None, page=None, auto_dims=True, detail_view=True, pmi=None, repair=True, assembly=None, model=None, decorations=None, requested=None, authored=None, trace=None, material='', date='', revision='A', company='', frame=False, projection=None, zones=False, scale_policy='fallback', reproducible=True, framed_recognition=False, text_position='inline', text_orientation='aligned', _post_build=None, _required_tables=(), _views=None, _include_iso=True, _view_constraints=None, _document_input=None, *, _analysis_base=None, _analysis_sink=None, projection_symbol=True, source=None, approved_by='', document_type='', sheet='', margin_left=None, margin_right=None, margin_top=None, margin_bottom=None, title_block_width=None, leader_region='auto', annotation_layout='demand-guided', _replayed_scale=None)
¶
Build a drawing, protecting required annotations under an explicit scale.
scale_policy applies only when scale is supplied. "fallback" (the safe
default) retries smaller preferred ISO 5455 scales and returns the largest one with no
required placement drop. "strict" raises :class:ScaleIncompatibilityError instead.
"permissive" explicitly opts into the historical best-effort result and warns when
it is degraded. Every returned drawing exposes the JSON-friendly decision through
:attr:Drawing.scale_decision; :attr:Drawing.scale is the effective scale.
Pass framed_recognition=True to opt an automatic build into the provider-owned local
recognition frame. Raw remains the default. Other arguments and return semantics are
unchanged from the one-pass builder.
Third-angle layout and its matching projection symbol are the default.
projection_symbol=False suppresses only the symbol. projection='first' places plan below
front and side to its left, keeping the physical viewing directions unchanged.
text_position="inline"|"above" and text_orientation="aligned"|"horizontal"
independently select dimension typography. Defaults preserve existing appearance.
leader_region="auto"|"interior"|"exterior" controls the candidate regions for
feature-leader labels without specifying page coordinates. "auto" preserves the
normal shared solve, "exterior" restores the historical exterior-only inventory,
and "interior" requires interior candidates where the feature family has proved
them. Explicit per-feature side= constraints remain exterior.
annotation_layout="compare" evaluates an alternative on the settled sheet and
scale, retaining the existing layout unless finished-drawing semantic parity and
layout quality prove a strict gain. The default "demand-guided" selects
a profile before rendering in one build, without a comparison.
"estimated-strips" uses the original feature-estimated reservations.
The original spellings "best", "candidate-preview", and "baseline"
remain accepted aliases.
Build and export in one call¶
make_drawing(step_file, out=None, title=None, number='DWG-001', tolerance=None, drawn_by='', scale=None, page=None, auto_dims=True, detail_view=True, pmi=None, assembly=None, material='', date='', revision='A', company='', frame=False, projection=None, zones=False, scale_policy='fallback', reproducible=True, framed_recognition=False, text_position='inline', text_orientation='aligned', *, projection_symbol=True, source=None, approved_by='', document_type='', sheet='', margin_left=None, margin_right=None, margin_top=None, margin_bottom=None, title_block_width=None, leader_region='auto', annotation_layout='demand-guided')
¶
Generate a technical drawing from a STEP file or build123d object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
step_file
|
str | Path | Shape
|
Path to a STEP/STP file, or a build123d |
required |
out
|
str | None
|
Output path stem (default: input filename stem, or |
None
|
title
|
str | None
|
Part title for the title block (default: stem uppercased). |
None
|
number
|
str
|
Drawing number (e.g. |
'DWG-001'
|
tolerance
|
str | None
|
General tolerance string (e.g. |
None
|
drawn_by
|
str
|
Designer name for the title block. |
''
|
scale
|
float | None
|
Drawing-scale override (e.g. |
None
|
scale_policy
|
Literal['strict', 'fallback', 'permissive']
|
required-annotation policy for an explicit |
'fallback'
|
page
|
str | tuple | None
|
Page-size override — an ISO name ( |
None
|
auto_dims
|
bool
|
pass |
True
|
detail_view
|
bool
|
automatically add an enlarged view for crowded prismatic step
dimensions. Default |
True
|
reproducible
|
bool
|
make repeated exports from the returned drawing byte-identical
on the same Draftwright version. On by default; pass |
True
|
framed_recognition
|
bool
|
opt an automatic build into the provider-owned local recognition frame. Raw remains the default rollout path. |
False
|
leader_region
|
Literal['auto', 'interior', 'exterior']
|
feature-leader label region policy. |
'auto'
|
annotation_layout
|
Literal['estimated-strips', 'demand-guided', 'compare', 'baseline', 'candidate-preview', 'best']
|
|
'demand-guided'
|
Returns:
| Type | Description |
|---|---|
tuple[str, str]
|
Tuple of |
This is a thin wrapper: make_drawing(...) is
build_drawing(...).export(formats=("svg", "dxf")), unpacked to a tuple.
To add or remove annotations or add section/auxiliary views before export,
call :func:build_drawing and use the returned :class:Drawing.
Inspect a STEP file without drawing it¶
inspect_step(path)
¶
Return the recognition evidence for the STEP file at path.
The source is resolved once and read once; recognition consumes a private copy of those exact hashed bytes, so replacing a mutable or symlinked source mid-inspection cannot make the document describe two different files.
Exactly one aggregate recognition run happens, and its evidence, model and conversion-time ownership are reused as-is. No drawing build, view projection, annotation placement, render, export or physical lint path runs.
It does, however, share the engine's ONE detect seam, which sizes the part while
detecting, so some scale-selection and dimension-planning work is done and discarded.
Measured, that is about 0.02% of an inspection — the cost is recognition and STEP
parsing — so the shared seam stays rather than growing a second one that could not be
checked against the drawing path. Evidence and method:
docs/research/1462-inspect-seam-cost.md.
Raises:
| Type | Description |
|---|---|
OSError
|
the path could not be read (missing, a directory, permissions). |
InspectionUnavailableError
|
the bytes are not a readable solid STEP body, or the run cannot state its evidence truthfully. |
Observe progress and request cancellation¶
observe_build() reports activity from the existing pipeline. It works around automatic
build_drawing() calls, Sheet.build(), and subsequent lint, repair, deferred edits and
Drawing.export() calls. It does not select views, change search limits or relax requirements.
from draftwright import BuildCancelled, build_drawing, observe_build
try:
with observe_build(lambda event: print(event.to_dict())) as control:
drawing = build_drawing("part.step")
drawing.export("out", formats=("pdf",))
# A UI or another thread can call control.cancel("user request").
except BuildCancelled as error:
print(error.diagnostic)
Each immutable event carries a stage path, phase, elapsed seconds for the observation context
and current stage, and details such as projection view or the existing retry/budget reason.
There is no estimated percentage. Callbacks run synchronously; keep them short. Ordinary
callback exceptions disable notifications with a warning so a broken observer does not abort
the drawing. Use control.cancel() to stop deliberately. Observation scopes are context-local;
enter the context in the thread doing the build and pass its controller to the cancelling UI.
Cancellation is cooperative. Checkpoints run between stages and during repeated leader
candidate/mesh work. A native CAD call must return before a Python checkpoint can execute;
this API supplies no hard kernel timeout. Ctrl-C inside the context raises the same
BuildCancelled, a KeyboardInterrupt subclass carrying a JSON-serializable diagnostic.
Cancelled and failed stages are distinct from finished stages.
No internal search candidate is returned on cancellation. If the public build has finished
and cancellation arrives at its publication boundary, error.completed_result contains that
normal mutable Drawing; otherwise it is None. It is not a snapshot or a manufacturing
approval. During a later export cancellation the caller already owns drawing; no earlier
build is attached to the exception. Deferred edits roll back interrupted placement; repair
rolls back a provisional change if its critique is interrupted. Already accepted edits and
files written before an export interruption are not undone.
The direct-render CLI displays a live stage and elapsed time on stderr in a terminal.
When redirected it emits no live controls; --verbose emits plain stage events to stderr.
--no-progress disables both forms. Output paths remain on stdout. Ctrl-C prints the
cancellation diagnostic to stderr and exits with code 130. --script generation does not use
this display.
CLI output destinations¶
The CLI defaults to writing beside the supplied STEP input. For example,
draftwright /parts/frame.step --format all writes /parts/frame.svg, .dxf, .pdf,
.png, and .draftwright.json. --script writes /parts/frame.py and its recognition
inspection sidecar; replay uses the destination selected when the script was generated and
writes /parts/frame.draftwright-assessment.json after a successful build/export. See
generated-script replay assessment for why the two JSON files have
separate schemas and authority.
Use --out-dir . to write into the current working directory, --out-dir drawings to
create/use a destination directory, or --out drawings/revised-frame to choose a prefix.
--out and --out-dir are mutually exclusive. Relative overrides are resolved at invocation.
For a live object script (module:part or file.py:part), the default is drawing.py in the
working directory; --out-dir places that basename in the requested directory.
This changes the CLI default for STEP inputs outside the working directory. Python API output defaults are unchanged. Every CLI prints its written artifact paths on stdout.