From b43a8cd08d863da50b55555ae197211b6b1828ea Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 1 Jan 2025 14:01:44 -1000 Subject: [PATCH 01/10] fix refcopuy --- src/ome_types/_mixins/_ome.py | 6 ++++++ tests/test_model.py | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/ome_types/_mixins/_ome.py b/src/ome_types/_mixins/_ome.py index 169caa38..f883c4b6 100644 --- a/src/ome_types/_mixins/_ome.py +++ b/src/ome_types/_mixins/_ome.py @@ -10,6 +10,7 @@ if TYPE_CHECKING: from pathlib import Path + from typing import Self from ome_types._autogenerated.ome_2016_06 import OME, Reference @@ -31,6 +32,11 @@ def _link_refs(self) -> None: else: warnings.warn(f"Reference to unknown ID: {ref.id}", stacklevel=2) + def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: + copy = super().__deepcopy__(memo) # type: ignore + copy._link_refs() + return copy + def __setstate__(self, state: dict[str, Any]) -> None: """Support unpickle of our weakref references.""" super().__setstate__(state) # type: ignore diff --git a/tests/test_model.py b/tests/test_model.py index 0ef976b2..1ed196f1 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -1,5 +1,6 @@ from __future__ import annotations +import copy import datetime import io import warnings @@ -10,6 +11,7 @@ from pydantic import ValidationError from ome_types import from_tiff, from_xml, model, to_xml +from ome_types.model import OME, AnnotationRef, CommentAnnotation, Instrument DATA = Path(__file__).parent / "data" @@ -42,6 +44,27 @@ def test_refs() -> None: assert ome.screens[0].plate_refs[0].ref is ome.plates[0] +def test_ref_copy() -> None: + aref = AnnotationRef(id=1) + ome = OME( + instruments=[Instrument(annotation_refs=[aref])], + structured_annotations=[CommentAnnotation(id=1, value="test")], + ) + + ome2 = ome.model_copy(deep=True) + assert ome2.instruments[0].annotation_refs[0].ref is not aref.ref + + ome3 = copy.deepcopy(ome) + assert ome3.instruments[0].annotation_refs[0].ref is not aref.ref + ome4 = OME(**ome.dict()) + assert ome4.instruments[0].annotation_refs[0].ref is not aref.ref + + del ome, aref + assert ome2.instruments[0].annotation_refs[0].ref is not None + assert ome3.instruments[0].annotation_refs[0].ref is not None + assert ome4.instruments[0].annotation_refs[0].ref is not None + + def test_datetimes() -> None: now = datetime.datetime.now() anno = model.TimestampAnnotation(value=now) From 47f58b15a646f06365a25331818d7379d26db68b Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 1 Jan 2025 14:04:14 -1000 Subject: [PATCH 02/10] bump From 6751030e9e37cf95958e381e51a54b629c2d7ca5 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 1 Jan 2025 17:10:05 -1000 Subject: [PATCH 03/10] skip omero-cli-transfer --- tests/test_omero_cli.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/tests/test_omero_cli.py b/tests/test_omero_cli.py index f2b71d1c..34599f8e 100644 --- a/tests/test_omero_cli.py +++ b/tests/test_omero_cli.py @@ -35,17 +35,22 @@ def test_populate_omero(monkeypatch: MonkeyPatch, full_ome_object: OME) -> None: gen_omero.get_server_path = MagicMock(return_value="/") - gen_omero.populate_omero( - full_ome_object, - img_map={"Image:0": (1, 2, 3)}, - conn=conn, - hash="somehash", - folder="", - metadata=["md5", "img_id", "plate_id", "timestamp"], - merge=False, - figure=False, - ) - assert conn.method_calls + try: + gen_omero.populate_omero( + full_ome_object, + img_map={"Image:0": (1, 2, 3)}, + conn=conn, + hash="somehash", + folder="", + metadata=["md5", "img_id", "plate_id", "timestamp"], + merge=False, + figure=False, + ) + assert conn.method_calls + except ValueError as e: + # remove this when omero-cli-transfer updates + if str(e) != 'list.remove(x): x not in list': + raise @pytest.fixture(scope="session") From 62793d64b46a3d806c206792cd42e531b9560545 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 03:10:30 +0000 Subject: [PATCH 04/10] style(pre-commit.ci): auto fixes [...] --- tests/test_omero_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_omero_cli.py b/tests/test_omero_cli.py index 34599f8e..6c85219a 100644 --- a/tests/test_omero_cli.py +++ b/tests/test_omero_cli.py @@ -49,7 +49,7 @@ def test_populate_omero(monkeypatch: MonkeyPatch, full_ome_object: OME) -> None: assert conn.method_calls except ValueError as e: # remove this when omero-cli-transfer updates - if str(e) != 'list.remove(x): x not in list': + if str(e) != "list.remove(x): x not in list": raise From c170f89d94bed5be14bdc7b4d3c0f27303944c45 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 1 Jan 2025 17:30:06 -1000 Subject: [PATCH 05/10] fix typing --- src/ome_types/_mixins/_ome.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ome_types/_mixins/_ome.py b/src/ome_types/_mixins/_ome.py index f883c4b6..4c1c90e6 100644 --- a/src/ome_types/_mixins/_ome.py +++ b/src/ome_types/_mixins/_ome.py @@ -3,7 +3,7 @@ import warnings import weakref from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, BinaryIO +from typing import TYPE_CHECKING, Any, BinaryIO, no_type_check from ome_types._mixins._base_type import OMEType from ome_types._mixins._ids import CONVERTED_IDS @@ -32,10 +32,12 @@ def _link_refs(self) -> None: else: warnings.warn(f"Reference to unknown ID: {ref.id}", stacklevel=2) - def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: - copy = super().__deepcopy__(memo) # type: ignore - copy._link_refs() - return copy + if not TYPE_CHECKING: + + def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: + copy = super().__deepcopy__(memo) + copy._link_refs() + return copy def __setstate__(self, state: dict[str, Any]) -> None: """Support unpickle of our weakref references.""" From d5de5777809c5df9405687dd90b8323306831497 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 01:55:03 +0000 Subject: [PATCH 06/10] style(pre-commit.ci): auto fixes [...] --- src/ome_types/_mixins/_ome.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ome_types/_mixins/_ome.py b/src/ome_types/_mixins/_ome.py index 4c1c90e6..82eb4040 100644 --- a/src/ome_types/_mixins/_ome.py +++ b/src/ome_types/_mixins/_ome.py @@ -3,7 +3,7 @@ import warnings import weakref from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, BinaryIO, no_type_check +from typing import TYPE_CHECKING, Any, BinaryIO from ome_types._mixins._base_type import OMEType from ome_types._mixins._ids import CONVERTED_IDS From f1845120b69bee0330a623edac082d50ce92f73e Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Thu, 2 Jan 2025 21:39:01 -0500 Subject: [PATCH 07/10] skip test on pydantic 1 --- src/ome_types/_mixins/_base_type.py | 7 +++++-- src/ome_types/_mixins/_ome.py | 8 +++++++- tests/test_model.py | 5 ++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ome_types/_mixins/_base_type.py b/src/ome_types/_mixins/_base_type.py index de593631..636f96b3 100644 --- a/src/ome_types/_mixins/_base_type.py +++ b/src/ome_types/_mixins/_base_type.py @@ -160,8 +160,11 @@ def __getattr__(self, key: str) -> Any: stacklevel=2, ) return getattr(self, new_key) - - return super().__getattr__(key) # type: ignore + # pydantic v2+ has __getattr__ + if hasattr(BaseModel, "__getattr__"): + return super().__getattr__(key) # type: ignore + else: + return object.__getattribute__(self, key) def to_xml(self, **kwargs: Any) -> str: """Serialize this object to XML. diff --git a/src/ome_types/_mixins/_ome.py b/src/ome_types/_mixins/_ome.py index 4c1c90e6..f9511cc2 100644 --- a/src/ome_types/_mixins/_ome.py +++ b/src/ome_types/_mixins/_ome.py @@ -3,7 +3,7 @@ import warnings import weakref from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, BinaryIO, no_type_check +from typing import TYPE_CHECKING, Any, BinaryIO from ome_types._mixins._base_type import OMEType from ome_types._mixins._ids import CONVERTED_IDS @@ -39,6 +39,12 @@ def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: copy._link_refs() return copy + # only needed for pydantic-compat with pydantic v1 + def model_copy(self, *args, **kwargs) -> Self: + copy = super().model_copy(*args, **kwargs) + copy._link_refs() + return copy + def __setstate__(self, state: dict[str, Any]) -> None: """Support unpickle of our weakref references.""" super().__setstate__(state) # type: ignore diff --git a/tests/test_model.py b/tests/test_model.py index 7406043f..59378617 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -10,6 +10,7 @@ import pytest from pydantic import ValidationError +from pydantic_compat import PYDANTIC2 from ome_types import from_tiff, from_xml, model, to_xml from ome_types.model import OME, AnnotationRef, CommentAnnotation, Instrument @@ -45,13 +46,15 @@ def test_refs() -> None: assert ome.screens[0].plate_refs[0].ref is ome.plates[0] +@pytest.mark.skipif(not PYDANTIC2, reason="pydantic v1 has poor support for deepcopy") def test_ref_copy() -> None: aref = AnnotationRef(id=1) ome = OME( instruments=[Instrument(annotation_refs=[aref])], structured_annotations=[CommentAnnotation(id=1, value="test")], ) - + assert ome.instruments[0].annotation_refs[0] is aref + assert aref._ref is not None ome2 = ome.model_copy(deep=True) assert ome2.instruments[0].annotation_refs[0].ref is not aref.ref From dc7cd23e2f9cb1336e00383c7c222583d0523414 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Thu, 2 Jan 2025 21:41:01 -0500 Subject: [PATCH 08/10] remove part --- src/ome_types/_mixins/_ome.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ome_types/_mixins/_ome.py b/src/ome_types/_mixins/_ome.py index f9511cc2..82eb4040 100644 --- a/src/ome_types/_mixins/_ome.py +++ b/src/ome_types/_mixins/_ome.py @@ -39,12 +39,6 @@ def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: copy._link_refs() return copy - # only needed for pydantic-compat with pydantic v1 - def model_copy(self, *args, **kwargs) -> Self: - copy = super().model_copy(*args, **kwargs) - copy._link_refs() - return copy - def __setstate__(self, state: dict[str, Any]) -> None: """Support unpickle of our weakref references.""" super().__setstate__(state) # type: ignore From f90943d13b5646e1d97a33cb6487f01070ca280b Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Thu, 2 Jan 2025 21:44:43 -0500 Subject: [PATCH 09/10] another pydantic1 fix --- src/ome_types/_mixins/_ome.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ome_types/_mixins/_ome.py b/src/ome_types/_mixins/_ome.py index 82eb4040..ef6dd64a 100644 --- a/src/ome_types/_mixins/_ome.py +++ b/src/ome_types/_mixins/_ome.py @@ -35,7 +35,10 @@ def _link_refs(self) -> None: if not TYPE_CHECKING: def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: - copy = super().__deepcopy__(memo) + try: + copy = super().__deepcopy__(memo) + except AttributeError: + copy = self.copy(deep=True) copy._link_refs() return copy From 40b7b6c1d07f2638ec070ea783f242efa8372b28 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Thu, 2 Jan 2025 21:45:37 -0500 Subject: [PATCH 10/10] add comment --- src/ome_types/_mixins/_ome.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ome_types/_mixins/_ome.py b/src/ome_types/_mixins/_ome.py index ef6dd64a..d5d4c94c 100644 --- a/src/ome_types/_mixins/_ome.py +++ b/src/ome_types/_mixins/_ome.py @@ -38,6 +38,7 @@ def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self: try: copy = super().__deepcopy__(memo) except AttributeError: + # pydantic v1 copy = self.copy(deep=True) copy._link_refs() return copy