Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add extra config to make Unit model hashable #187

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 4 additions & 1 deletion filip/models/ngsi_v2/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ class Unit(BaseModel):
class Config:
extra = 'ignore'
allow_population_by_field_name = True
allow_mutation = False
frozen = True

@root_validator(pre=False, allow_reuse=True)
def check_consistency(cls, values):
Expand Down Expand Up @@ -203,6 +205,7 @@ def __getattr__(self, item):
Return unit as attribute by name or code.
Notes:
Underscores will be substituted with whitespaces

Args:
item: if len(row) == 0:

Expand All @@ -221,7 +224,7 @@ def quantities(self):
"""
raise NotImplementedError("The used dataset does currently not "
"contain the information about quantity")

@lru_cache()
def __getitem__(self, item: str) -> Unit:
"""
Get unit by name or code
Expand Down
56 changes: 54 additions & 2 deletions tests/models/test_units.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""
Test for filip.models.units
"""
from unittest import TestCase
import unittest
import functools
from filip.models.ngsi_v2.units import \
Unit, \
Units, \
Expand All @@ -10,7 +11,7 @@
load_units


class TestUnitCodes(TestCase):
class TestUnitCodes(unittest.TestCase):

def setUp(self):
self.units_data = load_units()
Expand Down Expand Up @@ -39,13 +40,43 @@ def test_unit_text(self):
def test_unit_model(self):
"""
Test unit model

Returns:
None
"""
# test creation
unit = Unit(**self.unit)
unit_from_json = Unit.parse_raw(unit.json(by_alias=True))
self.assertEqual(unit, unit_from_json)

def test_unit_model_caching(self):
"""
Test caching of unit model

Returns:
None
"""

unit = Unit(**self.unit)
# testing hashing and caching
from functools import lru_cache
from time import perf_counter_ns

self.assertEqual(unit.__hash__(), unit.__hash__())

@functools.lru_cache
def cache_unit(unit: Unit):
return Unit(name=unit.name)

timers = []
for i in range(5):
start = perf_counter_ns()
cache_unit(unit)
stop = perf_counter_ns()
timers.append(stop - start)
if i > 0:
self.assertLess(timers[i], timers[0])

def test_units(self):
"""
Test units api
Expand Down Expand Up @@ -78,8 +109,29 @@ def test_unit_validator(self):
Returns:
None
"""

unit_data = self.unit.copy()
unit_data['name'] = "celcius"
with self.assertRaises(ValueError):
Unit(**unit_data)

def tearDown(self):
"""
clean up
"""
# using garbage collector to clean up all caches
import gc
gc.collect()

# All objects collected
objects = [i for i in gc.get_objects()
if isinstance(i, functools._lru_cache_wrapper)]

# All objects cleared
for object in objects:
object.cache_clear()

if __name__ == '__main__':
unittest.main()