Skip to content

API Reference

This reference is generated from ldraw.__all__ at build time, then rendered from the exported objects' type annotations and docstrings with mkdocstrings.

Generated ldraw.library.* modules are intentionally not included because they depend on the locally downloaded LDraw release. Run ldraw generate and ldraw stubs in consuming projects for release-specific import and type-stub coverage.

ALL_CATALOG_SEARCH_FIELDS module-attribute

ALL_CATALOG_SEARCH_FIELDS = tuple(CatalogSearchField)

AnnularProfile dataclass

Axisymmetric tyre bead or wheel-rim seat.

radius instance-attribute

radius: float

width instance-attribute

width: float

offset class-attribute instance-attribute

offset: float = 0.0

length property

length: float

Axial width of the fitted interface.

scaled

scaled(*, radial: float, axial: float) -> AnnularProfile

Return this profile under radial and axial scaling.

BfcCertification

Bases: StrEnum

Back-face-culling certification declared in the header.

CCW class-attribute instance-attribute

CCW = 'ccw'

CW class-attribute instance-attribute

CW = 'cw'

NOCERTIFY class-attribute instance-attribute

NOCERTIFY = 'nocertify'

UNKNOWN class-attribute instance-attribute

UNKNOWN = 'unknown'

BomRow dataclass

One line of a bill of materials.

part instance-attribute

part: str

description instance-attribute

description: str | None

colour_code instance-attribute

colour_code: int | None

colour_name instance-attribute

colour_name: str | None

quantity instance-attribute

quantity: int

to_dict

to_dict() -> dict[str, str | int | None]

Return the row as a plain dict keyed by BOM_FIELDS.

BoundingBox dataclass

An axis-aligned box in LDraw units (LDU).

LDraw's Y axis points down, so min.y is the highest point of the part (typically the stud tops) and max.y the lowest.

min instance-attribute

min: Vector

max instance-attribute

max: Vector

size property

size: Vector

Extent along each axis.

corners

corners() -> tuple[Vector, ...]

Return the eight corner points of the box.

BoundsGap dataclass

Non-negative axis and Euclidean separation between two AABBs.

axes instance-attribute

axes: Vector

distance instance-attribute

distance: float

intersects property

intersects: bool

Return whether the two bounds overlap or touch.

CameraState dataclass

Renderer-neutral LPub3D assembly camera state.

angles class-attribute instance-attribute

angles: tuple[float, float] | None = None

angle_preset class-attribute instance-attribute

angle_preset: str | None = None

position class-attribute instance-attribute

position: tuple[float, float, float] | None = None

target class-attribute instance-attribute

target: tuple[float, float, float] | None = None

up_vector class-attribute instance-attribute

up_vector: tuple[float, float, float] | None = None

distance class-attribute instance-attribute

distance: float | None = None

fov class-attribute instance-attribute

fov: float | None = None

name class-attribute instance-attribute

name: str | None = None

orthographic class-attribute instance-attribute

orthographic: bool | None = None

z_near class-attribute instance-attribute

z_near: float | None = None

z_far class-attribute instance-attribute

z_far: float | None = None

merged

merged(override: CameraState) -> CameraState

Return this state with non-None fields from override applied.

CancellationToken

Thread-safe cancellation token shared by library operations.

cancelled property

cancelled: bool

Whether cancellation has been requested.

cancel

cancel() -> None

Request cancellation; safe to call repeatedly from any thread.

raise_if_cancelled

raise_if_cancelled() -> None

Raise OperationCancelled when cancellation was requested.

CatalogBuildOutcome

Bases: StrEnum

How a catalog preparation obtained its in-memory catalog.

UNAVAILABLE class-attribute instance-attribute

UNAVAILABLE = 'unavailable'

LOADED class-attribute instance-attribute

LOADED = 'loaded'

REBUILT class-attribute instance-attribute

REBUILT = 'rebuilt'

REBUILT_NOT_PERSISTED class-attribute instance-attribute

REBUILT_NOT_PERSISTED = 'rebuilt-not-persisted'

CatalogBuildReport dataclass

Index work and persistence performed by prepare_catalog.

library_root instance-attribute

library_root: Path

index_path instance-attribute

index_path: Path

fingerprint instance-attribute

fingerprint: CatalogFingerprint | None

entry_count instance-attribute

entry_count: int

outcome instance-attribute

outcome: CatalogBuildOutcome

persisted instance-attribute

persisted: bool

CatalogEntry dataclass

Typed catalog entry for one part or primitive.

code instance-attribute

code: str

description instance-attribute

description: str

category instance-attribute

category: PartCategory

part class-attribute instance-attribute

part: Part | None = None

minifig_section class-attribute instance-attribute

minifig_section: MinifigSection | None = None

keywords class-attribute instance-attribute

keywords: tuple[str, ...] = ()

metadata class-attribute instance-attribute

metadata: PartMetadata | None = None

symbol_name property

symbol_name: str

Generated Python symbol name for this entry.

module_path property

module_path: str | None

Generated module path for this entry, if it is importable.

import_statement

import_statement() -> str | None

Generated-library import statement for this entry, if available.

CatalogPreparationResult dataclass

Parts plus before/after state and diagnostics from one preparation.

parts instance-attribute

parts: Parts | None

initial_state instance-attribute

initial_state: LDrawState

final_state instance-attribute

final_state: LDrawState

report instance-attribute

report: CatalogBuildReport

diagnostics class-attribute instance-attribute

diagnostics: tuple[Diagnostic, ...] = ()

complete property

complete: bool

Whether usable parts were produced without an error diagnostic.

CatalogSearchField

Bases: StrEnum

Catalog entry fields considered by PartsCatalog.search.

CODE class-attribute instance-attribute

CODE = 'code'

DESCRIPTION class-attribute instance-attribute

DESCRIPTION = 'description'

CATEGORY class-attribute instance-attribute

CATEGORY = 'category'

KEYWORD class-attribute instance-attribute

KEYWORD = 'keyword'

Colour dataclass

A colour, identified by a code, or by rgb/alpha for direct colours.

rgb is canonicalized on construction to #RRGGBB — a leading #, six uppercase hex digits — whatever form it was given in; malformed values raise ValueError.

code class-attribute instance-attribute

code: int | None = None

name class-attribute instance-attribute

name: str | None = None

rgb class-attribute instance-attribute

rgb: str | None = None

alpha class-attribute instance-attribute

alpha: int | None = None

colour_attributes class-attribute instance-attribute

colour_attributes: list[str] | None = None

is_solid property

is_solid: bool

Whether this colour is plain opaque paint — no alpha, no finish.

Judged from the data on this instance: full alpha (or none given) and no colour attributes (CHROME, GLITTER, LUMINANCE, …). Colours from a parts catalog carry both fields; a bare Colour(code=...) placeholder carries neither and so reads as solid — look the code up in Parts.colours_by_code to judge the real palette entry.

display_label property

display_label: str

Human-readable label for UI lists and inspectors.

swatch_rgb property

swatch_rgb: str | None

RGB hex value suitable for colour swatches, when known.

swatch_alpha property

swatch_alpha: int

Alpha channel suitable for colour swatches.

is_transparent property

is_transparent: bool

Whether this colour has a non-opaque alpha value.

ConnectionContact dataclass

Two placed connection features that are aligned and overlapping.

first_occurrence instance-attribute

first_occurrence: OccurrenceGeometry

second_occurrence instance-attribute

second_occurrence: OccurrenceGeometry

first instance-attribute

first: ConnectionFeature

second instance-attribute

second: ConnectionFeature

residual instance-attribute

residual: ConnectionResidual

status class-attribute instance-attribute

status: ConnectionStatus = ConnectionStatus.CONFIRMED

ConnectionFeature dataclass

One physical connection interface in a part's local coordinates.

The feature frame uses local +Y as its axis. The X and Z axes retain cross-section roll, which is significant for Technic axles and clips.

kind instance-attribute

kind: ConnectionKind

role instance-attribute

role: ConnectionRole

position instance-attribute

position: Vector

frame instance-attribute

frame: Matrix

profile instance-attribute

profile: ConnectionProfile

name class-attribute instance-attribute

name: str = ''

feature_id class-attribute instance-attribute

feature_id: str | None = None

group class-attribute instance-attribute

group: str | None = None

freedoms class-attribute instance-attribute

freedoms: frozenset[ConnectionFreedom] = field(
    default_factory=frozenset
)

source class-attribute instance-attribute

source: ConnectionSource = ConnectionSource.PRIMITIVE

confidence class-attribute instance-attribute

confidence: float = 1.0

owner_code class-attribute instance-attribute

owner_code: str | None = None

compatible_parts class-attribute instance-attribute

compatible_parts: tuple[str, ...] = ()

occupied class-attribute instance-attribute

occupied: bool = False

occupied_by class-attribute instance-attribute

occupied_by: str | None = None

provenance class-attribute instance-attribute

provenance: tuple[str, ...] = ()

metadata_id class-attribute instance-attribute

metadata_id: str | None = None

connection_provenance class-attribute instance-attribute

connection_provenance: ConnectionProvenance | None = None

scale_inheritance class-attribute instance-attribute

scale_inheritance: str = 'yandr'

mirror_inheritance class-attribute instance-attribute

mirror_inheritance: str = 'none'

axis property

axis: Vector

Unit axis, or the zero vector after a degenerate transform.

radial property

radial: Vector

Unit roll reference, or zero after a degenerate transform.

length property

length: float

Axial span represented by the profile.

centered property

centered: bool

Whether the profile spans symmetrically around position.

axial_midpoint property

axial_midpoint: Vector

Center of the feature's axial extent in its coordinate frame.

transformed

transformed(
    *,
    position: Vector,
    matrix: Matrix,
    inherit: bool = True,
) -> ConnectionFeature

Return this feature transformed by an LDraw placement.

ConnectionFreedom

Bases: StrEnum

Motion retained after a connection is made.

ROTATE class-attribute instance-attribute

ROTATE = 'rotate'

SLIDE class-attribute instance-attribute

SLIDE = 'slide'

DISCRETE_ROTATE class-attribute instance-attribute

DISCRETE_ROTATE = 'discrete_rotate'

FREE_ROTATE class-attribute instance-attribute

FREE_ROTATE = 'free_rotate'

ConnectionGraphEdge dataclass

One typed feature contact between two occurrence nodes.

first instance-attribute

first: int

second instance-attribute

second: int

first_feature_id instance-attribute

first_feature_id: str

second_feature_id instance-attribute

second_feature_id: str

status instance-attribute

status: ConnectionStatus

residual instance-attribute

residual: ConnectionResidual

ConnectionGraphs dataclass

Confirmed and optimistic views of one inspection's connectivity.

confirmed instance-attribute

confirmed: ConnectionMultigraph

optimistic instance-attribute

optimistic: ConnectionMultigraph

ConnectionKind

Bases: StrEnum

Physical interface represented by a connection feature.

STUD class-attribute instance-attribute

STUD = 'stud'

STUD_RECEPTACLE class-attribute instance-attribute

STUD_RECEPTACLE = 'stud_receptacle'

BAR class-attribute instance-attribute

BAR = 'bar'

CLIP class-attribute instance-attribute

CLIP = 'clip'

PIN class-attribute instance-attribute

PIN = 'pin'

PIN_HOLE class-attribute instance-attribute

PIN_HOLE = 'pin_hole'

AXLE class-attribute instance-attribute

AXLE = 'axle'

AXLE_HOLE class-attribute instance-attribute

AXLE_HOLE = 'axle_hole'

HINGE class-attribute instance-attribute

HINGE = 'hinge'

RIM_SEAT class-attribute instance-attribute

RIM_SEAT = 'rim_seat'

TYRE_BEAD class-attribute instance-attribute

TYRE_BEAD = 'tyre_bead'

GENERIC class-attribute instance-attribute

GENERIC = 'generic'

ConnectionMetadataCoverage

Bases: StrEnum

Completeness of normalized connection metadata for one part.

COMPLETE class-attribute instance-attribute

COMPLETE = 'complete'

PARTIAL class-attribute instance-attribute

PARTIAL = 'partial'

NONE class-attribute instance-attribute

NONE = 'none'

ConnectionMetadataReport dataclass

Immutable report for all connection metadata applied to one part.

part_code instance-attribute

part_code: str

coverage instance-attribute

coverage: ConnectionMetadataCoverage

features instance-attribute

features: tuple[ConnectionFeature, ...]

source_count instance-attribute

source_count: int

recognized_record_count instance-attribute

recognized_record_count: int

unsupported_record_count instance-attribute

unsupported_record_count: int

invalid_record_count instance-attribute

invalid_record_count: int

diagnostics instance-attribute

diagnostics: tuple[Diagnostic, ...]

ConnectionMultigraph dataclass

Immutable occurrence multigraph retaining parallel feature edges.

nodes instance-attribute

nodes: tuple[int, ...]

edges instance-attribute

edges: tuple[ConnectionGraphEdge, ...]

ConnectionProvenance dataclass

Structured origin of a normalized connection feature.

source instance-attribute

source: ConnectionSource

path class-attribute instance-attribute

path: Path | None = None

archive_member class-attribute instance-attribute

archive_member: str | None = None

line_number class-attribute instance-attribute

line_number: int | None = None

command class-attribute instance-attribute

command: str | None = None

include_chain class-attribute instance-attribute

include_chain: tuple[str, ...] = ()

ConnectionResidual dataclass

Geometric residuals between two compatible features.

distance instance-attribute

distance: float

axial_gap instance-attribute

axial_gap: float

alignment instance-attribute

alignment: float

roll_alignment class-attribute instance-attribute

roll_alignment: float = 1.0

entry_face_gap class-attribute instance-attribute

entry_face_gap: float | None = None

penetration class-attribute instance-attribute

penetration: float | None = None

ConnectionRole

Bases: StrEnum

Mating role of a feature.

MALE class-attribute instance-attribute

MALE = 'male'

FEMALE class-attribute instance-attribute

FEMALE = 'female'

NEUTRAL class-attribute instance-attribute

NEUTRAL = 'neutral'

ConnectionSource

Bases: StrEnum

Evidence from which a connection feature was derived.

HEURISTIC class-attribute instance-attribute

HEURISTIC = 'heuristic'

PRIMITIVE class-attribute instance-attribute

PRIMITIVE = 'primitive'

SHORTCUT class-attribute instance-attribute

SHORTCUT = 'shortcut'

LDCAD_INLINE class-attribute instance-attribute

LDCAD_INLINE = 'ldcad_inline'

LDCAD_SHADOW class-attribute instance-attribute

LDCAD_SHADOW = 'ldcad_shadow'

STUDIO class-attribute instance-attribute

STUDIO = 'studio'

OVERRIDE class-attribute instance-attribute

OVERRIDE = 'override'

ConnectionStatus

Bases: StrEnum

Confidence tier assigned to a placed feature contact.

CONFIRMED class-attribute instance-attribute

CONFIRMED = 'confirmed'

POTENTIAL class-attribute instance-attribute

POTENTIAL = 'potential'

CylindricalCaps

Bases: StrEnum

Blocked ends of an LDCad cylindrical connection profile.

NONE class-attribute instance-attribute

NONE = 'none'

ONE class-attribute instance-attribute

ONE = 'one'

TWO class-attribute instance-attribute

TWO = 'two'

A class-attribute instance-attribute

A = 'a'

B class-attribute instance-attribute

B = 'b'

CylindricalProfile dataclass

Axial profile composed of round, axle, or square sections.

sections instance-attribute

sections: tuple[CylindricalSection, ...]

centered class-attribute instance-attribute

centered: bool = True

friction class-attribute instance-attribute

friction: bool = False

caps class-attribute instance-attribute

caps: CylindricalCaps = CylindricalCaps.NONE

length property

length: float

Total length along the feature axis.

primary_shape property

primary_shape: SectionShape

Most constraining cross-section in the profile.

mating_radius property

mating_radius: float

Smallest rigid radius, used for broad compatibility checks.

scaled

scaled(
    *, radial: float, axial: float
) -> CylindricalProfile

Return this profile under radial and axial scaling.

CylindricalSection dataclass

One axial section of a pin, hole, axle, bar, or clip profile.

shape instance-attribute

shape: SectionShape

radius instance-attribute

radius: float

length instance-attribute

length: float

flexible class-attribute instance-attribute

flexible: bool = False

scaled

scaled(
    *, radial: float, axial: float
) -> CylindricalSection

Return this section under radial and axial scaling.

Diagnostic dataclass

One structured problem, warning, or recovery made by an operation.

line_number remains the first field so the historical ValidationIssue(line_number, message, severity) constructor stays source compatible. New callers should prefer keyword arguments.

Warning: equality and hashing deliberately compare only line_number, message, and severity (historical ValidationIssue behavior), so set/dict deduplication collapses diagnostics that differ only by code, path, or section. To deduplicate diagnostics across files, key on a tuple such as (diagnostic.path, diagnostic.code, diagnostic.line_number, diagnostic.message) instead.

line_number class-attribute instance-attribute

line_number: int | None = None

message class-attribute instance-attribute

message: str = ''

severity class-attribute instance-attribute

severity: Severity = Severity.ERROR

code class-attribute instance-attribute

code: DiagnosticCode | str = field(
    default=DiagnosticCode.GENERIC, compare=False
)

path class-attribute instance-attribute

path: Path | None = field(default=None, compare=False)

section class-attribute instance-attribute

section: str | None = field(default=None, compare=False)

offending_value class-attribute instance-attribute

offending_value: object | None = field(
    default=None, compare=False
)

suggestions class-attribute instance-attribute

suggestions: tuple[str, ...] = field(
    default=(), compare=False
)

cause class-attribute instance-attribute

cause: BaseException | None = field(
    default=None, compare=False, repr=False
)

to_dict

to_dict() -> dict[str, Any]

Return a JSON-ready representation, including safe cause details.

offending_value passes JSON-native scalars through unchanged; any other value (bytes, matrices, exceptions, ...) is coerced with repr() so the result always survives json.dumps.

DiagnosticCode

Bases: StrEnum

Stable codes emitted by PyLDraw report-oriented operations.

GENERIC class-attribute instance-attribute

GENERIC = 'generic'

CATALOG_LIBRARY_MISSING class-attribute instance-attribute

CATALOG_LIBRARY_MISSING = 'catalog.library_missing'

CATALOG_INDEX_MISSING class-attribute instance-attribute

CATALOG_INDEX_MISSING = 'catalog.index_missing'

CATALOG_INDEX_STALE class-attribute instance-attribute

CATALOG_INDEX_STALE = 'catalog.index_stale'

CATALOG_INDEX_UNREADABLE class-attribute instance-attribute

CATALOG_INDEX_UNREADABLE = 'catalog.index_unreadable'

CATALOG_PERSIST_FAILED class-attribute instance-attribute

CATALOG_PERSIST_FAILED = 'catalog.persist_failed'

GENERATION_FAILED class-attribute instance-attribute

GENERATION_FAILED = 'generation.failed'

IO_READ_FAILED class-attribute instance-attribute

IO_READ_FAILED = 'io.read_failed'

IO_DECODE_FAILED class-attribute instance-attribute

IO_DECODE_FAILED = 'io.decode_failed'

PARSE_INVALID_LINE class-attribute instance-attribute

PARSE_INVALID_LINE = 'parse.invalid_line'

PARSE_INVALID_NUMERIC class-attribute instance-attribute

PARSE_INVALID_NUMERIC = 'parse.invalid_numeric'

PARSE_INVALID_COLOUR class-attribute instance-attribute

PARSE_INVALID_COLOUR = 'parse.invalid_colour'

MPD_MISPLACED_NOFILE class-attribute instance-attribute

MPD_MISPLACED_NOFILE = 'mpd.misplaced_nofile'

MPD_CONTENT_AFTER_NOFILE class-attribute instance-attribute

MPD_CONTENT_AFTER_NOFILE = 'mpd.content_after_nofile'

MPD_DUPLICATE_SECTION class-attribute instance-attribute

MPD_DUPLICATE_SECTION = 'mpd.duplicate_section'

MPD_UNRESOLVED_SUBMODEL class-attribute instance-attribute

MPD_UNRESOLVED_SUBMODEL = 'mpd.unresolved_submodel'

MPD_CYCLE class-attribute instance-attribute

MPD_CYCLE = 'mpd.cycle'

MODEL_UNKNOWN_PART class-attribute instance-attribute

MODEL_UNKNOWN_PART = 'model.unknown_part'

MODEL_UNKNOWN_COLOUR class-attribute instance-attribute

MODEL_UNKNOWN_COLOUR = 'model.unknown_colour'

MODEL_LEGACY_COLOUR class-attribute instance-attribute

MODEL_LEGACY_COLOUR = 'model.legacy_colour'

MODEL_SINGULAR_MATRIX class-attribute instance-attribute

MODEL_SINGULAR_MATRIX = 'model.singular_matrix'

MODEL_NON_ORTHONORMAL_MATRIX class-attribute instance-attribute

MODEL_NON_ORTHONORMAL_MATRIX = (
    "model.non_orthonormal_matrix"
)

MODEL_UNKNOWN_META class-attribute instance-attribute

MODEL_UNKNOWN_META = 'model.unknown_meta'

PART_NOT_FOUND class-attribute instance-attribute

PART_NOT_FOUND = 'part.not_found'

PART_HEADER_INVALID class-attribute instance-attribute

PART_HEADER_INVALID = 'part.header_invalid'

PART_REFERENCE_UNRESOLVED class-attribute instance-attribute

PART_REFERENCE_UNRESOLVED = 'part.reference_unresolved'

PART_REFERENCE_CYCLE class-attribute instance-attribute

PART_REFERENCE_CYCLE = 'part.reference_cycle'

GEOMETRY_INCOMPLETE class-attribute instance-attribute

GEOMETRY_INCOMPLETE = 'geometry.incomplete'

CONNECTION_UNSUPPORTED_RECORD class-attribute instance-attribute

CONNECTION_UNSUPPORTED_RECORD = (
    "connection.unsupported_record"
)

CONNECTION_UNSUPPORTED_OPTION class-attribute instance-attribute

CONNECTION_UNSUPPORTED_OPTION = (
    "connection.unsupported_option"
)

CONNECTION_INVALID_OPTION_VALUE class-attribute instance-attribute

CONNECTION_INVALID_OPTION_VALUE = (
    "connection.invalid_option_value"
)

CONNECTION_METADATA_INVALID class-attribute instance-attribute

CONNECTION_METADATA_INVALID = (
    "connection.invalid_option_value"
)

CONNECTION_MISSING_REQUIRED_OPTION class-attribute instance-attribute

CONNECTION_MISSING_REQUIRED_OPTION = (
    "connection.missing_required_option"
)

CONNECTION_INCLUDE_NOT_FOUND class-attribute instance-attribute

CONNECTION_INCLUDE_NOT_FOUND = (
    "connection.include_not_found"
)

CONNECTION_INCLUDE_CYCLE class-attribute instance-attribute

CONNECTION_INCLUDE_CYCLE = 'connection.include_cycle'

CONNECTION_FEATURE_CONFLICT class-attribute instance-attribute

CONNECTION_FEATURE_CONFLICT = 'connection.feature_conflict'

CONNECTION_INVALID_TRANSFORM class-attribute instance-attribute

CONNECTION_INVALID_TRANSFORM = (
    "connection.invalid_transform"
)

CONNECTION_INVALID_GRID class-attribute instance-attribute

CONNECTION_INVALID_GRID = 'connection.invalid_grid'

DISCOVERY_INVALID_LIBRARY class-attribute instance-attribute

DISCOVERY_INVALID_LIBRARY = 'discovery.invalid_library'

DOWNLOAD_PLAN_FAILED class-attribute instance-attribute

DOWNLOAD_PLAN_FAILED = 'download.plan_failed'

DOWNLOAD_INTEGRITY_FAILED class-attribute instance-attribute

DOWNLOAD_INTEGRITY_FAILED = 'download.integrity_failed'

RENDER_UNAVAILABLE class-attribute instance-attribute

RENDER_UNAVAILABLE = 'render.unavailable'

RENDER_FAILED class-attribute instance-attribute

RENDER_FAILED = 'render.failed'

DownloadPlan dataclass

Network and local-cache facts for a prospective library download.

version instance-attribute

version: str

release instance-attribute

release: str | None

url instance-attribute

url: str

archive_path instance-attribute

archive_path: Path

destination instance-attribute

destination: Path

download_size instance-attribute

download_size: int | None

cached_bytes instance-attribute

cached_bytes: int

resumable instance-attribute

resumable: bool

cached_archive_valid instance-attribute

cached_archive_valid: bool | None

diagnostics class-attribute instance-attribute

diagnostics: tuple[Diagnostic, ...] = ()

remaining_bytes property

remaining_bytes: int | None

Return the expected remaining transfer size when known.

FingerProfile dataclass

Interlocking hinge fingers arranged along the hinge axis.

sequence instance-attribute

sequence: tuple[float, ...]

radius instance-attribute

radius: float

first_role class-attribute instance-attribute

first_role: ConnectionRole = ConnectionRole.MALE

detents class-attribute instance-attribute

detents: tuple[float, ...] = ()

centered class-attribute instance-attribute

centered: bool = True

length property

length: float

Total finger span along the hinge axis.

scaled

scaled(*, radial: float, axial: float) -> FingerProfile

Return this profile under radial and axial scaling.

GenericBounds dataclass

One validated LDCad generic bounding shape.

kind instance-attribute

kind: GenericBoundsKind

dimensions class-attribute instance-attribute

dimensions: tuple[float, ...] = ()

scaled

scaled(*, radial: float, axial: float) -> GenericBounds

Return the bounds under radial and axial scaling.

GenericBoundsKind

Bases: StrEnum

Bounding shape used to rank and validate a generic interface.

POINT class-attribute instance-attribute

POINT = 'point'

BOX class-attribute instance-attribute

BOX = 'box'

CYLINDER class-attribute instance-attribute

CYLINDER = 'cylinder'

SPHERE class-attribute instance-attribute

SPHERE = 'sphere'

GenericMatch

Bases: StrEnum

LDCad matching rule for generic interfaces.

SHAPE class-attribute instance-attribute

SHAPE = 'shape'

SIZE class-attribute instance-attribute

SIZE = 'size'

GROUP class-attribute instance-attribute

GROUP = 'group'

GenericPlacement

Bases: StrEnum

Orientation behavior retained by a generic interface.

ALIGNED class-attribute instance-attribute

ALIGNED = 'aligned'

FREE class-attribute instance-attribute

FREE = 'free'

GenericProfile dataclass

Named interface for shapes which need curated compatibility.

name instance-attribute

name: str

length class-attribute instance-attribute

length: float = 0.0

bounds class-attribute instance-attribute

bounds: GenericBounds | None = None

match class-attribute instance-attribute

match: GenericMatch = GenericMatch.SHAPE

placement class-attribute instance-attribute

placement: GenericPlacement = GenericPlacement.ALIGNED

scaled

scaled(*, radial: float, axial: float) -> GenericProfile

Return this profile under axial scaling.

Group dataclass

A group of pieces.

position class-attribute instance-attribute

position: Vector = field(
    default_factory=lambda: Vector(0, 0, 0)
)

matrix class-attribute instance-attribute

matrix: Matrix = field(default_factory=Identity)

pieces class-attribute instance-attribute

pieces: list[Piece] = field(default_factory=list)

to_ldraw

to_ldraw() -> str

Serialize all pieces in this group to LDraw lines.

add_piece

add_piece(piece: Piece) -> None

Add a piece to the group.

remove_piece

remove_piece(piece: Piece) -> None

Remove a piece from the group.

copy

copy() -> Self

Return an independent copy of this group with copies of its pieces.

Identity

Identity() -> Matrix

Return a transformation matrix representing Identity.

InstructionBuilder

Write balanced instruction directives into a Model.

model instance-attribute

model = model

step

step() -> None

Append a plain LDraw step boundary.

rotation_step

rotation_step(
    x: float,
    y: float,
    z: float,
    *,
    mode: RotationMode = RotationMode.RELATIVE,
) -> None

Append a rotation-step boundary.

end_rotation

end_rotation() -> None

Restore the default instruction view.

note

note(text: str) -> None

Append a renderer-neutral textual note.

arrow

arrow(
    start: Vector, end: Vector, *, label: str | None = None
) -> None

Append a section-local 3D arrow annotation.

highlight

highlight(piece: Piece) -> None

Highlight an existing placement using proximity-safe metadata.

page_break

page_break(
    *, offset: tuple[float, float] | None = None
) -> None

Append an LPub3D page break.

suppress_step

suppress_step() -> None

Mark the current step as suppressed in LPub3D.

set_camera

set_camera(
    camera: CameraState,
    *,
    scope: InstructionScope = InstructionScope.LOCAL,
    context: CameraContext = CameraContext.ASSEMBLY,
) -> None

Append canonical LPub3D camera directives for non-None fields.

callout

callout(
    *, mode: CalloutMode = CalloutMode.ASSEMBLED
) -> Iterator[None]

Write a balanced LPub3D callout range.

multi_step

multi_step() -> Iterator[None]

Write a balanced LPub3D multi-step range.

ignore

ignore(target: InventoryTarget) -> Iterator[None]

Write a balanced LPub3D inventory-ignore range.

InstructionDocument dataclass

A sectioned semantic view of an LDraw model's instructions.

root instance-attribute

root: InstructionSection

sections instance-attribute

sections: tuple[InstructionSection, ...]

orphan_sections instance-attribute

orphan_sections: tuple[InstructionSection, ...]

model class-attribute instance-attribute

model: Model = field(repr=False, compare=False)

parts class-attribute instance-attribute

parts: Parts | None = field(
    default=None, repr=False, compare=False
)

from_model classmethod

from_model(
    model: Model, *, parts: Parts | None = None
) -> InstructionDocument

Build a semantic instruction document from model.

section

section(name: str) -> InstructionSection

Return a reachable section by case-insensitive reference name.

InstructionIssue dataclass

A structural or semantic instruction problem.

section instance-attribute

section: str

line_number instance-attribute

line_number: int | None

code instance-attribute

code: str

message instance-attribute

message: str

severity class-attribute instance-attribute

severity: Severity = Severity.ERROR

InstructionSection dataclass

The independent instruction sequence for one model section.

name instance-attribute

name: str

is_root instance-attribute

is_root: bool

reachable instance-attribute

reachable: bool

references instance-attribute

references: tuple[str, ...]

steps instance-attribute

steps: tuple[InstructionStep, ...]

model class-attribute instance-attribute

model: Model = field(repr=False, compare=False)

InstructionStep dataclass

One section-local building step and its effective instruction state.

number instance-attribute

number: int

section_name instance-attribute

section_name: str

objects instance-attribute

objects: tuple[ParsedObject, ...]

added_pieces instance-attribute

added_pieces: tuple[Piece, ...]

directives instance-attribute

directives: tuple[InstructionDirective, ...]

rotation instance-attribute

rotation: RotationStep | None

camera instance-attribute

camera: CameraState

callouts instance-attribute

callouts: tuple[InstructionCallout, ...]

multi_step_group instance-attribute

multi_step_group: int | None

page_break_before instance-attribute

page_break_before: bool

suppressed instance-attribute

suppressed: bool

source_start_line instance-attribute

source_start_line: int | None

source_end_line instance-attribute

source_end_line: int | None

cumulative_pieces property

cumulative_pieces: tuple[Piece, ...]

Direct placements accumulated in this section through this step.

cumulative_objects property

cumulative_objects: tuple[ParsedObject, ...]

Parsed objects accumulated in this section through this step.

source_line_for

source_line_for(obj: ParsedObject) -> int | None

Return the source line for one object in this step's section.

added_occurrences

added_occurrences(
    *, expand_submodels: bool = True
) -> tuple[ModelOccurrence, ...]

Return leaf occurrences added in this step.

cumulative_occurrences

cumulative_occurrences(
    *, expand_submodels: bool = True
) -> tuple[ModelOccurrence, ...]

Return leaf occurrences accumulated through this step.

added_bill_of_materials

added_bill_of_materials(
    *,
    parts: Parts | None = None,
    expand_submodels: bool = True,
    respect_lpub: bool = True,
) -> list[BomRow]

Return the parts tray for placements added in this step.

cumulative_bill_of_materials

cumulative_bill_of_materials(
    *,
    parts: Parts | None = None,
    expand_submodels: bool = True,
    respect_lpub: bool = True,
) -> list[BomRow]

Return the accumulated BOM through this step.

LDCadShadowLibrary

Read unpacked, ZIP, or CSL LDCad shadow metadata.

source instance-attribute

source = Path(source).expanduser()

connections_for

connections_for(
    code: str,
    *,
    siblings: tuple[LDCadShadowLibrary, ...] = (),
) -> ShadowConnectionResult

Return resolved shadow features for a part or primitive code.

siblings is the full ordered registry of shadow libraries used to resolve SNAP_INCL references across the merged shadow namespace.

LDrawCapability

Bases: StrEnum

Configured data capabilities a caller may require.

CATALOG class-attribute instance-attribute

CATALOG = 'catalog'

GENERATED_MODULES class-attribute instance-attribute

GENERATED_MODULES = 'generated-modules'

LDrawPaths dataclass

Resolved filesystem paths for one pyldraw configuration.

library_path instance-attribute

library_path: Path

ldraw_path instance-attribute

ldraw_path: Path

parts_lst instance-attribute

parts_lst: Path

generated_path instance-attribute

generated_path: Path

generated_library instance-attribute

generated_library: Path

generation_hash instance-attribute

generation_hash: Path

catalog_db instance-attribute

catalog_db: Path

from_config classmethod

from_config(config: Config) -> Self

Resolve paths from config.

LDrawSession

Manage one configured LDraw catalog and generated library.

config instance-attribute

config: Config = (
    config if config is not None else Config.load()
)

paths property

paths: LDrawPaths

Resolved paths for this session.

state

state(
    *,
    capabilities: Iterable[LDrawCapability] | None = None,
    fingerprint: CatalogFingerprint | None = None,
) -> LDrawState

Classify only the configured capabilities requested by the caller.

capabilities=None (the default) means every capability; an empty iterable raises ValueError, matching prepare_catalog.

load

load() -> Parts

Load parts, building and persisting the catalog index when needed.

prepare_catalog

prepare_catalog(
    *,
    capabilities: Iterable[LDrawCapability] = (
        LDrawCapability.CATALOG,
    ),
    connection_shadows: Iterable[str | Path] = (),
    studio_metadata: Iterable[str | Path] = (),
    force: bool = False,
    on_progress: ProgressCallback | None = None,
    cancellation: CancellationToken | None = None,
    fingerprint: CatalogFingerprint | None = None,
) -> CatalogPreparationResult

Load or rebuild requested data using one filesystem fingerprint.

fingerprint lets a caller reuse an already-computed snapshot to avoid a second parts-tree walk; the caller is then responsible for its freshness — a stale value persists the index under stale keys.

rebuild_index

rebuild_index(
    *,
    force: bool = True,
    on_progress: ProgressCallback | None = None,
    cancellation: CancellationToken | None = None,
    fingerprint: CatalogFingerprint | None = None,
) -> Parts

Rebuild the persistent catalog index and return the loaded parts.

fingerprint lets a caller reuse an already-computed snapshot; the caller is then responsible for its freshness — the rebuilt index is persisted under exactly the keys it carries, so a stale value poisons the index until the next filesystem change.

open_model

open_model(path: Path | str) -> Model

Read a .ldr or .mpd model file.

load_model

load_model(
    path: Path | str,
    parts: Parts | None = None,
    *,
    tolerant: bool = True,
) -> ModelLoadResult

Read and validate a model into a structured load result.

LDrawState dataclass

Freshness state for a configured LDraw library and generated data.

paths instance-attribute

paths: LDrawPaths

reasons instance-attribute

reasons: tuple[LDrawStateReason, ...]

capabilities class-attribute instance-attribute

capabilities: frozenset[LDrawCapability] = frozenset(
    {
        LDrawCapability.CATALOG,
        LDrawCapability.GENERATED_MODULES,
    }
)

ready property

ready: bool

Whether every capability this state was scoped to is fresh.

Only the capabilities in :attr:capabilities were classified; unrequested capabilities may still be missing or stale.

library_available property

library_available: bool

Whether parts.lst exists and catalog loading can start.

needs_index_rebuild property

needs_index_rebuild: bool

Whether loading will need the slow catalog categorization pass.

needs_generation property

needs_generation: bool

Whether ldraw.library should be generated or refreshed.

LDrawStateReason

Bases: StrEnum

Reasons the configured LDraw data is not fully ready.

LIBRARY_MISSING class-attribute instance-attribute

LIBRARY_MISSING = 'library-missing'

INDEX_MISSING class-attribute instance-attribute

INDEX_MISSING = 'index-missing'

INDEX_STALE class-attribute instance-attribute

INDEX_STALE = 'index-stale'

INDEX_UNREADABLE class-attribute instance-attribute

INDEX_UNREADABLE = 'index-unreadable'

GENERATED_LIBRARY_MISSING class-attribute instance-attribute

GENERATED_LIBRARY_MISSING = 'generated-library-missing'

GENERATED_LIBRARY_STALE class-attribute instance-attribute

GENERATED_LIBRARY_STALE = 'generated-library-stale'

GENERATED_LIBRARY_UNREADABLE class-attribute instance-attribute

GENERATED_LIBRARY_UNREADABLE = (
    "generated-library-unreadable"
)

LibraryComponent dataclass

Presence and basic readability of one expected library component.

name instance-attribute

name: str

path instance-attribute

path: Path

present instance-attribute

present: bool

valid instance-attribute

valid: bool

detail class-attribute instance-attribute

detail: str | None = None

LibraryInspection dataclass

Non-mutating inspection of a possible LDraw installation.

path instance-attribute

path: Path

ldraw_path instance-attribute

ldraw_path: Path

release instance-attribute

release: str | None

components instance-attribute

components: tuple[LibraryComponent, ...]

diagnostics class-attribute instance-attribute

diagnostics: tuple[Diagnostic, ...] = ()

valid property

valid: bool

Return whether every required component is present and usable.

missing_components property

missing_components: tuple[str, ...]

Return names of components that were not found.

corrupt_components property

corrupt_components: tuple[str, ...]

Return names of present components that failed validation.

LibraryOrigin

Bases: StrEnum

Whether a header declares official or unofficial library origin.

OFFICIAL class-attribute instance-attribute

OFFICIAL = 'official'

UNOFFICIAL class-attribute instance-attribute

UNOFFICIAL = 'unofficial'

UNKNOWN class-attribute instance-attribute

UNKNOWN = 'unknown'

Matrix dataclass

A 3x3 transformation matrix.

rows property writable

rows: MatrixRows

Return matrix rows as plain Python lists.

copy

copy() -> Self

Make a copy of this matrix.

rotate

rotate(
    angle: Number,
    axis: type[Axis],
    units: type[AngleUnits] = Degrees,
) -> Matrix

Rotate the matrix by an angle around an axis.

scale

scale(sx: Number, sy: Number, sz: Number) -> Matrix

Scale the matrix on each axis, applied in the local frame like rotate.

transpose

transpose() -> Matrix

Return the transposed matrix.

inverse

inverse() -> Matrix

Return the inverse transform, raising for a singular matrix.

det

det() -> float

Return the determinant of the matrix.

is_singular

is_singular(*, tolerance: float = 1e-06) -> bool

Return whether the matrix flattens geometry (determinant near zero).

is_orthonormal

is_orthonormal(*, tolerance: float = 1e-06) -> bool

Return whether the matrix is a pure rotation or reflection.

flatten

flatten() -> tuple[float, ...]

Flatten the matrix in row-major order.

fix_diagonal

fix_diagonal() -> bool

POV-Ray does not like matrices with zero diagonal elements.

MinifigSection

Bases: StrEnum

Known minifigure catalog sections.

HATS class-attribute instance-attribute

HATS = 'hats'

HEADS class-attribute instance-attribute

HEADS = 'heads'

TORSOS class-attribute instance-attribute

TORSOS = 'torsos'

HIPS class-attribute instance-attribute

HIPS = 'hips'

LEGS class-attribute instance-attribute

LEGS = 'legs'

ARMS class-attribute instance-attribute

ARMS = 'arms'

HANDS class-attribute instance-attribute

HANDS = 'hands'

ACCESSORIES class-attribute instance-attribute

ACCESSORIES = 'accessories'

marker property

marker: str

Return the description marker used to infer this section.

Model dataclass

A whole LDraw model, optionally with MPD submodels.

Models compare and hash by identity: their objects contain identity-compared pieces, so field-wise equality would be meaningless. Compare model content with m1.to_ldraw() == m2.to_ldraw().

name class-attribute instance-attribute

name: str = ''

objects class-attribute instance-attribute

objects: list[ParsedObject] = field(default_factory=list)

submodels class-attribute instance-attribute

submodels: dict[str, Model] = field(default_factory=dict)

description property

description: str | None

The description from the first line, when it is an unmanaged comment.

header_name property

header_name: str | None

The 0 Name: header value.

author property

author: str | None

The 0 Author: header value.

ldraw_org property

ldraw_org: str | None

The 0 !LDRAW_ORG header value.

license property

license: str | None

The 0 !LICENSE header value.

bfc property

bfc: str | None

The 0 BFC header value.

pieces property

pieces: list[Piece]

The type-1 subfile references in this model.

steps property

steps: list[list[Piece]]

Pieces grouped by 0 STEP markers.

Pieces after the last marker form a final step, so a model without any 0 STEP lines is a single step. A trailing marker does not produce an empty step. Submodel references are not expanded.

submodel_for

submodel_for(piece: Piece) -> Model | None

Resolve a piece's subfile reference to a submodel, if any.

source_line_for

source_line_for(obj: ParsedObject) -> int | None

Return the parsed source line for this exact object.

add

add(*objects: ParsedObject) -> None

Append parsed objects (pieces, comments, geometry) to the model.

add_group

add_group(group: Group) -> None

Append a group's pieces; group transforms apply at serialization.

from_pieces classmethod

from_pieces(
    pieces: Iterable[Piece],
    *,
    name: str = "",
    description: str | None = None,
    author: str | None = None,
) -> Self

Build a model from pieces, optionally with header comments.

set_header

set_header(
    *,
    description: str | None = None,
    name: str | None = None,
    author: str | None = None,
    ldraw_org: str | None = None,
    license: str | None = None,
) -> None

Set or replace standard header lines at the top of the model.

ldraw_org and license write the 0 !LDRAW_ORG and 0 !LICENSE meta commands, placed after any Name:/Author: comments in canonical header order.

add_submodel

add_submodel(
    submodel: Model,
    *,
    colour: Colour | int = MAIN_COLOUR_CODE,
    position: Vector | None = None,
    matrix: Matrix | None = None,
) -> Piece

Register a submodel and append a type-1 piece referencing it.

The submodel's own nested submodels are hoisted into this model's flat mapping, since serialization only walks one level. The same submodel object may be added repeatedly; each call appends another placement piece. A different model under an already-registered name still raises DuplicateSubmodelError.

submodel_view

submodel_view(name: str) -> Model

Return a submodel that resolves references against this root.

Models taken straight from Model.submodels have an empty submodel table, so iterating them treats references to sibling submodels as leaf pieces. The returned model shares this root's submodel table instead, making iter_pieces, bill_of_materials, and find_pieces(recursive=True) expand nested references correctly. It is a live view — its objects and submodel table are shared with this model, not copied.

Raises UnknownSubmodelError for a name that is neither this model's nor one of its submodels'.

add_step

add_step() -> None

Append a 0 STEP marker ending the current building step.

add_rotation_step

add_rotation_step(
    x: float,
    y: float,
    z: float,
    *,
    mode: RotationMode | str = "REL",
) -> None

Append a canonical MLCad ROTSTEP instruction boundary.

end_rotation_steps

end_rotation_steps() -> None

Append 0 ROTSTEP END and restore the default instruction view.

instruction_document

instruction_document(
    *, parts: Parts | None = None
) -> InstructionDocument

Interpret this model and its reachable submodels as instructions.

iter_instruction_steps

iter_instruction_steps() -> Iterator[InstructionStep]

Yield this model section's semantic instruction steps.

This convenience method constructs the complete instruction document, including reachable and orphan sections. Callers that need to inspect steps repeatedly should build :meth:instruction_document once and reuse its root.steps tuple.

iter_pieces

iter_pieces() -> Iterator[Piece]

Recursively yield leaf pieces, expanding submodel references.

References are resolved against this model's submodel table. A model taken straight from Model.submodels has an empty table, so references to sibling submodels are silently yielded as if they were leaf pieces — inspect a submodel through root.submodel_view(name) instead.

iter_occurrences

iter_occurrences(
    *,
    expand_submodels: bool = True,
    include_steps: bool = True,
) -> Iterator[ModelOccurrence]

Yield placed part occurrences with transform and source context.

bill_of_materials

bill_of_materials(
    *, parts: Parts | None = None
) -> list[BomRow]

Count leaf pieces by part and colour, expanding submodel references.

Colour 16 (the main colour) inside a submodel is resolved to the colour the submodel was placed with. As with iter_pieces, submodel references only resolve against this model's own submodel table; to count a single submodel of a larger model, call this on root.submodel_view(name). Cyclic submodel references (possible in tolerantly-loaded models) are skipped instead of raising.

find_pieces

find_pieces(
    *,
    part: str | None = None,
    colour: Colour | int | None = None,
    recursive: bool = False,
) -> list[Piece]

Return pieces matching the given part code and/or colour.

Part codes are compared case-insensitively.

to_ldraw

to_ldraw() -> str

Serialize the model (and any submodels) to LDraw text.

save

save(path: Path | str) -> None

Write the model to a file, with a trailing newline.

ModelAnalysis dataclass

Occurrences, statistics, BOM, steps, and diagnostics for one model.

occurrences instance-attribute

occurrences: tuple[ModelOccurrence, ...]

summary instance-attribute

summary: ModelSummary

bom instance-attribute

bom: tuple[BomRow, ...]

instruction_steps instance-attribute

instruction_steps: tuple[InstructionStep, ...]

diagnostics instance-attribute

diagnostics: tuple[Diagnostic, ...]

inspection class-attribute instance-attribute

inspection: ModelInspection | None = None

ModelInspection dataclass

Exact bounds, resolved occurrences, failures, and source attribution.

bounds instance-attribute

bounds: BoundingBox | None

occurrences instance-attribute

occurrences: tuple[OccurrenceGeometry, ...]

skipped_geometry instance-attribute

skipped_geometry: tuple[SkippedOccurrenceGeometry, ...]

diagnostics instance-attribute

diagnostics: tuple[Diagnostic, ...]

occurrence_count instance-attribute

occurrence_count: int

complete property

complete: bool

Whether every occurrence and nested part reference resolved.

stud_contacts

stud_contacts(
    *, tolerance: float = 0.1, probe_distance: float = 0.1
) -> tuple[StudContact, ...]

Return strict stud matches as the historical stud-contact view.

connection_contacts

connection_contacts(
    *,
    tolerance: float = 0.25,
    angular_tolerance: float = 2.0,
) -> tuple[ConnectionContact, ...]

Return compatible connection features already mated in the model.

connection_graphs

connection_graphs(
    *,
    tolerance: float = 0.25,
    angular_tolerance: float = 2.0,
) -> ConnectionGraphs

Return confirmed and heuristic-inclusive occurrence multigraphs.

snap_candidates

snap_candidates(
    moving: OccurrenceGeometry | int,
    *,
    fixed: OccurrenceGeometry | int | None = None,
    limit: int | None = None,
) -> tuple[SnapCandidate, ...]

Return ranked placements for mating a moving occurrence's features.

moving and fixed accept either an occurrence geometry or its stable inspection index. When fixed is omitted, every other occurrence is considered.

contact_gaps

contact_gaps(
    *, minimum_gap: float = 5.0, chronological: bool = False
) -> tuple[OccurrenceContact, ...]

Return occurrences farther than minimum_gap from every peer.

ModelLoadResult dataclass

Model, diagnostics, and source completeness from one read/parse pass.

model instance-attribute

model: Model | None

diagnostics instance-attribute

diagnostics: tuple[Diagnostic, ...]

complete instance-attribute

complete: bool

valid property

valid: bool

Whether the load emitted no error diagnostics.

analyze

analyze(parts: Parts | None = None) -> ModelAnalysis | None

Analyze the loaded model without discarding its diagnostics.

ModelOccurrence dataclass

One placed leaf part occurrence in a model.

Occurrences are traversal events: two placements of the same submodel produce distinct occurrences, so they compare and hash by identity.

step is the effective (inherited) step: pieces inside a submodel report the step their outermost placement belongs to. This differs from path[-1].step, which is the placement's local step within its own section (OccurrencePathItem.local_step); source_step carries the same local semantics.

piece instance-attribute

piece: Piece

part_code instance-attribute

part_code: str

reference instance-attribute

reference: str

colour instance-attribute

colour: Colour

position instance-attribute

position: Vector

matrix instance-attribute

matrix: Matrix

source_model instance-attribute

source_model: Model

source_line instance-attribute

source_line: int | None

step instance-attribute

step: int | None

source_step instance-attribute

source_step: int | None

path class-attribute instance-attribute

path: tuple[OccurrencePathItem, ...] = ()

ModelSummary dataclass

Reusable summary of a model's placed parts and geometry extents.

bounds instance-attribute

bounds: BoundingBox | None

origin_bounds instance-attribute

origin_bounds: BoundingBox | None

part_counts instance-attribute

part_counts: dict[str, int]

colour_usage instance-attribute

colour_usage: dict[int | str | None, int]

skipped_geometry instance-attribute

skipped_geometry: tuple[SkippedGeometry, ...]

occurrence_count instance-attribute

occurrence_count: int

size_ldu property

size_ldu: Vector | None

Overall model size in LDraw units.

size_mm property

size_mm: Vector | None

Overall model size in millimetres.

from_model classmethod

from_model(
    model: Model, parts: Parts | None
) -> ModelSummary

Build a summary for model using geometry from parts.

Cyclic submodel references (possible in tolerantly-loaded models) are skipped rather than raising.

from_inspection classmethod

from_inspection(
    inspection: ModelInspection,
) -> ModelSummary

Build a summary reusing bounds already computed by an inspection.

inspect_model already transforms every occurrence's expanded points into exact world bounds; this constructor folds those results instead of recomputing them, so callers building both an inspection and a summary pay for the geometry only once.

from_occurrences classmethod

from_occurrences(
    occurrences: Iterable[ModelOccurrence],
    parts: Parts | None,
) -> ModelSummary

Build a summary from occurrences already traversed by a caller.

OccurrenceAttribution dataclass

Stable traversal identity and full source path for one occurrence.

index instance-attribute

index: int

occurrence instance-attribute

occurrence: ModelOccurrence

model_path instance-attribute

model_path: tuple[str, ...]

reference_path instance-attribute

reference_path: tuple[str, ...]

source_line_path instance-attribute

source_line_path: tuple[int | None, ...]

local_step_path instance-attribute

local_step_path: tuple[int | None, ...]

effective_step_path instance-attribute

effective_step_path: tuple[int | None, ...]

page_path instance-attribute

page_path: tuple[int | None, ...]

step_path property

step_path: tuple[int | None, ...]

Compatibility alias for local source steps.

installation_page property

installation_page: int | None

Page that places the outermost occurrence or submodel instance.

source_page property

source_page: int | None

Page local to the section which directly places the leaf part.

OccurrenceContact dataclass

One occurrence and its nearest AABB neighbour.

subject instance-attribute

subject: OccurrenceGeometry

nearest instance-attribute

nearest: OccurrenceGeometry

gap instance-attribute

gap: BoundsGap

OccurrenceGeometry dataclass

Expanded local geometry transformed into one occurrence's world frame.

attribution instance-attribute

attribution: OccurrenceAttribution

local instance-attribute

local: PartGeometry

bounds instance-attribute

bounds: BoundingBox

studs instance-attribute

studs: tuple[StudReference, ...]

connections class-attribute instance-attribute

connections: tuple[ConnectionFeature, ...] = ()

occurrence property

occurrence: ModelOccurrence

Return the source occurrence represented by this geometry.

index property

index: int

Return the occurrence's stable analysis-order index.

OccurrencePathItem dataclass

One local placement in a root-to-leaf occurrence path.

model instance-attribute

model: Model

piece instance-attribute

piece: Piece

source_line instance-attribute

source_line: int | None

local_step instance-attribute

local_step: int | None

effective_step instance-attribute

effective_step: int | None

step property

step: int | None

Compatibility spelling for local_step — the local step.

This is the step counted within the placement's own section, not the inherited one, so for submodel contents it differs from ModelOccurrence.step (which is the effective step). Use effective_step for the inherited semantics.

OperationCancelled

Bases: Exception

A caller requested cancellation of an in-progress operation.

Deliberately derives from Exception rather than RuntimeError: setup helpers such as ensure_library wrap genuine failures in RuntimeError, so a caller's except RuntimeError must not misreport a user-requested cancel as a failure.

PartCategory

Bases: StrEnum

Known LDraw part categories, mirroring the official LDraw.org list.

ANIMAL class-attribute instance-attribute

ANIMAL = 'animal'

ANTENNA class-attribute instance-attribute

ANTENNA = 'antenna'

ARCH class-attribute instance-attribute

ARCH = 'arch'

ARM class-attribute instance-attribute

ARM = 'arm'

BAR class-attribute instance-attribute

BAR = 'bar'

BASEPLATE class-attribute instance-attribute

BASEPLATE = 'baseplate'

BELVILLE class-attribute instance-attribute

BELVILLE = 'belville'

BOAT class-attribute instance-attribute

BOAT = 'boat'

BRACKET class-attribute instance-attribute

BRACKET = 'bracket'

BRICK class-attribute instance-attribute

BRICK = 'brick'

CANVAS class-attribute instance-attribute

CANVAS = 'canvas'

CAR class-attribute instance-attribute

CAR = 'car'

CLIKITS class-attribute instance-attribute

CLIKITS = 'clikits'

COCKPIT class-attribute instance-attribute

COCKPIT = 'cockpit'

CONE class-attribute instance-attribute

CONE = 'cone'

CONSTRACTION class-attribute instance-attribute

CONSTRACTION = 'constraction'

CONSTRACTION_ACCESSORY class-attribute instance-attribute

CONSTRACTION_ACCESSORY = 'constraction accessory'

CONTAINER class-attribute instance-attribute

CONTAINER = 'container'

CONVEYOR class-attribute instance-attribute

CONVEYOR = 'conveyor'

CRANE class-attribute instance-attribute

CRANE = 'crane'

CYLINDER class-attribute instance-attribute

CYLINDER = 'cylinder'

DISH class-attribute instance-attribute

DISH = 'dish'

DOOR class-attribute instance-attribute

DOOR = 'door'

DUPLO class-attribute instance-attribute

DUPLO = 'duplo'

ELECTRIC class-attribute instance-attribute

ELECTRIC = 'electric'

EXHAUST class-attribute instance-attribute

EXHAUST = 'exhaust'

FENCE class-attribute instance-attribute

FENCE = 'fence'

FIGURE class-attribute instance-attribute

FIGURE = 'figure'

FIGURE_ACCESSORY class-attribute instance-attribute

FIGURE_ACCESSORY = 'figure accessory'

FLAG class-attribute instance-attribute

FLAG = 'flag'

FORKLIFT class-attribute instance-attribute

FORKLIFT = 'forklift'

FREESTYLE class-attribute instance-attribute

FREESTYLE = 'freestyle'

GARAGE class-attribute instance-attribute

GARAGE = 'garage'

GLASS class-attribute instance-attribute

GLASS = 'glass'

GRAB class-attribute instance-attribute

GRAB = 'grab'

HINGE class-attribute instance-attribute

HINGE = 'hinge'

HOMEMAKER class-attribute instance-attribute

HOMEMAKER = 'homemaker'

HOSE class-attribute instance-attribute

HOSE = 'hose'

LADDER class-attribute instance-attribute

LADDER = 'ladder'

LEVER class-attribute instance-attribute

LEVER = 'lever'

MAGNET class-attribute instance-attribute

MAGNET = 'magnet'

MINIFIG class-attribute instance-attribute

MINIFIG = 'minifig'

MINIFIG_ACCESSORY class-attribute instance-attribute

MINIFIG_ACCESSORY = 'minifig accessory'

MINIFIG_FOOTWEAR class-attribute instance-attribute

MINIFIG_FOOTWEAR = 'minifig footwear'

MINIFIG_HEADWEAR class-attribute instance-attribute

MINIFIG_HEADWEAR = 'minifig headwear'

MINIFIG_HIPWEAR class-attribute instance-attribute

MINIFIG_HIPWEAR = 'minifig hipwear'

MINIFIG_NECKWEAR class-attribute instance-attribute

MINIFIG_NECKWEAR = 'minifig neckwear'

MONORAIL class-attribute instance-attribute

MONORAIL = 'monorail'

PANEL class-attribute instance-attribute

PANEL = 'panel'

PLANE class-attribute instance-attribute

PLANE = 'plane'

PLANT class-attribute instance-attribute

PLANT = 'plant'

PLATE class-attribute instance-attribute

PLATE = 'plate'

PLATFORM class-attribute instance-attribute

PLATFORM = 'platform'

PROPELLOR class-attribute instance-attribute

PROPELLOR = 'propellor'

RACK class-attribute instance-attribute

RACK = 'rack'

ROADSIGN class-attribute instance-attribute

ROADSIGN = 'roadsign'

ROCK class-attribute instance-attribute

ROCK = 'rock'

SCALA class-attribute instance-attribute

SCALA = 'scala'

SCREW class-attribute instance-attribute

SCREW = 'screw'

SHEET_CARDBOARD class-attribute instance-attribute

SHEET_CARDBOARD = 'sheet cardboard'

SHEET_FABRIC class-attribute instance-attribute

SHEET_FABRIC = 'sheet fabric'

SHEET_PLASTIC class-attribute instance-attribute

SHEET_PLASTIC = 'sheet plastic'

SLOPE class-attribute instance-attribute

SLOPE = 'slope'

SPHERE class-attribute instance-attribute

SPHERE = 'sphere'

STAIRCASE class-attribute instance-attribute

STAIRCASE = 'staircase'

STICKER class-attribute instance-attribute

STICKER = 'sticker'

STRING class-attribute instance-attribute

STRING = 'string'

SUPPORT class-attribute instance-attribute

SUPPORT = 'support'

TAIL class-attribute instance-attribute

TAIL = 'tail'

TAP class-attribute instance-attribute

TAP = 'tap'

TECHNIC class-attribute instance-attribute

TECHNIC = 'technic'

TILE class-attribute instance-attribute

TILE = 'tile'

TIPPER class-attribute instance-attribute

TIPPER = 'tipper'

TRACTOR class-attribute instance-attribute

TRACTOR = 'tractor'

TRAILER class-attribute instance-attribute

TRAILER = 'trailer'

TRAIN class-attribute instance-attribute

TRAIN = 'train'

TURNTABLE class-attribute instance-attribute

TURNTABLE = 'turntable'

TYRE class-attribute instance-attribute

TYRE = 'tyre'

VEHICLE class-attribute instance-attribute

VEHICLE = 'vehicle'

WEDGE class-attribute instance-attribute

WEDGE = 'wedge'

WHEEL class-attribute instance-attribute

WHEEL = 'wheel'

WINCH class-attribute instance-attribute

WINCH = 'winch'

WINDOW class-attribute instance-attribute

WINDOW = 'window'

WINDSCREEN class-attribute instance-attribute

WINDSCREEN = 'windscreen'

WING class-attribute instance-attribute

WING = 'wing'

ZNAP class-attribute instance-attribute

ZNAP = 'znap'

OTHER class-attribute instance-attribute

OTHER = 'other'

module_name property

module_name: str

Return the generated module name for this category.

These names are a frozen public contract: renaming one would break existing ldraw.library.parts.* imports.

from_label classmethod

from_label(label: str | None) -> PartCategory | None

Return the category matching an LDraw label.

PartCompatibility dataclass

Evidence that two complete parts fit one another.

first instance-attribute

first: str

second instance-attribute

second: str

relation instance-attribute

relation: str

source instance-attribute

source: ConnectionSource

evidence class-attribute instance-attribute

evidence: str | None = None

PartFileKind

Bases: StrEnum

Kind declared by the !LDRAW_ORG header.

PART class-attribute instance-attribute

PART = 'part'

SUBPART class-attribute instance-attribute

SUBPART = 'subpart'

PRIMITIVE class-attribute instance-attribute

PRIMITIVE = 'primitive'

PRIMITIVE_8 class-attribute instance-attribute

PRIMITIVE_8 = '8_primitive'

PRIMITIVE_48 class-attribute instance-attribute

PRIMITIVE_48 = '48_primitive'

SHORTCUT class-attribute instance-attribute

SHORTCUT = 'shortcut'

UNKNOWN class-attribute instance-attribute

UNKNOWN = 'unknown'

PartGeometry dataclass

Expanded drawable geometry plus explicit completeness diagnostics.

code instance-attribute

code: str

description instance-attribute

description: str

bounds instance-attribute

bounds: BoundingBox | None

points instance-attribute

points: tuple[Vector, ...]

studs instance-attribute

studs: tuple[StudReference, ...]

connections class-attribute instance-attribute

connections: tuple[ConnectionFeature, ...] = ()

diagnostics class-attribute instance-attribute

diagnostics: tuple[Diagnostic, ...] = ()

connection_metadata class-attribute instance-attribute

connection_metadata: ConnectionMetadataReport | None = None

complete property

complete: bool

Whether every referenced child was resolved and expanded.

top_studs property

top_studs: tuple[StudReference, ...]

Upward-facing stud connectors in local coordinates.

receptacles property

receptacles: tuple[StudReference, ...]

Detected underside/tube receivers in local coordinates.

PartHistoryEntry dataclass

One parsed !HISTORY line.

date instance-attribute

date: str

contributor instance-attribute

contributor: str | None

text instance-attribute

text: str

raw instance-attribute

raw: str

PartInspection dataclass

Part lookup, metadata, references, geometry, and explicit failures.

code instance-attribute

code: str

entry instance-attribute

entry: CatalogEntry | None

path instance-attribute

path: Path | None

metadata instance-attribute

metadata: PartMetadata | None

references instance-attribute

references: tuple[PartReference, ...]

geometry instance-attribute

geometry: PartGeometry | None

diagnostics instance-attribute

diagnostics: tuple[Diagnostic, ...]

complete property

complete: bool

Return whether every requested inspection component succeeded.

PartMetadata dataclass

Metadata and relationships represented by an LDraw part header.

description instance-attribute

description: str

name class-attribute instance-attribute

name: str | None = None

author class-attribute instance-attribute

author: str | None = None

author_username class-attribute instance-attribute

author_username: str | None = None

file_kind class-attribute instance-attribute

file_kind: PartFileKind = PartFileKind.UNKNOWN

origin class-attribute instance-attribute

origin: LibraryOrigin = LibraryOrigin.UNKNOWN

qualifiers class-attribute instance-attribute

qualifiers: tuple[str, ...] = ()

release class-attribute instance-attribute

release: str | None = None

license class-attribute instance-attribute

license: str | None = None

bfc class-attribute instance-attribute

bfc: BfcCertification = BfcCertification.UNKNOWN

history class-attribute instance-attribute

history: tuple[PartHistoryEntry, ...] = ()

category class-attribute instance-attribute

category: str | None = None

keywords class-attribute instance-attribute

keywords: tuple[str, ...] = ()

status class-attribute instance-attribute

status: PartStatus = PartStatus.CURRENT

replacement class-attribute instance-attribute

replacement: str | None = None

preview class-attribute instance-attribute

preview: PreviewTransform | None = None

to_dict

to_dict() -> dict[str, Any]

Return a JSON-ready representation for the persistent catalog.

from_dict classmethod

from_dict(value: dict[str, Any]) -> PartMetadata

Restore metadata previously returned by to_dict.

PartReference dataclass

A type-1 subfile reference found inside a part file.

parent_code instance-attribute

parent_code: str

code instance-attribute

code: str

reference instance-attribute

reference: str

kind instance-attribute

kind: PartReferenceKind

description instance-attribute

description: str | None

colour instance-attribute

colour: Colour

position instance-attribute

position: Vector

matrix instance-attribute

matrix: Matrix

depth instance-attribute

depth: int

PartReferenceKind

Bases: StrEnum

Kind of type-1 reference found inside a part file.

PART class-attribute instance-attribute

PART = 'part'

SUBPART class-attribute instance-attribute

SUBPART = 'subpart'

PRIMITIVE class-attribute instance-attribute

PRIMITIVE = 'primitive'

UNKNOWN class-attribute instance-attribute

UNKNOWN = 'unknown'

PartStatus

Bases: StrEnum

Relationship/lifecycle status derived from header evidence.

CURRENT class-attribute instance-attribute

CURRENT = 'current'

ALIAS class-attribute instance-attribute

ALIAS = 'alias'

MOVED class-attribute instance-attribute

MOVED = 'moved'

OBSOLETE class-attribute instance-attribute

OBSOLETE = 'obsolete'

Parts

Part catalog loader.

ColourAttributes class-attribute instance-attribute

ColourAttributes = (
    "CHROME",
    "PEARLESCENT",
    "RUBBER",
    "MATTE_METALLIC",
    "METAL",
    "GLITTER",
    "SPECKLE",
    "LUMINANCE",
)

path instance-attribute

path = Path(parts_lst)

parts_dirs instance-attribute

parts_dirs: list[Path] = []

parts_subdirs instance-attribute

parts_subdirs: dict[str, Path] = {}

by_name instance-attribute

by_name: dict[str, str] = {}

by_code instance-attribute

by_code: dict[str, str] = {}

by_code_name instance-attribute

by_code_name: dict[tuple[str, str], Part | None] = {}

by_category instance-attribute

by_category: defaultdict[str, dict[str, str]] = defaultdict(
    dict
)

primitives_by_name instance-attribute

primitives_by_name: dict[str, str] = {}

primitives_by_code instance-attribute

primitives_by_code: dict[str, str] = {}

colours instance-attribute

colours: dict[str | int, str] = {}

alpha_values instance-attribute

alpha_values: dict[str | int, int] = {}

colour_attributes instance-attribute

colour_attributes: dict[str | int, list[str]] = {}

colours_by_name instance-attribute

colours_by_name: dict[str, Colour] = {}

colours_by_code instance-attribute

colours_by_code: dict[int, Colour] = {}

library_root property

library_root: Path

Directory containing parts.lst, parts, primitives, and colours.

catalog property

catalog: PartsCatalog

The typed parts catalog, categorized on first access.

tyre_rim_compatibility property

tyre_rim_compatibility: tuple[PartCompatibility, ...]

Tyre/rim pairs evidenced by official complete-part shortcuts.

get classmethod

get(
    parts_lst: str | Path,
    *,
    tree_fingerprint: str | None = None,
    parts_lst_md5: str | None = None,
    connection_shadows: Iterable[str | Path] = (),
    studio_metadata: Iterable[str | Path] = (),
) -> Parts

Get a memoized Parts keyed by list and optional content fingerprints.

Omitting parts_lst_md5 memoizes under a different key than passing it, so mixing both styles for one file parses it twice. Directory connection sources are deliberately not walked on cache lookup; call fresh after editing their nested contents.

clear_cache classmethod

clear_cache() -> None

Clear memoized instances, including stale directory sources.

fresh classmethod

fresh(
    parts_lst: str | Path,
    *,
    tree_fingerprint: str | None = None,
    parts_lst_md5: str | None = None,
    connection_shadows: Iterable[str | Path] = (),
    studio_metadata: Iterable[str | Path] = (),
) -> Parts

Return a freshly constructed Parts, replacing the memoized one.

Explicit rebuild paths call this to guarantee a genuinely fresh categorization and reload nested connection-source edits; the memo is repopulated with the fresh instance.

from_catalog classmethod

from_catalog(
    parts_lst: str | Path, catalog: PartsCatalog
) -> Parts

Construct a Parts that adopts a prebuilt catalog.

Skips the expensive per-part categorization pass.

adopt_catalog

adopt_catalog(catalog: PartsCatalog) -> None

Adopt a prebuilt catalog, skipping categorization.

A no-op when this instance is already categorized, so a memoized instance can safely adopt the same persisted index repeatedly.

build_catalog

build_catalog(
    *,
    on_progress: ProgressCallback | None = None,
    cancellation: CancellationToken | None = None,
) -> PartsCatalog

Materialize the catalog with determinate progress and cancellation.

get_entry_by_code

get_entry_by_code(code: str) -> CatalogEntry | None

Return a typed catalog entry by part code.

get_entry_by_description

get_entry_by_description(
    description: str,
) -> CatalogEntry | None

Return a typed catalog entry by part description.

entries_by_category

entries_by_category(
    category: PartCategory,
) -> tuple[CatalogEntry, ...]

Return entries in a part category.

minifig_entries

minifig_entries(
    section: MinifigSection | None = None,
) -> tuple[CatalogEntry, ...]

Return entries in minifigure sections.

get_category

get_category(part_description: str) -> PartCategory | None

Get the category of a part based on its description.

load

load() -> None

Load the parts list, colours, and primitives (all cheap passes).

The expensive categorization pass — opening every part file for its !CATEGORY header — runs lazily on first catalog access.

section_find

section_find(pieces: list[str]) -> tuple[str, str]

Return code and description from a parts.lst split line.

The description is kept exactly as written in parts.lst; detected minifig sections are recorded for the catalog. Generated symbol names strip the Minifig prefix at generation time (see symbol_description).

description_for

description_for(code: str) -> str | None

Return the parts.lst description for a part code, or None.

The lookup tolerates casing differences: Piece.part preserves whatever casing the source used while parts.lst codes are typically lowercase, so the code is tried as given, lowercased, and uppercased.

part

part(
    description: str | None = None, code: str | None = None
) -> Part

Get a Part from its description or code.

Raises PartNotFoundError when the description or code is not in the library or the part file is missing; use find_part for a lookup that returns None instead.

find_part

find_part(
    description: str | None = None, code: str | None = None
) -> Part | None

Get a Part from its description or code, or None when not found.

bounding_box

bounding_box(code: str) -> BoundingBox

Axis-aligned bounding box of a part's geometry, in LDU.

Subfiles are resolved recursively; unresolvable ones are skipped with a warning. Raises PartNotFoundError for an unknown code and NoGeometryError when the part draws nothing.

geometry

geometry(code: str) -> PartGeometry

Return exact expanded geometry and completeness diagnostics.

connections

connections(code: str) -> tuple[ConnectionFeature, ...]

Return physical connection features detected for a part.

connection_metadata

connection_metadata(code: str) -> ConnectionMetadataReport

Return features and normalized metadata coverage for a part.

add_connection_shadow

add_connection_shadow(source: str | Path) -> None

Add an LDCad shadow library as an optional connection source.

Sources are applied in registration order; later sources can clear or supersede features from earlier sources.

clear_connection_shadows

clear_connection_shadows() -> None

Remove all configured LDCad shadow-library sources.

add_studio_metadata

add_studio_metadata(source: str | Path) -> None

Add a Studio connectivity JSON source at Studio precedence.

clear_studio_metadata

clear_studio_metadata() -> None

Remove every configured Studio connectivity source.

set_connection_overrides

set_connection_overrides(
    code: str,
    features: Iterable[ConnectionFeature],
    *,
    replace_existing: bool = False,
) -> None

Register authoritative connection features for one part.

By default overrides augment inferred and shadow-derived features. Set replace_existing to discard every lower-priority feature.

clear_connection_overrides

clear_connection_overrides(code: str | None = None) -> None

Remove connection overrides for one part or the whole library.

compatible_tyres

compatible_tyres(rim_code: str) -> tuple[str, ...]

Return tyre codes evidenced as compatible with rim_code.

compatible_rims

compatible_rims(tyre_code: str) -> tuple[str, ...]

Return rim codes evidenced as compatible with tyre_code.

inspect_part

inspect_part(
    code: str,
    *,
    include_geometry: bool = True,
    recursive_references: bool = False,
) -> PartInspection

Inspect one part without translating failures into empty data.

studs

studs(code: str) -> tuple[StudReference, ...]

All stud primitives a part places, in the part's own coordinates.

Includes underside tubes and other downward studs; filter with StudReference.is_top_stud or use stud_positions.

stud_positions

stud_positions(code: str) -> tuple[Vector, ...]

Positions of a part's top studs (upward connectors), in LDU.

resolve_colour

resolve_colour(colour: Colour | int) -> Colour

Return catalog metadata for colour when it is known.

references_for

references_for(
    code: str, *, recursive: bool = False
) -> tuple[PartReference, ...]

Return type-1 references placed by a part file.

PartsCatalog dataclass

Typed collection of part catalog entries.

by_code class-attribute instance-attribute

by_code: dict[str, CatalogEntry] = field(
    default_factory=dict
)

by_description class-attribute instance-attribute

by_description: dict[str, CatalogEntry] = field(
    default_factory=dict
)

by_category class-attribute instance-attribute

by_category: defaultdict[
    PartCategory, list[CatalogEntry]
] = field(default_factory=lambda: defaultdict(list))

by_minifig_section class-attribute instance-attribute

by_minifig_section: defaultdict[
    MinifigSection, list[CatalogEntry]
] = field(default_factory=lambda: defaultdict(list))

add

add(entry: CatalogEntry) -> None

Add or replace an entry in every lookup index.

get_entry_by_code

get_entry_by_code(code: str) -> CatalogEntry | None

Return a catalog entry by part code.

get_entry_by_description

get_entry_by_description(
    description: str,
) -> CatalogEntry | None

Return a catalog entry by part description.

entries_by_category

entries_by_category(
    category: PartCategory,
) -> tuple[CatalogEntry, ...]

Return catalog entries in a category.

minifig_entries

minifig_entries(
    section: MinifigSection | None = None,
) -> tuple[CatalogEntry, ...]

Return minifigure catalog entries, optionally for one section.

search

search(
    query: str,
    *,
    within: Iterable[CatalogEntry] | None = None,
    fields: Iterable[
        CatalogSearchField
    ] = ALL_CATALOG_SEARCH_FIELDS,
    limit: int | None = None,
) -> tuple[CatalogEntry, ...]

Return normalized token matches in deterministic relevance order.

Every token must occur somewhere in the selected fields. within scopes the search to a caller-provided category or other subset.

module_sections

module_sections() -> dict[tuple[str, ...], dict[str, str]]

Return generated module sections keyed by package path.

Section dicts are keyed by the catalog description exactly as written in parts.lst; symbol names (including minifig-prefix stripping) are derived at generation time, where collisions are deduplicated with part-code suffixes.

Person

Representation of a LEGO minifigure.

position instance-attribute

position = (
    position if position is not None else Vector(0, 0, 0)
)

matrix instance-attribute

matrix = matrix if matrix is not None else Identity()

pieces_info instance-attribute

pieces_info: dict[str, Piece] = {}

group instance-attribute

group = group

head

head(
    colour: ColourInput, angle: Number = 0, part: str = Head
) -> Piece

Add a head.

hat

hat(
    head: Piece, colour: ColourInput, part: str = Hat
) -> Piece

Add a hat piece to the figure's head.

torso

torso(colour: ColourInput, part: str = Torso) -> Piece

Add a torso piece.

backpack

backpack(
    colour: ColourInput,
    displacement: Vector | None = None,
    part: str = Airtanks,
) -> Piece

Add a backpack.

hips_and_legs

hips_and_legs(
    colour: ColourInput, part: str = HipsAndLegs
) -> Piece

Add combined hips and legs.

hips

hips(colour: ColourInput, part: str = Hips) -> Piece

Add hips.

left_arm

left_arm(
    colour: ColourInput,
    angle: Number = 0,
    part: str = ArmLeft,
) -> Piece

Add a left arm.

left_hand

left_hand(
    left_arm: Piece,
    colour: ColourInput,
    angle: Number = 0,
    part: str = Hand,
) -> Piece

Add a left hand piece to the figure's left arm.

left_hand_item

left_hand_item(
    left_hand: Piece,
    colour: ColourInput,
    displacement: Vector,
    angle: Number = 0,
    part: str | None = None,
) -> Piece | None

Add an item to the left hand.

right_arm

right_arm(
    colour: ColourInput,
    angle: Number = 0,
    part: str = ArmRight,
) -> Piece

Add a right arm.

right_hand

right_hand(
    right_arm: Piece,
    colour: ColourInput,
    angle: Number = 0,
    part: str = Hand,
) -> Piece

Add a right hand piece to the figure's right arm.

right_hand_item

right_hand_item(
    right_hand: Piece,
    colour: ColourInput,
    displacement: Vector,
    angle: Number = 0,
    part: str | None = None,
) -> Piece | None

Add a right hand item.

left_leg

left_leg(
    colour: ColourInput,
    angle: Number = 0,
    part: str = LegLeft,
) -> Piece

Add a left leg.

left_shoe

left_shoe(
    left_leg: Piece,
    colour: ColourInput,
    angle: Number = 0,
    part: str | None = None,
) -> Piece | None

Add a shoe on the left.

right_leg

right_leg(
    colour: ColourInput,
    angle: Number = 0,
    part: str = LegRight,
) -> Piece

Add a right leg.

right_shoe

right_shoe(
    right_leg: Piece,
    colour: ColourInput,
    angle: Number = 0,
    part: str | None = None,
) -> Piece | None

Add a shoe on the right.

Piece dataclass

A part with a defined colour, position, and rotation.

colour instance-attribute

colour: Colour = _as_colour(colour)

position instance-attribute

position: Vector = position

matrix instance-attribute

matrix: Matrix = matrix

part instance-attribute

part: str = part

suffix class-attribute instance-attribute

suffix: str = suffix

group class-attribute instance-attribute

group: Group | None = None

reference property

reference: str

The subfile reference this piece serializes to, e.g. 3001.dat.

place classmethod

place(
    part: str,
    *,
    colour: Colour | int = MAIN_COLOUR_CODE,
    position: Vector | None = None,
    matrix: Matrix | None = None,
    group: Group | None = None,
    suffix: str = DEFAULT_SUFFIX,
) -> Self

Create a piece keyword-first, defaulting to the origin and identity.

to_ldraw

to_ldraw() -> str

Serialize this piece to an LDraw type 1 line.

PreviewTransform dataclass

Official !PREVIEW colour and placement transform.

colour_code instance-attribute

colour_code: int

position instance-attribute

position: Vector

matrix instance-attribute

matrix: Matrix

ProgressEvent dataclass

One progress update from a long-running library operation.

stage instance-attribute

stage: ProgressStage

message instance-attribute

message: str

current class-attribute instance-attribute

current: int | None = None

total class-attribute instance-attribute

total: int | None = None

path class-attribute instance-attribute

path: Path | None = None

unit class-attribute instance-attribute

unit: ProgressUnit | None = None

determinate property

determinate: bool

Whether this event has a current value, total, and explicit unit.

ProgressStage

Bases: StrEnum

High-level setup stages reported to embedding applications.

DOWNLOAD class-attribute instance-attribute

DOWNLOAD = 'download'

UNPACK class-attribute instance-attribute

UNPACK = 'unpack'

PARTS_LIST class-attribute instance-attribute

PARTS_LIST = 'parts-list'

LIBRARY_GENERATION class-attribute instance-attribute

LIBRARY_GENERATION = 'library-generation'

FINGERPRINT class-attribute instance-attribute

FINGERPRINT = 'fingerprint'

INDEX_LOAD class-attribute instance-attribute

INDEX_LOAD = 'index-load'

INDEX_REBUILD class-attribute instance-attribute

INDEX_REBUILD = 'index-rebuild'

LIBRARY_DISCOVERY class-attribute instance-attribute

LIBRARY_DISCOVERY = 'library-discovery'

VALIDATION class-attribute instance-attribute

VALIDATION = 'validation'

RENDER class-attribute instance-attribute

RENDER = 'render'

DONE class-attribute instance-attribute

DONE = 'done'

ProgressUnit

Bases: StrEnum

Unit carried by determinate progress events.

BYTES class-attribute instance-attribute

BYTES = 'bytes'

FILES class-attribute instance-attribute

FILES = 'files'

PARTS class-attribute instance-attribute

PARTS = 'parts'

STEPS class-attribute instance-attribute

STEPS = 'steps'

VIEWS class-attribute instance-attribute

VIEWS = 'views'

RenderBackend

Bases: StrEnum

Supported optional command-line renderers, in preference order.

LDVIEW class-attribute instance-attribute

LDVIEW = 'ldview'

LEOCAD class-attribute instance-attribute

LEOCAD = 'leocad'

RenderCapability dataclass

Availability and executable path for one optional backend.

backend instance-attribute

backend: RenderBackend

available instance-attribute

available: bool

executable instance-attribute

executable: Path | None

RenderResult dataclass

Output or diagnostics from one preview request.

source instance-attribute

source: Path

view instance-attribute

view: RenderView

size instance-attribute

size: tuple[int, int]

backend instance-attribute

backend: RenderBackend | None

output instance-attribute

output: Path | None

cached instance-attribute

cached: bool

diagnostics class-attribute instance-attribute

diagnostics: tuple[Diagnostic, ...] = ()

complete property

complete: bool

Return whether a usable image was produced.

RenderView

Bases: StrEnum

Stable named preview viewpoints.

FRONT class-attribute instance-attribute

FRONT = 'front'

ISOMETRIC class-attribute instance-attribute

ISOMETRIC = 'isometric'

TOP class-attribute instance-attribute

TOP = 'top'

RotationMode

Bases: StrEnum

MLCad rotation-step modes.

RELATIVE class-attribute instance-attribute

RELATIVE = 'REL'

ADDITIVE class-attribute instance-attribute

ADDITIVE = 'ADD'

ABSOLUTE class-attribute instance-attribute

ABSOLUTE = 'ABS'

END class-attribute instance-attribute

END = 'END'

RotationStep dataclass

A parsed MLCad ROTSTEP boundary.

mode instance-attribute

mode: RotationMode

angles instance-attribute

angles: tuple[float, float, float] | None

command_matrix instance-attribute

command_matrix: Matrix

effective_matrix instance-attribute

effective_matrix: Matrix

source_line class-attribute instance-attribute

source_line: int | None = None

SectionShape

Bases: StrEnum

Cross-section used by one cylindrical profile section.

ROUND class-attribute instance-attribute

ROUND = 'round'

AXLE class-attribute instance-attribute

AXLE = 'axle'

SQUARE class-attribute instance-attribute

SQUARE = 'square'

Severity

Bases: StrEnum

How serious a diagnostic is.

ERROR class-attribute instance-attribute

ERROR = 'error'

WARNING class-attribute instance-attribute

WARNING = 'warning'

SkippedGeometry dataclass

A part occurrence whose geometry could not be folded into bounds.

part instance-attribute

part: str

source_model instance-attribute

source_model: str

source_line instance-attribute

source_line: int | None

reason instance-attribute

reason: str

SkippedOccurrenceGeometry dataclass

Occurrence whose geometry could not produce world bounds.

attribution instance-attribute

attribution: OccurrenceAttribution

diagnostic instance-attribute

diagnostic: Diagnostic

reason property

reason: str

Return the structured diagnostic's human-readable message.

SnapCandidate dataclass

Compatible feature pair and the resulting moving-part placement.

moving_occurrence instance-attribute

moving_occurrence: OccurrenceGeometry

fixed_occurrence instance-attribute

fixed_occurrence: OccurrenceGeometry

moving instance-attribute

moving: ConnectionFeature

fixed instance-attribute

fixed: ConnectionFeature

transform instance-attribute

transform: SnapTransform

residual instance-attribute

residual: ConnectionResidual

SnapTransform dataclass

Rigid placement aligning one local feature to another feature.

position instance-attribute

position: Vector

matrix instance-attribute

matrix: Matrix

StudContact dataclass

Compatibility projection of one strict stud/receptacle feature match.

stud_occurrence instance-attribute

stud_occurrence: OccurrenceGeometry

supported_occurrence instance-attribute

supported_occurrence: OccurrenceGeometry

stud instance-attribute

stud: StudReference

position instance-attribute

position: Vector

stud_feature class-attribute instance-attribute

stud_feature: ConnectionFeature | None = None

receptacle_feature class-attribute instance-attribute

receptacle_feature: ConnectionFeature | None = None

residual class-attribute instance-attribute

residual: ConnectionResidual | None = None

StudReference dataclass

A stud primitive placed by a part, in the part's own coordinates.

name instance-attribute

name: str

Casefolded primitive stem, e.g. stud or stud4.

description instance-attribute

description: str

The primitive's header description, e.g. Stud Tube Open.

position instance-attribute

position: Vector

The primitive's origin -- for top studs, the centre of the stud base.

up class-attribute instance-attribute

up: Vector = field(default_factory=lambda: Vector(0, -1, 0))

Image of the stud's local up direction (0, -1, 0) under the placing transforms; unit length under rigid placements.

is_receptacle property

is_receptacle: bool

Whether this primitive describes an underside/tube receiver.

is_placeholder property

is_placeholder: bool

Whether this is a drawing placeholder rather than a connector.

is_top_stud property

is_top_stud: bool

Whether this stud is an upward connector a brick can sit on.

Excludes underside tubes and placeholder primitives by description, and any stud whose placing transforms point it away from up (LDraw up is -Y), such as the sideways front stud of a headlight brick.

StudioConnectionLibrary

Read the supported connectivity subset of a Studio JSON export.

A part row with an empty or absent connections list contributes no authoritative evidence: heuristic and primitive features are kept and coverage is unchanged. Explicit clear-to-empty is an LDCad SNAP_CLEAR or override concern.

source instance-attribute

source = Path(source).expanduser()

connections_for

connections_for(code: str) -> ShadowConnectionResult

Return one part's row, or the document fallback when absent.

This single-part view carries per-part statistics, so summing it over an assembly double-counts document evidence. Assembly aggregation must use _part_feature_contribution per child and _document_result_for once per root query instead.

ValidationIssue module-attribute

ValidationIssue = Diagnostic

Vector dataclass

A vector in 3D.

x instance-attribute

x: Number

y instance-attribute

y: Number

z instance-attribute

z: Number

repr property

repr: str

Return string representation of vector coordinates.

copy

copy() -> Self

Copy the vector to a new vector containing the same values.

cross

cross(other: Vector) -> Vector

Cross product.

dot

dot(other: Vector) -> float

Dot product.

normalized

normalized() -> Vector

Return a unit-length copy of this vector.

XAxis

Bases: Axis

X-axis representation.

YAxis

Bases: Axis

Y-axis representation.

ZAxis

Bases: Axis

Z-axis representation.

analyze_model

analyze_model(
    model: Model,
    *,
    parts: Parts | None = None,
    diagnostics: Iterable[Diagnostic] = (),
) -> ModelAnalysis

Traverse leaf occurrences once and reuse them for all derived views.

Cyclic submodel references (possible in tolerantly-loaded models) are skipped rather than raising; each skipped reference surfaces as an MPD_CYCLE diagnostic unless an equal one was already passed in via diagnostics.

angular_alignment_within

angular_alignment_within(
    alignment: float, tolerance_degrees: float
) -> bool

Return whether an absolute axis alignment is within a tolerance.

bill_of_materials

bill_of_materials(
    model: _ModelLike | None = None,
    *,
    parts: Parts | None = None,
    occurrences: Iterable[ModelOccurrence] | None = None,
) -> list[BomRow]

Count leaf pieces by part and colour, expanding submodel references.

A submodel placed twice contributes its pieces twice. Submodel reference pieces themselves are expanded, never counted. Colour 16 (the main colour) inside a submodel is resolved to the colour the submodel was placed with. Descriptions and colour names are resolved when a parts catalog is given.

References only resolve against the given model's own submodel table. To count one submodel of a larger model, pass root.submodel_view(name) rather than a model taken straight from Model.submodels — the latter treats nested submodel references as leaf parts.

Part codes are counted case-insensitively; each row shows the code as first written in the model.

bounds_gap

bounds_gap(
    left: BoundingBox, right: BoundingBox
) -> BoundsGap

Return axis and Euclidean distance between two AABBs.

connection_residual

connection_residual(
    left: ConnectionFeature, right: ConnectionFeature
) -> ConnectionResidual

Return centerline, axial, and orientation residuals for two features.

connections_compatible

connections_compatible(
    left: ConnectionFeature,
    right: ConnectionFeature,
    *,
    radius_tolerance: float = 0.35,
) -> bool

Return whether two features are physically eligible to mate.

discover_libraries

discover_libraries(
    paths: Iterable[str | Path] | None = None,
    *,
    on_progress: ProgressCallback | None = None,
    cancellation: CancellationToken | None = None,
) -> tuple[LibraryInspection, ...]

Discover valid and partial installations in configured/common locations.

download

download(
    *,
    show_progress: bool = True,
    version: str = COMPLETE_VERSION,
    on_progress: ProgressCallback | None = None,
    resume: bool = False,
    cancellation: CancellationToken | None = None,
) -> str

Download and unpack an LDraw library version, generating parts.lst file.

The complete library comes from ldraw.org; versioned releases come from snapshot tags of the rienafairefr/ldraw-parts GitHub repository.

ensure_library

ensure_library(
    config: Config | None = None,
    *,
    version: str = COMPLETE_VERSION,
    write_config: bool = False,
    config_file: str | Path | None = None,
    force_generate: bool = False,
    on_progress: ProgressCallback | None = None,
    cancellation: CancellationToken | None = None,
) -> LDrawSession

Ensure a configured library, generated package, and catalog index exist.

When the library is downloaded, config.ldraw_library_path is updated in place on the caller's Config (persisted only when write_config is true), and the process-global default import configuration is replaced via LibraryImporter.set_config.

generate

generate(
    config: Config,
    *,
    force: bool = False,
    on_progress: ProgressCallback | None = None,
    fingerprint: str | None = None,
    cancellation: CancellationToken | None = None,
) -> None

Generate the library from configuration.

inspect_library

inspect_library(path: str | Path) -> LibraryInspection

Inspect a candidate installation without building its catalog.

inspect_model

inspect_model(
    model: Model,
    parts: Parts,
    *,
    occurrences: Iterable[ModelOccurrence] | None = None,
    page_marker_prefix: str = DEFAULT_PAGE_MARKER_PREFIX,
) -> ModelInspection

Inspect leaf occurrences using recursively expanded exact geometry.

iter_instruction_issues

iter_instruction_issues(
    document: InstructionDocument,
    *,
    max_parts: int | None = None,
) -> Iterator[InstructionIssue]

Yield structural and semantic issues in document.

iter_ldr_issues

iter_ldr_issues(
    path: Path | ModelLoadResult, parts: Parts | None = None
) -> Iterator[ValidationIssue]

Yield the issues found in an LDraw model or part file, in line order.

Malformed lines, unparseable colour values, and (when a parts catalog with colour definitions is given) unknown part references and colour codes are errors. Suspicious-but-legal constructs — legacy dithered colours, non-orthonormal or singular transformation matrices, and unknown bang meta-commands — are warnings.

Unreadable or non-UTF-8 files do not raise; they yield an IO_READ_FAILED or IO_DECODE_FAILED error diagnostic with line_number=None. Issues are yielded sorted by line number, with file-level diagnostics (line_number=None) first.

load_model

load_model(
    path: Path | str,
    parts: Parts | None = None,
    *,
    tolerant: bool = True,
) -> ModelLoadResult

Read, parse, and validate a model without throwing for data failures.

model_bounds

model_bounds(
    model: Model, parts: Parts
) -> BoundingBox | None

Return the true transformed bounds for model in LDraw units.

parse_model

parse_model(
    text: str,
    *,
    name: str = "",
    source: Path | str | None = None,
) -> Model

Parse LDraw document text into a Model.

A document without 0 FILE sections becomes a single model. In an MPD document the first section becomes the returned root model and later sections become its submodels, resolvable via Model.submodel_for.

parse_model_result

parse_model_result(
    text: str,
    *,
    name: str = "",
    source: Path | str | None = None,
    parts: Parts | None = None,
    tolerant: bool = True,
) -> ModelLoadResult

Parse and validate text once, optionally retaining a partial model.

plan_download

plan_download(
    version: str = COMPLETE_VERSION,
    *,
    cache_path: str | Path | None = None,
    cancellation: CancellationToken | None = None,
) -> DownloadPlan

Inspect remote size/resume support and local archive integrity.

prepare_catalog

prepare_catalog(
    config: Config | None = None,
    *,
    capabilities: Iterable[LDrawCapability] = (
        LDrawCapability.CATALOG,
    ),
    connection_shadows: Iterable[str | Path] = (),
    studio_metadata: Iterable[str | Path] = (),
    force: bool = False,
    on_progress: ProgressCallback | None = None,
    cancellation: CancellationToken | None = None,
) -> CatalogPreparationResult

Prepare requested configured data and return a structured report.

read_model

read_model(path: Path | str) -> Model

Read a .ldr or .mpd file into a Model.

render_capabilities

render_capabilities() -> tuple[RenderCapability, ...]

Detect optional renderers without invoking them.

render_preview

render_preview(
    source: str | Path,
    *,
    view: RenderView = RenderView.ISOMETRIC,
    size: tuple[int, int] = (800, 600),
    backend: RenderBackend | None = None,
    output: str | Path | None = None,
    cache_path: str | Path | None = None,
    refresh: bool = False,
    on_progress: ProgressCallback | None = None,
    cancellation: CancellationToken | None = None,
) -> RenderResult

Render one view, using a content-addressed PNG cache when possible.

The cache key covers the top-level source bytes, the resolved renderer executable path, and the full render command (backend, view angles, size, and renderer options). Files referenced by the source (submodels and sidecar part files) and the parts-library state are NOT part of the key, so edits to them do not invalidate cached previews; pass refresh=True to skip the cache read and force a re-render (the fresh image is still written back to the cache). The managed default cache evicts PNGs older than 90 days and caps retained data at 512 MiB, checking at most once per hour; caller-provided cache directories are never pruned automatically.

snap_transform

snap_transform(
    moving: ConnectionFeature, target: ConnectionFeature
) -> SnapTransform

Return a rigid transform placing moving onto target.

Centered cylindrical interfaces are direction-symmetric, so their target frame is flipped when that gives the smaller axis rotation; non-centered profiles extend one-sided and always mate axis-to-axis. Cross-section roll is preserved for axle profiles. Candidate frames are matched to the moving frame's handedness, so the delta is always a proper rotation and a part placed with a mirroring matrix is never reflected.

rows_to_csv

rows_to_csv(rows: Iterable[BomRow]) -> str

Serialize rows to CSV text with a header line.

rows_to_json

rows_to_json(rows: Iterable[BomRow]) -> str

Serialize rows to a JSON array of objects.

Config

Configuration settings for pyldraw.

ldraw_library_path instance-attribute

ldraw_library_path: str = (
    ldraw_library_path
    if ldraw_library_path is not None
    else str(Path(get_cache_dir()) / "complete")
)

generated_path instance-attribute

generated_path: str = (
    generated_path
    if generated_path is not None
    else str(Path(get_data_dir()) / "generated")
)

load classmethod

load(config_file: str | Path | None = None) -> Config

Load configuration from YAML file or create default configuration.

A missing file yields the defaults; an unreadable or malformed file raises ConfigLoadError naming the path and the problem.

to_dict

to_dict() -> dict[str, str]

Return public configuration values for serialization.

write

write(config_file: str | Path | None = None) -> None

Write the config atomically with a unique sibling temporary file.

NoGeometryError

Bases: PartError

The part (including its subfiles) draws no geometry at all.

code instance-attribute

code = code

message instance-attribute

message = message

source instance-attribute

source: str | None = None

line_number instance-attribute

line_number: int | None = None

add_context

add_context(*, source: str, line_number: int) -> Self

Extend the message with file/line context, at most once.

PartNotFoundError

Bases: PartError

Part was not found as expected.

code instance-attribute

code = code

path instance-attribute

path = path

message instance-attribute

message = message

source instance-attribute

source: str | None = None

line_number instance-attribute

line_number: int | None = None

add_context

add_context(*, source: str, line_number: int) -> Self

Extend the message with file/line context, at most once.

UnknownSubmodelError

Bases: PartError

The requested submodel name is not in this model's submodel table.

message instance-attribute

message = message

source instance-attribute

source: str | None = None

line_number instance-attribute

line_number: int | None = None

add_context

add_context(*, source: str, line_number: int) -> Self

Extend the message with file/line context, at most once.

part_bounding_box

part_bounding_box(
    parts: _PartGeometryLibrary, code: str
) -> BoundingBox

Axis-aligned bounding box of a part's geometry, in LDU.

Subfiles are resolved recursively and the expanded drawable points are transformed before the box is folded, including under oblique transforms. Unresolvable subfiles are skipped with a warning.

Raises PartNotFoundError for an unknown code and NoGeometryError when the part draws nothing. Read failures (OSError/UnicodeError) on the part's own file are tolerated the same way as unresolvable subfiles: the file contributes no geometry, so the query raises NoGeometryError rather than the underlying IO error.

part_studs

part_studs(
    parts: _PartGeometryLibrary, code: str
) -> tuple[StudReference, ...]

All stud primitives a part places, in the part's own coordinates.

Stud groups and subparts are expanded down to individual stud* primitives; recursion stops at each stud so nothing is counted twice. Filter with StudReference.is_top_stud (or use Parts.stud_positions) to keep only upward connectors.

symbol_description

symbol_description(description: str) -> str

Return the description that generated symbol names derive from.

Minifig part descriptions drop their Minifig prefix so symbols in the minifig/minifig_* modules read Torso, not MinifigTorso; every other description passes through unchanged.

module_path

module_path(entry: CatalogEntry) -> str | None

Return the generated module path containing entry, if any.

suggested_import

suggested_import(entry: CatalogEntry) -> str | None

Return an import statement for entry in the generated library.

symbol_name

symbol_name(entry: CatalogEntry) -> str

Return the generated Python symbol name for a catalog entry.

symbol_name_for_description

symbol_name_for_description(description: str) -> str

Return the generated Python symbol for an LDraw description.