Coder Social home page Coder Social logo

python-cmd2 / cmd2 Goto Github PK

View Code? Open in Web Editor NEW
584.0 23.0 112.0 8.73 MB

cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python

Home Page: https://cmd2.readthedocs.io/en/stable/

License: MIT License

Python 99.69% Shell 0.31%
python command-line cli terminal shell developer-tools auto-completion scripting unicode tab-completion

cmd2's People

Contributors

albertored avatar anselor avatar bambu avatar catherinedevlin avatar dependabot[bot] avatar dhellmann avatar ethanmcc avatar fdiasr avatar federicoceratto avatar felixonmars avatar gmmephisto avatar jayrod avatar jbraeuer avatar kami avatar kmvanbrunt avatar kotfu avatar ksunden avatar kyleking avatar lancestarr avatar lobocv avatar mgorny avatar mrkevinweiss avatar naveensrinivasan avatar nsoranzo avatar rowdyrotifer avatar srowe avatar starwarsfan2099 avatar stratosgear avatar tleonhardt avatar viralmutant avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cmd2's Issues

Missing Option to Prevent Processing of CLI Args

Originally reported by: Tyler Abair (Bitbucket: tabair, GitHub: tabair)


Cmd2 has a cool feature where it will process all CLI args passed to a script as commands, but there is no option to turn this feature off.

A quick work-around that I'm using at the moment is to save sys.argv to a tmp variable, and then set sys.argv = [tmp[0]] just before calling Cmd.cmdloop() and restore it after, but it'd be much nicer if I could just set an instance variable on my Cmd object to turn this feature off instead.


Use of parse_args in cmdloop

Originally reported by: Bhairav Shah (Bitbucket: bhairav, GitHub: bhairav)


In the cmdloop method, the following line is present:

#!python

(callopts, callargs) = parser.parse_args()

Digging deeper into optparse, parse_args() calls the below line:

#!python

rargs = self._get_args(args)

Which in turn has this:

#!python

    def _get_args(self, args):
        if args is None:
            return sys.argv[1:]
        else:
            return args[:]              # don't modify caller's list

While it may make sense for _get_args in optparse to use the sys.argv arguments, would it make sense for cmd2 to do the same? Thinking that cmd2 doesn't need to allow reading from normal shell commandline because it is supposed to be an embedded interpreter within the program.

Wondering if cmdloop in cmd2 can be fixed in one of two ways:

  1. To put an empty arg list to force _get_args to not use sys.argv:
#!python

(callopts, callargs) = parser.parse_args(args=[])

OR

  1. To allow the program to put an empty list in cmdloop (though that might break compatibility with cmd:
#!python

cmdloop(args=[])

I tested with option 1, and was able to make my program work by not having it complain with the following kind of error:

error: no such option: -f

Thanks.


test_input_redirection fails on Arch Linux

The same error happens with either Python 3.6.0 or 2.7.13:

=================================== FAILURES ===================================
____________________________ test_input_redirection ____________________________

base_app = <cmd2.Cmd object at 0x7fdd39ddab38>
request = <FixtureRequest for <Function 'test_input_redirection'>>

    @pytest.mark.skipif(sys.platform.startswith('linux') and getpass.getuser() == 'travis',
                        reason="Unit test passes on Ubuntu 16.04 and Debian 8.7, but fails on TravisCI Linux containers")
    def test_input_redirection(base_app, request):
        test_dir = os.path.dirname(request.module.__file__)
        filename = os.path.join(test_dir, 'redirect.txt')

        # NOTE: File 'redirect.txt" contains 1 word "history"

        # Verify that redirecting input from a file works
        out = run_cmd(base_app, 'help < {}'.format(filename))
        expected = normalize(HELP_HISTORY)
>       assert out == expected
E       assert [] == ['history [arg]: lists past ...lar expression search', ...]
E         Right contains more items, first extra item: 'history [arg]: lists past commands issued'
E         Use -v to get the full diff

tests/test_cmd2.py:361: AssertionError
===================== 1 failed, 77 passed in 37.79 seconds =====================

List all help as one-liners

Originally reported by: Anonymous


I find it efficient to list a summary of help for all documented commands. Thought you might find this worth including. Thanks for a nice tool! --Ken Bannister

#!python
    self.doc_header = 'Commands (type "help all" or "help <topic>"):'

    def help_all(self):
        """Lists first line of help for all documented commands"""
        names = self.get_names()
        names.sort()
        for name in names:
            if name[:3] == 'do_':
                try:
                    doc = getattr(self, name).__doc__
                    if doc:
                        maxlen = 65
                        ellipsis = ''
                        if len(doc) > maxlen:
                            ellipsis = '...'
                        self.stdout.write('{0} - {1}{2}\n'.format(
                                    name[3:80-maxlen], doc[:maxlen], ellipsis))
                except AttributeError:
                    pass

How to switch previous command

(Cmd) help

Documented commands (type help <topic>):
========================================
_relative_load  edit  help     list  orate  py    run   say  shell      show
cmdenvironment  eof   history  load  pause  quit  save  set  shortcuts  speak

(Cmd) ^[[A

when I press arrow up, I expect to show the previous command (help), but just display ^[[A. I guess it displayed what it read from keyboard event without processing.

cannot integrate cmd2 into event loops

Originally reported by: Michael Haberler (Bitbucket: mhaberler, GitHub: mhaberler)


I wish there were a way to register cmd2 input with event loops like zmq.loop, asyncio, poll, gobject/gevent etc without occupying the main loop

the assumption cmd2 owns the inner loop of a program is very restrictive - even Gnu readline can be used from an event loop (C, not Python though)

using threading is an overkill for the purpose, and brings its own set of problems


Piping output to input of os command causes unhandled exception on Python 3.x

The output redirection feature where command output can be piped (|) as input to operating-system commands, as in "help | wc" is broken for Python 3.x but still works for Python 2.7. This feature's expected behavior is documented here:
https://cmd2.readthedocs.io/en/latest/freefeatures.html#output-redirection

Not only is it broken, but it causes an unhandled exception. It appears to be a str (unicode) vs bytes issue.

When "debug" is set to True, this is the exception I got:
(Cmd) help | wc
Traceback (most recent call last):
File "/Users/toddleonhardt/src/cmd2/cmd2.py", line 872, in onecmd_plus_hooks
stop = self.onecmd(statement)
File "/Users/toddleonhardt/src/cmd2/cmd2.py", line 955, in onecmd
stop = func(statement)
File "/Users/toddleonhardt/src/cmd2/cmd2.py", line 543, in do_help
cmd.Cmd.do_help(self, arg)
File "/Users/toddleonhardt/anaconda/lib/python3.5/cmd.py", line 333, in do_help
self.stdout.write("%s\n"%str(self.doc_leader))
TypeError: a bytes-like object is required, not 'str'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/toddleonhardt/src/cmd2/cmd2.py", line 877, in onecmd_plus_hooks
self.restore_output(statement)
File "/Users/toddleonhardt/src/cmd2/cmd2.py", line 928, in restore_output
self.kept_state.stdout.write(result or '')
TypeError: write() argument must be str, not bytes

allow_cli_args not properly disabling usage of Optparse to look for -t transcript testing arg

Currently even if CLI args are disabled, cmd2 still tries to use OptParse to look for the "-t" flag which enables transcript testing. This interferes with using something like ArgParse to handle command line arguments for the overall application.

The when the allow_cli_args attribute is False, it should disable ALL processing of command-line arguments, including the "-t" one passed for transcript testing.

Order of shortcuts matter, but defined as dictionary

Originally reported by: Kent Duncan (Bitbucket: slamduncan, GitHub: slamduncan)


When adding to the shortcut list, if one shortcut is the start of another shortcut than it will override it and pass the remainder of the longer shortcut in arg.

Example:
Cmd.shortcuts.update({
'p': 'first_sc',
'pcon' : 'second_sc',
})

When it's running if you type in pcon it will call do_first_sc with the arg 'con'.


Local path completion wanted

It would be nice for commands which interact with the local file system such as edit, load, and shell to have built-in tab completion based on file system paths.

All commands should go through same shlex parsing

Currently arguments for commands using the options decorator are split using shlex.split(), however arguments for commands which do not use the options decorator are not split in this fashion.

Ideally, arguments for all commands would go through a more similar processing chain.

The real question, is where is the best place in the code to do that?

Investigate refactoring to allow incorporation of prompts from python-prompt-toolkit

Python Prompt Toolkit provides some really powerful and cool features:
https://github.com/jonathanslenders/python-prompt-toolkit

It would be nice if a cmd2 user could optionally replace the default prompt with a prompt from python-prompt-toolkit.

This would at a minimum require replacing the simple string prompt with a function which prints a prompt and returns the text the user entered. It would be somewhat of a departure from cmd. But it would open up the door for easily incorporating things like syntax-highlighting, input validation, and a bottom toolbar.

I'm not sure it would really be possible to make cmd2 and python-prompt-toolkit play nicely together, but if it is, it would be a great thing.

Consider alternative readline imports for OS compatibility

Mac OS X ships with libedit instead of libreadline. libedit doesn't work well with Python's readline module. So a user either needs to use homebrew to install GNU readline or they need to use pip to install the gnureadline module which is a version of Python's readline module which is statically linked to the GNU readline library.

So to help with Mac OS X compatibility for users that have gnureadline installed instead of libreadline, it would be good to have an import setup like so:

try:
    import gnureadline as readline
except ImportError:
    import readline

python3 doesn't have file type like python2 does

Originally reported by: Anonymous


Using python3.3 with a cmd2.py modified by 2to3.
There are two instances were cmd2 checks whether some object is of type file. There is apparently no builtin type file.

I fixed the issue this way:

try:
import io
file = io.TextIOWrapper
except ImportError:
pass # Python2

But only tried it on python3 version.

Also your documentation claims that cmd has shortcuts @ and !: there doesn't appear to be any @, but there is a ? shortcut.


Fix a failure under Python 2.6

Originally reported by: Tomaz Muraus (Bitbucket: kami, GitHub: kami)


Latest version (0.6.5) introduced a regression which breaks cmd2 under Python 2.6.

#!bash

kami ~/cmd2 $ python2.6 setup.py 
Traceback (most recent call last):
  File "setup.py", line 11, in <module>
    if sys.version_info.major < 3:
AttributeError: 'tuple' object has no attribute 'major'

In Python 2.6, sys.version_info is a tuple and not an object like thing so doing sys.version_info.major won't work.

I'm including a patch which fixes it and works under all supported versions (2.6, 2.7, 3.x).


Parsing unit tests should not depend on pyparsing implementation details

Currently all of the unit tests which verify how the command line is parsed are tightly coupled with the details of the underlying pyparsing implementation.

These unit tests should be refactored in a way that they relate to how cmd2 parses the command line, but are not directly dependent upon this parsing being done by pyparsing in particular.

Once they are more generic, they could be used to help safely refactor cmd2 to use a different library for doing this parsing.

Empty lines can't trigger updates to the prompt

Currently entering an empty line completely bypasses all precmd and postcmd hooks, so there is no way to do something like update the prompt based on asynchronous notifications from a background thread when the user just presses enter.

postparsing_postcmd() should always be called, even for an empty line.

Replacing pyparsing with shlex

Python's built-in "shlex" module for simple lexical analysis is probably good enough to handle our command-line parsing in cmd2 and it is implemented in C, so its performance would probably be a lot better than pyparsing, which is implemented in pure Python.

ANTLR and PLY also look like potentially superior alternatives to pyparsing, which is slow, dated, and at least in our case requires an overly-complicated grammar.

But shlex should be preferred since it is built-in to Python and not 3rd-party.

shlex:
https://docs.python.org/3.6/library/shlex.html

pyparsing:
http://pyparsing.wikispaces.com

ANTLR:
https://github.com/antlr/antlr4

PLY:
https://github.com/dabeaz/ply

This is a long-term "down the road" idea.

Quit command doesn't really quit when issued from within a python script

In general, all cmd2 commands are scriptable within a Python script via "cmd('command args')". However, since when running within a Python script we are actually within the do_py command, quit doesn't actually quit the cmd2 application.

The current behavior is non-intuitive. Issuing a cmd('quit') should really quit.

Add code like the following to do_quit() and do_py():

def do_quit(self):
    self._should_quit = True

def do_py(self):
    ...
    return self._should_quit

Consider adding support for nested commands or subcommands

Many REPL frameworks have support for multi-level commands, where the command has sub-commands.

While this can be done with cmd2, there isn't any built-in support to make it easy.

Consider adding some built-in support to make it easy to have nested commands or subcommands.

Easy way to integrate use as commandline over socket/telnet?

Originally reported by: Stuart Axon (Bitbucket: stuaxo, GitHub: stuaxo)


I have a homebuild command parser I'm using on my socket server, I'd like to use something like cmd2 instead.

Ideally, all the command history etc would be available - but that seems a bit ambitious ..

Is there a method I can pass a line of text + then cmd2 call the correct functions + return the feedback ?

That way I could use cmd2 for my ordinary shell and my socket shell.


Consider expanding scripting capability to include conditional control flow

The current built-in scripting capability is very nice for automating the execution of a series of commands.

However, there isn't any built-in way to run a command IF certain criteria are met (based on say whether or not a previous command "succeeded".

This may be beyond the scope of what cmd2 is intended to provide. But if there was an easy way to add this functionality, it would be useful.

The ability to recursively enter embedded interactive Python consoles considered harmful

The ability to enter a 2nd interactive Python console within an existing one via "cmd('py')" isn't helpful and could be harmful.

Recommend detecting if running in an interactive console, bypassing running a new one, and printing an error with something like:

def do_py(self):
    if self._in_py:
        self.perror("Recursively entering interactive Python consoles is not allowed.", traceback_war=False)
        return
    self._in_py = True

    ....
    self._in_py = False
    return self._should_quit

It would be useful to have more examples

Adding more, better, and more complicated / in depth examples which demonstrate the wealth of features present in cmd2 and the various ways cmd2 can be used in an application would likely be most helpful for new users.

Does it parse correct arguments with spaces?

Originally reported by: Anonymous


#!python

import sys
from cmd2 import Cmd, make_option, options

class DemoApp(Cmd):
    """Simple command processor example."""

    @options([make_option('-n', '--name', action="store", help="your name"),
         ])
    def do_hello(self, command, opts):
        if opts.name:
            sys.stdout.write('Hello %s\n' % opts.name)
        else:
            sys.stdout.write('Hello Nobody\n')

if __name__ == '__main__':
    DemoApp().cmdloop() 

if you pass:
hello 'Catherine Devlin'
it is printed:
Hello 'Catherine

the same with double quotes


GNU Readline goes haywire if prompt contains ANSI color codes

If at any point the cmd2 prompt gets changed to involve anything involving color via ANSI color escape codes, then the behavior of readline when the up and down arrows are pressed gets really messed up.

This is due to a bug in how GNU Readline calculates the prompt length when the Python3 input() or Python2 raw_input() methods are called. This article has more info:
https://bugs.python.org/issue17337

Ideally, we can make cmd2 protect against this case, even though it is fundamentally a bug in GNU Readline.

Transcript testing isn't calling preloop or postloop

When running with transcript testing, preloop() isn't getting called before the testing and postloop() isn't being called afterwards.

These should be called to handle required initialization and cleanup, respectively.

Add example of using regular expressions in a transcript test

The documentation states the following:

Regular expressions can be embedded in the transcript inside paired / slashes. These regular expressions should not include any whitespace expressions.

But the example we have for using transcript testing doesn't include any regular expressions.

Add an example for how to this to make it easier for users to take advantage of this feature.

Also, we don't appear to have any unit tests which use a transcript with a regular expression embedded within it. So we should add one.

If the feature doesn't work, we should either fix it or change the documentation.

packaging bug?

Originally reported by: Atsushi Odagiri (Bitbucket: aodag, GitHub: aodag)


I download eggs and sdist from https://pypi.python.org/pypi/cmd2 .
I think the egg for 2.7 includes sources applied 2to3.

#!

Traceback (most recent call last):
  File "bin/shirly", line 40, in <module>
    import shirly.script
  File "/home/aodag/works/shirly/src/shirly/script.py", line 2, in <module>
    from cliff.app import App
  File "/home/aodag/.buildout/eggs/cliff-1.4-py2.7.egg/cliff/app.py", line 11, in <module>
    from .interactive import InteractiveApp
  File "/home/aodag/.buildout/eggs/cliff-1.4-py2.7.egg/cliff/interactive.py", line 9, in <module>
    import cmd2
  File "/home/aodag/.buildout/eggs/cmd2-0.6.6-py2.7.egg/cmd2.py", line 36, in <module>
    import urllib.request, urllib.parse, urllib.error
ImportError: No module named request


doctests don't work with pyparsing version 2.1.10 or newer

All of the existing doctest tests work for older versions of pyparsing. But not with pyparsing 2.1.10 because how the ParseResults.dump() function treats strings changed (it now puts them in quotes).

I don't see an easy way to get the doctests to work for all versions of pyparsing.

The best option is to convert the existing doctest tests to pytest unit tests.

distutils compatibility is broken (and pointless)

Originally reported by: Michał Górny (Bitbucket: mgorny, GitHub: mgorny)


The code reads:

try:
    from setuptools import setup, find_packages
except ImportError:
    from distutils.core import setup
    def find_packages():
        return ['sqlpython']
                ^^^^^^^^^^^

which means that anyone trying to install it without setuptools is going to get wrong package name. Aside of that, setuptools-specific keys will trigger warnings in Python 2, lack of 2to3 conversion in Python 3 and fatal errors in Python 3.3.

I suggest just importing setuptools and forgetting about distutils compatibility.


Add final separator for path completion

For the commands which support local file system path completion, in the case where there is a single result and that result is a directory, it would be convenient if the completion function automatically added in the trailing path separator.

Missing Option to Disable Redirection and Piping

Originally reported by: Tyler Abair (Bitbucket: tabair, GitHub: tabair)


Cmd2's redirection with '>' and piping with '|' is a terrific feature, but I really want to disable redirection and piping sometimes. Unfortunately, there is no option I can set to make the '>' and '|' characters behave as plain characters.

I can't find a work-around to this without editing the source code. I did find that setting Cmd.redirrector to a non-printable character like '0x03' will stop redirection, but I can't find any way to touch piping. Furthermore, this is a TERRIBLE workaround to stop redirection, because a malicious user is capable of sending even non-printable characters through.


Dictionary usage problem

Originally reported by: Bhairav Shah (Bitbucket: bhairav, GitHub: bhairav)


Have an issue with getting dictionary values. Python 2.7. Sample code:

#!python

a = {}
a[1] = "blah"

class MyCmd(cmd.Cmd):
  def do_printdict(self, line):
    global a
    print "a is %s" % a
    val = a[1]
    print "val for 1 is: %s" % val
    val = a[2]
    print "val for 2 is: %s" % val

my_cmd = MyCmd()
my_cmd.cmdloop()

If I import the original cmd, I get the following output:

#!python

(Cmd) printdict
a is {1: 'blah'}
val for 1 is: blah
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/cmd.py", line 142, in cmdloop
    stop = self.onecmd(line)
  File "/usr/lib/python2.7/cmd.py", line 221, in onecmd
    return func(arg)
  File "<stdin>", line 7, in do_printdict
KeyError: 2

If I import cmd2, I get the following output:

#!python

(Cmd) printdict
a is {1: 'blah'}
val for 1 is: blah
2

The original cmd seems to be doing it right, giving the KeyError. Not sure what is happening with cmd2.

Thanks.


python3.5 fix for subprocess

AttributeError: module 'subprocess' has no attribute 'mswindows'

This has been changed to _mswindows. Otherwise everything seems to work in 3.5. Still testing though

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.