diff --git a/src/specklepy/objects_v2/graph_traversal/commit_object_builder.py b/src/specklepy/objects/graph_traversal/commit_object_builder.py
similarity index 100%
rename from src/specklepy/objects_v2/graph_traversal/commit_object_builder.py
rename to src/specklepy/objects/graph_traversal/commit_object_builder.py
diff --git a/src/specklepy/objects_v2/graph_traversal/traversal.py b/src/specklepy/objects/graph_traversal/traversal.py
similarity index 100%
rename from src/specklepy/objects_v2/graph_traversal/traversal.py
rename to src/specklepy/objects/graph_traversal/traversal.py
diff --git a/src/specklepy/objects/tests/asdasd.py b/src/specklepy/objects/tests/asdasd.py
new file mode 100644
index 00000000..13e3089e
--- /dev/null
+++ b/src/specklepy/objects/tests/asdasd.py
@@ -0,0 +1,9 @@
+from specklepy.objects.geometry import Point, Line
+from specklepy.objects.models.units import Units
+
+p_1 = Point(x=0, y=0, z=0, units=Units.m)
+p_2 = Point(x=3, y=0, z=0, units=Units.m)
+
+line = Line(start=p_1, end=p_2, units=Units.m)
+line.length = line.calculate_length()
+print(line.length)
diff --git a/src/specklepy/objects_v2/GIS/CRS.py b/src/specklepy/objects_v2/GIS/CRS.py
deleted file mode 100644
index 2527fe55..00000000
--- a/src/specklepy/objects_v2/GIS/CRS.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from typing import Optional
-
-from specklepy.objects.base import Base
-
-
-class CRS(Base, speckle_type="Objects.GIS.CRS"):
-    """A Coordinate Reference System stored in wkt format"""
-
-    name: Optional[str] = None
-    authority_id: Optional[str] = None
-    wkt: Optional[str] = None
-    units_native: Optional[str] = None
-    offset_x: Optional[float] = None
-    offset_y: Optional[float] = None
-    rotation: Optional[float] = None
diff --git a/src/specklepy/objects_v2/GIS/__init__.py b/src/specklepy/objects_v2/GIS/__init__.py
deleted file mode 100644
index 5ac3dff8..00000000
--- a/src/specklepy/objects_v2/GIS/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""Builtin Speckle object kit."""
-
-from specklepy.objects.GIS.CRS import CRS
-from specklepy.objects.GIS.geometry import (
-    GisLineElement,
-    GisPointElement,
-    GisPolygonElement,
-    GisPolygonGeometry,
-    GisRasterElement,
-    PolygonGeometry,
-)
-from specklepy.objects.GIS.layers import RasterLayer, VectorLayer
-
-__all__ = [
-    "VectorLayer",
-    "RasterLayer",
-    "GisPolygonGeometry",
-    "PolygonGeometry",
-    "GisPolygonElement",
-    "GisLineElement",
-    "GisPointElement",
-    "GisRasterElement",
-    "CRS",
-]
diff --git a/src/specklepy/objects_v2/GIS/geometry.py b/src/specklepy/objects_v2/GIS/geometry.py
deleted file mode 100644
index 68df54cf..00000000
--- a/src/specklepy/objects_v2/GIS/geometry.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from typing import List, Optional, Union
-
-from specklepy.objects.base import Base
-from specklepy.objects.geometry import (
-    Arc,
-    Circle,
-    Line,
-    Mesh,
-    Point,
-    Polycurve,
-    Polyline,
-)
-
-
-class PolygonGeometry(Base, speckle_type="Objects.GIS.PolygonGeometry"):
-    """GIS Polygon Geometry"""
-
-    boundary: Optional[Polyline]
-    voids: Optional[List[Polyline]]
-
-
-GisPolygonGeometry = PolygonGeometry
-
-
-class GisPolygonElement(Base, speckle_type="Objects.GIS.PolygonElement"):
-    """GIS Polygon element"""
-
-    geometry: Optional[List[GisPolygonGeometry]] = None
-    attributes: Optional[Base] = None
-
-
-class GisLineElement(Base, speckle_type="Objects.GIS.LineElement"):
-    """GIS Polyline element"""
-
-    geometry: Optional[List[Union[Polyline, Arc, Line, Circle, Polycurve]]] = None
-    attributes: Optional[Base] = None
-
-
-class GisPointElement(Base, speckle_type="Objects.GIS.PointElement"):
-    """GIS Point element"""
-
-    geometry: Optional[List[Point]] = None
-    attributes: Optional[Base] = None
-
-
-class GisRasterElement(
-    Base, speckle_type="Objects.GIS.RasterElement", detachable={"displayValue"}
-):
-    """GIS Raster element"""
-
-    band_count: Optional[int] = None
-    band_names: Optional[List[str]] = None
-    x_origin: Optional[float] = None
-    y_origin: Optional[float] = None
-    x_size: Optional[int] = None
-    y_size: Optional[int] = None
-    x_resolution: Optional[float] = None
-    y_resolution: Optional[float] = None
-    noDataValue: Optional[List[float]] = None
-    displayValue: Optional[List[Mesh]] = None
-
-
-class GisTopography(
-    GisRasterElement,
-    speckle_type="Objects.GIS.GisTopography",
-    detachable={"displayValue"},
-):
-    """GIS Raster element with 3d Topography representation"""
-
-
-class GisNonGeometryElement(Base, speckle_type="Objects.GIS.NonGeometryElement"):
-    """GIS Table feature"""
-
-    attributes: Optional[Base] = None
diff --git a/src/specklepy/objects_v2/GIS/layers.py b/src/specklepy/objects_v2/GIS/layers.py
deleted file mode 100644
index 3db33351..00000000
--- a/src/specklepy/objects_v2/GIS/layers.py
+++ /dev/null
@@ -1,142 +0,0 @@
-from typing import Any, Dict, List, Optional, Union
-
-from deprecated import deprecated
-
-from specklepy.objects.base import Base
-from specklepy.objects.GIS.CRS import CRS
-from specklepy.objects.other import Collection
-
-
-@deprecated(version="2.15", reason="Use VectorLayer or RasterLayer instead")
-class Layer(Base, detachable={"features"}):
-    """A GIS Layer"""
-
-    def __init__(
-        self,
-        name: Optional[str] = None,
-        crs: Optional[CRS] = None,
-        units: str = "m",
-        features: Optional[List[Base]] = None,
-        layerType: str = "None",
-        geomType: str = "None",
-        renderer: Optional[Dict[str, Any]] = None,
-        **kwargs,
-    ) -> None:
-        super().__init__(**kwargs)
-        self.name = name
-        self.crs = crs
-        self.units = units
-        self.type = layerType
-        self.features = features or []
-        self.geomType = geomType
-        self.renderer = renderer or {}
-
-
-@deprecated(version="2.16", reason="Use VectorLayer or RasterLayer instead")
-class VectorLayer(
-    Collection,
-    detachable={"elements"},
-    speckle_type="VectorLayer",
-    serialize_ignore={"features"},
-):
-    """GIS Vector Layer"""
-
-    name: Optional[str] = None
-    crs: Optional[Union[CRS, Base]] = None
-    units: Optional[str] = None
-    elements: Optional[List[Base]] = None
-    attributes: Optional[Base] = None
-    geomType: Optional[str] = "None"
-    renderer: Optional[Dict[str, Any]] = None
-    collectionType = "VectorLayer"
-
-    @property
-    @deprecated(version="2.14", reason="Use elements")
-    def features(self) -> Optional[List[Base]]:
-        return self.elements
-
-    @features.setter
-    def features(self, value: Optional[List[Base]]) -> None:
-        self.elements = value
-
-
-@deprecated(version="2.16", reason="Use VectorLayer or RasterLayer instead")
-class RasterLayer(
-    Collection,
-    detachable={"elements"},
-    speckle_type="RasterLayer",
-    serialize_ignore={"features"},
-):
-    """GIS Raster Layer"""
-
-    name: Optional[str] = None
-    crs: Optional[Union[CRS, Base]] = None
-    units: Optional[str] = None
-    rasterCrs: Optional[Union[CRS, Base]] = None
-    elements: Optional[List[Base]] = None
-    geomType: Optional[str] = "None"
-    renderer: Optional[Dict[str, Any]] = None
-    collectionType = "RasterLayer"
-
-    @property
-    @deprecated(version="2.14", reason="Use elements")
-    def features(self) -> Optional[List[Base]]:
-        return self.elements
-
-    @features.setter
-    def features(self, value: Optional[List[Base]]) -> None:
-        self.elements = value
-
-
-class VectorLayer(  # noqa: F811
-    Collection,
-    detachable={"elements"},
-    speckle_type="Objects.GIS.VectorLayer",
-    serialize_ignore={"features"},
-):
-    """GIS Vector Layer"""
-
-    name: Optional[str] = None
-    crs: Optional[Union[CRS, Base]] = None
-    units: Optional[str] = None
-    elements: Optional[List[Base]] = None
-    attributes: Optional[Base] = None
-    geomType: Optional[str] = "None"
-    renderer: Optional[Dict[str, Any]] = None
-    collectionType = "VectorLayer"
-
-    @property
-    @deprecated(version="2.14", reason="Use elements")
-    def features(self) -> Optional[List[Base]]:
-        return self.elements
-
-    @features.setter
-    def features(self, value: Optional[List[Base]]) -> None:
-        self.elements = value
-
-
-class RasterLayer(  # noqa: F811
-    Collection,
-    detachable={"elements"},
-    speckle_type="Objects.GIS.RasterLayer",
-    serialize_ignore={"features"},
-):
-    """GIS Raster Layer"""
-
-    name: Optional[str] = None
-    crs: Optional[Union[CRS, Base]] = None
-    units: Optional[str] = None
-    rasterCrs: Optional[Union[CRS, Base]] = None
-    elements: Optional[List[Base]] = None
-    geomType: Optional[str] = "None"
-    renderer: Optional[Dict[str, Any]] = None
-    collectionType = "RasterLayer"
-
-    @property
-    @deprecated(version="2.14", reason="Use elements")
-    def features(self) -> Optional[List[Base]]:
-        return self.elements
-
-    @features.setter
-    def features(self, value: Optional[List[Base]]) -> None:
-        self.elements = value
diff --git a/src/specklepy/objects_v2/__init__.py b/src/specklepy/objects_v2/__init__.py
deleted file mode 100644
index 3e363623..00000000
--- a/src/specklepy/objects_v2/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""Builtin Speckle object kit."""
-
-# from specklepy.objects import (
-#     GIS,
-#     encoding,
-#     geometry,
-#     other,
-#     primitive,
-#     structural,
-#     units,
-# )
-from specklepy.objects.base import Base
-
-__all__ = [
-    "Base",
-    # "encoding",
-    # "geometry",
-    # "other",
-    # "units",
-    # "structural",
-    # "primitive",
-    # "GIS",
-]
diff --git a/src/specklepy/objects_v2/base.py b/src/specklepy/objects_v2/base.py
deleted file mode 100644
index 035ee2fa..00000000
--- a/src/specklepy/objects_v2/base.py
+++ /dev/null
@@ -1,595 +0,0 @@
-import contextlib
-from enum import Enum
-from inspect import isclass
-from typing import (
-    Any,
-    ClassVar,
-    Dict,
-    ForwardRef,
-    List,
-    Optional,
-    Set,
-    Tuple,
-    Type,
-    Union,
-    get_type_hints,
-)
-from warnings import warn
-
-from stringcase import pascalcase
-
-from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
-from specklepy.objects_v2.units import Units
-from specklepy.transports.memory import MemoryTransport
-
-PRIMITIVES = (int, float, str, bool)
-
-# to remove from dir() when calling get_member_names()
-REMOVE_FROM_DIR = {
-    "Config",
-    "_Base__dict_helper",
-    "__annotations__",
-    "__class__",
-    "__delattr__",
-    "__dict__",
-    "__dir__",
-    "__doc__",
-    "__eq__",
-    "__format__",
-    "__ge__",
-    "__getattribute__",
-    "__getitem__",
-    "__gt__",
-    "__hash__",
-    "__init__",
-    "__init_subclass__",
-    "__le__",
-    "__lt__",
-    "__module__",
-    "__ne__",
-    "__new__",
-    "__reduce__",
-    "__reduce_ex__",
-    "__repr__",
-    "__setattr__",
-    "__setitem__",
-    "__sizeof__",
-    "__str__",
-    "__subclasshook__",
-    "__weakref__",
-    "_chunk_size_default",
-    "_chunkable",
-    "_count_descendants",
-    "_attr_types",
-    "_detachable",
-    "_handle_object_count",
-    "_type_check",
-    "_type_registry",
-    "_units",
-    "add_chunkable_attrs",
-    "add_detachable_attrs",
-    "get_children_count",
-    "get_dynamic_member_names",
-    "get_id",
-    "get_member_names",
-    "get_registered_type",
-    "get_typed_member_names",
-    "to_dict",
-    "update_forward_refs",
-    "validate_prop_name",
-    "from_list",
-    "to_list",
-}
-
-
-class _RegisteringBase:
-    """
-    Private Base model for Speckle types.
-
-    This is an implementation detail, please do not use this outside this module.
-
-    This class provides automatic registration of `speckle_type` into a global,
-    (class level) registry for each subclassing type.
-    The type registry is a base for accurate type based (de)serialization.
-    """
-
-    speckle_type: ClassVar[str]
-    _speckle_type_override: ClassVar[Optional[str]] = None
-    _speckle_namespace: ClassVar[Optional[str]] = None
-    _type_registry: ClassVar[Dict[str, Type["Base"]]] = {}
-    _attr_types: ClassVar[Dict[str, Type]] = {}
-    # dict of chunkable props and their max chunk size
-    _chunkable: Dict[str, int] = {}
-    _chunk_size_default: int = 1000
-    _detachable: Set[str] = set()  # list of defined detachable props
-    _serialize_ignore: Set[str] = set()
-
-    @classmethod
-    def get_registered_type(cls, speckle_type: str) -> Optional[Type["Base"]]:
-        """Get the registered type from the protected mapping via the `speckle_type`"""
-        for full_name in reversed(speckle_type.split(":")):
-            maybe_type = cls._type_registry.get(full_name, None)
-            if maybe_type:
-                return maybe_type
-        return None
-
-    @classmethod
-    def _determine_speckle_type(cls) -> str:
-        """
-        This method brings the speckle_type construction in par with Speckle-sharp/Core.
-
-        The implementation differs, because in Core the basis of the speckle_type if
-        type.FullName, which includes the dotnet namespace name too.
-        Copying that behavior is hard in python, where the concept of namespaces
-        means something entirely different.
-
-        So we enabled a speckle_type override mechanism, that enables
-        """
-        base_name = "Base"
-        if cls.__name__ == base_name:
-            return base_name
-
-        bases = [
-            b._full_name()
-            for b in reversed(cls.mro())
-            if issubclass(b, Base) and b.__name__ != base_name
-        ]
-        return ":".join(bases)
-
-    @classmethod
-    def _full_name(cls) -> str:
-        base_name = "Base"
-        if cls.__name__ == base_name:
-            return base_name
-
-        if cls._speckle_type_override:
-            return cls._speckle_type_override
-
-        # convert the module names to PascalCase to match c# namespace naming convention
-        # also drop specklepy from the beginning
-        namespace = ".".join(
-            pascalcase(m)
-            for m in filter(lambda name: name != "specklepy", cls.__module__.split("."))
-        )
-        return f"{namespace}.{cls.__name__}"
-
-    def __init_subclass__(
-        cls,
-        speckle_type: Optional[str] = None,
-        chunkable: Optional[Dict[str, int]] = None,
-        detachable: Optional[Set[str]] = None,
-        serialize_ignore: Optional[Set[str]] = None,
-        **kwargs: Dict[str, Any],
-    ):
-        """
-        Hook into subclass type creation.
-
-        This is provides a mechanism to hook into the event of the subclass type object
-        initialization. This is reused to register each subclassing type into a class
-        level dictionary.
-        """
-        # if not speckle_type:
-        #     raise Exception("no type")
-        cls._speckle_type_override = speckle_type
-        cls.speckle_type = cls._determine_speckle_type()
-        # cls.speckle_type = speckle_type
-        if cls._full_name() in cls._type_registry:
-            raise ValueError(
-                f"The speckle_type: {speckle_type} is already registered for type: "
-                f"{cls._type_registry[cls._full_name()].__name__}. "
-                "Please choose a different type name."
-            )
-        cls._type_registry[cls._full_name()] = cls  # type: ignore
-        try:
-            cls._attr_types = get_type_hints(cls)
-        except Exception:
-            cls._attr_types = getattr(cls, "__annotations__", {})
-        if chunkable:
-            chunkable = {k: v for k, v in chunkable.items() if isinstance(v, int)}
-            cls._chunkable = dict(cls._chunkable, **chunkable)
-        if detachable:
-            cls._detachable = cls._detachable.union(detachable)
-        if serialize_ignore:
-            cls._serialize_ignore = cls._serialize_ignore.union(serialize_ignore)
-        # we know, that the super here is object, that takes no args on init subclass
-        return super().__init_subclass__()
-
-
-# T = TypeVar("T")
-
-# how i wish the code below would be correct, but we're also parsing into floats
-# and converting into strings if the original type is string, but the value isn't
-# def _validate_type(t: type, value: T) -> Tuple[bool, T]:
-
-
-def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
-    # this should be reworked. Its only ok to return null for Optionals...
-    # if t is None and value is None:
-    if value is None:
-        return True, value
-
-    # after fixing the None t above, this should be
-    # if t is Any:
-    # if t is None:
-
-    if t is None or t is Any:
-        return True, value
-
-    if isclass(t) and issubclass(t, Enum):
-        if isinstance(value, t):
-            return True, value
-        if value in t._value2member_map_:
-            return True, t(value)
-
-    if getattr(t, "__module__", None) == "typing":
-        if isinstance(t, ForwardRef):
-            return True, value
-
-        origin = t.__origin__
-        # below is what in nicer for >= py38
-        # origin = get_origin(t)
-
-        # recursive validation for Unions on both types preferring the fist type
-        if origin is Union:
-            # below is what in nicer for >= py38
-            # t_1, t_2 = get_args(t)
-            args = t.__args__  # type: ignore
-            for arg_t in args:
-                t_success, t_value = _validate_type(arg_t, value)
-                if t_success:
-                    return True, t_value
-            return False, value
-        if origin is dict:
-            if not isinstance(value, dict):
-                return False, value
-            if value == {}:
-                return True, value
-            if not getattr(t, "__args__", None):
-                return True, value
-            t_key, t_value = t.__args__  # type: ignore
-
-            if (
-                getattr(t_key, "__name__", None),
-                getattr(t_value, "__name__", None),
-            ) == ("KT", "VT"):
-                return True, value
-            # we're only checking the first item, but the for loop and return after
-            # evaluating the first item is the fastest way
-            for dict_key, dict_value in value.items():
-                valid_key, _ = _validate_type(t_key, dict_key)
-                valid_value, _ = _validate_type(t_value, dict_value)
-
-                if valid_key and valid_value:
-                    return True, value
-                return False, value
-
-        if origin is list:
-            if not isinstance(value, list):
-                return False, value
-            if value == []:
-                return True, value
-            if not hasattr(t, "__args__"):
-                return True, value
-            t_items = t.__args__[0]  # type: ignore
-            if getattr(t_items, "__name__", None) == "T":
-                return True, value
-            first_item_valid, _ = _validate_type(t_items, value[0])
-            if first_item_valid:
-                return True, value
-            return False, value
-
-        if origin is tuple:
-            if not isinstance(value, tuple):
-                return False, value
-            if not hasattr(t, "__args__"):
-                return True, value
-            args = t.__args__  # type: ignore
-            if args == tuple():
-                return True, value
-            # we're not checking for empty tuple, cause tuple lengths must match
-            if len(args) != len(value):
-                return False, value
-            values = []
-            for t_item, v_item in zip(args, value, strict=True):
-                item_valid, item_value = _validate_type(t_item, v_item)
-                if not item_valid:
-                    return False, value
-                values.append(item_value)
-            return True, tuple(values)
-
-        if origin is set:
-            if not isinstance(value, set):
-                return False, value
-            if not hasattr(t, "__args__"):
-                return True, value
-            t_items = t.__args__[0]  # type: ignore
-            first_item_valid, _ = _validate_type(t_items, next(iter(value)))
-            if first_item_valid:
-                return True, value
-            return False, value
-
-    if isinstance(value, t):
-        return True, value
-
-    with contextlib.suppress(ValueError, TypeError):
-        if t is float and value is not None:
-            return True, float(value)
-        # TODO: dafuq, i had to add this not list check
-        # but it would also fail for objects and other complex values
-        if t is str and value and not isinstance(value, list):
-            return True, str(value)
-
-    return False, value
-
-
-class Base(_RegisteringBase, speckle_type="Base"):
-    # id: Union[str, None] = None
-    # totalChildrenCount: Union[int, None] = None
-    # applicationId: Union[str, None] = None
-    _units: Union[None, str] = None
-
-    def __init__(
-        self,
-        id: str | None = None,
-        # totalChildrenCount: Union[int, None] = None,
-        applicationId: str | None = None,
-        **kwargs,
-    ) -> None:
-        self.id = id
-        # self.totalChildrenCount = totalChildrenCount
-        self.applicationId = applicationId
-        super().__init__()
-        for k, v in kwargs.items():
-            self.__setattr__(k, v)
-
-    def __repr__(self) -> str:
-        return (
-            f"{self.__class__.__name__}(id: {self.id}, "
-            f"speckle_type: {self.speckle_type}, "
-            # f"totalChildrenCount: {self.totalChildrenCount})"
-        )
-
-    def __str__(self) -> str:
-        return self.__repr__()
-
-    @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
-
-    def __setitem__(self, name: str, value: Any) -> None:
-        self.validate_prop_name(name)
-        self.__dict__[name] = value
-
-    def __getitem__(self, name: str) -> Any:
-        return self.__dict__[name]
-
-    def __setattr__(self, name: str, value: Any) -> None:
-        """
-        Type checking, guard attribute, and property set mechanism.
-
-        The `speckle_type` is a protected class attribute it must not be overridden.
-
-        This also performs a type check if the attribute is type hinted.
-        """
-        if name == "speckle_type":
-            # not sure if we should raise an exception here??
-            # raise SpeckleException(
-            #     "Cannot override the `speckle_type`."
-            #     "This is set manually by the class or on deserialisation"
-            # )
-            return
-        # if value is not None:
-        value = self._type_check(name, value)
-        attr = getattr(self.__class__, name, None)
-        if isinstance(attr, property):
-            try:
-                attr.__set__(self, value)
-            except AttributeError:
-                return  # the prop probably doesn't have a setter
-        super().__setattr__(name, value)
-
-    @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,
-            )
-
-    @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 '/'",
-            )
-
-    def _type_check(self, name: str, value: Any) -> Any:
-        """
-        Lightweight type checking of values before setting them
-
-        NOTE: Does not check subscripted types within generics as the performance hit
-        of checking each item within a given collection isn't worth it.
-        Eg if you have a type Dict[str, float],
-        we will only check if the value you're trying to set is a dict.
-        """
-        types = getattr(self, "_attr_types", {})
-        t = types.get(name, None)
-
-        valid, checked_value = _validate_type(t, value)
-
-        if valid:
-            return checked_value
-
-        raise SpeckleException(
-            f"Cannot set '{self.__class__.__name__}.{name}':"
-            f"it expects type '{str(t)}',"
-            f"but received type '{type(value).__name__}'"
-        )
-
-    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)
-
-    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)
-
-    @property
-    def units(self) -> Union[str, None]:
-        return self._units
-
-    @units.setter
-    def units(self, value: Union[str, Units, None]):
-        """
-        While this property accepts any string value,
-        geometry expects units to be specific strings (see Units enum)
-        """
-        if isinstance(value, str) or value is None:
-            self._units = value
-        elif isinstance(value, Units):
-            self._units = value.value
-        else:
-            raise SpeckleInvalidUnitException(
-                f"Unknown type {type(value)} received for units"
-            )
-
-    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))
-        ]
-
-    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))
-
-    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())
-
-    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()))
-
-    def get_children_count(self) -> int:
-        """Get the total count of children Base objects"""
-        parsed = []
-        return 1 + self._count_descendants(self, parsed)
-
-    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]
-
-    def _count_descendants(self, base: "Base", parsed: List) -> int:
-        if base in parsed:
-            return 0
-        parsed.append(base)
-
-        return sum(
-            self._handle_object_count(value, parsed)
-            for name, value in base.get_member_names()
-            if not name.startswith("@")
-        )
-
-    def _handle_object_count(self, obj: Any, parsed: List) -> int:
-        # pylint: disable=isinstance-second-argument-not-valid-type
-        count = 0
-        if obj is None:
-            return count
-        if isinstance(obj, "Base"):
-            count += 1
-            count += self._count_descendants(obj, parsed)
-            return count
-        elif isinstance(obj, list):
-            for item in obj:
-                if isinstance(item, "Base"):
-                    count += 1
-                    count += self._count_descendants(item, parsed)
-                else:
-                    count += self._handle_object_count(item, parsed)
-        elif isinstance(obj, dict):
-            for _, value in obj.items():
-                if isinstance(value, "Base"):
-                    count += 1
-                    count += self._count_descendants(value, parsed)
-                else:
-                    count += self._handle_object_count(value, parsed)
-        return count
-
-
-Base.update_forward_refs()
-
-
-class DataChunk(Base, speckle_type="Speckle.Core.Models.DataChunk"):
-    data: Union[List[Any], None] = None
-
-    def __init__(self) -> None:
-        super().__init__()
-        self.data = []
diff --git a/src/specklepy/objects_v2/encoding.py b/src/specklepy/objects_v2/encoding.py
deleted file mode 100644
index eab2d873..00000000
--- a/src/specklepy/objects_v2/encoding.py
+++ /dev/null
@@ -1,131 +0,0 @@
-from enum import Enum
-from typing import Any, Callable, Dict, List, Optional, Type
-
-from specklepy.logging.exceptions import SpeckleException
-from specklepy.objects.base import Base
-
-
-class CurveTypeEncoding(int, Enum):
-    Arc = 0
-    Circle = 1
-    Curve = 2
-    Ellipse = 3
-    Line = 4
-    Polyline = 5
-    Polycurve = 6
-
-    @property
-    def object_class(self) -> Type:
-        from . import geometry
-
-        if self == self.Arc:
-            return geometry.Arc
-        elif self == self.Circle:
-            return geometry.Circle
-        elif self == self.Curve:
-            return geometry.Curve
-        elif self == self.Ellipse:
-            return geometry.Ellipse
-        elif self == self.Line:
-            return geometry.Line
-        elif self == self.Polyline:
-            return geometry.Polyline
-        elif self == self.Polycurve:
-            return geometry.Polycurve
-        raise SpeckleException(
-            f"No corresponding object class for CurveTypeEncoding: {self}"
-        )
-
-
-def curve_from_list(args: List[float]):
-    curve_type = CurveTypeEncoding(args[0])
-    return curve_type.object_class.from_list(args)
-
-
-class ObjectArray:
-    def __init__(self, data: Optional[list] = None) -> None:
-        self.data = data or []
-
-    @classmethod
-    def from_objects(cls, objects: List[Base]) -> "ObjectArray":
-        data_list = cls()
-        if not objects:
-            return data_list
-
-        speckle_type = objects[0].speckle_type
-
-        for obj in objects:
-            if speckle_type != obj.speckle_type:
-                raise SpeckleException(
-                    "All objects in chunk should have the same speckle_type. "
-                    f"Found {speckle_type} and {obj.speckle_type}"
-                )
-            data_list.encode_object(obj=obj)
-
-        return data_list
-
-    @staticmethod
-    def decode_data(
-        data: List[Any], decoder: Callable[[List[Any]], Base], **kwargs: Dict[str, Any]
-    ) -> List[Base]:
-        bases: List[Base] = []
-        if not data:
-            return bases
-        index = 0
-        while index < len(data):
-            item_length = int(data[index])
-            item_start = index + 1
-            item_end = item_start + item_length
-            item_data = data[item_start:item_end]
-            index = item_end
-            decoded_data = decoder(item_data, **kwargs)
-            bases.append(decoded_data)
-
-        return bases
-
-    def decode(self, decoder: Callable[[List[Any]], Any], **kwargs: Dict[str, Any]):
-        return self.decode_data(data=self.data, decoder=decoder, **kwargs)
-
-    def encode_object(self, obj: Base):
-        encoded = obj.to_list()
-        encoded.insert(0, len(encoded))
-        self.data.extend(encoded)
-
-
-class CurveArray(ObjectArray):
-    @classmethod
-    def from_curve(cls, curve: Base) -> "CurveArray":
-        crv_array = cls()
-        crv_array.data = curve.to_list()
-        return crv_array
-
-    @classmethod
-    def from_curves(cls, curves: List[Base]) -> "CurveArray":
-        data = []
-        for curve in curves:
-            curve_list = curve.to_list()
-            curve_list.insert(0, len(curve_list))
-            data.extend(curve_list)
-        crv_array = cls()
-        crv_array.data = data
-        return crv_array
-
-    @staticmethod
-    def curve_from_list(args: List[float]) -> Base:
-        curve_type = CurveTypeEncoding(args[0])
-        return curve_type.object_class.from_list(args)
-
-    @property
-    def type(self) -> CurveTypeEncoding:
-        return CurveTypeEncoding(self.data[0])
-
-    def to_curve(self) -> Base:
-        return self.type.object_class.from_list(self.data)
-
-    @classmethod
-    def _curve_decoder(cls, data: List[float]) -> Base:
-        crv_array = cls(data)
-        return crv_array.to_curve()
-
-    def to_curves(self) -> List[Base]:
-        return self.decode(decoder=self._curve_decoder)
diff --git a/src/specklepy/objects_v2/geometry.py b/src/specklepy/objects_v2/geometry.py
deleted file mode 100644
index 5f7f1e28..00000000
--- a/src/specklepy/objects_v2/geometry.py
+++ /dev/null
@@ -1,948 +0,0 @@
-from enum import Enum
-from typing import Any, List, Optional
-
-from specklepy.objects_v2.base import Base
-from specklepy.objects_v2.encoding import CurveArray, CurveTypeEncoding, ObjectArray
-from specklepy.objects_v2.primitive import Interval
-from specklepy.objects_v2.units import get_encoding_from_units, get_units_from_encoding
-
-GEOMETRY = "Objects.Geometry."
-
-
-class Point(Base, speckle_type=GEOMETRY + "Point"):
-    x: float = 0.0
-    y: float = 0.0
-    z: float = 0.0
-
-    def __repr__(self) -> str:
-        return (
-            f"{self.__class__.__name__}(x: {self.x}, y: {self.y}, z: {self.z}, id:"
-            f" {self.id}, speckle_type: {self.speckle_type})"
-        )
-
-    @classmethod
-    def from_list(cls, args: List[float]) -> "Point":
-        """
-        Create a new Point from a list of three floats
-        representing the x, y, and z coordinates
-        """
-        return cls(x=args[0], y=args[1], z=args[2])
-
-    def to_list(self) -> List[Any]:
-        return [self.x, self.y, self.z]
-
-    @classmethod
-    def from_coords(cls, x: float = 0.0, y: float = 0.0, z: float = 0.0):
-        """Create a new Point from x, y, and z values"""
-        pt = Point()
-        pt.x, pt.y, pt.z = x, y, z
-        return pt
-
-
-class Pointcloud(
-    Base,
-    speckle_type=GEOMETRY + "Pointcloud",
-    chunkable={"points": 31250, "colors": 62500, "sizes": 62500},
-):
-    points: Optional[List[float]] = None
-    colors: Optional[List[int]] = None
-    sizes: Optional[List[float]] = None
-    bbox: Optional["Box"] = None
-
-
-class Vector(Base, speckle_type=GEOMETRY + "Vector"):
-    x: float = 0.0
-    y: float = 0.0
-    z: float = 0.0
-    applicationId: Optional[str] = None
-
-    def __repr__(self) -> str:
-        return (
-            f"{self.__class__.__name__} "
-            "(x: {self.x}, y: {self.y}, z: {self.z}, id: {self.id}, "
-            "speckle_type: {self.speckle_type})"
-        )
-
-    @classmethod
-    def from_list(cls, args: List[float]) -> "Vector":
-        """
-        Create from a list of three floats representing the x, y, and z coordinates.
-        """
-        return cls(x=args[0], y=args[1], z=args[2])
-
-    def to_list(self) -> List[float]:
-        return [self.x, self.y, self.z]
-
-    @classmethod
-    def from_coords(cls, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> "Vector":
-        """Create a new Point from x, y, and z values"""
-        v = Vector()
-        v.x, v.y, v.z = x, y, z
-        return v
-
-
-class ControlPoint(Point, speckle_type=GEOMETRY + "ControlPoint"):
-    weight: Optional[float] = None
-
-
-class Plane(Base, speckle_type=GEOMETRY + "Plane"):
-    origin: Point = Point()
-    normal: Vector = Vector()
-    xdir: Vector = Vector()
-    ydir: Vector = Vector()
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Plane":
-        return cls(
-            origin=Point.from_list(args[:3]),
-            normal=Vector.from_list(args[3:6]),
-            xdir=Vector.from_list(args[6:9]),
-            ydir=Vector.from_list(args[9:12]),
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            *self.origin.to_list(),
-            *self.normal.to_list(),
-            *self.xdir.to_list(),
-            *self.ydir.to_list(),
-            get_encoding_from_units(self._units),
-        ]
-
-
-class Box(Base, speckle_type=GEOMETRY + "Box"):
-    basePlane: Plane = Plane()
-    xSize: Interval = Interval()
-    ySize: Interval = Interval()
-    zSize: Interval = Interval()
-    area: Optional[float] = None
-    volume: Optional[float] = None
-
-
-class Line(Base, speckle_type=GEOMETRY + "Line"):
-    start: Point = Point()
-    end: Optional[Point] = None
-    domain: Optional[Interval] = None
-    bbox: Optional[Box] = None
-    length: Optional[float] = None
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Line":
-        return cls(
-            start=Point.from_list(args[1:4]),
-            end=Point.from_list(args[4:7]),
-            domain=Interval.from_list(args[7:10]),
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        domain = self.domain.to_list() if self.domain else [0, 1]
-        return [
-            CurveTypeEncoding.Line.value,
-            *self.start.to_list(),
-            *self.end.to_list(),
-            *domain,
-            get_encoding_from_units(self._units),
-        ]
-
-
-class Arc(Base, speckle_type=GEOMETRY + "Arc"):
-    radius: Optional[float] = None
-    startAngle: Optional[float] = None
-    endAngle: Optional[float] = None
-    angleRadians: Optional[float] = None
-    plane: Optional[Plane] = None
-    domain: Optional[Interval] = None
-    startPoint: Optional[Point] = None
-    midPoint: Optional[Point] = None
-    endPoint: Optional[Point] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    length: Optional[float] = None
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Arc":
-        return cls(
-            radius=args[1],
-            startAngle=args[2],
-            endAngle=args[3],
-            angleRadians=args[4],
-            domain=Interval.from_list(args[5:7]),
-            plane=Plane.from_list(args[7:20]),
-            startPoint=Point.from_list(args[20:23]),
-            midPoint=Point.from_list(args[23:26]),
-            endPoint=Point.from_list(args[26:29]),
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            CurveTypeEncoding.Arc.value,
-            self.radius,
-            self.startAngle,
-            self.endAngle,
-            self.angleRadians,
-            *self.domain.to_list(),
-            *self.plane.to_list(),
-            *self.startPoint.to_list(),
-            *self.midPoint.to_list(),
-            *self.endPoint.to_list(),
-            get_encoding_from_units(self._units),
-        ]
-
-
-class Circle(Base, speckle_type=GEOMETRY + "Circle"):
-    radius: Optional[float] = None
-    plane: Optional[Plane] = None
-    domain: Optional[Interval] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    length: Optional[float] = None
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Circle":
-        return cls(
-            radius=args[1],
-            domain=Interval.from_list(args[2:4]),
-            plane=Plane.from_list(args[4:17]),
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            CurveTypeEncoding.Circle.value,
-            self.radius,
-            *self.domain.to_list(),
-            *self.plane.to_list(),
-            get_encoding_from_units(self._units),
-        ]
-
-
-class Ellipse(Base, speckle_type=GEOMETRY + "Ellipse"):
-    firstRadius: Optional[float] = None
-    secondRadius: Optional[float] = None
-    plane: Optional[Plane] = None
-    domain: Optional[Interval] = None
-    trimDomain: Optional[Interval] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    length: Optional[float] = None
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Ellipse":
-        return cls(
-            firstRadius=args[1],
-            secondRadius=args[2],
-            domain=Interval.from_list(args[3:5]),
-            plane=Plane.from_list(args[5:18]),
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            CurveTypeEncoding.Ellipse.value,
-            self.firstRadius,
-            self.secondRadius,
-            *self.domain.to_list(),
-            *self.plane.to_list(),
-            get_encoding_from_units(self._units),
-        ]
-
-
-class Polyline(Base, speckle_type=GEOMETRY + "Polyline", chunkable={"value": 20000}):
-    value: Optional[List[float]] = None
-    closed: Optional[bool] = None
-    domain: Optional[Interval] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    length: Optional[float] = None
-
-    @classmethod
-    def from_points(cls, points: List[Point]):
-        """Create a new Polyline from a list of Points"""
-        polyline = cls()
-        polyline.units = points[0].units
-        polyline.value = []
-        for point in points:
-            polyline.value.extend([point.x, point.y, point.z])
-        return polyline
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Polyline":
-        point_count = args[4]
-        return cls(
-            closed=bool(args[1]),
-            domain=Interval.from_list(args[2:4]),
-            value=args[5 : 5 + point_count],
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            CurveTypeEncoding.Polyline.value,
-            int(self.closed),
-            *self.domain.to_list(),
-            len(self.value),
-            *self.value,
-            get_encoding_from_units(self._units),
-        ]
-
-    def as_points(self) -> List[Point]:
-        """Converts the `value` attribute to a list of Points"""
-        if not self.value:
-            return
-
-        if len(self.value) % 3:
-            raise ValueError("Points array malformed: length%3 != 0.")
-
-        values = iter(self.value)
-        return [
-            Point(x=v, y=next(values), z=next(values), units=self.units) for v in values
-        ]
-
-
-class SpiralType(Enum):
-    Biquadratic = 0
-    BiquadraticParabola = 1
-    Bloss = 2
-    Clothoid = 3
-    Cosine = 4
-    Cubic = 5
-    CubicParabola = 6
-    Radioid = 7
-    Sinusoid = 8
-    Unknown = 9
-
-
-class Spiral(Base, speckle_type=GEOMETRY + "Spiral", detachable={"displayValue"}):
-    startPoint: Optional[Point] = None
-    endPoint: Optional[Point]
-    plane: Optional[Plane]
-    turns: Optional[float]
-    pitchAxis: Optional[Vector] = Vector()
-    pitch: float = 0
-    spiralType: Optional[SpiralType] = None
-    displayValue: Optional[Polyline] = None
-    bbox: Optional[Box] = None
-    length: Optional[float] = None
-    domain: Optional[Interval] = None
-
-
-class Curve(
-    Base,
-    speckle_type=GEOMETRY + "Curve",
-    chunkable={"points": 20000, "weights": 20000, "knots": 20000},
-):
-    degree: Optional[int] = None
-    periodic: Optional[bool] = None
-    rational: Optional[bool] = None
-    points: Optional[List[float]] = None
-    weights: Optional[List[float]] = None
-    knots: Optional[List[float]] = None
-    domain: Optional[Interval] = None
-    displayValue: Optional[Polyline] = None
-    closed: Optional[bool] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    length: Optional[float] = None
-
-    def as_points(self) -> List[Point]:
-        """Converts the `value` attribute to a list of Points"""
-        if not self.points:
-            return
-
-        if len(self.points) % 3:
-            raise ValueError("Points array malformed: length%3 != 0.")
-
-        values = iter(self.points)
-        return [
-            Point(x=v, y=next(values), z=next(values), units=self.units) for v in values
-        ]
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Curve":
-        point_count = int(args[7])
-        weights_count = int(args[8])
-        knots_count = int(args[9])
-
-        points_start = 10
-        weights_start = 10 + point_count
-        knots_start = weights_start + weights_count
-        knots_end = knots_start + knots_count
-
-        return cls(
-            degree=int(args[1]),
-            periodic=bool(args[2]),
-            rational=bool(args[3]),
-            closed=bool(args[4]),
-            domain=Interval.from_list(args[5:7]),
-            points=args[points_start:weights_start],
-            weights=args[weights_start:knots_start],
-            knots=args[knots_start:knots_end],
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            CurveTypeEncoding.Curve.value,
-            self.degree,
-            int(self.periodic),
-            int(self.rational),
-            int(self.closed),
-            *self.domain.to_list(),
-            len(self.points),
-            len(self.weights),
-            len(self.knots),
-            *self.points,
-            *self.weights,
-            *self.knots,
-            get_encoding_from_units(self._units),
-        ]
-
-
-class Polycurve(Base, speckle_type=GEOMETRY + "Polycurve"):
-    segments: Optional[List[Base]] = None
-    domain: Optional[Interval] = None
-    closed: Optional[bool] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    length: Optional[float] = None
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Polycurve":
-        curve_arrays = CurveArray(args[5:-1])
-        return cls(
-            closed=bool(args[1]),
-            domain=Interval.from_list(args[2:4]),
-            segments=curve_arrays.to_curves(),
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        curve_array = CurveArray.from_curves(self.segments).data
-        return [
-            CurveTypeEncoding.Polycurve.value,
-            int(self.closed),
-            *self.domain.to_list(),
-            len(curve_array),
-            *curve_array,
-            get_encoding_from_units(self._units),
-        ]
-
-
-class Extrusion(Base, speckle_type=GEOMETRY + "Extrusion"):
-    capped: Optional[bool] = None
-    profile: Optional[Base] = None
-    pathStart: Optional[Point] = None
-    pathEnd: Optional[Point] = None
-    pathCurve: Optional[Base] = None
-    pathTangent: Optional[Base] = None
-    profiles: Optional[List[Base]] = None
-    length: Optional[float] = None
-    area: Optional[float] = None
-    volume: Optional[float] = None
-    bbox: Optional[Box] = None
-
-
-class Mesh(
-    Base,
-    speckle_type=GEOMETRY + "Mesh",
-    chunkable={
-        "vertices": 2000,
-        "faces": 2000,
-        "colors": 2000,
-        "textureCoordinates": 2000,
-    },
-):
-    vertices: Optional[List[float]] = None
-    faces: Optional[List[int]] = None
-    colors: Optional[List[int]] = None
-    textureCoordinates: Optional[List[float]] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    volume: Optional[float] = None
-
-    @classmethod
-    def create(
-        cls,
-        vertices: List[float],
-        faces: List[int],
-        colors: Optional[List[int]] = None,
-        texture_coordinates: Optional[List[float]] = None,
-    ) -> "Mesh":
-        """
-        Create a new Mesh from lists representing its vertices, faces,
-        colors (optional), and texture coordinates (optional).
-
-        This will initialise empty lists for colors and texture coordinates
-        if you do not provide any.
-        """
-        return cls(
-            vertices=vertices,
-            faces=faces,
-            colors=colors or [],
-            textureCoordinates=texture_coordinates or [],
-        )
-
-
-class Surface(Base, speckle_type=GEOMETRY + "Surface"):
-    degreeU: Optional[int] = None
-    degreeV: Optional[int] = None
-    rational: Optional[bool] = None
-    area: Optional[float] = None
-    pointData: Optional[List[float]] = None
-    countU: Optional[int] = None
-    countV: Optional[int] = None
-    bbox: Optional[Box] = None
-    closedU: Optional[bool] = None
-    closedV: Optional[bool] = None
-    domainU: Optional[Interval] = None
-    domainV: Optional[Interval] = None
-    knotsU: Optional[List[float]] = None
-    knotsV: Optional[List[float]] = None
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Surface":
-        point_count = int(args[11])
-        knots_u_count = int(args[12])
-        knots_v_count = int(args[13])
-
-        start_point_data = 14
-        start_knots_u = start_point_data + point_count
-        start_knots_v = start_knots_u + knots_u_count
-
-        return cls(
-            degreeU=int(args[0]),
-            degreeV=int(args[1]),
-            countU=int(args[2]),
-            countV=int(args[3]),
-            rational=bool(args[4]),
-            closedU=bool(args[5]),
-            closedV=bool(args[6]),
-            domainU=Interval(start=args[7], end=args[8]),
-            domainV=Interval(start=args[9], end=args[10]),
-            pointData=args[start_point_data:start_knots_u],
-            knotsU=args[start_knots_u:start_knots_v],
-            knotsV=args[start_knots_v : start_knots_v + knots_v_count],
-            units=get_units_from_encoding(args[-1]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            self.degreeU,
-            self.degreeV,
-            self.countU,
-            self.countV,
-            int(self.rational),
-            int(self.closedU),
-            int(self.closedV),
-            *self.domainU.to_list(),
-            *self.domainV.to_list(),
-            len(self.pointData),
-            len(self.knotsU),
-            len(self.knotsV),
-            *self.pointData,
-            *self.knotsU,
-            *self.knotsV,
-            get_encoding_from_units(self._units),
-        ]
-
-
-class BrepFace(Base, speckle_type=GEOMETRY + "BrepFace"):
-    _Brep: Optional["Brep"] = None
-    SurfaceIndex: Optional[int] = None
-    OuterLoopIndex: Optional[int] = None
-    OrientationReversed: Optional[bool] = None
-    LoopIndices: Optional[List[int]] = None
-
-    @property
-    def _outer_loop(self):
-        return self._Brep.Loops[self.OuterLoopIndex]  # pylint: disable=no-member
-
-    @property
-    def _surface(self):
-        return self._Brep.Surfaces[self.SurfaceIndex]  # pylint: disable=no-member
-
-    @property
-    def _loops(self):
-        if self.LoopIndices:
-            # pylint: disable=not-an-iterable, no-member
-            return [self._Brep.Loops[i] for i in self.LoopIndices]
-
-    @classmethod
-    def from_list(cls, args: List[Any], brep: "Brep" = None) -> "BrepFace":
-        return cls(
-            _Brep=brep,
-            SurfaceIndex=args[0],
-            OuterLoopIndex=args[1],
-            OrientationReversed=bool(args[2]),
-            LoopIndices=args[3:],
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            self.SurfaceIndex,
-            self.OuterLoopIndex,
-            int(self.OrientationReversed),
-            *self.LoopIndices,
-        ]
-
-
-class BrepEdge(Base, speckle_type=GEOMETRY + "BrepEdge"):
-    _Brep: Optional["Brep"] = None
-    Curve3dIndex: Optional[int] = None
-    TrimIndices: Optional[List[int]] = None
-    StartIndex: Optional[int] = None
-    EndIndex: Optional[int] = None
-    ProxyCurveIsReversed: Optional[bool] = None
-    Domain: Optional[Interval] = None
-
-    @property
-    def _start_vertex(self):
-        return self._Brep.Vertices[self.StartIndex]
-
-    @property
-    def _end_vertex(self):
-        return self._Brep.Vertices[self.EndIndex]
-
-    @property
-    def _trims(self):
-        if self.TrimIndices:
-            # pylint: disable=not-an-iterable
-            return [self._Brep.Trims[i] for i in self.TrimIndices]
-
-    @property
-    def _curve(self):
-        return self._Brep.Curve3D[self.Curve3dIndex]
-
-    @classmethod
-    def from_list(cls, args: List[Any], brep: "Brep" = None) -> "BrepEdge":
-        domain_start = args[4]
-        domain_end = args[5]
-        domain = (
-            Interval(start=domain_start, end=domain_end)
-            if None not in (domain_start, domain_end)
-            else None
-        )
-        return cls(
-            _Brep=brep,
-            Curve3dIndex=int(args[0]),
-            TrimIndices=[int(t) for t in args[6:]],
-            StartIndex=int(args[1]),
-            EndIndex=int(args[2]),
-            ProxyCurveIsReversed=bool(args[3]),
-            Domain=domain,
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            self.Curve3dIndex,
-            self.StartIndex,
-            self.EndIndex,
-            int(self.ProxyCurveIsReversed),
-            self.Domain.start,
-            self.Domain.end,
-            *self.TrimIndices,
-        ]
-
-
-class BrepLoopType(int, Enum):
-    Unknown = 0
-    Outer = 1
-    Inner = 2
-    Slit = 3
-    CurveOnSurface = 4
-    PointOnSurface = 5
-
-
-class BrepLoop(Base, speckle_type=GEOMETRY + "BrepLoop"):
-    _Brep: Optional["Brep"] = None
-    FaceIndex: Optional[Optional[int]] = None
-    TrimIndices: Optional[List[int]] = None
-    Type: Optional[BrepLoopType] = None
-
-    @property
-    def _face(self):
-        return self._Brep.Faces[self.FaceIndex]
-
-    @property
-    def _trims(self):
-        if self.TrimIndices:
-            # pylint: disable=not-an-iterable
-            return [self._Brep.Trims[i] for i in self.TrimIndices]
-
-    @classmethod
-    def from_list(cls, args: List[any], brep: "Brep" = None):
-        return cls(
-            _Brep=brep,
-            FaceIndex=args[0],
-            Type=BrepLoopType(args[1]),
-            TrimIndices=args[2:],
-        )
-
-    def to_list(self) -> List[int]:
-        return [
-            self.FaceIndex,
-            self.Type.value,
-            *self.TrimIndices,
-        ]
-
-
-class BrepTrimType(int, Enum):
-    Unknown = 0
-    Boundary = 1
-    Mated = 2
-    Seam = 3
-    Singular = 4
-    CurveOnSurface = 5
-    PointOnSurface = 6
-    Slit = 7
-
-
-class BrepTrim(Base, speckle_type=GEOMETRY + "BrepTrim"):
-    _Brep: Optional["Brep"] = None
-    EdgeIndex: Optional[int] = None
-    StartIndex: Optional[int] = None
-    EndIndex: Optional[int] = None
-    FaceIndex: Optional[int] = None
-    LoopIndex: Optional[int] = None
-    CurveIndex: Optional[int] = None
-    IsoStatus: Optional[int] = None
-    TrimType: Optional[BrepTrimType] = None
-    IsReversed: Optional[bool] = None
-    Domain: Optional[Interval] = None
-
-    @property
-    def _face(self):
-        if self._Brep:
-            return self._Brep.Faces[self.FaceIndex]  # pylint: disable=no-member
-
-    @property
-    def _loop(self):
-        if self._Brep:
-            return self._Brep.Loops[self.LoopIndex]  # pylint: disable=no-member
-
-    @property
-    def _edge(self):
-        if self._Brep:
-            # pylint: disable=no-member
-            return self._Brep.Edges[self.EdgeIndex] if self.EdgeIndex != -1 else None
-
-    @property
-    def _curve_2d(self):
-        if self._Brep:
-            return self._Brep.Curve2D[self.CurveIndex]  # pylint: disable=no-member
-
-    @classmethod
-    def from_list(cls, args: List[Any], brep: "Brep" = None) -> "BrepTrim":
-        return cls(
-            _Brep=brep,
-            EdgeIndex=args[0],
-            StartIndex=args[1],
-            EndIndex=args[2],
-            FaceIndex=args[3],
-            LoopIndex=args[4],
-            CurveIndex=args[5],
-            IsoStatus=args[6],
-            TrimType=BrepTrimType(args[7]),
-            IsReversed=bool(args[8]),
-        )
-
-    def to_list(self) -> List[Any]:
-        return [
-            self.EdgeIndex,
-            self.StartIndex,
-            self.EndIndex,
-            self.FaceIndex,
-            self.LoopIndex,
-            self.CurveIndex,
-            self.IsoStatus,
-            self.TrimType.value,
-            int(self.IsReversed),
-        ]
-
-
-class Brep(
-    Base,
-    speckle_type=GEOMETRY + "Brep",
-    chunkable={
-        "SurfacesValue": 31250,
-        "Curve3DValues": 31250,
-        "Curve2DValues": 31250,
-        "VerticesValue": 31250,
-        "EdgesValue": 62500,
-        "LoopsValue": 62500,
-        "FacesValue": 62500,
-        "TrimsValue": 62500,
-    },
-    detachable={"displayValue"},
-    serialize_ignore={
-        "Surfaces",
-        "Curve3D",
-        "Curve2D",
-        "Vertices",
-        "Trims",
-        "Edges",
-        "Loops",
-        "Faces",
-    },
-):
-    provenance: Optional[str] = None
-    bbox: Optional[Box] = None
-    area: Optional[float] = None
-    volume: Optional[float] = None
-    _displayValue: Optional[List[Mesh]] = None
-    Surfaces: Optional[List[Surface]] = None
-    Curve3D: Optional[List[Base]] = None
-    Curve2D: Optional[List[Base]] = None
-    Vertices: Optional[List[Point]] = None
-    Edges: Optional[List[BrepEdge]] = None
-    Loops: Optional[List[BrepLoop]] = None
-    Faces: Optional[List[BrepFace]] = None
-    Trims: Optional[List[BrepTrim]] = None
-    IsClosed: Optional[bool] = None
-    Orientation: Optional[int] = None
-
-    def _inject_self_into_children(self, children: Optional[List[Base]]) -> List[Base]:
-        if children is None:
-            return children
-
-        for child in children:
-            child._Brep = self  # pylint: disable=protected-access
-        return children
-
-    # set as prop for now for backwards compatibility
-    @property
-    def displayValue(self) -> List[Mesh]:
-        return self._displayValue
-
-    @displayValue.setter
-    def displayValue(self, value):
-        if isinstance(value, Mesh):
-            self._displayValue = [value]
-        elif isinstance(value, list):
-            self._displayValue = value
-
-    @property
-    def EdgesValue(self) -> List[BrepEdge]:
-        return None if self.Edges is None else ObjectArray.from_objects(self.Edges).data
-
-    @EdgesValue.setter
-    def EdgesValue(self, value: List[float]):
-        if not value:
-            return
-
-        self.Edges = ObjectArray.decode_data(value, BrepEdge.from_list, brep=self)
-
-    @property
-    def LoopsValue(self) -> List[BrepLoop]:
-        return None if self.Loops is None else ObjectArray.from_objects(self.Loops).data
-
-    @LoopsValue.setter
-    def LoopsValue(self, value: List[int]):
-        if not value:
-            return
-
-        self.Loops = ObjectArray.decode_data(value, BrepLoop.from_list, brep=self)
-
-    @property
-    def FacesValue(self) -> List[int]:
-        return None if self.Faces is None else ObjectArray.from_objects(self.Faces).data
-
-    @FacesValue.setter
-    def FacesValue(self, value: List[int]):
-        if not value:
-            return
-
-        self.Faces = ObjectArray.decode_data(value, BrepFace.from_list, brep=self)
-
-    @property
-    def SurfacesValue(self) -> List[float]:
-        return (
-            None
-            if self.Surfaces is None
-            else ObjectArray.from_objects(self.Surfaces).data
-        )
-
-    @SurfacesValue.setter
-    def SurfacesValue(self, value: List[float]):
-        if not value:
-            return
-
-        self.Surfaces = ObjectArray.decode_data(value, Surface.from_list)
-
-    @property
-    def Curve3DValues(self) -> List[float]:
-        return (
-            None if self.Curve3D is None else CurveArray.from_curves(self.Curve3D).data
-        )
-
-    @Curve3DValues.setter
-    def Curve3DValues(self, value: List[float]):
-        crv_array = CurveArray(value)
-        self.Curve3D = crv_array.to_curves()
-
-    @property
-    def Curve2DValues(self) -> List[Base]:
-        return (
-            None if self.Curve2D is None else CurveArray.from_curves(self.Curve2D).data
-        )
-
-    @Curve2DValues.setter
-    def Curve2DValues(self, value: List[float]):
-        crv_array = CurveArray(value)
-        self.Curve2D = crv_array.to_curves()
-
-    @property
-    def VerticesValue(self) -> List[Point]:
-        if self.Vertices is None:
-            return None
-        encoded_unit = get_encoding_from_units(self.Vertices[0].units)
-        values = [encoded_unit]
-        for vertex in self.Vertices:
-            values.extend(vertex.to_list())
-        return values
-
-    @VerticesValue.setter
-    def VerticesValue(self, value: List[float]):
-        value = value.copy()
-        units = get_units_from_encoding(value.pop(0))
-
-        vertices = []
-
-        for i in range(0, len(value), 3):
-            vertex = Point.from_list(value[i : i + 3])
-            vertex.units = units
-            vertices.append(vertex)
-
-        self.Vertices = vertices
-
-    # TODO: can this be consistent with loops, edges, faces, curves,
-    # etc and prepend with the chunk list? needs to happen in sharp first
-    @property
-    def TrimsValue(self) -> List[float]:
-        # return None if self.Trims is None else
-        # ObjectArray.from_objects(self.Trims).data
-        if not self.Trims:
-            return
-        value = []
-        for trim in self.Trims:
-            value.extend(trim.to_list())
-        return value
-
-    @TrimsValue.setter
-    def TrimsValue(self, value: List[float]):
-        if not value:
-            return
-
-        # self.Trims = ObjectArray.decode_data(value, BrepTrim.from_list, brep=self)
-        self.Trims = [
-            BrepTrim.from_list(value[i : i + 9], self) for i in range(0, len(value), 9)
-        ]
-
-
-BrepEdge.update_forward_refs()
-BrepLoop.update_forward_refs()
-BrepTrim.update_forward_refs()
-BrepFace.update_forward_refs()
diff --git a/src/specklepy/objects_v2/other.py b/src/specklepy/objects_v2/other.py
deleted file mode 100644
index fbf4d436..00000000
--- a/src/specklepy/objects_v2/other.py
+++ /dev/null
@@ -1,311 +0,0 @@
-from typing import Any, List, Optional
-
-from deprecated import deprecated
-
-from specklepy.objects.geometry import Plane, Point, Polyline, Vector
-
-from .base import Base
-
-OTHER = "Objects.Other."
-OTHER_REVIT = OTHER + "Revit."
-
-IDENTITY_TRANSFORM = [
-    1.0,
-    0.0,
-    0.0,
-    0.0,
-    0.0,
-    1.0,
-    0.0,
-    0.0,
-    0.0,
-    0.0,
-    1.0,
-    0.0,
-    0.0,
-    0.0,
-    0.0,
-    1.0,
-]
-
-
-class Material(Base, speckle_type=OTHER + "Material"):
-    """Generic class for materials containing generic parameters."""
-
-    name: Optional[str] = None
-
-
-class RevitMaterial(Material, speckle_type="Objects.Other.Revit." + "RevitMaterial"):
-    materialCategory: Optional[str] = None
-    materialClass: Optional[str] = None
-    shininess: Optional[int] = None
-    smoothness: Optional[int] = None
-    transparency: Optional[int] = None
-    parameters: Optional[Base] = None
-
-
-class RenderMaterial(Base, speckle_type=OTHER + "RenderMaterial"):
-    name: Optional[str] = None
-    opacity: float = 1
-    metalness: float = 0
-    roughness: float = 1
-    diffuse: int = -2894893  # light gray arbg
-    emissive: int = -16777216  # black arbg
-
-
-class MaterialQuantity(Base, speckle_type=OTHER + "MaterialQuantity"):
-    material: Optional[Material] = None
-    volume: Optional[float] = None
-    area: Optional[float] = None
-
-
-class DisplayStyle(Base, speckle_type=OTHER + "DisplayStyle"):
-    """
-    Minimal display style class.
-    Developed primarily for display styles in Rhino and AutoCAD.
-    Rhino object attributes uses OpenNURBS definition for linetypes and lineweights.
-    """
-
-    name: Optional[str] = None
-    color: int = -2894893  # light gray arbg
-    linetype: Optional[str] = None
-    lineweight: float = 0
-
-
-class Text(Base, speckle_type=OTHER + "Text"):
-    """
-    Text object to render it on viewer.
-    """
-
-    plane: Plane
-    value: str
-    height: float
-    rotation: float
-    displayValue: Optional[List[Polyline]] = None
-    richText: Optional[str] = None
-
-
-class Transform(
-    Base,
-    speckle_type=OTHER + "Transform",
-    serialize_ignore={"translation", "scaling", "is_identity", "value"},
-):
-    """The 4x4 transformation matrix
-
-    The 3x3 sub-matrix determines scaling.
-    The 4th column defines translation,
-    where the last value is a divisor (usually equal to 1).
-    """
-
-    _value: Optional[List[float]] = None
-
-    @property
-    @deprecated(version="2.12", reason="Use matrix")
-    def value(self) -> List[float]:
-        return self._value
-
-    @value.setter
-    def value(self, value: List[float]) -> None:
-        self.matrix = value
-
-    @property
-    def matrix(self) -> List[float]:
-        """The transform matrix represented as a flat list of 16 floats"""
-        return self._value
-
-    @matrix.setter
-    def matrix(self, value: List[float]) -> None:
-        try:
-            value = [float(x) for x in value]
-        except (ValueError, TypeError) as error:
-            raise ValueError(
-                "Could not create a Transform object with the requested value. Input"
-                f" must be a 16 element list of numbers. Value provided: {value}"
-            ) from error
-
-        if len(value) != 16:
-            raise ValueError(
-                "Could not create a Transform object: input list should be 16 floats"
-                f" long, but was {len(value)} long"
-            )
-
-        self._value = value
-
-    @property
-    def translation(self) -> List[float]:
-        """The final column of the matrix which defines the translation"""
-        return [self._value[i] for i in (3, 7, 11, 15)]
-
-    @property
-    def scaling(self) -> List[float]:
-        """The 3x3 scaling sub-matrix"""
-        return [self._value[i] for i in (0, 1, 2, 4, 5, 6, 8, 9, 10)]
-
-    @property
-    def is_identity(self) -> bool:
-        return self._value == IDENTITY_TRANSFORM
-
-    def apply_to_point(self, point: Point) -> Point:
-        """Transform a single speckle Point
-
-        Arguments:
-            point {Point} -- the speckle Point to transform
-
-        Returns:
-            Point -- a new transformed point
-        """
-        coords = self.apply_to_point_value([point.x, point.y, point.z])
-        return Point(x=coords[0], y=coords[1], z=coords[2], units=point.units)
-
-    def apply_to_point_value(self, point_value: List[float]) -> List[float]:
-        """Transform a list of three floats representing a point
-
-        Arguments:
-            point_value {List[float]} -- a list of 3 floats
-
-        Returns:
-            List[float] -- the list with the transform applied
-        """
-        transformed = [
-            point_value[0] * self._value[i]
-            + point_value[1] * self._value[i + 1]
-            + point_value[2] * self._value[i + 2]
-            + self._value[i + 3]
-            for i in range(0, 15, 4)
-        ]
-
-        return [transformed[i] / transformed[3] for i in range(3)]
-
-    def apply_to_points(self, points: List[Point]) -> List[Point]:
-        """Transform a list of speckle Points
-
-        Arguments:
-            points {List[Point]} -- the list of speckle Points to transform
-
-        Returns:
-            List[Point] -- a new list of transformed points
-        """
-        return [self.apply_to_point(point) for point in points]
-
-    def apply_to_points_values(self, points_value: List[float]) -> List[float]:
-        """Transform a list of speckle Points
-
-        Arguments:
-            points {List[float]}
-            -- a flat list of floats representing points to transform
-
-        Returns:
-            List[float] -- a new transformed list
-        """
-        if len(points_value) % 3 != 0:
-            raise ValueError(
-                "Cannot apply transform as the points list is malformed: expected"
-                " length to be multiple of 3"
-            )
-        transformed = []
-        for i in range(0, len(points_value), 3):
-            transformed.extend(self.apply_to_point_value(points_value[i : i + 3]))
-
-        return transformed
-
-    def apply_to_vector(self, vector: Vector) -> Vector:
-        """Transform a single speckle Vector
-
-        Arguments:
-            point {Vector} -- the speckle Vector to transform
-
-        Returns:
-            Vector -- a new transformed point
-        """
-        coords = self.apply_to_vector_value([vector.x, vector.y, vector.z])
-        return Vector(x=coords[0], y=coords[1], z=coords[2], units=vector.units)
-
-    def apply_to_vector_value(self, vector_value: List[float]) -> List[float]:
-        """Transform a list of three floats representing a vector
-
-        Arguments:
-            vector_value {List[float]} -- a list of 3 floats
-
-        Returns:
-            List[float] -- the list with the transform applied
-        """
-        return [
-            vector_value[0] * self._value[i]
-            + vector_value[1] * self._value[i + 1]
-            + vector_value[2] * self._value[i + 2]
-            for i in range(0, 15, 4)
-        ][:3]
-
-    @classmethod
-    def from_list(cls, value: Optional[List[float]] = None) -> "Transform":
-        """Returns a Transform object from a list of 16 numbers.
-        If no value is provided, an identity transform will be returned.
-
-        Arguments:
-            value {List[float]} -- the matrix as a flat list of 16 numbers
-            (defaults to the identity transform)
-
-        Returns:
-            Transform -- a complete transform object
-        """
-        if not value:
-            value = IDENTITY_TRANSFORM
-        return cls(value=value)
-
-
-class BlockDefinition(
-    Base, speckle_type=OTHER + "BlockDefinition", detachable={"geometry"}
-):
-    name: Optional[str] = None
-    basePoint: Optional[Point] = None
-    geometry: Optional[List[Base]] = None
-
-
-class Instance(Base, speckle_type=OTHER + "Instance", detachable={"definition"}):
-    transform: Optional[Transform] = None
-    definition: Optional[Base] = None
-
-
-class BlockInstance(
-    Instance, speckle_type=OTHER + "BlockInstance", serialize_ignore={"blockDefinition"}
-):
-    @property
-    @deprecated(version="2.13", reason="Use definition")
-    def blockDefinition(self) -> Optional[BlockDefinition]:
-        if isinstance(self.definition, BlockDefinition):
-            return self.definition
-        return None
-
-    @blockDefinition.setter
-    def blockDefinition(self, value: Optional[BlockDefinition]) -> None:
-        self.definition = value
-
-
-class RevitInstance(Instance, speckle_type=OTHER_REVIT + "RevitInstance"):
-    level: Optional[Base] = None
-    facingFlipped: bool
-    handFlipped: bool
-    parameters: Optional[Base] = None
-    elementId: Optional[str]
-
-
-# TODO: prob move this into a built elements module, but just trialling this for now
-class RevitParameter(Base, speckle_type="Objects.BuiltElements.Revit.Parameter"):
-    name: Optional[str] = None
-    value: Any = None
-    applicationUnitType: Optional[str] = None  # eg UnitType UT_Length
-    applicationUnit: Optional[str] = None  # DisplayUnitType eg DUT_MILLIMITERS
-    applicationInternalName: Optional[str] = (
-        None  # BuiltInParameterName or GUID for shared parameter
-    )
-    isShared: bool = False
-    isReadOnly: bool = False
-    isTypeParameter: bool = False
-
-
-class Collection(
-    Base, speckle_type="Speckle.Core.Models.Collection", detachable={"elements"}
-):
-    name: Optional[str] = None
-    collectionType: Optional[str] = None
-    elements: Optional[List[Base]] = None
diff --git a/src/specklepy/objects_v2/primitive.py b/src/specklepy/objects_v2/primitive.py
deleted file mode 100644
index d4a4aaee..00000000
--- a/src/specklepy/objects_v2/primitive.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from typing import Any, List
-
-from specklepy.objects.base import Base
-
-NAMESPACE = "Objects.Primitive"
-
-
-class Interval(Base, speckle_type=f"{NAMESPACE}.Interval"):
-    start: float = 0.0
-    end: float = 0.0
-
-    def length(self):
-        return abs(self.start - self.end)
-
-    @classmethod
-    def from_list(cls, args: List[Any]) -> "Interval":
-        return cls(start=args[0], end=args[1])
-
-    def to_list(self) -> List[Any]:
-        return [self.start, self.end]
-
-
-class Interval2d(Base, speckle_type=f"{NAMESPACE}.Interval2d"):
-    u: Interval
-    v: Interval
diff --git a/src/specklepy/objects_v2/structural/__init__.py b/src/specklepy/objects_v2/structural/__init__.py
deleted file mode 100644
index dc91f3a2..00000000
--- a/src/specklepy/objects_v2/structural/__init__.py
+++ /dev/null
@@ -1,142 +0,0 @@
-"""Builtin Speckle object kit."""
-
-from specklepy.objects.structural.analysis import (
-    Model,
-    ModelInfo,
-    ModelSettings,
-    ModelUnits,
-)
-from specklepy.objects.structural.axis import Axis, AxisType
-from specklepy.objects.structural.geometry import (
-    Element1D,
-    Element2D,
-    Element3D,
-    ElementType1D,
-    ElementType2D,
-    ElementType3D,
-    Node,
-    Restraint,
-)
-from specklepy.objects.structural.loading import (
-    ActionType,
-    BeamLoadType,
-    CombinationType,
-    FaceLoadType,
-    Load,
-    LoadAxisType,
-    LoadBeam,
-    LoadCase,
-    LoadCombinations,
-    LoadDirection,
-    LoadDirection2D,
-    LoadFace,
-    LoadGravity,
-    LoadNode,
-    LoadType,
-)
-from specklepy.objects.structural.materials import (
-    Concrete,
-    MaterialType,
-    Steel,
-    StructuralMaterial,
-    Timber,
-)
-from specklepy.objects.structural.properties import (
-    BaseReferencePoint,
-    MemberType,
-    Property,
-    Property1D,
-    Property2D,
-    Property3D,
-    PropertyDamper,
-    PropertyMass,
-    PropertySpring,
-    PropertyType2D,
-    PropertyType3D,
-    PropertyTypeDamper,
-    PropertyTypeSpring,
-    ReferenceSurface,
-    ReferenceSurfaceEnum,
-    SectionProfile,
-    ShapeType,
-    shapeType,
-)
-from specklepy.objects.structural.results import (
-    Result,
-    Result1D,
-    Result2D,
-    Result3D,
-    ResultGlobal,
-    ResultNode,
-    ResultSet1D,
-    ResultSet2D,
-    ResultSet3D,
-    ResultSetAll,
-    ResultSetNode,
-)
-
-__all__ = [
-    "Element1D",
-    "Element2D",
-    "Element3D",
-    "ElementType1D",
-    "ElementType2D",
-    "ElementType3D",
-    "AxisType",
-    "Axis",
-    "Node",
-    "Restraint",
-    "Load",
-    "LoadType",
-    "ActionType",
-    "BeamLoadType",
-    "FaceLoadType",
-    "LoadDirection",
-    "LoadDirection2D",
-    "LoadAxisType",
-    "CombinationType",
-    "LoadBeam",
-    "LoadCase",
-    "LoadCombinations",
-    "LoadFace",
-    "LoadGravity",
-    "LoadNode",
-    "Model",
-    "ModelInfo",
-    "ModelSettings",
-    "ModelUnits",
-    "MaterialType",
-    "Concrete",
-    "StructuralMaterial",
-    "Steel",
-    "Timber",
-    "Property",
-    "Property1D",
-    "Property2D",
-    "Property3D",
-    "PropertyDamper",
-    "PropertyMass",
-    "PropertySpring",
-    "SectionProfile",
-    "MemberType",
-    "BaseReferencePoint",
-    "ReferenceSurface",
-    "PropertyType2D",
-    "PropertyType3D",
-    "ShapeType",
-    "PropertyTypeSpring",
-    "PropertyTypeDamper",
-    "ReferenceSurfaceEnum",
-    "shapeType",
-    "Result",
-    "Result1D",
-    "ResultSet1D",
-    "Result2D",
-    "ResultSet2D",
-    "Result3D",
-    "ResultSet3D",
-    "ResultGlobal",
-    "ResultSetNode",
-    "ResultNode",
-    "ResultSetAll",
-]
diff --git a/src/specklepy/objects_v2/structural/analysis.py b/src/specklepy/objects_v2/structural/analysis.py
deleted file mode 100644
index ee82eead..00000000
--- a/src/specklepy/objects_v2/structural/analysis.py
+++ /dev/null
@@ -1,49 +0,0 @@
-from typing import List, Optional
-
-from specklepy.objects.base import Base
-
-STRUCTURAL_ANALYSIS = "Objects.Structural.Analysis."
-
-
-class ModelUnits(Base, speckle_type=STRUCTURAL_ANALYSIS + "ModelUnits"):
-    length: Optional[str] = None
-    sections: Optional[str] = None
-    displacements: Optional[str] = None
-    stress: Optional[str] = None
-    force: Optional[str] = None
-    mass: Optional[str] = None
-    time: Optional[str] = None
-    temperature: Optional[str] = None
-    velocity: Optional[str] = None
-    acceleration: Optional[str] = None
-    energy: Optional[str] = None
-    angle: Optional[str] = None
-    strain: Optional[str] = None
-
-
-class ModelSettings(Base, speckle_type=STRUCTURAL_ANALYSIS + "ModelSettings"):
-    modelUnits: Optional[ModelUnits] = None
-    steelCode: Optional[str] = None
-    concreteCode: Optional[str] = None
-    coincidenceTolerance: float = 0.0
-
-
-class ModelInfo(Base, speckle_type=STRUCTURAL_ANALYSIS + "ModelInfo"):
-    name: Optional[str] = None
-    description: Optional[str] = None
-    projectNumber: Optional[str] = None
-    projectName: Optional[str] = None
-    settings: Optional[ModelSettings] = None
-    initials: Optional[str] = None
-    application: Optional[str] = None
-
-
-class Model(Base, speckle_type=STRUCTURAL_ANALYSIS + "Model"):
-    specs: Optional[ModelInfo] = None
-    nodes: Optional[List] = None
-    elements: Optional[List] = None
-    loads: Optional[List] = None
-    restraints: Optional[List] = None
-    properties: Optional[List] = None
-    materials: Optional[List] = None
-    layerDescription: Optional[str] = None
diff --git a/src/specklepy/objects_v2/structural/axis.py b/src/specklepy/objects_v2/structural/axis.py
deleted file mode 100644
index aa4408de..00000000
--- a/src/specklepy/objects_v2/structural/axis.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from enum import Enum
-from typing import Optional
-
-from specklepy.objects.base import Base
-from specklepy.objects.geometry import Plane
-
-
-class AxisType(int, Enum):
-    Cartesian = 0
-    Cylindrical = 1
-    Spherical = 2
-
-
-class Axis(Base, speckle_type="Objects.Structural.Geometry.Axis"):
-    name: Optional[str] = None
-    axisType: Optional[AxisType] = None
-    plane: Optional[Plane] = None
diff --git a/src/specklepy/objects_v2/structural/geometry.py b/src/specklepy/objects_v2/structural/geometry.py
deleted file mode 100644
index f232529b..00000000
--- a/src/specklepy/objects_v2/structural/geometry.py
+++ /dev/null
@@ -1,110 +0,0 @@
-from enum import Enum
-from typing import List, Optional
-
-from specklepy.objects.base import Base
-from specklepy.objects.geometry import Line, Mesh, Plane, Point, Vector
-from specklepy.objects.structural.axis import Axis
-from specklepy.objects.structural.properties import (
-    Property1D,
-    Property2D,
-    Property3D,
-    PropertyDamper,
-    PropertyMass,
-    PropertySpring,
-)
-
-STRUCTURAL_GEOMETRY = "Objects.Structural.Geometry"
-
-
-class ElementType1D(int, Enum):
-    Beam = 0
-    Brace = 1
-    Bar = 2
-    Column = 3
-    Rod = 4
-    Spring = 5
-    Tie = 6
-    Strut = 7
-    Link = 8
-    Damper = 9
-    Cable = 10
-    Spacer = 11
-    Other = 12
-    Null = 13
-
-
-class ElementType2D(int, Enum):
-    Quad4 = 0
-    Quad8 = 1
-    Triangle3 = 2
-    Triangle6 = 3
-
-
-class ElementType3D(int, Enum):
-    Brick8 = 0
-    Wedge6 = 1
-    Pyramid5 = 2
-    Tetra4 = 3
-
-
-class Restraint(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Restraint"):
-    code: Optional[str] = None
-    stiffnessX: float = 0.0
-    stiffnessY: float = 0.0
-    stiffnessZ: float = 0.0
-    stiffnessXX: float = 0.0
-    stiffnessYY: float = 0.0
-    stiffnessZZ: float = 0.0
-
-
-class Node(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Node"):
-    name: Optional[str] = None
-    basePoint: Optional[Point] = None
-    constraintAxis: Optional[Axis] = None
-    restraint: Optional[Restraint] = None
-    springProperty: Optional[PropertySpring] = None
-    massProperty: Optional[PropertyMass] = None
-    damperProperty: Optional[PropertyDamper] = None
-
-
-class Element1D(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Element1D"):
-    name: Optional[str] = None
-    baseLine: Optional[Line] = None
-    property: Optional[Property1D] = None
-    type: Optional[ElementType1D] = None
-    end1Releases: Optional[Restraint] = None
-    end2Releases: Optional[Restraint] = None
-    end1Offset: Optional[Vector] = None
-    end2Offset: Optional[Vector] = None
-    orientationNode: Optional[Node] = None
-    orinetationAngle: float = 0.0
-    localAxis: Optional[Plane] = None
-    parent: Optional[Base] = None
-    end1Node: Optional[Node] = None
-    end2Node: Optional[Node] = None
-    topology: Optional[List] = None
-    displayMesh: Optional[Mesh] = None
-
-
-class Element2D(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Element2D"):
-    name: Optional[str] = None
-    property: Optional[Property2D] = None
-    type: Optional[ElementType2D] = None
-    offset: float = 0.0
-    orientationAngle: float = 0.0
-    parent: Optional[Base] = None
-    topology: Optional[List] = None
-    displayMesh: Optional[Mesh] = None
-
-
-class Element3D(Base, speckle_type=STRUCTURAL_GEOMETRY + ".Element3D"):
-    name: Optional[str] = None
-    baseMesh: Optional[Mesh] = None
-    property: Optional[Property3D] = None
-    type: Optional[ElementType3D] = None
-    orientationAngle: float = 0.0
-    parent: Optional[Base] = None
-    topology: List
-
-
-# class Storey needs ependency on built elements first
diff --git a/src/specklepy/objects_v2/structural/loading.py b/src/specklepy/objects_v2/structural/loading.py
deleted file mode 100644
index 9e6f1e59..00000000
--- a/src/specklepy/objects_v2/structural/loading.py
+++ /dev/null
@@ -1,137 +0,0 @@
-from enum import Enum
-from typing import List, Optional
-
-from specklepy.objects.base import Base
-from specklepy.objects.geometry import Vector
-from specklepy.objects.structural.axis import Axis
-
-STRUCTURAL_LOADING = "Objects.Structural.Loading."
-
-
-class LoadType(int, Enum):
-    none = 0
-    Dead = 1
-    SuperDead = 2
-    Soil = 3
-    Live = 4
-    LiveRoof = 5
-    ReducibleLive = 6
-    Wind = 7
-    Snow = 8
-    Rain = 9
-    Thermal = 10
-    Notional = 11
-    Prestress = 12
-    Equivalent = 13
-    Accidental = 14
-    SeismicRSA = 15
-    SeismicAccTorsion = 16
-    SeismicStatic = 17
-    Other = 18
-
-
-class ActionType(int, Enum):
-    none = 0
-    Permanent = 1
-    Variable = 2
-    Accidental = 3
-
-
-class BeamLoadType(int, Enum):
-    Point = 0
-    Uniform = 1
-    Linear = 2
-    Patch = 3
-    TriLinear = 4
-
-
-class FaceLoadType(int, Enum):
-    Constant = 0
-    Variable = 1
-    Point = 2
-
-
-class LoadDirection2D(int, Enum):
-    X = 0
-    Y = 1
-    Z = 2
-
-
-class LoadDirection(int, Enum):
-    X = 0
-    Y = 1
-    Z = 2
-    XX = 3
-    YY = 4
-    ZZ = 5
-
-
-class LoadAxisType(int, Enum):
-    Global = 0
-    Local = 1  # local element axes
-    DeformedLocal = (
-        2  # element local axis that is embedded in the element as it deforms
-    )
-
-
-class CombinationType(int, Enum):
-    LinearAdd = 0
-    Envelope = 1
-    AbsoluteAdd = 2
-    SRSS = 3
-    RangeAdd = 4
-
-
-class LoadCase(Base, speckle_type=STRUCTURAL_LOADING + "LoadCase"):
-    name: Optional[str] = None
-    loadType: Optional[LoadType] = None
-    group: Optional[str] = None
-    actionType: Optional[ActionType] = None
-    description: Optional[str] = None
-
-
-class Load(Base, speckle_type=STRUCTURAL_LOADING + "Load"):
-    name: Optional[str] = None
-    loadCase: Optional[LoadCase] = None
-
-
-class LoadBeam(Load, speckle_type=STRUCTURAL_LOADING + "LoadBeam"):
-    elements: Optional[List] = None
-    loadType: Optional[BeamLoadType] = None
-    direction: Optional[LoadDirection] = None
-    loadAxis: Optional[Axis] = None
-    loadAxisType: Optional[LoadAxisType] = None
-    isProjected: Optional[bool] = None
-    values: Optional[List] = None
-    positions: Optional[List] = None
-
-
-class LoadCombinations(Base, speckle_type=STRUCTURAL_LOADING + "LoadCombination"):
-    name: Optional[str] = None
-    loadCases: List
-    loadFactors: List
-    combinationType: CombinationType
-
-
-class LoadFace(Load, speckle_type=STRUCTURAL_LOADING + "LoadFace"):
-    elements: Optional[List] = None
-    loadType: Optional[FaceLoadType] = None
-    direction: Optional[LoadDirection2D] = None
-    loadAxis: Optional[Axis] = None
-    loadAxisType: Optional[LoadAxisType] = None
-    isProjected: Optional[bool] = None
-    values: Optional[List] = None
-    positions: Optional[List] = None
-
-
-class LoadGravity(Load, speckle_type=STRUCTURAL_LOADING + "LoadGravity"):
-    elements: Optional[List] = None
-    nodes: Optional[List] = None
-    gravityFactors: Optional[Vector] = None
-
-
-class LoadNode(Load, speckle_type=STRUCTURAL_LOADING + "LoadNode"):
-    nodes: Optional[List] = None
-    loadAxis: Optional[Axis] = None
-    direction: Optional[LoadDirection] = None
-    value: float = 0.0
diff --git a/src/specklepy/objects_v2/structural/materials.py b/src/specklepy/objects_v2/structural/materials.py
deleted file mode 100644
index ab0abcda..00000000
--- a/src/specklepy/objects_v2/structural/materials.py
+++ /dev/null
@@ -1,61 +0,0 @@
-from enum import Enum
-from typing import Optional
-
-from specklepy.objects.base import Base
-
-STRUCTURAL_MATERIALS = "Objects.Structural.Materials"
-
-
-class MaterialType(int, Enum):
-    Concrete = 0
-    Steel = 1
-    Timber = 2
-    Aluminium = 3
-    Masonry = 4
-    FRP = 5
-    Glass = 6
-    Fabric = 7
-    Rebar = 8
-    Tendon = 9
-    ColdFormed = 10
-    Other = 11
-
-
-class StructuralMaterial(
-    Base, speckle_type=STRUCTURAL_MATERIALS + ".StructuralMaterial"
-):
-    name: Optional[str] = None
-    grade: Optional[str] = None
-    materialType: Optional[MaterialType] = None
-    designCode: Optional[str] = None
-    codeYear: Optional[str] = None
-    strength: float = 0.0
-    elasticModulus: float = 0.0
-    poissonsRatio: float = 0.0
-    shearModulus: float = 0.0
-    density: float = 0.0
-    thermalExpansivity: float = 0.0
-    dampingRatio: float = 0.0
-    cost: float = 0.0
-    materialSafetyFactor: float = 0.0
-
-
-class Concrete(StructuralMaterial):
-    compressiveStrength: float = 0.0
-    tensileStrength: float = 0.0
-    flexuralStrength: float = 0.0
-    maxCompressiveStrain: float = 0.0
-    maxTensileStrain: float = 0.0
-    maxAggregateSize: float = 0.0
-    lightweight: Optional[bool] = None
-
-
-class Steel(StructuralMaterial, speckle_type=STRUCTURAL_MATERIALS + ".Steel"):
-    yieldStrength: float = 0.0
-    ultimateStrength: float = 0.0
-    maxStrain: float = 0.0
-    strainHardeningModulus: float = 0.0
-
-
-class Timber(StructuralMaterial, speckle_type=STRUCTURAL_MATERIALS + ".Timber"):
-    species: Optional[str] = None
diff --git a/src/specklepy/objects_v2/structural/properties.py b/src/specklepy/objects_v2/structural/properties.py
deleted file mode 100644
index e0153a1e..00000000
--- a/src/specklepy/objects_v2/structural/properties.py
+++ /dev/null
@@ -1,212 +0,0 @@
-from enum import Enum
-from typing import Optional
-
-from specklepy.objects.base import Base
-from specklepy.objects.structural.axis import Axis
-from specklepy.objects.structural.materials import StructuralMaterial
-
-STRUCTURAL_PROPERTY = "Objects.Structural.Properties"
-
-
-class MemberType(int, Enum):
-    Beam = 0
-    Column = 1
-    Generic1D = 2
-    Slab = 3
-    Wall = 4
-    Generic2D = 5
-    VoidCutter1D = 6
-    VoidCutter2D = 7
-
-
-class BaseReferencePoint(int, Enum):
-    Centroid = 0
-    TopLeft = 1
-    TopCentre = 2
-    TopRight = 3
-    MidLeft = 4
-    MidRight = 5
-    BotLeft = 6
-    BotCentre = 7
-    BotRight = 8
-
-
-class ReferenceSurface(int, Enum):
-    Top = 0
-    Middle = 1
-    Bottom = 2
-
-
-class PropertyType2D(int, Enum):
-    Stress = 0
-    Fabric = 1
-    Plate = 2
-    Shell = 3
-    Curved = 4
-    Wall = 5
-    Strain = 6
-    Axi = 7
-    Load = 8
-
-
-class PropertyType3D(int, Enum):
-    Solid = 0
-    Infinite = 1
-
-
-class ShapeType(int, Enum):
-    Rectangular = 0
-    Circular = 1
-    I = 2  # noqa: E741
-    Tee = 3
-    Angle = 4
-    Channel = 5
-    Perimeter = 6
-    Box = 7
-    Catalogue = 8
-    Explicit = 9
-    Undefined = 10
-
-
-class PropertyTypeSpring(int, Enum):
-    Axial = 0
-    Torsional = 1
-    General = 2
-    Matrix = 3
-    TensionOnly = 4
-    CompressionOnly = 5
-    Connector = 6
-    LockUp = 7
-    Gap = 8
-    Friction = 9
-
-
-class PropertyTypeDamper(int, Enum):
-    Axial = 0
-    Torsional = 1
-    General = 2
-
-
-class Property(Base, speckle_type=STRUCTURAL_PROPERTY):
-    name: Optional[str] = None
-
-
-class SectionProfile(
-    Base, speckle_type=STRUCTURAL_PROPERTY + ".Profiles.SectionProfile"
-):
-    name: Optional[str] = None
-    shapeType: Optional[ShapeType] = None
-    area: float = 0.0
-    Iyy: float = 0.0
-    Izz: float = 0.0
-    J: float = 0.0
-    Ky: float = 0.0
-    weight: float = 0.0
-
-
-class Property1D(Property, speckle_type=STRUCTURAL_PROPERTY + ".Property1D"):
-    memberType: Optional[MemberType] = None
-    material: Optional[StructuralMaterial] = None
-    profile: Optional[SectionProfile] = None
-    referencePoint: Optional[BaseReferencePoint] = None
-    offsetY: float = 0.0
-    offsetZ: float = 0.0
-
-
-class Property2D(Property, speckle_type=STRUCTURAL_PROPERTY + ".Property2D"):
-    type: Optional[PropertyType2D] = None
-    thickness: float = 0.0
-    material: Optional[StructuralMaterial] = None
-    orientationAxis: Optional[Axis] = None
-    refSurface: Optional[ReferenceSurface] = None
-    zOffset: float = 0.0
-    modifierInPlane: float = 0.0
-    modifierBending: float = 0.0
-    modifierShear: float = 0.0
-    modifierVolume: float = 0.0
-
-
-class Property3D(Property, speckle_type=STRUCTURAL_PROPERTY + ".Property3D"):
-    type: Optional[PropertyType3D] = None
-    material: Optional[StructuralMaterial] = None
-    orientationAxis: Optional[Axis] = None
-
-
-class PropertyDamper(Property, speckle_type=STRUCTURAL_PROPERTY + ".PropertyDamper"):
-    damperType: Optional[PropertyTypeDamper] = None
-    dampingX: float = 0.0
-    dampingY: float = 0.0
-    dampingZ: float = 0.0
-    dampingXX: float = 0.0
-    dampingYY: float = 0.0
-    dampingZZ: float = 0.0
-
-
-class PropertyMass(Property, speckle_type=STRUCTURAL_PROPERTY + ".PropertyMass"):
-    mass: float = 0.0
-    inertiaXX: float = 0.0
-    inertiaYY: float = 0.0
-    inertiaZZ: float = 0.0
-    inertiaXY: float = 0.0
-    inertiaYZ: float = 0.0
-    inertiaZX: float = 0.0
-    massModified: Optional[bool] = None
-    massModifierX: float = 0.0
-    massModifierY: float = 0.0
-    massModifierZ: float = 0.0
-
-
-class PropertySpring(Property, speckle_type=STRUCTURAL_PROPERTY + ".PropertySpring"):
-    springType: Optional[PropertyTypeSpring] = None
-    springCurveX: float = 0.0
-    stiffnessX: float = 0.0
-    springCurveY: float = 0.0
-    stiffnessY: float = 0.0
-    springCurveZ: float = 0.0
-    stiffnessZ: float = 0.0
-    springCurveXX: float = 0.0
-    stiffnessXX: float = 0.0
-    springCurveYY: float = 0.0
-    stiffnessYY: float = 0.0
-    springCurveZZ: float = 0.0
-    stiffnessZZ: float = 0.0
-    dampingRatio: float = 0.0
-    dampingX: float = 0.0
-    dampingY: float = 0.0
-    dampingZ: float = 0.0
-    dampingXX: float = 0.0
-    dampingYY: float = 0.0
-    dampingZZ: float = 0.0
-    matrix: float = 0.0
-    postiveLockup: float = 0.0
-    frictionCoefficient: float = 0.0
-
-
-class ReferenceSurfaceEnum(int, Enum):
-    Concrete = 0
-    Steel = 1
-    Timber = 2
-    Aluminium = 3
-    Masonry = 4
-    FRP = 5
-    Glass = 6
-    Fabric = 7
-    Rebar = 8
-    Tendon = 9
-    ColdFormed = 10
-    Other = 11
-
-
-class shapeType(int, Enum):
-    Concrete = 0
-    Steel = 1
-    Timber = 2
-    Aluminium = 3
-    Masonry = 4
-    FRP = 5
-    Glass = 6
-    Fabric = 7
-    Rebar = 8
-    Tendon = 9
-    ColdFormed = 10
-    Other = 11
diff --git a/src/specklepy/objects_v2/structural/results.py b/src/specklepy/objects_v2/structural/results.py
deleted file mode 100644
index d014f458..00000000
--- a/src/specklepy/objects_v2/structural/results.py
+++ /dev/null
@@ -1,172 +0,0 @@
-from typing import List, Optional
-
-from specklepy.objects.base import Base
-from specklepy.objects.structural.analysis import Model
-from specklepy.objects.structural.geometry import Element1D, Element2D, Element3D, Node
-
-STRUCTURAL_RESULTS = "Objects.Structural.Results."
-
-
-class Result(Base, speckle_type=STRUCTURAL_RESULTS + "Result"):
-    resultCase: Optional[Base] = None
-    permutation: Optional[str] = None
-    description: Optional[str] = None
-
-
-class ResultSet1D(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSet1D"):
-    results1D: List
-
-
-class Result1D(Result, speckle_type=STRUCTURAL_RESULTS + "Result1D"):
-    element: Optional[Element1D] = None
-    position: Optional[float] = None
-    dispX: Optional[float] = None
-    dispY: Optional[float] = None
-    dispZ: Optional[float] = None
-    rotXX: Optional[float] = None
-    rotYY: Optional[float] = None
-    rotZZ: Optional[float] = None
-    forceX: Optional[float] = None
-    forceY: Optional[float] = None
-    forceZ: Optional[float] = None
-    momentXX: Optional[float] = None
-    momentYY: Optional[float] = None
-    momentZZ: Optional[float] = None
-    axialStress: Optional[float] = None
-    shearStressY: Optional[float] = None
-    shearStressZ: Optional[float] = None
-    bendingStressYPos: Optional[float] = None
-    bendingStressYNeg: Optional[float] = None
-    bendingStressZPos: Optional[float] = None
-    bendingStressZNeg: Optional[float] = None
-    combinedStressMax: Optional[float] = None
-    combinedStressMin: Optional[float] = None
-
-
-class ResultSet2D(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSet2D"):
-    results2D: List
-
-
-class Result2D(Result, speckle_type=STRUCTURAL_RESULTS + "Result2D"):
-    element: Optional[Element2D] = None
-    position: List
-    dispX: Optional[float] = None
-    dispY: Optional[float] = None
-    dispZ: Optional[float] = None
-    forceXX: Optional[float] = None
-    forceYY: Optional[float] = None
-    forceXY: Optional[float] = None
-    momentXX: Optional[float] = None
-    momentYY: Optional[float] = None
-    momentXY: Optional[float] = None
-    shearX: Optional[float] = None
-    shearY: Optional[float] = None
-    stressTopXX: Optional[float] = None
-    stressTopYY: Optional[float] = None
-    stressTopZZ: Optional[float] = None
-    stressTopXY: Optional[float] = None
-    stressTopYZ: Optional[float] = None
-    stressTopZX: Optional[float] = None
-    stressMidXX: Optional[float] = None
-    stressMidYY: Optional[float] = None
-    stressMidZZ: Optional[float] = None
-    stressMidXY: Optional[float] = None
-    stressMidYZ: Optional[float] = None
-    stressMidZX: Optional[float] = None
-    stressBotXX: Optional[float] = None
-    stressBotYY: Optional[float] = None
-    stressBotZZ: Optional[float] = None
-    stressBotXY: Optional[float] = None
-    stressBotYZ: Optional[float] = None
-    stressBotZX: Optional[float] = None
-
-
-class ResultSet3D(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSet3D"):
-    results3D: List
-
-
-class Result3D(Result, speckle_type=STRUCTURAL_RESULTS + "Result3D"):
-    element: Optional[Element3D] = None
-    position: List
-    dispX: Optional[float] = None
-    dispY: Optional[float] = None
-    dispZ: Optional[float] = None
-    stressXX: Optional[float] = None
-    stressYY: Optional[float] = None
-    stressZZ: Optional[float] = None
-    stressXY: Optional[float] = None
-    stressYZ: Optional[float] = None
-    stressZX: Optional[float] = None
-
-
-class ResultGlobal(Result, speckle_type=STRUCTURAL_RESULTS + "ResultGlobal"):
-    model: Optional[Model] = None
-    loadX: Optional[float] = None
-    loadY: Optional[float] = None
-    loadZ: Optional[float] = None
-    loadXX: Optional[float] = None
-    loadYY: Optional[float] = None
-    loadZZ: Optional[float] = None
-    reactionX: Optional[float] = None
-    reactionY: Optional[float] = None
-    reactionZ: Optional[float] = None
-    reactionXX: Optional[float] = None
-    reactionYY: Optional[float] = None
-    reactionZZ: Optional[float] = None
-    mode: Optional[float] = None
-    frequency: Optional[float] = None
-    loadFactor: Optional[float] = None
-    modalStiffness: Optional[float] = None
-    modalGeoStiffness: Optional[float] = None
-    effMassX: Optional[float] = None
-    effMassY: Optional[float] = None
-    effMassZ: Optional[float] = None
-    effMassXX: Optional[float] = None
-    effMassYY: Optional[float] = None
-    effMassZZ: Optional[float] = None
-
-
-class ResultSetNode(Result, speckle_type=STRUCTURAL_RESULTS + "ResultSetNode"):
-    resultsNode: List
-
-
-class ResultNode(Result, speckle_type=STRUCTURAL_RESULTS + " ResultNode"):
-    node: Optional[Node] = None
-    dispX: Optional[float] = None
-    dispY: Optional[float] = None
-    dispZ: Optional[float] = None
-    rotXX: Optional[float] = None
-    rotYY: Optional[float] = None
-    rotZZ: Optional[float] = None
-    reactionX: Optional[float] = None
-    reactionY: Optional[float] = None
-    reactionZ: Optional[float] = None
-    reactionXX: Optional[float] = None
-    reactionYY: Optional[float] = None
-    reactionZZ: Optional[float] = None
-    constraintX: Optional[float] = None
-    constraintY: Optional[float] = None
-    constraintZ: Optional[float] = None
-    constraintXX: Optional[float] = None
-    constraintYY: Optional[float] = None
-    constraintZZ: Optional[float] = None
-    velX: Optional[float] = None
-    velY: Optional[float] = None
-    velZ: Optional[float] = None
-    velXX: Optional[float] = None
-    velYY: Optional[float] = None
-    velZZ: Optional[float] = None
-    accX: Optional[float] = None
-    accY: Optional[float] = None
-    accZ: Optional[float] = None
-    accXX: Optional[float] = None
-    accYY: Optional[float] = None
-    accZZ: Optional[float] = None
-
-
-class ResultSetAll(Base, speckle_type=None):
-    resultSet1D: Optional[ResultSet1D] = None
-    resultSet2D: Optional[ResultSet2D] = None
-    resultSet3D: Optional[ResultSet3D] = None
-    resultsGlobal: Optional[ResultGlobal] = None
-    resultsNode: Optional[ResultSetNode] = None
diff --git a/src/specklepy/objects_v2/units.py b/src/specklepy/objects_v2/units.py
deleted file mode 100644
index 0afade75..00000000
--- a/src/specklepy/objects_v2/units.py
+++ /dev/null
@@ -1,124 +0,0 @@
-from enum import Enum
-from typing import Union
-
-from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
-
-__all__ = [
-    "Units",
-    "get_encoding_from_units",
-    "get_units_from_encoding",
-    "get_units_from_string",
-]
-
-
-class Units(Enum):
-    mm = "mm"
-    cm = "cm"
-    m = "m"
-    km = "km"
-    inches = "in"
-    feet = "ft"
-    yards = "yd"
-    miles = "mi"
-    none = "none"
-
-
-UNITS_STRINGS = {
-    Units.mm: ["mm", "mil", "millimeters", "millimetres"],
-    Units.cm: ["cm", "centimetre", "centimeter", "centimetres", "centimeters"],
-    Units.m: ["m", "meter", "meters", "metre", "metres"],
-    Units.km: ["km", "kilometer", "kilometre", "kilometers", "kilometres"],
-    Units.inches: ["in", "inch", "inches"],
-    Units.feet: ["ft", "foot", "feet"],
-    Units.yards: ["yd", "yard", "yards"],
-    Units.miles: ["mi", "mile", "miles"],
-    Units.none: ["none", "null"],
-}
-
-
-UNITS_ENCODINGS = {
-    Units.none: 0,
-    None: 0,
-    Units.mm: 1,
-    Units.cm: 2,
-    Units.m: 3,
-    Units.km: 4,
-    Units.inches: 5,
-    Units.feet: 6,
-    Units.yards: 7,
-    Units.miles: 8,
-}
-
-
-UNIT_SCALE = {
-    Units.none: 1,
-    Units.mm: 0.001,
-    Units.cm: 0.01,
-    Units.m: 1.0,
-    Units.km: 1000.0,
-    Units.inches: 0.0254,
-    Units.feet: 0.3048,
-    Units.yards: 0.9144,
-    Units.miles: 1609.340,
-}
-"""Unit scaling factor to meters"""
-
-
-def get_units_from_string(unit: str) -> Units:
-    if not isinstance(unit, str):
-        raise SpeckleInvalidUnitException(unit)
-    unit = str.lower(unit)
-    for name, alternates in UNITS_STRINGS.items():
-        if unit in alternates:
-            return name
-    raise SpeckleInvalidUnitException(unit)
-
-
-def get_units_from_encoding(unit: int) -> Units:
-    for name, encoding in UNITS_ENCODINGS.items():
-        if unit == encoding:
-            return name or Units.none
-
-    raise SpeckleException(
-        message=(
-            f"Could not understand what unit {unit} is referring to."
-            f"Please enter a valid unit encoding (eg {UNITS_ENCODINGS})."
-        )
-    )
-
-
-def get_encoding_from_units(unit: Union[Units, str, None]):
-    maybe_sanitized_unit = unit
-    if isinstance(unit, str):
-        for unit_enum, aliases in UNITS_STRINGS.items():
-            if unit in aliases:
-                maybe_sanitized_unit = unit_enum
-    try:
-        return UNITS_ENCODINGS[maybe_sanitized_unit]
-    except KeyError as e:
-        raise SpeckleException(
-            message=(
-                f"No encoding exists for unit {maybe_sanitized_unit}."
-                f"Please enter a valid unit to encode (eg {UNITS_ENCODINGS})."
-            )
-        ) from e
-
-
-def get_scale_factor_from_string(fromUnits: str, toUnits: str) -> float:
-    """Returns a scalar to convert distance values from one unit system to another"""
-    return get_scale_factor(
-        get_units_from_string(fromUnits), get_units_from_string(toUnits)
-    )
-
-
-def get_scale_factor(fromUnits: Units, toUnits: Units) -> float:
-    """Returns a scalar to convert distance values from one unit system to another"""
-    return get_scale_factor_to_meters(fromUnits) / get_scale_factor_to_meters(toUnits)
-
-
-def get_scale_factor_to_meters(fromUnits: Units) -> float:
-    """Returns a scalar to convert distance values from one unit system to meters"""
-    if fromUnits not in UNIT_SCALE:
-        raise ValueError(f"Invalid units provided: {fromUnits}")
-
-    return UNIT_SCALE[fromUnits]
diff --git a/tests/integration/client/deprecated/test_objects.py b/tests/integration/client/deprecated/test_objects.py
deleted file mode 100644
index f921ee66..00000000
--- a/tests/integration/client/deprecated/test_objects.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import pytest
-
-from specklepy.api.models import Stream
-from specklepy.objects import Base
-from specklepy.objects.encoding import ObjectArray
-from specklepy.serialization.base_object_serializer import BaseObjectSerializer
-from specklepy.transports.sqlite import SQLiteTransport
-
-
-class TestObject:
-    @pytest.fixture(scope="module")
-    def stream(self, client):
-        stream = Stream(
-            name="a sample stream for testing",
-            description="a stream created for testing",
-            isPublic=True,
-        )
-        stream.id = client.stream.create(
-            stream.name, stream.description, stream.isPublic
-        )
-        return stream
-
-    def test_object_create(self, client, stream, base):
-        transport = SQLiteTransport()
-        s = BaseObjectSerializer(write_transports=[transport], read_transport=transport)
-        _, base_dict = s.traverse_base(base)
-        obj_id = client.object.create(stream_id=stream.id, objects=[base_dict])[0]
-
-        assert isinstance(obj_id, str)
-        assert base_dict["@detach"]["speckle_type"] == "reference"
-        assert obj_id == base.get_id(True)
-
-    def test_object_get(self, client, stream, base):
-        fetched_base = client.object.get(
-            stream_id=stream.id, object_id=base.get_id(True)
-        )
-
-        assert isinstance(fetched_base, Base)
-        assert fetched_base.name == base.name
-        assert isinstance(fetched_base.vertices, list)
-        # assert fetched_base["@detach"]["speckle_type"] == "reference"
-
-    def test_object_array_decoder(self):
-        array = ObjectArray()
-        array.data = [5, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1, 1]
-
-        assert array.decode(decoder=sum) == [5, 4, 3, 2, 1]
diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
index 10a24360..cf78bef4 100644
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -12,7 +12,7 @@
 from specklepy.core.api.models import Stream, Version
 from specklepy.logging import metrics
 from specklepy.objects.base import Base
-from specklepy.objects.fakemesh import FakeDirection, FakeMesh
+from .fakemesh import FakeMesh, FakeDirection
 from specklepy.objects.geometry import Point
 from specklepy.transports.server.server import ServerTransport
 
@@ -44,7 +44,8 @@ def seed_user(host: str) -> Dict[str, str]:
     if not r.ok:
         raise Exception(f"Cannot seed user: {r.reason}")
     redirect_url = urlparse(r.headers.get("location"))
-    access_code = parse_qs(redirect_url.query)["access_code"][0]  # type: ignore
+    access_code = parse_qs(redirect_url.query)[
+        "access_code"][0]  # type: ignore
 
     r_tokens = requests.post(
         url=f"http://{host}/auth/token",
@@ -113,7 +114,8 @@ def sample_stream(client: SpeckleClient) -> Stream:
         description="a stream created for testing",
         isPublic=True,
     )
-    stream.id = client.stream.create(stream.name, stream.description, stream.isPublic)
+    stream.id = client.stream.create(
+        stream.name, stream.description, stream.isPublic)
     return stream
 
 
diff --git a/src/specklepy/objects_v2/fakemesh.py b/tests/integration/fakemesh.py
similarity index 97%
rename from src/specklepy/objects_v2/fakemesh.py
rename to tests/integration/fakemesh.py
index dfa43448..5e0d646a 100644
--- a/src/specklepy/objects_v2/fakemesh.py
+++ b/tests/integration/fakemesh.py
@@ -3,7 +3,7 @@
 
 from specklepy.objects.geometry import Point
 
-from .base import Base
+from specklepy.objects.base import Base
 
 CHUNKABLE_PROPS = {
     "vertices": 100,
diff --git a/tests/integration/test_serialization.py b/tests/integration/test_serialization.py
index 85bcd927..8c2e2603 100644
--- a/tests/integration/test_serialization.py
+++ b/tests/integration/test_serialization.py
@@ -3,8 +3,8 @@
 import pytest
 
 from specklepy.api import operations
-from specklepy.objects import Base
-from specklepy.objects.fakemesh import FakeMesh
+from specklepy.objects.base import Base
+from .fakemesh import FakeMesh
 from specklepy.objects.geometry import Point
 from specklepy.transports.memory import MemoryTransport
 from specklepy.transports.server import ServerTransport
diff --git a/tests/unit/test_base.py b/tests/unit/test_base.py
index cf4af535..ede149d0 100644
--- a/tests/unit/test_base.py
+++ b/tests/unit/test_base.py
@@ -6,8 +6,8 @@
 
 from specklepy.api import operations
 from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException
-from specklepy.objects_v2.base import Base
-from specklepy.objects_v2.units import Units
+from specklepy.objects.base import Base
+from specklepy.objects.models.units import Units
 
 
 @pytest.mark.parametrize(
diff --git a/tests/unit/test_geometry.py b/tests/unit/test_geometry.py
deleted file mode 100644
index ad3da59a..00000000
--- a/tests/unit/test_geometry.py
+++ /dev/null
@@ -1,523 +0,0 @@
-# pylint: disable=redefined-outer-name
-import json
-
-import pytest
-
-from specklepy.api import operations
-from specklepy.logging.exceptions import SpeckleException
-from specklepy.objects.base import Base
-from specklepy.objects_v2.encoding import CurveArray, ObjectArray
-from specklepy.objects_v2.geometry import (
-    Arc,
-    Box,
-    Brep,
-    BrepEdge,
-    BrepFace,
-    BrepLoop,
-    BrepLoopType,
-    BrepTrim,
-    BrepTrimType,
-    Circle,
-    Curve,
-    Ellipse,
-    Interval,
-    Line,
-    Mesh,
-    Plane,
-    Point,
-    Polycurve,
-    Polyline,
-    Surface,
-    Vector,
-)
-from specklepy.objects_v2.units import Units
-from specklepy.transports.memory import MemoryTransport
-
-
-@pytest.fixture()
-def interval():
-    return Interval(start=0, end=5)
-
-
-@pytest.fixture()
-def point():
-    return Point(x=1, y=10, z=0)
-
-
-@pytest.fixture()
-def vector():
-    return Vector(x=1, y=32, z=10)
-
-
-@pytest.fixture()
-def plane(point, vector):
-    return Plane(origin=point, normal=vector, xdir=vector, ydir=vector, units="m")
-
-
-@pytest.fixture()
-def box(plane, interval):
-    return Box(
-        basePlane=plane,
-        ySize=interval,
-        zSize=interval,
-        xSize=interval,
-        area=20.4,
-        volume=44.2,
-    )
-
-
-@pytest.fixture()
-def line(point, interval):
-    return Line(
-        start=point,
-        end=point,
-        domain=interval,
-        units="none",
-        # These attributes are not handled in C#
-        # bbox=None,
-        # length=None
-    )
-
-
-@pytest.fixture()
-def arc(plane, interval, point):
-    return Arc(
-        radius=2.3,
-        startAngle=22.1,
-        endAngle=44.5,
-        angleRadians=33,
-        plane=plane,
-        domain=interval,
-        units="m",
-        startPoint=point,
-        midPoint=point,
-        endPoint=point,
-        # These attributes are not handled in C#
-        # bbox=None,
-        # area=None,
-        # length=None,
-    )
-
-
-@pytest.fixture()
-def circle(plane, interval):
-    return Circle(
-        radius=22,
-        plane=plane,
-        domain=interval,
-        units="m",
-        # These attributes are not handled in C#
-        # bbox=None,
-        # area=None,
-        # length=None,
-    )
-
-
-@pytest.fixture()
-def ellipse(plane, interval):
-    return Ellipse(
-        firstRadius=34,
-        secondRadius=22,
-        plane=plane,
-        domain=interval,
-        units="m",
-        # These attributes are not handled in C#
-        # trimDomain=None,
-        # bbox=None,
-        # area=None,
-        # length=None,
-    )
-
-
-@pytest.fixture()
-def polyline(interval):
-    return Polyline(
-        value=[22, 44, 54.3, 99, 232, 21],
-        closed=True,
-        domain=interval,
-        units="m",
-        # These attributes are not handled in C#
-        # bbox=None,
-        # area=None,
-        # length=None,
-    )
-
-
-@pytest.fixture()
-def curve(interval):
-    return Curve(
-        degree=90,
-        periodic=True,
-        rational=False,
-        closed=True,
-        domain=interval,
-        points=[23, 21, 44, 43, 56, 76, 1, 3, 2],
-        weights=[23, 11, 23],
-        knots=[22, 45, 76, 11],
-        units="m",
-        # These attributes are not handled in C#
-        # displayValue=None,
-        # bbox=None,
-        # area=None,
-        # length=None,
-    )
-
-
-@pytest.fixture()
-def polycurve(interval, curve, polyline):
-    return Polycurve(
-        segments=[curve, polyline],
-        domain=interval,
-        closed=True,
-        units="m",
-        # These attributes are not handled in C#
-        # bbox=None,
-        # area=None,
-        # length=None
-    )
-
-
-@pytest.fixture()
-def mesh(box):
-    return Mesh(
-        vertices=[2, 1, 2, 4, 77.3, 5, 33, 4, 2],
-        faces=[1, 2, 3, 4, 5, 6, 7],
-        colors=[111, 222, 333, 444, 555, 666, 777],
-        bbox=box,
-        area=233,
-        volume=232.2,
-    )
-
-
-@pytest.fixture()
-def surface(interval):
-    return Surface(
-        degreeU=33,
-        degreeV=44,
-        rational=True,
-        pointData=[1, 2.2, 3, 4, 5, 6, 7, 8, 9],
-        countU=3,
-        countV=4,
-        closedU=True,
-        closedV=False,
-        domainU=interval,
-        domainV=interval,
-        knotsU=[1.1, 2.2, 3.3, 4.4],
-        knotsV=[9, 8, 7, 6, 5, 4.4],
-        units="m",
-        # These attributes are not handled in C#
-        # bbox=None,
-        # area=None,
-    )
-
-
-@pytest.fixture()
-def brep_face():
-    return BrepFace(
-        SurfaceIndex=3,
-        LoopIndices=[1, 2, 3, 4],
-        OuterLoopIndex=2,
-        OrientationReversed=False,
-    )
-
-
-@pytest.fixture()
-def brep_edge(interval):
-    return BrepEdge(
-        Curve3dIndex=2,
-        TrimIndices=[4, 5, 6, 7],
-        StartIndex=2,
-        EndIndex=6,
-        ProxyCurveIsReversed=True,
-        Domain=interval,
-    )
-
-
-@pytest.fixture()
-def brep_loop():
-    return BrepLoop(FaceIndex=5, TrimIndices=[3, 4, 5], Type=BrepLoopType.Unknown)
-
-
-@pytest.fixture()
-def brep_trim():
-    return BrepTrim(
-        EdgeIndex=3,
-        StartIndex=4,
-        EndIndex=6,
-        FaceIndex=1,
-        LoopIndex=4,
-        CurveIndex=7,
-        IsoStatus=6,
-        TrimType=BrepTrimType.Mated,
-        IsReversed=False,
-        # These attributes are not handled in C#
-        # Domain=None,
-    )
-
-
-@pytest.fixture
-def brep(
-    mesh,
-    box,
-    surface,
-    curve,
-    polyline,
-    circle,
-    point,
-    brep_edge,
-    brep_loop,
-    brep_trim,
-    brep_face,
-):
-    return Brep(
-        provenance="pytest",
-        bbox=box,
-        area=32,
-        volume=54,
-        displayValue=mesh,
-        Surfaces=[surface, surface, surface],
-        Curve3D=[curve, polyline],
-        Curve2D=[circle],
-        Vertices=[point, point, point, point],
-        Edges=[brep_edge],
-        Loops=[brep_loop, brep_loop],
-        Trims=[brep_trim],
-        Faces=[brep_face, brep_face],
-        IsClosed=False,
-        Orientation=3,
-    )
-
-
-@pytest.fixture
-def geometry_objects_dict(
-    point,
-    vector,
-    plane,
-    line,
-    arc,
-    circle,
-    ellipse,
-    polyline,
-    curve,
-    polycurve,
-    surface,
-    brep_trim,
-):
-    return {
-        "point": point,
-        "vector": vector,
-        "plane": plane,
-        "line": line,
-        "arc": arc,
-        "circle": circle,
-        "ellipse": ellipse,
-        "polyline": polyline,
-        "curve": curve,
-        "polycurve": polycurve,
-        "surface": surface,
-        "brep_trim": brep_trim,
-    }
-
-
-@pytest.mark.parametrize(
-    "object_name",
-    [
-        "point",
-        "vector",
-        "plane",
-        "line",
-        "arc",
-        "circle",
-        "ellipse",
-        "polyline",
-        "curve",
-        "polycurve",
-        "surface",
-        "brep_trim",
-    ],
-)
-def test_to_and_from_list(object_name: str, geometry_objects_dict):
-    obj = geometry_objects_dict[object_name]
-    assert hasattr(obj, "to_list")
-    assert hasattr(obj, "from_list")
-
-    chunks = obj.to_list()
-    assert isinstance(chunks, list)
-
-    object_class = obj.__class__
-    decoded_object: Base = object_class.from_list(chunks)
-    assert decoded_object.get_id() == obj.get_id()
-
-
-def test_brep_surfaces_value_serialization(surface):
-    brep = Brep()
-    assert brep.Surfaces is None
-    assert brep.SurfacesValue is None
-    brep.Surfaces = [surface, surface]
-    assert brep.SurfacesValue == ObjectArray.from_objects([surface, surface]).data
-
-    brep.SurfacesValue = ObjectArray.from_objects([surface]).data
-    assert len(brep.Surfaces) == 1
-    assert brep.Surfaces[0].get_id() == surface.get_id()
-
-
-def test_brep_curve2d_values_serialization(curve, polyline, circle):
-    brep = Brep()
-    assert brep.Curve2D is None
-    assert brep.Curve2DValues is None
-    brep.Curve2D = [curve, polyline]
-    assert brep.Curve2DValues == CurveArray.from_curves([curve, polyline]).data
-
-    brep.Curve2DValues = CurveArray.from_curves([circle]).data
-    assert len(brep.Curve2D) == 1
-    assert brep.Curve2D[0].get_id() == circle.get_id()
-
-
-def test_brep_curve3d_values_serialization(curve, polyline, circle):
-    brep = Brep()
-    assert brep.Curve3D is None
-    assert brep.Curve3DValues is None
-    brep.Curve3D = [curve, polyline]
-    assert brep.Curve3DValues == CurveArray.from_curves([curve, polyline]).data
-
-    brep.Curve3DValues = CurveArray.from_curves([circle]).data
-    assert len(brep.Curve3D) == 1
-    assert brep.Curve3D[0].get_id() == circle.get_id()
-
-
-def test_brep_vertices_values_serialization():
-    brep = Brep()
-    brep.VerticesValue = [1, 1, 1, 1, 2, 2, 2, 3, 3, 3]
-    assert brep.Vertices[0].get_id() == Point(x=1, y=1, z=1, units=Units.mm).get_id()
-    assert brep.Vertices[1].get_id() == Point(x=2, y=2, z=2, units=Units.mm).get_id()
-    assert brep.Vertices[2].get_id() == Point(x=3, y=3, z=3, units=Units.mm).get_id()
-
-
-def test_trims_value_serialization():
-    brep = Brep()
-    brep.TrimsValue = [
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        1,
-        1,
-        0,
-        1,
-        0,
-        0,
-        0,
-        0,
-        1,
-        2,
-        1,
-        1,
-    ]
-
-    assert (
-        brep.Trims[0].get_id()
-        == BrepTrim(
-            EdgeIndex=0,
-            StartIndex=0,
-            EndIndex=0,
-            FaceIndex=0,
-            LoopIndex=0,
-            CurveIndex=0,
-            IsoStatus=1,
-            TrimType=BrepTrimType.Boundary,
-            IsReversed=False,
-        ).get_id()
-    )
-
-    assert (
-        brep.Trims[1].get_id()
-        == BrepTrim(
-            EdgeIndex=1,
-            StartIndex=0,
-            EndIndex=0,
-            FaceIndex=0,
-            LoopIndex=0,
-            CurveIndex=1,
-            IsoStatus=2,
-            TrimType=BrepTrimType.Boundary,
-            IsReversed=True,
-        ).get_id()
-    )
-
-
-def test_loops_value_serialization():
-    brep = Brep()
-    brep.LoopsValue = [6, 0, 1, 0, 1, 2, 3]
-
-    assert brep == brep.Loops[0]._Brep  # pylint: disable=protected-access
-    assert (
-        brep.Loops[0].get_id()
-        == BrepLoop(
-            FaceIndex=0, Type=BrepLoopType(1), TrimIndices=[0, 1, 2, 3]
-        ).get_id()
-    )
-
-
-def test_edges_value_serialization():
-    brep = Brep()
-    brep.EdgesValue = [8, 0, 0, 1, 0, -8.13345756858629, 8.13345756858629, 1, 3]
-
-    assert brep == brep.Edges[0]._Brep  # pylint: disable=protected-access
-    assert (
-        brep.Edges[0].get_id()
-        == BrepEdge(
-            Curve3dIndex=0,
-            StartIndex=0,
-            EndIndex=1,
-            ProxyCurveIsReversed=False,
-            Domain=Interval(start=-8.13345756858629, end=8.13345756858629),
-            TrimIndices=[1, 3],
-        ).get_id()
-    )
-
-
-def test_faces_value_serialization():
-    brep = Brep()
-    brep.FacesValue = [4, 0, 0, 1, 0]
-
-    assert brep == brep.Faces[0]._Brep  # pylint: disable=protected-access
-    assert (
-        brep.Faces[0].get_id()
-        == BrepFace(
-            SurfaceIndex=0, OuterLoopIndex=0, OrientationReversed=True, LoopIndices=[0]
-        ).get_id()
-    )
-
-
-def test_serialized_brep_attributes(brep: Brep):
-    transport = MemoryTransport()
-    serialized = operations.serialize(brep, [transport])
-    serialized_dict = json.loads(serialized)
-
-    removed_keys = [
-        "Surfaces",
-        "Curve3D",
-        "Curve2D",
-        "Vertices",
-        "Trims",
-        "Loops",
-        "Edges",
-        "Faces",
-    ]
-
-    for k in removed_keys:
-        assert k not in serialized_dict
-
-
-def test_mesh_create():
-    vertices = [2, 1, 2, 4, 77.3, 5, 33, 4, 2]
-    faces = [1, 2, 3, 4, 5, 6, 7]
-    mesh = Mesh.create(vertices, faces)
-
-    with pytest.raises(SpeckleException):
-        bad_mesh = Mesh.create(vertices=7, faces=faces)  # noqa: F841
-
-    assert mesh.vertices == vertices
-    assert mesh.textureCoordinates == []
diff --git a/tests/unit/test_graph_traversal.py b/tests/unit/test_graph_traversal.py
index 9fb37d96..005f3084 100644
--- a/tests/unit/test_graph_traversal.py
+++ b/tests/unit/test_graph_traversal.py
@@ -2,8 +2,8 @@
 from typing import Dict, List, Optional
 from unittest import TestCase
 
-from specklepy.objects_v2 import Base
-from specklepy.objects_v2.graph_traversal.traversal import GraphTraversal, TraversalRule
+from specklepy.objects.base import Base
+from specklepy.objects.graph_traversal.traversal import GraphTraversal, TraversalRule
 
 
 @dataclass()
@@ -100,6 +100,7 @@ def test_traverse_dynamic(self):
             for context in GraphTraversal([traverse_lists_rule]).traverse(test_case)
         ]
 
-        self.assertCountEqual(ret, [test_case, expected_traverse, expected_traverse])
+        self.assertCountEqual(
+            ret, [test_case, expected_traverse, expected_traverse])
         self.assertNotIn(expected_ignore, ret)
         self.assertEqual(len(ret), 3)
diff --git a/tests/unit/test_registering_base.py b/tests/unit/test_registering_base.py
index 65639b06..1ad096b4 100644
--- a/tests/unit/test_registering_base.py
+++ b/tests/unit/test_registering_base.py
@@ -2,8 +2,7 @@
 
 import pytest
 
-from specklepy.objects_v2.base import Base
-from specklepy.objects_v2.structural import Concrete
+from specklepy.objects.base import Base
 
 
 class Foo(Base):
@@ -28,10 +27,6 @@ class Baz(Bar):
             Baz,
             "Tests.Unit.TestRegisteringBase.Foo:Custom.Bar:Tests.Unit.TestRegisteringBase.Baz",
         ),
-        (
-            Concrete,
-            "Objects.Structural.Materials.StructuralMaterial:Objects.Structural.Materials.Concrete",
-        ),
     ],
 )
 def test_determine_speckle_type(klass: Type[Base], speckle_type: str):
@@ -43,7 +38,6 @@ def test_determine_speckle_type(klass: Type[Base], speckle_type: str):
     [
         (Base, "Base"),
         (Foo, "Tests.Unit.TestRegisteringBase.Foo"),
-        (Concrete, "Objects.Structural.Materials.Concrete"),
     ],
 )
 def test_full_name(klass: Type[Base], fully_qualified_name: str):
diff --git a/tests/unit/test_structural.py b/tests/unit/test_structural.py
deleted file mode 100644
index 0064a588..00000000
--- a/tests/unit/test_structural.py
+++ /dev/null
@@ -1,143 +0,0 @@
-import pytest
-
-from specklepy.objects_v2.geometry import Line, Mesh, Point, Vector
-from specklepy.objects_v2.structural.analysis import Model
-from specklepy.objects_v2.structural.geometry import (
-    Element1D,
-    Element2D,
-    ElementType1D,
-    ElementType2D,
-    Node,
-    Restraint,
-)
-from specklepy.objects_v2.structural.loading import LoadGravity
-from specklepy.objects_v2.structural.materials import StructuralMaterial
-from specklepy.objects_v2.structural.properties import (
-    MemberType,
-    Property1D,
-    Property2D,
-    SectionProfile,
-    ShapeType,
-)
-
-
-@pytest.fixture()
-def point():
-    return Point(x=1, y=10, z=0)
-
-
-@pytest.fixture()
-def vector():
-    return Vector(x=0, y=0, z=-1)
-
-
-@pytest.fixture()
-def line(point, interval):
-    return Line(
-        start=point,
-        end=point,
-        domain=interval,
-        # These attributes are not handled in C#
-        # bbox=None,
-        # length=None
-    )
-
-
-@pytest.fixture()
-def mesh(box):
-    return Mesh(
-        vertices=[2, 1, 2, 4, 77.3, 5, 33, 4, 2],
-        faces=[1, 2, 3, 4, 5, 6, 7],
-        colors=[111, 222, 333, 444, 555, 666, 777],
-        bbox=box,
-        area=233,
-        volume=232.2,
-    )
-
-
-@pytest.fixture()
-def restraint():
-    return Restraint(code="FFFFFF")
-
-
-@pytest.fixture()
-def node(restraint, point):
-    return Node(basePoint=point, restraint=restraint, name="node1")
-
-
-@pytest.fixture()
-def material():
-    return StructuralMaterial(name="TestMaterial")
-
-
-@pytest.fixture()
-def memberType():
-    return MemberType(0)
-
-
-@pytest.fixture()
-def shapeType():
-    return ShapeType(8)
-
-
-@pytest.fixture()
-def sectionProfile(shapeType):
-    return SectionProfile(name="Test", shapeType=shapeType)
-
-
-@pytest.fixture()
-def property1D(memberType, sectionProfile, material):
-    return Property1D(
-        Material=material,
-        SectionProfile=sectionProfile,
-        memberType=memberType,
-    )
-
-
-@pytest.fixture()
-def elementType1D():
-    return ElementType1D(0)
-
-
-@pytest.fixture()
-def element1D(line, restraint, elementType1D, property1D):
-    return Element1D(
-        baseLine=line,
-        end1Releases=restraint,
-        end2Releases=restraint,
-        type=elementType1D,
-        property=property1D,
-    )
-
-
-@pytest.fixture()
-def property2D(material):
-    return Property2D(Material=material)
-
-
-@pytest.fixture()
-def elementType2D():
-    return ElementType2D(0)
-
-
-@pytest.fixture()
-def element2D(point, elementType2D):
-    return Element2D(
-        topology=[point],
-        type=elementType2D,
-    )
-
-
-@pytest.fixture()
-def loadGravity(element1D, element2D, vector):
-    return LoadGravity(elements=[element1D, element2D], gravityFactors=vector)
-
-
-@pytest.fixture()
-def model(loadGravity, element1D, element2D, material, property1D, property2D):
-    return Model(
-        loads=[loadGravity],
-        elements=[element1D, element2D],
-        materials=[material],
-        properties=[property1D, property2D],
-    )
diff --git a/tests/unit/test_transforms.py b/tests/unit/test_transforms.py
deleted file mode 100644
index ea85dd4c..00000000
--- a/tests/unit/test_transforms.py
+++ /dev/null
@@ -1,129 +0,0 @@
-from typing import List
-
-import pytest
-
-from specklepy.api import operations
-from specklepy.objects_v2.geometry import Point, Vector
-from specklepy.objects_v2.other import Transform
-
-
-@pytest.fixture()
-def point():
-    return Point(x=1, y=10, z=2)
-
-
-@pytest.fixture()
-def points():
-    return [Point(x=1 + i, y=10 + i, z=2 + i) for i in range(5)]
-
-
-@pytest.fixture()
-def point_value():
-    return [1, 10, 2]
-
-
-@pytest.fixture()
-def points_values():
-    coords = []
-    for i in range(5):
-        coords.extend([1 + i, 10 + i, 2 + 1])
-    return coords
-
-
-@pytest.fixture()
-def vector():
-    return Vector(x=1, y=10, z=2)
-
-
-@pytest.fixture()
-def vector_value():
-    return [1, 1, 2]
-
-
-@pytest.fixture()
-def transform():
-    """Translates to [1, 2, 0] and scales z by 0.5"""
-    return Transform.from_list(
-        [
-            1.0,
-            0.0,
-            0.0,
-            1.0,
-            0.0,
-            1.0,
-            0.0,
-            2.0,
-            0.0,
-            0.0,
-            0.5,
-            0.0,
-            0.0,
-            0.0,
-            0.0,
-            1.0,
-        ]
-    )
-
-
-def test_point_transform(point: Point, transform: Transform):
-    new_point = transform.apply_to_point(point)
-
-    assert new_point.x == point.x + 1
-    assert new_point.y == point.y + 2
-    assert new_point.z == point.z * 0.5
-
-
-def test_points_transform(points: List[Point], transform: Transform):
-    new_points = transform.apply_to_points(points)
-
-    for i, new_point in enumerate(new_points):
-        assert new_point.x == points[i].x + 1
-        assert new_point.y == points[i].y + 2
-        assert new_point.z == points[i].z * 0.5
-
-
-def test_point_value_transform(point_value: List[float], transform: Transform):
-    new_coords = transform.apply_to_point_value(point_value)
-
-    assert new_coords[0] == point_value[0] + 1
-    assert new_coords[1] == point_value[1] + 2
-    assert new_coords[2] == point_value[2] * 0.5
-
-
-def test_points_values_transform(points_values: List[float], transform: Transform):
-    new_coords = transform.apply_to_points_values(points_values)
-
-    for i in range(0, len(points_values), 3):
-        assert new_coords[i] == points_values[i] + 1
-        assert new_coords[i + 1] == points_values[i + 1] + 2
-        assert new_coords[i + 2] == points_values[i + 2] * 0.5
-
-
-def test_vector_transform(vector: Vector, transform: Transform):
-    new_vector = transform.apply_to_vector(vector)
-
-    assert new_vector.x == vector.x
-    assert new_vector.y == vector.y
-    assert new_vector.z == vector.z * 0.5
-
-
-def test_vector_value_transform(vector_value: List[float], transform: Transform):
-    new_coords = transform.apply_to_vector_value(vector_value)
-
-    assert new_coords[0] == vector_value[0]
-    assert new_coords[1] == vector_value[1]
-    assert new_coords[2] == vector_value[2] * 0.5
-
-
-def test_transform_fails_with_malformed_value():
-    with pytest.raises(ValueError):
-        Transform.from_list("asdf")
-    with pytest.raises(ValueError):
-        Transform.from_list([7, 8, 9])
-
-
-def test_transform_serialisation(transform: Transform):
-    serialized = operations.serialize(transform)
-    deserialized = operations.deserialize(serialized)
-
-    assert transform.get_id() == deserialized.get_id()
diff --git a/tests/unit/test_traverse_value.py b/tests/unit/test_traverse_value.py
index 847d3f40..47e8c75b 100644
--- a/tests/unit/test_traverse_value.py
+++ b/tests/unit/test_traverse_value.py
@@ -1,9 +1,11 @@
 from typing import List
+from dataclasses import dataclass
 
-from specklepy.objects_v2.base import Base
+from specklepy.objects.base import Base
 from specklepy.serialization.base_object_serializer import BaseObjectSerializer
 
 
+@dataclass(kw_only=True)
 class FakeBase(Base):
     foo: List[str]
     bar: int
diff --git a/tests/unit/test_type_validation.py b/tests/unit/test_type_validation.py
index 4b845f7e..27fa539f 100644
--- a/tests/unit/test_type_validation.py
+++ b/tests/unit/test_type_validation.py
@@ -3,8 +3,8 @@
 
 import pytest
 
-from specklepy.objects_v2.base import Base, _validate_type
-from specklepy.objects_v2.primitive import Interval
+from specklepy.objects.base import Base, _validate_type
+from specklepy.objects.primitive import Interval
 
 test_base = Base()
 
@@ -87,7 +87,8 @@ def __init__(self, foo: str) -> None:
         (Tuple, (1, "foo", "bar"), True, (1, "foo", "bar")),
         # given our current rules, this is the reality. Its just sad...
         (Tuple[str, str, str], (1, "foo", "bar"), True, ("1", "foo", "bar")),
-        (Tuple[str, Optional[str], str], (1, None, "bar"), True, ("1", None, "bar")),
+        (Tuple[str, Optional[str], str],
+         (1, None, "bar"), True, ("1", None, "bar")),
         (Set[bool], set([1, 2]), False, set([1, 2])),
         (Set[int], set([1, 2]), True, set([1, 2])),
         (Set[int], set([None, 2]), True, set([None, 2])),
@@ -99,7 +100,8 @@ def __init__(self, foo: str) -> None:
         (Optional[Union[List[int], List[FakeBase]]], None, True, None),
         (Optional[Union[List[int], List[FakeBase]]], "foo", False, "foo"),
         (Union[List[int], List[FakeBase], None], "foo", False, "foo"),
-        (Optional[Union[List[int], List[FakeBase]]], [1, 2, 3], True, [1, 2, 3]),
+        (Optional[Union[List[int], List[FakeBase]]],
+         [1, 2, 3], True, [1, 2, 3]),
         (
             Optional[Union[List[int], List[FakeBase]]],
             fake_bases,
@@ -113,7 +115,8 @@ def __init__(self, foo: str) -> None:
             True,
             {"foo": 1.0, "bar": 2.0},
         ),
-        (Union[float, Dict[str, float]], {"foo": "bar"}, False, {"foo": "bar"}),
+        (Union[float, Dict[str, float]], {
+         "foo": "bar"}, False, {"foo": "bar"}),
     ],
 )
 def test_validate_type(
diff --git a/tests/unit/test_unit_scaling.py b/tests/unit/test_unit_scaling.py
index a7d414e4..dbe1bfc5 100644
--- a/tests/unit/test_unit_scaling.py
+++ b/tests/unit/test_unit_scaling.py
@@ -1,6 +1,6 @@
 import pytest
 
-from specklepy.objects_v2.units import Units, get_scale_factor
+from specklepy.objects.models.units import Units, get_scale_factor
 
 
 @pytest.mark.parametrize(