Skip to content

Sending bundle versions

BundleBuilder is the authoring API for the new Speckle object model: you describe objects, their properties and geometry, and the relationships between them, and operations.send3 publishes the result as a new version over the /api/v2 rail. Requires the bundle extra:

pip install "specklepy[bundle]"

Authoring

from specklepy.api import operations
from specklepy.api.credentials import get_default_account
from specklepy.bundle import BundleBuilder, Producer
from specklepy.objects.geometry import Mesh

b = BundleBuilder(Producer(slug="my-script", version="1.0"), units="m")

walls = b.get_or_add_container_path(["Level 1", "Walls"], subtype="Category")
concrete = b.get_or_add_material("concrete", "Concrete", argb=-8355712, roughness=0.8)
level = b.get_or_add_level("L1", "Level 1", elevation=0.0)

wall = b.get_or_add_object("wall-1").set_properties(
    {"Constraints": {"Base Offset": 0.5}},
    name="Basic Wall",
    speckle_type="Objects.Data.DataObject",
    source_type="Walls",
)
wall.collection = walls
wall.level = level
wall.add_geometry(Mesh(vertices=[...], faces=[...], units="m")).material = concrete

door = b.get_or_add_object("door-1").set_properties({"Width": 0.9}, name="Door")
door.collection = walls
door.host = wall
door.parent = wall

chair = b.get_or_add_definition(
    "def-chair", "Chair", lambda d: d.add_geometry(chair_mesh)
)
b.get_or_add_object("chair-1").place(chair, transform)  # 16 row-major doubles

result = operations.send3(get_default_account(), project_id, model_id, b)
print(result.version_id, result.bundle_reference)

Rules, mirroring the .NET BundleBuilder:

  • get_or_add_* interns a node by key: the same key returns the same handle and writes nothing; the same key with different attributes raises.
  • add_* appends a row every call (geometry, model properties, camera views).
  • Property setters and verbs (wall.level = …, door.host = …, place, connect_to) emit one edge each and cannot be retracted; assigning None before any edge is a no-op.
  • set_properties writes an object's rows once; objects can be referenced before they are described.
  • build() (called by send3) injects a default scene view grouping by collection when none was declared.

Definitions with members that own their properties use add_member, add_member_placement and add_existing_geometry; nested placements use place_nested.

operations.send3

send3(account, project_id, model_id, builder, options=None) takes an optional SendOptions (message, file_name, file_size_bytes, max_idle_timeout_seconds, keep_files). It creates the model ingestion (the server reserves the version id), builds and re-keys the bundle files to that id, uploads them, and returns a SendResult. The version becomes visible when the server finishes ingesting; poll client.version.get for it. The builder is finished by the call and cannot be reused. On failure the ingestion is marked failed and the error re-raised.

API

Authoring façade over :class:ObjectsArtifactPipeline (port of the .NET BundleBuilder).

get_or_add_* interns a node by key — the same key returns the same handle and writes nothing; a repeat with different attributes raises. add_* appends a row every call. Property setters and verbs emit one edge each, and an edge cannot be retracted.

BundleBuilder

BundleBuilder(
    producer: Producer,
    units: str,
    output_dir: str | None = None,
    base_name: str = DEFAULT_BASE_NAME,
)
Source code in src/specklepy/bundle/builder.py
def __init__(
    self,
    producer: Producer,
    units: str,
    output_dir: str | None = None,
    base_name: str = DEFAULT_BASE_NAME,
) -> None:
    if not units or not units.strip():
        raise ValueError("units is required")
    self.producer = producer
    self.units = units
    self.directory = output_dir or tempfile.mkdtemp(prefix="speckle-bundle-")
    self.base_name = base_name
    os.makedirs(self.directory, exist_ok=True)
    self.pipeline = ObjectsArtifactPipeline(self.directory, base_name, producer)
    self._objects: dict[str, BundleObject] = {}
    self._containers: dict[str, BundleContainer] = {}
    self._semantic_containers: dict[str, BundleContainer] = {}
    self._definitions: dict[str, BundleDefinition] = {}
    self._materials: dict[str, BundleMaterial] = {}
    self._colors: dict[int, BundleColor] = {}
    self._levels: dict[str, BundleLevel] = {}
    self._geometries: dict[str, BundleGeometry] = {}
    self._scene_views: list[SceneView] = []
    self._built = False

producer instance-attribute

producer = producer

units instance-attribute

units = units

directory instance-attribute

directory = output_dir or mkdtemp(prefix='speckle-bundle-')

base_name instance-attribute

base_name = base_name

pipeline instance-attribute

pipeline = ObjectsArtifactPipeline(
    directory, base_name, producer
)

objects property

objects: list[BundleObject]

get_or_add_container_path

get_or_add_container_path(
    path: Sequence[str],
    subtype: str = "Collection",
    gh_topology: str | None = None,
) -> BundleContainer
Source code in src/specklepy/bundle/builder.py
def get_or_add_container_path(
    self,
    path: Sequence[str],
    subtype: str = "Collection",
    gh_topology: str | None = None,
) -> BundleContainer:
    if not path:
        raise ValueError("A collection path needs at least one segment.")
    parent: BundleContainer | None = None
    key = ""
    for i, segment in enumerate(path):
        key = segment if not key else f"{key}/{segment}"
        leaf = i == len(path) - 1
        parent = self.get_or_add_container(
            key, segment, parent, subtype, gh_topology if leaf else None
        )
    assert parent is not None
    return parent

get_or_add_container

get_or_add_container(
    key: str,
    name: str | None,
    parent: BundleContainer | None,
    subtype: str,
    gh_topology: str | None = None,
) -> BundleContainer
Source code in src/specklepy/bundle/builder.py
def get_or_add_container(
    self,
    key: str,
    name: str | None,
    parent: BundleContainer | None,
    subtype: str,
    gh_topology: str | None = None,
) -> BundleContainer:
    existing = self._containers.get(key)
    if existing is not None:
        _same(key, existing.name, name, "name")
        _same(key, existing.subtype, subtype, "subtype")
        _same(
            key,
            existing.parent.key if existing.parent else None,
            parent.key if parent else None,
            "parent",
        )
        return existing
    k = self.pipeline.add_collection(
        key, name, parent.k if parent else None, subtype, gh_topology=gh_topology
    )
    container = BundleContainer(self, k, key, name, subtype, parent)
    self._containers[key] = container
    return container

get_or_add_semantic_container

get_or_add_semantic_container(
    key: str,
    name: str | None,
    parent: BundleContainer | None,
    subtype: str,
) -> BundleContainer

Semantic container (MEP System / Network / Group …) — the cont: namespace, distinct from the scene tree.

Source code in src/specklepy/bundle/builder.py
def get_or_add_semantic_container(
    self,
    key: str,
    name: str | None,
    parent: BundleContainer | None,
    subtype: str,
) -> BundleContainer:
    """Semantic container (MEP System / Network / Group …) — the ``cont:``
    namespace, distinct from the scene tree."""
    existing = self._semantic_containers.get(key)
    if existing is not None:
        _same(key, existing.name, name, "name")
        _same(key, existing.subtype, subtype, "subtype")
        _same(
            key,
            existing.parent.key if existing.parent else None,
            parent.key if parent else None,
            "parent",
        )
        return existing
    k = self.pipeline.add_container(
        key, name, parent.k if parent else None, subtype
    )
    container = BundleContainer(self, k, key, name, subtype, parent)
    self._semantic_containers[key] = container
    return container

get_or_add_object

get_or_add_object(application_id: str) -> BundleObject
Source code in src/specklepy/bundle/builder.py
def get_or_add_object(self, application_id: str) -> BundleObject:
    obj = self._objects.get(application_id)
    if obj is None:
        obj = BundleObject(
            self, self.pipeline.intern_object(application_id), application_id
        )
        self._objects[application_id] = obj
    return obj

try_get_object

try_get_object(application_id: str) -> BundleObject | None
Source code in src/specklepy/bundle/builder.py
def try_get_object(self, application_id: str) -> BundleObject | None:
    return self._objects.get(application_id)

try_get_geometry

try_get_geometry(
    geometry_key: str,
) -> BundleGeometry | None
Source code in src/specklepy/bundle/builder.py
def try_get_geometry(self, geometry_key: str) -> BundleGeometry | None:
    return self._geometries.get(geometry_key)

try_get_definition

try_get_definition(key: str) -> BundleDefinition | None
Source code in src/specklepy/bundle/builder.py
def try_get_definition(self, key: str) -> BundleDefinition | None:
    return self._definitions.get(key)

get_or_add_material

get_or_add_material(
    key: str,
    name: str | None,
    argb: int,
    opacity: float = 1.0,
    metalness: float = 0.0,
    roughness: float = 1.0,
    emissive: int | None = None,
    ior: float | None = None,
) -> BundleMaterial
Source code in src/specklepy/bundle/builder.py
def get_or_add_material(
    self,
    key: str,
    name: str | None,
    argb: int,
    opacity: float = 1.0,
    metalness: float = 0.0,
    roughness: float = 1.0,
    emissive: int | None = None,
    ior: float | None = None,
) -> BundleMaterial:
    existing = self._materials.get(key)
    if existing is not None:
        _same(key, existing.name, name, "name")
        _same(key, existing.argb, argb, "argb")
        return existing
    k = self.pipeline.add_material(
        key,
        argb,
        opacity,
        metalness,
        roughness,
        name=name,
        emissive=emissive,
        ior=ior,
    )
    material = BundleMaterial(self, k, key, name, argb)
    self._materials[key] = material
    return material

get_or_add_color

get_or_add_color(argb: int) -> BundleColor
Source code in src/specklepy/bundle/builder.py
def get_or_add_color(self, argb: int) -> BundleColor:
    color = self._colors.get(argb)
    if color is None:
        color = BundleColor(self, self.pipeline.add_color(argb), argb)
        self._colors[argb] = color
    return color

get_or_add_level

get_or_add_level(
    key: str, name: str | None, elevation: float
) -> BundleLevel
Source code in src/specklepy/bundle/builder.py
def get_or_add_level(
    self, key: str, name: str | None, elevation: float
) -> BundleLevel:
    existing = self._levels.get(key)
    if existing is not None:
        _same(key, existing.name, name, "name")
        _same(key, existing.elevation, elevation, "elevation")
        return existing
    level = BundleLevel(
        self, self.pipeline.add_level(key, name, elevation), key, name, elevation
    )
    self._levels[key] = level
    return level

get_or_add_definition

get_or_add_definition(
    key: str,
    name: str | None,
    populate: Callable[[BundleDefinition], None]
    | None = None,
) -> BundleDefinition
Source code in src/specklepy/bundle/builder.py
def get_or_add_definition(
    self,
    key: str,
    name: str | None,
    populate: Callable[[BundleDefinition], None] | None = None,
) -> BundleDefinition:
    existing = self._definitions.get(key)
    if existing is not None:
        if name is not None:
            _same(key, existing.name, name, "name")
        return existing
    definition = BundleDefinition(
        self, self.pipeline.add_definition(key, name), key, name
    )
    self._definitions[key] = definition
    if populate is not None:
        populate(definition)
    return definition

add_model_property

add_model_property(
    path: str, value: Any, unit: str | None = None
) -> None
Source code in src/specklepy/bundle/builder.py
def add_model_property(
    self, path: str, value: Any, unit: str | None = None
) -> None:
    self.pipeline.add_model_property(path, value, unit)

add_model_placement

add_model_placement(
    default: str,
    transform: Sequence[float],
    units: str | None,
    applied_to_geometry: bool,
    *,
    source: str | None = None,
    options: Mapping[str, Sequence[float]] | None = None,
) -> None
Source code in src/specklepy/bundle/builder.py
def add_model_placement(
    self,
    default: str,
    transform: Sequence[float],
    units: str | None,
    applied_to_geometry: bool,
    *,
    source: str | None = None,
    options: Mapping[str, Sequence[float]] | None = None,
) -> None:
    self.pipeline.add_model_placement(
        default,
        transform,
        units,
        applied_to_geometry,
        source=source,
        options=options,
    )

add_property_set_definition

add_property_set_definition(
    *args: Any, **kwargs: Any
) -> None
Source code in src/specklepy/bundle/builder.py
def add_property_set_definition(self, *args: Any, **kwargs: Any) -> None:
    self.pipeline.add_property_set_definition(*args, **kwargs)

add_camera_view

add_camera_view(view: CameraView) -> None
Source code in src/specklepy/bundle/builder.py
def add_camera_view(self, view: CameraView) -> None:
    self.pipeline.add_camera_view(view)

scene_view

scene_view(
    name: str, is_default: bool, *tiers: SceneViewKey
) -> None
Source code in src/specklepy/bundle/builder.py
def scene_view(self, name: str, is_default: bool, *tiers: SceneViewKey) -> None:
    view = SceneView(len(self._scene_views), name, is_default, list(tiers))
    self._scene_views.append(view)
    self.pipeline.add_scene_view(view)

build

build() -> BundleFiles
Source code in src/specklepy/bundle/builder.py
def build(self) -> BundleFiles:
    if self._built:
        raise RuntimeError("build() has already been called on this BundleBuilder.")
    self._built = True
    if not self._scene_views:
        self.scene_view("Default", True, SceneViewKey.rel(Rel.IN_COLLECTION))
    self.pipeline.complete()
    prefix = self.base_name + "."
    files = sorted(
        os.path.join(self.directory, f)
        for f in os.listdir(self.directory)
        if f.startswith(prefix) and f.endswith(".parquet")
    )
    return BundleFiles(self.directory, self.base_name, files, len(self._objects))

BundleFiles dataclass

BundleFiles(
    directory: str,
    base_name: str,
    files: list[str],
    object_count: int,
)

directory instance-attribute

directory: str

base_name instance-attribute

base_name: str

files instance-attribute

files: list[str]

object_count instance-attribute

object_count: int

by_name property

by_name: dict[str, str]

rename_to

rename_to(version_id: str) -> BundleFiles
Source code in src/specklepy/bundle/builder.py
def rename_to(self, version_id: str) -> BundleFiles:
    if version_id == self.base_name:
        return self
    renamed = []
    for path in self.files:
        name = os.path.basename(path)
        target = os.path.join(
            self.directory, version_id + name[len(self.base_name) :]
        )
        os.replace(path, target)
        renamed.append(target)
    return BundleFiles(
        self.directory, version_id, sorted(renamed), self.object_count
    )

BundleObject

BundleObject(
    builder: BundleBuilder, k: int, application_id: str
)
Source code in src/specklepy/bundle/builder.py
def __init__(self, builder: BundleBuilder, k: int, application_id: str) -> None:
    self._builder = builder
    self.k = k
    self.application_id = application_id
    self.name: str | None = None
    self.properties_written = False
    self.geometries: list[BundleGeometry] = []
    self.assembly: BundleObject | None = None
    self._parent: BundleObject | None = None
    self._collection: BundleContainer | None = None
    self._model: BundleContainer | None = None
    self._level: BundleLevel | None = None
    self._material: BundleMaterial | None = None
    self._color: BundleColor | None = None
    self._host: BundleObject | None = None
    self._room: BundleObject | None = None
    self._display_ord = 0
    self._solid_ord = 0
    self._placement_ord = 0
    self._child_ord = 0

k instance-attribute

k = k

application_id instance-attribute

application_id = application_id

name instance-attribute

name: str | None = None

properties_written instance-attribute

properties_written = False

geometries instance-attribute

geometries: list[BundleGeometry] = []

assembly instance-attribute

assembly: BundleObject | None = None

collection property writable

collection: BundleContainer | None

model property writable

model: BundleContainer | None

level property writable

level: BundleLevel | None

material property writable

material: BundleMaterial | None

color property writable

color: BundleColor | None

host property writable

host: BundleObject | None

room property writable

room: BundleObject | None

parent property writable

parent: BundleObject | None

set_properties

set_properties(
    properties: Mapping[str, Any] | None = None,
    *,
    name: str | None = None,
    speckle_type: str | None = None,
    source_type: str | None = None,
    units: str | None = None,
    type_key: str | None = None,
    root_scalars: Iterable[tuple[str, Any]] | None = None,
) -> BundleObject
Source code in src/specklepy/bundle/builder.py
def set_properties(
    self,
    properties: Mapping[str, Any] | None = None,
    *,
    name: str | None = None,
    speckle_type: str | None = None,
    source_type: str | None = None,
    units: str | None = None,
    type_key: str | None = None,
    root_scalars: Iterable[tuple[str, Any]] | None = None,
) -> BundleObject:
    if self.properties_written:
        raise RuntimeError(
            f"Properties for '{self.application_id}' were already written; an "
            "object's properties are written once."
        )
    self._builder._write_properties(
        self,
        properties,
        name,
        speckle_type,
        source_type,
        units,
        type_key,
        root_scalars,
    )
    self.properties_written = True
    self.name = name
    return self

add_geometry

add_geometry(
    geometry: Any, geometry_key: str | None = None
) -> BundleGeometry
Source code in src/specklepy/bundle/builder.py
def add_geometry(
    self, geometry: Any, geometry_key: str | None = None
) -> BundleGeometry:
    ord = self._display_ord
    self._display_ord += 1
    key = geometry_key or f"{self.application_id}:g{ord}"
    k = self._builder.pipeline.add_geometry(key, geometry)
    self._builder.pipeline.display(self.k, k, ord)
    return self._register(key, BundleGeometry(self._builder, k, ord))

add_raw_geometry

add_raw_geometry(
    content: bytes,
    type: str,
    geometry_key: str | None = None,
) -> BundleGeometry
Source code in src/specklepy/bundle/builder.py
def add_raw_geometry(
    self, content: bytes, type: str, geometry_key: str | None = None
) -> BundleGeometry:
    ord = self._solid_ord
    self._solid_ord += 1
    key = geometry_key or f"{self.application_id}:raw{ord}"
    k = self._builder.pipeline.add_raw_geometry(key, content, type)
    self._builder.pipeline.solid(self.k, k, ord)
    return self._register(key, BundleGeometry(self._builder, k, ord))

place

place(
    definition: BundleDefinition,
    transform: Sequence[float],
    units: str | None = None,
    key: str | None = None,
) -> BundleInstance
Source code in src/specklepy/bundle/builder.py
def place(
    self,
    definition: BundleDefinition,
    transform: Sequence[float],
    units: str | None = None,
    key: str | None = None,
) -> BundleInstance:
    ord = self._placement_ord
    self._placement_ord += 1
    k = self._builder.pipeline.add_instance(
        key or f"{self.application_id}:inst{ord}",
        definition.k,
        transform,
        units or self._builder.units,
    )
    self._builder.pipeline.display_instance(self.k, k, ord)
    return BundleInstance(self._builder, k, definition)

add_child

add_child(
    child: BundleObject, ord: int | None = None
) -> None
Source code in src/specklepy/bundle/builder.py
def add_child(self, child: BundleObject, ord: int | None = None) -> None:
    if child._parent is self:
        return
    if child._parent is not None:
        raise RuntimeError(
            f"Object '{child.application_id}' already has parent "
            f"'{child._parent.application_id}'; a bundle edge cannot be retracted"
        )
    o = self._child_ord if ord is None else ord
    self._child_ord = max(self._child_ord, o + 1)
    child._parent = self
    self._builder.pipeline.subelement(self.k, child.k, o)

add_assembly_member

add_assembly_member(
    member: BundleObject, ord: int | None = None
) -> None
Source code in src/specklepy/bundle/builder.py
def add_assembly_member(self, member: BundleObject, ord: int | None = None) -> None:
    if member.assembly is self:
        return
    if member.assembly is not None:
        raise RuntimeError(
            f"Object '{member.application_id}' is already in assembly "
            f"'{member.assembly.application_id}'; a bundle edge cannot be "
            "retracted."
        )
    o = self._assembly_member_ord if ord is None else ord
    self._assembly_member_ord = max(self._assembly_member_ord, o + 1)
    member.assembly = self
    self._builder.pipeline.in_assembly(member.k, self.k, o)

add_to_group

add_to_group(group: BundleContainer, ord: int = 0) -> None
Source code in src/specklepy/bundle/builder.py
def add_to_group(self, group: BundleContainer, ord: int = 0) -> None:
    self._builder.pipeline.in_group(self.k, group.k, ord)

add_to_system

add_to_system(
    system: BundleContainer, ord: int = 0
) -> None
Source code in src/specklepy/bundle/builder.py
def add_to_system(self, system: BundleContainer, ord: int = 0) -> None:
    self._builder.pipeline.in_system(self.k, system.k, ord)

connect_to

connect_to(other: BundleObject, scope: int = 0) -> None
Source code in src/specklepy/bundle/builder.py
def connect_to(self, other: BundleObject, scope: int = 0) -> None:
    self._builder.pipeline.connects_to(self.k, other.k, scope)

bounds

bounds(room: BundleObject, ord: int = 0) -> None
Source code in src/specklepy/bundle/builder.py
def bounds(self, room: BundleObject, ord: int = 0) -> None:
    self._builder.pipeline.bounds(self.k, room.k, ord)

BundleDefinition

BundleDefinition(
    builder: BundleBuilder,
    k: int,
    key: str,
    name: str | None,
)

DEFINES / DEFINES_INSTANCE / DEFINES_MEMBER share one member-ordinal space; the (definition, ordinal) pair is what joins a member's object row to its geometry.

Source code in src/specklepy/bundle/builder.py
def __init__(
    self, builder: BundleBuilder, k: int, key: str, name: str | None
) -> None:
    super().__init__(builder, k)
    self.key = key
    self.name = name
    self._geometry_ord = 0
    self._member_ord = 0

key instance-attribute

key = key

name instance-attribute

name = name

add_geometry

add_geometry(
    geometry: Any,
    geometry_key: str | None = None,
    member_ord: int | None = None,
) -> BundleGeometry
Source code in src/specklepy/bundle/builder.py
def add_geometry(
    self,
    geometry: Any,
    geometry_key: str | None = None,
    member_ord: int | None = None,
) -> BundleGeometry:
    ord = member_ord if member_ord is not None else self._take_geometry_ord()
    k = self._builder.pipeline.add_geometry(
        geometry_key or f"{self.key}:g{ord}", geometry
    )
    self._builder.pipeline.defines(self.k, k, ord)
    return BundleGeometry(self._builder, k, ord)

add_raw_geometry

add_raw_geometry(
    content: bytes,
    type: str,
    geometry_key: str | None = None,
    member_ord: int | None = None,
) -> BundleGeometry
Source code in src/specklepy/bundle/builder.py
def add_raw_geometry(
    self,
    content: bytes,
    type: str,
    geometry_key: str | None = None,
    member_ord: int | None = None,
) -> BundleGeometry:
    ord = member_ord if member_ord is not None else self._take_geometry_ord()
    k = self._builder.pipeline.add_raw_geometry(
        geometry_key or f"{self.key}:raw{ord}", content, type
    )
    self._builder.pipeline.defines(self.k, k, ord)
    return BundleGeometry(self._builder, k, ord)

place_nested

place_nested(
    definition: BundleDefinition,
    transform: Sequence[float],
    units: str | None = None,
    key: str | None = None,
) -> BundleInstance
Source code in src/specklepy/bundle/builder.py
def place_nested(
    self,
    definition: BundleDefinition,
    transform: Sequence[float],
    units: str | None = None,
    key: str | None = None,
) -> BundleInstance:
    ord = self._take_geometry_ord()
    k = self._builder.pipeline.add_instance(
        key or f"{self.key}:inst{ord}", definition.k, transform, units
    )
    self._builder.pipeline.defines_instance(self.k, k, ord)
    return BundleInstance(self._builder, k, definition)

add_member

add_member(
    member: BundleObject,
    geometry: Iterable[Any],
    member_ord: int | None = None,
) -> list[BundleGeometry]
Source code in src/specklepy/bundle/builder.py
def add_member(
    self,
    member: BundleObject,
    geometry: Iterable[Any],
    member_ord: int | None = None,
) -> list[BundleGeometry]:
    ord = member_ord if member_ord is not None else self._next_member_ordinal()
    self._bump(ord)
    pipeline = self._builder.pipeline
    pipeline.defines_member(self.k, member.k, ord)
    result: list[BundleGeometry] = []
    for i, g in enumerate(geometry):
        key = f"{member.application_id}:g{i}"
        k = pipeline.add_geometry(key, g)
        pipeline.defines(self.k, k, ord)
        handle = BundleGeometry(self._builder, k, ord)
        self._builder._geometries[key] = handle
        result.append(handle)
    return result

add_member_raw_geometry

add_member_raw_geometry(
    member: BundleObject,
    content: bytes,
    type: str,
    member_ord: int,
) -> BundleGeometry
Source code in src/specklepy/bundle/builder.py
def add_member_raw_geometry(
    self, member: BundleObject, content: bytes, type: str, member_ord: int
) -> BundleGeometry:
    key = f"{member.application_id}:raw{member_ord}"
    k = self._builder.pipeline.add_raw_geometry(key, content, type)
    self._builder.pipeline.defines(self.k, k, member_ord)
    handle = BundleGeometry(self._builder, k, member_ord)
    self._builder._geometries[key] = handle
    return handle

add_member_placement

add_member_placement(
    member: BundleObject,
    nested: BundleDefinition,
    transform: Sequence[float],
    units: str | None = None,
    member_ord: int | None = None,
) -> BundleInstance
Source code in src/specklepy/bundle/builder.py
def add_member_placement(
    self,
    member: BundleObject,
    nested: BundleDefinition,
    transform: Sequence[float],
    units: str | None = None,
    member_ord: int | None = None,
) -> BundleInstance:
    ord = member_ord if member_ord is not None else self._next_member_ordinal()
    self._bump(ord)
    pipeline = self._builder.pipeline
    k = pipeline.add_instance(
        member.application_id, nested.k, transform, units or self._builder.units
    )
    pipeline.defines_instance(self.k, k, ord)
    pipeline.defines_member(self.k, member.k, ord)
    pipeline.places(member.k, k)
    return BundleInstance(self._builder, k, nested)

add_existing_geometry

add_existing_geometry(
    geometry: BundleGeometry, member_ord: int | None = None
) -> None
Source code in src/specklepy/bundle/builder.py
def add_existing_geometry(
    self, geometry: BundleGeometry, member_ord: int | None = None
) -> None:
    ord = member_ord if member_ord is not None else self._next_member_ordinal()
    self._bump(ord)
    self._builder.pipeline.defines(self.k, geometry.k, ord)

BundleGeometry

BundleGeometry(builder: BundleBuilder, k: int, ord: int)
Source code in src/specklepy/bundle/builder.py
def __init__(self, builder: BundleBuilder, k: int, ord: int) -> None:
    self._builder = builder
    self.k = k
    self.ord = ord
    self._material: BundleMaterial | None = None
    self._color: BundleColor | None = None

k instance-attribute

k = k

ord instance-attribute

ord = ord

material property writable

material: BundleMaterial | None

color property writable

color: BundleColor | None

BundleContainer

BundleContainer(
    builder: BundleBuilder,
    k: int,
    key: str,
    name: str | None,
    subtype: str,
    parent: BundleContainer | None,
)
Source code in src/specklepy/bundle/builder.py
def __init__(
    self,
    builder: BundleBuilder,
    k: int,
    key: str,
    name: str | None,
    subtype: str,
    parent: BundleContainer | None,
) -> None:
    super().__init__(builder, k)
    self.key = key
    self.name = name
    self.subtype = subtype
    self.parent = parent

key instance-attribute

key = key

name instance-attribute

name = name

subtype instance-attribute

subtype = subtype

parent instance-attribute

parent = parent

BundleLevel

BundleLevel(
    builder: BundleBuilder,
    k: int,
    key: str,
    name: str | None,
    elevation: float,
)
Source code in src/specklepy/bundle/builder.py
def __init__(
    self,
    builder: BundleBuilder,
    k: int,
    key: str,
    name: str | None,
    elevation: float,
) -> None:
    super().__init__(builder, k)
    self.key = key
    self.name = name
    self.elevation = elevation

key instance-attribute

key = key

name instance-attribute

name = name

elevation instance-attribute

elevation = elevation

BundleMaterial

BundleMaterial(
    builder: BundleBuilder,
    k: int,
    key: str,
    name: str | None,
    argb: int,
)
Source code in src/specklepy/bundle/builder.py
def __init__(
    self, builder: BundleBuilder, k: int, key: str, name: str | None, argb: int
) -> None:
    super().__init__(builder, k)
    self.key = key
    self.name = name
    self.argb = argb

key instance-attribute

key = key

name instance-attribute

name = name

argb instance-attribute

argb = argb

BundleColor

BundleColor(builder: BundleBuilder, k: int, argb: int)
Source code in src/specklepy/bundle/builder.py
def __init__(self, builder: BundleBuilder, k: int, argb: int) -> None:
    super().__init__(builder, k)
    self.argb = argb

argb instance-attribute

argb = argb

BundleInstance

BundleInstance(
    builder: BundleBuilder,
    k: int,
    definition: BundleDefinition,
)
Source code in src/specklepy/bundle/builder.py
def __init__(
    self, builder: BundleBuilder, k: int, definition: BundleDefinition
) -> None:
    super().__init__(builder, k)
    self.definition = definition

definition instance-attribute

definition = definition

message class-attribute instance-attribute

message: str | None = None

file_name class-attribute instance-attribute

file_name: str | None = None

file_size_bytes class-attribute instance-attribute

file_size_bytes: int | None = None

max_idle_timeout_seconds class-attribute instance-attribute

max_idle_timeout_seconds: int = 600

keep_files class-attribute instance-attribute

keep_files: bool = False

project_id instance-attribute

project_id: str

model_id instance-attribute

model_id: str

version_id instance-attribute

version_id: str

ingestion_id instance-attribute

ingestion_id: str

object_count instance-attribute

object_count: int

bundle_reference property

bundle_reference: str