From 9f8b6dc0c6bc9d0be32c0309b282ac1fb547e472 Mon Sep 17 00:00:00 2001 From: BJ Dierkes Date: Fri, 7 Sep 2012 15:30:54 -0500 Subject: [PATCH] Resolved Issue 172 - PEP8 Compliance --- ChangeLog | 4 + README.md | 5 +- cement/__init__.py | 2 +- cement/core/arg.py | 67 ++--- cement/core/backend.py | 45 ++-- cement/core/cache.py | 85 ++++--- cement/core/config.py | 126 +++++----- cement/core/controller.py | 331 ++++++++++++------------ cement/core/exc.py | 22 +- cement/core/extension.py | 107 ++++---- cement/core/foundation.py | 446 +++++++++++++++++---------------- cement/core/handler.py | 169 +++++++------ cement/core/hook.py | 76 +++--- cement/core/interface.py | 31 +-- cement/core/log.py | 101 ++++---- cement/core/meta.py | 14 +- cement/core/output.py | 64 ++--- cement/core/plugin.py | 65 ++--- cement/ext/__init__.py | 2 +- cement/ext/ext_argparse.py | 37 +-- cement/ext/ext_configparser.py | 93 +++---- cement/ext/ext_json.py | 44 ++-- cement/ext/ext_logging.py | 205 +++++++-------- cement/ext/ext_nulloutput.py | 20 +- cement/ext/ext_plugin.py | 101 ++++---- cement/utils/fs.py | 12 +- cement/utils/misc.py | 3 +- cement/utils/shell.py | 59 +++-- cement/utils/test.py | 28 ++- doc/source/index.rst | 7 +- requirements-dev.txt | 1 + 31 files changed, 1235 insertions(+), 1137 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91cd990e..54d1e1d9 100755 --- a/ChangeLog +++ b/ChangeLog @@ -36,6 +36,10 @@ Features: * :issue:`165` - Allow utils.fs.backup() to support a suffix kwarg * :issue:`166` - Ability to set the 'app' for CementTestCase.make_app() +Misc: + + * :issue:`172` - 100% PEP8 Compliant + Incompatible Changes: * :issue:`167` - Listed above, in order to fix this issue as well as diff --git a/README.md b/README.md index 0dc25ddf..394de10d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ 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. -[![Continuous Integration Status](https://secure.travis-ci.org/cement/cement.png)](http://travis-ci.org/cement/cement) +[![Continuous Integration Status](http://travis-ci.org/cement/cement.png)](http://travis-ci.org/cement/cement) Cement core features include (but are not limited to): @@ -25,7 +25,8 @@ Cement core features include (but are not limited to): * Cache handler interface adds caching support for improved performance * Controller handler supports sub-commands, and nested controllers * Zero external dependencies* (ext's with dependencies ship separately) - * 100% test coverage + * 100% test coverage using Nose + * 100% PEP8 compliant using `pep8` and `autopep8` tools * Extensive Sphinx documentation * Tested on Python 2.6, 2.7, 3.1, and 3.2 diff --git a/cement/__init__.py b/cement/__init__.py index 2cdb0e40..656dc0f7 100644 --- a/cement/__init__.py +++ b/cement/__init__.py @@ -1 +1 @@ -__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover +__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover diff --git a/cement/core/arg.py b/cement/core/arg.py index 7bfcfe97..6eaba2c0 100644 --- a/cement/core/arg.py +++ b/cement/core/arg.py @@ -7,106 +7,109 @@ from ..core import backend, interface, handler LOG = backend.minimal_logger(__name__) + def argument_validator(klass, obj): """Validates a handler implementation against the IArgument interface.""" + members = [ '_setup', 'parse', 'add_argument', - ] + ] + interface.validate(IArgument, obj, members) - + + class IArgument(interface.Interface): """ - This class defines the Argument Handler Interface. Classes that - implement this handler must provide the methods and attributes defined + This class defines the Argument Handler Interface. Classes that + implement this handler must provide the methods and attributes defined below. Implementations do *not* subclass from interfaces. - + Example: - + .. code-block:: python - + from cement.core import interface, arg class MyArgumentHandler(arg.CementArgumentHandler): class Meta: interface = arg.IArgument label = 'my_argument_handler' - + """ class IMeta: """Interface meta-data options.""" label = 'argument' """The string identifier of the interface.""" - + validator = argument_validator """Interface validator function.""" - + # Must be provided by the implementation Meta = interface.Attribute('Handler Meta-data') - + def _setup(app_obj): """ The _setup function is called during application initialization and must 'setup' the handler object making it ready for the framework or the application to make further calls to it. - + :param app_obj: The application object :returns: None - + """ - + def add_argument(*args, **kw): """ - Add arguments for parsing. This should be -o/--option or positional. + Add arguments for parsing. This should be -o/--option or positional. Note that the interface defines the following parameters so that at - the very least, external extensions can guarantee that they can + the very least, external extensions can guarantee that they can properly add command line arguments when necessary. The implementation itself should, and will provide and support many more options than those listed here. That said, the implementation must support the following: - - :arg args: List of option arguments. Generally something like + + :arg args: List of option arguments. Generally something like ['-h', '--help']. :keyword dest: The destination name (var). Default: arg[0]'s string. :keyword help: The help text for --help output (for that argument). - :keyword action: Must support: ['store', 'store_true', 'store_false', + :keyword action: Must support: ['store', 'store_true', 'store_false', 'store_const'] :keyword const: The value stored if action == 'store_const'. :keyword default: The default value. :returns: None - + """ - + def parse(arg_list): """ Parse the argument list (i.e. sys.argv). Can return any object as - long as it's members contain those of the added arguments. For + long as it's members contain those of the added arguments. For example, if adding a '-v/--version' option that stores to the dest of 'version', then the member must be callable as 'Object().version'. - + :param arg_list: A list of command line arguments. :returns: Callable object - + """ + class CementArgumentHandler(handler.CementBaseHandler): - """ - Base class that all Argument Handlers should sub-class from. - - """ + """Base class that all Argument Handlers should sub-class from.""" + class Meta: """ - Handler meta-data (can be passed as keyword arguments to the parent + Handler meta-data (can be passed as keyword arguments to the parent class). """ - + label = None """The string identifier of the handler implementation.""" - + interface = IArgument """The interface that this class implements.""" - + def __init__(self, *args, **kw): super(CementArgumentHandler, self).__init__(*args, **kw) diff --git a/cement/core/backend.py b/cement/core/backend.py index 7c60c175..46a0edb1 100644 --- a/cement/core/backend.py +++ b/cement/core/backend.py @@ -6,71 +6,74 @@ import logging from ..core import exc + def defaults(*sections): """ Returns a standard dictionary object to use for application defaults. If sections are given, it will create a nested dict for each section name. - + :arg sections: Section keys to create nested dictionaries for. :returns: Dictionary of nested dictionaries (sections) :rtype: dict - + .. code-block:: python - + from cement.core import foundation, backend - + defaults = backend.defaults('myapp', 'section2', 'section3') defaults['myapp']['debug'] = False defaults['section2']['foo'] = 'bar defaults['section3']['foo2'] = 'bar2' - + app = foundation.CementApp('myapp', config_defaults=defaults) - - """ + + """ defaults = dict() for section in sections: defaults[section] = dict() return defaults + def minimal_logger(name, debug=False): """ Setup just enough for cement to be able to do debug logging. This is the logger used by the Cement framework, which is setup and accessed before - the application is functional (and more importantly before the + the application is functional (and more importantly before the applications log handler is usable). - - :param name: The logging namespace. This is generally '__name__' or + + :param name: The logging namespace. This is generally '__name__' or anything you want. :param debug: Toggle debug output. Default: False - :type debug: boolean + :type debug: boolean :returns: Logger object .. code-block:: python - + from cement.core import backend LOG = backend.minimal_logger('cement') LOG.debug('This is a debug message') - + """ - + log = logging.getLogger(name) formatter = logging.Formatter( - "%(asctime)s (%(levelname)s) %(name)s : %(message)s") + "%(asctime)s (%(levelname)s) %(name)s : %(message)s") console = logging.StreamHandler() console.setFormatter(formatter) - console.setLevel(logging.INFO) + console.setLevel(logging.INFO) log.setLevel(logging.INFO) - + # FIX ME: really don't want to hard check sys.argv like this but can't # figure any better way get logging started (only for debug) before the # app logging is setup. if '--debug' in sys.argv or debug: - console.setLevel(logging.DEBUG) + console.setLevel(logging.DEBUG) log.setLevel(logging.DEBUG) - + log.addHandler(console) return log - + + # global handlers dict handlers = {} @@ -78,7 +81,7 @@ handlers = {} hooks = {} # Save original stdout/stderr for supressing output. This is actually reset -# in foundation.CementApp.lay_cement() before nullifying output, but we set +# in foundation.CementApp.lay_cement() before nullifying output, but we set # it here just for a default. SAVED_STDOUT = sys.stdout SAVED_STDERR = sys.stderr diff --git a/cement/core/cache.py b/cement/core/cache.py index 496d0826..42fca804 100644 --- a/cement/core/cache.py +++ b/cement/core/cache.py @@ -4,105 +4,108 @@ from ..core import backend, exc, interface, handler LOG = backend.minimal_logger(__name__) + def cache_validator(klass, obj): """Validates a handler implementation against the ICache interface.""" - + members = [ '_setup', 'get', 'set', 'delete', 'purge', - ] - interface.validate(ICache, obj, members) - + ] + interface.validate(ICache, obj, members) + + class ICache(interface.Interface): """ - This class defines the Cache Handler Interface. Classes that - implement this handler must provide the methods and attributes defined + This class defines the Cache Handler Interface. Classes that + implement this handler must provide the methods and attributes defined below. - + Implementations do *not* subclass from interfaces. - + Usage: - + .. code-block:: python - + from cement.core import cache - + class MyCacheHandler(object): class Meta: interface = cache.ICache label = 'my_cache_handler' ... - + """ # pylint: disable=W0232, C0111, R0903 class IMeta: """Interface meta-data.""" - + label = 'cache' """The label (or type identifier) of the interface.""" - + validator = cache_validator """Interface validator function.""" - + # Must be provided by the implementation Meta = interface.Attribute('Handler meta-data') - + def _setup(app_obj): """ The _setup function is called during application initialization and must 'setup' the handler object making it ready for the framework or the application to make further calls to it. - - :param app_obj: The application object. - :returns: None - + + :param app_obj: The application object. + :returns: None + """ - + def get(key, fallback=None): """ Get the value for a key in the cache. If the key does not exist - or the key/value in cache is expired, this functions must return + or the key/value in cache is expired, this functions must return 'fallback' (which in turn must default to None). - + :param key: The key of the value stored in cache - :param fallback: Optional value that is returned if the cache is + :param fallback: Optional value that is returned if the cache is expired or the key does not exist. Default: None :returns: Unknown (whatever the value is in cache, or the `fallback`) - - """ + + """ def set(key, value, time=None): """ - Set the key/value in the cache for a set amount of `time`. - + Set the key/value in the cache for a set amount of `time`. + :param key: The key of the value to store in cache. :param value: The value of that key to store in cache. - :param time: A one-off expire time. If no time is given, then a - default value is used (determined by the implementation). + :param time: A one-off expire time. If no time is given, then a + default value is used (determined by the implementation). :type time: integer (seconds) or None :returns: None - + """ - + def delete(key): """ Deletes a key/value from the cache. - + :param key: The key in the cache to delete. :returns: True if the key is successfully deleted, False otherwise. :rtype: boolean - + """ - + def purge(): """ Clears all data from the cache. - + """ - + + class CementCacheHandler(handler.CementBaseHandler): """ Base class that all Cache Handlers should sub-class from. @@ -110,15 +113,15 @@ class CementCacheHandler(handler.CementBaseHandler): """ class Meta: """ - Handler meta-data (can be passed as keyword arguments to the parent + Handler meta-data (can be passed as keyword arguments to the parent class). """ - + label = None """String identifier of this handler implementation.""" - + interface = ICache """The interface that this handler class implements.""" - + def __init__(self, *args, **kw): super(CementCacheHandler, self).__init__(*args, **kw) diff --git a/cement/core/config.py b/cement/core/config.py index 5082f396..5841c935 100644 --- a/cement/core/config.py +++ b/cement/core/config.py @@ -2,144 +2,146 @@ from ..core import exc, backend, interface, handler + def config_validator(klass, obj): """Validates a handler implementation against the IConfig interface.""" members = [ '_setup', - 'keys', + 'keys', 'has_key', - 'get_sections', + 'get_sections', 'get_section_dict', - 'get', - 'set', - 'parse_file', + 'get', + 'set', + 'parse_file', 'merge', 'add_section', 'has_section', - ] + ] interface.validate(IConfig, obj, members) - + + class IConfig(interface.Interface): """ - This class defines the Config Handler Interface. Classes that - implement this handler must provide the methods and attributes defined + This class defines the Config Handler Interface. Classes that + implement this handler must provide the methods and attributes defined below. - - All implementations must provide sane 'default' functionality when - instantiated with no arguments. Meaning, it can and should accept + + All implementations must provide sane 'default' functionality when + instantiated with no arguments. Meaning, it can and should accept optional parameters that alter how it functions, but can not require any parameters. When the framework first initializes handlers it does not pass anything too them, though a handler can be instantiated first (with or without parameters) and then passed to 'CementApp()' already instantiated. - + Implementations do *not* subclass from interfaces. - + Usage: - + .. code-block:: python - + from cement.core import config - + class MyConfigHandler(config.CementConfigHandler): class Meta: interface = config.IConfig label = 'my_config_handler' ... - + """ # pylint: disable=W0232, C0111, R0903 class IMeta: """Interface meta-data.""" label = 'config' """The string identifier of the interface.""" - + validator = config_validator """The validator function.""" - + # Must be provided by the implementation Meta = interface.Attribute('Handler Meta-data') - + def _setup(app_obj): """ The _setup function is called during application initialization and must 'setup' the handler object making it ready for the framework or the application to make further calls to it. - - :param app_obj: The application object. - :returns: None - + + :param app_obj: The application object. + :returns: None + """ def parse_file(file_path): """ Parse config file settings from file_path. Returns True if the file existed, and was parsed successfully. Returns False otherwise. - + :param file_path: The path to the config file to parse. - :returns: True if the file was parsed, False otherwise. + :returns: True if the file was parsed, False otherwise. :rtype: boolean - + """ def keys(section): """ Return a list of configuration keys from `section`. - + :param section: The config [section] to pull keys from. :returns: A list of keys in `section`. :rtype: list - + """ - + def get_sections(): """ Return a list of configuration sections. These are designated by a [block] label in a config file. - + :returns: A list of config sections. :rtype: list - + """ - + def get_section_dict(section): """ Return a dict of configuration parameters for [section]. - - :param section: The config [section] to generate a dict from (using + + :param section: The config [section] to generate a dict from (using that section keys). :returns: A dictionary of the config section. :rtype: dict - + """ - + def add_section(section): """ Add a new section if it doesn't exist. - + :param section: The [section] label to create. :returns: None - - """ - + + """ + def get(section, key): """ Return a configuration value based on [section][key]. The return value type is unknown. - - :param section: The [section] of the configuration to pull key value + + :param section: The [section] of the configuration to pull key value from. :param key: The configuration key to get the value from. - :returns: The value of the `key` in `section`. + :returns: The value of the `key` in `section`. :rtype: Unknown - + """ - + def set(section, key, value): """ Set a configuration value based at [section][key]. - - :param section: The [section] of the configuration to pull key value + + :param section: The [section] of the configuration to pull key value from. :param key: The configuration key to set the value at. :param value: The value to set. @@ -150,39 +152,39 @@ class IConfig(interface.Interface): def merge(dict_obj, override=True): """ Merges a dict object into the configuration. - + :param dict_obj: The dictionary to merge into the config - :param override: Boolean. Whether to override existing values. + :param override: Boolean. Whether to override existing values. Default: True :returns: None """ - + def has_section(section): """ Returns whether or not the section exists. - + :param section: The section to test for. :returns: boolean - + """ - + + class CementConfigHandler(handler.CementBaseHandler): """ Base class that all Config Handlers should sub-class from. - + """ class Meta: """ - Handler meta-data (can be passed as keyword arguments to the parent + Handler meta-data (can be passed as keyword arguments to the parent class). """ - + label = None """The string identifier of the implementation.""" - + interface = IConfig """The interface that this handler implements.""" - + def __init__(self, *args, **kw): - super(CementConfigHandler, self).__init__(*args, **kw) - \ No newline at end of file + super(CementConfigHandler, self).__init__(*args, **kw) diff --git a/cement/core/controller.py b/cement/core/controller.py index a8ab5864..12325826 100644 --- a/cement/core/controller.py +++ b/cement/core/controller.py @@ -7,15 +7,16 @@ from ..core import backend, exc, interface, handler LOG = backend.minimal_logger(__name__) + def controller_validator(klass, obj): """ Validates a handler implementation against the IController interface. - + """ members = [ '_setup', '_dispatch', - ] + ] meta = [ 'label', 'interface', @@ -27,53 +28,54 @@ def controller_validator(klass, obj): 'epilog', 'stacked_on', 'hide', - ] + ] interface.validate(IController, obj, members, meta=meta) - + # also check _meta.arguments values errmsg = "Controller arguments must be a list of tuples. I.e. " + \ "[ (['-f', '--foo'], dict(action='store')), ]" try: - for _args,_kwargs in obj._meta.arguments: + for _args, _kwargs in obj._meta.arguments: if not type(_args) is list: raise exc.InterfaceError(errmsg) if not type(_kwargs) is dict: raise exc.InterfaceError(errmsg) except ValueError: raise exc.InterfaceError(errmsg) - + + class IController(interface.Interface): """ - This class defines the Controller Handler Interface. Classes that - implement this handler must provide the methods and attributes defined + This class defines the Controller Handler Interface. Classes that + implement this handler must provide the methods and attributes defined below. - + Implementations do *not* subclass from interfaces. - + Usage: - + .. code-block:: python - + from cement.core import controller - + class MyBaseController(controller.CementBaseController): class Meta: interface = controller.IController - ... + ... """ # pylint: disable=W0232, C0111, R0903 class IMeta: """Interface meta-data.""" - + label = 'controller' """The string identifier of the interface.""" - + validator = controller_validator """The interface validator function.""" - + # Must be provided by the implementation Meta = interface.Attribute('Handler meta-data') - + def _setup(app_obj): """ The _setup function is after application initialization and after it @@ -82,62 +84,63 @@ class IController(interface.Interface): right before it's _dispatch() function is called to execute a command. Must 'setup' the handler object making it ready for the framework or the application to make further calls to it. - + :param app_obj: The application object. :returns: None - + """ - + def _dispatch(self): """ Reads the application object's data to dispatch a command from this controller. For example, reading self.app.pargs to determine what command was passed, and then executing that command function. - + Note that Cement does *not* parse arguments when calling _dispatch() - on a controller, as it expects the controller to handle parsing + on a controller, as it expects the controller to handle parsing arguments (I.e. self.app.args.parse()). - - :returns: None - + + :returns: None + """ + class expose(object): """ - Used to expose controller functions to be listed as commands, and to + Used to expose controller functions to be listed as commands, and to decorate the function with Meta data for the argument parser. - + :param hide: Whether the command should be visible. :type hide: boolean :param help: Help text to display for that command. :type help: str :param aliases: Aliases to this command. :type aliases: list - + Usage: - + .. code-block:: python - + from cement.core.controller import CementBaseController, expose - + class MyAppBaseController(CementBaseController): class Meta: label = 'base' - + @expose(hide=True, aliases=['run']) def default(self): print("In MyAppBaseController.default()") - + @expose() def my_command(self): print("In MyAppBaseController.my_command()") - + """ def __init__(self, hide=False, help='', aliases=[]): self.hide = hide self.help = help self.aliases = aliases - + def __call__(self, func): self.func = func self.func.label = self.func.__name__ @@ -147,23 +150,24 @@ class expose(object): self.func.aliases = self.aliases return self.func + class CementBaseController(handler.CementBaseHandler): """ - This is an implementation of the - `IControllerHandler <#cement.core.controller.IController>`_ interface, but - as a base class that application controllers `should` subclass from. + This is an implementation of the + `IControllerHandler <#cement.core.controller.IController>`_ interface, but + as a base class that application controllers `should` subclass from. Registering it directly as a handler is useless. - + NOTE: This handler **requires** that the applications 'arg_handler' be - argparse. If using an alternative argument handler you will need to + argparse. If using an alternative argument handler you will need to write your own controller base class. - + Usage: - + .. code-block:: python - + from cement.core import controller - + class MyAppBaseController(controller.CementBaseController): class Meta: label = 'base' @@ -172,97 +176,97 @@ class CementBaseController(handler.CementBaseHandler): arguments = [] epilog = "This is the text at the bottom of --help." # ... - + class MyStackedController(controller.CementBaseController): class Meta: label = 'second_controller' aliases = ['sec', 'secondary'] stacked_on = 'base' # ... - + """ class Meta: """ - Controller meta-data (can be passed as keyword arguments to the parent + Controller meta-data (can be passed as keyword arguments to the parent class). - + """ - + interface = IController """The interface this class implements.""" - + label = 'base' """The string identifier for the controller.""" - + aliases = [] """ A list of aliases for the controller. Will be treated like command/function aliases for non-stacked controllers. For example: - 'myapp --help' is the same as + 'myapp --help' is the same as 'myapp --help'. """ - + description = None """The description shown at the top of '--help'. Default: None""" - + config_section = None """ - A config [section] to merge config_defaults into. Cement will default + A config [section] to merge config_defaults into. Cement will default to controller.