diff options
author | Todd Leonhardt <todd.leonhardt@gmail.com> | 2016-12-09 16:54:10 -0500 |
---|---|---|
committer | Todd Leonhardt <todd.leonhardt@gmail.com> | 2016-12-09 16:54:10 -0500 |
commit | 06331d3ab75feb807dc48d824cbd54898a6b6cdd (patch) | |
tree | 24034e3f0ff7cd94239d575fe046acc550e7a49f | |
parent | b9658cff197beff5a00632a68ecf85838879835e (diff) | |
download | cmd2-git-06331d3ab75feb807dc48d824cbd54898a6b6cdd.tar.gz |
First stage of refactoring to support full simultaneous Python 2 and 3 compatibility via use of the six module.
-rwxr-xr-x | README.rst | 53 | ||||
-rwxr-xr-x | cmd2.py | 54 | ||||
-rw-r--r-- | docs/conf.py | 2 | ||||
-rw-r--r-- | docs/freefeatures.rst | 72 | ||||
-rw-r--r-- | docs/pycon2010/fileutil.py | 12 | ||||
-rw-r--r-- | docs/pycon2010/graph.py | 41 | ||||
-rw-r--r-- | docs/pycon2010/pirate.py | 3 | ||||
-rw-r--r-- | docs/pycon2010/pirate2.py | 1 | ||||
-rw-r--r-- | docs/pycon2010/pirate3.py | 5 | ||||
-rw-r--r-- | docs/pycon2010/pirate4.py | 11 | ||||
-rw-r--r-- | docs/pycon2010/pirate5.py | 11 | ||||
-rw-r--r-- | docs/pycon2010/pirate6.py | 11 | ||||
-rw-r--r-- | docs/pycon2010/pirate7.py | 11 | ||||
-rw-r--r-- | docs/pycon2010/pirate8.py | 13 | ||||
-rw-r--r-- | docs/pycon2010/pycon2010.rst | 64 | ||||
-rw-r--r-- | docs/pycon2010/schematic.py | 32 | ||||
-rw-r--r-- | docs/unfreefeatures.rst | 42 | ||||
-rwxr-xr-x | example/example.py | 2 | ||||
-rwxr-xr-x | setup.py | 23 | ||||
-rw-r--r-- | tests/conftest.py | 1 | ||||
-rw-r--r-- | tests/test_cmd2.py | 9 | ||||
-rw-r--r-- | tests/test_transcript.py | 1 | ||||
-rw-r--r-- | tox.ini | 1 |
23 files changed, 205 insertions, 270 deletions
@@ -40,8 +40,8 @@ Instructions for implementing each feature follow. - Searchable command history
- All commands will automatically be tracked in the session's history, unless the command is listed in Cmd's excludeFromHistory attribute.
- The history is accessed through the `history`, `list`, and `run` commands
+ All commands will automatically be tracked in the session's history, unless the command is listed in Cmd's excludeFromHistory attribute.
+ The history is accessed through the `history`, `list`, and `run` commands
(and their abbreviations: `hi`, `li`, `l`, `r`).
If you wish to exclude some of your custom commands from the history, append their names
to the list at Cmd.ExcludeFromHistory.
@@ -49,37 +49,37 @@ Instructions for implementing each feature follow. - Load commands from file, save to file, edit commands in file
Type `help load`, `help save`, `help edit` for details.
-
+
- Multi-line commands
Any command accepts multi-line input when its name is listed in `Cmd.multilineCommands`.
- The program will keep expecting input until a line ends with any of the characters
+ The program will keep expecting input until a line ends with any of the characters
in `Cmd.terminators` . The default terminators are `;` and `/n` (empty newline).
-
+
- Case-insensitive commands
All commands are case-insensitive, unless `Cmd.caseInsensitive` is set to `False`.
-
+
- Special-character shortcut commands (beyond cmd's "@" and "!")
To create a single-character shortcut for a command, update `Cmd.shortcuts`.
-
+
- Settable environment parameters
- To allow a user to change an environment parameter during program execution,
+ To allow a user to change an environment parameter during program execution,
append the parameter's name to `Cmd.settable`.
-
-- Parsing commands with `optparse` options (flags)
+
+- Parsing commands with `optparse` options (flags)
::
-
+
@options([make_option('-m', '--myoption', action="store_true", help="all about my option")])
def do_myfunc(self, arg, opts):
if opts.myoption:
...
-
+
See Python standard library's `optparse` documentation: http://docs.python.org/lib/optparse-defining-options.html
-
+
cmd2 can be installed with `easy_install cmd2`
Cheese Shop page: http://pypi.python.org/pypi/cmd2
@@ -87,16 +87,16 @@ Cheese Shop page: http://pypi.python.org/pypi/cmd2 Example cmd2 application (example/example.py) ::
'''A sample application for cmd2.'''
-
+
from cmd2 import Cmd, make_option, options, Cmd2TestCase
import unittest, optparse, sys
-
+
class CmdLineApp(Cmd):
multilineCommands = ['orate']
Cmd.shortcuts.update({'&': 'speak'})
maxrepeats = 3
Cmd.settable.append('maxrepeats')
-
+
@options([make_option('-p', '--piglatin', action="store_true", help="atinLay"),
make_option('-s', '--shout', action="store_true", help="N00B EMULATION MODE"),
make_option('-r', '--repeat', type="int", help="output [n] times")
@@ -114,14 +114,14 @@ Example cmd2 application (example/example.py) :: self.stdout.write('\n')
# self.stdout.write is better than "print", because Cmd can be
# initialized with a non-standard output destination
-
+
do_say = do_speak # now "say" is a synonym for "speak"
do_orate = do_speak # another synonym, but this one takes multi-line input
-
+
class TestMyAppCase(Cmd2TestCase):
CmdApp = CmdLineApp
transcriptFileName = 'exampleSession.txt'
-
+
parser = optparse.OptionParser()
parser.add_option('-t', '--test', dest='unittests', action='store_true', default=False, help='Run unit test suite')
(callopts, callargs) = parser.parse_args()
@@ -133,8 +133,8 @@ Example cmd2 application (example/example.py) :: app.cmdloop()
The following is a sample session running example.py.
-Thanks to `TestMyAppCase(Cmd2TestCase)`, it also serves as a test
-suite for example.py when saved as `exampleSession.txt`.
+Thanks to `TestMyAppCase(Cmd2TestCase)`, it also serves as a test
+suite for example.py when saved as `exampleSession.txt`.
Running `python example.py -t` will run all the commands in the
transcript against `example.py`, verifying that the output produced
matches the transcript.
@@ -142,12 +142,12 @@ matches the transcript. example/exampleSession.txt::
(Cmd) help
-
+
Documented commands (type help <topic>):
========================================
- _load edit history li load pause run say shell show
+ _load edit history li load pause run say shell show
ed hi l list orate r save set shortcuts speak
-
+
Undocumented commands:
======================
EOF cmdenvironment eof exit help q quit
@@ -155,14 +155,14 @@ example/exampleSession.txt:: (Cmd) help say
Repeats what you tell me to.
Usage: speak [options] arg
-
+
Options:
-h, --help show this help message and exit
-p, --piglatin atinLay
-s, --shout N00B EMULATION MODE
-r REPEAT, --repeat=REPEAT
output [n] times
-
+
(Cmd) say goodnight, Gracie
goodnight, Gracie
(Cmd) say -ps --repeat=5 goodnight, Gracie
@@ -222,3 +222,4 @@ example/exampleSession.txt:: now: --->
---> say goodbye
goodbye
+
@@ -1,3 +1,4 @@ +# coding=utf-8 """Variant on standard library's cmd with extra features. To use, simply import cmd2.Cmd instead of cmd.Cmd; use precisely as though you @@ -33,7 +34,6 @@ import tempfile import doctest import unittest import datetime -import urllib import glob import traceback import platform @@ -42,20 +42,24 @@ from code import InteractiveConsole from optparse import make_option import pyparsing -__version__ = '0.6.9a' +# Possible types for text data. This is basestring() in Python 2 and str in Python 3. +from six import string_types -try: - raw_input -except NameError: - raw_input = input +# raw_input() for Python 2 or input() for Python 3 +from six.moves import input + +# Python 2 urllib2.urlopen() or Python3 urllib.request.urlopen() +from six.moves.urllib.request import urlopen + +__version__ = '0.6.9b' # Python 3 compatability hack due to no built-in file keyword in Python 3 -# Due to two occurences of isinstance(<foo>, file) checking to see if something is of file type +# Due to one occurence of isinstance(<foo>, file) checking to see if something is of file type try: import io file = io.TextIOWrapper except ImportError: - pass # Python2 + pass # Python2 if sys.version_info[0] == 2: pyparsing.ParserElement.enablePackrat() @@ -704,8 +708,8 @@ class Cmd(cmd.Cmd): - command: what ''' #outputParser = (pyparsing.Literal('>>') | (pyparsing.WordStart() + '>') | pyparsing.Regex('[^=]>'))('output') - outputParser = (pyparsing.Literal(self.redirector *2) | \ - (pyparsing.WordStart() + self.redirector) | \ + outputParser = (pyparsing.Literal(self.redirector *2) | + (pyparsing.WordStart() + self.redirector) | pyparsing.Regex('[^=]' + self.redirector))('output') terminatorParser = pyparsing.Or([(hasattr(t, 'parseString') and t) or pyparsing.Literal(t) for t in self.terminators])('terminator') @@ -805,6 +809,7 @@ class Cmd(cmd.Cmd): # Python 2.4 support can be dropped. stop = 0 try: + statement = '' try: statement = self.complete_statement(line) (stop, statement) = self.postparsing_precmd(statement) @@ -915,7 +920,7 @@ class Cmd(cmd.Cmd): if self.use_rawinput: try: - line = raw_input(prompt) + line = input(prompt) except EOFError: line = 'EOF' else: @@ -947,18 +952,18 @@ class Cmd(cmd.Cmd): readline.parse_and_bind(self.completekey+": complete") except ImportError: pass + stop = None try: if intro is not None: self.intro = intro if self.intro: self.stdout.write(str(self.intro)+"\n") - stop = None while not stop: if self.cmdqueue: line = self.cmdqueue.pop(0) else: line = self.pseudo_raw_input(self.prompt) - if (self.echo) and (isinstance(self.stdin, file)): + if self.echo and isinstance(self.stdin, file): self.stdout.write(line + '\n') stop = self.onecmd_plus_hooks(line) self.postloop() @@ -991,11 +996,11 @@ class Cmd(cmd.Cmd): | a list of tuples -> interpreted as (value, text), so that the return value can differ from the text advertised to the user ''' - if isinstance(options, basestring): + if isinstance(options, string_types): options = zip(options.split(), options.split()) fulloptions = [] for opt in options: - if isinstance(opt, basestring): + if isinstance(opt, string_types): fulloptions.append((opt, opt)) else: try: @@ -1005,7 +1010,7 @@ class Cmd(cmd.Cmd): for (idx, (value, text)) in enumerate(fulloptions): self.poutput(' %2d. %s\n' % (idx+1, text)) while True: - response = raw_input(prompt) + response = input(prompt) try: response = int(response) result = fulloptions[response - 1][0] @@ -1067,7 +1072,7 @@ class Cmd(cmd.Cmd): def do_pause(self, arg): 'Displays the specified text then waits for the user to press RETURN.' - raw_input(arg + '\n') + input(arg + '\n') def do_shell(self, arg): 'execute a command as if at the OS prompt.' @@ -1104,6 +1109,7 @@ class Cmd(cmd.Cmd): self.pystate['exit'] = quit self.pystate['cmd'] = onecmd_plus_hooks self.pystate['run'] = run + keepstate = None try: cprt = 'Type "help", "copyright", "credits" or "license" for more information.' keepstate = Statekeeper(sys, ('stdin','stdout')) @@ -1113,7 +1119,8 @@ class Cmd(cmd.Cmd): (sys.version, sys.platform, cprt, self.__class__.__name__, self.do_py.__doc__)) except EmbeddedConsoleExit: pass - keepstate.restore() + if keepstate is not None: + keepstate.restore() @options([make_option('-s', '--script', action="store_true", help="Script format; no separation lines"), ], arg_desc = '(limit on which commands to include)') @@ -1225,12 +1232,12 @@ class Cmd(cmd.Cmd): def read_file_or_url(self, fname): # TODO: not working on localhost - if isinstance(fname, file): + if os.path.isfile(fname): result = open(fname, 'r') else: match = self.urlre.match(fname) if match: - result = urllib.urlopen(match.group(1)) + result = urlopen(match.group(1)) else: fname = os.path.expanduser(fname) try: @@ -1317,7 +1324,7 @@ class Cmd(cmd.Cmd): if self.onecmd_plus_hooks(initial_command + '\n'): return self._STOP_AND_EXIT - def cmdloop(self): + def cmdloop(self, intro=None): parser = optparse.OptionParser() parser.add_option('-t', '--test', dest='test', action="store_true", @@ -1565,8 +1572,9 @@ class Cmd2TestCase(unittest.TestCase): line = transcript.next() except StopIteration: raise (StopIteration, - 'Transcript broke off while reading command beginning at line %d with\n%s' - % (command[0])) + 'Transcript broke off while reading command beginning at line {} with\n{}'.format(lineNum, + command[0]) + ) lineNum += 1 command = ''.join(command) # Send the command into the application and capture the resulting output diff --git a/docs/conf.py b/docs/conf.py index ee6b5e6a..29fe144a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,7 +11,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +# import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/docs/freefeatures.rst b/docs/freefeatures.rst index 87952611..43b39b29 100644 --- a/docs/freefeatures.rst +++ b/docs/freefeatures.rst @@ -51,8 +51,8 @@ Commands at invocation You can send commands to your app as you invoke it by including them as extra arguments to the program. -``cmd2`` interprets each argument as a separate -command, so you should enclose each command in +``cmd2`` interprets each argument as a separate +command, so you should enclose each command in quotation marks if it is more than a one-word command. :: @@ -60,9 +60,9 @@ quotation marks if it is more than a one-word command. cat@eee:~/proj/cmd2/example$ python example.py "say hello" "say Gracie" quit hello Gracie - cat@eee:~/proj/cmd2/example$ + cat@eee:~/proj/cmd2/example$ + - Output redirection ================== @@ -75,7 +75,7 @@ As in a Unix shell, output of a command can be redirected: ending with a bare ``>``, as in ``mycommand args >``.. Redirecting to paste buffer requires software to be installed on the operating system, pywin32_ on Windows or xclip_ on \*nix. - + If your application depends on mathematical syntax, ``>`` may be a bad choice for redirecting output - it will prevent you from using the greater-than sign in your actual user commands. You can override your @@ -83,7 +83,7 @@ app's value of ``self.redirector`` to use a different string for output redirect class MyApp(cmd2.Cmd): redirector = '->' - + :: (Cmd) say line1 -> out.txt @@ -94,7 +94,7 @@ app's value of ``self.redirector`` to use a different string for output redirect .. _pywin32: http://sourceforge.net/projects/pywin32/ .. _xclip: http://www.cyberciti.biz/faq/xclip-linux-insert-files-command-output-intoclipboard/ - + Python ====== @@ -109,34 +109,34 @@ See see :ref:`parameters`) :: - (Cmd) py print("-".join("spelling")) - s-p-e-l-l-i-n-g - (Cmd) py - Python 2.6.4 (r264:75706, Dec 7 2009, 18:45:15) - [GCC 4.4.1] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - (CmdLineApp) - - py <command>: Executes a Python command. - py: Enters interactive Python mode. - End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, 'exit()`. - Non-python commands can be issued with `cmd("your command")`. - - >>> import os - >>> os.uname() - ('Linux', 'eee', '2.6.31-19-generic', '#56-Ubuntu SMP Thu Jan 28 01:26:53 UTC 2010', 'i686') - >>> cmd("say --piglatin {os}".format(os=os.uname()[0])) - inuxLay - >>> self.prompt - '(Cmd) ' - >>> self.prompt = 'Python was here > ' - >>> quit() - Python was here > + (Cmd) py print("-".join("spelling")) + s-p-e-l-l-i-n-g + (Cmd) py + Python 2.6.4 (r264:75706, Dec 7 2009, 18:45:15) + [GCC 4.4.1] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + (CmdLineApp) + + py <command>: Executes a Python command. + py: Enters interactive Python mode. + End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, 'exit()`. + Non-python commands can be issued with `cmd("your command")`. + + >>> import os + >>> os.uname() + ('Linux', 'eee', '2.6.31-19-generic', '#56-Ubuntu SMP Thu Jan 28 01:26:53 UTC 2010', 'i686') + >>> cmd("say --piglatin {os}".format(os=os.uname()[0])) + inuxLay + >>> self.prompt + '(Cmd) ' + >>> self.prompt = 'Python was here > ' + >>> quit() + Python was here > Searchable command history ========================== -All cmd_-based applications have access to previous commands with +All cmd_-based applications have access to previous commands with the up- and down- cursor keys. All cmd_-based applications on systems with the ``readline`` module @@ -155,7 +155,7 @@ also provide `bash-like history list editing`_. Quitting the application ======================== -``cmd2`` pre-defines a ``quit`` command for you (with +``cmd2`` pre-defines a ``quit`` command for you (with synonyms ``exit`` and simply ``q``). It's trivial, but it's one less thing for you to remember. @@ -164,14 +164,14 @@ Abbreviated commands ==================== ``cmd2`` apps will accept shortened command names -so long as there is no ambiguity. Thus, if +so long as there is no ambiguity. Thus, if ``do_divide`` is defined, then ``divid``, ``div``, or even ``d`` will suffice, so long as there are no other commands defined beginning with *divid*, *div*, or *d*. This behavior can be turned off with ``app.abbrev`` (see :ref:`parameters`) - + Misc. pre-defined commands ========================== @@ -196,12 +196,12 @@ a ``cmd2``-based app is copied from the screen and pasted into a text file, ``transcript.txt``, then a transcript test can be run against it:: python app.py --test transcript.txt - + Any non-whitespace deviations between the output prescribed in ``transcript.txt`` and the actual output from a fresh run of the application will be reported as a unit test failure. (Whitespace is ignored during the comparison.) -Regular expressions can be embedded in the transcript inside paired ``/`` +Regular expressions can be embedded in the transcript inside paired ``/`` slashes. These regular expressions should not include any whitespace expressions. diff --git a/docs/pycon2010/fileutil.py b/docs/pycon2010/fileutil.py deleted file mode 100644 index 5e754b5a..00000000 --- a/docs/pycon2010/fileutil.py +++ /dev/null @@ -1,12 +0,0 @@ -import glob -import os.path - -for fullfilename in glob.glob('/home/cat/proj/cmd2/*.py'): - (dirpath, fname) = os.path.split(fullfilename) - stats = os.stat(fullfilename) - binds['path'] = dirpath - binds['name'] = fname - binds['bytes'] = stats.st_size - cmd("""INSERT INTO cat.files (path, name, bytes) - VALUES (%(path)s, %(name)s, %(bytes)s)""") -quit() diff --git a/docs/pycon2010/graph.py b/docs/pycon2010/graph.py deleted file mode 100644 index 96ffde72..00000000 --- a/docs/pycon2010/graph.py +++ /dev/null @@ -1,41 +0,0 @@ -from turtle import * -pu() -goto(-400,-400) - -def label(txt): - write(txt, font=('Arial', 20, 'italic')) -hideturtle() -width(6) - -def line(len, _label): - start = pos() - pd() - forward(len) - pu() - forward(30) - pd() - label(_label) - pu() - goto(start) - -def tech(x, y, _label): - pu() - goto(x, y) - pd() - write(_label, font=('Arial', 40, 'bold')) - pu() - -line(600, "Easy to write") -left(90) -line(600, "Easy to use") - -tech(-360, 160, 'GUI') -tech(-390, 100, 'AJAX') -tech(-300, -10, 'webapp') -tech(190, -380, 'CLU') -tech(60, -320, 'TUI') -tech(100, -210, 'cmd') -tech(80, -80, 'cmd2') - -while True: - pass
\ No newline at end of file diff --git a/docs/pycon2010/pirate.py b/docs/pycon2010/pirate.py index 98db50ea..48afe629 100644 --- a/docs/pycon2010/pirate.py +++ b/docs/pycon2010/pirate.py @@ -1,7 +1,8 @@ +# coding=utf-8 from cmd import Cmd class Pirate(Cmd): pass pirate = Pirate() -pirate.cmdloop()
\ No newline at end of file +pirate.cmdloop() diff --git a/docs/pycon2010/pirate2.py b/docs/pycon2010/pirate2.py index e2c49609..c1852f03 100644 --- a/docs/pycon2010/pirate2.py +++ b/docs/pycon2010/pirate2.py @@ -1,3 +1,4 @@ +# coding=utf-8 from cmd import Cmd # using ``do_`` methods diff --git a/docs/pycon2010/pirate3.py b/docs/pycon2010/pirate3.py index 7977a8dc..61eb2d4e 100644 --- a/docs/pycon2010/pirate3.py +++ b/docs/pycon2010/pirate3.py @@ -1,3 +1,4 @@ +# coding=utf-8 from cmd import Cmd # using hook @@ -7,12 +8,12 @@ class Pirate(Cmd): 'Seize booty from a passing ship.' self.gold += 1 def do_drink(self, arg): - 'Drown your sorrrows in rrrum.' + 'Drown your sorrrows in rrrum.' self.gold -= 1 def precmd(self, line): self.initial_gold = self.gold return line - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons' .format(self.gold)) diff --git a/docs/pycon2010/pirate4.py b/docs/pycon2010/pirate4.py index 5de9c212..29de7301 100644 --- a/docs/pycon2010/pirate4.py +++ b/docs/pycon2010/pirate4.py @@ -1,3 +1,4 @@ +# coding=utf-8 from cmd import Cmd # using arguments @@ -8,20 +9,20 @@ class Pirate(Cmd): self.gold += 1 def do_drink(self, arg): '''Drown your sorrrows in rrrum. - - drink [n] - drink [n] barrel[s] o' rum.''' + + drink [n] - drink [n] barrel[s] o' rum.''' try: self.gold -= int(arg) except: if arg: print('''What's "{0}"? I'll take rrrum.'''.format(arg)) - self.gold -= 1 + self.gold -= 1 def precmd(self, line): self.initial_gold = self.gold return line - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons'.format(self.gold)) pirate = Pirate() -pirate.cmdloop()
\ No newline at end of file +pirate.cmdloop() diff --git a/docs/pycon2010/pirate5.py b/docs/pycon2010/pirate5.py index 7add4635..f6125f57 100644 --- a/docs/pycon2010/pirate5.py +++ b/docs/pycon2010/pirate5.py @@ -1,3 +1,4 @@ +# coding=utf-8 from cmd import Cmd # quitting @@ -8,18 +9,18 @@ class Pirate(Cmd): self.gold += 1 def do_drink(self, arg): '''Drown your sorrrows in rrrum. - - drink [n] - drink [n] barrel[s] o' rum.''' + + drink [n] - drink [n] barrel[s] o' rum.''' try: self.gold -= int(arg) except: if arg: print('''What's "{0}"? I'll take rrrum.'''.format(arg)) - self.gold -= 1 + self.gold -= 1 def precmd(self, line): self.initial_gold = self.gold return line - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons' .format(self.gold)) @@ -29,7 +30,7 @@ class Pirate(Cmd): return stop def do_quit(self, arg): print("Quiterrr!") - return True + return True pirate = Pirate() pirate.cmdloop() diff --git a/docs/pycon2010/pirate6.py b/docs/pycon2010/pirate6.py index 4a03fed4..dbb18ce9 100644 --- a/docs/pycon2010/pirate6.py +++ b/docs/pycon2010/pirate6.py @@ -1,3 +1,4 @@ +# coding=utf-8 from cmd2 import Cmd # prompts and defaults @@ -12,18 +13,18 @@ class Pirate(Cmd): self.gold += 1 def do_drink(self, arg): '''Drown your sorrrows in rrrum. - - drink [n] - drink [n] barrel[s] o' rum.''' + + drink [n] - drink [n] barrel[s] o' rum.''' try: self.gold -= int(arg) except: if arg: print('''What's "{0}"? I'll take rrrum.'''.format(arg)) - self.gold -= 1 + self.gold -= 1 def precmd(self, line): self.initial_gold = self.gold return line - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons' .format(self.gold)) @@ -33,7 +34,7 @@ class Pirate(Cmd): return stop def do_quit(self, arg): print("Quiterrr!") - return True + return True pirate = Pirate() pirate.cmdloop() diff --git a/docs/pycon2010/pirate7.py b/docs/pycon2010/pirate7.py index 25ff5822..32f4954d 100644 --- a/docs/pycon2010/pirate7.py +++ b/docs/pycon2010/pirate7.py @@ -1,3 +1,4 @@ +# coding=utf-8 from cmd2 import Cmd # prompts and defaults @@ -11,18 +12,18 @@ class Pirate(Cmd): self.gold += 1 def do_drink(self, arg): '''Drown your sorrrows in rrrum. - - drink [n] - drink [n] barrel[s] o' rum.''' + + drink [n] - drink [n] barrel[s] o' rum.''' try: self.gold -= int(arg) except: if arg: print('''What's "{0}"? I'll take rrrum.'''.format(arg)) - self.gold -= 1 + self.gold -= 1 def precmd(self, line): self.initial_gold = self.gold return line - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons' .format(self.gold)) @@ -32,7 +33,7 @@ class Pirate(Cmd): return stop def do_quit(self, arg): print("Quiterrr!") - return True + return True default_to_shell = True multilineCommands = ['sing'] terminators = Cmd.terminators + ['...'] diff --git a/docs/pycon2010/pirate8.py b/docs/pycon2010/pirate8.py index 3e80b241..c80d41f4 100644 --- a/docs/pycon2010/pirate8.py +++ b/docs/pycon2010/pirate8.py @@ -1,3 +1,4 @@ +# coding=utf-8 from cmd2 import Cmd, options, make_option # prompts and defaults @@ -11,18 +12,18 @@ class Pirate(Cmd): self.gold += 1 def do_drink(self, arg): '''Drown your sorrrows in rrrum. - - drink [n] - drink [n] barrel[s] o' rum.''' + + drink [n] - drink [n] barrel[s] o' rum.''' try: self.gold -= int(arg) except: if arg: print('''What's "{0}"? I'll take rrrum.'''.format(arg)) - self.gold -= 1 + self.gold -= 1 def precmd(self, line): self.initial_gold = self.gold return line - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons' .format(self.gold)) @@ -32,7 +33,7 @@ class Pirate(Cmd): return stop def do_quit(self, arg): print("Quiterrr!") - return True + return True default_to_shell = True multilineCommands = ['sing'] terminators = Cmd.terminators + ['...'] @@ -44,7 +45,7 @@ class Pirate(Cmd): @options([make_option('--ho', type='int', default=2, help="How often to chant 'ho'"), make_option('-c', '--commas', - action="store_true", + action="store_true", help="Intersperse commas")]) def do_yo(self, arg, opts): chant = ['yo'] + ['ho'] * opts.ho diff --git a/docs/pycon2010/pycon2010.rst b/docs/pycon2010/pycon2010.rst index 0b3b7a46..6c3af676 100644 --- a/docs/pycon2010/pycon2010.rst +++ b/docs/pycon2010/pycon2010.rst @@ -11,7 +11,7 @@ Web 2.0 .. image:: web-2-0-logos.gif :height: 350px - + But first... ============ @@ -20,10 +20,10 @@ But first... .. image:: akkad.png :height: 250px - + Sargon the Great Founder of Akkadian Empire - + .. twenty-third century BC In between @@ -31,16 +31,16 @@ In between .. image:: apple.jpg :height: 250px - + Command-Line Interface - Unlike the Akkadian Empire, + Unlike the Akkadian Empire, the CLI will never die. Defining CLI ============ Also known as - + - "Line-oriented command interpreter" - "Command-line interface" - "Shell" @@ -85,24 +85,24 @@ Examples .. image:: urwid.png :height: 250px - + Decide your priorities ====================== .. image:: strategy.png :height: 350px - + A ``cmd`` app: pirate.py ======================== :: from cmd import Cmd - + class Pirate(Cmd): pass - + pirate = Pirate() pirate.cmdloop() @@ -114,9 +114,9 @@ Fundamental prrrinciple ======================= .. class:: huge - - ``(Cmd) foo a b c`` - + + ``(Cmd) foo a b c`` + becomes ``self.do_foo('a b c')`` @@ -139,7 +139,7 @@ Fundamental prrrinciple print('Now we gots {0} doubloons' .format(self.gold)) -.. do_methods; more help +.. do_methods; more help Hooks ===== @@ -163,16 +163,16 @@ Hooks: pirate3.py 'Seize booty from a passing ship.' self.gold += 1 def do_drink(self, arg): - 'Drown your sorrrows in rrrum.' + 'Drown your sorrrows in rrrum.' self.gold -= 1 def precmd(self, line): self.initial_gold = self.gold return line - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons' .format(self.gold)) - + Arguments: pirate4.py ===================== @@ -180,22 +180,22 @@ Arguments: pirate4.py def do_drink(self, arg): '''Drown your sorrrows in rrrum. - - drink [n] - drink [n] barrel[s] o' rum.''' + + drink [n] - drink [n] barrel[s] o' rum.''' try: self.gold -= int(arg) except: if arg: print('''What's "{0}"? I'll take rrrum.''' .format(arg)) - self.gold -= 1 - + self.gold -= 1 + quitting: pirate5.py ==================== :: - def postcmd(self, stop, line): + def postcmd(self, stop, line): if self.gold != self.initial_gold: print('Now we gots {0} doubloons' .format(self.gold)) @@ -205,7 +205,7 @@ quitting: pirate5.py return stop def do_quit(self, arg): print("Quiterrr!") - return True + return True prompts, defaults: pirate6.py ============================= @@ -227,7 +227,7 @@ Other CLI packages * CMdO * pycopia * cmdlin - * cmd2 + * cmd2 Demo ==== @@ -258,7 +258,7 @@ Script files Commands at invocation -Output redirection +Output redirection Python @@ -273,9 +273,9 @@ But wait, there's more * Timing * Echo * Debug - + Minor changes: pirate7.py -========================= +========================= :: @@ -287,18 +287,18 @@ Minor changes: pirate7.py Cmd.shortcuts.update({'~': 'sing'}) def do_sing(self, arg): print(self.colorize(arg, self.songcolor)) - + Now how much would you pay? =========================== options / flags -Quiet (suppress feedback) +Quiet (suppress feedback) BASH-style ``select`` Parsing: terminators, suffixes - + Options: pirate8.py =================== @@ -307,13 +307,13 @@ Options: pirate8.py @options([make_option('--ho', type='int', default=2, help="How often to chant 'ho'"), make_option('-c', '--commas', - action="store_true", + action="store_true", help="Intersperse commas")]) def do_yo(self, arg, opts): chant = ['yo'] + ['ho'] * opts.ho separator = ', ' if opts.commas else ' ' chant = separator.join(chant) - print('{0} and a bottle of {1}' + print('{0} and a bottle of {1}' .format(chant, arg)) Serious example: sqlpython diff --git a/docs/pycon2010/schematic.py b/docs/pycon2010/schematic.py deleted file mode 100644 index 80774859..00000000 --- a/docs/pycon2010/schematic.py +++ /dev/null @@ -1,32 +0,0 @@ -from turtle import * -hideturtle() -width(6) -pensize = 10 -pu() -goto(0,-400) - -def rectangle(x, y, _label): - pu() - seth(0) - backward(x / 2) - fontsize = 40 - pd() - for i in range(2): - forward(x) - left(90) - forward(y) - left(90) - pu() - forward(x / 2) - left(90) - forward(y / 2 - fontsize) - pd() - write(_label, align='center', font=('Arial', fontsize, 'bold')) - -rectangle(800, 80, 'cmd') -pu() -forward(80) -rectangle(200, 400, 'cmd2') - -while True: - pass diff --git a/docs/unfreefeatures.rst b/docs/unfreefeatures.rst index 1cd0081c..c9149409 100644 --- a/docs/unfreefeatures.rst +++ b/docs/unfreefeatures.rst @@ -6,13 +6,13 @@ Multiline commands ================== Command input may span multiple lines for the -commands whose names are listed in the +commands whose names are listed in the parameter ``app.multilineCommands``. These commands will be executed only after the user has entered a *terminator*. By default, the command terminators is ``;``; replacing or appending to the list -``app.terminators`` allows different +``app.terminators`` allows different terminators. A blank line is *always* considered a command terminator (cannot be overridden). @@ -21,17 +21,17 @@ Parsed statements ================= ``cmd2`` passes ``arg`` to a ``do_`` method (or -``default`) as a ParsedString, a subclass of +``default`) as a ParsedString, a subclass of string that includes an attribute ``parsed``. ``parsed`` is a ``pyparsing.ParseResults`` -object produced by applying a pyparsing_ +object produced by applying a pyparsing_ grammar applied to ``arg``. It may include: command Name of the command called raw - Full input exactly as typed. + Full input exactly as typed. terminator Character used to end a multiline command @@ -68,9 +68,9 @@ process are painfully complex and should not be considered stable; future ``cmd2`` releases may change it somewhat (hopefully reducing complexity). -(Getting ``arg`` as a ``ParsedString`` is +(Getting ``arg`` as a ``ParsedString`` is technically "free", in that it requires no application -changes from the cmd_ standard, but there will +changes from the cmd_ standard, but there will be no result unless you change your application to *use* ``arg.parsed``.) @@ -83,7 +83,7 @@ to *use* ``arg.parsed``.) Environment parameters ====================== -Your application can define user-settable parameters +Your application can define user-settable parameters which your code can reference. Create them as class attributes with their default values, and add them (with optional documentation) to ``settable``. @@ -111,7 +111,7 @@ documentation) to ``settable``. (Cmd) set --long degrees_c: 22 # temperature in Celsius - sunny: False # + sunny: False # (Cmd) sunbathe Too dim. (Cmd) set sunny yes @@ -135,7 +135,7 @@ a ``do_`` methods accept Unix-style *flags*. It uses optparse_ to parse the flags, and they work the same way as for that module. -Flags are defined with the ``options`` decorator, +Flags are defined with the ``options`` decorator, which is passed a list of optparse_-style options, each created with ``make_option``. The method should accept a second argument, ``opts``, in @@ -180,19 +180,19 @@ the option's online help. arg_desc='(from city) (to city)') def do_travel(self, arg, opts=None): 'Gets you from (from city) to (to city).' - + :: (Cmd) help travel Gets you from (from city) to (to city). Usage: travel [options] (from-city) (to-city) - + Options: -h, --help show this help message and exit -t, --train by train - -.. _optparse: + +.. _optparse: .. _outputters: @@ -200,17 +200,17 @@ poutput, pfeedback, perror ========================== Standard ``cmd`` applications produce their output with ``self.stdout.write('output')`` (or with ``print``, -but ``print`` decreases output flexibility). ``cmd2`` applications can use +but ``print`` decreases output flexibility). ``cmd2`` applications can use ``self.poutput('output')``, ``self.pfeedback('message')``, and ``self.perror('errmsg')`` instead. These methods have these advantages: - More concise - ``.pfeedback()`` destination is controlled by :ref:`quiet` parameter. - + color ===== -Text output can be colored by wrapping it in the ``colorize`` method. +Text output can be colored by wrapping it in the ``colorize`` method. .. automethod:: cmd2.Cmd.colorize @@ -221,7 +221,7 @@ quiet Controls whether ``self.pfeedback('message')`` output is suppressed; useful for non-essential feedback that the user may not always want -to read. ``quiet`` is only relevant if +to read. ``quiet`` is only relevant if ``app.pfeedback`` is sometimes used. ``select`` @@ -234,13 +234,13 @@ Presents numbered options to user, as bash ``select``. .. automethod:: cmd2.Cmd.select :: - + def do_eat(self, arg): sauce = self.select('sweet salty', 'Sauce? ') result = '{food} with {sauce} sauce, yum!' result = result.format(food=arg, sauce=sauce) self.stdout.write(result + '\n') - + :: (Cmd) eat wheaties @@ -248,4 +248,4 @@ Presents numbered options to user, as bash ``select``. 2. salty Sauce? 2 wheaties with salty sauce, yum! -
\ No newline at end of file + diff --git a/example/example.py b/example/example.py index 9d17bbb7..081bdb6f 100755 --- a/example/example.py +++ b/example/example.py @@ -1,4 +1,4 @@ - +# coding=utf-8 """A sample application for cmd2. """ @@ -1,9 +1,11 @@ #!/usr/bin/python -from setuptools import setup, find_packages -import sys +# coding=utf-8 +from setuptools import setup install_requires = ['pyparsing >= 2.0.1'] +tests_require = ['mock', 'pytest', 'six'] + setup( name="cmd2", version="0.6.9", @@ -11,14 +13,15 @@ setup( use_2to3=True, # metadata for upload to PyPI - author = 'Catherine Devlin', - author_email = 'catherine.devlin@gmail.com', - description = "Extra features for standard library's cmd module", - license = 'MIT', - keywords = 'command prompt console cmd', - url = 'http://packages.python.org/cmd2/', - install_requires = install_requires, - long_description = """Enhancements for standard library's cmd module. + author='Catherine Devlin', + author_email='catherine.devlin@gmail.com', + description="Extra features for standard library's cmd module", + license='MIT', + keywords='command prompt console cmd', + url='http://packages.python.org/cmd2/', + install_requires=install_requires, + tests_require=tests_require, + long_description="""Enhancements for standard library's cmd module. Drop-in replacement adds several features for command-prompt tools: diff --git a/tests/conftest.py b/tests/conftest.py index 55700914..e1204086 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +# coding=utf-8 # # Cmd2 unit/functional testing # diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index 8435ac1a..0deb9a0b 100644 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -1,3 +1,4 @@ +# coding=utf-8 # # Cmd2 unit/functional testing # @@ -6,14 +7,10 @@ import mock import pytest - from conftest import run_cmd, _normalize -import cmd2 +from six import StringIO -try: - from StringIO import StringIO -except ImportError: - from io import StringIO +import cmd2 def test_ver(): diff --git a/tests/test_transcript.py b/tests/test_transcript.py index 06cf50b6..ebd13a59 100644 --- a/tests/test_transcript.py +++ b/tests/test_transcript.py @@ -1,3 +1,4 @@ +# coding=utf-8 # # Cmd2 functional testing based on transcript # @@ -6,6 +6,7 @@ deps = mock pyparsing pytest + six commands= py.test -v --basetemp={envtmpdir} {posargs} {envpython} cmd2.py |