Skip to content

Catalog

The catalog resolves part and color ids into shapes, geometry and colors.

catalog

The parts and colors bricky knows.

The catalog keys parts and colors by their BrickLink ids. BrickLink, the LEGO Group's marketplace, lists every part. bricky catalog import imports BrickLink's catalog into a catalog file (see :mod:bricky.catalog.importing), and bricky uses the small sample shipped with it until then.

Each catalog part carries BrickLink's facts and, when bricky has one, a shape: the family that generates the part's geometry and the numbers the family needs. The catalog generates a part's geometry on first use, so a catalog of every part loads quickly.

SAMPLE_CATALOG module-attribute

SAMPLE_CATALOG: Final = Path(
    str(
        files("bricky.catalog").joinpath(
            "data", "sample.toml"
        )
    )
)

The sample catalog shipped with bricky.

The sample holds common parts and colors, with shapes written by hand.

IMPORTED_CATALOG module-attribute

IMPORTED_CATALOG: Final = (
    user_data_path("bricky", appauthor=False)
    / "catalog.json"
)

The file bricky catalog import writes by default.

bricky also looks for a catalog in this file.

Catalog

Catalog(
    parts: Iterable[CatalogPart | Mapping[str, Any]] = (),
    colors: Iterable[Color] = (),
    *,
    source: str = "",
)

An immutable index of parts and colors.

A part entry is a :class:CatalogPart or raw data. The catalog validates raw data the first time the entry is needed, so a catalog of every BrickLink part loads in a fraction of a second.

Index parts and colors by id; a part stays raw data until first used.

is_sample property

is_sample: bool

Whether this is the sample shipped with bricky, not an imported catalog.

entries property

entries: tuple[CatalogPart, ...]

Every catalog part, with or without a shape, in catalog order.

parts property

parts: tuple[Part, ...]

Every part with a shape, in catalog order.

Reading the property generates every part's geometry.

colors property

colors: tuple[Color, ...]

Every color, in catalog order.

from_data classmethod

from_data(
    data: Mapping[str, Any], *, origin: str = "catalog data"
) -> Catalog

Build a catalog from the data of a catalog file.

The catalog validates colors at once and each part when first used.

Raises:

Type Description
BrickyError

If the data is not a catalog, or an id or name repeats.

entry

entry(part_id: str) -> CatalogPart | None

Return the catalog part with a BrickLink id, with or without a shape.

A part's alternate ids find it too: 3068b finds the part BrickLink lists as 3068.

shape

shape(part_id: str) -> Shape | None

Return a part's shape, or a printed part's base's shape, or None.

part

part(part_id: str) -> Part | None

Return the part with a BrickLink id, or None when it has no shape.

color

color(color_id: int) -> Color | None

Return the color with a BrickLink id, or None if the catalog lacks it.

resolve_color

resolve_color(value: int | str) -> Color

Return the color with a BrickLink color id or a name, ignoring case.

Raises:

Type Description
ValueError

If no color matches.

find

find(
    *,
    family: Family | str | None = None,
    size: tuple[int, int] | None = None,
) -> list[Part]

Return the parts of a family and footprint, plain parts before printed ones.

Parameters:

Name Type Description Default
family Family | str | None

A family, such as "plate"; any family when omitted.

None
size tuple[int, int] | None

A footprint in studs, in either order: (1, 6) and (6, 1) both find a 1 x 6 part; any footprint when omitted.

None

Examples:

>>> [
...     part.id
...     for part in default_catalog().find(family="plate", size=(6, 1))
... ]
['3666']

search_colors

search_colors(query: str = '') -> list[Color]

Return colors whose id, name and type together contain every word of a query.

A query that is an RGB value, such as #F2CD37, returns the colors nearest to it instead, nearest first.

search_parts

search_parts(
    query: str, *, shapeless: bool = False
) -> list[CatalogPart]

Return the catalog parts whose text matches every word of a query.

A part's text is its id, alternate ids, name, category and family. A word matches when the text contains it. A size matches a whole size of the text only, in either order and either spelling: "1x2", "2x1" and "1 x 2" all find Plate 1 x 2 and not Plate 1 x 12. Parts without a shape appear only when shapeless is set.

Parts with a shape come first. DUPLO, Quatro, Primo and Modulex parts, which belong to other building systems, follow the rest unless the query names their system. Plain parts come before printed ones, and shorter names before longer ones.

CatalogFile

A catalog file: colors and parts, as bricky catalog import writes them.

dump

dump() -> bytes

Encode the file as JSON, one color or part per line, without defaults.

load_catalog

load_catalog(path: Path) -> Catalog

Read a catalog file in JSON or TOML.

bricky catalog import writes JSON, and the sample catalog is TOML.

Raises:

Type Description
BrickyError

If the file cannot be read or is not a valid catalog.

default_catalog cached

default_catalog() -> Catalog

Return the catalog at :func:catalog_path, loaded once per process.

catalog_path

catalog_path(settings: Settings | None = None) -> Path

Return the catalog file bricky uses.

The configured catalog comes first, then the catalog imported into bricky's data folder, then the sample shipped with bricky.

models

Catalog data types: catalog parts, shapes, generated parts, connectors and colors.

A catalog part pairs BrickLink's facts about a part (its id, name, category and the colors it comes in) with the shape bricky generates its geometry from, when bricky has one.

Part dataclass

Part(
    id: str,
    name: str,
    family: Family,
    size: Vector,
    solids: tuple[Solid, ...],
    connectors: tuple[Connector, ...],
    note: str = "",
    category: str | None = None,
)

A catalog part with its geometry in its local frame.

The local frame puts the bounding box's minimum corner at the origin, with x along the part's width, y along its length and z up. The body is a union of solids. Studs are connectors and stand outside the bounding box.

note class-attribute instance-attribute

note: str = ''

How the part sits when placed unrotated, for parts where it matters.

category class-attribute instance-attribute

category: str | None = None

BrickLink category, such as "Brick, Round".

stud_count property

stud_count: int

The number of studs on the part.

footprint property

footprint: tuple[int, int]

Width and length in studs, along the local x and y axes.

CatalogPart

A part as the catalog lists it: BrickLink's facts, and bricky's shape for it.

Color

A color, identified by its BrickLink color id.

ColorType

BrickLink color types, which change how a color looks.

Connector dataclass

Connector(
    kind: ConnectorKind, position: Vector, normal: Vector
)

A stud or an anti-stud, in its part's local frame or in world space.

position instance-attribute

position: Vector

The connector's center, on the part's face.

normal instance-attribute

normal: Vector

The outward unit axis.

transformed

transformed(pose: Pose) -> Connector

Return this connector placed by a pose.

ConnectorKind

The kinds of connector: studs and anti-studs.

STUD class-attribute instance-attribute

STUD = 'stud'

A stud, on a part's top or on one of its sides.

ANTI_STUD class-attribute instance-attribute

ANTI_STUD = 'anti_stud'

The socket under a part that a stud fits.

mate property

The kind that fits this one.

Family

The families: generators that convert a part's shape into its geometry.

BOXES class-attribute instance-attribute

BOXES = 'boxes'

Any part, as converted from LDraw: body as boxes, connectors one by one.

importing

Build a catalog: BrickLink for what exists, names and LDraw for shapes.

Each source supplies what it knows best:

  • BrickLink, the LEGO Group's marketplace, lists every part and color: ids, names, categories, and the colors each part comes in (:mod:bricky.catalog.bricklink).
  • Names: a part whose official name follows a pattern, such as "Slope 45 2 x 4", gets that family's shape, exact and oriented by bricky's conventions (:mod:bricky.catalog.names).
  • Printed parts take the shape of the part they are printed on.
  • LDraw, the LDraw.org Parts Library, gives every other part its shape, converted into boxes and connectors (:mod:bricky.catalog.ldraw).

An import without BrickLink's downloads takes the parts from LDraw alone, with LDraw's names, and the colors from the sample catalog. The import compares the two shapes of a part that has both a shape from its name and an LDraw file. The two agree for almost every part, which checks both.

The import reports every disagreement. Where LDraw's shape only lacks anti-studs that the name gives, the part keeps its name's shape: the conversion finds anti-studs by the room under a body on a 0.8 mm grid, which misses sockets under thin and curved bodies. Any other disagreement means the name hides a detail that changes the part, so the part takes LDraw's shape.

Coverage

What an import found: parts and colors, each shape's source, and the checks.

import_catalog

import_catalog(
    bricklink: Downloads | None,
    ldraw: Library | None,
    progress: Progress | None = None,
) -> tuple[CatalogFile, Coverage]

Build a catalog file and its coverage.

The import reads BrickLink's downloads, an LDraw library, or both.

Raises:

Type Description
BrickyError

If neither source is given.