summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xREADME.md20
-rwxr-xr-xcmd2.py100
-rwxr-xr-xexamples/example.py11
-rw-r--r--tests/test_parsing.py21
-rw-r--r--tests/test_transcript.py12
5 files changed, 45 insertions, 119 deletions
diff --git a/README.md b/README.md
index 5125eaba..862622f3 100755
--- a/README.md
+++ b/README.md
@@ -103,16 +103,22 @@ Example cmd2 application (**examples/example.py**):
```python
'''A sample application for cmd2.'''
-from cmd2 import Cmd, make_option, options
+from cmd2 import Cmd, make_option, options, set_use_arg_list
class CmdLineApp(Cmd):
- multilineCommands = ['orate']
- Cmd.shortcuts.update({'&': 'speak'})
- maxrepeats = 3
- Cmd.settable.append('maxrepeats')
+ def __init__(self):
+ self.multilineCommands = ['orate']
+ self.maxrepeats = 3
- # Setting this true makes it run a shell command if a cmd2/cmd command doesn't exist
- # default_to_shell = True
+ # Add stuff to settable and shortcutgs before calling base class initializer
+ self.settable['maxrepeats'] = 'max repetitions for speak command'
+ self.shortcuts.update({'&': 'speak'})
+
+ # Set use_ipython to True to enable the "ipy" command which embeds and interactive IPython shell
+ Cmd.__init__(self, use_ipython=False)
+
+ # For option commands, pass a single argument string instead of a list of argument strings to the do_* methods
+ set_use_arg_list(False)
@options([make_option('-p', '--piglatin', action="store_true", help="atinLay"),
make_option('-s', '--shout', action="store_true", help="N00B EMULATION MODE"),
diff --git a/cmd2.py b/cmd2.py
index b2b7c22f..0c6c2c1a 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -27,7 +27,6 @@ Git repository on GitHub at https://github.com/python-cmd2/cmd2
"""
import cmd
import collections
-import copy
import datetime
import glob
import optparse
@@ -474,71 +473,6 @@ class ParsedString(str):
return new
-class StubbornDict(dict):
- """ Dictionary that tolerates many input formats.
-
- Create it with the stubbornDict(arg) factory function.
- """
- # noinspection PyMethodOverriding
- def update(self, arg):
- """Adds dictionary arg's key-values pairs in to dict
-
- :param arg: an object convertible to a StubbornDict
- """
- dict.update(self, StubbornDict.to_dict(arg))
-
- append = update
-
- def __iadd__(self, arg):
- self.update(arg)
- return self
-
- def __add__(self, arg):
- selfcopy = copy.copy(self)
- selfcopy.update(stubborn_dict(arg))
- return selfcopy
-
- def __radd__(self, arg):
- selfcopy = copy.copy(self)
- selfcopy.update(stubborn_dict(arg))
- return selfcopy
-
- @classmethod
- def to_dict(cls, arg):
- """Generates dictionary from string or list of strings"""
- if hasattr(arg, 'splitlines'):
- arg = arg.splitlines()
- if hasattr(arg, '__reversed__'):
- result = {}
- for a in arg:
- a = a.strip()
- if a:
- key_val = a.split(None, 1)
- key = key_val[0]
- if len(key_val) > 1:
- val = key_val[1]
- else:
- val = ''
- result[key] = val
- else:
- result = arg
- return result
-
-
-def stubborn_dict(*arg, **kwarg):
- """ Factory function which creates instances of the StubbornDict class.
-
- :param arg: an argument which could be used to construct a built-in dict dictionary
- :param kwarg: a variable number of key/value pairs
- :return: StubbornDict - a StubbornDict containing everything in both arg and kwarg
- """
- result = {}
- for a in arg:
- result.update(StubbornDict.to_dict(a))
- result.update(kwarg)
- return StubbornDict(result)
-
-
def replace_with_file_contents(fname):
"""Action to perform when successfully matching parse element definition for inputFrom parser.
@@ -619,21 +553,20 @@ class Cmd(cmd.Cmd):
timing = False # Prints elapsed time for each command
# To make an attribute settable with the "do_set" command, add it to this ...
- settable = stubborn_dict('''
- abbrev Accept abbreviated commands
- autorun_on_edit Automatically run files after editing
- case_insensitive Upper- and lower-case both OK
- colors Colorized output (*nix only)
- continuation_prompt On 2nd+ line of input
- debug Show full error stack on error
- echo Echo command issued into output
- editor Program used by ``edit``
- feedback_to_output Include nonessentials in `|`, `>` results
- locals_in_py Allow access to your application in py via self
- prompt The prompt issued to solicit input
- quiet Don't print nonessential feedback
- timing Report execution times
- ''')
+ # This starts out as a dictionary but gets converted to an OrderedDict sorted alphabetically by key
+ settable = {'abbrev': 'Accept abbreviated commands',
+ 'autorun_on_edit': 'Automatically run files after editing',
+ 'case_insensitive': 'Upper- and lower-case both OK',
+ 'colors': 'Colorized output (*nix only)',
+ 'continuation_prompt': 'On 2nd+ line of input',
+ 'debug': 'Show full error stack on error',
+ 'echo': 'Echo command issued into output',
+ 'editor': 'Program used by ``edit``',
+ 'feedback_to_output': 'Include nonessentials in `|`, `>` results',
+ 'locals_in_py': 'Allow access to your application in py via self',
+ 'prompt': 'The prompt issued to solicit input',
+ 'quiet': "Don't print nonessential feedback",
+ 'timing': 'Report execution times'}
def __init__(self, completekey='tab', stdin=None, stdout=None, use_ipython=False, transcript_files=None):
"""An easy but powerful framework for writing line-oriented command interpreters, extends Python's cmd package.
@@ -710,6 +643,9 @@ class Cmd(cmd.Cmd):
# noinspection PyUnresolvedReferences
self.shortcuts = sorted(self.shortcuts.items(), reverse=True)
+ # Make sure settable parameters are sorted alphabetically by key
+ self.settable = collections.OrderedDict(sorted(self.settable.items(), key=lambda t: t[0]))
+
def poutput(self, msg):
"""Convenient shortcut for self.stdout.write(); adds newline if necessary."""
if msg:
@@ -1271,7 +1207,7 @@ class Cmd(cmd.Cmd):
if result:
for p in sorted(result):
if opts.long:
- self.poutput('%s # %s' % (result[p].ljust(maxlen), self.settable[p]))
+ self.poutput('{} # {}'.format(result[p].ljust(maxlen), self.settable[p]))
else:
self.poutput(result[p])
else:
diff --git a/examples/example.py b/examples/example.py
index 68e08890..fd886a76 100755
--- a/examples/example.py
+++ b/examples/example.py
@@ -14,15 +14,18 @@ from cmd2 import Cmd, make_option, options, set_use_arg_list
class CmdLineApp(Cmd):
""" Example cmd2 application. """
- multilineCommands = ['orate']
- Cmd.shortcuts.update({'&': 'speak'})
- maxrepeats = 3
- Cmd.settable.append('maxrepeats')
# Setting this true makes it run a shell command if a cmd2/cmd command doesn't exist
# default_to_shell = True
def __init__(self):
+ self.multilineCommands = ['orate']
+ self.maxrepeats = 3
+
+ # Add stuff to settable and shortcutgs before calling base class initializer
+ self.settable['maxrepeats'] = 'max repetitions for speak command'
+ self.shortcuts.update({'&': 'speak'})
+
# Set use_ipython to True to enable the "ipy" command which embeds and interactive IPython shell
Cmd.__init__(self, use_ipython=False)
diff --git a/tests/test_parsing.py b/tests/test_parsing.py
index a3b601db..dda29911 100644
--- a/tests/test_parsing.py
+++ b/tests/test_parsing.py
@@ -43,27 +43,6 @@ def test_remaining_args():
assert cmd2.remaining_args('-f bar bar cow', ['bar', 'cow']) == 'bar cow'
-def test_stubborn_dict_class():
- d = cmd2.StubbornDict(large='gross', small='klein')
- assert sorted(d.items()) == [('large', 'gross'), ('small', 'klein')]
-
- d.append(['plain', ' plaid'])
- assert sorted(d.items()) == [('large', 'gross'), ('plaid', ''), ('plain', ''), ('small', 'klein')]
-
- d += ' girl Frauelein, Maedchen\n\n shoe schuh'
- assert sorted(d.items()) == [('girl', 'Frauelein, Maedchen'), ('large', 'gross'), ('plaid', ''), ('plain', ''),
- ('shoe', 'schuh'), ('small', 'klein')]
-
-def test_stubborn_dict_factory():
- assert sorted(cmd2.stubborn_dict('cow a bovine\nhorse an equine').items()) == [('cow', 'a bovine'),
- ('horse', 'an equine')]
- assert sorted(cmd2.stubborn_dict(['badger', 'porcupine a poky creature']).items()) == [('badger', ''),
- ('porcupine',
- 'a poky creature')]
- assert sorted(cmd2.stubborn_dict(turtle='has shell', frog='jumpy').items()) == [('frog', 'jumpy'),
- ('turtle', 'has shell')]
-
-
def test_history_span(hist):
h = hist
assert h.span('-2..') == ['third', 'fourth']
diff --git a/tests/test_transcript.py b/tests/test_transcript.py
index 4b6f4c99..a31ebd17 100644
--- a/tests/test_transcript.py
+++ b/tests/test_transcript.py
@@ -20,14 +20,16 @@ from conftest import run_cmd, StdOut, normalize
class CmdLineApp(Cmd):
- multilineCommands = ['orate']
- maxrepeats = 3
- redirector = '->'
-
def __init__(self, *args, **kwargs):
+ self.multilineCommands = ['orate']
+ self.maxrepeats = 3
+ self.redirector = '->'
+
+ # Add stuff to settable and/or shortcuts before calling base class initializer
+ self.settable['maxrepeats'] = 'Max number of `--repeat`s allowed'
+
# Need to use this older form of invoking super class constructor to support Python 2.x and Python 3.x
Cmd.__init__(self, *args, **kwargs)
- self.settable.append('maxrepeats Max number of `--repeat`s allowed')
# Configure how arguments are parsed for @options commands
set_posix_shlex(False)