From 34b6c19d072a8e3eff0c647132090a6763709938 Mon Sep 17 00:00:00 2001 From: Daniel Flehner Heen Date: Wed, 13 Mar 2024 14:44:26 +0100 Subject: [PATCH] Remove parent strategy (#14) * Make sure validation checks all canvases from all contexts * removed parent variable * make sure FDLValidationError if validation fails... * refactored tests for canvas.source_canvas_id --------- Signed-off-by: apetrynet --- src/pyfdl/base.py | 11 ++--------- src/pyfdl/canvas.py | 30 +----------------------------- src/pyfdl/canvas_template.py | 12 +----------- src/pyfdl/framing_decision.py | 12 +----------- src/pyfdl/framing_intent.py | 12 +----------- src/pyfdl/pyfdl.py | 32 +++++++++++++++++++------------- tests/test_canvas.py | 32 +++++++++++++------------------- 7 files changed, 38 insertions(+), 103 deletions(-) diff --git a/src/pyfdl/base.py b/src/pyfdl/base.py index 4dda438..1924a3b 100644 --- a/src/pyfdl/base.py +++ b/src/pyfdl/base.py @@ -123,11 +123,10 @@ def to_dict(self) -> dict: return data @classmethod - def from_dict(cls, raw: dict, parent: Any = None) -> Any: + def from_dict(cls, raw: dict) -> Any: """Create instances of classes from a provided dict. Args: - parent: is used in collections of items raw: dictionary to convert to supported classes Returns: @@ -149,23 +148,19 @@ def from_dict(cls, raw: dict, parent: Any = None) -> Any: tc = TypedCollection(_cls) for item in value: - tc.add_item(_cls.from_dict(item, parent=tc)) + tc.add_item(_cls.from_dict(item)) value = tc else: value = cls.object_map[key].from_dict(value) kwargs[keyword] = value - if parent: - kwargs['parent'] = parent - return cls(**kwargs) @staticmethod def generate_uuid(): return str(uuid.uuid4()) - @abstractmethod def __repr__(self) -> str: pass @@ -215,8 +210,6 @@ def add_item(self, item: Any): else: raise FDLError(f"Item must have a valid identifier (\"{self._cls.id_attribute}\"), not None or empty string") - item.parent = self - def get_item(self, item_id: str) -> Union[Any, None]: """Get an item in the collection diff --git a/src/pyfdl/canvas.py b/src/pyfdl/canvas.py index 1f4bb5e..20b2a1b 100644 --- a/src/pyfdl/canvas.py +++ b/src/pyfdl/canvas.py @@ -40,10 +40,8 @@ def __init__( photosite_dimensions: DimensionsInt = None, physical_dimensions: DimensionsFloat = None, anamorphic_squeeze: float = None, - framing_decisions: TypedCollection = None, - parent: TypedCollection = None + framing_decisions: TypedCollection = None ): - self.parent = parent self.label = label self.id = _id self.source_canvas_id = source_canvas_id @@ -128,31 +126,5 @@ def get_dimensions(self) -> Tuple[DimensionsInt, Point]: return self.dimensions, Point(x=0, y=0) - @property - def parent(self) -> Union[TypedCollection, None]: - return self._parent - - @parent.setter - def parent(self, parent: TypedCollection): - self._parent = parent - - @property - def source_canvas_id(self) -> str: - return self._source_canvas_id - - @source_canvas_id.setter - def source_canvas_id(self, canvas_id: str): - if not canvas_id: - return - - if self.parent and canvas_id in self.parent or canvas_id == self.id: - self._source_canvas_id = canvas_id - - else: - raise FDLError( - f'"source_canvas_id" {canvas_id} must either be self.id or the id of another canvas in ' - f'the registered canvases. {self.parent}' - ) - def __repr__(self): return f'{self.__class__.__name__}(label="{self.label}", id="{self.id}")' diff --git a/src/pyfdl/canvas_template.py b/src/pyfdl/canvas_template.py index d3de7bc..6d83f8c 100644 --- a/src/pyfdl/canvas_template.py +++ b/src/pyfdl/canvas_template.py @@ -49,10 +49,8 @@ def __init__( preserve_from_source_canvas: str = None, maximum_dimensions: DimensionsInt = None, pad_to_maximum: bool = False, - _round: RoundStrategy = None, - parent: TypedCollection = None + _round: RoundStrategy = None ): - self.parent = parent self.label = label self.id = _id self.target_dimensions = target_dimensions @@ -66,14 +64,6 @@ def __init__( self.pad_to_maximum = pad_to_maximum self.round = _round - @property - def parent(self) -> Union[TypedCollection, None]: - return self._parent - - @parent.setter - def parent(self, parent: TypedCollection): - self._parent = parent - @property def fit_source(self) -> str: return self._fit_source diff --git a/src/pyfdl/framing_decision.py b/src/pyfdl/framing_decision.py index bd87aaf..240fd69 100644 --- a/src/pyfdl/framing_decision.py +++ b/src/pyfdl/framing_decision.py @@ -30,10 +30,8 @@ def __init__( dimensions: DimensionsFloat = None, anchor_point: Point = None, protection_dimensions: DimensionsFloat = None, - protection_anchor_point: Point = None, - parent: TypedCollection = None + protection_anchor_point: Point = None ): - self.parent = parent self.label = label self.id = _id self.framing_intent_id = framing_intent_id @@ -42,14 +40,6 @@ def __init__( self.protection_dimensions = protection_dimensions self.protection_anchor_point = protection_anchor_point - @property - def parent(self) -> Union[TypedCollection, None]: - return self._parent - - @parent.setter - def parent(self, parent: TypedCollection): - self._parent = parent - def __eq__(self, other): return ( self.id == other.id and diff --git a/src/pyfdl/framing_intent.py b/src/pyfdl/framing_intent.py index eddffd7..959596e 100644 --- a/src/pyfdl/framing_intent.py +++ b/src/pyfdl/framing_intent.py @@ -16,23 +16,13 @@ def __init__( label: str = None, _id: str = None, aspect_ratio: DimensionsInt = None, - protection: float = None, - parent: TypedCollection = None + protection: float = None ): - self.parent = parent self.id = _id self.label = label self.aspect_ratio = aspect_ratio self.protection = protection - @property - def parent(self) -> Union[TypedCollection, None]: - return self._parent - - @parent.setter - def parent(self, parent: TypedCollection): - self._parent = parent - def __repr__(self): return (f'{self.__class__.__name__}(' f'label="{self.label}", ' diff --git a/src/pyfdl/pyfdl.py b/src/pyfdl/pyfdl.py index b1eca3f..3f7151a 100644 --- a/src/pyfdl/pyfdl.py +++ b/src/pyfdl/pyfdl.py @@ -122,21 +122,27 @@ def validate(self): errors = [] # Check internal relations - for context in self.contexts: - for canvas in context.canvases: - if canvas.source_canvas_id not in context.canvases: + canvases = TypedCollection(Canvas) + canvas_collections = [context.canvases for context in self.contexts] + + for canvas_collection in canvas_collections: + for canvas in canvas_collection: + canvases.add_item(canvas) + + for canvas in canvases: + if canvases.get_item(canvas.source_canvas_id) is None: + errors.append( + f'{canvas.source_canvas_id} (canvas.source_canvas_id) not found in ' + f'registered canvases' + ) + + for framing_decision in canvas.framing_decisions: + if framing_decision.framing_intent_id not in self.framing_intents: errors.append( - f'{canvas}.source_canvas_id (canvas.source_canvas_id) not found in ' - f'registered canvases' + f'{framing_decision}.framing_intent_id ({framing_decision.framing_intent_id}) ' + f'not found in registered framing intents' ) - for framing_decision in canvas.framing_decisions: - if framing_decision.framing_intent_id not in self.framing_intents: - errors.append( - f'{framing_decision}.framing_intent_id ({framing_decision.framing_intent_id}) ' - f'not found in registered framing intents' - ) - # Check structure and values against json schema v = jsonschema.validators.validator_for(self._schema) validator = v(schema=self._schema, format_checker=v.FORMAT_CHECKER) @@ -145,7 +151,7 @@ def validate(self): if errors: nl = '\n' - FDLValidationError( + raise FDLValidationError( f"Validation failed!\n" f"{f'{nl}'.join(errors)}" ) diff --git a/tests/test_canvas.py b/tests/test_canvas.py index 621bebd..b2301f5 100644 --- a/tests/test_canvas.py +++ b/tests/test_canvas.py @@ -29,31 +29,25 @@ def test_canvas_linked_requirements(sample_canvas_kwargs): assert canvas.check_required() == [] -def test_source_canvas_id(sample_canvas_kwargs): - tc = pyfdl.TypedCollection(pyfdl.Canvas) +def test_source_canvas_id(sample_canvas_kwargs, sample_canvas): + fdl = pyfdl.FDL() + fdl.apply_defaults() - kwargs = sample_canvas_kwargs.copy() - _id = kwargs.pop('source_canvas_id') - cv1 = pyfdl.Canvas(**kwargs) - tc.add_item(cv1) - # This should fail because a canvas with id 123 is not in container - with pytest.raises(pyfdl.FDLError) as err: - cv1.source_canvas_id = '123' + canvas1 = pyfdl.Canvas.from_dict(sample_canvas) - assert '"source_canvas_id" 123 must either be self.id' in str(err.value) - cv1.source_canvas_id = _id + fdl.place_canvas_in_context(context_label="context1", canvas=canvas1) + assert fdl.validate() is None - kwargs['_id'] = '123' - cv2 = pyfdl.Canvas(**kwargs) + canvas2 = pyfdl.Canvas.from_dict(sample_canvas) + canvas2.id = "456" + canvas2.source_canvas_id = "123" - # This should fail because cv2 is not in a container and id is not equal its own - with pytest.raises(pyfdl.FDLError) as err: - cv2.source_canvas_id = cv1.id + fdl.place_canvas_in_context(context_label="context2", canvas=canvas2) - assert f'"source_canvas_id" {cv1.id} must either be self.id' in str(err.value) + with pytest.raises(pyfdl.FDLValidationError) as err: + fdl.validate() - tc.add_item(cv2) - cv2.source_canvas_id = cv1.id + assert f'{canvas2.source_canvas_id} (canvas.source_canvas_id) not found in ' in str(err) def test_place_framing_intent(sample_framing_intent, sample_canvas, sample_framing_decision):