lebrice / SimpleParsing

Simple, Elegant, Typed Argument Parsing with argparse
MIT License
384 stars 46 forks source link

Literals not parsing correctly in python 3.9 #259

Closed levmckinney closed 1 year ago

levmckinney commented 1 year ago

Describe the bug Literals appear to be broken in python 3.9. Valid inputs are not recognized as valid during parsing. Interestingly, I do not appear to have this issue in python 3.10

To Reproduce

from typing import Literal
from dataclasses import dataclass
from simple_parsing import ArgumentParser

@dataclass
class Foo:
    param: Literal['bar', 'biz'] = 'biz'

def test_parsing():
    parser = ArgumentParser()
    parser.add_arguments(Foo, dest="foo")
    args = parser.parse_args()
    print(args.foo.param)

if __name__ == '__main__':
    test_parsing()

Expected behavior A clear and concise description of what you expected to happen.

$ python issue.py
biz

Actual behavior A clear and concise description of what is happening.

$ python issue.py
usage: issue.py [-h] [--param typing.Literal['bar', 'biz']]
issue.py: error: argument --param: invalid typing.Literal['bar', 'biz'] value: 'biz'
$ python issue.py --param biz
usage: issue.py [-h] [--param typing.Literal['bar', 'biz']]
issue.py: error: argument --param: invalid typing.Literal['bar', 'biz'] value: 'biz'

Desktop (please complete the following information):

Additional context I am not encountering this bug in python 3.10 it only appears to be causing my python 3.9 CI to fail.

Complete pip freeze

accelerate==0.19.0
aiohttp==3.8.4
aiosignal==1.3.1
appdirs==1.4.4
asttokens==2.2.1
async-timeout==4.0.2
attrs==23.1.0
backcall==0.2.0
certifi==2023.5.7
charset-normalizer==3.1.0
click==8.1.3
cmake==3.26.3
comm==0.1.3
coverage==7.2.6
datasets==2.12.0
debugpy==1.6.7
decorator==5.1.1
dill==0.3.6
docker-pycreds==0.4.0
docstring-parser==0.15
exceptiongroup==1.1.1
executing==1.2.0
fastjsonschema==2.17.1
filelock==3.12.0
frozenlist==1.3.3
fsspec==2023.5.0
gitdb==4.0.10
GitPython==3.1.31
huggingface-hub==0.14.1
idna==3.4
importlib-metadata==6.6.0
iniconfig==2.0.0
ipykernel==6.23.1
ipython==8.13.2
jedi==0.18.2
Jinja2==3.1.2
jsonschema==4.17.3
jupyter_client==8.2.0
jupyter_core==5.3.0
lit==16.0.5
MarkupSafe==2.1.2
matplotlib-inline==0.1.6
mock==5.0.2
mpmath==1.3.0
multidict==6.0.4
multiprocess==0.70.14
nbclient==0.6.8
nbformat==5.8.0
nbmake==1.4.1
nest-asyncio==1.5.6
networkx==3.1
numpy==1.24.3
nvidia-cublas-cu11==11.10.3.66
nvidia-cuda-cupti-cu11==11.7.101
nvidia-cuda-nvrtc-cu11==11.7.99
nvidia-cuda-runtime-cu11==11.7.99
nvidia-cudnn-cu11==8.5.0.96
nvidia-cufft-cu11==10.9.0.58
nvidia-curand-cu11==10.2.10.91
nvidia-cusolver-cu11==11.4.0.1
nvidia-cusparse-cu11==11.7.4.91
nvidia-nccl-cu11==2.14.3
nvidia-nvtx-cu11==11.7.91
packaging==23.1
pandas==2.0.1
parso==0.8.3
pathtools==0.1.2
pexpect==4.8.0
pickleshare==0.7.5
platformdirs==3.5.1
plotly==5.14.1
pluggy==1.0.0
prompt-toolkit==3.0.38
protobuf==4.23.2
psutil==5.9.5
ptyprocess==0.7.0
pure-eval==0.2.2
pyarrow==12.0.0
pydantic==1.10.8
Pygments==2.15.1
pyrsistent==0.19.3
pytest==7.3.1
pytest-cov==4.1.0
pytest-skip-slow==0.0.5
python-dateutil==2.8.2
pytz==2023.3
PyYAML==6.0
pyzmq==25.1.0
regex==2023.5.5
requests==2.31.0
responses==0.18.0
sentencepiece==0.1.99
sentry-sdk==1.24.0
setproctitle==1.3.2
simple-parsing==0.1.2.post1
six==1.16.0
smmap==5.0.0
stack-data==0.6.2
sympy==1.12
tenacity==8.2.2
tokenizers==0.13.3
tomli==2.0.1
torch==2.0.1
torchdata==0.6.1
tornado==6.3.2
tqdm==4.65.0
traitlets==5.9.0
transformers==4.29.2
triton==2.0.0
-e git+https://github.com/AlignmentResearch/tuned-lens.git@c2603edf0d4e06c61ac70770ebf04c86c745f25e#egg=tuned_lens
typing_extensions==4.6.2
tzdata==2023.3
urllib3==1.26.16
wandb==0.15.3
wcwidth==0.2.6
xxhash==3.2.0
yarl==1.9.2
zipp==3.15.0
levmckinney commented 1 year ago

Okay I found a mitigation:

from typing_extensions import Literal

It seems like its typing.Literal specifically that has the issue.

brentyi commented 1 year ago

This PR is the reason: https://github.com/python/typing_extensions/pull/148

lebrice commented 1 year ago

Oh this is really interesting stuff! Thanks @levmckinney for posting the issue, and thanks @brentyi for finding (what appears to be) the cause of the bug!

Did this issue appear suddenly lately? Is there perhaps something I could be doing differently in simple-parsing?

IIRC I'm using typing.get_args (or some variant of it) to get the parameters of the Literal type annotation, and passing those as the choices argument to parser.add_argument.

zhiruiluo commented 1 year ago

This issue also causes DocTestFailure in simple_parsing/utils.py for Python 3.9 and Python 3.8.

>>> is_literal(Literal[True, False])
Expected:
    True
Got:
    False