diff --git a/src/specklepy/objects/base.py b/src/specklepy/objects/base.py index 51765f1a..d0a797c9 100644 --- a/src/specklepy/objects/base.py +++ b/src/specklepy/objects/base.py @@ -18,7 +18,7 @@ from stringcase import pascalcase -from specklepy.logging.exceptions import SpeckleException +from specklepy.logging.exceptions import SpeckleException, SpeckleInvalidUnitException from specklepy.objects.units import Units, get_units_from_string from specklepy.transports.memory import MemoryTransport @@ -322,7 +322,7 @@ class Base(_RegisteringBase): id: Union[str, None] = None totalChildrenCount: Union[int, None] = None applicationId: Union[str, None] = None - _units: Union[Units, None] = None + _units: Union[None, str] = None def __init__(self, **kwargs) -> None: super().__init__() @@ -463,22 +463,18 @@ def add_detachable_attrs(self, names: Set[str]) -> None: @property def units(self) -> Union[str, None]: - if self._units: - return self._units.value - return None + return self._units @units.setter def units(self, value: Union[str, Units, None]): - if value is None: - units = value + if isinstance(value, str) or value is None: + self._units = value elif isinstance(value, Units): - units: Units = value + self._units = value.value else: - units = get_units_from_string(value) - self._units = units - # except SpeckleInvalidUnitException as ex: - # warn(f"Units are reset to None. Reason {ex.message}") - # self._units = None + 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""" diff --git a/src/specklepy/objects/units.py b/src/specklepy/objects/units.py index e89dbc71..182ea1d3 100644 --- a/src/specklepy/objects/units.py +++ b/src/specklepy/objects/units.py @@ -72,13 +72,18 @@ def get_units_from_encoding(unit: int): ) -def get_encoding_from_units(unit: Union[Units, None]): +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[unit] + return UNITS_ENCODINGS[maybe_sanitized_unit] except KeyError as e: raise SpeckleException( message=( - f"No encoding exists for unit {unit}." + f"No encoding exists for unit {maybe_sanitized_unit}." f"Please enter a valid unit to encode (eg {UNITS_ENCODINGS})." ) ) from e diff --git a/tests/intergration/test_serialization.py b/tests/intergration/test_serialization.py index 6f444795..85bcd927 100644 --- a/tests/intergration/test_serialization.py +++ b/tests/intergration/test_serialization.py @@ -17,7 +17,7 @@ def test_serialize(self, base): deserialized = operations.deserialize(serialized) assert base.get_id() == deserialized.get_id() - assert base.units == "mm" + assert base.units == "millimetres" assert isinstance(base.test_bases[0], Base) assert base["@revit_thing"].speckle_type == "SpecialRevitFamily" assert base["@detach"].name == deserialized["@detach"].name diff --git a/tests/unit/test_base.py b/tests/unit/test_base.py index f653a3a4..1dc87f35 100644 --- a/tests/unit/test_base.py +++ b/tests/unit/test_base.py @@ -85,14 +85,15 @@ def test_speckle_type_cannot_be_set(base: Base) -> None: def test_setting_units(): b = Base(units="foot") - assert b.units == "ft" + assert b.units == "foot" - with pytest.raises(SpeckleInvalidUnitException): - b.units = "big" + # with pytest.raises(SpeckleInvalidUnitException): + b.units = "big" + assert b.units == "big" with pytest.raises(SpeckleInvalidUnitException): b.units = 7 # invalid args are skipped - assert b.units == "ft" + assert b.units == "big" b.units = None # None should be a valid arg assert b.units is None