diff --git a/pact_methodology/product_footprint/preceding_pf_ids.py b/pact_methodology/product_footprint/preceding_pf_ids.py new file mode 100644 index 0000000..5c9b0e9 --- /dev/null +++ b/pact_methodology/product_footprint/preceding_pf_ids.py @@ -0,0 +1,45 @@ +from typing import List, Set +from .id import ProductFootprintId + +class PrecedingPfIds: + def __init__(self, pf_ids: List[ProductFootprintId] = None): + """ + A collection of preceding product footprint identifiers. + + Attributes: + pf_ids (Set[ProductFootprintId]): The set of preceding product footprint identifiers. + + Raises: + ValueError: If the provided list contains non-unique or invalid ProductFootprintId objects. + """ + if pf_ids is None: + self.pf_ids = set() + else: + if not all(isinstance(pf_id, ProductFootprintId) for pf_id in pf_ids): + raise ValueError("All elements in pf_ids must be instances of ProductFootprintId") + if len(pf_ids) != len(set(pf_ids)): + raise ValueError("pf_ids must not contain duplicates") + self.pf_ids = set(pf_ids) + + def add(self, pf_id: ProductFootprintId): + """ + Add a new product footprint identifier to the collection. + + Args: + pf_id (ProductFootprintId): The product footprint identifier to add. + + Raises: + ValueError: If the provided product footprint identifier is not unique. + """ + if pf_id in self.pf_ids: + raise ValueError("pf_id already exists in the collection") + self.pf_ids.add(pf_id) + + def __iter__(self): + return iter(self.pf_ids) + + def __len__(self): + return len(self.pf_ids) + + def __repr__(self): + return f"PrecedingPfIds({list(self.pf_ids)})" \ No newline at end of file diff --git a/tests/product_footprint/test_preceding_pf_ids.py b/tests/product_footprint/test_preceding_pf_ids.py new file mode 100644 index 0000000..05f0465 --- /dev/null +++ b/tests/product_footprint/test_preceding_pf_ids.py @@ -0,0 +1,60 @@ +import pytest +from pact_methodology.product_footprint.preceding_pf_ids import PrecedingPfIds +from pact_methodology.product_footprint.id import ProductFootprintId + +def test_preceding_pf_ids_empty_initialization(): + pf_ids = PrecedingPfIds() + assert len(pf_ids) == 0 + +def test_preceding_pf_ids_initialization_with_valid_list(): + pf_id1 = ProductFootprintId() + pf_id2 = ProductFootprintId() + pf_ids = PrecedingPfIds([pf_id1, pf_id2]) + assert len(pf_ids) == 2 + assert pf_id1 in pf_ids + assert pf_id2 in pf_ids + +def test_preceding_pf_ids_initialization_with_invalid_list(): + with pytest.raises(ValueError, match="All elements in pf_ids must be instances of ProductFootprintId"): + PrecedingPfIds([ProductFootprintId(), "invalid_id"]) + +def test_preceding_pf_ids_initialization_with_duplicates(): + pf_id = ProductFootprintId() + with pytest.raises(ValueError, match="pf_ids must not contain duplicates"): + PrecedingPfIds([pf_id, pf_id]) + +def test_preceding_pf_ids_add_method(): + pf_id1 = ProductFootprintId() + pf_id2 = ProductFootprintId() + pf_ids = PrecedingPfIds([pf_id1]) + pf_ids.add(pf_id2) + assert len(pf_ids) == 2 + assert pf_id1 in pf_ids + assert pf_id2 in pf_ids + +def test_preceding_pf_ids_add_duplicate_method(): + pf_id = ProductFootprintId() + pf_ids = PrecedingPfIds([pf_id]) + with pytest.raises(ValueError, match="pf_id already exists in the collection"): + pf_ids.add(pf_id) + +def test_preceding_pf_ids_iter(): + pf_id1 = ProductFootprintId() + pf_id2 = ProductFootprintId() + pf_ids = PrecedingPfIds([pf_id1, pf_id2]) + iter_pf_ids = list(pf_ids) + assert len(iter_pf_ids) == 2 + assert pf_id1 in iter_pf_ids + assert pf_id2 in iter_pf_ids + +def test_preceding_pf_ids_len(): + pf_id1 = ProductFootprintId() + pf_id2 = ProductFootprintId() + pf_ids = PrecedingPfIds([pf_id1, pf_id2]) + assert len(pf_ids) == 2 + +def test_preceding_pf_ids_repr(): + pf_id1 = ProductFootprintId() + pf_id2 = ProductFootprintId() + pf_ids = PrecedingPfIds([pf_id1, pf_id2]) + assert repr(pf_ids) == f"PrecedingPfIds([{pf_id1!r}, {pf_id2!r}])" \ No newline at end of file