diff --git a/PKG-INFO b/PKG-INFO index a97b885dbb6ac74bb8697d848cb7f7654ba288c7..f9bcafd17410f37d9819e23c4137799b7c4f14f0 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: swh.model -Version: 0.0.40 +Version: 0.0.41 Summary: Software Heritage data model Home-page: https://forge.softwareheritage.org/diffusion/DMOD/ Author: Software Heritage developers diff --git a/swh.model.egg-info/PKG-INFO b/swh.model.egg-info/PKG-INFO index a97b885dbb6ac74bb8697d848cb7f7654ba288c7..f9bcafd17410f37d9819e23c4137799b7c4f14f0 100644 --- a/swh.model.egg-info/PKG-INFO +++ b/swh.model.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: swh.model -Version: 0.0.40 +Version: 0.0.41 Summary: Software Heritage data model Home-page: https://forge.softwareheritage.org/diffusion/DMOD/ Author: Software Heritage developers diff --git a/swh/model/hypothesis_strategies.py b/swh/model/hypothesis_strategies.py index 1b99957a737030dab80f3f01f204a925e6d2621f..e20f4ea114d097f0d728b3c672cabe698d3e219f 100644 --- a/swh/model/hypothesis_strategies.py +++ b/swh/model/hypothesis_strategies.py @@ -132,7 +132,7 @@ def contents(draw): (status, data, reason) = draw(one_of( tuples(just('visible'), binary(), none()), tuples(just('absent'), none(), pgsql_text()), - tuples(just('hidden'), none(), none()), + tuples(just('hidden'), binary(), none()), )) return draw(builds( diff --git a/swh/model/model.py b/swh/model/model.py index 5f2d960a8a7bf6be2dc943c27ebd5deb6c74a287..36f8ef3f1838fcf0ea8c632962cde906ee7db5bb 100644 --- a/swh/model/model.py +++ b/swh/model/model.py @@ -11,6 +11,7 @@ import attr import dateutil.parser from .identifiers import normalize_timestamp +from .hashutil import DEFAULT_ALGORITHMS SHA1_SIZE = 20 @@ -335,11 +336,16 @@ class Content(BaseModel): default=None, validator=attr.validators.optional([])) + ctime = attr.ib(type=Optional[datetime.datetime], + default=None) + @length.validator def check_length(self, attribute, value): """Checks the length is positive.""" - if value < 0: - raise ValueError('Length must be positive.') + if self.status == 'absent' and value < -1: + raise ValueError('Length must be positive or -1.') + elif self.status != 'absent' and value < 0: + raise ValueError('Length must be positive, unless status=absent.') @reason.validator def check_reason(self, attribute, value): @@ -353,8 +359,12 @@ class Content(BaseModel): def to_dict(self): content = attr.asdict(self) - if content['data'] is None: - del content['data'] - if content['reason'] is None: - del content['reason'] + for field in ('data', 'reason', 'ctime'): + if content[field] is None: + del content[field] return content + + def get_hash(self, hash_name): + if hash_name not in DEFAULT_ALGORITHMS: + raise ValueError('{} is not a valid hash name.'.format(hash_name)) + return getattr(self, hash_name) diff --git a/swh/model/tests/test_hypothesis_strategies.py b/swh/model/tests/test_hypothesis_strategies.py index 3e69ab9b93c8963c84f45023a0f89d9d61b3ad62..09c21d8119359c4d3849dc23d8dcb10bb3de1bc8 100644 --- a/swh/model/tests/test_hypothesis_strategies.py +++ b/swh/model/tests/test_hypothesis_strategies.py @@ -49,7 +49,7 @@ def test_dicts_generation(obj_type_and_obj): set(DEFAULT_ALGORITHMS) | {'length', 'status', 'reason'} elif object_['status'] == 'hidden': assert set(object_) == \ - set(DEFAULT_ALGORITHMS) | {'length', 'status'} + set(DEFAULT_ALGORITHMS) | {'length', 'status', 'data'} else: assert False, object_ elif obj_type == 'release': diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py index 220ba324798e9a5f522483f731502f16e9950793..f91868577235614cd5733957a0af6d19a289c046 100644 --- a/swh/model/tests/test_model.py +++ b/swh/model/tests/test_model.py @@ -7,6 +7,7 @@ import copy from hypothesis import given +from swh.model.model import Content from swh.model.hypothesis_strategies import objects @@ -24,3 +25,11 @@ def test_todict_inverse_fromdict(objtype_and_obj): # Check the composition of from_dict and to_dict is the identity assert obj_as_dict == type(obj).from_dict(obj_as_dict).to_dict() + + +def test_content_get_hash(): + hashes = dict( + sha1=b'foo', sha1_git=b'bar', sha256=b'baz', blake2s256=b'qux') + c = Content(length=42, status='visible', **hashes) + for (hash_name, hash_) in hashes.items(): + assert c.get_hash(hash_name) == hash_ diff --git a/version.txt b/version.txt index f57c086155d813c6da9d5222efe96821263bb513..d73351960bdbc86edfc8ef92e7024fa8f81763ad 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v0.0.40-0-g56eb29f \ No newline at end of file +v0.0.41-0-g01a5d4c \ No newline at end of file