From e558aeb68298cbcc4d6199bcd8c6f1c4ffa6123b Mon Sep 17 00:00:00 2001 From: JohnVonNeumann Date: Tue, 16 Jul 2024 10:43:33 +1000 Subject: [PATCH] UPDATE product_footprint.py - implement preceding_pf_ids attribute --- .../product_footprint/product_footprint.py | 12 +++++ .../test_product_footprint.py | 53 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/pathfinder_framework/product_footprint/product_footprint.py b/pathfinder_framework/product_footprint/product_footprint.py index ed5f618..11eeac8 100644 --- a/pathfinder_framework/product_footprint/product_footprint.py +++ b/pathfinder_framework/product_footprint/product_footprint.py @@ -34,6 +34,7 @@ class ProductFootprint: comment (str): A comment about the ProductFootprint. extensions (list[DataModelExtension]): A list of DataModelExtension objects. pcf (CarbonFootprint): The carbon footprint of the given product with value conforming to the data type CarbonFootprint. + preceding_pf_ids (list[ProductFootprintId]): A list of preceding ProductFootprintIds. """ def __init__( @@ -56,6 +57,7 @@ def __init__( comment: str, extensions: list[DataModelExtension], pcf: CarbonFootprint, + preceding_pf_ids: list[ProductFootprintId] | None = None, ): """ Initializes a new ProductFootprint instance. @@ -78,6 +80,7 @@ def __init__( comment (str): A comment about the ProductFootprint. extensions (list[DataModelExtension]): A list of DataModelExtension objects. pcf (CarbonFootprint): The carbon footprint of the given product with value conforming to the data type CarbonFootprint. + preceding_pf_ids (list[ProductFootprintId] | None): A list of preceding ProductFootprintIds. """ if not isinstance(pcf, CarbonFootprint): @@ -123,6 +126,14 @@ def __init__( if not isinstance(pcf, CarbonFootprint): raise ValueError("pcf must be an instance of CarbonFootprint") + if preceding_pf_ids is not None: + if not isinstance(preceding_pf_ids, list) or not all( + isinstance(pf_id, ProductFootprintId) for pf_id in preceding_pf_ids + ): + raise ValueError("preceding_pf_ids must be a list of ProductFootprintId") + if len(preceding_pf_ids) != len(set(preceding_pf_ids)): + raise ValueError("preceding_pf_ids must not contain duplicates") + self.id = id if id else ProductFootprintId() self.spec_version = spec_version self.version = version @@ -140,6 +151,7 @@ def __init__( self.comment = comment self.extensions = extensions self.pcf = pcf + self.preceding_pf_ids = preceding_pf_ids def __repr__(self) -> str: """Returns a string representation of the ProductFootprint instance.""" diff --git a/tests/product_footprint/test_product_footprint.py b/tests/product_footprint/test_product_footprint.py index 2986405..f8b26e1 100644 --- a/tests/product_footprint/test_product_footprint.py +++ b/tests/product_footprint/test_product_footprint.py @@ -151,6 +151,7 @@ def valid_product_footprint_data(valid_carbon_footprint_data): "comment": "This is a comment", "extensions": extensions, "pcf": CarbonFootprint(**valid_carbon_footprint_data), + "preceding_pf_ids": [ProductFootprintId(), ProductFootprintId()], } @@ -180,6 +181,10 @@ def test_product_footprint_initialization(valid_product_footprint_data): isinstance(ext, DataModelExtension) for ext in product_footprint.extensions ) assert isinstance(product_footprint.pcf, CarbonFootprint) + assert isinstance(product_footprint.preceding_pf_ids, list) + assert all( + isinstance(pf_id, ProductFootprintId) for pf_id in product_footprint.preceding_pf_ids + ) def test_product_footprint_spec_version(valid_product_footprint_data): @@ -585,3 +590,51 @@ def test_product_footprint_invalid_pcf(valid_product_footprint_data, pcf): invalid_product_footprint_data = {**valid_product_footprint_data, "pcf": pcf} with pytest.raises(ValueError, match="pcf must be an instance of CarbonFootprint"): ProductFootprint(**invalid_product_footprint_data) + + +@pytest.mark.parametrize( + "preceding_pf_ids", + [ + [ProductFootprintId(), ProductFootprintId()], # list with multiple items + [], # empty list + ], +) +def test_product_footprint_preceding_pf_ids(valid_product_footprint_data, preceding_pf_ids): + product_footprint_data = { + **valid_product_footprint_data, + "preceding_pf_ids": preceding_pf_ids, + } + product_footprint = ProductFootprint(**product_footprint_data) + assert len(product_footprint.preceding_pf_ids) == len(preceding_pf_ids) + for pf_id in product_footprint.preceding_pf_ids: + assert isinstance(pf_id, ProductFootprintId) + + +@pytest.mark.parametrize( + "preceding_pf_ids", + [ + 123, + 1.0, + "string", + {}, + ProductFootprintId(), + ], +) +def test_product_footprint_invalid_preceding_pf_ids(valid_product_footprint_data, preceding_pf_ids): + invalid_product_footprint_data = { + **valid_product_footprint_data, + "preceding_pf_ids": preceding_pf_ids, + } + with pytest.raises(ValueError, match="preceding_pf_ids must be a list of ProductFootprintId"): + ProductFootprint(**invalid_product_footprint_data) + + +def test_product_footprint_duplicate_preceding_pf_ids(valid_product_footprint_data): + pf_id = ProductFootprintId() + preceding_pf_ids = [pf_id, pf_id] + product_footprint_data = { + **valid_product_footprint_data, + "preceding_pf_ids": preceding_pf_ids, + } + with pytest.raises(ValueError, match="preceding_pf_ids must not contain duplicates"): + ProductFootprint(**product_footprint_data)