From 7acf134816e136e6df58e3ead4ad1b28ea020f91 Mon Sep 17 00:00:00 2001 From: Matthew Wildoer Date: Thu, 14 Nov 2024 13:24:15 -0800 Subject: [PATCH 1/3] Libs: Make sets mutable --- src/faebryk/libs/util.py | 9 ++++++++- test/libs/test_util_func_collections.py | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/faebryk/libs/util.py b/src/faebryk/libs/util.py index c0e82297..c570fe18 100644 --- a/src/faebryk/libs/util.py +++ b/src/faebryk/libs/util.py @@ -957,7 +957,7 @@ def debugging() -> bool: return debugpy.is_client_connected() -class FuncSet[T, H: Hashable](collections.abc.Set[T]): +class FuncSet[T, H: Hashable](collections.abc.MutableSet[T]): """ A set by pre-processing the objects with the hasher function. """ @@ -973,6 +973,13 @@ def add(self, item: T): if item not in self._deref[self._hasher(item)]: self._deref[self._hasher(item)].append(item) + def discard(self, item: T): + hashed = self._hasher(item) + if hashed in self._deref and item in self._deref[hashed]: + self._deref[hashed].remove(item) + if not self._deref[hashed]: + del self._deref[hashed] + def __contains__(self, item: T): return item in self._deref[self._hasher(item)] diff --git a/test/libs/test_util_func_collections.py b/test/libs/test_util_func_collections.py index 6dba9314..b8eddf13 100644 --- a/test/libs/test_util_func_collections.py +++ b/test/libs/test_util_func_collections.py @@ -80,3 +80,12 @@ def test_func_set_hash_collision(): assert len(a) == 2 assert 1 in a assert 2 in a + + +def test_func_set_discard(): + a = FuncSet((1,2), hasher=lambda x: x) + assert 1 in a + assert 2 in a + a.discard(1) + assert 1 not in a + assert 2 in a From f70a0677fe0023b7b623838fb56320eff68a3b3f Mon Sep 17 00:00:00 2001 From: Matthew Wildoer Date: Thu, 14 Nov 2024 21:55:01 -0800 Subject: [PATCH 2/3] Improve unit checking. Avoids error on construction w/ quantities that mismatch the unit's registry --- src/faebryk/libs/library/L.py | 1 + src/faebryk/libs/sets.py | 4 ++-- src/faebryk/libs/units.py | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/faebryk/libs/library/L.py b/src/faebryk/libs/library/L.py index 9b1c7ab9..04911195 100644 --- a/src/faebryk/libs/library/L.py +++ b/src/faebryk/libs/library/L.py @@ -4,6 +4,7 @@ import logging from faebryk.core.module import Module # noqa: F401 +from faebryk.core.moduleinterface import ModuleInterface # noqa: F401 from faebryk.core.node import ( # noqa: F401 InitVar, Node, diff --git a/src/faebryk/libs/sets.py b/src/faebryk/libs/sets.py index 88c5c175..c6a900d5 100644 --- a/src/faebryk/libs/sets.py +++ b/src/faebryk/libs/sets.py @@ -398,14 +398,14 @@ def __init__( self.units = units or min_unit or max_unit self.range_units = base_units(self.units) - if isinstance(min, Quantity): + if HasUnit.check(min): num_min = min.to_base_units().magnitude if not (isinstance(num_min, float) or isinstance(num_min, int)): raise ValueError("min must be a float or int quantity") else: num_min = min - if isinstance(max, Quantity): + if HasUnit.check(max): num_max = max.to_base_units().magnitude if not (isinstance(num_max, float) or isinstance(num_max, int)): raise ValueError("max must be a float or int quantity") diff --git a/src/faebryk/libs/units.py b/src/faebryk/libs/units.py index 526e161a..5225dc98 100644 --- a/src/faebryk/libs/units.py +++ b/src/faebryk/libs/units.py @@ -5,7 +5,7 @@ from typing import Any from pint import Quantity as _Quantity # noqa: F401 -from pint import UndefinedUnitError, Unit, UnitRegistry # noqa: F401 +from pint import UndefinedUnitError, UnitRegistry # noqa: F401 from pint.util import UnitsContainer as _UnitsContainer from faebryk.libs.util import cast_assert @@ -14,6 +14,7 @@ UnitsContainer = _UnitsContainer | str Quantity = P.Quantity +Unit = P.Unit dimensionless = cast_assert(Unit, P.dimensionless) From ef42cd2fffe369608b094487fb355ffc07636564 Mon Sep 17 00:00:00 2001 From: Matthew Wildoer Date: Thu, 14 Nov 2024 21:55:25 -0800 Subject: [PATCH 3/3] Add properties for parameter attributes instead of exclusively processing them on init --- src/faebryk/core/parameter.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/faebryk/core/parameter.py b/src/faebryk/core/parameter.py index f43c42ef..6b061c33 100644 --- a/src/faebryk/core/parameter.py +++ b/src/faebryk/core/parameter.py @@ -865,17 +865,10 @@ def __init__( likely_constrained: bool = False, # TODO rename expect_constraits or similiar ): super().__init__() - if within is not None and not within.units.is_compatible_with(units): - raise ValueError("incompatible units") - - if isinstance(within, Range): - within = Ranges(within) - - if isinstance(soft_set, Range): - soft_set = Ranges(soft_set) if not isinstance(units, Unit): raise TypeError("units must be a Unit") + self.units = units self.within = within self.domain = domain @@ -884,6 +877,28 @@ def __init__( self.tolerance_guess = tolerance_guess self.likely_constrained = likely_constrained + @property + def within(self) -> Ranges | None: + return self._within + + @within.setter + def within(self, value: Range | Ranges | None): + if value is not None and not value.units.is_compatible_with(self.units): + raise ValueError("incompatible units") + if isinstance(value, Range): + value = Ranges(value) + self._within = value + + @property + def soft_set(self) -> Ranges | None: + return self._soft_set + + @soft_set.setter + def soft_set(self, value: Range | Ranges | None): + if isinstance(value, Range): + value = Ranges(value) + self._soft_set = value + # Type forwards type All = ParameterOperatable.All type NumberLike = ParameterOperatable.NumberLike