Created
September 1, 2013 22:52
-
-
Save scottt/6407845 to your computer and use it in GitHub Desktop.
diff between the forked _cmdln.py in applib and cmdln git master
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- /home/scottt/work/python-applib/applib/applib/_cmdln.py 2013-09-02 06:31:58.187831448 +0800 | |
+++ lib/cmdln.py 2013-09-02 06:46:06.076666182 +0800 | |
@@ -1,4 +1,5 @@ | |
#!/usr/bin/env python | |
+# Copyright (c) 2012 Trent Mick | |
# Copyright (c) 2002-2009 ActiveState Software Inc. | |
# License: MIT (see LICENSE.txt for license details) | |
# Author: Trent Mick | |
@@ -30,33 +31,23 @@ | |
retval = shell.main() | |
sys.exit(retval) | |
-See the README.txt or <http://code.google.com/p/cmdln/> for more | |
+See the README.txt or <http://trentm.com/projects/cmdln/> for more | |
details. | |
""" | |
-__version_info__ = (1, 2, 0) | |
+__version_info__ = (1, 3, 0) | |
__version__ = '.'.join(map(str, __version_info__)) | |
import os | |
-from os import path | |
import sys | |
import re | |
-import types | |
import cmd | |
import optparse | |
from pprint import pprint | |
-try: | |
- import ConfigParser | |
-except ImportError: | |
- import configparser as ConfigParser # python3 | |
+import sys | |
import datetime | |
-if sys.hexversion > 0x03000000: | |
- ClassType = type | |
-else: | |
- ClassType = types.ClassType | |
- | |
#---- globals | |
@@ -69,7 +60,7 @@ | |
# failed because of incorrect number of arguments (see | |
# Python/getargs.c). | |
_INCORRECT_NUM_ARGS_RE = re.compile( | |
- r"(takes [\w ]+ )(\d+)[\w ]*( arguments? \()(\d+)( given\))") | |
+ r"(takes [\w ]+ )(\d+)( arguments? \()(\d+)( given\))") | |
@@ -92,7 +83,7 @@ | |
def alias(*aliases): | |
"""Decorator to add aliases for Cmdln.do_* command handlers. | |
- | |
+ | |
Example: | |
class MyShell(cmdln.Cmdln): | |
@cmdln.alias("!", "sh") | |
@@ -139,7 +130,7 @@ | |
helpindent = '' # string with which to indent help output | |
- def __init__(self, completekey='tab', | |
+ def __init__(self, completekey='tab', | |
stdin=None, stdout=None, stderr=None): | |
"""Cmdln(completekey='tab', stdin=None, stdout=None, stderr=None) | |
@@ -147,15 +138,16 @@ | |
completion key; it defaults to the Tab key. If completekey is | |
not None and the readline module is available, command completion | |
is done automatically. | |
- | |
+ | |
The optional arguments 'stdin', 'stdout' and 'stderr' specify | |
alternate input, output and error output file objects; if not | |
specified, sys.* are used. | |
- | |
+ | |
If 'stdout' but not 'stderr' is specified, stdout is used for | |
error output. This is to provide least surprise for users used | |
to only the 'stdin' and 'stdout' options with cmd.Cmd. | |
""" | |
+ import sys | |
if self.name is None: | |
self.name = os.path.basename(sys.argv[0]) | |
if self.prompt is None: | |
@@ -180,60 +172,32 @@ | |
self.completekey = completekey | |
self.cmdlooping = False | |
- def get_option_defaults(self, cmdname): | |
- """Return default values for command options | |
- | |
- For all options registered for the given command (`cmdname`), return | |
- the default values as a dictionary (option name as keys, default value | |
- as values) | |
- | |
- If `cmdname` is None, return default for top-level options | |
- """ | |
- return {} | |
- | |
def get_optparser(self): | |
"""Hook for subclasses to set the option parser for the | |
top-level command/shell. | |
- NOTE: you may not override this method anymore; cmdln.option decorator | |
- can now be used on the class itself to create toplevel options. | |
- | |
- This option parser is retrieved and used by `.main()' to handle | |
- top-level options. | |
+ This option parser is used retrieved and used by `.main()' to | |
+ handle top-level options. | |
The default implements a single '-h|--help' option. Sub-classes | |
can return None to have no options at the top-level. Typically | |
an instance of CmdlnOptionParser should be returned. | |
""" | |
- return self._create_toplevel_optparser() | |
- | |
- def _create_toplevel_optparser(self): | |
- version = (self.version is not None | |
+ version = (self.version is not None | |
and "%s %s" % (self._name_str, self.version) | |
or None) | |
- parser = CmdlnOptionParser(self, version=version) | |
- | |
- # if ``useconfig`` is used, add the -c option to specify extra config | |
- # file | |
- # if hasattr(self, 'defaultsconfig'): | |
- # parser.add_option('-c', '--configfile', | |
- # dest='configfile', | |
- # help="specify the config file location", | |
- # default=None) | |
- | |
- # add toplevel options | |
- if hasattr(self, 'toplevel_optparser_options'): | |
- for args, kwargs in self.toplevel_optparser_options: | |
- parser.add_option(*args, **kwargs) | |
- | |
- return parser | |
+ return CmdlnOptionParser(self, version=version) | |
def postoptparse(self): | |
"""Hook method executed just after `.main()' parses top-level | |
options. | |
When called `self.options' holds the results of the option parse. | |
+ | |
+ If this returns non-zero/non-None, then command processing is stopped | |
+ and this retval is returned from `main()`. | |
""" | |
+ pass | |
def main(self, argv=None, loop=LOOP_NEVER): | |
"""A possible mainline handler for a script, like so: | |
@@ -242,14 +206,14 @@ | |
class MyCmd(cmdln.Cmdln): | |
name = "mycmd" | |
... | |
- | |
+ | |
if __name__ == "__main__": | |
MyCmd().main() | |
By default this will use sys.argv to issue a single command to | |
'MyCmd', then exit. The 'loop' argument can be use to control | |
interactive shell behaviour. | |
- | |
+ | |
Arguments: | |
"argv" (optional, default sys.argv) is the command to run. | |
It must be a sequence, where the first element is the | |
@@ -264,34 +228,29 @@ | |
otherwise, start loop | |
""" | |
if argv is None: | |
+ import sys | |
argv = sys.argv | |
else: | |
argv = argv[:] # don't modify caller's list | |
- try: | |
- self.optparser = self.get_optparser() | |
- if self.optparser: # i.e. optparser=None means don't process for opts | |
- try: | |
- self.options, args = self.optparser.parse_args(argv[1:]) | |
- except StopOptionProcessing: | |
- return 0 | |
- else: | |
- # Set default options *after* parsing command line options | |
- # This is an requirement for CmdlnWithConfigParser which | |
- # relies on the -c option which is only parsed in the above | |
- # `try' block | |
- self.optparser.set_defaults(**self.get_option_defaults(None)) | |
- self.options, args = self.optparser.parse_args(argv[1:]) | |
- else: | |
- self.options, args = None, argv[1:] | |
- self.postoptparse() | |
- except CmdlnUserError: | |
- _, ex, _ = sys.exc_info() | |
- msg = "%s: %s\nTry '%s help' for info.\n"\ | |
- % (self.name, ex, self.name) | |
- self.stderr.write(self._str(msg)) | |
- self.stderr.flush() | |
- return 1 | |
+ self.optparser = self.get_optparser() | |
+ if self.optparser: # i.e. optparser=None means don't process for opts | |
+ try: | |
+ self.options, args = self.optparser.parse_args(argv[1:]) | |
+ except CmdlnUserError, ex: | |
+ msg = "%s: %s\nTry '%s help' for info.\n"\ | |
+ % (self.name, ex, self.name) | |
+ self.stderr.write(self._str(msg)) | |
+ self.stderr.flush() | |
+ return 1 | |
+ except StopOptionProcessing, ex: | |
+ return 0 | |
+ else: | |
+ self.options, args = None, argv[1:] | |
+ | |
+ retval = self.postoptparse() | |
+ if retval: | |
+ return retval | |
if loop == LOOP_ALWAYS: | |
if args: | |
@@ -310,7 +269,7 @@ | |
def cmd(self, argv): | |
"""Run one command and exit. | |
- | |
+ | |
"argv" is the arglist for the command to run. argv[0] is the | |
command to run. If argv is an empty list then the | |
'emptyline' handler is run. | |
@@ -338,6 +297,7 @@ | |
#XXX What is the proper encoding to use here? 'utf-8' seems | |
# to work better than "getdefaultencoding" (usually | |
# 'ascii'), on OS X at least. | |
+ #import sys | |
#return s.encode(sys.getdefaultencoding(), "replace") | |
return s.encode("utf-8", "replace") | |
@@ -345,7 +305,7 @@ | |
"""Repeatedly issue a prompt, accept input, parse into an argv, and | |
dispatch (via .precmd(), .onecmd() and .postcmd()), passing them | |
the argv. In other words, start a shell. | |
- | |
+ | |
"intro" (optional) is a introductory message to print when | |
starting the command loop. This overrides the class | |
"intro" attribute, if any. | |
@@ -357,7 +317,10 @@ | |
import readline | |
self.old_completer = readline.get_completer() | |
readline.set_completer(self.complete) | |
- readline.parse_and_bind(self.completekey+": complete") | |
+ if sys.platform == "darwin": | |
+ readline.parse_and_bind("bind ^I rl_complete") | |
+ else: | |
+ readline.parse_and_bind(self.completekey+": complete") | |
except ImportError: | |
pass | |
try: | |
@@ -415,7 +378,7 @@ | |
interpreted, but after the input prompt is generated and issued. | |
"argv" is the cmd to run. | |
- | |
+ | |
Returns an argv to run (i.e. this method can modify the command | |
to run). | |
""" | |
@@ -423,7 +386,7 @@ | |
def postcmd(self, argv): | |
"""Hook method executed just after a command dispatch is finished. | |
- | |
+ | |
"argv" is the command that was run. | |
""" | |
pass | |
@@ -438,6 +401,7 @@ | |
opposed to programmer error in the design of the script using | |
cmdln.py). | |
""" | |
+ import sys | |
type, exc, traceback = sys.exc_info() | |
if isinstance(exc, CmdlnUserError): | |
msg = "%s %s: %s\nTry '%s help %s' for info.\n"\ | |
@@ -467,7 +431,7 @@ | |
"""Hook called to handle a command for which there is no handler. | |
"argv" is the command and arguments to run. | |
- | |
+ | |
The default implementation writes an error message to stderr | |
and returns an error exit status. | |
@@ -503,7 +467,7 @@ | |
"cmd" is the command name on which help was requested. | |
"known" is a boolean indicating if this command is known | |
(i.e. if there is a handler for it). | |
- | |
+ | |
Returns a return code. | |
""" | |
if known: | |
@@ -629,7 +593,7 @@ | |
i.e. using @cmdln.option decorators or manually setting the | |
'optparser' attribute on the 'do_*' method.) | |
- Returns the processed help. | |
+ Returns the processed help. | |
""" | |
preprocessors = { | |
"${name}": self._help_preprocess_name, | |
@@ -664,7 +628,7 @@ | |
block = self.optparser.format_option_help() + '\n' | |
else: | |
block = "" | |
- | |
+ | |
help = help.replace(indent+marker+suffix, block, 1) | |
return help | |
@@ -682,7 +646,8 @@ | |
for attr in self.get_names(): | |
if attr.startswith("do_"): | |
cmdnames[attr[3:]] = True | |
- cmdnames = list(sorted(cmdnames.keys())) | |
+ cmdnames = cmdnames.keys() | |
+ cmdnames.sort() | |
linedata = [] | |
for cmdname in cmdnames: | |
if aliases.get(cmdname): | |
@@ -700,7 +665,7 @@ | |
doc = handler.__doc__ | |
else: | |
doc = helpfunc() | |
- | |
+ | |
# Strip "${cmd_name}: " from the start of a command's doc. Best | |
# practice dictates that command help strings begin with this, but | |
# it isn't at all wanted for the command list. | |
@@ -710,9 +675,9 @@ | |
# to_strip, cmdname) | |
doc = doc[len(to_strip):].lstrip() | |
linedata.append( (cmdstr, doc) ) | |
- | |
+ | |
return linedata | |
- | |
+ | |
def _help_preprocess_command_list(self, help, cmdname=None): | |
marker = "${command_list}" | |
indent, indent_width = _get_indent(marker, help) | |
@@ -777,7 +742,7 @@ | |
handler = self._get_cmd_handler(cmdname) | |
if not handler: | |
raise CmdlnError("cannot preprocess '%s' into help string: " | |
- "could not find command handler for %r" | |
+ "could not find command handler for %r" | |
% (marker, cmdname)) | |
s = cmdname | |
if hasattr(handler, "aliases"): | |
@@ -793,20 +758,20 @@ | |
handler = self._get_cmd_handler(cmdname) | |
if not handler: | |
raise CmdlnError("cannot preprocess '%s' into help string: " | |
- "could not find command handler for %r" | |
+ "could not find command handler for %r" | |
% (marker, cmdname)) | |
indent, indent_width = _get_indent(marker, help) | |
suffix = _get_trailing_whitespace(marker, help) | |
# Extract the introspection bits we need. | |
- func = handler.__func__ | |
- if func.__defaults__: | |
- func_defaults = list(func.__defaults__) | |
+ func = handler.im_func | |
+ if func.func_defaults: | |
+ func_defaults = list(func.func_defaults) | |
else: | |
func_defaults = [] | |
- co_argcount = func.__code__.co_argcount | |
- co_varnames = func.__code__.co_varnames | |
- co_flags = func.__code__.co_flags | |
+ co_argcount = func.func_code.co_argcount | |
+ co_varnames = func.func_code.co_varnames | |
+ co_flags = func.func_code.co_flags | |
CO_FLAGS_ARGS = 4 | |
CO_FLAGS_KWARGS = 8 | |
@@ -829,9 +794,9 @@ | |
# keyword arguments from the command line. Could | |
# *perhaps* consider: arg=value arg2=value2 ... | |
warnings.warn("argument '**%s' on '%s.%s' command " | |
- "handler will never get values" | |
+ "handler will never get values" | |
% (name, self.__class__.__name__, | |
- func.__name__)) | |
+ func.func_name)) | |
if co_flags & CO_FLAGS_ARGS: | |
name = argnames.pop(-1) | |
tail = "[%s...]" % name.upper() | |
@@ -861,7 +826,7 @@ | |
handler = self._get_cmd_handler(cmdname) | |
if not handler: | |
raise CmdlnError("cannot preprocess '%s' into help string: " | |
- "could not find command handler for %r" | |
+ "could not find command handler for %r" | |
% (marker, cmdname)) | |
indent, indent_width = _get_indent(marker, help) | |
suffix = _get_trailing_whitespace(marker, help) | |
@@ -960,7 +925,7 @@ | |
StopIteration. This is raised by _OptionParserEx's default "help" | |
and "version" option actions and can be raised by custom option | |
callbacks too. | |
- | |
+ | |
Hence the typical CmdlnOptionParser (a subclass of _OptionParserEx) | |
usage is: | |
@@ -1052,44 +1017,27 @@ | |
def error(self, msg): | |
raise CmdlnUserError(msg) | |
- | |
+ | |
def option(*args, **kwargs): | |
"""Decorator to add an option to the optparser argument of a Cmdln | |
- subcommand | |
+ subcommand. | |
- To add a toplevel option, apply the decorator on the class itself. (see | |
- p4.py for an example) | |
- | |
Example: | |
- @cmdln.option("-E", dest="environment_path") | |
class MyShell(cmdln.Cmdln): | |
@cmdln.option("-f", "--force", help="force removal") | |
def do_remove(self, subcmd, opts, *args): | |
#... | |
""" | |
- def decorate_sub_command(method): | |
- """create and add sub-command options""" | |
- if not hasattr(method, "optparser"): | |
- method.optparser = SubCmdOptionParser() | |
- method.optparser.add_option(*args, **kwargs) | |
- return method | |
- def decorate_class(klass): | |
- """store toplevel options""" | |
- assert _forgiving_issubclass(klass, Cmdln) | |
- _inherit_attr(klass, "toplevel_optparser_options", [], cp=lambda l: l[:]) | |
- klass.toplevel_optparser_options.append( (args, kwargs) ) | |
- return klass | |
- | |
#XXX Is there a possible optimization for many options to not have a | |
# large stack depth here? | |
- def decorate(obj): | |
- if _forgiving_issubclass(obj, Cmdln): | |
- return decorate_class(obj) | |
- else: | |
- return decorate_sub_command(obj) | |
+ def decorate(f): | |
+ if not hasattr(f, "optparser"): | |
+ f.optparser = SubCmdOptionParser() | |
+ f.optparser.add_option(*args, **kwargs) | |
+ return f | |
return decorate | |
- | |
+ | |
class Cmdln(RawCmdln): | |
"""An improved (on cmd.Cmd) framework for building multi-subcommand | |
scripts (think "svn" & "cvs") and simple shells (think "pdb" and | |
@@ -1119,7 +1067,6 @@ | |
integration. See this class' _dispatch_cmd() docstring and general | |
cmdln document for more information. | |
""" | |
- | |
def _dispatch_cmd(self, handler, argv): | |
"""Introspect sub-command handler signature to determine how to | |
dispatch the command. The raw handler provided by the base | |
@@ -1157,20 +1104,15 @@ | |
and an appropriate error message will be raised/printed if the | |
command is called with a different number of args. | |
""" | |
- co_argcount = handler.__func__.__code__.co_argcount | |
+ co_argcount = handler.im_func.func_code.co_argcount | |
if co_argcount == 2: # handler ::= do_foo(self, argv) | |
return handler(argv) | |
elif co_argcount >= 3: # handler ::= do_foo(self, subcmd, opts, ...) | |
try: | |
optparser = handler.optparser | |
except AttributeError: | |
- optparser = handler.__func__.optparser = SubCmdOptionParser() | |
+ optparser = handler.im_func.optparser = SubCmdOptionParser() | |
assert isinstance(optparser, SubCmdOptionParser) | |
- | |
- # apply subcommand options' defaults from config files, if any. | |
- subcmd = handler.__name__.split('do_', 1)[1] | |
- optparser.set_defaults(**self.get_option_defaults(subcmd)) | |
- | |
optparser.set_cmdln_info(self, argv[0]) | |
try: | |
opts, args = optparser.parse_args(argv[1:]) | |
@@ -1181,15 +1123,14 @@ | |
try: | |
return handler(argv[0], opts, *args) | |
- except TypeError: | |
- _, ex, _ = sys.exc_info() | |
+ except TypeError, ex: | |
# Some TypeError's are user errors: | |
# do_foo() takes at least 4 arguments (3 given) | |
# do_foo() takes at most 5 arguments (6 given) | |
# do_foo() takes exactly 5 arguments (6 given) | |
- # do_foo() takes exactly 5 positional arguments (6 given) | |
# Raise CmdlnUserError for these with a suitably | |
# massaged error message. | |
+ import sys | |
tb = sys.exc_info()[2] # the traceback object | |
if tb.tb_next is not None: | |
# If the traceback is more than one level deep, then the | |
@@ -1221,15 +1162,15 @@ | |
def man_sections_from_cmdln(inst, summary=None, description=None, author=None): | |
"""Return man page sections appropriate for the given Cmdln instance. | |
Join these sections for man page content. | |
- | |
+ | |
The man page sections generated are: | |
NAME | |
SYNOPSIS | |
DESCRIPTION (if `description` is given) | |
OPTIONS | |
COMMANDS | |
- HELP TOPICS (if any) | |
- | |
+ HELP TOPICS (if any) | |
+ | |
@param inst {Cmdln} Instance of Cmdln subclass for which to generate | |
man page content. | |
@param summary {str} A one-liner summary of the command. | |
@@ -1246,12 +1187,12 @@ | |
data = { | |
"name": inst.name, | |
"ucname": inst.name.upper(), | |
- "date": datetime.date.today().strftime("%b %Y"), | |
+ "date": datetime.date.today().strftime("%b %Y"), | |
"cmdln_version": __version__, | |
"version_str": inst.version and " %s" % inst.version or "", | |
"summary_str": summary and r" \- %s" % summary or "", | |
} | |
- | |
+ | |
sections = [] | |
sections.append('.\\" Automatically generated by cmdln %(cmdln_version)s\n' | |
'.TH %(ucname)s "1" "%(date)s" "%(name)s%(version_str)s" "User Commands"\n' | |
@@ -1292,7 +1233,7 @@ | |
doc = doc.rstrip() + "\n" # trim down trailing space | |
section += '.PP\n.SS %s\n%s\n' % (cmdstr, doc) | |
sections.append(section) | |
- | |
+ | |
help_names = inst._get_help_names() | |
if help_names: | |
section = ".SH HELP TOPICS\n" | |
@@ -1311,36 +1252,9 @@ | |
#---- internal support functions | |
-def _inherit_attr(klass, attr, default, cp): | |
- """Inherit the attribute from the base class | |
- | |
- Copy `attr` from base class (otherwise use `default`). Copying is done using | |
- the passed `cp` function. | |
- | |
- The motivation behind writing this function is to allow inheritance among | |
- Cmdln classes where base classes set 'common' options using the | |
- `@cmdln.option` decorator. To ensure this, we must not write to the base | |
- class's options when handling the derived class. | |
- """ | |
- if attr not in klass.__dict__: | |
- if hasattr(klass, attr): | |
- value = cp(getattr(klass, attr)) | |
- else: | |
- value = default | |
- setattr(klass, attr, value) | |
- | |
-def _forgiving_issubclass(derived_class, base_class): | |
- """Forgiving version of ``issubclass`` | |
- | |
- Does not throw any exception when arguments are not of class type | |
- """ | |
- return (type(derived_class) is ClassType and \ | |
- type(base_class) is ClassType and \ | |
- issubclass(derived_class, base_class)) | |
- | |
def _format_linedata(linedata, indent, indent_width): | |
"""Format specific linedata into a pleasant layout. | |
- | |
+ | |
"linedata" is a list of 2-tuples of the form: | |
(<item-display-string>, <item-docstring>) | |
"indent" is a string to use for one level of indentation | |
@@ -1374,7 +1288,7 @@ | |
def _summarize_doc(doc, length=60): | |
r"""Parse out a short one line summary from the given doclines. | |
- | |
+ | |
"doc" is the doc string to summarize. | |
"length" is the max length for the summary | |
@@ -1406,19 +1320,19 @@ | |
summary = ' '.join(summlines) | |
if len(summary) > length: | |
- summary = summary[:length-3] + "..." | |
+ summary = summary[:length-3] + "..." | |
return summary | |
def line2argv(line): | |
r"""Parse the given line into an argument vector. | |
- | |
+ | |
"line" is the line of input to parse. | |
This may get niggly when dealing with quoting and escaping. The | |
current state of this parsing may not be completely thorough/correct | |
in this respect. | |
- | |
+ | |
>>> from cmdln import line2argv | |
>>> line2argv("foo") | |
['foo'] | |
@@ -1430,7 +1344,7 @@ | |
['foo', 'bar'] | |
Quote handling: | |
- | |
+ | |
>>> line2argv("'foo bar'") | |
['foo bar'] | |
>>> line2argv('"foo bar"') | |
@@ -1441,7 +1355,7 @@ | |
['foo bar', 'spam'] | |
>>> line2argv("'foo 'bar spam") | |
['foo bar', 'spam'] | |
- | |
+ | |
>>> line2argv('some\tsimple\ttests') | |
['some', 'simple', 'tests'] | |
>>> line2argv('a "more complex" test') | |
@@ -1533,9 +1447,9 @@ | |
def argv2line(argv): | |
r"""Put together the given argument vector into a command line. | |
- | |
+ | |
"argv" is the argument vector to process. | |
- | |
+ | |
>>> from cmdln import argv2line | |
>>> argv2line(['foo']) | |
'foo' | |
@@ -1568,20 +1482,20 @@ | |
# Recipe: dedent (0.1) in /Users/trentm/tm/recipes/cookbook | |
def _dedentlines(lines, tabsize=8, skip_first_line=False): | |
"""_dedentlines(lines, tabsize=8, skip_first_line=False) -> dedented lines | |
- | |
+ | |
"lines" is a list of lines to dedent. | |
"tabsize" is the tab width to use for indent width calculations. | |
"skip_first_line" is a boolean indicating if the first line should | |
be skipped for calculating the indent width and for dedenting. | |
This is sometimes useful for docstrings and similar. | |
- | |
+ | |
Same as dedent() except operates on a sequence of lines. Note: the | |
lines list is modified **in-place**. | |
""" | |
DEBUG = False | |
- if DEBUG: | |
- print("dedent: dedent(..., tabsize=%d, skip_first_line=%r)"\ | |
- % (tabsize, skip_first_line)) | |
+ if DEBUG: | |
+ print "dedent: dedent(..., tabsize=%d, skip_first_line=%r)"\ | |
+ % (tabsize, skip_first_line) | |
indents = [] | |
margin = None | |
for i, line in enumerate(lines): | |
@@ -1598,12 +1512,12 @@ | |
break | |
else: | |
continue # skip all-whitespace lines | |
- if DEBUG: print("dedent: indent=%d: %r" % (indent, line)) | |
+ if DEBUG: print "dedent: indent=%d: %r" % (indent, line) | |
if margin is None: | |
margin = indent | |
else: | |
margin = min(margin, indent) | |
- if DEBUG: print("dedent: margin=%r" % margin) | |
+ if DEBUG: print "dedent: margin=%r" % margin | |
if margin is not None and margin > 0: | |
for i, line in enumerate(lines): | |
@@ -1615,7 +1529,7 @@ | |
elif ch == '\t': | |
removed += tabsize - (removed % tabsize) | |
elif ch in '\r\n': | |
- if DEBUG: print("dedent: %r: EOL -> strip up to EOL" % line) | |
+ if DEBUG: print "dedent: %r: EOL -> strip up to EOL" % line | |
lines[i] = lines[i][j:] | |
break | |
else: | |
@@ -1623,8 +1537,8 @@ | |
"line %r while removing %d-space margin" | |
% (ch, line, margin)) | |
if DEBUG: | |
- print("dedent: %r: %r -> removed %d/%d"\ | |
- % (line, ch, removed, margin)) | |
+ print "dedent: %r: %r -> removed %d/%d"\ | |
+ % (line, ch, removed, margin) | |
if removed == margin: | |
lines[i] = lines[i][j+1:] | |
break | |
@@ -1641,7 +1555,7 @@ | |
"skip_first_line" is a boolean indicating if the first line should | |
be skipped for calculating the indent width and for dedenting. | |
This is sometimes useful for docstrings and similar. | |
- | |
+ | |
textwrap.dedent(s), but don't expand tabs to spaces | |
""" | |
lines = text.splitlines(1) | |
@@ -1737,8 +1651,7 @@ | |
try: | |
script = _module_from_path(script_path) | |
- except ImportError: | |
- _, ex, _ = sys.exc_info() | |
+ except ImportError, ex: | |
_log("error importing `%s': %s" % (script_path, ex)) | |
return [] | |
shell = getattr(script, class_name)() | |
@@ -1787,57 +1700,4 @@ | |
return [] | |
for cpln in _get_bash_cplns(*sys.argv[1:]): | |
- print(cpln) | |
- | |
- | |
- | |
-## -- contrib -- | |
- | |
-@option("-c", "--configfile", dest="configfile", default=None, | |
- metavar='FILENAME', | |
- help='Configuration file to read options from') | |
-class CmdlnWithConfigParser(Cmdln): | |
- """Cmdln with configparser support | |
- | |
- Add a new option -c --configfile for reading config file; and set | |
- default values for both toplevel and command-specific options. | |
- | |
- See examples/cfgexample.py | |
- """ | |
- | |
- class NoConfigFile(Exception): pass | |
- | |
- def __init__(self, default_configfile=None, *args, **kwargs): | |
- Cmdln.__init__(self, *args, **kwargs) | |
- self._cfgparser = None | |
- self._default_configfile = default_configfile | |
- | |
- def get_optparser(self): | |
- parser = Cmdln.get_optparser(self) | |
- parser.set_default('configfile', self._default_configfile) | |
- return parser | |
- | |
- def _load_config(self): | |
- if not self._cfgparser: | |
- if self.options.configfile: | |
- self._cfgparser = ConfigParser.SafeConfigParser() | |
- if not path.exists(self.options.configfile): | |
- raise CmdlnUserError( | |
- 'config file "%s" does not exist' % \ | |
- self.options.configfile) | |
- self._cfgparser.read(self.options.configfile) | |
- else: | |
- raise self.NoConfigFile | |
- | |
- def get_option_defaults(self, cmd): | |
- try: | |
- self._load_config() | |
- except self.NoConfigFile: | |
- return {} | |
- else: | |
- section = cmd or 'cmdln' | |
- try: | |
- return dict(self._cfgparser.items(section)) | |
- except ConfigParser.NoSectionError: | |
- return {} | |
- | |
+ print cpln |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment