class PipelineSpec: tasks: Union[None, List[PipelineTask]] = attr.ib( default=None, validator=type_validator() ) params: Union[None, List[ParamSpec]] = attr.ib( default=None, validator=type_validator() )
class TriggerTemplateSpec: resourcetemplates: Union[None, List[TriggerResourceTemplates]] = attr.ib( default=None, validator=type_validator() ) params: Union[None, List[ParamSpec]] = attr.ib( default=None, validator=type_validator() )
class TaskSpec: steps: Union[None, List[Step]] = attr.ib(default=None, validator=type_validator()) params: Union[None, List[ParamSpec]] = attr.ib( default=None, validator=type_validator() ) resources: Union[None, List[Resources]] = attr.ib( default=None, validator=type_validator() )
class ParamSpec: name: Union[str, None] = attr.ib(default=None, validator=type_validator()) description: Union[str, None] = attr.ib(default=None, validator=type_validator()) default: Union[str, None] = attr.ib(default=None, validator=type_validator()) type: Union[ParamEnum, None] = attr.ib(default=None, validator=type_validator()) def ref(self) -> str: return f"$(params.{self.name})"
class FileObject(Base): name: Union[str, None] = attr.ib(default=None, validator=type_validator()) description: Union[str, None] = attr.ib(default=None, validator=type_validator()) apiVersion: str = attr.ib(default="tekton.dev/v1beta1", validator=type_validator()) def asdict(self): def get_delete(d, key): v = d[key] del d[key] return v def rewrite_if_fileobject(d): if "apiVersion" in d: # If there is an apiVersion it is a file object. Rearrange attributes # Move all keys to the spec spec = {} for (key, val) in d.items(): spec[key] = val for (key, val) in spec.items(): del d[key] # create the file level attributes d.update( { "metadata": {"name": get_delete(spec, "name")}, "kind": get_delete(spec, "kind"), "apiVersion": get_delete(spec, "apiVersion"), } ) if len(spec) > 0: d["spec"] = spec if "description" in spec: d["metadata"]["description"] = get_delete(spec, "description") def rewrite_fileobjects(d): if isinstance(d, dict): rewrite_if_fileobject(d) for (key, val) in d.items(): rewrite_fileobjects(val) if isinstance(d, list): for i in d: rewrite_fileobjects(i) root = attr.asdict(self, filter=lambda attr, value: value != None) # asdict returned a dictionary that is specified correctly except the Fileobjects rewrite_fileobjects(root) return root def to_yaml(self, **kwargs): if kwargs.get("check", True): self._semantic_check() return yaml_dump(self.asdict()) def _semantic_check(self): if self.name == None: raise MissingAttribute(f"{str(self.__class__)} must have a name") def ref(self) -> Ref: return Ref(self.name)
class PipelineRunSpec: params: Union[None, List[ParamSpec]] = attr.ib( default=None, validator=type_validator() ) pipelineRef: Union[None, Ref] = attr.ib(default=None, validator=type_validator()) pipelineSpec: Union[None, PipelineSpec] = attr.ib( default=None, validator=type_validator() ) serviceAccountName: Union[None, str] = attr.ib( default=None, validator=type_validator() )
def test_abc_mapping_types_throw_when_type_is_wrong(data, type, validator_type, error_message): class TestMapping(type): def __init__(self, items): self._data = items def __getitem__(self, item): return self._data[item] def __len__(self): return len(self._data) def __iter__(self): return iter(self._data) def __delitem__(self, item): pass def __setitem__(self, item, value): pass validator = type_validator() attr = MagicMock() attr.name = "zoo" attr.type = validator_type[str, str] with pytest.raises(ValueError) as error: validator(None, attr, TestMapping(data)) assert error_message in repr(error.value)
class ExtendedSWHID(_BaseSWHID[ExtendedObjectType]): """ Dataclass holding the relevant info associated to a SoftWare Heritage persistent IDentifier (SWHID). It extends `CoreSWHID`, by allowing non-standard object types; and should only be used internally to Software Heritage. Raises: swh.model.exceptions.ValidationError: In case of invalid object type or id To get the raw SWHID string from an instance of this class, use the :func:`str` function: >>> swhid = ExtendedSWHID( ... object_type=ExtendedObjectType.CONTENT, ... object_id=bytes.fromhex('8ff44f081d43176474b267de5451f2c2e88089d0'), ... ) >>> str(swhid) 'swh:1:cnt:8ff44f081d43176474b267de5451f2c2e88089d0' And vice-versa with :meth:`CoreSWHID.from_string`: >>> swhid == ExtendedSWHID.from_string( ... "swh:1:cnt:8ff44f081d43176474b267de5451f2c2e88089d0" ... ) True """ object_type = attr.ib( type=ExtendedObjectType, validator=type_validator(), converter=ExtendedObjectType, ) """the type of object the identifier points to"""
def test_abc_mapping_types_throw_when_type_is_wrong(data, type, validator_type, error_message): class TestMapping(type): def __init__(self, items): # noqa: N804 self._data = items def __getitem__(self, item): # noqa: N804 return self._data[item] def __len__(self): # noqa: N804 return len(self._data) # pragma: no cover def __iter__(self): # noqa: N804 return iter(self._data) def __delitem__(self, item): # noqa: N804,U100 ... def __setitem__(self, item, value): # noqa: N804,U100 ... validator = type_validator() attr = MagicMock() attr.name = "zoo" attr.type = validator_type[str, str] with pytest.raises(ValueError, match=re.escape(error_message)): validator(None, attr, TestMapping(data))
class OriginVisitStats(BaseSchedulerModel): """Represents an aggregated origin visits view.""" url = attr.ib(type=str, validator=[type_validator()], metadata={"primary_key": True}) visit_type = attr.ib(type=str, validator=[type_validator()], metadata={"primary_key": True}) last_successful = attr.ib(type=Optional[datetime.datetime], validator=type_validator(), default=None) last_visit = attr.ib(type=Optional[datetime.datetime], validator=type_validator(), default=None) last_visit_status = attr.ib( type=Optional[LastVisitStatus], validator=type_validator(), default=None, converter=convert_last_visit_status, ) last_scheduled = attr.ib( type=Optional[datetime.datetime], validator=[type_validator()], default=None, ) last_snapshot = attr.ib(type=Optional[bytes], validator=type_validator(), default=None) next_visit_queue_position = attr.ib(type=Optional[int], validator=type_validator(), default=None) next_position_offset = attr.ib(type=int, validator=type_validator(), default=4) successive_visits = attr.ib(type=int, validator=type_validator(), default=1) @last_successful.validator def check_last_successful(self, attribute, value): check_timestamptz(value) @last_visit.validator def check_last_visit(self, attribute, value): check_timestamptz(value)
def test_does_not_raise_when_container_is_empty_and_allowed(): items = [] validator = type_validator(True) attr = MagicMock() attr.type = typing.List[int] validator(None, attr, items)
def test_union_not_raise_for_correct_values(element, type_): validator = type_validator() attr = MagicMock() attr.name = "foo" attr.type = type_ validator(None, attr, element)
def test_list_of_valid_values_no_raise(values, type_): validator = type_validator() attrib = MagicMock() attrib.name = "numbers" attrib.type = type_ validator(None, attrib, values)
class SchedulerMetrics(BaseSchedulerModel): """Metrics for the scheduler, aggregated by (lister_id, visit_type)""" lister_id = attr.ib(type=UUID, validator=[type_validator()], metadata={"primary_key": True}) visit_type = attr.ib(type=str, validator=[type_validator()], metadata={"primary_key": True}) last_update = attr.ib( type=Optional[datetime.datetime], validator=[type_validator()], default=None, ) origins_known = attr.ib(type=int, validator=[type_validator()], default=0) """Number of known (enabled or disabled) origins""" origins_enabled = attr.ib(type=int, validator=[type_validator()], default=0) """Number of origins that were present in the latest listings""" origins_never_visited = attr.ib(type=int, validator=[type_validator()], default=0) """Number of enabled origins that have never been visited (according to the visit cache)""" origins_with_pending_changes = attr.ib(type=int, validator=[type_validator()], default=0) """Number of enabled origins with known activity (recorded by a lister)
def test_typing_newtype_single_validation_success(test_type, correct): SomeNew = typing.NewType("SomeNew", test_type) # noqa: N806 validator = type_validator() attr = MagicMock() attr.type = SomeNew validator(None, attr, correct) validator(None, attr, SomeNew(correct))
def test_typing_newtype_within_container_validation_success( container, test_type, correct): SomeNew = typing.NewType("SomeNew", test_type) validator = type_validator() attr = MagicMock() attr.type = container[SomeNew] validator(None, attr, correct)
def test_container_is_not_of_expected_type_raises_type_error( items, types, message): validator = type_validator() attr = MagicMock() attr.name = "Smth" attr.type = types with pytest.raises(ValueError, match=re.escape(message)): validator(None, attr, items)
def test_list_of_values_raise_value_error(values, type_, error_message): validator = type_validator() attrib = MagicMock() attrib.name = "numbers" attrib.type = type_ with pytest.raises(ValueError, match=re.escape(error_message)): validator(None, attrib, values)
def test_variable_length_tuple_empty(): element = () attr = MagicMock() attr.name = "foo" attr.type = Tuple[int, ...] validator = type_validator() validator(None, attr, element)
def test_literal_raises_for_invalid_type_arguments_to_literal( element, type_, error_message): validator = type_validator() attr = MagicMock() attr.name = "foo" attr.type = type_ with pytest.raises(ValueError, match=re.escape(error_message)): validator(None, attr, element)
def test_literal_when_type_is_not_specified_raises(element, type_, error_message): validator = type_validator() attr = MagicMock() attr.name = "foo" attr.type = type_ with pytest.raises(ValueError, match=re.escape(error_message)): validator(None, attr, element)
def test_dict_with_any_does_not_raise(): elem = {"foo": 123, "b": "abc"} validator = type_validator() attr = MagicMock() attr.name = "zoo" attr.type = Dict[str, Any] validator(None, attr, elem)
def test_raises_when_container_is_empty_and_empty_ok_is_false(): # GIVEN items = [] validator = type_validator(empty_ok=False) attr = MagicMock() attr.name = "Smth" attr.type = str msg = f"Smth can not be empty and must be {str} (got [])" with pytest.raises(ValueError, match=re.escape(msg)): validator(None, attr, items)
def test_raises_when_container_is_empty_and_empty_ok_is_false(): # GIVEN items = [] validator = type_validator(empty_ok=False) # WHEN with pytest.raises(ValueError) as error: validator(None, None, items) # THEN assert "Expected a non-empty attribute" == str(error.value)
def test_defaultdict_with_correct_type_no_raise(): elem = collections.defaultdict(int) elem[5] = [1, 2, 3] elem[6] = [4, 5, 6] validator = type_validator() attr = MagicMock() attr.name = "foo" attr.type = DefaultDict[int, List[int]] validator(None, attr, elem)
def test_typing_newtype_single_validation_failure(test_type, wrongs): SomeNew = typing.NewType("SomeNew", test_type) # noqa: N806 validator = type_validator() attr = MagicMock() attr.type = SomeNew for wrong in wrongs: with pytest.raises(AttributeTypeError) as error: validator(None, attr, wrong) assert f"must be NewType(SomeNew, {str(test_type)})" in str(error.value)
class Lister(BaseSchedulerModel): name = attr.ib(type=str, validator=[type_validator()]) instance_name = attr.ib(type=str, validator=[type_validator()]) # Populated by database id = attr.ib( type=Optional[UUID], validator=type_validator(), default=None, metadata={"auto_primary_key": True}, ) current_state = attr.ib(type=Dict[str, Any], validator=[type_validator()], factory=dict) created = attr.ib( type=Optional[datetime.datetime], validator=[type_validator()], default=None, metadata={"auto_now_add": True}, ) updated = attr.ib( type=Optional[datetime.datetime], validator=[type_validator()], default=None, metadata={"auto_now": True}, )
def test_container_is_not_of_expected_type_raises_TypeError( items, types, message): validator = type_validator() attr = MagicMock() attr.name = "Smth" attr.type = types with pytest.raises(ValueError) as error: validator(None, attr, items) repr_msg = "<{}>".format(message) assert repr_msg == repr(error.value)
def test_literal_raises_for_invalid_type_arguments_to_literal( element, type_, error_message): validator = type_validator() attr = MagicMock() attr.name = "foo" attr.type = type_ with pytest.raises(ValueError) as error: validator(None, attr, element) repr_msg = "<{}>".format(error_message) assert repr_msg == repr(error.value)
def test_literal_when_type_is_not_specified_raises(element, type_, error_message): validator = type_validator() attr = MagicMock() attr.name = "foo" attr.type = type_ with pytest.raises(ValueError) as error: validator(None, attr, element) repr_msg = "<{}>".format(error_message) assert repr_msg == repr(error.value)