documentation
authorAlexander Solovyov <piranha@piranha.org.ua>
Mon, 13 Jul 2009 18:23:42 +0300
changeset 33 e82b3f5c36d9
parent 32 9d42e3d16bcf
child 34 e4588c625dcb
documentation
.hgignore
README
docs/Makefile
docs/api.rst
docs/conf.py
docs/index.rst
docs/make.bat
docs/overview.rst
finaloption.py
--- a/.hgignore	Mon Jul 13 17:50:35 2009 +0300
+++ b/.hgignore	Mon Jul 13 18:23:42 2009 +0300
@@ -1,1 +1,2 @@
 \.pyc$
+^docs/_build/
--- a/README	Mon Jul 13 17:50:35 2009 +0300
+++ b/README	Mon Jul 13 18:23:42 2009 +0300
@@ -1,118 +1,51 @@
 .. -*- mode: rst -*-
 
-==========
- Fancycmd
-==========
-
-Fancycmd is a command line parser, indented to make writing command line
-applications easy and painless. It uses built-in Python types (lists,
-dictionaries, etc) to define options (or subcommands in case you need them),
-which makes configuration clear and concise.
-
+=============
+ Finaloption
+=============
 
-Options
--------
-
-Configuration of option parser is a list of tuples::
+::
 
-    opts = [('l', 'listen', 'localhost', 'ip to listen on'),
-            ('p', 'port', 8000, 'port to listen on'),
-            ('d', 'daemonize', False, 'daemonize process'),
-            ('', 'pid-file', '', 'name of file to write process ID to')]
-
-Each tuple is a definition of some option, consisting of 4 elements:
+  If that's the Final Option,
+  I'm gonna choose it.
+                   Die Krupps
 
- 1. short name
- 2. long name
- 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. 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
+Finaloption is a command line parser, indented to make writing command line
+applications easy and painless. It uses built-in Python types (lists,
+dictionaries, etc) to define options, which makes configuration clear and
+concise. Additionally it contains possibility to handle subcommands (i.e.
+``hg commit`` or ``svn update``).
 
-Usage is easy like that::
+JFYI: name is derived from Die Krupps' song Final Option, featured in epigraph.
 
-    from fancycmd import fancyopts
-    def main(dirname, **opts):
-        '''write some help here'''
-        pass
-    parser = fancyopts(main, opts, usage='%s [-l HOST] DIR' % sys.argv[0])
-    parser(sys.argv[1:])
+Quick example
+-------------
 
-Subcommands
------------
-
-It's pretty usual for complex application to have some system of subcommands,
-and fancycmd provides facility for handling them. Configuration is simple as
-well::
+That's simple example to show you example of an option definition::
 
-    cmdtable = {
-        '^simple':
-            (simple,
-             [('t', 'test', False, 'just test execution')],
-             '[-t] ...'),
-        'complex|hard':
-            (complex_,
-             [('p', 'pass', False, 'don\'t run the command'),
-              ('', 'exit', 0, 'exit with supplied code (default: 0)')],
-             '[-p] [--exit value] ...')}
+  import sys
+  from finaloption import command
 
-Keys in this dictionary are subcommand names. You can add aliases for
-subcommands, separating them with the ``|`` sign (of course, there can be few
-aliases). Marking command with preceding ``^`` means that this commands should
-be included in short help (more on that later).
-
-Values here are tuples, consisting of 3 elements:
-
- 1. function, which will handle this subcommand
- 2. list of options
- 3. usage string (used by help generator)
-
-Your application will also always have ``help`` command, when it uses subcommand
-system.
-
-You can define your functions for subcommands like this::
-
-    def simple(ui, *args, **opts):
-        '''some descriptive text here
+  @command(usage='%name [-n] MESSAGE')
+  def main(message,
+           nonewline=('n', False, 'don\'t print a newline')):
+      'Simple echo program'
+      sys.stdout.write(message)
+      if not nonewline:
+          sys.stdout.write('\n')
 
-        more help, I'd said a lot of help here ;-)
-        '''
-        pass
-
-Naturally ``args`` is a list, containing all arguments to command, and ``opts``
-is a dictionary, containing every option. ``ui`` is an UI_ instance.
+  if __name__ == '__main__':
+      main()
 
-Usage::
+Running this program will print the help::
 
-   describe api here
-
-UI
---
+  echo.py [-n] MESSAGE
 
-``UI`` is a special object intended to ease output handling in your
-application. There are two global options added, which are used by this object:
-``-v/--verbose`` and ``-q/--quiet``. And then you are encouraged to use ``UI``
-instance to output instead of directly printing messages, which is possible by
-using one of following methods:
+  Simple echo program
+
+  options:
 
-  - ``UI.info`` prints by default, but hides output with quiet option
-  - ``UI.note`` prints only if verbose option supplied
-  - ``UI.write`` prints in any case
-  - ``UI.warn`` prints to stderr (in any case)
-
+   -n --nonewline  don't print a newline
+   -h --help       show help
 
-Help generation
----------------
-
-Help is generated automatically and is available by the ``--help`` command line
-option or by ``help`` subcommand (if you're using subcommand system).
-
-Help is wrapped to length of 70 characters.
+I think this mostly describes what's going to. To learn more, read documentation.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/Makefile	Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,94 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: all help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+all:
+	make html
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  dirhtml   to make HTML files named index.html in directories"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  qthelp    to make HTML files and a qthelp project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+	@echo "  doctest   to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf _build/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
+	@echo
+	@echo "Build finished. The HTML pages are in _build/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in _build/dirhtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in _build/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in _build/qthelp, like this:"
+	@echo "# qcollectiongenerator _build/qthelp/Finaloption.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile _build/qthelp/Finaloption.qhc"
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in _build/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
+	@echo
+	@echo "The overview file is in _build/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in _build/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in _build/doctest/output.txt."
+
+open:
+	open _build/html/index.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/api.rst	Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,8 @@
+=================
+ Finaloption API
+=================
+
+.. module:: finaloption
+
+.. autofunction:: command
+.. autofunction:: dispatch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/conf.py	Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+import sys, os
+
+sys.path.append('..')
+
+# -- General configuration -----------------------------------------------------
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
+templates_path = ['_templates']
+source_suffix = '.rst'
+master_doc = 'index'
+project = u'Finaloption'
+copyright = u'2009, Alexander Solovyov'
+version = '0.9'
+release = '0.9'
+exclude_trees = ['_build']
+pygments_style = 'sphinx'
+
+
+# -- 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_static_path = ['_static']
+html_use_smartypants = True
+htmlhelp_basename = 'Finaloptiondoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_documents = [
+  ('index', 'Finaloption.tex', u'Finaloption Documentation',
+   u'Alexander Solovyov', 'manual'),
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/index.rst	Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,34 @@
+=============
+ Finaloption
+=============
+
+::
+
+  If that's the Final Option,
+  I'm gonna choose it.
+                   Die Krupps 
+
+.. toctree::
+   :maxdepth: 2
+
+   overview
+   api
+
+Finaloption is a command line parser, indented to make writing command line
+applications easy and painless. It uses built-in Python types (lists,
+dictionaries, etc) to define options, which makes configuration clear and
+concise. Additionally it contains possibility to handle subcommands (i.e.
+``hg commit`` or ``svn update``).
+
+JFYI: name is derived from Die Krupps' song Final Option, featured in epigraph.
+
+Features
+--------
+
+ - parsing arguments from sys.argv or custom strings
+ - converting from string to appropriate Python objects
+ - generating help message
+ - positional and named arguments
+ - subcommands support
+ - short, clean and concise definitions
+ - ability to shorten names of subcommand and long options
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/make.bat	Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,112 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+set SPHINXBUILD=sphinx-build
+set ALLSPHINXOPTS=-d _build/doctrees %SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html      to make standalone HTML files
+	echo.  dirhtml   to make HTML files named index.html in directories
+	echo.  pickle    to make pickle files
+	echo.  json      to make JSON files
+	echo.  htmlhelp  to make HTML files and a HTML help project
+	echo.  qthelp    to make HTML files and a qthelp project
+	echo.  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  changes   to make an overview over all changed/added/deprecated items
+	echo.  linkcheck to check all external links for integrity
+	echo.  doctest   to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (_build\*) do rmdir /q /s %%i
+	del /q /s _build\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% _build/html
+	echo.
+	echo.Build finished. The HTML pages are in _build/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% _build/dirhtml
+	echo.
+	echo.Build finished. The HTML pages are in _build/dirhtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% _build/pickle
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% _build/json
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% _build/htmlhelp
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in _build/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% _build/qthelp
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in _build/qthelp, like this:
+	echo.^> qcollectiongenerator _build\qthelp\Finaloption.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile _build\qthelp\Finaloption.ghc
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% _build/latex
+	echo.
+	echo.Build finished; the LaTeX files are in _build/latex.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% _build/changes
+	echo.
+	echo.The overview file is in _build/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% _build/linkcheck
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in _build/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% _build/doctest
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in _build/doctest/output.txt.
+	goto end
+)
+
+:end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/overview.rst	Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,146 @@
+===================
+ Finaloption usage
+===================
+
+Options
+-------
+
+Configuration of option parser is a list of tuples::
+
+  opts = [('l', 'listen', 'localhost', 'ip to listen on'),
+          ('p', 'port', 8000, 'port to listen on'),
+          ('d', 'daemonize', False, 'daemonize process'),
+          ('', 'pid-file', '', 'name of file to write process ID to')]
+
+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
+
+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:
+
+ - 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
+
+Usage is easy like that::
+
+  from finaloption import command
+
+  @command(options=opts, usage='%name [-l HOST] DIR')
+  def main(dirname, **opts):
+      '''write some help here'''
+      pass
+
+There is alternative declaration, easier for simple cases::
+
+  @command(usage='%name [-l HOST] DIR')
+  def main(dirname,
+           listen=('l', 'localhost', 'ip to listen on'),
+           pid_file=('', '', 'name of file to write process ID to')):
+      pass
+
+.. _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 dash 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.
+
+To make your application work, just call ``main()`` to parse ``sys.argv``.
+
+Subcommands
+-----------
+
+It's pretty usual for complex application to have some system of subcommands,
+and finaloption provides facility for handling them. Configuration is simple::
+
+  cmdtable = {
+      '^simple':
+          (simple,
+           [('t', 'test', False, 'just test execution')],
+           '[-t] ...'),
+      'complex|hard':
+          (complex_,
+           [('p', 'pass', False, 'don\'t run the command'),
+            ('', 'exit', 0, 'exit with supplied code (default: 0)')],
+           '[-p] [--exit value] ...')}
+
+Keys in this dictionary are subcommand names. You can add aliases for
+subcommands, separating them with the ``|`` sign (of course, there can be few
+aliases). Marking command with preceding ``^`` means that this commands should
+be included in short help (more on that later).
+
+Values here are tuples, consisting of 3 elements:
+
+ 1. function, which will handle this subcommand
+ 2. list of options
+ 3. usage string (used by help generator)
+
+Your application will also always have ``help`` command, when it uses subcommand
+system.
+
+You can define your functions for subcommands like this::
+
+    def simple(*args, **opts):
+        '''some descriptive text here
+
+        more help, I'd said a lot of help here ;-)
+        '''
+        pass
+
+Naturally ``args`` is a list, containing all arguments to command, and ``opts``
+is a dictionary, containing every option.
+
+After definition of all elements you can call command dispatcher::
+
+  from finaloption import dispatch
+
+  if __name__ == '__main__':
+      dispatch(cmdtable=cmdtable)
+
+But if your program is something like program shown earlier, you can use
+shortened api::
+
+  @command(usage='[-t] ...', shortlist=True)
+  def simple(somearg,
+             test=('t', False, 'just test execution')):
+      pass
+
+  if __name__ == '__main__':
+      dispatch()
+
+Every ``@command`` stores information about decorated function in special global
+command table, which allows to call ``dispatch()`` without arguments.
+
+
+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).
+
+It is generated from usage, function docstring and a list of option help
+strings, wrapped to length of 70 characters and looks like that::
+
+  > ./test.py help complex
+  complex: [-p] [--exit value] ...
+
+  That's more complex command indented to do something
+
+      Let's try to do that (what?!)
+
+  options:
+
+   -p --pass  don't run the command
+      --exit  exit with supplied code (default: 0)
+   -h --help  show help
+
--- a/finaloption.py	Mon Jul 13 17:50:35 2009 +0300
+++ b/finaloption.py	Mon Jul 13 18:23:42 2009 +0300
@@ -23,10 +23,10 @@
 
      - ``options``: options in format described in docs. If not supplied,
        will be determined from function.
-     - ``usage``: usage string for function, replaces %name with name
-       of program or subcommand. In case if it's subcommand and %name
-       is not present, usage is prepended by 'name: '
-     - ``name``: used for multiple subcommands. defaults to wrapped
+     - ``usage``: usage string for function, replaces ``%name`` with name
+       of program or subcommand. In case if it's subcommand and ``%name``
+       is not present, usage is prepended by ``name``
+     - ``name``: used for multiple subcommands. Defaults to wrapped
        function name
      - ``shortlist``: if command should be included in shortlist. Used
        only for multiple subcommands
@@ -68,25 +68,23 @@
 def dispatch(args=None, cmdtable=None, globalopts=None):
     '''Dispatch command arguments based on subcommands.
 
-     - ``args``: list of arguments, default: sys.argv[1:]
-     - ``cmdtable``: dict of commands in next format::
-
-     {'name': (function, options, usage)}
+    - ``args``: list of arguments, default: ``sys.argv[1:]``
+    - ``cmdtable``: dict of commands in format described below.
+      If not supplied, functions decorated with ``@command`` will be used.
+    - ``globalopts``: list of options which are applied to all
+      commands, if not supplied will contain ``--help`` option
 
-       if not supplied, functions decorated with @command will be used.
-
-     - ``globalopts``: list of options which are applied to all
-       commands, if not supplied will contain ``--help`` option
+    cmdtable format description::
 
-    cmdtable format description follows:
+      {'name': (function, options, usage)}
 
-     - ``name`` is the name used on command-line. Can containt
-       aliases (separate them with '|') or pointer to the fact
-       that this command should be displayed in short help (start
-       name with '^')
-     - ``function`` is the actual callable
-     - ``options`` is options list in format described in docs
-     - ``usage`` is the short string of usage
+    - ``name`` is the name used on command-line. Can containt
+      aliases (separate them with ``|``) or pointer to the fact
+      that this command should be displayed in short help (start
+      name with ``^``)
+    - ``function`` is the actual callable
+    - ``options`` is options list in format described in docs
+    - ``usage`` is the short string of usage
     '''
     args = args or sys.argv[1:]
     cmdtable = cmdtable or CMDTABLE
@@ -156,6 +154,10 @@
 def help_cmd(func, usage, options):
     '''show help for given command
 
+    - ``func``: function to generate help for (``func.__doc__`` is taken)
+    - ``usage``: usage string
+    - ``options``: options in usual format
+
     >>> def test(*args, **opts):
     ...     """that's a test command
     ...