Skip to content

Base

Base class for all Speckle objects.

The base object class is the foundation of all data being transferred with Speckle. Any custom data structure that you want to transfer via Speckle should inherit from it.

Objects in Speckle are immutable for storage purposes. When any property changes, the object gets a new identity (hash). This hash is stored in the id property after serialization.

Attributes:

Name Type Description
id Union[str, None]

Unique identifier (hash) for the object. This is typically

applicationId Union[str, None]

Optional identifier for the application that created this object, can store the host application's native object ID.

Example
from specklepy.objects.base import Base
obj = Base(id="some-id", applicationId="my-app")
obj["custom_prop"] = 42  # Add a dynamic property
obj["@detached_prop"] = another_object  # Add a detached property

id class-attribute instance-attribute

id: Union[str, None] = None

applicationId class-attribute instance-attribute

applicationId: Union[str, None] = None

of_type classmethod

of_type(speckle_type: str, **kwargs) -> Base

Get a plain Base object with a specified speckle_type.

The speckle_type is protected and cannot be overwritten on a class instance. This is to prevent problems with receiving in other platforms or connectors. However, if you really need a base with a different type, here is a helper to do that for you.

This is used in the deserialisation of unknown types so their speckle_type can be preserved.

Source code in src/specklepy/objects/base.py
@classmethod
def of_type(cls, speckle_type: str, **kwargs) -> "Base":
    """
    Get a plain Base object with a specified speckle_type.

    The speckle_type is protected and cannot be overwritten on a class instance.
    This is to prevent problems with receiving in other platforms or connectors.
    However, if you really need a base with a different type, here is a helper
    to do that for you.

    This is used in the deserialisation of unknown types so their speckle_type
    can be preserved.
    """
    b = cls(**kwargs)
    b.__dict__.update(speckle_type=speckle_type)
    return b

update_forward_refs classmethod

update_forward_refs() -> None

Attempts to populate the internal defined types dict for type checking sometime after defining the class. This is already done when defining the class, but can be called again if references to undefined types were included.

See objects.geometry for an example of how this is used with the Brep class definitions.

Source code in src/specklepy/objects/base.py
@classmethod
def update_forward_refs(cls) -> None:
    """
    Attempts to populate the internal defined types dict for type checking
    sometime after defining the class.
    This is already done when defining the class, but can be called
    again if references to undefined types were
    included.

    See `objects.geometry` for an example of how this is used with
    the Brep class definitions.
    """
    try:
        cls._attr_types = get_type_hints(cls)
    except Exception as e:
        warn(
            f"Could not update forward refs for class {cls.__name__}: {e}",
            stacklevel=2,
        )

validate_prop_name classmethod

validate_prop_name(name: str) -> None

Validator for dynamic attribute names.

Source code in src/specklepy/objects/base.py
@classmethod
def validate_prop_name(cls, name: str) -> None:
    """Validator for dynamic attribute names."""
    if name in {"", "@"}:
        raise ValueError("Invalid Name: Base member names cannot be empty strings")
    if name.startswith("@@"):
        raise ValueError(
            "Invalid Name: Base member names cannot start with more than one '@'",
        )
    if "." in name or "/" in name:
        raise ValueError(
            "Invalid Name: Base member names cannot contain characters '.' or '/'",
        )

add_chunkable_attrs

add_chunkable_attrs(**kwargs: int) -> None

Mark defined attributes as chunkable for serialisation

Source code in src/specklepy/objects/base.py
def add_chunkable_attrs(self, **kwargs: int) -> None:
    """
    Mark defined attributes as chunkable for serialisation

    Arguments:
        kwargs {int} -- the name of the attribute as the keyword
        and the chunk size as the arg
    """
    chunkable = {k: v for k, v in kwargs.items() if isinstance(v, int)}
    self._chunkable = dict(self._chunkable, **chunkable)

add_detachable_attrs

add_detachable_attrs(names: Set[str]) -> None

Mark defined attributes as detachable for serialisation

Source code in src/specklepy/objects/base.py
def add_detachable_attrs(self, names: Set[str]) -> None:
    """
    Mark defined attributes as detachable for serialisation

    Arguments:
        names {Set[str]} -- the names of the attributes to detach as a set of string
    """
    self._detachable = self._detachable.union(names)

get_member_names

get_member_names() -> List[str]

Get all of the property names on this object, dynamic or not

Source code in src/specklepy/objects/base.py
def get_member_names(self) -> List[str]:
    """Get all of the property names on this object, dynamic or not"""
    attr_dir = list(set(dir(self)) - REMOVE_FROM_DIR)
    return [
        name
        for name in attr_dir
        if not name.startswith("_") and not callable(getattr(self, name))
    ]

get_serializable_attributes

get_serializable_attributes() -> List[str]

Get the attributes that should be serialized

Source code in src/specklepy/objects/base.py
def get_serializable_attributes(self) -> List[str]:
    """Get the attributes that should be serialized"""
    return sorted(list(set(self.get_member_names()) - self._serialize_ignore))

get_typed_member_names

get_typed_member_names() -> List[str]

Get all of the names of the defined (typed) properties of this object

Source code in src/specklepy/objects/base.py
def get_typed_member_names(self) -> List[str]:
    """Get all of the names of the defined (typed) properties of this object"""
    return list(self._attr_types.keys())

get_dynamic_member_names

get_dynamic_member_names() -> List[str]

Get all of the names of the dynamic properties of this object

Source code in src/specklepy/objects/base.py
def get_dynamic_member_names(self) -> List[str]:
    """Get all of the names of the dynamic properties of this object"""
    return list(set(self.__dict__.keys()) - set(self._attr_types.keys()))

get_children_count

get_children_count() -> int

Get the total count of children Base objects

Source code in src/specklepy/objects/base.py
def get_children_count(self) -> int:
    """Get the total count of children Base objects"""
    parsed = []
    return 1 + self._count_descendants(self, parsed)

get_id

get_id(decompose: bool = False) -> str

Gets the id (a unique hash) of this object. ⚠️ This method fully serializes the object which, in the case of large objects (with many sub-objects), has a tangible cost. Avoid using it!

Note: the hash of a decomposed object differs from that of a non-decomposed object

Returns:

Type Description
str

str -- the hash (id) of the fully serialized object

Source code in src/specklepy/objects/base.py
def get_id(self, decompose: bool = False) -> str:
    """
    Gets the id (a unique hash) of this object.
    ⚠️ This method fully serializes the object which,
    in the case of large objects (with many sub-objects), has a tangible cost.
    Avoid using it!

    Note: the hash of a decomposed object differs from that of a
    non-decomposed object

    Arguments:
        decompose {bool} -- if True, will decompose the object in
        the process of hashing it

    Returns:
        str -- the hash (id) of the fully serialized object
    """
    from specklepy.serialization.base_object_serializer import BaseObjectSerializer

    serializer = BaseObjectSerializer()
    if decompose:
        serializer.write_transports = [MemoryTransport()]
    return serializer.traverse_base(self)[0]

data class-attribute instance-attribute

data: List[Any] = field(default_factory=list)