python-cmd2 / cmd2

cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python
https://cmd2.readthedocs.io/en/stable/
MIT License
613 stars 116 forks source link

TypeError: __init__() got an unexpected keyword argument 'allow_abbrev' #1073

Closed glisignoli closed 3 years ago

glisignoli commented 3 years ago

I get the following error when trying to use cmd2

Traceback (most recent call last):
  File "/usr/local/bin/fcreplay", line 33, in <module>
    sys.exit(load_entry_point('fcreplay==0.9', 'console_scripts', 'fcreplay')())
  File "/usr/local/bin/fcreplay", line 25, in importlib_load_entry_point
    return next(matches).load()
  File "/usr/local/lib/python3.8/importlib/metadata.py", line 77, in load
    module = import_module(match.group('module'))
  File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/usr/local/lib/python3.8/site-packages/fcreplay-0.9-py3.8.egg/fcreplay/__main__.py", line 26, in <module>
    from fcreplay.cli import Cli
  File "/usr/local/lib/python3.8/site-packages/fcreplay-0.9-py3.8.egg/fcreplay/cli.py", line 3, in <module>
    import cmd2
  File "/usr/local/lib/python3.8/site-packages/cmd2-1.5.0-py3.8.egg/cmd2/__init__.py", line 30, in <module>
    from .cmd2 import Cmd
  File "/usr/local/lib/python3.8/site-packages/cmd2-1.5.0-py3.8.egg/cmd2/cmd2.py", line 182, in <module>
    class Cmd(cmd.Cmd):
  File "/usr/local/lib/python3.8/site-packages/cmd2-1.5.0-py3.8.egg/cmd2/cmd2.py", line 2785, in Cmd
    alias_parser = DEFAULT_ARGUMENT_PARSER(description=alias_description, epilog=alias_epilog)
  File "/usr/local/lib/python3.8/site-packages/cmd2-1.5.0-py3.8.egg/cmd2/argparse_custom.py", line 823, in __init__
    super(Cmd2ArgumentParser, self).__init__(
TypeError: __init__() got an unexpected keyword argument 'allow_abbrev'

https://github.com/glisignoli/fcreplay/blob/master/fcreplay/cli.py

tleonhardt commented 3 years ago

@glisignoli Can you please provide more information so we can attempt to reproduce? Things which might be useful include:

glisignoli commented 3 years ago

Os: Debian 10 (Buster) Python Version: 3.8 cmd2 version: 1.5.0 Terminal: docker / bash / windows terminal

Pip freeze output:

attrs==20.3.0
backports.csv==1.0.7
beautifulsoup4==4.9.3
Bootstrap-Flask==1.5.1
cachetools==4.2.1
cairocffi==1.2.0
CairoSVG==2.5.2
Cerberus==1.3.2
certifi==2020.12.5
cffi==1.14.5
chardet==4.0.0
click==7.1.2
cmd2==1.5.0
colorama==0.4.4
contextlib2==0.6.0.post1
cssselect2==0.4.1
Cython==0.29.22
debugpy==1.2.1
defusedxml==0.7.1
distro==1.5.0
docker==4.4.4
docopt==0.6.2
dominate==2.6.0
EasyProcess==0.3
entrypoint2==0.2.3
fcreplay==0.9
Flask==1.1.2
Flask-Cors==3.0.10
Flask-SQLAlchemy==2.4.4
Flask-WTF==0.14.3
google-api-core==1.26.1
google-api-python-client==2.0.2
google-auth==1.27.1
google-auth-httplib2==0.1.0
googleapis-common-protos==1.53.0
greenlet==1.0.0
gunicorn==20.0.4
httplib2==0.19.0
i3ipc==2.2.1
idna==2.10
internetarchive==1.9.9
itsdangerous==1.1.0
jeepney==0.6.0
Jinja2==2.11.3
jsonpatch==1.32
jsonpointer==2.1
lxml==4.6.2
MarkupSafe==1.1.1
MouseInfo==0.1.3
mss==6.1.0
numpy==1.20.1
oauth2client==4.1.3
packaging==20.9
Pillow==8.1.2
progressbar2==3.53.1
protobuf==3.15.6
psycopg2==2.8.6
pyasn1==0.4.8
pyasn1-modules==0.2.8
PyAutoGUI==0.9.52
pycparser==2.20
PyGetWindow==0.0.9
PyMsgBox==1.0.9
pyparsing==2.4.7
pyperclip==1.8.2
PyRect==0.1.4
pyscreenshot==2.3
PyScreeze==0.1.26
python-logging-loki==0.3.1
python-utils==2.5.6
python-xlib==0.29
python3-xlib==0.15
PyTweening==1.0.3
pytz==2021.1
requests==2.25.1
retrying==1.3.3
rfc3339==6.2
rsa==4.7.2
schedule==1.0.0
schema==0.7.4
scikit-build==0.11.1
six==1.15.0
soupsieve==2.2
SQLAlchemy==1.4.1
SQLAlchemy-Utils==0.36.8
tinycss2==1.1.0
tqdm==4.59.0
uritemplate==3.0.1
urllib3==1.26.3
visitor==0.1.3
wcwidth==0.2.5
webencodings==0.5.1
websocket-client==0.58.0
Werkzeug==1.0.1
WTForms==2.3.3
youtube-upload==0.8.0
MaxWipfli commented 3 years ago

fI got a similar error while trying to use the completer argument to Cmd2ArgumentParser.

Traceback (most recent call last):
  File "mwe.py", line 3, in <module>
    class App(cmd2.Cmd):
  File "mwe.py", line 5, in App
    parser.add_argument('file', completer=cmd2.Cmd.path_complete)
  File "/home/user/.local/lib/python3.8/site-packages/cmd2/argparse_custom.py", line 478, in _add_argument_wrapper
    new_arg = orig_actions_container_add_argument(self, *args, **kwargs)
  File "/usr/lib/python3.8/argparse.py", line 1380, in add_argument
    action = action_class(**kwargs)
TypeError: __init__() got an unexpected keyword argument 'completer'

Minimal working example:

import cmd2

class App(cmd2.Cmd):
    parser = cmd2.Cmd2ArgumentParser()
    parser.add_argument('file', completer=cmd2.Cmd.path_complete)
    @cmd2.with_argparser(parser)
    def do_test(self, args):
        print(args.file)
Ubuntu 20.04 LTS
Python 3.8.5
cmd 1.5.0

Possible Solution

I think the problem is that all **kwargs are passed onto the original ArgumentParser.add_argument function in file cmd2/argparse_custom.py on line 445:

new_arg = orig_actions_container_add_argument(self, *args, **kwargs)

I assume that argparse is checking for "invalid" keyword arguments and thus throws an error. The "new" arguments supported by Cmd2ArgumentParsershould be removed from kwargs before forwarding it to argparse.ArgumentParser.

anselor commented 3 years ago

@MaxWipfli Your issue is more of a documentation reference issue. The completer parameter is part of the new Cmd2 2.0 release we're still working on. The last published version of cmd2 (1.5) doesn't have that parameter defined.

kmvanbrunt commented 3 years ago

Use completer_method on cmd2 1.5.

MaxWipfli commented 3 years ago

@anselor @kmvanbrunt Thank you very much!

glisignoli commented 3 years ago

@kmvanbrunt Can you leave this open? My issue isn't resolved yet.

glisignoli commented 3 years ago

Still not sure what's going on here

I'm using my setup.py to create /usr/local/bin/fcreplay

....
   entry_points={"console_scripts": ["fcreplay=fcreplay.__main__:main"]},
...

Which generates:

#!/usr/local/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'fcreplay==0.9','console_scripts','fcreplay'
import re
import sys

# for compatibility with easy_install; see #2198
__requires__ = 'fcreplay==0.9'

try:
    from importlib.metadata import distribution
except ImportError:
    try:
        from importlib_metadata import distribution
    except ImportError:
        from pkg_resources import load_entry_point

def importlib_load_entry_point(spec, group, name):
    dist_name, _, _ = spec.partition('==')
    matches = (
        entry_point
        for entry_point in distribution(dist_name).entry_points
        if entry_point.group == group and entry_point.name == name
    )
    return next(matches).load()

globals().setdefault('load_entry_point', importlib_load_entry_point)

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(load_entry_point('fcreplay==0.9', 'console_scripts', 'fcreplay')())

If I run fcreplay cli from bash, I get the reported error. If I run python3.8 /usr/local/bin/fcreplay cli I still get the reported error. But, if I run python3.8 -m pudb /usr/local/bin/fcreplay cli it works fine.

Then if I run python3.8 -m pdb /usr/local/bin/fcreplay cli I get the error reported. I'm lost as to why pudb3 will cause this to work, yet anything else wont.

anselor commented 3 years ago

@glisignoli Can you try creating a fresh venv and installing in there?

What you're describing doesn't make sense and I'm very suspicious of your host environment.

I've on many occasions ended up with a completely unusable python environment when mixing Linux packaging with python's own packaging system. On one occasion, I ended up with python 2 base libraries getting loaded when I run python 3.

glisignoli commented 3 years ago

I get the same thing when running in a virtual environment with pipenv.

The host environment is the python 3.8 buster image (https://hub.docker.com/_/python)

My Dockerfile looks like this: https://pastebin.com/5yuJ9kHw

Running with:

docker-compose run --rm --entrypoint /bin/bash fcreplay-tasker
Creating fcreplay_fcreplay-tasker_run ... done
root@7c1bfb0b32e0:/# cd /root
root@7c1bfb0b32e0:~# pipenv run fcreplay
Traceback (most recent call last):
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/bin/fcreplay", line 33, in <module>
    sys.exit(load_entry_point('fcreplay==0.9', 'console_scripts', 'fcreplay')())
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/bin/fcreplay", line 25, in importlib_load_entry_point
    return next(matches).load()
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/importlib/metadata.py", line 77, in load
    module = import_module(match.group('module'))
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/site-packages/fcreplay-0.9-py3.8.egg/fcreplay/__main__.py", line 26, in <module>
    from fcreplay.cli import Cli
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/site-packages/fcreplay-0.9-py3.8.egg/fcreplay/cli.py", line 3, in <module>
    import cmd2
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/site-packages/cmd2/__init__.py", line 30, in <module>
    from .cmd2 import Cmd
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/site-packages/cmd2/cmd2.py", line 182, in <module>
    class Cmd(cmd.Cmd):
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/site-packages/cmd2/cmd2.py", line 2785, in Cmd
    alias_parser = DEFAULT_ARGUMENT_PARSER(description=alias_description, epilog=alias_epilog)
  File "/root/.local/share/virtualenvs/root-BuDEOXnJ/lib/python3.8/site-packages/cmd2/argparse_custom.py", line 823, in __init__
    super(Cmd2ArgumentParser, self).__init__(
TypeError: __init__() got an unexpected keyword argument 'allow_abbrev'
glisignoli commented 3 years ago

Found the issue (with a lot of help).

Another library (pyscreenshot) is importing entrypoint2, which uses https://github.com/ThomasWaldmann/argparse as a requirement.

See: https://github.com/ponty/entrypoint2/issues/9

Consider this resolved, since it's nothing to do with cmd2

kmvanbrunt commented 3 years ago

@glisignoli Thanks for the update. That certainly explains it since allow_abbrev wasn't introduced until the Python 3.5 version of argparse.