Closed
Description
It looks like there was a regression in the assembling refactor.
The following used to work:
import sys
import argh
from argparse import FileType
@argh.arg("-x", type=FileType("r", encoding="utf-8"), default=sys.stdin)
def foo(*, x):
pass
if __name__ == "__main__":
p = argh.ArghParser(prog="foo")
p.add_commands([foo])
p.dispatch()
Since 0.30.0 it results in the following stacktrace:
File "/path/to/project/venv/lib/python3.11/site-packages/argh/helpers.py", line 47, in add_commands
return add_commands(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/project/venv/lib/python3.11/site-packages/argh/assembling.py", line 557, in add_commands
set_default_command(
File "/path/to/project/venv/lib/python3.11/site-packages/argh/assembling.py", line 319, in set_default_command
spec = _prepare_parser_add_argument_spec(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/project/venv/lib/python3.11/site-packages/argh/assembling.py", line 354, in _prepare_parser_add_argument_spec
spec = ParserAddArgumentSpec(**asdict(parser_add_argument_spec))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/dataclasses.py", line 1284, in asdict
return _asdict_inner(obj, dict_factory)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/dataclasses.py", line 1291, in _asdict_inner
value = _asdict_inner(getattr(obj, f.name), dict_factory)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/dataclasses.py", line 1325, in _asdict_inner
return copy.deepcopy(obj)
^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/copy.py", line 161, in deepcopy
rv = reductor(4)
^^^^^^^^^^^
TypeError: cannot pickle '_io.TextIOWrapper' object
I suspect it can't picke sys.stdin
?
Side note: Was it intentional that the keyword-only arguments become already mandatory?
#191 mentioned a smooth transition path.
If you change the above example to:
@argh.arg("-x", type=FileType("r", encoding="utf-8"), default=sys.stdin)
def foo(x):
pass
It fails with argh.exceptions.AssemblingError: foo: argument "x" declared as positional (in function signature) and optional (via decorator)
Not that big of a deal and easy enough to adjust, but given that the issue mentions that there should be a smooth migration I wanted to mention it too.