python-fire icon indicating copy to clipboard operation
python-fire copied to clipboard

not compatible with pydantic.validate_arguments

Open xbanke opened this issue 3 years ago • 4 comments

A function with Field parameter wrapped by pydantic.validate_arguments, can not been exeuted from the command line.

from datetime import datetime
from pydantic import Field, validate_arguments


@validate_arguments()
def foo(dt: datetime = Field(default_factory=datetime.now)):
    print(dt)


if __name__ == '__main__':
    import fire
    fire.Fire(foo)

run this code from command line with raise:

Traceback (most recent call last):
  File "/home/xxx/repositories/others/test_fire.py", line 12, in <module>
    fire.Fire(foo)
  File "/home/xxx/.conda/envs/py39/lib/python3.9/site-packages/fire/core.py", line 141, in Fire
    component_trace = _Fire(component, args, parsed_flag_args, context, name)
  File "/home/xxx/.conda/envs/py39/lib/python3.9/site-packages/fire/core.py", line 466, in _Fire
    component, remaining_args = _CallAndUpdateTrace(
  File "/home/xxx/.conda/envs/py39/lib/python3.9/site-packages/fire/core.py", line 681, in _CallAndUpdateTrace
    component = fn(*varargs, **kwargs)
  File "pydantic/decorator.py", line 40, in pydantic.decorator.validate_arguments.validate.wrapper_function
    from contextlib import _GeneratorContextManager
  File "pydantic/decorator.py", line 133, in pydantic.decorator.ValidatedFunction.call
    func.__dict__.update(kw)
  File "pydantic/decorator.py", line 130, in pydantic.decorator.ValidatedFunction.init_model_instance
    else:
  File "pydantic/main.py", line 341, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for Foo
dt
  invalid type; expected datetime, string, bytes, int or float (type=type_error)

xbanke avatar Aug 29 '22 02:08 xbanke

Thanks for raising this. I'm marking it as a bug.

It looks like the call to foo is failing at https://github.com/google/python-fire/blob/37c4305194ff3d0a63f435f08a40e14b1978bd4e/fire/core.py#L475-L480

This is surprising, because calling foo without arguments normally (i.e. without _CallAndUpdateTrace) passes pydantic's validation, but making the call with _CallAndUpdateTrace fails validation.

Looking deeper, I see the arguments being used to call foo by _CallAndUpdateTrace are different than when calling foo directly. This is determined by these lines: https://github.com/google/python-fire/blob/37c4305194ff3d0a63f435f08a40e14b1978bd4e/fire/core.py#L682-L683

When this is run, varargs takes on the value [FieldInfo(default=PydanticUndefined, default_factory=<built-in method now of type object at 0x10292f978>, extra={})] rather than []. This seems problematic. The next steps are to investigate why this occurs and what the appropriate change to make is to resolve it.

dbieber avatar Sep 13 '22 16:09 dbieber

See also #343 -- in that issue @melsabagh-kw shows a decorator he wrote to get typeguard typechecking with fire.

dbieber avatar Sep 13 '22 17:09 dbieber

Can I look into this? @dbieber

varshneydevansh avatar Sep 07 '23 13:09 varshneydevansh

Yes, just please be advised that we don't have any planned review time for accepting PRs right now, so it might be a while before we can provide feedback or accept your proposed change.

dbieber avatar Sep 07 '23 15:09 dbieber