Miksus / red-bird

Repository Patterns for Python
https://red-bird.readthedocs.io
MIT License
163 stars 22 forks source link

JSON repository appears to call item serialization twice on update vs. replace #50

Open gregoryfoster opened 1 year ago

gregoryfoster commented 1 year ago

Building on the JSONDirectoryRepo framework, I implemented a model with a Pydantic field_serializer to convert a Decimal value to string. That worked well when calling the BaseRepo methods to add or replace files in the repository, but I turned up an unusual error when attempting to call update. I haven't tried to track it down more because I am using replace as a workaround.

From what I can tell, it appears that the update call attempts to serialize the model twice, causing a failure when the field_serializer is handed a string instead of the expected Decimal value. That points to a likely unnecessary call to item_to_dict somewhere along the way, probably in the JSONDirectoryRepo override of update.

I'm new to the codebase, and using @ManiMozaffar's fork to support Pydantic v2 - but the error appears to be in the mainline codebase. I'll attach the traceback output as a comment for reference.

gregoryfoster commented 1 year ago
Traceback (most recent call last):
  File "[src]/model/transcript.py", line 47, in serialize_time_value
    return f"{time_value:.6f}"
           ^^^^^^^^^^^^^^^^^^^
ValueError: Unknown format code 'f' for object of type 'str'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/transcribe/transcribe.py", line 93, in <module>
    transcribe()
 ...
  File "/transcribe/command/add_speaker.py", line 71, in add_speaker
    transcripts_json_repo.update(transcript)
  File "/transcribe/.venv/lib/python3.11/site-packages/redbird/base.py", line 282, in update
    self.filter_by(**qry).update(**values)
  File "/transcribe/.venv/lib/python3.11/site-packages/redbird/templates.py", line 30, in update
    return self.repo.query_update(self.query_, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/transcribe/.venv/lib/python3.11/site-packages/redbird/repos/json.py", line 86, in query_update
    self.write_files(new_items)
  File "/transcribe/.venv/lib/python3.11/site-packages/redbird/repos/json.py", line 119, in write_files
    self.write_file(item)
  File "/transcribe/.venv/lib/python3.11/site-packages/redbird/repos/json.py", line 126, in write_file
    data = self.item_to_dict(item, exclude_unset=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/transcribe/.venv/lib/python3.11/site-packages/redbird/base.py", line 294, in item_to_dict
    return item.dict(exclude_unset=exclude_unset)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/transcribe/.venv/lib/python3.11/site-packages/typing_extensions.py", line 2562, in wrapper
    return __arg(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/transcribe/.venv/lib/python3.11/site-packages/pydantic/main.py", line 929, in dict
    return self.model_dump(
           ^^^^^^^^^^^^^^^^
  File "/transcribe/.venv/lib/python3.11/site-packages/pydantic/main.py", line 309, in model_dump
    return self.__pydantic_serializer__.to_python(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.PydanticSerializationError: Error calling function `serialize_time_value`: ValueError: Unknown format code 'f' for object of type 'str'