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.

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.

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, ...] = ()

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.

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.

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.

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) -> LDrawPaths

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() -> LDrawState

Classify the configured library, catalog index, and generated package.

load

load() -> Parts

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

rebuild_index

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

Rebuild the persistent catalog index and return the loaded parts.

open_model

open_model(path: Path | str) -> Model

Read a .ldr or .mpd model file.

LDrawState dataclass

Freshness state for a configured LDraw library and generated data.

paths instance-attribute

paths: LDrawPaths

reasons instance-attribute

reasons: tuple[LDrawStateReason, ...]

ready property

ready: bool

Whether the catalog index and generated library are fresh.

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"
)

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.

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(piece: Piece) -> int | None

Return the parsed source line for this exact piece 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.

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).

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.

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.

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

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) -> ModelSummary

Build a summary for model using geometry from parts.

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.

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'

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] = {}

catalog property

catalog: PartsCatalog

The typed parts catalog, categorized on first access.

get classmethod

get(parts_lst: str | Path) -> Parts

Get a memoized Parts instance, keyed by path, mtime, and size.

clear_cache classmethod

clear_cache() -> None

Clear the memoized Parts instances.

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.

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.

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.

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.

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

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'

INDEX_REBUILD class-attribute instance-attribute

INDEX_REBUILD = 'index-rebuild'

DONE class-attribute instance-attribute

DONE = 'done'

Severity

Bases: StrEnum

How serious a validation issue 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

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_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.

ValidationIssue dataclass

A problem found on one line of an LDraw file.

line_number instance-attribute

line_number: int

message instance-attribute

message: str

severity class-attribute instance-attribute

severity: Severity = Severity.ERROR

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.

bill_of_materials

bill_of_materials(
    model: _ModelLike, *, parts: Parts | 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.

download

download(
    *,
    show_progress: bool = True,
    version: str = COMPLETE_VERSION,
    on_progress: ProgressCallback | 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,
) -> 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,
) -> None

Generate the library from configuration.

iter_ldr_issues

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

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

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.

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.

read_model

read_model(path: Path | str) -> Model

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

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 their memoized boxes composed by transforming box corners, which is exact under the axis-aligned rotations that dominate the library and slightly conservative under oblique ones. Unresolvable subfiles are skipped with a warning.

Raises PartNotFoundError for an unknown code and NoGeometryError when the part draws nothing.

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.