Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Bump Pydantic to v2 #49

Closed
wants to merge 62 commits into from
Closed

Conversation

lmmx
Copy link

@lmmx lmmx commented Jan 20, 2024

  • chore: upgrade Pydantic pin to 2.5.3 and fastapi to 0.109.0
  • fix: comment out pre-v2 Pydantic patch calls

@lmmx lmmx changed the title Bump Pydantic to v2 chore: Bump Pydantic to v2 Jan 20, 2024
@lmmx
Copy link
Author

lmmx commented Jan 24, 2024

Adding the model validators works well but when the field validators are sent as well, an infinite recursion bug appears.

In commit 853a93d I commented out the body of the field_validators dict, so it is created as an empty dict and the field validators (a single one named validate_epochs simply does not get serialised, so the test fails due to missing this feature.

Click to show pytest failure
============================= test session starts ==============================
platform linux -- Python 3.11.7, pytest-7.4.4, pluggy-1.3.0
rootdir: /home/louis/dev/fal/pydantic-2-bump/projects/fal/tests
plugins: asyncio-0.23.3, anyio-4.2.0
asyncio: mode=Mode.STRICT
collected 1 item

test_pydantic.py F                                                       [100%]

=================================== FAILURES ===================================
_______________________ test_deserialise_pydantic_model ________________________

    def test_deserialise_pydantic_model():
        """Test deserialisation of a Pydantic model succeeds.
    
        The deserialisation failure mode reproduction is incompatible with pytest (see
        [#29](https://github.com/fal-ai/fal/issues/29#issuecomment-1902241217) for
        discussion) so we directly invoke the current Python executable on this file.
        """
        subprocess_args = [sys.executable, __file__, "--run-deserialisation-test"]
        proc = subprocess.run(subprocess_args, capture_output=True, text=True)
        model_fields_ok = "model-field-missing-annotation" not in proc.stderr
        assert model_fields_ok, "Deserialisation failed (`model_fields` not deserialised)"
        # The return code should be zero or else the deserialisation failed
        deserialisation_ok = proc.returncode == 0
>       assert deserialisation_ok, f"Pydantic model deserialisation failed:\n{proc.stderr}"
E       AssertionError: Pydantic model deserialisation failed:
E         /home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/pydantic/main.py:1406: RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"
E           warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
E         Traceback (most recent call last):
E           File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/test_pydantic.py", line 192, in <module>
E             validate_deserialisation(model)
E           File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/test_pydantic.py", line 169, in validate_deserialisation
E             assert model.epochs == 30, "The `validate_epochs` field validator didn't run"
E                    ^^^^^^^^^^^^^^^^^^
E         AssertionError: The `validate_epochs` field validator didn't run
E         
E       assert False

test_pydantic.py:187: AssertionError
=========================== short test summary info ============================
FAILED test_pydantic.py::test_deserialise_pydantic_model - AssertionError: Py...
============================== 1 failed in 0.15s ===============================

We can reproduce it directly:

$ python test_pydantic.py --run-deserialisation-test
===== DESERIALIZING =====
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/pydantic/main.py:1406: RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"
  warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
===== INSTANTIATING =====
Traceback (most recent call last):
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/test_pydantic.py", line 192, in <module>
    validate_deserialisation(model)
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/test_pydantic.py", line 169, in validate_deserialisation
    assert model.epochs == 30, "The `validate_epochs` field validator didn't run"
           ^^^^^^^^^^^^^^^^^^
AssertionError: The `validate_epochs` field validator didn't run
  • The warning says that we are creating a field named __annotations__ !

RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"

In commit 3c71e6c I got the field validator in question to deserialise, but it still doesn't trigger upon instantiation

$ python test_pydantic.py --run-deserialisation-test
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/pydantic/main.py:1406: RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"
  warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
===== DESERIALIZING =====
===== INSTANTIATING =====
Traceback (most recent call last):
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/test_pydantic.py", line 219, in <module>
    validate_deserialisation(model)
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/test_pydantic.py", line 196, in validate_deserialisation
    assert model.epochs == 30, "The `validate_epochs` field validator didn't run"
           ^^^^^^^^^^^^^^^^^^
AssertionError: The `validate_epochs` field validator didn't run

Inspecting the __dict__ shows the field validators entry in the decorators is empty

 '__pydantic_decorators__': DecoratorInfos(validators={},
                                           field_validators={},
                                           root_validators={},
                                           field_serializers={},
                                           model_serializers={},
                                           model_validators={'increment': Decorator(cls_ref='__main__.Input:39874048',
                                                                                    cls_var_name='increment',
                                                                                    func=<function Input.increment at 0x7fc9be6c1580>,
                                                                                    shim=None,
                                                                                    info=ModelValidatorDecoratorInfo(mode='after'))},

whereas running the module interactively and inspecting the pprint-out of the Input class (i.e. without dill involvement) gives:

              '__pydantic_decorators__': DecoratorInfos(validators={},
                                                        field_validators={'triple_epochs': Decorator(cls_ref='__main__.Input:44759808',
                                                                                                     cls_var_name='triple_epochs',
                                                                                                     func=<bound method Input.triple_epochs of <class '__main__.Input'>>,
                                                                                                     shim=None,
                                                                                                     info=FieldValidatorDecoratorInfo(fields=('epochs',),
                                                                                                                                      mode='after',
                                                                                                                                      check_fields=None))},
                                                        root_validators={},
                                                        field_serializers={},
                                                        model_serializers={},
                                                        model_validators={'increment': Decorator(cls_ref='__main__.Input:44759808',
                                                                                                 cls_var_name='increment',
                                                                                                 func=<function Input.increment at 0x7f805f2722a0>,
                                                                                                 shim=None,
                                                                                                 info=ModelValidatorDecoratorInfo(mode='after'))},
                                                        computed_fields={}),

In 3c44f35 I added a print out of the field validators before and after:

{'triple_epochs': Decorator(cls_ref='__main__.Input:16611568',
                            cls_var_name='triple_epochs',
                            func=<bound method Input.triple_epochs of <class '__main__.Input'>>,
                            shim=None,
                            info=FieldValidatorDecoratorInfo(fields=('epochs',),
                                                             mode='after',
                                                             check_fields=None))}
===== DESERIALIZING =====
{}
===== INSTANTIATING =====

My sense is that I shouldn't have used the .__func__ attribute of the field validator function because that seems to have stopped it from working as a validator (somehow).

But without doing that there was a recursion bug as soon as you added a field validator 😕 Doesn't really make sense why you should access functions for model validators differently to field validators though.

(There is no existing code I can find online that supplies field validators to create_model)

@lmmx
Copy link
Author

lmmx commented Jan 27, 2024

After discussing the issues with field validators not running (3c71e6c) we decided to prioritise just reproducing behaviour already tested for (and a full solution to the outlined issues can come later).

The new definition of done is therefore for test_apps.py to run on the Pydantic v2 branch (as it does on the Pydantic v1 branch).

This test raises completely different errors to the ones we wrote so far! 🙃 However, I suspect it ultimately indicates the same thing (a failure to deserialise Pydantic models), so the different error does not mean we have another bug to tackle: it's just another symptom of the same underlying problem.

Test Apps error intro

The test runs fine on v1 (click to show)
(fal_pyd1) louis 🌟 ~/dev/fal/fal/projects/fal/tests $ python -m pytest test_apps.py 
========================================== test session starts ===========================================
platform linux -- Python 3.11.7, pytest-8.0.0, pluggy-1.4.0
rootdir: /home/louis/dev/fal/fal/projects/fal/tests
plugins: anyio-4.2.0
collected 7 items                                                                                                                                                                             

test_apps.py .......                                                                                                                                                                    [100%]

========================================= 7 passed in 73.91s (0:01:13) =========================================

but on this feature branch (in an environment with its Pydantic v2 dependency) we hit the following error

isolate.connections.common.SerializationError: Error while serializing the given object

Which is downstream of

TypeError: cannot pickle 'EncodedFile' object

This happens for all 7 tests (click to show)
======================================== short test summary info =========================================
ERROR test_apps.py::test_app_client - isolate.connections.common.SerializationError: Error while serializing the given object
ERROR test_apps.py::test_stateful_app_client - isolate.connections.common.SerializationError: Error while serializing the given object
ERROR test_apps.py::test_app_client_async - isolate.connections.common.SerializationError: Error while serializing the given object
ERROR test_apps.py::test_app_openapi_spec_metadata - isolate.connections.common.SerializationError: Error while serializing the given object
ERROR test_apps.py::test_app_no_serve_spec_metadata - isolate.connections.common.SerializationError: Error while serializing the given object
ERROR test_apps.py::test_app_update_app - isolate.connections.common.SerializationError: Error while serializing the given object
ERROR test_apps.py::test_app_set_delete_alias - isolate.connections.common.SerializationError: Error while serializing the given object
=========================================== 7 errors in 4.92s ============================================
Full error record (click to show)
============================= test session starts ==============================
platform linux -- Python 3.11.7, pytest-7.4.4, pluggy-1.3.0
rootdir: /home/louis/dev/fal/fal/projects/fal/tests
plugins: asyncio-0.23.3, anyio-4.2.0
asyncio: mode=Mode.STRICT
collected 7 items

test_apps.py EEEEEEE                                                     [100%]

==================================== ERRORS ====================================
______________________ ERROR at setup of test_app_client _______________________

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
>           yield

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:95: in serialize_object
    return serialization_backend.dumps(object)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:278: in dumps
    dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:250: in dump
    Pickler(file, protocol, **_kwds).dump(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:418: in dump
    StockPickler.dump(self, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:487: in dump
    self.save(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:1003: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dill._dill.Pickler object at 0x7f2a3c6406d0>
obj = <_io.TextIOWrapper name="<_io.FileIO name=6 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>
save_persistent_id = True

    def save(self, obj, save_persistent_id=True):
        self.framer.commit_frame()
    
        # Check for persistent id (defined by a subclass)
        pid = self.persistent_id(obj)
        if pid is not None and save_persistent_id:
            self.save_pers(pid)
            return
    
        # Check the memo
        x = self.memo.get(id(obj))
        if x is not None:
            self.write(self.get(x[0]))
            return
    
        rv = NotImplemented
        reduce = getattr(self, "reducer_override", None)
        if reduce is not None:
            rv = reduce(obj)
    
        if rv is NotImplemented:
            # Check the type dispatch table
            t = type(obj)
            f = self.dispatch.get(t)
            if f is not None:
                f(self, obj)  # Call unbound method with explicit self
                return
    
            # Check private dispatch table if any, or else
            # copyreg.dispatch_table
            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
            if reduce is not None:
                rv = reduce(obj)
            else:
                # Check for a class with a custom metaclass; treat as regular
                # class
                if issubclass(t, type):
                    self.save_global(obj)
                    return
    
                # Check for a __reduce_ex__ method, fall back to __reduce__
                reduce = getattr(obj, "__reduce_ex__", None)
                if reduce is not None:
>                   rv = reduce(self.proto)
E                   TypeError: cannot pickle 'EncodedFile' object

/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:578: TypeError

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

    @pytest.fixture(scope="module")
    def test_app():
        # Create a temporary app, register it, and return the ID of it.
    
        from fal.cli import _get_user_id
    
>       app_revision = addition_app.host.register(
            func=addition_app.func,
            options=addition_app.options,
        )

test_apps.py:129: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:235: in handler
    return fn(*args, **kwargs)
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:392: in register
    for partial_result in self._connection.register(
../../../../pydantic-2-bump/projects/fal/src/fal/sdk.py:420: in register
    wrapped_function = to_serialized_object(function, serialization_method)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/grpc/interface.py:68: in to_serialized_object
    definition=serialize_object(method, obj),
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:94: in serialize_object
    with _step("serializing the given object"):
/home/louis/miniconda3/envs/fal/lib/python3.11/contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
            yield
        except BaseException as exception:
>           raise SerializationError("Error while " + message) from exception
E           isolate.connections.common.SerializationError: Error while serializing the given object

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:42: SerializationError
__________________ ERROR at setup of test_stateful_app_client __________________

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
>           yield

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:95: in serialize_object
    return serialization_backend.dumps(object)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:278: in dumps
    dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:250: in dump
    Pickler(file, protocol, **_kwds).dump(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:418: in dump
    StockPickler.dump(self, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:487: in dump
    self.save(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1112: in _save_with_postproc
    pickler.save_reduce(*reduction)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:1003: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dill._dill.Pickler object at 0x7f2a37c7e910>
obj = <_io.TextIOWrapper name="<_io.FileIO name=6 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>
save_persistent_id = True

    def save(self, obj, save_persistent_id=True):
        self.framer.commit_frame()
    
        # Check for persistent id (defined by a subclass)
        pid = self.persistent_id(obj)
        if pid is not None and save_persistent_id:
            self.save_pers(pid)
            return
    
        # Check the memo
        x = self.memo.get(id(obj))
        if x is not None:
            self.write(self.get(x[0]))
            return
    
        rv = NotImplemented
        reduce = getattr(self, "reducer_override", None)
        if reduce is not None:
            rv = reduce(obj)
    
        if rv is NotImplemented:
            # Check the type dispatch table
            t = type(obj)
            f = self.dispatch.get(t)
            if f is not None:
                f(self, obj)  # Call unbound method with explicit self
                return
    
            # Check private dispatch table if any, or else
            # copyreg.dispatch_table
            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
            if reduce is not None:
                rv = reduce(obj)
            else:
                # Check for a class with a custom metaclass; treat as regular
                # class
                if issubclass(t, type):
                    self.save_global(obj)
                    return
    
                # Check for a __reduce_ex__ method, fall back to __reduce__
                reduce = getattr(obj, "__reduce_ex__", None)
                if reduce is not None:
>                   rv = reduce(self.proto)
E                   TypeError: cannot pickle 'EncodedFile' object

/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:578: TypeError

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

    @pytest.fixture(scope="module")
    def test_stateful_app():
        # Create a temporary app, register it, and return the ID of it.
    
        from fal.cli import _get_user_id
    
        app = fal.wrap_app(StatefulAdditionApp)
>       app_revision = app.host.register(
            func=app.func,
            options=app.options,
        )

test_apps.py:158: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:235: in handler
    return fn(*args, **kwargs)
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:392: in register
    for partial_result in self._connection.register(
../../../../pydantic-2-bump/projects/fal/src/fal/sdk.py:420: in register
    wrapped_function = to_serialized_object(function, serialization_method)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/grpc/interface.py:68: in to_serialized_object
    definition=serialize_object(method, obj),
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:94: in serialize_object
    with _step("serializing the given object"):
/home/louis/miniconda3/envs/fal/lib/python3.11/contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
            yield
        except BaseException as exception:
>           raise SerializationError("Error while " + message) from exception
E           isolate.connections.common.SerializationError: Error while serializing the given object

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:42: SerializationError
___________________ ERROR at setup of test_app_client_async ____________________

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
>           yield

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:95: in serialize_object
    return serialization_backend.dumps(object)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:278: in dumps
    dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:250: in dump
    Pickler(file, protocol, **_kwds).dump(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:418: in dump
    StockPickler.dump(self, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:487: in dump
    self.save(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:1003: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dill._dill.Pickler object at 0x7f2a3c6406d0>
obj = <_io.TextIOWrapper name="<_io.FileIO name=6 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>
save_persistent_id = True

    def save(self, obj, save_persistent_id=True):
        self.framer.commit_frame()
    
        # Check for persistent id (defined by a subclass)
        pid = self.persistent_id(obj)
        if pid is not None and save_persistent_id:
            self.save_pers(pid)
            return
    
        # Check the memo
        x = self.memo.get(id(obj))
        if x is not None:
            self.write(self.get(x[0]))
            return
    
        rv = NotImplemented
        reduce = getattr(self, "reducer_override", None)
        if reduce is not None:
            rv = reduce(obj)
    
        if rv is NotImplemented:
            # Check the type dispatch table
            t = type(obj)
            f = self.dispatch.get(t)
            if f is not None:
                f(self, obj)  # Call unbound method with explicit self
                return
    
            # Check private dispatch table if any, or else
            # copyreg.dispatch_table
            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
            if reduce is not None:
                rv = reduce(obj)
            else:
                # Check for a class with a custom metaclass; treat as regular
                # class
                if issubclass(t, type):
                    self.save_global(obj)
                    return
    
                # Check for a __reduce_ex__ method, fall back to __reduce__
                reduce = getattr(obj, "__reduce_ex__", None)
                if reduce is not None:
>                   rv = reduce(self.proto)
E                   TypeError: cannot pickle 'EncodedFile' object

/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:578: TypeError

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

    @pytest.fixture(scope="module")
    def test_app():
        # Create a temporary app, register it, and return the ID of it.
    
        from fal.cli import _get_user_id
    
>       app_revision = addition_app.host.register(
            func=addition_app.func,
            options=addition_app.options,
        )

test_apps.py:129: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:235: in handler
    return fn(*args, **kwargs)
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:392: in register
    for partial_result in self._connection.register(
../../../../pydantic-2-bump/projects/fal/src/fal/sdk.py:420: in register
    wrapped_function = to_serialized_object(function, serialization_method)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/grpc/interface.py:68: in to_serialized_object
    definition=serialize_object(method, obj),
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:94: in serialize_object
    with _step("serializing the given object"):
/home/louis/miniconda3/envs/fal/lib/python3.11/contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
            yield
        except BaseException as exception:
>           raise SerializationError("Error while " + message) from exception
E           isolate.connections.common.SerializationError: Error while serializing the given object

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:42: SerializationError
_______________ ERROR at setup of test_app_openapi_spec_metadata _______________

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
>           yield

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:95: in serialize_object
    return serialization_backend.dumps(object)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:278: in dumps
    dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:250: in dump
    Pickler(file, protocol, **_kwds).dump(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:418: in dump
    StockPickler.dump(self, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:487: in dump
    self.save(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:1003: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dill._dill.Pickler object at 0x7f2a3c6406d0>
obj = <_io.TextIOWrapper name="<_io.FileIO name=6 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>
save_persistent_id = True

    def save(self, obj, save_persistent_id=True):
        self.framer.commit_frame()
    
        # Check for persistent id (defined by a subclass)
        pid = self.persistent_id(obj)
        if pid is not None and save_persistent_id:
            self.save_pers(pid)
            return
    
        # Check the memo
        x = self.memo.get(id(obj))
        if x is not None:
            self.write(self.get(x[0]))
            return
    
        rv = NotImplemented
        reduce = getattr(self, "reducer_override", None)
        if reduce is not None:
            rv = reduce(obj)
    
        if rv is NotImplemented:
            # Check the type dispatch table
            t = type(obj)
            f = self.dispatch.get(t)
            if f is not None:
                f(self, obj)  # Call unbound method with explicit self
                return
    
            # Check private dispatch table if any, or else
            # copyreg.dispatch_table
            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
            if reduce is not None:
                rv = reduce(obj)
            else:
                # Check for a class with a custom metaclass; treat as regular
                # class
                if issubclass(t, type):
                    self.save_global(obj)
                    return
    
                # Check for a __reduce_ex__ method, fall back to __reduce__
                reduce = getattr(obj, "__reduce_ex__", None)
                if reduce is not None:
>                   rv = reduce(self.proto)
E                   TypeError: cannot pickle 'EncodedFile' object

/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:578: TypeError

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

    @pytest.fixture(scope="module")
    def test_app():
        # Create a temporary app, register it, and return the ID of it.
    
        from fal.cli import _get_user_id
    
>       app_revision = addition_app.host.register(
            func=addition_app.func,
            options=addition_app.options,
        )

test_apps.py:129: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:235: in handler
    return fn(*args, **kwargs)
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:392: in register
    for partial_result in self._connection.register(
../../../../pydantic-2-bump/projects/fal/src/fal/sdk.py:420: in register
    wrapped_function = to_serialized_object(function, serialization_method)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/grpc/interface.py:68: in to_serialized_object
    definition=serialize_object(method, obj),
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:94: in serialize_object
    with _step("serializing the given object"):
/home/louis/miniconda3/envs/fal/lib/python3.11/contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
            yield
        except BaseException as exception:
>           raise SerializationError("Error while " + message) from exception
E           isolate.connections.common.SerializationError: Error while serializing the given object

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:42: SerializationError
______________ ERROR at setup of test_app_no_serve_spec_metadata _______________

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
>           yield

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:95: in serialize_object
    return serialization_backend.dumps(object)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:278: in dumps
    dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:250: in dump
    Pickler(file, protocol, **_kwds).dump(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:418: in dump
    StockPickler.dump(self, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:487: in dump
    self.save(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:1003: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1107: in _save_with_postproc
    pickler._batch_setitems(iter(source.items()))
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dill._dill.Pickler object at 0x7f2a37f2cc10>
obj = <_io.TextIOWrapper name="<_io.FileIO name=6 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>
save_persistent_id = True

    def save(self, obj, save_persistent_id=True):
        self.framer.commit_frame()
    
        # Check for persistent id (defined by a subclass)
        pid = self.persistent_id(obj)
        if pid is not None and save_persistent_id:
            self.save_pers(pid)
            return
    
        # Check the memo
        x = self.memo.get(id(obj))
        if x is not None:
            self.write(self.get(x[0]))
            return
    
        rv = NotImplemented
        reduce = getattr(self, "reducer_override", None)
        if reduce is not None:
            rv = reduce(obj)
    
        if rv is NotImplemented:
            # Check the type dispatch table
            t = type(obj)
            f = self.dispatch.get(t)
            if f is not None:
                f(self, obj)  # Call unbound method with explicit self
                return
    
            # Check private dispatch table if any, or else
            # copyreg.dispatch_table
            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
            if reduce is not None:
                rv = reduce(obj)
            else:
                # Check for a class with a custom metaclass; treat as regular
                # class
                if issubclass(t, type):
                    self.save_global(obj)
                    return
    
                # Check for a __reduce_ex__ method, fall back to __reduce__
                reduce = getattr(obj, "__reduce_ex__", None)
                if reduce is not None:
>                   rv = reduce(self.proto)
E                   TypeError: cannot pickle 'EncodedFile' object

/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:578: TypeError

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

    @pytest.fixture(scope="module")
    def test_fastapi_app():
        # Create a temporary app, register it, and return the ID of it.
    
        from fal.cli import _get_user_id
    
>       app_revision = calculator_app.host.register(
            func=calculator_app.func,
            options=calculator_app.options,
        )

test_apps.py:143: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:235: in handler
    return fn(*args, **kwargs)
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:392: in register
    for partial_result in self._connection.register(
../../../../pydantic-2-bump/projects/fal/src/fal/sdk.py:420: in register
    wrapped_function = to_serialized_object(function, serialization_method)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/grpc/interface.py:68: in to_serialized_object
    definition=serialize_object(method, obj),
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:94: in serialize_object
    with _step("serializing the given object"):
/home/louis/miniconda3/envs/fal/lib/python3.11/contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
            yield
        except BaseException as exception:
>           raise SerializationError("Error while " + message) from exception
E           isolate.connections.common.SerializationError: Error while serializing the given object

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:42: SerializationError
____________________ ERROR at setup of test_app_update_app _____________________

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
>           yield

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:95: in serialize_object
    return serialization_backend.dumps(object)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:278: in dumps
    dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:250: in dump
    Pickler(file, protocol, **_kwds).dump(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:418: in dump
    StockPickler.dump(self, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:487: in dump
    self.save(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:1003: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dill._dill.Pickler object at 0x7f2a37ba5f90>
obj = <_io.TextIOWrapper name="<_io.FileIO name=6 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>
save_persistent_id = True

    def save(self, obj, save_persistent_id=True):
        self.framer.commit_frame()
    
        # Check for persistent id (defined by a subclass)
        pid = self.persistent_id(obj)
        if pid is not None and save_persistent_id:
            self.save_pers(pid)
            return
    
        # Check the memo
        x = self.memo.get(id(obj))
        if x is not None:
            self.write(self.get(x[0]))
            return
    
        rv = NotImplemented
        reduce = getattr(self, "reducer_override", None)
        if reduce is not None:
            rv = reduce(obj)
    
        if rv is NotImplemented:
            # Check the type dispatch table
            t = type(obj)
            f = self.dispatch.get(t)
            if f is not None:
                f(self, obj)  # Call unbound method with explicit self
                return
    
            # Check private dispatch table if any, or else
            # copyreg.dispatch_table
            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
            if reduce is not None:
                rv = reduce(obj)
            else:
                # Check for a class with a custom metaclass; treat as regular
                # class
                if issubclass(t, type):
                    self.save_global(obj)
                    return
    
                # Check for a __reduce_ex__ method, fall back to __reduce__
                reduce = getattr(obj, "__reduce_ex__", None)
                if reduce is not None:
>                   rv = reduce(self.proto)
E                   TypeError: cannot pickle 'EncodedFile' object

/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:578: TypeError

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

    @pytest.fixture(scope="module")
    def aliased_app() -> Generator[tuple[str, str], None, None]:
        # Create a temporary app, register it, and return the ID of it.
    
        import uuid
    
        app_alias = str(uuid.uuid4()).replace("-", "")[:10]
>       app_revision = addition_app.host.register(
            func=addition_app.func,
            options=addition_app.options,
            # random enough
            application_name=app_alias,
            application_auth_mode="private",
        )

test_apps.py:113: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:235: in handler
    return fn(*args, **kwargs)
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:392: in register
    for partial_result in self._connection.register(
../../../../pydantic-2-bump/projects/fal/src/fal/sdk.py:420: in register
    wrapped_function = to_serialized_object(function, serialization_method)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/grpc/interface.py:68: in to_serialized_object
    definition=serialize_object(method, obj),
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:94: in serialize_object
    with _step("serializing the given object"):
/home/louis/miniconda3/envs/fal/lib/python3.11/contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
            yield
        except BaseException as exception:
>           raise SerializationError("Error while " + message) from exception
E           isolate.connections.common.SerializationError: Error while serializing the given object

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:42: SerializationError
_________________ ERROR at setup of test_app_set_delete_alias __________________

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
>           yield

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:95: in serialize_object
    return serialization_backend.dumps(object)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:278: in dumps
    dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:250: in dump
    Pickler(file, protocol, **_kwds).dump(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:418: in dump
    StockPickler.dump(self, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:487: in dump
    self.save(obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1965: in save_function
    _save_with_postproc(pickler, (_create_function, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:1003: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1812: in save_type
    _save_with_postproc(pickler, (_create_type, (
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1093: in _save_with_postproc
    pickler.save_reduce(*reduction, obj=obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:902: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:692: in save_reduce
    save(args)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:887: in save_tuple
    save(element)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:603: in save
    self.save_reduce(obj=obj, *rv)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:717: in save_reduce
    save(state)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:560: in save
    f(self, obj)  # Call unbound method with explicit self
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:1212: in save_module_dict
    StockPickler.save_dict(pickler, obj)
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:972: in save_dict
    self._batch_setitems(obj.items())
/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:998: in _batch_setitems
    save(v)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/dill/_dill.py:412: in save
    StockPickler.save(self, obj, save_persistent_id)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dill._dill.Pickler object at 0x7f2a37ba5f90>
obj = <_io.TextIOWrapper name="<_io.FileIO name=6 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>
save_persistent_id = True

    def save(self, obj, save_persistent_id=True):
        self.framer.commit_frame()
    
        # Check for persistent id (defined by a subclass)
        pid = self.persistent_id(obj)
        if pid is not None and save_persistent_id:
            self.save_pers(pid)
            return
    
        # Check the memo
        x = self.memo.get(id(obj))
        if x is not None:
            self.write(self.get(x[0]))
            return
    
        rv = NotImplemented
        reduce = getattr(self, "reducer_override", None)
        if reduce is not None:
            rv = reduce(obj)
    
        if rv is NotImplemented:
            # Check the type dispatch table
            t = type(obj)
            f = self.dispatch.get(t)
            if f is not None:
                f(self, obj)  # Call unbound method with explicit self
                return
    
            # Check private dispatch table if any, or else
            # copyreg.dispatch_table
            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
            if reduce is not None:
                rv = reduce(obj)
            else:
                # Check for a class with a custom metaclass; treat as regular
                # class
                if issubclass(t, type):
                    self.save_global(obj)
                    return
    
                # Check for a __reduce_ex__ method, fall back to __reduce__
                reduce = getattr(obj, "__reduce_ex__", None)
                if reduce is not None:
>                   rv = reduce(self.proto)
E                   TypeError: cannot pickle 'EncodedFile' object

/home/louis/miniconda3/envs/fal/lib/python3.11/pickle.py:578: TypeError

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

    @pytest.fixture(scope="module")
    def aliased_app() -> Generator[tuple[str, str], None, None]:
        # Create a temporary app, register it, and return the ID of it.
    
        import uuid
    
        app_alias = str(uuid.uuid4()).replace("-", "")[:10]
>       app_revision = addition_app.host.register(
            func=addition_app.func,
            options=addition_app.options,
            # random enough
            application_name=app_alias,
            application_auth_mode="private",
        )

test_apps.py:113: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:235: in handler
    return fn(*args, **kwargs)
../../../../pydantic-2-bump/projects/fal/src/fal/api.py:392: in register
    for partial_result in self._connection.register(
../../../../pydantic-2-bump/projects/fal/src/fal/sdk.py:420: in register
    wrapped_function = to_serialized_object(function, serialization_method)
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/grpc/interface.py:68: in to_serialized_object
    definition=serialize_object(method, obj),
/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:94: in serialize_object
    with _step("serializing the given object"):
/home/louis/miniconda3/envs/fal/lib/python3.11/contextlib.py:158: in __exit__
    self.gen.throw(typ, value, traceback)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

message = 'serializing the given object'

    @contextmanager
    def _step(message: str) -> Iterator[None]:
        """A context manager to capture every expression
        underneath it and if any of them fails for any reason
        then it will raise a SerializationError with the
        given message."""
    
        try:
            yield
        except BaseException as exception:
>           raise SerializationError("Error while " + message) from exception
E           isolate.connections.common.SerializationError: Error while serializing the given object

/home/louis/miniconda3/envs/fal/lib/python3.11/site-packages/isolate/connections/common.py:42: SerializationError
=========================== short test summary info ============================
ERROR test_apps.py::test_app_client - isolate.connections.common.Serializatio...
ERROR test_apps.py::test_stateful_app_client - isolate.connections.common.Ser...
ERROR test_apps.py::test_app_client_async - isolate.connections.common.Serial...
ERROR test_apps.py::test_app_openapi_spec_metadata - isolate.connections.comm...
ERROR test_apps.py::test_app_no_serve_spec_metadata - isolate.connections.com...
ERROR test_apps.py::test_app_update_app - isolate.connections.common.Serializ...
ERROR test_apps.py::test_app_set_delete_alias - isolate.connections.common.Se...
============================== 7 errors in 4.84s ===============================

Solving the EncodedFile error

This error message has been reported already, and I came across it but thought it wasn't relevant because our error message was different.

I already linked to it in issue 29:

  • A pytest maintainer's comments (1, 2) on a pytest issue raised by dill users seemed to show some opposition between the 2 libraries:

    "To me that reads like dill choose to explicitly transfer things that are serialization unsafe in a unsafe way and now there is sudden surprise

    Dill is clearly doing something that works by chance and is broken by design, I'm not going to pretend it's a theoretically sound approach"

The solution in that report was to run pytest with --assert=plain. When I do that, the error changes to:

_pickle.PicklingError: Can't pickle <class 'main.File'>: it's not found as main.File

I think it's possible this is essentially just a result of the error we already saw (and that by registering the dill hook as already described we would eliminate this error, i.e. I don't know if we need to be concerned about the assert rewriting in itself, the error about EncodedFile will go away when we deserialise Pydantic classes correctly)

@lmmx
Copy link
Author

lmmx commented Jan 28, 2024

I'm going to try copying over the same dill-registered BaseModel hook from test_pydantic.py and see if that fixes the test_apps.py test failure.

Also note that we can't set the model_config (there's a clash with passing another create_model param) but we can set it after creating the model class (currently I've left a comment noting it's UNUSED).

@lmmx
Copy link
Author

lmmx commented Jan 29, 2024

Running the tests now does not crash (which is progress!) but also does not succeed.

The app test fails with

httpx.HTTPStatusError: Server error '503 Service Unavailable' for url 'https://2979452-616ebf27-[...].gateway.alpha.fal.ai/fal/queue/requests/61cf2c62-[...]/response/'

When I go to that URL I get an auth error which may be misleading (I don't see any reason why the URL should be wrong, but when opening it in the browser the auth headers would not be passed so this may be perfectly normal to see).

I want to get this fixed

python -m pytest --assert=plain test_apps.py -x

But it's simpler to test (and read) a test file with a single script, rather than select it with -k.

On Pydantic v1 it works fine

(fal_pyd1) louis 🌟 ~/dev/fal/pydantic-2-bump/projects/fal/tests $ python -m pytest -vvv --assert=plain test_apps_simple.py -x -s --log-level=DEBUG
============================= test session starts ==============================
platform linux -- Python 3.11.7, pytest-8.0.0, pluggy-1.4.0 -- /home/louis/miniconda3/envs/fal_pyd1/bin/python3
cachedir: .pytest_cache
rootdir: /home/louis/dev/fal/pydantic-2-bump/projects/fal/tests
plugins: anyio-4.2.0
collecting ... collected 1 item

test_apps_simple.py::test_app_client PASSED

============================== 1 passed in 16.06s ==============================

On Pydantic v2 it just hangs indefinitely (until it's "hung up on" by the timeout).

No doubt this is too much, but I dumped the entire log

  • Full traceback with all debug logs was too long to show here, see gist (4135 lines)

(I re-auth'd just in case there were any private credentials included here)

You only get the error logs if the test fails, so I threw a trivial error and re-ran the working test (Pydantic v1) to compare the results more clearly.

@chamini2
Copy link
Member

chamini2 commented Jan 29, 2024

No doubt this is too much, but I dumped the entire log

* Full traceback with all debug logs was too long to show here, see [gist](https://gist.github.com/lmmx/278a6b15cb8dc6c64981d59a496c83b3) (4135 lines)

I re-auth'd just in case there were any private credentials included here

Hey @lmmx, I went into our logs and the requests I see failing with a 503 internally are just

StatusCode.INVALID_ARGUMENT: The function function could not be deserialized.

I think this may be related to a change we introduced in our platform which probably is obscuring the real error and just returning Service Unavailable.

We will see if we can re-surface the real error by changing some things on our side, but just wanted to let you know that it is indeed a serialization problem still.

OK, I checked with the team and actually this happens for the gateway submit flow, which is expected (we could not provision a machine).

So you would have to check the sdk call logs (if it was fal function run) or the logs in the UI at https://www.fal.ai/dashboard/logs (if it was a fal function serve and later called in the gateway) to see the error happening.

@lmmx
Copy link
Author

lmmx commented Jan 29, 2024

Patch applied within a minimal test (test_apps_simple.py) and fix acquired! 🎣

@isidentical noted that the 'hanging' API calls could be diagnosed as actual bugs using fal --debug fn run rather than running as library code via pytest

(P.S. thanks for the reply @chamini2 I missed it 😅 Yes fal --debug fn run made it immediately clear and led to the fix)

PYTHONPATH=. fal --debug fn run test_apps_simple.py addition_app

Note the fal env used here has this branch's projects/fal path pip installed as editable package, of course

This identified a bug: you can't always rely on .annotation as you won't always have FieldInfo in model fields.

Batuhan amended this .annotation attribute access to use a None fallback. We should try to find a better way than that, the actual error we got was to do with dict not having an annotation attribute so we can inspect that

  File "/root/.cache/isolate/virtualenv/741ff6a01b8571a0cd4c10769658d96db5c871c77f13a7cb173766e3286738ab/lib/python3.11/site-packages/dill/_dill.py", line 442, in load
    obj = StockUnpickler.load(self)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/tmp6t5zsbtc/pydantic_patch.py", line 78, in build_pydantic_model
    model_fields["__annotations__"] = {
                                      ^
  File "/tmp/tmp6t5zsbtc/pydantic_patch.py", line 79, in <dictcomp>
    name: field.annotation for name, field in model_fields.items()
          ^^^^^^^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'annotation'

There is a shortcut to running these deployed functions: https://fal.run (which Batuhan sent a POST request to via xh)

❯ xh https://fal.run/47358913/4beacb31-86d1-4fc8-a039-64ab4acfca73 lhs:=2 rhs:=4
HTTP/2.0 200 OK
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
content-length: 12
content-type: application/json
date: Mon, 29 Jan 2024 21:48:01 GMT
server: uvicorn
via: 1.1 google
x-fal-request-id: 3508e0d3-e55b-487c-a0c2-91910b46b8ad
x-fal-served-from: http://worker-s-efb93cde-6bdc-4e54-bdc3-880d61f9e728.worker-headless-service:8080/

{
    "result": 6
}

Thus Pydantic 2 is now up and running. 🚀

The next step is to drop the setup_function workaround by executing the patch from within serialization.py instead.

@lmmx
Copy link
Author

lmmx commented Feb 11, 2024

Summary something's going wrong with the identity comparison between instances of the Pydantic model before and after serialisation. We may be able to 'trick' it by setting a __pydantic_generic_metadata__ field or we may need an approach in mainify itself.

Decision I suggest relaxing this test because in v1 all it did was check the serialised models were the same.

Result test_pydantic_serialization and test_serve_on_off in stability_test.py pass (6862c9f 8d79b61)

In v1 all a Pydantic model __eq__ method did was compare .dict() serialisation outputs (source)

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, BaseModel):
            return self.dict() == other.dict()

In v2 it became more complex and effectively based on __class__ comparison (source).

I suspect it'd be acceptable to relax this test thought it may be wise to use it to guide further patching:

assert result == MathResult(result=3)

It suggests we need extra logic to overwrite the type info, which is checked in __pydantic_generic_metadata__['origin'] before falling back to __class__ (the fallback is always used and is the first failing condition, so setting it on the origin key of this metadata dict would be an accessible solution)

The full test here can be debugged with:

def test_pydantic_serialization(isolated_client):
    from fal.toolkit import mainify
    from pydantic import BaseModel, Field

    @mainify
    class MathQuery(BaseModel):
        x: int = Field(gt=0, description="The first operand")
        y: int = Field(gt=0, description="The second operand")

    @mainify
    class MathResult(BaseModel):
        result: int = Field(description="The result of the operation")

    @isolated_client("virtualenv", requirements=["pydantic>=2"])
    def add(query: MathQuery) -> MathResult:
        return MathResult(result=query.x + query.y)

    result = add(MathQuery(x=1, y=2))
    assert result.result == 3
    breakpoint()
    is_identical = result == MathResult(result=3)
    assert is_identical
  • The left hand side is the result (i.e. deserialised) and the right hand side is the locally defined (perhaps it indicates that it wasn't mainify'd correctly?)
-> self_type = self.__pydantic_generic_metadata__['origin'] or self.__class__
(Pdb) n
> /home/louis/miniconda3/envs/fal39/lib/python3.9/site-packages/pydantic/main.py(869)__eq__()
-> other_type = other.__pydantic_generic_metadata__['origin'] or other.__class__
(Pdb) p self_type
<class 'tests.stability_test.MathResult'>
(Pdb) n
> /home/louis/miniconda3/envs/fal39/lib/python3.9/site-packages/pydantic/main.py(872)__eq__()
-> self_type == other_type
(Pdb) p other_type
<class 'tests.stability_test.test_pydantic_serialization.<locals>.MathResult'>
(Pdb) p self_type == other_type
False

The internal equality check involves a type comparison

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, BaseModel):
            # When comparing instances of generic types for equality, as long as all field values are equal,
            # only require their generic origin types to be equal, rather than exact type equality.
            # This prevents headaches like MyGeneric(x=1) != MyGeneric[Any](x=1).
            self_type = self.__pydantic_generic_metadata__['origin'] or self.__class__
            other_type = other.__pydantic_generic_metadata__['origin'] or other.__class__

            return (
                self_type == other_type
                and self.__dict__ == other.__dict__
                and self.__pydantic_private__ == other.__pydantic_private__
                and self.__pydantic_extra__ == other.__pydantic_extra__
            )
        else:
            return NotImplemented  # delegate to the other item in the comparison

@lmmx
Copy link
Author

lmmx commented Feb 11, 2024

It looks like

    def test_fal_storage(isolated_client):                                                                                                                     
>       file = File.from_bytes(b"Hello fal storage from local", repository="fal")

stability_test.py:491:                                                                                                                                         
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../src/fal/toolkit/file/file/standard.py:95: in from_bytes
    return cls(                                                                                                                                                
../src/fal/toolkit/file/file/standard.py:47: in __init__                                                                                                       
    self._file_data = data                                                                                                                                     
/home/louis/miniconda3/envs/fal39/lib/python3.9/site-packages/pydantic/main.py:770: in __setattr__
    if self.__pydantic_private__ is None or name not in self.__private_attributes__:

doesn't work.

It seems that the private attribute isn't being set (which should get passed through as part of our post-fixes, by definition PrivateAttr are not serialised)

Reading the docs it seems like the proper way to do this in v2 is after the call to super().__init__(...), and sure enough implementing this in 499260d resolved the issue that was being reported (an AttributeError from __private_attributes__).

This test test_fal_storage still doesn't pass but it's progressed.

I think this 401 unauthorized is due to env vars not being set outside of the CI environment... so I think this one is actually resolved?

There's also an env var test that fails... Unless I missed something to do with how they are set which is done locally.

I'm tentatively marking all 4 remaining errors in stability_test.py resolved now

@lmmx
Copy link
Author

lmmx commented Feb 11, 2024

After bumping some more versions, the remaining issues are all to do with File, and it looks like these are classmethods

FAILED integration_test.py::test_fal_file_from_path - AttributeError: from_path
FAILED integration_test.py::test_fal_file_from_bytes - AttributeError: from_bytes
FAILED integration_test.py::test_fal_file_save - AttributeError: from_bytes

and others which I presume are downstream of those AttributeErrors

FAILED integration_test.py::

  • test_fal_file_input[https://raw.githubusercontent.com/fal-ai/fal/fe0e2a1aa4b46a42a93bad0fbd9aca4aefcb4296/README.md-projects/fal/README.md]

    • pydantic_core._pydantic_core.ValidationError: 1 validation error for TestInput
  • test_fal_file_input[data:text/plain;charset=UTF-8,fal-fal]

    • pydantic_core._pydantic_core.ValidationError: 1 validation error for TestInput
  • test_fal_compressed_file

    • pydantic_core._pydantic_core.ValidationError: 1 validation error for TestInput

Confirmed: we have a serialisation omission

integration_test.py 
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PDB set_trace (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/integration_test.py(462)test_fal_file_from_path()
-> file_content = "file-test"
(Pdb) p File
<class '__main__.File'>
(Pdb) p File.from_
File.from_bytes  File.from_orm    File.from_path   
(Pdb) p File.from_path
<bound method File.from_path of <class '__main__.File'>>
(Pdb) n
> /home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/integration_test.py(463)test_fal_file_from_path()
-> file = fal_file_from_temp(file_content)
(Pdb) n
2024-02-11 20:12:15.200 [stderr   ] /root/.cache/isolate/virtualenv/41b75195d7b215f22ee035bac8643a593c1c84af7a90e9a23e2831c305aac606/lib/python3.9/site-packages/pydantic/main.py:1406: RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"
2024-02-11 20:12:15.201 [stderr   ]   warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
AttributeError: from_path
> /home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/integration_test.py(463)test_fal_file_from_path()
-> file = fal_file_from_temp(file_content)

Possibly need to make a standalone test for File since its proper serialisation is so central.

The expected __dict__ keys are a good start to look at

>>> pprint(list(vars(fal.toolkit.file.File)))
['__module__',
 '__annotations__',
 '__init__',
 '__get_validators__',
 '_File__convert_from_str',
 '_from_url',
 'from_bytes',
 'from_path',
 'as_bytes',
 'save',
 'model_config',
 'model_post_init',
...
]

The rest are dunders:

'__class_vars__', '__private_attributes__', '__weakref__', '__doc__', '__abstractmethods__', '_abc_impl', '__pydantic_custom_init__', '__pydantic_post_init__', '__pydantic_decorators__', '__pydantic_generic_metadata__', '__pydantic_complete__', '__pydantic_parent_namespace__', 'model_fields', '__pydantic_core_schema__', '__pydantic_validator__', '__pydantic_serializer__', '__signature__'

As a very simple first attempt we can put this list call in a serialised fal function and return it to see what we're working with

Adding the File methods interface to the test suite, we can see the results: File has no class methods (and relies heavily on them, hence these tests are breaking).

    def test_fal_file_methods(isolated_client):
        @isolated_client(requirements=["pydantic==2.5.3"])
        def fal_file_methods_set():
            file_cls_methods = set(vars(File))
            return file_cls_methods
    
        file_cls_methods = fal_file_methods_set()
    
        expected = {"_from_url", "from_bytes", "from_path", "as_bytes", "save"}
>       assert expected.difference(file_cls_methods) == set()
E       AssertionError: assert {'_from_url', 'as_bytes', 'from_path', 'from_bytes', 'save'} == set()
E         Extra items in the left set:
E         'from_path'
E         'from_bytes'
E         'save'
E         '_from_url'
E         'as_bytes'
E         Full diff:
E         - set()
E         + {'_from_url', 'as_bytes', 'from_path', 'from_bytes', 'save'}

@lmmx
Copy link
Author

lmmx commented Feb 11, 2024

I went back to an earlier draft and there was a patch that (allegedly) could be run standalone, and I could get a classmethod to run with that

Click to show standalone repro
from __future__ import annotations

import dataclasses

import dill
import dill._dill as dill_serialization
from pydantic import BaseModel, Field, model_validator


def build_pydantic_model(
    name, base_cls, model_config, model_fields, validators, class_fields
):
    """Recreate the Pydantic model from the deserialised validator info."""
    import pydantic

    model_cls = pydantic.create_model(
        name,
        __base__=base_cls,
        __validators__={
            validator_name: pydantic.model_validator(mode=validator_info.mode)(
                validator_func
            )
            for validator_name, (validator_func, validator_info) in validators.items()
        },
        **model_fields,
        **class_fields,
    )
    print(f"{model_fields=}")
    print(f"{class_fields=}")
    return model_cls


@dill.register(type(BaseModel))
def _dill_hook_for_pydantic_models(
    pickler: dill.Pickler,
    pydantic_model,
) -> None:
    if pydantic_model is BaseModel:
        dill_serialization.save_type(pickler, pydantic_model)
        return

    validators = {}
    decorators = pydantic_model.__pydantic_decorators__
    for validator_name, decorator in decorators.model_validators.items():
        validators[validator_name] = (decorator.func, decorator.info)

    class_fields = {
        "__annotations__": pydantic_model.__annotations__,
    }
    for class_field_name, class_field_value in pydantic_model.__dict__.items():
        if class_field_name.startswith("_"):
            continue
        elif class_field_name in ("model_fields", "model_config"):
            continue
        elif class_field_name in pydantic_model.model_fields:
            continue
        elif class_field_name in validators:
            continue

        class_fields[class_field_name] = class_field_value

    pickler.save_reduce(
        build_pydantic_model,
        (
            pydantic_model.__name__,
            pydantic_model.__bases__[0],
            pydantic_model.model_config,
            pydantic_model.model_fields,
            validators,
            class_fields,
        ),
    )


class Input(BaseModel):
    prompt: str = Field()
    num_steps: int = Field(default=2, ge=1, le=10)

    def get_xxx(self):
        return self.num_steps * 2

    @model_validator(mode="after")
    def validate_num_steps(self):
        print(1)
        if self.num_steps % 2 != 0:
            raise ValueError("num_steps must be odd")

    @classmethod
    def from_name(cls, name: str, num_steps: int):
        return cls(prompt=f"DSLR photograph of {name}", num_steps=num_steps)


if __name__ == "__main__":
    dill.settings["recurse"] = True
    serialized_cls = dill.dumps(Input)
    print()
    print("====== DESERIALIZING =====")
    print()
    cls = dill.loads(serialized_cls)
    print("======== RUNNING =====")
    inp = cls.from_name(name="Pikachu", num_steps=6)
    print(inp.prompt)

Whereas this seems to have been lost.

I printed out the values and the classmethod is in the class_fields (which I think I took out as it seemed to clash with the model_fields and didn't make sense to me in theory).

====== DESERIALIZING =====

/home/louis/miniconda3/envs/fal39/lib/python3.9/site-packages/pydantic/main.py:1406: RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"
  warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
model_fields={'prompt': FieldInfo(annotation=str, required=True), 'num_steps': FieldInfo(annotation=int, required=False, default=2, metadata=[Ge(ge=1), Le(le=10)])}
class_fields={'__annotations__': {'prompt': 'str', 'num_steps': 'int'}, 'get_xxx': <function Input.get_xxx at 0x7f89e9510040>, 'from_name': <classmethod object at 0x7f89e9437a90>}
======== RUNNING =====
1
DSLR photograph of Pikachu

@lmmx
Copy link
Author

lmmx commented Feb 11, 2024

Summary classmethod serialisation fixed in 12a2ad8 but gives a TypeError: No constructor defined when used

OK lastly it seems like I already figured out that you can't just put classmethods in the model fields (it doesn't seem to work) but you can assign them (you just can't get them to work as field validators, which isn't used internally anyway so is fine for a MVP...)

I already implemented an approach that uses setattr which I just (re)confirmed works:

    methods = {
        field_name: field_value
        for field_name, field_value in model.__dict__.items()
        if field_name in ["steps_x2", "from_template"]
    }

I suspect that I can just replace the way I was building up a list of classmethods and... put them in here?

Unless this breaks anything else, this would seem to be the final piece of the puzzle. Adding from_template (my test model classmethod) to this "cheat list" of method names, it goes from failing at the last hurdle:

(fal39) louis 🌟 ~/dev/fal/pydantic-2-bump/projects/fal/tests $ python pydantic_test.py --run-deserialisation-test
===== DESERIALIZING =====
/home/louis/miniconda3/envs/fal39/lib/python3.9/site-packages/pydantic/main.py:1406: RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"
  warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
===== INSTANTIATING =====
Traceback (most recent call last):
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/pydantic_test.py", line 137, in <module>
    run_deserialisation_test()
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/pydantic_test.py", line 131, in run_deserialisation_test
    assert has_classmethod, "Classmethod `from_template` was not deserialised"
AssertionError: Classmethod `from_template` was not deserialised

To working

(fal39) louis 🌟 ~/dev/fal/pydantic-2-bump/projects/fal/tests $ vim pydantic_standalone/pydantic_patch.py 
(fal39) louis 🌟 ~/dev/fal/pydantic-2-bump/projects/fal/tests $ python pydantic_test.py --run-deserialisation-test
===== DESERIALIZING =====
/home/louis/miniconda3/envs/fal39/lib/python3.9/site-packages/pydantic/main.py:1406: RuntimeWarning: fields may not start with an underscore, ignoring "__annotations__"
  warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
===== INSTANTIATING =====

Dunder methods are valid to deserialise

Additionally, there are dunder methods on CompressedFile which explains why this approach won't work!

E.g. a trivial class MyModel with a _private_field and accessor method __get_private_field__ shows that custom dunders are interspersed with a few that maybe shouldn't be messed with:

>>> pprint([k for k in MyModel.__dict__ if k.startswith("_") if not k.startswith("__pydantic_")])
['__module__',
 '__annotations__',
 '__get_private_field__',
 '__class_vars__',
 '__private_attributes__',
 '__weakref__',
 '__doc__',
 '__abstractmethods__',
 '_abc_impl',
 '__signature__']

Or maybe we can... Maybe we could simply:

  • Do some inspection to see whether the methods are bound or belong to the model base class
  • Check if they're already set (but this wouldn't work in cases where we're overriding them like a custom __init__, like for CompressedFile)

It turns out you can distinguish between a Pydantic model with a default autogenerated (dataclass-style) __init__ method and one with a custom one by whether it's in __dict__

louis 🌟 ~/lab/fal/pyd2/round_2 $ python -i private_attr.py 
>>> "__init__" in MyModel.__dict__
False
>>> 
louis 🌟 ~/lab/fal/pyd2/round_2 $ python -i private_attr_custom_init.py 
>>> "__init__" in MyModel.__dict__
True

I'd expect this will mean exactly what it looks like: whether the class's namespace has the method defined in it: so in fact you'd want to enumerate methods down the entire MRO until you reach the base class (which we have access to!)

Therefore it's actually relevant to methods in general, and nothing to do with dunders specifically. This means we have a way to filter for legit methods I think!

@lmmx
Copy link
Author

lmmx commented Feb 12, 2024

Dug into this some more and the dunders can be identified from the model metaclass MRO based on the qualname

E.g. the __init__ method of File is set (and therefore should be serialised as a method) but its __eq__ method is simply acquired by "falling through" to BaseModel's method

(Pdb) p model.__eq__.__class__
<class 'function'>
(Pdb) p model.__eq__.__module__
'pydantic.main'
(Pdb) p model.__eq__
<function BaseModel.__eq__ at 0x7fd829b1cee0>
(Pdb) p model.__init__
<function File.__init__ at 0x7fd829b28c10>
(Pdb) p model.__init__.__qualname__
'File.__init__'

We can therefore test this based on the qualnames of the two classes being similar, or more robustly we can take the first part of the qualname and compare it to the class name

Negative result for __eq__

(Pdb) p model.__qualname__
'File'
(Pdb) p model.__eq__.__name__
'__eq__'
(Pdb) p model.__eq__.__qualname__
'BaseModel.__eq__'
(Pdb) p model.__eq__.__qualname__, f"{model.__qualname__}.{model.__eq__.__name__}"
('BaseModel.__eq__', 'File.__eq__')
(Pdb) p model.__eq__.__qualname__ == f"{model.__qualname__}.{model.__eq__.__name__}"
False

Positive result for __init__

(Pdb) p model.__qualname__
'File'
(Pdb) p model.__init__.__name__
'__init__'
(Pdb) p model.__init__.__qualname__
'File.__init__'
(Pdb) p model.__init__.__qualname__, f"{model.__qualname__}.{model.__init__.__name__}"
('File.__init__', 'File.__init__')
(Pdb) p model.__init__.__qualname__ == f"{model.__qualname__}.{model.__init__.__name__}"
True

@lmmx
Copy link
Author

lmmx commented Feb 12, 2024

The good news is: the serialisation is working! The approach to get methods involves checking the qualname, with classmethods detected based on their .__class__.__name__ and then their __func__ used instead of their __dict__ value

The bad news is: the mechanism uses just a single level of the MRO, so calls to super will trigger recursion (I naively hoped that the base classes might just work out nicely)

/root/.cache/isolate/virtualenv/41b75195d7b215f22ee035bac8643a593c1c84af7a90e9a23e2831c305aac606/lib/python3.9/site-packages/dill/_dill.py:412: PicklingWarning: Cannot pickle <class 'main.File'>: main.File has recursive self-references that trigger a RecursionError.

  • This one only showed up in the logs

I suspect that we might be able to interfere with the MRO manually? If it's legit/possible? (Just spoof it, like we spoof everything else)

2024-02-12 22:24:50.996 [stderr   ] /root/.cache/isolate/virtualenv/41b75195d7b215f22ee035bac8643a593c1c84af7a90e9a23e2831c305aac606/lib/python3.9/site-packages/dill/_dill.py:412:
PicklingWarning: Cannot pickle <class '__main__.File'>: __main__.File has recursive self-refe
rences that trigger a RecursionError.                                                                                                                                                                                                                                            
2024-02-12 22:24:50.996 [stderr   ]   StockPickler.save(self, obj, save_persistent_id)                                                  
2024-02-12 22:24:50.996 [stderr   ] Traceback (most recent call last):                                                                                                                                                                                                           
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/src/fal/toolkit/file/file/standard.py", line 95, in from_bytes                 
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/src/fal/toolkit/file/file/standard.py", line 55, in __init__                                                                                                                                                            
TypeError: super(type, obj): obj must be an instance or subtype of type                                                                                                                                                                                                          
                                                                                                                                        
During handling of the above exception, another exception occurred:                                                                                                                                                                                                              
                                                                                                                                        
Traceback (most recent call last):                                                                                                                                                                                                                                               
  File "/opt/venv/lib/python3.9/site-packages/isolate/connections/grpc/agent.py", line 130, in execute_function                                                                                                                                                                  
    result = function(*extra_args)                                                                                                                                                                                                                                               
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/src/fal/api.py", line 183, in wrapper                                          
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/tests/integration_test.py", line 470, in fal_file_from_temp                    
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/src/fal/toolkit/file/file/standard.py", line 114, in from_path                                                                                                                                                          
  File "/home/louis/dev/fal/pydantic-2-bump/projects/fal/src/fal/toolkit/file/file/standard.py", line 100, in from_bytes                
ValueError: (<class '__main__.File'>, <class 'pydantic.main.BaseModel'>, <class 'object'>)                                                                                                                                                                                       

Note The remaining failing tests can be targeted specifically with

python -m pytest integration_test.py -k "path or bytes or save or input or compressed" -s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants