diff --git a/advanced_alchemy/service/_async.py b/advanced_alchemy/service/_async.py index fd6e13b0..5fcbf808 100644 --- a/advanced_alchemy/service/_async.py +++ b/advanced_alchemy/service/_async.py @@ -473,6 +473,10 @@ def filter_unset(attr: Any, value: Any) -> bool: # noqa: ARG001 **asdict(data, filter=filter_unset), ) + # Check if data is already an instance of the expected model type + if isinstance(data, self.model_type): + return cast("ModelT", data) + # Fallback for objects with __dict__ (e.g., regular classes) if hasattr(data, "__dict__"): return model_from_dict( diff --git a/advanced_alchemy/service/_sync.py b/advanced_alchemy/service/_sync.py index 98456594..76e8467b 100644 --- a/advanced_alchemy/service/_sync.py +++ b/advanced_alchemy/service/_sync.py @@ -472,6 +472,10 @@ def filter_unset(attr: Any, value: Any) -> bool: # noqa: ARG001 **asdict(data, filter=filter_unset), ) + # Check if data is already an instance of the expected model type + if isinstance(data, self.model_type): + return cast("ModelT", data) + # Fallback for objects with __dict__ (e.g., regular classes) if hasattr(data, "__dict__"): return model_from_dict( diff --git a/tests/integration/test_repository.py b/tests/integration/test_repository.py index d92d9504..addae5f9 100644 --- a/tests/integration/test_repository.py +++ b/tests/integration/test_repository.py @@ -339,7 +339,10 @@ async def test_repo_update_method(seeded_test_session_async: "tuple[AsyncSession # Get first author authors = await maybe_async(author_repo.list()) author = authors[0] + original_name = author.name + original_created_at = author.created_at + original_updated_at = author.updated_at # Update the author author.name = "Updated Name" @@ -347,6 +350,8 @@ async def test_repo_update_method(seeded_test_session_async: "tuple[AsyncSession assert updated_author.name == "Updated Name" assert updated_author.name != original_name + assert updated_author.created_at == original_created_at + assert updated_author.updated_at > original_updated_at async def test_repo_update_many_method_stale_data_fix( @@ -385,7 +390,7 @@ async def test_repo_update_many_method_stale_data_fix( # updated_at should be newer than before if updated_author.id == authors[0].id: assert updated_author.created_at == original_created_at - assert updated_author.updated_at >= original_updated_at + assert updated_author.updated_at > original_updated_at async def test_repo_update_many_mixed_types(seeded_test_session_async: "tuple[AsyncSession, dict[str, type]]") -> None: @@ -498,11 +503,18 @@ async def test_service_update_method(seeded_test_session_async: "tuple[AsyncSess author = authors[0] author_id = author.id + original_name = author.name + original_created_at = author.created_at + original_updated_at = author.updated_at + # Update via service - correct parameter order is (data, item_id) - update_data = {"name": "Service Updated Name"} - updated_author = await maybe_async(author_service.update(update_data, item_id=author_id)) + author.name = "Service Updated Name" + updated_author = await maybe_async(author_service.update(author, item_id=author_id)) assert updated_author.name == "Service Updated Name" + assert updated_author.name != original_name + assert updated_author.created_at == original_created_at + assert updated_author.updated_at > original_updated_at async def test_service_delete_method(seeded_test_session_async: "tuple[AsyncSession, dict[str, type]]") -> None: @@ -679,6 +691,10 @@ async def test_service_update_many_schema_types_github_535( original_dob1 = author1.dob original_dob2 = author2.dob + original_created_at1 = author1.created_at + original_created_at2 = author2.created_at + original_updated_at1 = author1.updated_at + original_updated_at2 = author2.updated_at # Get ID type from model for dynamic schema creation # For Pydantic compatibility, we need to map database-specific types to Python types @@ -720,9 +736,13 @@ class AuthorUpdateMsgspecSchema(msgspec.Struct): # type: ignore[name-defined,mi # Verify: names were updated, but dobs remain unchanged assert updated_author1.name == "Updated Author One" assert updated_author1.dob == original_dob1 # Should be unchanged + assert updated_author1.created_at == original_created_at1 + assert updated_author1.updated_at > original_updated_at1 assert updated_author2.name == "Updated Author Two" assert updated_author2.dob == original_dob2 # Should be unchanged + assert updated_author2.created_at == original_created_at2 + assert updated_author2.updated_at > original_updated_at2 async def test_repo_update_many_non_returning_backend_refresh(