documentation cleanup

This commit is contained in:
BJ Dierkes 2010-01-20 20:12:27 -06:00
parent fb614fc8ad
commit 625e15a8a5
17 changed files with 136 additions and 103 deletions

View File

@ -1,4 +1,4 @@
MODIFIED PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between William J. Dierkes (a.k.a "BJ Dierkes"),

12
README
View File

@ -6,7 +6,7 @@ DESCRIPTION:
Cement is an advanced CLI Application Framework for Python. It promotes code
re-use by way of plugins and helper libraries that can be shared between
any application built on cement. The MVC and overall framework design is
any application built on Cement. The MVC and overall framework design is
very much inspired by the TurboGears2 web framework. Its goal is to introduce
a standard, and feature-full platform for both simple and complex command line
applications as well as support rapid development needs without sacrificing
@ -35,11 +35,11 @@ plugin system is designed to allow portability of re-usable code, and it
is encouraged to contribute any plugins back to the project to extend the
functionality of Cement.
The Cement CLI Application Framework for Python is Open Source and is
distributed under the Python Software Foundation License. When creating
plugins specifically for re-use within the community, please be sure to
follow the standard naming convention "HelloWorld Plugin for Cement" as an
example. The actual module name should be 'cement.plugins.helloworld'.
The Cement CLI Application Framework is Open Source and is distributed under
the Python Software Foundation License. When creating plugins specifically
for re-use within the community, please be sure to follow the standard naming
convention "HelloWorld Plugin for Cement" as an example. The actual module
name should be 'cement.plugins.helloworld'.
GETTING STARTED:

View File

@ -14,38 +14,35 @@ from cement.core.hook import register_hook, define_hook, run_hooks
log = get_logger(__name__)
def register_default_hooks():
"""Register Cement framework hooks."""
"""Registers Cement framework hooks."""
define_hook('options_hook')
define_hook('post_options_hook')
define_hook('validate_config_hook')
define_hook('pre_plugins_hook')
define_hook('post_plugins_hook')
def lay_cement(default_app_config=None, version_banner=None):
def lay_cement(config=None, banner=None):
"""
Primary method to setup an application for Cement.
Arguments:
config => dict containing application config.
version_banner => Option txt displayed for --version
Keyword arguments:
config -- Dict containing application config.
banner -- Optional text to display for --version
"""
vb = version_banner
if not version_banner:
vb = """%s version %s""" % (
default_app_config['app_name'],
get_distribution(default_app_config['app_egg_name']).version
)
if not banner:
banner = "%s version %s" % (
config['app_name'],
get_distribution(config['app_egg_name']).version)
namespace = CementNamespace(
label = 'global',
version = get_distribution(default_app_config['app_egg_name']).version,
required_api = CEMENT_API,
config = get_default_config(),
version_banner = vb,
label='global',
version=get_distribution(config['app_egg_name']).version,
required_api=CEMENT_API,
config=get_default_config(),
banner=banner,
)
define_namespace('global', namespace)
namespaces['global'].config.update(default_app_config)
namespaces['global'].config.update(config)
register_default_hooks()

View File

@ -12,18 +12,24 @@ from cement.core.exc import CementArgumentError
log = get_logger(__name__)
# FIXME: This method is so effing ugly.
def run_command(command_name):
def run_command(cmd_name=None):
"""
Run the command or namespace-subcommand.
Run the command or namespace-subcommand as defined by the 'expose()'
decorator used on a Controller function.
Keyword arguments:
cmd_name -- The command name as store in the global 'namespaces'. For
example, namespaces['global'].commands['cmd_name'].
"""
log.debug("processing passed command '%s'", command_name)
command_name = command_name.rstrip('*')
if command_name in namespaces.keys():
namespace = command_name
log.debug("processing passed command '%s'", cmd_name)
cmd_name = cmd_name.rstrip('*')
if cmd_name in namespaces.keys():
namespace = cmd_name
else:
namespace = 'global'
m = re.match('(.*)-help', command_name)
m = re.match('(.*)-help', cmd_name)
if m and m.group(1) in namespaces.keys():
namespace = m.group(1)
raise CementArgumentError, \
@ -46,7 +52,7 @@ def run_command(command_name):
pass # doesn't expect a result
if namespace == 'global':
actual_cmd = command_name
actual_cmd = cmd_name
else:
try:
actual_cmd = cli_args[1]
@ -62,4 +68,4 @@ def run_command(command_name):
log.debug("executing command '%s'" % actual_cmd)
func(cli_opts, cli_args)
else:
raise CementArgumentError, "Unknown command, see --help?"
raise CementArgumentError, "Unknown command '%s', see --help?" % actual_cmd

View File

@ -7,9 +7,26 @@ from cement.core.opt import init_parser
class CementNamespace(object):
"""
Class that handles plugins and namespaces (commands, options, hooks).
Class that handles plugins and namespaces.
"""
def __init__(self, label, version, required_api, **kw):
"""
Initialize CementNamespace class.
Required arguments:
label -- Namespace label. Class is stored in the global
'namespaces' dict as namespaces['label'].
version -- The version of the application.
required_api-- The required Cement API the application was built on.
Optional keyword arguments:
description -- Description of the plugin/namespace (default: '')
commands -- A dict of command functions (default: {})
is_hidden -- Boolean, whether command should display in --help
output (default: False)
config -- A config dict (default: None)
banner -- A version banner to display for --version (default: '')
"""
self.label = label
self.version = version
self.required_api = required_api
@ -21,20 +38,20 @@ class CementNamespace(object):
if kw.get('config', None):
self.config.update(kw['config'])
if not kw.get('version_banner'):
vb = "%s version %s" % (self.label, self.version)
if not kw.get('banner'):
banner = "%s version %s" % (self.label, self.version)
else:
vb = kw.get('version_banner')
self.options = kw.get('options', init_parser(version_banner=vb))
banner = kw.get('banner')
self.options = kw.get('options', init_parser(banner=banner))
def define_namespace(namespace, namespace_obj):
"""
Define a namespace for commands, options, configuration, etc.
Arguments:
namespace => label of the namespace
namespace_obj => CementNamespace object
Keyword arguments:
namespace -- Label of the namespace
namespace_obj -- CementNamespace object. Stored in global 'namespaces'
dict as namespaces['namespace']
"""
if namespaces.has_key(namespace):
raise CementRuntimeError, "Namespace '%s' already defined!" % namespace

View File

@ -38,12 +38,18 @@ class Options(object):
self.parser = OptionParser(formatter=fmt, version=version_banner)
def init_parser(version_banner=None):
"""Create an OptionParser object and returns its parser member."""
def init_parser(banner=None):
"""
Create an OptionParser object and returns its parser member.
Keyword arguments:
banner -- Optional version banner to display for --version
"""
fmt = IndentedHelpFormatter(
indent_increment=4, max_help_position=32, width=77, short_first=1
)
parser = OptionParser(formatter=fmt, version=version_banner)
parser = OptionParser(formatter=fmt, version=banner)
return parser

View File

@ -132,7 +132,6 @@ def load_all_plugins():
elif opt.get_opt_string() == '--json':
pass
else:
print opt
namespaces[namespace].options.add_option(opt)
for res in run_hooks('post_plugins_hook'):

View File

@ -29,7 +29,7 @@ def main():
# Warning: You shouldn't modify below this point unless you know what
# you're doing.
lay_cement(default_config, version_banner=BANNER)
lay_cement(config=default_config, banner=BANNER)
log = get_logger(__name__)
log.debug("Cement Framework Initialized!")

View File

@ -21,11 +21,11 @@ class {{package}}Plugin(CementPlugin):
def __init__(self):
CementPlugin.__init__(self,
label = '{{package}}',
version = VERSION,
description = 'Core plugin for {{package}}',
required_api = REQUIRED_CEMENT_API,
version_banner = BANNER,
label='{{package}}',
version=VERSION,
description='Core plugin for {{package}}',
required_api=REQUIRED_CEMENT_API,
banner=BANNER,
is_hidden=True,
)

View File

@ -25,11 +25,11 @@ class ExamplePlugin(CementPlugin):
def __init__(self):
CementPlugin.__init__(self,
label = 'example',
version = VERSION,
description = 'Example plugin for {{package}}',
required_api = REQUIRED_CEMENT_API,
version_banner=BANNER,
label='example',
version=VERSION,
description='Example plugin for {{package}}',
required_api=REQUIRED_CEMENT_API,
banner=BANNER,
)
# plugin configurations can be setup this way

View File

@ -27,11 +27,11 @@ class {{plugin}}Plugin(CementPlugin):
def __init__(self):
CementPlugin.__init__(self,
label = '{{plugin}}',
version = VERSION,
description = '{{plugin}} plugin for {{project}}',
required_api = REQUIRED_CEMENT_API,
version_banner=BANNER
label='{{plugin}}',
version=VERSION,
description='{{plugin}} plugin for {{project}}',
required_api=REQUIRED_CEMENT_API,
banner=BANNER
)
#

View File

@ -24,7 +24,7 @@ plugin_dir = ./var/lib/helloworld/plugins.d
# show_plugin_load = true
# toggle debug output... can be true, false, yes, no, 1, 0
debug = true
debug = false
# toggle the log level... can be info, warn, error, fatal, debug
log_level = warn
@ -34,4 +34,4 @@ log_to_console = true
# add any config options you'd like here
#
# myoption = this is my option
# myoption = this is my option

View File

@ -29,7 +29,7 @@ def main():
# Warning: You shouldn't modify below this point unless you know what
# you're doing.
lay_cement(default_config, version_banner=BANNER)
lay_cement(config=default_config, banner=BANNER)
log = get_logger(__name__)
log.debug("Cement Framework Initialized!")

View File

@ -25,11 +25,11 @@ class ExamplePlugin(CementPlugin):
def __init__(self):
CementPlugin.__init__(self,
label = 'example',
version = VERSION,
description = 'Example plugin for helloworld',
required_api = REQUIRED_CEMENT_API,
version_banner=BANNER,
label='example',
version=VERSION,
description='Example plugin for helloworld',
required_api=REQUIRED_CEMENT_API,
banner=BANNER,
)
# plugin configurations can be setup this way

View File

@ -21,11 +21,11 @@ class helloworldPlugin(CementPlugin):
def __init__(self):
CementPlugin.__init__(self,
label = 'helloworld',
version = VERSION,
description = 'Core plugin for helloworld',
required_api = REQUIRED_CEMENT_API,
version_banner = BANNER,
label='helloworld',
version=VERSION,
description='Core plugin for helloworld',
required_api=REQUIRED_CEMENT_API,
banner=BANNER,
is_hidden=True,
)

View File

@ -27,11 +27,11 @@ class sayhiPlugin(CementPlugin):
def __init__(self):
CementPlugin.__init__(self,
label = 'sayhi',
version = VERSION,
description = 'sayhi plugin for helloworld',
required_api = REQUIRED_CEMENT_API,
version_banner=BANNER
label='sayhi',
version=VERSION,
description='sayhi plugin for helloworld',
required_api=REQUIRED_CEMENT_API,
banner=BANNER
)
#

View File

@ -4,34 +4,42 @@ import sys, os
version = '0.5.1'
LONG = """
Cement is a CLI Application Framework for Python. It promotes code re-use by
way of plugins and helper libraries that can be maintained internally, or
shared with the community. The MVC and overall framework design is very much
inspired by the TurboGears2 web framework.
Cement is an advanced CLI Application Framework for Python. It promotes code
re-use by way of plugins and helper libraries that can be shared between
any application built on Cement. The MVC and overall framework design is
very much inspired by the TurboGears2 web framework. Its goal is to introduce
a standard, and feature-full platform for both simple and complex command line
applications as well as support rapid development needs without sacrificing
quality.
At a minimum, Cement easily sets up the following:
* Configuration file parsing [using ConfigObj]
* Command line arguments and option parsing [using OptParse]
* Logging [using Logger]
* Plugin support [partially using setuptools]
* Basic "hook" support
* Full MVC support for advanced application design
* Text output rendering with Genshi templates
At a minimum, Cement configures the following features for every application:
::
* Multiple Configuration file parsing (default: /etc, ~/)
* Command line argument and option parsing
* Dual Console/File Logging Support
* Full Internal and External (3rd Party) Plugin support
* Basic "hook" support
* Full MVC support for advanced application design
* Text output rendering with Genshi templates
* Json output rendering allows other programs to access your CLI-API
These pieces are important for any command line application..
Normally to accomplish what's listed above would require hundreds of lines of
code before you even begin working on your application logic. With Cement, the
above is configured with more or less a single command (via paste).
The above provides any level developer with a solid, and fully functional
cli application from the very start with more or less a single command via
the paster utility. Cement brings an end to the 'hack it out, and [maybe]
clean it up later' routine that we all find ourselves in under deadlines.
Cement is most generally used as a starting point from which to begin
developing a command line type application. That said, applications using
cement can also share plugins with either cement or other applications using
cement.
Any application can utilize existing plugins from the CementPlugins
project, or from other 3rd party resources to extend functionality. The
plugin system is designed to allow portability of re-usable code, and it
is encouraged to contribute any plugins back to the project to extend the
functionality of Cement.
The Cement CLI Application Framework for Python is Open Source and is
distributed under the Python Software Foundation License.
distributed under the Python Software Foundation License. When creating
plugins specifically for re-use within the community, please be sure to
follow the standard naming convention "HelloWorld Plugin for Cement" as an
example. The actual module name should be 'cement.plugins.helloworld'.
GETTING STARTED: