summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2016-12-09 16:54:10 -0500
committerTodd Leonhardt <todd.leonhardt@gmail.com>2016-12-09 16:54:10 -0500
commit06331d3ab75feb807dc48d824cbd54898a6b6cdd (patch)
tree24034e3f0ff7cd94239d575fe046acc550e7a49f
parentb9658cff197beff5a00632a68ecf85838879835e (diff)
downloadcmd2-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-xREADME.rst53
-rwxr-xr-xcmd2.py54
-rw-r--r--docs/conf.py2
-rw-r--r--docs/freefeatures.rst72
-rw-r--r--docs/pycon2010/fileutil.py12
-rw-r--r--docs/pycon2010/graph.py41
-rw-r--r--docs/pycon2010/pirate.py3
-rw-r--r--docs/pycon2010/pirate2.py1
-rw-r--r--docs/pycon2010/pirate3.py5
-rw-r--r--docs/pycon2010/pirate4.py11
-rw-r--r--docs/pycon2010/pirate5.py11
-rw-r--r--docs/pycon2010/pirate6.py11
-rw-r--r--docs/pycon2010/pirate7.py11
-rw-r--r--docs/pycon2010/pirate8.py13
-rw-r--r--docs/pycon2010/pycon2010.rst64
-rw-r--r--docs/pycon2010/schematic.py32
-rw-r--r--docs/unfreefeatures.rst42
-rwxr-xr-xexample/example.py2
-rwxr-xr-xsetup.py23
-rw-r--r--tests/conftest.py1
-rw-r--r--tests/test_cmd2.py9
-rw-r--r--tests/test_transcript.py1
-rw-r--r--tox.ini1
23 files changed, 205 insertions, 270 deletions
diff --git a/README.rst b/README.rst
index 6a248de2..1f65b4fc 100755
--- a/README.rst
+++ b/README.rst
@@ -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
+
diff --git a/cmd2.py b/cmd2.py
index 8b94c3e2..687571b0 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -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.
"""
diff --git a/setup.py b/setup.py
index 54e156e9..61c84f17 100755
--- a/setup.py
+++ b/setup.py
@@ -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
#
diff --git a/tox.ini b/tox.ini
index 91ce4283..34ec348c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,6 +6,7 @@ deps =
mock
pyparsing
pytest
+ six
commands=
py.test -v --basetemp={envtmpdir} {posargs}
{envpython} cmd2.py