Skip to content

Receiving bundle versions

Versions created with the new Speckle object model are bundle-only: instead of an object graph they carry a bundle reference (bundle.<projectId>.<modelId>.<versionId>) in Version.referencedObject, and their data lives in parquet artifacts served by the /api/v2 rail. Receiving one needs the bundle extra:

pip install "specklepy[bundle]"

operations.receive3

from specklepy.api import operations
from specklepy.api.credentials import get_default_account

account = get_default_account()
with operations.receive3(account, project_id, model_id, version_id) as model:
    for obj in model.objects_with("Constraints.Base Offset"):
        print(obj.application_id, obj["Constraints.Base Offset"], obj.level.name)

    wall = model.object_by_application_id("wall-1")
    for geometry in wall.geometries:          # placements already composed
        mesh = geometry.decode_mesh()
        material = geometry.effective_material

The returned Model owns the downloaded files until it is closed (leave the with block, or call close()); parsed data stays usable afterwards. Geometry is parsed from disk on first access — pass include_geometry=False to skip downloading it entirely.

Properties are read straight from the bundle's columnar storage: obj.properties is a read-only mapping of dotted paths ("Constraints.Base Offset"), obj["path"] resolves instance → type → root scalar, and model.objects_with(path) scans one column across the whole model.

Legacy operations.receive

operations.receive(obj_id, remote_transport, ...) detects a bundle reference and returns the same data projected onto the classic Collection / DataObject tree (Model.to_base()): objects keyed by applicationId, nested properties, renderMaterialProxies and instanceDefinitionProxies on the root, version = 4. It needs an authenticated ServerTransport for the reference's project.

API

Read façade over a received bundle (port of .NET Speckle.Sdk.Bundles.Model).

Model

Model(
    project_id: str,
    model_id: str,
    version_id: str,
    directory: str,
    files: Sequence[str],
    bundle: ArtefactBundle,
    geometry_downloaded: bool = True,
)

A received version. Owns its download directory until :meth:close; parsed data stays usable afterwards, geometry is parsed from disk on first access.

Source code in src/specklepy/bundle/model.py
def __init__(
    self,
    project_id: str,
    model_id: str,
    version_id: str,
    directory: str,
    files: Sequence[str],
    bundle: ArtefactBundle,
    geometry_downloaded: bool = True,
) -> None:
    self.project_id = project_id
    self.model_id = model_id
    self.version_id = version_id
    self.directory = directory
    self.files = list(files)
    self.bundle = bundle
    self._geometry_downloaded = geometry_downloaded
    self._closed = False
    if bundle.relations.unknown_rels:
        log.warning(
            "bundle %s/%s/%s uses relation ids this SDK does not know: %s",
            project_id,
            model_id,
            version_id,
            sorted(bundle.relations.unknown_rels),
        )

project_id instance-attribute

project_id = project_id

model_id instance-attribute

model_id = model_id

version_id instance-attribute

version_id = version_id

directory instance-attribute

directory = directory

files instance-attribute

files = list(files)

bundle instance-attribute

bundle = bundle

units property

units: str

properties property

properties: dict[str, object]

default_scene_view cached property

default_scene_view: list[SceneViewTier]

camera_views property

camera_views: list[CameraView]

property_set_definitions property

property_set_definitions

unknown_relations property

unknown_relations: set[int]

property_paths cached property

property_paths: list[str]

objects cached property

objects: list[ModelObject]

nodes cached property

nodes: dict[int, ModelNode]

levels cached property

levels: list[ModelLevel]

materials cached property

materials: list[ModelMaterial]

colors cached property

colors: list[ModelColor]

definitions cached property

definitions: list[ModelDefinition]

collections cached property

collections: list[ModelContainer]

is_geometry_loaded property

is_geometry_loaded: bool

geometries cached property

geometries: dict[int, Geometry]

index cached property

index: RelationIndex

close

close() -> None
Source code in src/specklepy/bundle/model.py
def close(self) -> None:
    if self._closed:
        return
    self._closed = True
    shutil.rmtree(self.directory, ignore_errors=True)

objects_with

objects_with(path: str) -> list[ModelObject]
Source code in src/specklepy/bundle/model.py
def objects_with(self, path: str) -> list[ModelObject]:
    keys = self.bundle.property_table.keys_with(PROPERTIES_PREFIX + path)
    return [o for k in keys if (o := self.object(k)) is not None]

object

object(k: int) -> ModelObject | None
Source code in src/specklepy/bundle/model.py
def object(self, k: int) -> ModelObject | None:
    return self._objects_by_k.get(k)

object_by_application_id

object_by_application_id(
    application_id: str,
) -> ModelObject | None
Source code in src/specklepy/bundle/model.py
def object_by_application_id(self, application_id: str) -> ModelObject | None:
    return self._objects_by_app_id.get(application_id)

node

node(k: int | None) -> ModelNode | None
Source code in src/specklepy/bundle/model.py
def node(self, k: int | None) -> ModelNode | None:
    return None if k is None else self.nodes.get(k)

to_base

to_base() -> Collection
Source code in src/specklepy/bundle/model.py
def to_base(self) -> Collection:
    from specklepy.bundle.base_projection import to_base

    return to_base(self)

ModelObject

ModelObject(model: Model, k: int, application_id: str)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, application_id: str) -> None:
    self._model = model
    self.k = k
    self.application_id = application_id

k instance-attribute

k = k

application_id instance-attribute

application_id = application_id

name property

name: str | None

properties property

properties: PropertyView

root_properties property

root_properties: PropertyView

type_properties property

type_properties: PropertyView

geometries cached property

geometries: list[ModelGeometry]

parent property

parent: ModelObject | None

children property

children: list[ModelObject]

host property

host: ModelObject | None

hosted property

hosted: list[ModelObject]

connected_to property

connected_to: list[ModelObject]

bounds_rooms property

bounds_rooms: list[ModelObject]

bounded_by property

bounded_by: list[ModelObject]

room property

room: ModelObject | None

contains property

contains: list[ModelObject]

assembly property

assembly: ModelObject | None

assembly_members property

assembly_members: list[ModelObject]

level property

level: ModelLevel | None

system property

system: ModelContainer | None

First system membership; see :attr:systems for all of them.

systems property

systems: list[ModelContainer]

collection property

collection: ModelContainer | None

groups property

collection_path cached property

collection_path: list[str]

scene_view_segments property

scene_view_segments: list[SceneViewSegment]

material property

material: ModelMaterial | None

color property

color: ModelColor | None

container_material property

container_material: ModelMaterial | None

container_color property

container_color: ModelColor | None

placements property

placements: list[ModelInstance]

definitions property

definitions: list[ModelDefinition]

definition property

definition: ModelDefinition | None

get_double

get_double(path: str) -> float | None
Source code in src/specklepy/bundle/model.py
def get_double(self, path: str) -> float | None:
    return self._typed("get_double", path)

get_string

get_string(path: str) -> str | None
Source code in src/specklepy/bundle/model.py
def get_string(self, path: str) -> str | None:
    return self._typed("get_string", path)

get_bool

get_bool(path: str) -> bool | None
Source code in src/specklepy/bundle/model.py
def get_bool(self, path: str) -> bool | None:
    return self._typed("get_bool", path)

ModelGeometry

ModelGeometry(
    model: Model,
    owner: ModelObject,
    k: int,
    geometry: Geometry,
    role: GeometryRole,
    ord: int,
    transform: Transform | None = None,
    instance_k: int | None = None,
)
Source code in src/specklepy/bundle/model.py
def __init__(
    self,
    model: Model,
    owner: ModelObject,
    k: int,
    geometry: Geometry,
    role: GeometryRole,
    ord: int,
    transform: Transform | None = None,
    instance_k: int | None = None,
) -> None:
    self._model = model
    self.owner = owner
    self.k = k
    self.content = geometry.content
    self.type = geometry.type
    self.is_sgeo = geometry.is_sgeo
    self.role = role
    self.ord = ord
    self.transform = None if transform is None else list(transform)
    self._instance_k = instance_k

owner instance-attribute

owner = owner

k instance-attribute

k = k

content instance-attribute

content = content

type instance-attribute

type = type

is_sgeo instance-attribute

is_sgeo = is_sgeo

role instance-attribute

role = role

ord instance-attribute

ord = ord

transform instance-attribute

transform = None if transform is None else list(transform)

placement property

placement: ModelInstance | None

material property

material: ModelMaterial | None

color property

color: ModelColor | None

effective_material property

effective_material: ModelMaterial | None

effective_color property

effective_color: ModelColor | None

decode

decode() -> Base
Source code in src/specklepy/bundle/model.py
def decode(self) -> Base:
    return sgeo.decode(self.content)

decode_mesh

decode_mesh() -> DecodedMesh
Source code in src/specklepy/bundle/model.py
def decode_mesh(self) -> sgeo.DecodedMesh:
    return sgeo.decode_mesh(self.content)

ModelNode

ModelNode(model: Model, k: int, node: Node)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, node: Node) -> None:
    self._model = model
    self._node = node
    self.k = k

k instance-attribute

k = k

kind property

kind: int

name property

name: str | None

units property

units: str | None

material property

material: ModelMaterial | None

color property

color: ModelColor | None

ModelContainer

ModelContainer(model: Model, k: int, node: Node)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, node: Node) -> None:
    self._model = model
    self._node = node
    self.k = k

subtype property

subtype: str | None

gh_topology property

gh_topology: str | None

parent property

parent: ModelContainer | None

path property

path: list[str]

objects property

objects: list[ModelObject]

children property

children: list[ModelContainer]

argb property

argb: int | None

ModelLevel

ModelLevel(model: Model, k: int, node: Node)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, node: Node) -> None:
    self._model = model
    self._node = node
    self.k = k

elevation property

elevation: float | None

objects property

objects: list[ModelObject]

ModelMaterial

ModelMaterial(model: Model, k: int, node: Node)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, node: Node) -> None:
    self._model = model
    self._node = node
    self.k = k

argb property

argb: int | None

opacity property

opacity: float | None

metalness property

metalness: float | None

roughness property

roughness: float | None

emissive property

emissive: int | None

ior property

ior: float | None

ModelColor

ModelColor(model: Model, k: int, node: Node)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, node: Node) -> None:
    self._model = model
    self._node = node
    self.k = k

argb property

argb: int

ModelDefinition

ModelDefinition(model: Model, k: int, node: Node)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, node: Node) -> None:
    self._model = model
    self._node = node
    self.k = k

placements property

placements: list[ModelInstance]

members property

members: list[ModelObject]

objects property

objects: list[ModelObject]

ModelInstance

ModelInstance(model: Model, k: int, node: Node)
Source code in src/specklepy/bundle/model.py
def __init__(self, model: Model, k: int, node: Node) -> None:
    self._model = model
    self._node = node
    self.k = k

transform cached property

transform: list[float] | None

definition property

definition: ModelDefinition | None