--- a/.hgtags Sat Nov 06 12:14:40 2010 -0700
+++ b/.hgtags Fri Dec 03 11:53:57 2010 -0800
@@ -11,3 +11,4 @@
95653a562a05f97e1a969d916d805bc6cf8a8b9b 0.9.10
bf6908d12aae4a54ac584df5a6f97f84157030d6 0.9.11
8d3e644647f8b0ebf4c215352f39ad48bf5c5c4c 0.9.12
+e21e182229c16059d00d9b79158ba1f3dd6b70ef 0.9.13
--- a/README Sat Nov 06 12:14:40 2010 -0700
+++ b/README Fri Dec 03 11:53:57 2010 -0800
@@ -20,10 +20,10 @@
@command(usage='%name [-n] MESSAGE')
def main(message,
- nonewline=('n', False, 'don\'t print a newline')):
+ no_newline=('n', False, 'don\'t print a newline')):
'Simple echo program'
sys.stdout.write(message)
- if not nonewline:
+ if not no_newline:
sys.stdout.write('\n')
if __name__ == '__main__':
@@ -37,13 +37,20 @@
options:
- -n --nonewline don't print a newline
- -h --help show help
+ -n --no-newline don't print a newline
+ -h --help show help
-I think this mostly describes what's going on, except that I'd like to mention
-one interesting feature - if you are using long name for option, you can use
-only partial name, for example ``./echo.py --nonew`` a is valid command
-line. This is also true for subcommands: read about that and everything else
-you'd like to know in `documentation`_.
+As you can see, here we have defined option to not print newline: keyword
+argument name is a long name for option, default value is a 3-tuple, containing
+short name for an option (can be empty), default value (on base of which
+processing is applied - `see description`_) and a help string.
+
+Underscores in long names are converted into dashes.
+
+If you are calling a command with option using long name, you can supply it
+partially. In this case it could look like ``./echo.py --nonew``. This is also
+true for subcommands: read about them and everything else you'd like to know in
+`documentation`_.
.. _documentation: http://hg.piranha.org.ua/opster/docs/
+.. _see description: http://hg.piranha.org.ua/opster/docs/overview.html#options-processing
--- a/contrib/PKGBUILD Sat Nov 06 12:14:40 2010 -0700
+++ b/contrib/PKGBUILD Fri Dec 03 11:53:57 2010 -0800
@@ -1,18 +1,19 @@
# Maintainer: Andrey Vlasovskikh <andrey.vlasovskikh@gmail.com>
pkgname=python-opster
-pkgver=0.9.11
-pkgrel=3
+pkgver=0.9.13
+pkgrel=1
pkgdesc="Python command line parsing speedster"
arch=(any)
url="http://hg.piranha.org.ua/opster/"
license=('BSD')
depends=('python2')
source=("http://pypi.python.org/packages/source/o/opster/opster-$pkgver.tar.gz")
-md5sums=('24b2349fa3930eb17e28e6fc7cf78575')
+md5sums=('462b102563886fc9dda9719470549c9e')
build() {
cd "$srcdir/opster-$pkgver"
python2 setup.py build || return 1
python2 setup.py install --root=$pkgdir --optimize=1 || return 1
}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/_static/custom.css Fri Dec 03 11:53:57 2010 -0800
@@ -0,0 +1,3 @@
+@import url("default.css");
+
+body { max-width: 70em; margin: 0 auto; }
--- a/docs/changelog.rst Sat Nov 06 12:14:40 2010 -0700
+++ b/docs/changelog.rst Fri Dec 03 11:53:57 2010 -0800
@@ -1,6 +1,12 @@
Changelog
---------
+0.9.13
+~~~~~~
+
+ - fixed exception handling (cleanup previous fix, actually)
+ - display only name of application, without full path
+
0.9.12
~~~~~~
--- a/docs/conf.py Sat Nov 06 12:14:40 2010 -0700
+++ b/docs/conf.py Fri Dec 03 11:53:57 2010 -0800
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
-import sys, os
-sys.path.append('..')
+import sys
+sys.path.insert(0, '..')
import opster
# -- General configuration -----------------------------------------------------
@@ -11,7 +11,7 @@
source_suffix = '.rst'
master_doc = 'index'
project = u'Opster'
-copyright = u'2009, Alexander Solovyov'
+copyright = u'2009-2010, Alexander Solovyov'
version = release = opster.__version__
exclude_trees = ['_build']
pygments_style = 'sphinx'
@@ -20,21 +20,9 @@
# -- Options for HTML output ---------------------------------------------------
html_theme = 'default'
-# "<project> v<release> documentation".
-#html_title = None
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-#html_logo = None
-#html_favicon = None
+html_style = 'custom.css'
+html_title = "%s v%s" % (project, version)
html_static_path = ['_static']
html_use_smartypants = True
-htmlhelp_basename = 'Opsterdoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-latex_documents = [
- ('index', 'Opster.tex', u'Opster Documentation',
- u'Alexander Solovyov', 'manual'),
-]
+html_use_index = False
+html_show_sourcelink = False
--- a/docs/overview.rst Sat Nov 06 12:14:40 2010 -0700
+++ b/docs/overview.rst Fri Dec 03 11:53:57 2010 -0800
@@ -1,6 +1,6 @@
-===================
+==============
Opster usage
-===================
+==============
Options
-------
@@ -12,6 +12,9 @@
('d', 'daemonize', False, 'daemonize process'),
('', 'pid-file', '', 'name of file to write process ID to')]
+Options contents
+^^^^^^^^^^^^^^^^
+
Each tuple is a definition of some option, consisting of 4 elements:
1. short name
@@ -20,14 +23,21 @@
4. help string
If a short name renders to False (for example, empty string), then it's not used
-at all. Long name is pretended to be available in any case. Default value also
-determines how supplied argument should be parsed:
+at all. Long name is pretended to be available in any case.
+
+Options processing
+^^^^^^^^^^^^^^^^^^
+
+Default value also determines how supplied argument should be parsed:
- function: return value of function called with a specified value is passed
- integer: value is convert to integer
- string: value is passed as is
- list: value is appended to this list
- - boolean/None: ``not default`` is passed and option takes no argument
+ - boolean/None: ``not default`` is passed and option takes no value
+
+Usage
+^^^^^
Usage is easy like that::
--- a/opster.py Sat Nov 06 12:14:40 2010 -0700
+++ b/opster.py Fri Dec 03 11:53:57 2010 -0800
@@ -6,7 +6,7 @@
from itertools import imap
__all__ = ['command', 'dispatch']
-__version__ = '0.9.12'
+__version__ = '0.9.13'
__author__ = 'Alexander Solovyov'
__email__ = 'piranha@piranha.org.ua'
@@ -87,12 +87,19 @@
# no catcher here because this is call from Python
return call_cmd_regular(func, options_)(*args, **opts)
- opts, args = catcher(lambda: parse(argv, options_), help_func)
+ try:
+ opts, args = catcher(lambda: parse(argv, options_), help_func)
+ except Abort:
+ return -1
if opts.pop('help', False):
return help_func()
- return catcher(lambda: call_cmd(name_, func)(*args, **opts),
- help_func)
+
+ try:
+ return catcher(lambda: call_cmd(name_, func)(*args, **opts),
+ help_func)
+ except Abort:
+ return -1
return inner
return wrapper
@@ -132,17 +139,22 @@
autocomplete(cmdtable, args, middleware)
- name, func, args, kwargs = catcher(
- lambda: _dispatch(args, cmdtable, globaloptions),
- help_func)
+ try:
+ name, func, args, kwargs = catcher(
+ lambda: _dispatch(args, cmdtable, globaloptions),
+ help_func)
+ except Abort:
+ return -1
+
if name == '_completion': # skip middleware
- return catcher(
- lambda: call_cmd(name, func)(*args, **kwargs),
- help_func)
+ worker = lambda: call_cmd(name, func)(*args, **kwargs)
else:
- return catcher(
- lambda: call_cmd(name, middleware(func))(*args, **kwargs),
- help_func)
+ worker = lambda: call_cmd(name, middleware(func))(*args, **kwargs)
+
+ try:
+ return catcher(worker, help_func)
+ except Abort:
+ return -1
# --------
# Help
@@ -451,17 +463,22 @@
return target()
except UnknownCommand, e:
err("unknown command: '%s'\n" % e)
+ raise Abort()
except AmbiguousCommand, e:
err("command '%s' is ambiguous:\n %s\n" %
(e.args[0], ' '.join(e.args[1])))
+ raise Abort()
except ParseError, e:
err('%s: %s\n' % (e.args[0], e.args[1]))
help_func(e.args[0])
+ raise Abort()
except getopt.GetoptError, e:
- err('error: %s\n' % e)
+ err('error: %s\n\n' % e)
help_func()
+ raise Abort()
except OpsterError, e:
err('%s\n' % e)
+ raise Abort()
def call_cmd(name, func):
def inner(*args, **kwargs):
@@ -495,7 +512,9 @@
def sysname():
name = sys.argv[0]
- if name.startswith('./'):
+ if name.startswith('/'):
+ return name.rsplit('/', 1)[1]
+ elif name.startswith('./'):
return name[2:]
return name
@@ -608,17 +627,17 @@
# --------
# Command exceptions
-class CommandException(Exception):
- 'Base class for command exceptions'
+class OpsterError(Exception):
+ 'Base opster exception'
-class AmbiguousCommand(CommandException):
+class AmbiguousCommand(OpsterError):
'Raised if command is ambiguous'
-class UnknownCommand(CommandException):
+class UnknownCommand(OpsterError):
'Raised if command is unknown'
-class ParseError(CommandException):
+class ParseError(OpsterError):
'Raised on error in command line parsing'
-class OpsterError(CommandException):
- 'Raised on trouble with opster configuration'
+class Abort(OpsterError):
+ 'Processing error, abort execution'
--- a/setup.cfg Sat Nov 06 12:14:40 2010 -0700
+++ b/setup.cfg Fri Dec 03 11:53:57 2010 -0800
@@ -1,2 +1,7 @@
+[build_sphinx]
+source-dir = docs/
+build-dir = docs/_build
+all_files = 1
+
[upload_docs]
upload-dir = docs/_build/html
--- a/tests/multicommands.py Sat Nov 06 12:14:40 2010 -0700
+++ b/tests/multicommands.py Fri Dec 03 11:53:57 2010 -0800
@@ -22,7 +22,7 @@
@command(cplx_opts, usage='[-p] [--exit value] ...', name='complex', hide=True)
def complex_(ui, *args, **opts):
- u'''That's more complex command indented to do something
+ u'''That's more complex command intended to do something
И самое главное - мы тут немножечко текста не в ascii напишем
и посмотрим, что будет. :)
--- a/tests/opster.t Sat Nov 06 12:14:40 2010 -0700
+++ b/tests/opster.t Fri Dec 03 11:53:57 2010 -0800
@@ -8,7 +8,7 @@
Check if usage is working::
$ run multicommands.py
- usage: /Users/piranha/dev/misc/opster/tests/multicommands.py <command> [options]
+ usage: multicommands.py <command> [options]
commands:
@@ -23,9 +23,9 @@
check it out::
$ run multicommands.py help complex
- /Users/piranha/dev/misc/opster/tests/multicommands.py complex [-p] [--exit value] ...
+ multicommands.py complex [-p] [--exit value] ...
- That's more complex command indented to do something
+ That's more complex command intended to do something
И самое главное - мы тут немножечко текста не в ascii напишем
и посмотрим, что будет. :)
@@ -44,7 +44,7 @@
$ run test_opts.py
another: invalid arguments
- /Users/piranha/dev/misc/opster/tests/test_opts.py [-l HOST] DIR
+ test_opts.py [-l HOST] DIR
Command with option declaration as keyword arguments
@@ -67,4 +67,22 @@
'port': 8000,
'test': 'test'}
+Should we check passing some invalid arguments? I think so::
+
+ $ run test_opts.py --wrong-option
+ error: option --wrong-option not recognized
+
+ test_opts.py [-l HOST] DIR
+
+ Command with option declaration as keyword arguments
+
+ options:
+
+ -l --listen ip to listen on (default: localhost)
+ -p --port port to listen on (default: 8000)
+ -d --daemonize daemonize process
+ --pid-file name of file to write process ID to
+ -t --test testing help for a function (default: test)
+ -h --help show help
+
That's all for today; see you next time!