# HG changeset patch # User Alexander Solovyov <alexander@solovyov.net> # Date 1296115842 -3600 # Node ID c7517e6c769892f8cbf0154377d5b6ef0687b604 # Parent 1c983a38fdbc7ba3e4c89e0ebff7b696f2fa6b9c# Parent e167305851a0ba658222e51a4e7cdf87fabc240d merge in archlinux pkgbuild diff -r e167305851a0 -r c7517e6c7698 .hgtags --- a/.hgtags Thu Jan 27 02:48:28 2011 +0300 +++ b/.hgtags Thu Jan 27 09:10:42 2011 +0100 @@ -16,3 +16,4 @@ cfcc54fe6d49330d9ec2923e52f30869afc90485 1.1 b8f101500f1d030a4b1e9f586136fdfa38de1f62 1.2 a8a8ae1a3fbe7c27e90f5ae2fef09d78a8327c24 2.0 +a083e23ed554dd9d85d4f3362b9658acf1325259 2.1 diff -r e167305851a0 -r c7517e6c7698 docs/_static/cleanery.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/_static/cleanery.css Thu Jan 27 09:10:42 2011 +0100 @@ -0,0 +1,20 @@ +@import url("default.css"); + +body { + max-width: 50em; + margin: 0 auto; + background-color: white; +} + +h1, h2, h3, h4, h5, h6 { + background-color: white !important; + border-bottom: none !important; +} + +div.related { + background-color: white; + color: black; +} +div.related a { + color: #20435C +} diff -r e167305851a0 -r c7517e6c7698 docs/_static/custom.css --- a/docs/_static/custom.css Thu Jan 27 02:48:28 2011 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -@import url("default.css"); - -body { max-width: 70em; margin: 0 auto; } diff -r e167305851a0 -r c7517e6c7698 docs/conf.py --- a/docs/conf.py Thu Jan 27 02:48:28 2011 +0300 +++ b/docs/conf.py Thu Jan 27 09:10:42 2011 +0100 @@ -20,7 +20,8 @@ # -- Options for HTML output --------------------------------------------------- html_theme = 'default' -html_style = 'custom.css' +html_style = 'cleanery.css' +html_theme_options = {'nosidebar': True} html_title = "%s v%s" % (project, version) html_static_path = ['_static'] html_use_smartypants = True diff -r e167305851a0 -r c7517e6c7698 docs/index.rst --- a/docs/index.rst Thu Jan 27 02:48:28 2011 +0300 +++ b/docs/index.rst Thu Jan 27 09:10:42 2011 +0100 @@ -1,6 +1,6 @@ -============= +======== Opster -============= +======== Opster is a command line parser, intended to make writing command line applications easy and painless. It uses built-in Python types (lists, @@ -14,23 +14,69 @@ Features -------- - - parsing arguments from sys.argv or custom strings - - converting from string to appropriate Python objects - - help message generation - - positional and named arguments - - subcommands support - - short, clean and concise definitions - - ability to shorten names of subcommand and long options +- parsing arguments from ``sys.argv`` or custom strings +- :ref:`converting <options-processing>` from string to appropriate Python + objects +- :ref:`help message <help-generation>` generation +- positional and named arguments (i.e. arguments and options) +- :ref:`subcommands <subcommands>` support +- short, clean and concise definitions +- :ref:`ability to shorten <partial-names>` names of subcommand and long options + +Quick example +------------- + +That's an example of an option definition:: + + import sys + from opster import command + + @command(usage='%name [-n] MESSAGE') + def main(message, + no_newline=('n', False, "don't print a newline")): + 'Simple echo program' + sys.stdout.write(message) + if not no_newline: + sys.stdout.write('\n') + + if __name__ == '__main__': + main() + +Running this program will print the help:: + + > ./echo.py + echo.py: invalid arguments + echo.py [-n] MESSAGE + + Simple echo program + + options: + + -n --no-newline don't print a newline + -h --help show help + +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 - :ref:`see description <options-processing>`) 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 +further in documentation. What's nice ----------- - - Opster is a `single file`_, which means that you can easily include it with - your application - - When you've decorated function as command, you can continue to use it as - usual Python function. - - It's easy to switch between usual command line options parser and - subcommands. +- Opster is a `single file`_, which means that you can easily include it with + your application +- When you've decorated function as command, you can continue to use it as + usual Python function. +- It's easy to switch between usual command line options parser and + subcommands. Read more in :doc:`overview`. diff -r e167305851a0 -r c7517e6c7698 docs/overview.rst --- a/docs/overview.rst Thu Jan 27 02:48:28 2011 +0300 +++ b/docs/overview.rst Thu Jan 27 09:10:42 2011 +0100 @@ -3,7 +3,7 @@ ============== Options -------- +======= Configuration of option parser is a list of tuples:: @@ -13,35 +13,35 @@ ('', '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 - 2. long name (read note_) - 3. default value - 4. help string +1. short name +2. long name (read :ref:`note <renaming-note>`) +3. default value +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. +.. _options-processing: + 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 - - dictionary: value is then assumed being in format ``key=value`` and is - then assigned to this dictionary, `example`_ - - boolean/None: ``not default`` is passed and option takes no value - -.. _example: http://hg.piranha.org.ua/opster/file/default/tests/opster.t#l109 +- 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 +- dictionary: value is then assumed being in format ``key=value`` and is + then assigned to this dictionary, :ref:`example <definitions-test>` +- boolean/None: ``not default`` is passed and option takes no value Usage -^^^^^ +----- Usage is easy like that:: @@ -60,14 +60,15 @@ pid_file=('', '', 'name of file to write process ID to')): pass -.. _note: +.. _renaming-note: +.. note:: -I think it's easy to understand what's going on here, except that you need to -know that underscores in the long name will be replaced with dashes at the -command line. Of course, reverse process happens: if you have option with a dash -in long name in a definition, it will be replaced with underscore when passed to -function. This is done to comply with standarts of writing both console -interfaces and Python application. + I think it's easy to understand what's going on here, except that you need to + know that underscores in the long name will be replaced with dashes at the + command line. Of course, reverse process happens: if you have option with a + dash in long name in a definition, it will be replaced with underscore when + passed to function. This is done to comply with standarts of writing both + console interfaces and Python applications. After that you can simply call this function as an entry point to your program:: @@ -92,8 +93,10 @@ In this case no type conversion (which is done upon arguments parsing) will be performed. +.. _subcommands: + Subcommands ------------ +=========== It's pretty usual for complex application to have some system of subcommands, and opster provides facility for handling them. Configuration is simple:: @@ -144,11 +147,13 @@ if __name__ == '__main__': dispatch(cmdtable=cmdtable) +.. _partial-names: + Example usage, calling ``complex_`` with 5 as an argument for ``exit`` option, shows that command dispatcher will understand partial names of commands and options:: - app har --ex 5 + app comp --ex 5 But if your program is something like program shown earlier, you can use shortened api:: @@ -165,8 +170,10 @@ special global command table, which allows to call ``dispatch()`` without arguments. +.. _help-generation: + Help generation ---------------- +=============== Help is generated automatically and is available by the ``-h/--help`` command line option or by ``help`` subcommand (if you're using subcommand system). @@ -194,7 +201,7 @@ @command() def something(): - if some_consiquences: + if some_consequences: something.help() See `example from tests`_. @@ -203,7 +210,7 @@ Tips and tricks ---------------- +=============== There is one thing which may be obvious: it's easy to have "semi-global" options. If your subcommands (or scripts) tend to have same options in some diff -r e167305851a0 -r c7517e6c7698 setup.py --- a/setup.py Thu Jan 27 02:48:28 2011 +0300 +++ b/setup.py Thu Jan 27 09:10:42 2011 +0100 @@ -23,7 +23,7 @@ version = opster.__version__, author = opster.__author__, author_email = opster.__email__, - url = 'http://hg.piranha.org.ua/opster/docs/', + url = 'http://piranha.org.ua/opster/', classifiers = [ 'Environment :: Console', 'Intended Audience :: Developers', diff -r e167305851a0 -r c7517e6c7698 tests/opster.t --- a/tests/opster.t Thu Jan 27 02:48:28 2011 +0300 +++ b/tests/opster.t Thu Jan 27 09:10:42 2011 +0100 @@ -107,6 +107,8 @@ 'port': 5656, 'test': 'test'} +.. _definitions-test: + Now let's test our definitions:: $ run test_opts.py -D a=b so-what?