diff --git a/PKG-INFO b/PKG-INFO index de02b1c34cd05d40ab6a3ceb9596d41fdc775e96..ffcee9d004f2b4af0f980d6674255f21c81c3e84 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: swh.model -Version: 0.0.60 +Version: 0.0.62 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 de02b1c34cd05d40ab6a3ceb9596d41fdc775e96..ffcee9d004f2b4af0f980d6674255f21c81c3e84 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.60 +Version: 0.0.62 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 6fe27b79f52c0c8ad8397f460d83dd19b613e399..b6c35933fdfef36ab9d3e8ec5cc2930e6daee159 100644 --- a/swh/model/hypothesis_strategies.py +++ b/swh/model/hypothesis_strategies.py @@ -75,7 +75,6 @@ def timestamps_with_timezone(): def origins(): return builds( Origin, - type=sampled_from(['git', 'hg', 'svn', 'pypi', 'deb']), url=urls()) diff --git a/swh/model/identifiers.py b/swh/model/identifiers.py index 85fc76c4585ccba88b8f7e69eca8ae2f9ff34ea1..6ccf948849e96bc45298909bb0677c9e881ef38e 100644 --- a/swh/model/identifiers.py +++ b/swh/model/identifiers.py @@ -612,7 +612,7 @@ def origin_identifier(origin): An origin's identifier is the sha1 checksum of the entire origin URL """ - return hashlib.sha1(origin['url'].encode('ascii')).hexdigest() + return hashlib.sha1(origin['url'].encode('utf-8')).hexdigest() _object_type_map = { diff --git a/swh/model/model.py b/swh/model/model.py index a3809f9d08ab807e1c715b4ee7e210528b9315c7..7cfb7e3ce71460abd4795936d62da763b2fced88 100644 --- a/swh/model/model.py +++ b/swh/model/model.py @@ -32,6 +32,20 @@ SHA1_SIZE = 20 Sha1Git = bytes +def dictify(value): + "Helper function used by BaseModel.to_dict()" + if isinstance(value, BaseModel): + return value.to_dict() + elif isinstance(value, Enum): + return value.value + elif isinstance(value, dict): + return {k: dictify(v) for k, v in value.items()} + elif isinstance(value, list): + return [dictify(v) for v in value] + else: + return value + + class BaseModel: """Base class for SWH model classes. @@ -41,21 +55,7 @@ class BaseModel: def to_dict(self): """Wrapper of `attr.asdict` that can be overridden by subclasses that have special handling of some of the fields.""" - - def dictify(value): - if isinstance(value, BaseModel): - return value.to_dict() - elif isinstance(value, Enum): - return value.value - elif isinstance(value, dict): - return {k: dictify(v) for k, v in value.items()} - elif isinstance(value, list): - return [dictify(v) for v in value] - else: - return value - - ret = attr.asdict(self, recurse=False) - return dictify(ret) + return dictify(attr.asdict(self, recurse=False)) @classmethod def from_dict(cls, d): @@ -194,12 +194,6 @@ class TimestampWithTimezone(BaseModel): class Origin(BaseModel): """Represents a software source: a VCS and an URL.""" url = attr.ib(type=str) - type = attr.ib(type=Optional[str], default=None) - - def to_dict(self): - r = super().to_dict() - r.pop('type', None) - return r @attr.s(frozen=True) diff --git a/swh/model/tests/test_identifiers.py b/swh/model/tests/test_identifiers.py index d5f0f1d46ea103c875c7f3b61f587a53359e3d2d..8c6c70d1944cc86a85f50e3b1ee8638682483186 100644 --- a/swh/model/tests/test_identifiers.py +++ b/swh/model/tests/test_identifiers.py @@ -9,7 +9,7 @@ import unittest from swh.model import hashutil, identifiers from swh.model.exceptions import ValidationError -from swh.model.hashutil import hash_to_bytes +from swh.model.hashutil import hash_to_bytes as _x from swh.model.identifiers import (CONTENT, DIRECTORY, RELEASE, REVISION, SNAPSHOT, PersistentId) @@ -119,85 +119,85 @@ directory_example = { 'type': 'file', 'perms': 33188, 'name': b'README', - 'target': '37ec8ea2110c0b7a32fbb0e872f6e7debbf95e21' + 'target': _x('37ec8ea2110c0b7a32fbb0e872f6e7debbf95e21') }, { 'type': 'file', 'perms': 33188, 'name': b'Rakefile', - 'target': '3bb0e8592a41ae3185ee32266c860714980dbed7' + 'target': _x('3bb0e8592a41ae3185ee32266c860714980dbed7') }, { 'type': 'dir', 'perms': 16384, 'name': b'app', - 'target': '61e6e867f5d7ba3b40540869bc050b0c4fed9e95' + 'target': _x('61e6e867f5d7ba3b40540869bc050b0c4fed9e95') }, { 'type': 'file', 'perms': 33188, 'name': b'1.megabyte', - 'target': '7c2b2fbdd57d6765cdc9d84c2d7d333f11be7fb3' + 'target': _x('7c2b2fbdd57d6765cdc9d84c2d7d333f11be7fb3') }, { 'type': 'dir', 'perms': 16384, 'name': b'config', - 'target': '591dfe784a2e9ccc63aaba1cb68a765734310d98' + 'target': _x('591dfe784a2e9ccc63aaba1cb68a765734310d98') }, { 'type': 'dir', 'perms': 16384, 'name': b'public', - 'target': '9588bf4522c2b4648bfd1c61d175d1f88c1ad4a5' + 'target': _x('9588bf4522c2b4648bfd1c61d175d1f88c1ad4a5') }, { 'type': 'file', 'perms': 33188, 'name': b'development.sqlite3', - 'target': 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391' + 'target': _x('e69de29bb2d1d6434b8b29ae775ad8c2e48c5391') }, { 'type': 'dir', 'perms': 16384, 'name': b'doc', - 'target': '154705c6aa1c8ead8c99c7915373e3c44012057f' + 'target': _x('154705c6aa1c8ead8c99c7915373e3c44012057f') }, { 'type': 'dir', 'perms': 16384, 'name': b'db', - 'target': '85f157bdc39356b7bc7de9d0099b4ced8b3b382c' + 'target': _x('85f157bdc39356b7bc7de9d0099b4ced8b3b382c') }, { 'type': 'dir', 'perms': 16384, 'name': b'log', - 'target': '5e3d3941c51cce73352dff89c805a304ba96fffe' + 'target': _x('5e3d3941c51cce73352dff89c805a304ba96fffe') }, { 'type': 'dir', 'perms': 16384, 'name': b'script', - 'target': '1b278423caf176da3f3533592012502aa10f566c' + 'target': _x('1b278423caf176da3f3533592012502aa10f566c') }, { 'type': 'dir', 'perms': 16384, 'name': b'test', - 'target': '035f0437c080bfd8711670b3e8677e686c69c763' + 'target': _x('035f0437c080bfd8711670b3e8677e686c69c763') }, { 'type': 'dir', 'perms': 16384, 'name': b'vendor', - 'target': '7c0dc9ad978c1af3f9a4ce061e50f5918bd27138' + 'target': _x('7c0dc9ad978c1af3f9a4ce061e50f5918bd27138') }, { 'type': 'rev', 'perms': 57344, 'name': b'will_paginate', - 'target': '3d531e169db92a16a9a8974f0ae6edf52e52659e' + 'target': _x('3d531e169db92a16a9a8974f0ae6edf52e52659e') }, # in git order, the dir named "order" should be between the files @@ -206,19 +206,19 @@ directory_example = { 'type': 'dir', 'perms': 16384, 'name': b'order', - 'target': '62cdb7020ff920e5aa642c3d4066950dd1f01f4d' + 'target': _x('62cdb7020ff920e5aa642c3d4066950dd1f01f4d') }, { 'type': 'file', 'perms': 16384, 'name': b'order.', - 'target': '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' + 'target': _x('0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33') }, { 'type': 'file', 'perms': 16384, 'name': b'order0', - 'target': 'bbe960a25ea311d21d40669e93df2003ba9b90a2' + 'target': _x('bbe960a25ea311d21d40669e93df2003ba9b90a2') }, ], } @@ -255,8 +255,8 @@ linus_tz = datetime.timezone(datetime.timedelta(minutes=-420)) revision_example = { 'id': 'bc0195aad0daa2ad5b0d76cce22b167bc3435590', - 'directory': '85a74718d377195e1efd0843ba4f3260bad4fe07', - 'parents': ['01e2d0627a9a6edb24c37db45db5ecb31e9de808'], + 'directory': _x('85a74718d377195e1efd0843ba4f3260bad4fe07'), + 'parents': [_x('01e2d0627a9a6edb24c37db45db5ecb31e9de808')], 'author': { 'name': b'Linus Torvalds', 'email': b'torvalds@linux-foundation.org', @@ -302,8 +302,8 @@ dg1KdHOa34shrKDaOVzW self.revision_none_metadata = { 'id': 'bc0195aad0daa2ad5b0d76cce22b167bc3435590', - 'directory': '85a74718d377195e1efd0843ba4f3260bad4fe07', - 'parents': ['01e2d0627a9a6edb24c37db45db5ecb31e9de808'], + 'directory': _x('85a74718d377195e1efd0843ba4f3260bad4fe07'), + 'parents': [_x('01e2d0627a9a6edb24c37db45db5ecb31e9de808')], 'author': { 'name': b'Linus Torvalds', 'email': b'torvalds@linux-foundation.org', @@ -356,8 +356,8 @@ dg1KdHOa34shrKDaOVzW # cat commit.txt | git hash-object -t commit --stdin self.revision_with_extra_headers = { 'id': '010d34f384fa99d047cdd5e2f41e56e5c2feee45', - 'directory': '85a74718d377195e1efd0843ba4f3260bad4fe07', - 'parents': ['01e2d0627a9a6edb24c37db45db5ecb31e9de808'], + 'directory': _x('85a74718d377195e1efd0843ba4f3260bad4fe07'), + 'parents': [_x('01e2d0627a9a6edb24c37db45db5ecb31e9de808')], 'author': { 'name': b'Linus Torvalds', 'email': b'torvalds@linux-foundation.org', @@ -383,9 +383,9 @@ dg1KdHOa34shrKDaOVzW self.revision_with_gpgsig = { 'id': '44cc742a8ca17b9c279be4cc195a93a6ef7a320e', - 'directory': 'b134f9b7dc434f593c0bab696345548b37de0558', - 'parents': ['689664ae944b4692724f13b709a4e4de28b54e57', - 'c888305e1efbaa252d01b4e5e6b778f865a97514'], + 'directory': _x('b134f9b7dc434f593c0bab696345548b37de0558'), + 'parents': [_x('689664ae944b4692724f13b709a4e4de28b54e57'), + _x('c888305e1efbaa252d01b4e5e6b778f865a97514')], 'author': { 'name': b'Jiang Xin', 'email': b'worldhello.net@gmail.com', @@ -417,9 +417,9 @@ dg1KdHOa34shrKDaOVzW self.revision_no_message = { 'id': '4cfc623c9238fa92c832beed000ce2d003fd8333', - 'directory': 'b134f9b7dc434f593c0bab696345548b37de0558', - 'parents': ['689664ae944b4692724f13b709a4e4de28b54e57', - 'c888305e1efbaa252d01b4e5e6b778f865a97514'], + 'directory': _x('b134f9b7dc434f593c0bab696345548b37de0558'), + 'parents': [_x('689664ae944b4692724f13b709a4e4de28b54e57'), + _x('c888305e1efbaa252d01b4e5e6b778f865a97514')], 'author': { 'name': b'Jiang Xin', 'email': b'worldhello.net@gmail.com', @@ -442,9 +442,9 @@ dg1KdHOa34shrKDaOVzW self.revision_empty_message = { 'id': '7442cd78bd3b4966921d6a7f7447417b7acb15eb', - 'directory': 'b134f9b7dc434f593c0bab696345548b37de0558', - 'parents': ['689664ae944b4692724f13b709a4e4de28b54e57', - 'c888305e1efbaa252d01b4e5e6b778f865a97514'], + 'directory': _x('b134f9b7dc434f593c0bab696345548b37de0558'), + 'parents': [_x('689664ae944b4692724f13b709a4e4de28b54e57'), + _x('c888305e1efbaa252d01b4e5e6b778f865a97514')], 'author': { 'name': b'Jiang Xin', 'email': b'worldhello.net@gmail.com', @@ -467,8 +467,8 @@ dg1KdHOa34shrKDaOVzW self.revision_only_fullname = { 'id': '010d34f384fa99d047cdd5e2f41e56e5c2feee45', - 'directory': '85a74718d377195e1efd0843ba4f3260bad4fe07', - 'parents': ['01e2d0627a9a6edb24c37db45db5ecb31e9de808'], + 'directory': _x('85a74718d377195e1efd0843ba4f3260bad4fe07'), + 'parents': [_x('01e2d0627a9a6edb24c37db45db5ecb31e9de808')], 'author': { 'fullname': b'Linus Torvalds <torvalds@linux-foundation.org>', }, @@ -716,16 +716,14 @@ o6X/3T+vm8K3bf3driRr34c= snapshot_example = { - 'id': hash_to_bytes('6e65b86363953b780d92b0a928f3e8fcdd10db36'), + 'id': _x('6e65b86363953b780d92b0a928f3e8fcdd10db36'), 'branches': { b'directory': { - 'target': hash_to_bytes( - '1bd0e65f7d2ff14ae994de17a1e7fe65111dcad8'), + 'target': _x('1bd0e65f7d2ff14ae994de17a1e7fe65111dcad8'), 'target_type': 'directory', }, b'content': { - 'target': hash_to_bytes( - 'fe95a46679d128ff167b7c55df5d02356c5a1ae1'), + 'target': _x('fe95a46679d128ff167b7c55df5d02356c5a1ae1'), 'target_type': 'content', }, b'alias': { @@ -733,19 +731,15 @@ snapshot_example = { 'target_type': 'alias', }, b'revision': { - 'target': hash_to_bytes( - 'aafb16d69fd30ff58afdd69036a26047f3aebdc6'), + 'target': _x('aafb16d69fd30ff58afdd69036a26047f3aebdc6'), 'target_type': 'revision', }, b'release': { - 'target': hash_to_bytes( - '7045404f3d1c54e6473c71bbb716529fbad4be24'), + 'target': _x('7045404f3d1c54e6473c71bbb716529fbad4be24'), 'target_type': 'release', }, b'snapshot': { - 'target': hash_to_bytes( - '1a8893e6a86f444e8be8e7bda6cb34fb1735a00e' - ), + 'target': _x('1a8893e6a86f444e8be8e7bda6cb34fb1735a00e'), 'target_type': 'snapshot', }, b'dangling': None, @@ -813,8 +807,7 @@ class SnapshotIdentifier(unittest.TestCase): ) def test_persistent_identifier(self): - _snapshot_id = hashutil.hash_to_bytes( - 'c7c108084bc0bf3d81436bf980b46e98bd338453') + _snapshot_id = _x('c7c108084bc0bf3d81436bf980b46e98bd338453') _release_id = '22ece559cc7cc2364edc5e5593d63ae8bd229f9f' _revision_id = '309cf2674ee7a0749978cf8265ab91a60aea0f7d' _directory_id = 'd198bc9d7a6bcf6db04f476d29314f157507d505' diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py index 8bffa80b491f65e98a51618fb1d5064f35bab15e..5e8e1ee22acf0653f8188f084ff7a00f4c4d0ca6 100644 --- a/swh/model/tests/test_model.py +++ b/swh/model/tests/test_model.py @@ -259,52 +259,53 @@ def test_skipped_content_from_data(data): def test_directory_model_id_computation(): - dir_dict = dict(directory_example) + dir_dict = directory_example.copy() del dir_dict['id'] dir_id = hash_to_bytes(directory_identifier(dir_dict)) - for dir_model in [Directory(**dir_dict), Directory.from_dict(dir_dict)]: - assert dir_model.id == dir_id + dir_model = Directory.from_dict(dir_dict) + assert dir_model.id == dir_id def test_revision_model_id_computation(): - rev_dict = dict(revision_example) + rev_dict = revision_example.copy() del rev_dict['id'] rev_id = hash_to_bytes(revision_identifier(rev_dict)) - for rev_model in [Revision(**rev_dict), Revision.from_dict(rev_dict)]: - assert rev_model.id == rev_id + rev_model = Revision.from_dict(rev_dict) + assert rev_model.id == rev_id def test_revision_model_id_computation_with_no_date(): """We can have revision with date to None """ - rev_dict = dict(revision_example) + rev_dict = revision_example.copy() rev_dict['date'] = None rev_dict['committer_date'] = None del rev_dict['id'] rev_id = hash_to_bytes(revision_identifier(rev_dict)) - for rev_model in [Revision(**rev_dict), Revision.from_dict(rev_dict)]: - assert rev_model.date is None - assert rev_model.committer_date is None - assert rev_model.id == rev_id + rev_model = Revision.from_dict(rev_dict) + assert rev_model.date is None + assert rev_model.committer_date is None + assert rev_model.id == rev_id def test_release_model_id_computation(): - rel_dict = dict(release_example) + rel_dict = release_example.copy() del rel_dict['id'] rel_id = hash_to_bytes(release_identifier(rel_dict)) - for rel_model in [Release(**rel_dict), Release.from_dict(rel_dict)]: - assert rel_model.id == hash_to_bytes(rel_id) + rel_model = Release.from_dict(rel_dict) + assert isinstance(rel_model.date, TimestampWithTimezone) + assert rel_model.id == hash_to_bytes(rel_id) def test_snapshot_model_id_computation(): - snp_dict = dict(snapshot_example) + snp_dict = snapshot_example.copy() del snp_dict['id'] snp_id = hash_to_bytes(snapshot_identifier(snp_dict)) - for snp_model in [Snapshot(**snp_dict), Snapshot.from_dict(snp_dict)]: - assert snp_model.id == snp_id + snp_model = Snapshot.from_dict(snp_dict) + assert snp_model.id == snp_id diff --git a/version.txt b/version.txt index ed7808504f726444e81919a73be3543107695917..eb7e24b8d7e2668da7d581835a78257a098c7cdc 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v0.0.60-0-ga5a9f57 \ No newline at end of file +v0.0.62-0-g4a2233c \ No newline at end of file