nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: niconoe/pyinaturalist
Pull request #389 (2022-05-26 18:26:19)

Fix BaseModel.copy to not recursively convert nested objects back into dicts


Patch:
diff --git a/pyinaturalist/models/base.py b/pyinaturalist/models/base.py
index 4dd96b7..1d5c9de 100644
--- a/pyinaturalist/models/base.py
+++ b/pyinaturalist/models/base.py
@@ -8,7 +8,7 @@ from os.path import expanduser
 from pathlib import Path
 from typing import Dict, Generic, List, Type, TypeVar
 
-from attr import Factory, asdict, define, field, fields, fields_dict
+from attr import Factory, asdict, define, field, fields_dict
 
 from pyinaturalist.constants import (
     DATETIME_SHORT_FORMAT,
@@ -81,17 +81,19 @@ class BaseModel:
         """Get the subset of attribute names to show in the model's string representation"""
         raise NotImplementedError
 
-    def to_dict(self, **kwargs) -> JsonResponse:
+    def to_dict(self, recurse: bool = True) -> JsonResponse:
         """Convert this object back to dict format"""
 
         def vs(_inst, _key, value):
             return value.to_dict() if isinstance(value, BaseModel) else value
 
-        obj_dict = asdict(self, value_serializer=vs, retain_collection_types=True, **kwargs)
-        for a in fields(self.__class__):
-            if a.init is False:
-                obj_dict.pop(a.name, None)
-
+        obj_dict = asdict(
+            self,
+            filter=lambda a, _: a.init is True,
+            retain_collection_types=True,
+            recurse=recurse,
+            value_serializer=vs if recurse else None,
+        )
         return {k.lstrip('_'): v for k, v in obj_dict.items()}
 
     def __rich_repr__(self):


Test patch:
diff --git a/test/test_models.py b/test/test_models.py
index 9982140..7ca6ccb 100644
--- a/test/test_models.py
+++ b/test/test_models.py
@@ -663,6 +663,18 @@ def test_taxon__update_from_full_record():
     pass
 
 
+def test_taxon_count__copy():
+    """When an IconPhoto is used in place of a missing Taxon.default_photo, and the taxon is copied
+    into a TaxonCount object, the IconPhoto object should be copied as-is instead of converting
+    back to a dict and then into a Photo.
+    """
+    taxon = Taxon(id=1, iconic_taxon_id=3)
+    taxon_counts = TaxonCount.copy(taxon)
+    assert isinstance(taxon.default_photo, IconPhoto)
+    assert isinstance(taxon_counts.default_photo, IconPhoto)
+    assert taxon.default_photo.medium_url == taxon_counts.default_photo.medium_url
+
+
 def test_taxon_counts__converters():
     taxon_counts = TaxonCounts.from_json(j_obs_species_counts)
     assert taxon_counts.data[0] == taxon_counts[0]