Page MenuHomeSoftware Heritage

D2819.id10271.diff
No OneTemporary

D2819.id10271.diff

diff --git a/mypy.ini b/mypy.ini
--- a/mypy.ini
+++ b/mypy.ini
@@ -2,9 +2,11 @@
namespace_packages = True
warn_unused_ignores = True
-
# 3rd party libraries without stubs (yet)
+[mypy-attrs_strict.*] # a bit sad, but...
+ignore_missing_imports = True
+
[mypy-django.*] # false positive, only used my hypotesis' extras
ignore_missing_imports = True
diff --git a/requirements.txt b/requirements.txt
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,6 +3,7 @@
# dependency lines, see https://pip.readthedocs.org/en/1.1/requirements.html
vcversioner
attrs
+attrs_strict
hypothesis
python-dateutil
iso8601
diff --git a/swh/model/model.py b/swh/model/model.py
--- a/swh/model/model.py
+++ b/swh/model/model.py
@@ -7,9 +7,10 @@
from abc import ABCMeta, abstractmethod
from enum import Enum
-from typing import List, Optional, Dict, Union
+from typing import Dict, List, Optional, Union
import attr
+from attrs_strict import type_validator
import dateutil.parser
import iso8601
@@ -84,9 +85,15 @@
@attr.s(frozen=True)
class Person(BaseModel):
"""Represents the author/committer of a revision or release."""
- fullname = attr.ib(type=bytes)
- name = attr.ib(type=Optional[bytes])
- email = attr.ib(type=Optional[bytes])
+ fullname = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ name = attr.ib(
+ type=Optional[bytes],
+ validator=type_validator())
+ email = attr.ib(
+ type=Optional[bytes],
+ validator=type_validator())
@classmethod
def from_fullname(cls, fullname: bytes):
@@ -131,8 +138,12 @@
@attr.s(frozen=True)
class Timestamp(BaseModel):
"""Represents a naive timestamp from a VCS."""
- seconds = attr.ib(type=int)
- microseconds = attr.ib(type=int)
+ seconds = attr.ib(
+ type=int,
+ validator=type_validator())
+ microseconds = attr.ib(
+ type=int,
+ validator=type_validator())
@seconds.validator
def check_seconds(self, attribute, value):
@@ -150,9 +161,15 @@
@attr.s(frozen=True)
class TimestampWithTimezone(BaseModel):
"""Represents a TZ-aware timestamp from a VCS."""
- timestamp = attr.ib(type=Timestamp)
- offset = attr.ib(type=int)
- negative_utc = attr.ib(type=bool)
+ timestamp = attr.ib(
+ type=Timestamp,
+ validator=type_validator())
+ offset = attr.ib(
+ type=int,
+ validator=type_validator())
+ negative_utc = attr.ib(
+ type=bool,
+ validator=type_validator())
@offset.validator
def check_offset(self, attribute, value):
@@ -193,25 +210,38 @@
@attr.s(frozen=True)
class Origin(BaseModel):
"""Represents a software source: a VCS and an URL."""
- url = attr.ib(type=str)
+ url = attr.ib(
+ type=str,
+ validator=type_validator())
@attr.s(frozen=True)
class OriginVisit(BaseModel):
"""Represents a visit of an origin at a given point in time, by a
SWH loader."""
- origin = attr.ib(type=str)
- date = attr.ib(type=datetime.datetime)
+ origin = attr.ib(
+ type=str,
+ validator=type_validator())
+ date = attr.ib(
+ type=datetime.datetime,
+ validator=type_validator())
status = attr.ib(
type=str,
validator=attr.validators.in_(['ongoing', 'full', 'partial']))
- type = attr.ib(type=str)
- snapshot = attr.ib(type=Optional[Sha1Git])
- metadata = attr.ib(type=Optional[Dict[str, object]],
- default=None)
-
- visit = attr.ib(type=Optional[int],
- default=None)
+ type = attr.ib(
+ type=str,
+ validator=type_validator())
+ snapshot = attr.ib(
+ type=Optional[Sha1Git],
+ validator=type_validator())
+ metadata = attr.ib(
+ type=Optional[Dict[str, object]],
+ validator=type_validator(),
+ default=None)
+ visit = attr.ib(
+ type=Optional[int],
+ validator=type_validator(),
+ default=None)
"""Should not be set before calling 'origin_visit_add()'."""
def to_dict(self):
@@ -225,13 +255,10 @@
@classmethod
def from_dict(cls, d):
"""Parses the date from a string, and accepts missing visit ids."""
- d = d.copy()
- date = d.pop('date')
- return cls(
- date=(date
- if isinstance(date, datetime.datetime)
- else dateutil.parser.parse(date)),
- **d)
+ if isinstance(d['date'], str):
+ d = d.copy()
+ d['date'] = dateutil.parser.parse(d['date'])
+ return super().from_dict(d)
class TargetType(Enum):
@@ -257,8 +284,12 @@
@attr.s(frozen=True)
class SnapshotBranch(BaseModel):
"""Represents one of the branches of a snapshot."""
- target = attr.ib(type=bytes)
- target_type = attr.ib(type=TargetType)
+ target = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ target_type = attr.ib(
+ type=TargetType,
+ validator=type_validator())
@target.validator
def check_target(self, attribute, value):
@@ -279,8 +310,13 @@
@attr.s(frozen=True)
class Snapshot(BaseModel, HashableObject):
"""Represents the full state of an origin at a given point in time."""
- branches = attr.ib(type=Dict[bytes, Optional[SnapshotBranch]])
- id = attr.ib(type=Sha1Git, default=b'')
+ branches = attr.ib(
+ type=Dict[bytes, Optional[SnapshotBranch]],
+ validator=type_validator())
+ id = attr.ib(
+ type=Sha1Git,
+ validator=type_validator(),
+ default=b'')
@staticmethod
def compute_hash(object_dict):
@@ -299,18 +335,37 @@
@attr.s(frozen=True)
class Release(BaseModel, HashableObject):
- name = attr.ib(type=bytes)
- message = attr.ib(type=bytes)
- target = attr.ib(type=Optional[Sha1Git])
- target_type = attr.ib(type=ObjectType)
- synthetic = attr.ib(type=bool)
- author = attr.ib(type=Optional[Person],
- default=None)
- date = attr.ib(type=Optional[TimestampWithTimezone],
- default=None)
- metadata = attr.ib(type=Optional[Dict[str, object]],
- default=None)
- id = attr.ib(type=Sha1Git, default=b'')
+ name = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ message = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ target = attr.ib(
+ type=Optional[Sha1Git],
+ validator=type_validator())
+ target_type = attr.ib(
+ type=ObjectType,
+ validator=type_validator())
+ synthetic = attr.ib(
+ type=bool,
+ validator=type_validator())
+ author = attr.ib(
+ type=Optional[Person],
+ validator=type_validator(),
+ default=None)
+ date = attr.ib(
+ type=Optional[TimestampWithTimezone],
+ validator=type_validator(),
+ default=None)
+ metadata = attr.ib(
+ type=Optional[Dict[str, object]],
+ validator=type_validator(),
+ default=None)
+ id = attr.ib(
+ type=Sha1Git,
+ validator=type_validator(),
+ default=b'')
@staticmethod
def compute_hash(object_dict):
@@ -350,19 +405,42 @@
@attr.s(frozen=True)
class Revision(BaseModel, HashableObject):
- message = attr.ib(type=bytes)
- author = attr.ib(type=Person)
- committer = attr.ib(type=Person)
- date = attr.ib(type=Optional[TimestampWithTimezone])
- committer_date = attr.ib(type=Optional[TimestampWithTimezone])
- type = attr.ib(type=RevisionType)
- directory = attr.ib(type=Sha1Git)
- synthetic = attr.ib(type=bool)
- metadata = attr.ib(type=Optional[Dict[str, object]],
- default=None)
- parents = attr.ib(type=List[Sha1Git],
- default=attr.Factory(list))
- id = attr.ib(type=Sha1Git, default=b'')
+ message = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ author = attr.ib(
+ type=Person,
+ validator=type_validator())
+ committer = attr.ib(
+ type=Person,
+ validator=type_validator())
+ date = attr.ib(
+ type=Optional[TimestampWithTimezone],
+ validator=type_validator())
+ committer_date = attr.ib(
+ type=Optional[TimestampWithTimezone],
+ validator=type_validator())
+ type = attr.ib(
+ type=RevisionType,
+ validator=type_validator())
+ directory = attr.ib(
+ type=Sha1Git,
+ validator=type_validator())
+ synthetic = attr.ib(
+ type=bool,
+ validator=type_validator())
+ metadata = attr.ib(
+ type=Optional[Dict[str, object]],
+ validator=type_validator(),
+ default=None)
+ parents = attr.ib(
+ type=List[Sha1Git],
+ validator=type_validator(),
+ default=attr.Factory(list))
+ id = attr.ib(
+ type=Sha1Git,
+ validator=type_validator(),
+ default=b'')
@staticmethod
def compute_hash(object_dict):
@@ -391,18 +469,30 @@
@attr.s(frozen=True)
class DirectoryEntry(BaseModel):
- name = attr.ib(type=bytes)
- type = attr.ib(type=str,
- validator=attr.validators.in_(['file', 'dir', 'rev']))
- target = attr.ib(type=Sha1Git)
- perms = attr.ib(type=int)
+ name = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ type = attr.ib(
+ type=str,
+ validator=attr.validators.in_(['file', 'dir', 'rev']))
+ target = attr.ib(
+ type=Sha1Git,
+ validator=type_validator())
+ perms = attr.ib(
+ type=int,
+ validator=type_validator())
"""Usually one of the values of `swh.model.from_disk.DentryPerms`."""
@attr.s(frozen=True)
class Directory(BaseModel, HashableObject):
- entries = attr.ib(type=List[DirectoryEntry])
- id = attr.ib(type=Sha1Git, default=b'')
+ entries = attr.ib(
+ type=List[DirectoryEntry],
+ validator=type_validator())
+ id = attr.ib(
+ type=Sha1Git,
+ validator=type_validator(),
+ default=b'')
@staticmethod
def compute_hash(object_dict):
@@ -461,22 +551,37 @@
@attr.s(frozen=True)
class Content(BaseContent):
- sha1 = attr.ib(type=bytes)
- sha1_git = attr.ib(type=Sha1Git)
- sha256 = attr.ib(type=bytes)
- blake2s256 = attr.ib(type=bytes)
-
- length = attr.ib(type=int)
+ sha1 = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ sha1_git = attr.ib(
+ type=Sha1Git,
+ validator=type_validator())
+ sha256 = attr.ib(
+ type=bytes,
+ validator=type_validator())
+ blake2s256 = attr.ib(
+ type=bytes,
+ validator=type_validator())
+
+ length = attr.ib(
+ type=int,
+ validator=type_validator())
status = attr.ib(
type=str,
- default='visible',
- validator=attr.validators.in_(['visible', 'hidden']))
+ validator=attr.validators.in_(['visible', 'hidden']),
+ default='visible')
- data = attr.ib(type=Optional[bytes], default=None)
+ data = attr.ib(
+ type=Optional[bytes],
+ validator=type_validator(),
+ default=None)
- ctime = attr.ib(type=Optional[datetime.datetime],
- default=None)
+ ctime = attr.ib(
+ type=Optional[datetime.datetime],
+ validator=type_validator(),
+ default=None)
@length.validator
def check_length(self, attribute, value):
@@ -518,24 +623,40 @@
@attr.s(frozen=True)
class SkippedContent(BaseContent):
- sha1 = attr.ib(type=Optional[bytes])
- sha1_git = attr.ib(type=Optional[Sha1Git])
- sha256 = attr.ib(type=Optional[bytes])
- blake2s256 = attr.ib(type=Optional[bytes])
-
- length = attr.ib(type=Optional[int])
+ sha1 = attr.ib(
+ type=Optional[bytes],
+ validator=type_validator())
+ sha1_git = attr.ib(
+ type=Optional[Sha1Git],
+ validator=type_validator())
+ sha256 = attr.ib(
+ type=Optional[bytes],
+ validator=type_validator())
+ blake2s256 = attr.ib(
+ type=Optional[bytes],
+ validator=type_validator())
+
+ length = attr.ib(
+ type=Optional[int],
+ validator=type_validator())
status = attr.ib(
type=str,
validator=attr.validators.in_(['absent']))
- reason = attr.ib(type=Optional[str],
- default=None)
-
- origin = attr.ib(type=Optional[Origin],
- default=None)
-
- ctime = attr.ib(type=Optional[datetime.datetime],
- default=None)
+ reason = attr.ib(
+ type=Optional[str],
+ validator=type_validator(),
+ default=None)
+
+ origin = attr.ib(
+ type=Optional[Origin],
+ validator=type_validator(),
+ default=None)
+
+ ctime = attr.ib(
+ type=Optional[datetime.datetime],
+ validator=type_validator(),
+ default=None)
@reason.validator
def check_reason(self, attribute, value):

File Metadata

Mime Type
text/plain
Expires
Wed, Sep 17, 4:55 PM (6 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3222811

Event Timeline