[mod] autopep8

This commit is contained in:
Laurent Peuch 2016-12-18 01:15:40 +01:00
parent c0291ff479
commit 897ad08183
14 changed files with 192 additions and 163 deletions

View file

@ -32,7 +32,7 @@ __all__ = [
from moulinette.core import init_interface, MoulinetteError from moulinette.core import init_interface, MoulinetteError
## Package functions # Package functions
def init(logging_config=None, **kwargs): def init(logging_config=None, **kwargs):
"""Package initialization """Package initialization
@ -68,7 +68,7 @@ def init(logging_config=None, **kwargs):
sys.path.insert(0, pkg.libdir) sys.path.insert(0, pkg.libdir)
## Easy access to interfaces # Easy access to interfaces
def api(namespaces, host='localhost', port=80, routes={}, def api(namespaces, host='localhost', port=80, routes={},
use_websocket=True, use_cache=True): use_websocket=True, use_cache=True):
@ -108,6 +108,7 @@ def api(namespaces, host='localhost', port=80, routes={},
logging.getLogger(namespaces[0]).info(m18n.g('operation_interrupted')) logging.getLogger(namespaces[0]).info(m18n.g('operation_interrupted'))
return 0 return 0
def cli(namespaces, args, use_cache=True, output_as=None, def cli(namespaces, args, use_cache=True, output_as=None,
password=None, timeout=None, parser_kwargs={}): password=None, timeout=None, parser_kwargs={}):
"""Command line interface """Command line interface

View file

@ -18,7 +18,7 @@ from moulinette.utils.log import start_action_logging
logger = logging.getLogger('moulinette.actionsmap') logger = logging.getLogger('moulinette.actionsmap')
## Extra parameters ---------------------------------------------------- # Extra parameters ----------------------------------------------------
# Extra parameters definition # Extra parameters definition
@ -30,26 +30,24 @@ class _ExtraParameter(object):
implement. implement.
""" """
def __init__(self, iface): def __init__(self, iface):
# TODO: Add conn argument which contains authentification object # TODO: Add conn argument which contains authentification object
self.iface = iface self.iface = iface
# Required variables
## Required variables
# Each extra parameters classes must overwrite these variables. # Each extra parameters classes must overwrite these variables.
"""The extra parameter name""" """The extra parameter name"""
name = None name = None
# Optional variables
## Optional variables
# Each extra parameters classes can overwrite these variables. # Each extra parameters classes can overwrite these variables.
"""A list of interface for which the parameter doesn't apply""" """A list of interface for which the parameter doesn't apply"""
skipped_iface = [] skipped_iface = []
# Virtual methods
## Virtual methods
# Each extra parameters classes can implement these methods. # Each extra parameters classes can implement these methods.
def __call__(self, parameter, arg_name, arg_value): def __call__(self, parameter, arg_name, arg_value):
@ -82,6 +80,7 @@ class _ExtraParameter(object):
""" """
return value return value
class AskParameter(_ExtraParameter): class AskParameter(_ExtraParameter):
""" """
Ask for the argument value if possible and needed. Ask for the argument value if possible and needed.
@ -91,7 +90,7 @@ class AskParameter(_ExtraParameter):
""" """
name = 'ask' name = 'ask'
skipped_iface = [ 'api' ] skipped_iface = ['api']
def __call__(self, message, arg_name, arg_value): def __call__(self, message, arg_name, arg_value):
if arg_value: if arg_value:
@ -107,14 +106,15 @@ class AskParameter(_ExtraParameter):
def validate(klass, value, arg_name): def validate(klass, value, arg_name):
# Deprecated boolean or empty string # Deprecated boolean or empty string
if isinstance(value, bool) or (isinstance(value, str) and not value): if isinstance(value, bool) or (isinstance(value, str) and not value):
logger.warning("expecting a string for extra parameter '%s' of " \ logger.warning("expecting a string for extra parameter '%s' of "
"argument '%s'", klass.name, arg_name) "argument '%s'", klass.name, arg_name)
value = arg_name value = arg_name
elif not isinstance(value, str): elif not isinstance(value, str):
raise TypeError("parameter value must be a string, got %r" \ raise TypeError("parameter value must be a string, got %r"
% value) % value)
return value return value
class PasswordParameter(AskParameter): class PasswordParameter(AskParameter):
""" """
Ask for the password argument value if possible and needed. Ask for the password argument value if possible and needed.
@ -135,6 +135,7 @@ class PasswordParameter(AskParameter):
except NotImplementedError: except NotImplementedError:
return arg_value return arg_value
class PatternParameter(_ExtraParameter): class PatternParameter(_ExtraParameter):
""" """
Check if the argument value match a pattern. Check if the argument value match a pattern.
@ -172,14 +173,15 @@ class PatternParameter(_ExtraParameter):
def validate(value, arg_name): def validate(value, arg_name):
# Deprecated string type # Deprecated string type
if isinstance(value, str): if isinstance(value, str):
logger.warning("expecting a list for extra parameter 'pattern' of " \ logger.warning("expecting a list for extra parameter 'pattern' of "
"argument '%s'", arg_name) "argument '%s'", arg_name)
value = [value, 'pattern_not_match'] value = [value, 'pattern_not_match']
elif not isinstance(value, list) or len(value) != 2: elif not isinstance(value, list) or len(value) != 2:
raise TypeError("parameter value must be a list, got %r" \ raise TypeError("parameter value must be a list, got %r"
% value) % value)
return value return value
class RequiredParameter(_ExtraParameter): class RequiredParameter(_ExtraParameter):
""" """
Check if a required argument is defined or not. Check if a required argument is defined or not.
@ -201,8 +203,8 @@ class RequiredParameter(_ExtraParameter):
@staticmethod @staticmethod
def validate(value, arg_name): def validate(value, arg_name):
if not isinstance(value, bool): if not isinstance(value, bool):
raise TypeError("parameter value must be a list, got %r" \ raise TypeError("parameter value must be a list, got %r"
% value) % value)
return value return value
""" """
@ -210,11 +212,12 @@ The list of available extra parameters classes. It will keep to this list
order on argument parsing. order on argument parsing.
""" """
extraparameters_list = [ AskParameter, PasswordParameter, RequiredParameter, extraparameters_list = [AskParameter, PasswordParameter, RequiredParameter,
PatternParameter ] PatternParameter]
# Extra parameters argument Parser # Extra parameters argument Parser
class ExtraArgumentParser(object): class ExtraArgumentParser(object):
""" """
Argument validator and parser for the extra parameters. Argument validator and parser for the extra parameters.
@ -223,6 +226,7 @@ class ExtraArgumentParser(object):
- iface -- The running interface - iface -- The running interface
""" """
def __init__(self, iface): def __init__(self, iface):
self.iface = iface self.iface = iface
self.extra = OrderedDict() self.extra = OrderedDict()
@ -255,7 +259,7 @@ class ExtraArgumentParser(object):
# Validate parameter value # Validate parameter value
parameters[p] = klass.validate(v, arg_name) parameters[p] = klass.validate(v, arg_name)
except Exception as e: except Exception as e:
logger.error("unable to validate extra parameter '%s' " \ logger.error("unable to validate extra parameter '%s' "
"for argument '%s': %s", p, arg_name, e) "for argument '%s': %s", p, arg_name, e)
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
@ -320,7 +324,7 @@ class ExtraArgumentParser(object):
return args return args
## Main class ---------------------------------------------------------- # Main class ----------------------------------------------------------
def ordered_yaml_load(stream): def ordered_yaml_load(stream):
class OrderedLoader(yaml.Loader): class OrderedLoader(yaml.Loader):
@ -353,6 +357,7 @@ class ActionsMap(object):
class at construction class at construction
""" """
def __init__(self, parser_class, namespaces=[], use_cache=True, def __init__(self, parser_class, namespaces=[], use_cache=True,
parser_kwargs={}): parser_kwargs={}):
if not issubclass(parser_class, BaseActionsMapParser): if not issubclass(parser_class, BaseActionsMapParser):
@ -540,8 +545,7 @@ class ActionsMap(object):
return actionsmaps return actionsmaps
# Private methods
## Private methods
def _construct_parser(self, actionsmaps, **kwargs): def _construct_parser(self, actionsmaps, **kwargs):
""" """
@ -557,19 +561,21 @@ class ActionsMap(object):
An interface relevant's parser object An interface relevant's parser object
""" """
## Get extra parameters # Get extra parameters
if not self.use_cache: if not self.use_cache:
validate_extra = True validate_extra = True
else: else:
validate_extra = False validate_extra = False
## Add arguments to the parser # Add arguments to the parser
def _add_arguments(tid, parser, arguments): def _add_arguments(tid, parser, arguments):
for argn, argp in arguments.items(): for argn, argp in arguments.items():
names = top_parser.format_arg_names(str(argn), names = top_parser.format_arg_names(str(argn),
argp.pop('full', None)) argp.pop('full', None))
try: argp['type'] = eval(argp['type']) try:
except: pass argp['type'] = eval(argp['type'])
except:
pass
try: try:
extra = argp.pop('extra') extra = argp.pop('extra')
@ -612,7 +618,7 @@ class ActionsMap(object):
actions = cp.pop('actions') actions = cp.pop('actions')
except KeyError: except KeyError:
# Invalid category without actions # Invalid category without actions
logger.warning("no actions found in category '%s' in " \ logger.warning("no actions found in category '%s' in "
"namespace '%s'", cn, n) "namespace '%s'", cn, n)
continue continue

View file

@ -27,6 +27,7 @@ class BaseAuthenticator(object):
- name -- The authenticator profile name - name -- The authenticator profile name
""" """
def __init__(self, name): def __init__(self, name):
self._name = name self._name = name
@ -35,8 +36,7 @@ class BaseAuthenticator(object):
"""Return the name of the authenticator instance""" """Return the name of the authenticator instance"""
return self._name return self._name
# Virtual properties
## Virtual properties
# Each authenticator classes must implement these properties. # Each authenticator classes must implement these properties.
"""The vendor name of the authenticator""" """The vendor name of the authenticator"""
@ -45,11 +45,10 @@ class BaseAuthenticator(object):
@property @property
def is_authenticated(self): def is_authenticated(self):
"""Either the instance is authenticated or not""" """Either the instance is authenticated or not"""
raise NotImplementedError("derived class '%s' must override this property" % \ raise NotImplementedError("derived class '%s' must override this property" %
self.__class__.__name__) self.__class__.__name__)
# Virtual methods
## Virtual methods
# Each authenticator classes must implement these methods. # Each authenticator classes must implement these methods.
def authenticate(password=None): def authenticate(password=None):
@ -62,11 +61,10 @@ class BaseAuthenticator(object):
- password -- A clear text password - password -- A clear text password
""" """
raise NotImplementedError("derived class '%s' must override this method" % \ raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__) self.__class__.__name__)
# Authentication methods
## Authentication methods
def __call__(self, password=None, token=None): def __call__(self, password=None, token=None):
"""Attempt to authenticate """Attempt to authenticate
@ -127,8 +125,7 @@ class BaseAuthenticator(object):
return self return self
# Private methods
## Private methods
def _open_sessionfile(self, session_id, mode='r'): def _open_sessionfile(self, session_id, mode='r'):
"""Open a session file for this instance in given mode""" """Open a session file for this instance in given mode"""

View file

@ -28,8 +28,9 @@ class Authenticator(BaseAuthenticator):
- user_rdn -- The user rdn to authenticate - user_rdn -- The user rdn to authenticate
""" """
def __init__(self, name, uri, base_dn, user_rdn=None): def __init__(self, name, uri, base_dn, user_rdn=None):
logger.debug("initialize authenticator '%s' with: uri='%s', " \ logger.debug("initialize authenticator '%s' with: uri='%s', "
"base_dn='%s', user_rdn='%s'", name, uri, base_dn, user_rdn) "base_dn='%s', user_rdn='%s'", name, uri, base_dn, user_rdn)
super(Authenticator, self).__init__(name) super(Authenticator, self).__init__(name)
@ -48,8 +49,7 @@ class Authenticator(BaseAuthenticator):
if self.con: if self.con:
self.con.unbind_s() self.con.unbind_s()
# Implement virtual properties
## Implement virtual properties
vendor = 'ldap' vendor = 'ldap'
@ -65,8 +65,7 @@ class Authenticator(BaseAuthenticator):
return True return True
return False return False
# Implement virtual methods
## Implement virtual methods
def authenticate(self, password): def authenticate(self, password):
try: try:
@ -83,8 +82,7 @@ class Authenticator(BaseAuthenticator):
else: else:
self.con = con self.con = con
# Additional LDAP methods
## Additional LDAP methods
# TODO: Review these methods # TODO: Review these methods
def search(self, base=None, filter='(objectClass=*)', attrs=['dn']): def search(self, base=None, filter='(objectClass=*)', attrs=['dn']):
@ -108,7 +106,7 @@ class Authenticator(BaseAuthenticator):
try: try:
result = self.con.search_s(base, ldap.SCOPE_SUBTREE, filter, attrs) result = self.con.search_s(base, ldap.SCOPE_SUBTREE, filter, attrs)
except: except:
logger.exception("error during LDAP search operation with: base='%s', " \ logger.exception("error during LDAP search operation with: base='%s', "
"filter='%s', attrs=%s", base, filter, attrs) "filter='%s', attrs=%s", base, filter, attrs)
raise MoulinetteError(169, m18n.g('ldap_operation_error')) raise MoulinetteError(169, m18n.g('ldap_operation_error'))
@ -139,7 +137,7 @@ class Authenticator(BaseAuthenticator):
try: try:
self.con.add_s(dn, ldif) self.con.add_s(dn, ldif)
except: except:
logger.exception("error during LDAP add operation with: rdn='%s', " \ logger.exception("error during LDAP add operation with: rdn='%s', "
"attr_dict=%s", rdn, attr_dict) "attr_dict=%s", rdn, attr_dict)
raise MoulinetteError(169, m18n.g('ldap_operation_error')) raise MoulinetteError(169, m18n.g('ldap_operation_error'))
else: else:
@ -189,7 +187,7 @@ class Authenticator(BaseAuthenticator):
self.con.modify_ext_s(dn, ldif) self.con.modify_ext_s(dn, ldif)
except: except:
logger.exception("error during LDAP update operation with: rdn='%s', " \ logger.exception("error during LDAP update operation with: rdn='%s', "
"attr_dict=%s, new_rdn=%s", rdn, attr_dict, new_rdn) "attr_dict=%s, new_rdn=%s", rdn, attr_dict, new_rdn)
raise MoulinetteError(169, m18n.g('ldap_operation_error')) raise MoulinetteError(169, m18n.g('ldap_operation_error'))
else: else:

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import sys
import time import time
import json import json
import errno import errno
@ -25,6 +24,7 @@ class Package(object):
not (only for debugging) not (only for debugging)
""" """
def __init__(self, _from_source=False): def __init__(self, _from_source=False):
if _from_source: if _from_source:
import sys import sys
@ -32,7 +32,7 @@ class Package(object):
logger.debug('initialize Package object running from source') logger.debug('initialize Package object running from source')
# Retrieve source's base directory # Retrieve source's base directory
basedir = os.path.abspath(os.path.dirname(sys.argv[0]) +'/../') basedir = os.path.abspath(os.path.dirname(sys.argv[0]) + '/../')
# Set local directories # Set local directories
self._datadir = '%s/data' % basedir self._datadir = '%s/data' % basedir
@ -55,8 +55,7 @@ class Package(object):
return return
self.__dict__[name] = value self.__dict__[name] = value
# Easy access to package directories
## Easy access to package directories
@property @property
def datadir(self): def datadir(self):
@ -78,8 +77,7 @@ class Package(object):
"""Return the cache directory of the package""" """Return the cache directory of the package"""
return self._cachedir return self._cachedir
# Additional methods
## Additional methods
def get_cachedir(self, subdir='', make_dir=True): def get_cachedir(self, subdir='', make_dir=True):
"""Get the path to a cache directory """Get the path to a cache directory
@ -131,6 +129,7 @@ class Translator(object):
- default_locale -- The default locale to use - default_locale -- The default locale to use
""" """
def __init__(self, locale_dir, default_locale='en'): def __init__(self, locale_dir, default_locale='en'):
self.locale_dir = locale_dir self.locale_dir = locale_dir
self.locale = default_locale self.locale = default_locale
@ -244,6 +243,7 @@ class Moulinette18n(object):
- default_locale -- The default locale to use - default_locale -- The default locale to use
""" """
def __init__(self, package, default_locale='en'): def __init__(self, package, default_locale='en'):
self.default_locale = default_locale self.default_locale = default_locale
self.locale = default_locale self.locale = default_locale
@ -333,6 +333,7 @@ class MoulinetteSignals(object):
- kwargs -- A dict of {signal: handler} to connect - kwargs -- A dict of {signal: handler} to connect
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
# Initialize handlers # Initialize handlers
for s in self.signals: for s in self.signals:
@ -356,11 +357,10 @@ class MoulinetteSignals(object):
return return
setattr(self, '_%s' % signal, self._notimplemented) setattr(self, '_%s' % signal, self._notimplemented)
# Signals definitions
## Signals definitions
"""The list of available signals""" """The list of available signals"""
signals = { 'authenticate', 'prompt', 'display' } signals = {'authenticate', 'prompt', 'display'}
def authenticate(self, authenticator, help): def authenticate(self, authenticator, help):
"""Process the authentication """Process the authentication
@ -471,6 +471,7 @@ def init_interface(name, kwargs={}, actionsmap={}):
return interface(amap, **kwargs) return interface(amap, **kwargs)
def init_authenticator((vendor, name), kwargs={}): def init_authenticator((vendor, name), kwargs={}):
"""Return a new authenticator instance """Return a new authenticator instance
@ -491,6 +492,7 @@ def init_authenticator((vendor, name), kwargs={}):
else: else:
return mod.Authenticator(name, **kwargs) return mod.Authenticator(name, **kwargs)
def clean_session(session_id, profiles=[]): def clean_session(session_id, profiles=[]):
"""Clean a session cache """Clean a session cache
@ -534,6 +536,7 @@ class MoulinetteLock(object):
lock lock
""" """
def __init__(self, namespace, timeout=None, interval=.5): def __init__(self, namespace, timeout=None, interval=.5):
self.namespace = namespace self.namespace = namespace
self.timeout = timeout self.timeout = timeout

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import sys
import errno import errno
import logging import logging
import argparse import argparse
@ -31,6 +30,7 @@ class BaseActionsMapParser(object):
- parent -- A parent BaseActionsMapParser derived object - parent -- A parent BaseActionsMapParser derived object
""" """
def __init__(self, parent=None, **kwargs): def __init__(self, parent=None, **kwargs):
if parent: if parent:
self._o = parent self._o = parent
@ -43,15 +43,13 @@ class BaseActionsMapParser(object):
self._global_conf = {} self._global_conf = {}
self._conf = {} self._conf = {}
# Virtual properties
## Virtual properties
# Each parser classes must implement these properties. # Each parser classes must implement these properties.
"""The name of the interface for which it is the parser""" """The name of the interface for which it is the parser"""
interface = None interface = None
# Virtual methods
## Virtual methods
# Each parser classes must implement these methods. # Each parser classes must implement these methods.
@staticmethod @staticmethod
@ -70,8 +68,8 @@ class BaseActionsMapParser(object):
A list of option strings A list of option strings
""" """
raise NotImplementedError("derived class '%s' must override this method" % \ raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__) self.__class__.__name__)
def add_global_parser(self, **kwargs): def add_global_parser(self, **kwargs):
"""Add a parser for global arguments """Add a parser for global arguments
@ -82,8 +80,8 @@ class BaseActionsMapParser(object):
An ArgumentParser based object An ArgumentParser based object
""" """
raise NotImplementedError("derived class '%s' must override this method" % \ raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__) self.__class__.__name__)
def add_category_parser(self, name, **kwargs): def add_category_parser(self, name, **kwargs):
"""Add a parser for a category """Add a parser for a category
@ -97,8 +95,8 @@ class BaseActionsMapParser(object):
A BaseParser based object A BaseParser based object
""" """
raise NotImplementedError("derived class '%s' must override this method" % \ raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__) self.__class__.__name__)
def add_action_parser(self, name, tid, **kwargs): def add_action_parser(self, name, tid, **kwargs):
"""Add a parser for an action """Add a parser for an action
@ -113,8 +111,8 @@ class BaseActionsMapParser(object):
An ArgumentParser based object An ArgumentParser based object
""" """
raise NotImplementedError("derived class '%s' must override this method" % \ raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__) self.__class__.__name__)
def parse_args(self, args, **kwargs): def parse_args(self, args, **kwargs):
"""Parse arguments """Parse arguments
@ -129,11 +127,10 @@ class BaseActionsMapParser(object):
The populated namespace The populated namespace
""" """
raise NotImplementedError("derived class '%s' must override this method" % \ raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__) self.__class__.__name__)
# Arguments helpers
## Arguments helpers
def prepare_action_namespace(self, tid, namespace=None): def prepare_action_namespace(self, tid, namespace=None):
"""Prepare the namespace for a given action""" """Prepare the namespace for a given action"""
@ -168,8 +165,7 @@ class BaseActionsMapParser(object):
return namespace return namespace
# Configuration access
## Configuration access
@property @property
def global_conf(self): def global_conf(self):
@ -237,7 +233,6 @@ class BaseActionsMapParser(object):
""" """
self._o._conf[action] = self._validate_conf(configuration) self._o._conf[action] = self._validate_conf(configuration)
def _validate_conf(self, configuration, is_global=False): def _validate_conf(self, configuration, is_global=False):
"""Validate configuration for the parser """Validate configuration for the parser
@ -265,7 +260,7 @@ class BaseActionsMapParser(object):
# Store only if authentication is needed # Store only if authentication is needed
conf['authenticate'] = True if self.interface in ifaces else False conf['authenticate'] = True if self.interface in ifaces else False
else: else:
logger.error("expecting 'all', 'False' or a list for " \ logger.error("expecting 'all', 'False' or a list for "
"configuration 'authenticate', got %r", ifaces) "configuration 'authenticate', got %r", ifaces)
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
@ -280,12 +275,12 @@ class BaseActionsMapParser(object):
# Store needed authenticator profile # Store needed authenticator profile
conf['authenticator'] = self.global_conf['authenticator'][auth] conf['authenticator'] = self.global_conf['authenticator'][auth]
except KeyError: except KeyError:
logger.error("requesting profile '%s' which is undefined in " \ logger.error("requesting profile '%s' which is undefined in "
"global configuration of 'authenticator'", auth) "global configuration of 'authenticator'", auth)
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
elif is_global and isinstance(auth, dict): elif is_global and isinstance(auth, dict):
if len(auth) == 0: if len(auth) == 0:
logger.warning('no profile defined in global configuration ' \ logger.warning('no profile defined in global configuration '
"for 'authenticator'") "for 'authenticator'")
else: else:
auths = {} auths = {}
@ -299,11 +294,11 @@ class BaseActionsMapParser(object):
# - parameters: a dict of arguments for the # - parameters: a dict of arguments for the
# authenticator profile # authenticator profile
auths[auth_name] = ((auth_conf.get('vendor'), auth_name), auths[auth_name] = ((auth_conf.get('vendor'), auth_name),
{ 'help': auth_conf.get('help', None) }, {'help': auth_conf.get('help', None)},
auth_conf.get('parameters', {})) auth_conf.get('parameters', {}))
conf['authenticator'] = auths conf['authenticator'] = auths
else: else:
logger.error("expecting a dict of profile(s) or a profile name " \ logger.error("expecting a dict of profile(s) or a profile name "
"for configuration 'authenticator', got %r", auth) "for configuration 'authenticator', got %r", auth)
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
@ -316,7 +311,7 @@ class BaseActionsMapParser(object):
if isinstance(arg_auth, bool): if isinstance(arg_auth, bool):
conf['argument_auth'] = arg_auth conf['argument_auth'] = arg_auth
else: else:
logger.error("expecting a boolean for configuration " \ logger.error("expecting a boolean for configuration "
"'argument_auth', got %r", arg_auth) "'argument_auth', got %r", arg_auth)
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
@ -329,7 +324,7 @@ class BaseActionsMapParser(object):
if isinstance(lock, bool): if isinstance(lock, bool):
conf['lock'] = lock conf['lock'] = lock
else: else:
logger.error("expecting a boolean for configuration 'lock', " \ logger.error("expecting a boolean for configuration 'lock', "
"got %r", lock) "got %r", lock)
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
@ -369,14 +364,16 @@ class BaseInterface(object):
""" """
# TODO: Add common interface methods and try to standardize default ones # TODO: Add common interface methods and try to standardize default ones
def __init__(self, actionsmap): def __init__(self, actionsmap):
raise NotImplementedError("derived class '%s' must override this method" % \ raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__) self.__class__.__name__)
# Argument parser ------------------------------------------------------ # Argument parser ------------------------------------------------------
class _CallbackAction(argparse.Action): class _CallbackAction(argparse.Action):
def __init__(self, def __init__(self,
option_strings, option_strings,
dest, dest,
@ -427,7 +424,7 @@ class _CallbackAction(argparse.Action):
# Execute callback and get returned value # Execute callback and get returned value
value = self.callback(namespace, values, **self.callback_kwargs) value = self.callback(namespace, values, **self.callback_kwargs)
except: except:
logger.exception("cannot get value from callback method " \ logger.exception("cannot get value from callback method "
"'{0}'".format(self.callback_method)) "'{0}'".format(self.callback_method))
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
else: else:
@ -437,6 +434,7 @@ class _CallbackAction(argparse.Action):
else: else:
setattr(namespace, self.dest, value) setattr(namespace, self.dest, value)
class _ExtendedSubParsersAction(argparse._SubParsersAction): class _ExtendedSubParsersAction(argparse._SubParsersAction):
"""Subparsers with extended properties for argparse """Subparsers with extended properties for argparse
@ -450,6 +448,7 @@ class _ExtendedSubParsersAction(argparse._SubParsersAction):
- deprecated_alias -- A list of deprecated command alias names - deprecated_alias -- A list of deprecated command alias names
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
required = kwargs.pop('required', False) required = kwargs.pop('required', False)
super(_ExtendedSubParsersAction, self).__init__(*args, **kwargs) super(_ExtendedSubParsersAction, self).__init__(*args, **kwargs)
@ -500,6 +499,7 @@ class _ExtendedSubParsersAction(argparse._SubParsersAction):
class ExtendedArgumentParser(argparse.ArgumentParser): class ExtendedArgumentParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ExtendedArgumentParser, self).__init__(*args, **kwargs) super(ExtendedArgumentParser, self).__init__(*args, **kwargs)
@ -517,8 +517,10 @@ class ExtendedArgumentParser(argparse.ArgumentParser):
c, v = queue.popleft() c, v = queue.popleft()
# FIXME: break dequeue if callback returns # FIXME: break dequeue if callback returns
c.execute(namespace, v) c.execute(namespace, v)
try: delattr(namespace, CALLBACKS_PROP) try:
except: pass delattr(namespace, CALLBACKS_PROP)
except:
pass
def _get_callbacks_queue(self, namespace, create=True): def _get_callbacks_queue(self, namespace, create=True):
try: try:
@ -536,7 +538,7 @@ class ExtendedArgumentParser(argparse.ArgumentParser):
return '([-AO]*)' return '([-AO]*)'
else: else:
return super(ExtendedArgumentParser, self)._get_nargs_pattern( return super(ExtendedArgumentParser, self)._get_nargs_pattern(
action) action)
def _get_values(self, action, arg_strings): def _get_values(self, action, arg_strings):
if action.nargs == argparse.PARSER and not action.required: if action.nargs == argparse.PARSER and not action.required:
@ -547,5 +549,5 @@ class ExtendedArgumentParser(argparse.ArgumentParser):
value = argparse.SUPPRESS value = argparse.SUPPRESS
else: else:
value = super(ExtendedArgumentParser, self)._get_values( value = super(ExtendedArgumentParser, self)._get_values(
action, arg_strings) action, arg_strings)
return value return value

View file

@ -29,11 +29,13 @@ class LogQueues(dict):
"""Map of session id to queue.""" """Map of session id to queue."""
pass pass
class APIQueueHandler(log.Handler): class APIQueueHandler(log.Handler):
""" """
A handler class which store logging records into a queue, to be used A handler class which store logging records into a queue, to be used
and retrieved from the API. and retrieved from the API.
""" """
def __init__(self): def __init__(self):
log.Handler.__init__(self) log.Handler.__init__(self)
self.queues = LogQueues() self.queues = LogQueues()
@ -52,6 +54,7 @@ class APIQueueHandler(log.Handler):
# populate the new message in the queue # populate the new message in the queue
sleep(0) sleep(0)
class _HTTPArgumentParser(object): class _HTTPArgumentParser(object):
"""Argument parser for HTTP requests """Argument parser for HTTP requests
@ -59,6 +62,7 @@ class _HTTPArgumentParser(object):
on ExtendedArgumentParser class and implements some of its methods. on ExtendedArgumentParser class and implements some of its methods.
""" """
def __init__(self): def __init__(self):
# Initialize the ArgumentParser object # Initialize the ArgumentParser object
self._parser = ExtendedArgumentParser(usage='', self._parser = ExtendedArgumentParser(usage='',
@ -89,7 +93,7 @@ class _HTTPArgumentParser(object):
def parse_args(self, args={}, namespace=None): def parse_args(self, args={}, namespace=None):
arg_strings = [] arg_strings = []
## Append an argument to the current one # Append an argument to the current one
def append(arg_strings, value, option_string=None): def append(arg_strings, value, option_string=None):
if isinstance(value, bool): if isinstance(value, bool):
# Append the option string only # Append the option string only
@ -110,11 +114,11 @@ class _HTTPArgumentParser(object):
if isinstance(v, str): if isinstance(v, str):
arg_strings.append(v) arg_strings.append(v)
else: else:
logger.warning("unsupported argument value type %r " \ logger.warning("unsupported argument value type %r "
"in %s for option string %s", v, value, "in %s for option string %s", v, value,
option_string) option_string)
else: else:
logger.warning("unsupported argument type %r for option " \ logger.warning("unsupported argument type %r for option "
"string %s", value, option_string) "string %s", value, option_string)
return arg_strings return arg_strings
@ -138,6 +142,7 @@ class _HTTPArgumentParser(object):
# TODO: Raise a proper exception # TODO: Raise a proper exception
raise MoulinetteError(1, message) raise MoulinetteError(1, message)
class _ActionsMapPlugin(object): class _ActionsMapPlugin(object):
"""Actions map Bottle Plugin """Actions map Bottle Plugin
@ -174,7 +179,7 @@ class _ActionsMapPlugin(object):
- app -- The application instance - app -- The application instance
""" """
## Login wrapper # Login wrapper
def _login(callback): def _login(callback):
def wrapper(): def wrapper():
kwargs = {} kwargs = {}
@ -189,7 +194,7 @@ class _ActionsMapPlugin(object):
return callback(**kwargs) return callback(**kwargs)
return wrapper return wrapper
## Logout wrapper # Logout wrapper
def _logout(callback): def _logout(callback):
def wrapper(): def wrapper():
kwargs = {} kwargs = {}
@ -258,8 +263,7 @@ class _ActionsMapPlugin(object):
return callback((request.method, context.rule), params) return callback((request.method, context.rule), params)
return wrapper return wrapper
# Routes callbacks
## Routes callbacks
def login(self, password, profile='default'): def login(self, password, profile='default'):
"""Log in to an authenticator profile """Log in to an authenticator profile
@ -290,8 +294,10 @@ class _ActionsMapPlugin(object):
auth(password, token=(s_id, s_hash)) auth(password, token=(s_id, s_hash))
except MoulinetteError as e: except MoulinetteError as e:
if len(s_hashes) > 0: if len(s_hashes) > 0:
try: self.logout(profile) try:
except: pass self.logout(profile)
except:
pass
raise error_to_response(e) raise error_to_response(e)
else: else:
# Update dicts with new values # Update dicts with new values
@ -359,7 +365,7 @@ class _ActionsMapPlugin(object):
else: else:
try: try:
# Send the message # Send the message
wsock.send(json_encode({ style: message })) wsock.send(json_encode({style: message}))
except WebSocketError: except WebSocketError:
break break
sleep(0) sleep(0)
@ -391,8 +397,7 @@ class _ActionsMapPlugin(object):
else: else:
queue.put(StopIteration) queue.put(StopIteration)
# Signals handlers
## Signals handlers
def _do_authenticate(self, authenticator, help): def _do_authenticate(self, authenticator, help):
"""Process the authentication """Process the authentication
@ -438,25 +443,35 @@ class _ActionsMapPlugin(object):
# HTTP Responses ------------------------------------------------------- # HTTP Responses -------------------------------------------------------
class HTTPOKResponse(HTTPResponse): class HTTPOKResponse(HTTPResponse):
def __init__(self, output=''): def __init__(self, output=''):
super(HTTPOKResponse, self).__init__(output, 200) super(HTTPOKResponse, self).__init__(output, 200)
class HTTPBadRequestResponse(HTTPResponse): class HTTPBadRequestResponse(HTTPResponse):
def __init__(self, output=''): def __init__(self, output=''):
super(HTTPBadRequestResponse, self).__init__(output, 400) super(HTTPBadRequestResponse, self).__init__(output, 400)
class HTTPUnauthorizedResponse(HTTPResponse): class HTTPUnauthorizedResponse(HTTPResponse):
def __init__(self, output=''): def __init__(self, output=''):
super(HTTPUnauthorizedResponse, self).__init__(output, 401) super(HTTPUnauthorizedResponse, self).__init__(output, 401)
class HTTPForbiddenResponse(HTTPResponse): class HTTPForbiddenResponse(HTTPResponse):
def __init__(self, output=''): def __init__(self, output=''):
super(HTTPForbiddenResponse, self).__init__(output, 403) super(HTTPForbiddenResponse, self).__init__(output, 403)
class HTTPErrorResponse(HTTPResponse): class HTTPErrorResponse(HTTPResponse):
def __init__(self, output=''): def __init__(self, output=''):
super(HTTPErrorResponse, self).__init__(output, 500) super(HTTPErrorResponse, self).__init__(output, 500)
def error_to_response(error): def error_to_response(error):
"""Convert a MoulinetteError to relevant HTTP response.""" """Convert a MoulinetteError to relevant HTTP response."""
if error.errno == errno.EPERM: if error.errno == errno.EPERM:
@ -464,18 +479,19 @@ def error_to_response(error):
elif error.errno == errno.EACCES: elif error.errno == errno.EACCES:
return HTTPUnauthorizedResponse(error.strerror) return HTTPUnauthorizedResponse(error.strerror)
# Client-side error # Client-side error
elif error.errno in [ errno.ENOENT, errno.ESRCH, errno.ENXIO, errno.EEXIST, elif error.errno in [errno.ENOENT, errno.ESRCH, errno.ENXIO, errno.EEXIST,
errno.ENODEV, errno.EINVAL, errno.ENOPKG, errno.EDESTADDRREQ ]: errno.ENODEV, errno.EINVAL, errno.ENOPKG, errno.EDESTADDRREQ]:
return HTTPBadRequestResponse(error.strerror) return HTTPBadRequestResponse(error.strerror)
# Server-side error # Server-side error
elif error.errno in [ errno.EIO, errno.EBUSY, errno.ENODATA, errno.EINTR, elif error.errno in [errno.EIO, errno.EBUSY, errno.ENODATA, errno.EINTR,
errno.ENETUNREACH ]: errno.ENETUNREACH]:
return HTTPErrorResponse(error.strerror) return HTTPErrorResponse(error.strerror)
else: else:
logger.debug('unknown relevant response for error [%s] %s', logger.debug('unknown relevant response for error [%s] %s',
error.errno, error.strerror) error.errno, error.strerror)
return HTTPErrorResponse(error.strerror) return HTTPErrorResponse(error.strerror)
def format_for_response(content): def format_for_response(content):
"""Format the resulted content of a request for the HTTP response.""" """Format the resulted content of a request for the HTTP response."""
if request.method == 'POST': if request.method == 'POST':
@ -503,10 +519,11 @@ class ActionsMapParser(BaseActionsMapParser):
the arguments is represented by a ExtendedArgumentParser object. the arguments is represented by a ExtendedArgumentParser object.
""" """
def __init__(self, parent=None, **kwargs): def __init__(self, parent=None, **kwargs):
super(ActionsMapParser, self).__init__(parent) super(ActionsMapParser, self).__init__(parent)
self._parsers = {} # dict({(method, path): _HTTPArgumentParser}) self._parsers = {} # dict({(method, path): _HTTPArgumentParser})
self._route_re = re.compile(r'(GET|POST|PUT|DELETE) (/\S+)') self._route_re = re.compile(r'(GET|POST|PUT|DELETE) (/\S+)')
@property @property
@ -514,13 +531,11 @@ class ActionsMapParser(BaseActionsMapParser):
"""Get current routes""" """Get current routes"""
return self._parsers.keys() return self._parsers.keys()
# Implement virtual properties
## Implement virtual properties
interface = 'api' interface = 'api'
# Implement virtual methods
## Implement virtual methods
@staticmethod @staticmethod
def format_arg_names(name, full): def format_arg_names(name, full):
@ -559,7 +574,7 @@ class ActionsMapParser(BaseActionsMapParser):
try: try:
keys.append(self._extract_route(r)) keys.append(self._extract_route(r))
except ValueError as e: except ValueError as e:
logger.warning("cannot add api route '%s' for " \ logger.warning("cannot add api route '%s' for "
"action %s: %s", r, tid, e) "action %s: %s", r, tid, e)
continue continue
if len(keys) == 0: if len(keys) == 0:
@ -613,8 +628,7 @@ class ActionsMapParser(BaseActionsMapParser):
parser.dequeue_callbacks(ret) parser.dequeue_callbacks(ret)
return ret return ret
# Private methods
## Private methods
def _extract_route(self, string): def _extract_route(self, string):
"""Extract action route from a string """Extract action route from a string
@ -652,6 +666,7 @@ class Interface(BaseInterface):
registered logging handlers registered logging handlers
""" """
def __init__(self, actionsmap, routes={}, use_websocket=True, def __init__(self, actionsmap, routes={}, use_websocket=True,
log_queues=None): log_queues=None):
self.use_websocket = use_websocket self.use_websocket = use_websocket
@ -665,14 +680,14 @@ class Interface(BaseInterface):
# TODO: Return OK to 'OPTIONS' xhr requests (l173) # TODO: Return OK to 'OPTIONS' xhr requests (l173)
app = Bottle(autojson=True) app = Bottle(autojson=True)
## Wrapper which sets proper header # Wrapper which sets proper header
def apiheader(callback): def apiheader(callback):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
response.set_header('Access-Control-Allow-Origin', '*') response.set_header('Access-Control-Allow-Origin', '*')
return callback(*args, **kwargs) return callback(*args, **kwargs)
return wrapper return wrapper
## Attempt to retrieve and set locale # Attempt to retrieve and set locale
def api18n(callback): def api18n(callback):
try: try:
locale = request.params.pop('locale') locale = request.params.pop('locale')
@ -729,8 +744,7 @@ class Interface(BaseInterface):
m18n.g('server_already_running')) m18n.g('server_already_running'))
raise MoulinetteError(errno.EIO, m18n.g('error_see_log')) raise MoulinetteError(errno.EIO, m18n.g('error_see_log'))
# Routes handlers
## Routes handlers
def doc(self, category=None): def doc(self, category=None):
""" """

View file

@ -26,15 +26,16 @@ CLI_COLOR_TEMPLATE = '\033[{:d}m\033[1m'
END_CLI_COLOR = '\033[m' END_CLI_COLOR = '\033[m'
colors_codes = { colors_codes = {
'red' : CLI_COLOR_TEMPLATE.format(31), 'red': CLI_COLOR_TEMPLATE.format(31),
'green' : CLI_COLOR_TEMPLATE.format(32), 'green': CLI_COLOR_TEMPLATE.format(32),
'yellow': CLI_COLOR_TEMPLATE.format(33), 'yellow': CLI_COLOR_TEMPLATE.format(33),
'blue' : CLI_COLOR_TEMPLATE.format(34), 'blue': CLI_COLOR_TEMPLATE.format(34),
'purple': CLI_COLOR_TEMPLATE.format(35), 'purple': CLI_COLOR_TEMPLATE.format(35),
'cyan' : CLI_COLOR_TEMPLATE.format(36), 'cyan': CLI_COLOR_TEMPLATE.format(36),
'white' : CLI_COLOR_TEMPLATE.format(37), 'white': CLI_COLOR_TEMPLATE.format(37),
} }
def colorize(astr, color): def colorize(astr, color):
"""Colorize a string """Colorize a string
@ -50,6 +51,7 @@ def colorize(astr, color):
else: else:
return astr return astr
def plain_print_dict(d, depth=0): def plain_print_dict(d, depth=0):
"""Print in a plain way a dictionary recursively """Print in a plain way a dictionary recursively
@ -79,16 +81,17 @@ def plain_print_dict(d, depth=0):
d = list(d) d = list(d)
if isinstance(d, list): if isinstance(d, list):
for v in d: for v in d:
plain_print_dict(v, depth+1) plain_print_dict(v, depth + 1)
elif isinstance(d, dict): elif isinstance(d, dict):
for k,v in d.items(): for k, v in d.items():
print("{}{}".format("#" * (depth+1), k)) print("{}{}".format("#" * (depth + 1), k))
plain_print_dict(v, depth+1) plain_print_dict(v, depth + 1)
else: else:
if isinstance(d, unicode): if isinstance(d, unicode):
d = d.encode('utf-8') d = d.encode('utf-8')
print(d) print(d)
def pretty_print_dict(d, depth=0): def pretty_print_dict(d, depth=0):
"""Print in a pretty way a dictionary recursively """Print in a pretty way a dictionary recursively
@ -111,23 +114,24 @@ def pretty_print_dict(d, depth=0):
v = v[0] v = v[0]
if isinstance(v, dict): if isinstance(v, dict):
print("{:s}{}: ".format(" " * depth, k)) print("{:s}{}: ".format(" " * depth, k))
pretty_print_dict(v, depth+1) pretty_print_dict(v, depth + 1)
elif isinstance(v, list): elif isinstance(v, list):
print("{:s}{}: ".format(" " * depth, k)) print("{:s}{}: ".format(" " * depth, k))
for key, value in enumerate(v): for key, value in enumerate(v):
if isinstance(value, tuple): if isinstance(value, tuple):
pretty_print_dict({value[0]: value[1]}, depth+1) pretty_print_dict({value[0]: value[1]}, depth + 1)
elif isinstance(value, dict): elif isinstance(value, dict):
pretty_print_dict({key: value}, depth+1) pretty_print_dict({key: value}, depth + 1)
else: else:
if isinstance(value, unicode): if isinstance(value, unicode):
value = value.encode('utf-8') value = value.encode('utf-8')
print("{:s}- {}".format(" " * (depth+1), value)) print("{:s}- {}".format(" " * (depth + 1), value))
else: else:
if isinstance(v, unicode): if isinstance(v, unicode):
v = v.encode('utf-8') v = v.encode('utf-8')
print("{:s}{}: {}".format(" " * depth, k, v)) print("{:s}{}: {}".format(" " * depth, k, v))
def get_locale(): def get_locale():
"""Return current user locale""" """Return current user locale"""
lang = locale.getdefaultlocale()[0] lang = locale.getdefaultlocale()[0]
@ -155,13 +159,13 @@ class TTYHandler(log.StreamHandler):
""" """
LEVELS_COLOR = { LEVELS_COLOR = {
log.NOTSET : 'white', log.NOTSET: 'white',
log.DEBUG : 'white', log.DEBUG: 'white',
log.INFO : 'cyan', log.INFO: 'cyan',
log.SUCCESS : 'green', log.SUCCESS: 'green',
log.WARNING : 'yellow', log.WARNING: 'yellow',
log.ERROR : 'red', log.ERROR: 'red',
log.CRITICAL : 'red', log.CRITICAL: 'red',
} }
def __init__(self, message_key='fmessage'): def __init__(self, message_key='fmessage'):
@ -216,6 +220,7 @@ class ActionsMapParser(BaseActionsMapParser):
be take into account but not parsed be take into account but not parsed
""" """
def __init__(self, parent=None, parser=None, subparser_kwargs=None, def __init__(self, parent=None, parser=None, subparser_kwargs=None,
top_parser=None, **kwargs): top_parser=None, **kwargs):
super(ActionsMapParser, self).__init__(parent) super(ActionsMapParser, self).__init__(parent)
@ -234,13 +239,11 @@ class ActionsMapParser(BaseActionsMapParser):
action.dest = SUPPRESS action.dest = SUPPRESS
glob._add_action(action) glob._add_action(action)
# Implement virtual properties
## Implement virtual properties
interface = 'cli' interface = 'cli'
# Implement virtual methods
## Implement virtual methods
@staticmethod @staticmethod
def format_arg_names(name, full): def format_arg_names(name, full):
@ -251,7 +254,7 @@ class ActionsMapParser(BaseActionsMapParser):
def add_global_parser(self, **kwargs): def add_global_parser(self, **kwargs):
if not self._global_parser: if not self._global_parser:
self._global_parser = self._parser.add_argument_group( self._global_parser = self._parser.add_argument_group(
"global arguments") "global arguments")
return self._global_parser return self._global_parser
def add_category_parser(self, name, category_help=None, **kwargs): def add_category_parser(self, name, category_help=None, **kwargs):
@ -266,7 +269,7 @@ class ActionsMapParser(BaseActionsMapParser):
""" """
parser = self._subparsers.add_parser(name, help=category_help, **kwargs) parser = self._subparsers.add_parser(name, help=category_help, **kwargs)
return self.__class__(self, parser, { return self.__class__(self, parser, {
'title': "actions", 'required': True 'title': "actions", 'required': True
}) })
def add_action_parser(self, name, tid, action_help=None, deprecated=False, def add_action_parser(self, name, tid, action_help=None, deprecated=False,
@ -310,6 +313,7 @@ class Interface(BaseInterface):
- actionsmap -- The ActionsMap instance to connect to - actionsmap -- The ActionsMap instance to connect to
""" """
def __init__(self, actionsmap): def __init__(self, actionsmap):
# Set user locale # Set user locale
m18n.set_locale(get_locale()) m18n.set_locale(get_locale())
@ -347,7 +351,7 @@ class Interface(BaseInterface):
# Set handler for authentication # Set handler for authentication
if password: if password:
msignals.set_handler('authenticate', msignals.set_handler('authenticate',
lambda a,h: a(password=password)) lambda a, h: a(password=password))
try: try:
ret = self.actionsmap.process(args, timeout=timeout) ret = self.actionsmap.process(args, timeout=timeout)
@ -370,8 +374,7 @@ class Interface(BaseInterface):
else: else:
print(ret) print(ret)
# Signals handlers
## Signals handlers
def _do_authenticate(self, authenticator, help): def _do_authenticate(self, authenticator, help):
"""Process the authentication """Process the authentication

View file

@ -2,7 +2,6 @@ import os
import errno import errno
import shutil import shutil
from pwd import getpwnam from pwd import getpwnam
from grp import getgrnam
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError

View file

@ -1,6 +1,6 @@
import os import os
import logging import logging
from logging import * from logging import addLevelName, setLoggerClass, Logger, getLogger
# Global configuration and functions ----------------------------------- # Global configuration and functions -----------------------------------
@ -31,6 +31,7 @@ DEFAULT_LOGGING = {
}, },
} }
def configure_logging(logging_config=None): def configure_logging(logging_config=None):
"""Configure logging with default and optionally given configuration """Configure logging with default and optionally given configuration
@ -49,6 +50,7 @@ def configure_logging(logging_config=None):
if logging_config: if logging_config:
dictConfig(logging_config) dictConfig(logging_config)
def getHandlersByClass(classinfo, limit=0): def getHandlersByClass(classinfo, limit=0):
"""Retrieve registered handlers of a given class.""" """Retrieve registered handlers of a given class."""
handlers = [] handlers = []
@ -59,7 +61,7 @@ def getHandlersByClass(classinfo, limit=0):
return o return o
handlers.append(o) handlers.append(o)
if limit != 0 and len(handlers) > limit: if limit != 0 and len(handlers) > limit:
return handlers[:limit-1] return handlers[:limit - 1]
return handlers return handlers
@ -111,9 +113,11 @@ class MoulinetteLogger(Logger):
pid = os.getpid() pid = os.getpid()
action_id = 0 action_id = 0
def _get_action_id(): def _get_action_id():
return '%d.%d' % (pid, action_id) return '%d.%d' % (pid, action_id)
def start_action_logging(): def start_action_logging():
"""Configure logging for a new action """Configure logging for a new action
@ -126,6 +130,7 @@ def start_action_logging():
return _get_action_id() return _get_action_id()
def getActionLogger(name=None, logger=None, action_id=None): def getActionLogger(name=None, logger=None, action_id=None):
"""Get the logger adapter for an action """Get the logger adapter for an action
@ -133,7 +138,7 @@ def getActionLogger(name=None, logger=None, action_id=None):
optionally for a given action id, retrieving it if necessary. optionally for a given action id, retrieving it if necessary.
Either a name or a logger must be specified. Either a name or a logger must be specified.
""" """
if not name and not logger: if not name and not logger:
raise ValueError('Either a name or a logger must be specified') raise ValueError('Either a name or a logger must be specified')
@ -152,6 +157,7 @@ class ActionFilter(object):
message formatted for the action or just the original one. message formatted for the action or just the original one.
""" """
def __init__(self, message_key='fmessage', strict=False): def __init__(self, message_key='fmessage', strict=False):
self.message_key = message_key self.message_key = message_key
self.strict = strict self.strict = strict

View file

@ -1,9 +1,5 @@
import time import time
import subprocess import subprocess
try:
from pipes import quote # Python2 & Python3 <= 3.2
except ImportError:
from shlex import quote # Python3 >= 3.3
from .stream import async_file_reading from .stream import async_file_reading
@ -145,17 +141,17 @@ def check_commands(cmds, raise_on_error=False, callback=None,
raise CalledProcessError(r, c, o) raise CalledProcessError(r, c, o)
else: else:
# Continue commands execution # Continue commands execution
callback = lambda r,c,o: True callback = lambda r, c, o: True
elif not callable(callback): elif not callable(callback):
raise ValueError('callback argument must be callable') raise ValueError('callback argument must be callable')
# Manage stderr # Manage stderr
if separate_stderr: if separate_stderr:
_stderr = subprocess.PIPE _stderr = subprocess.PIPE
_get_output = lambda o,e: (o,e) _get_output = lambda o, e: (o, e)
else: else:
_stderr = subprocess.STDOUT _stderr = subprocess.STDOUT
_get_output = lambda o,e: o _get_output = lambda o, e: o
# Iterate over commands # Iterate over commands
for cmd in cmds: for cmd in cmds:

View file

@ -16,11 +16,12 @@ class JSONExtendedEncoder(JSONEncoder):
- set: converted into list - set: converted into list
""" """
def default(self, o): def default(self, o):
"""Return a serializable object""" """Return a serializable object"""
# Convert compatible containers into list # Convert compatible containers into list
if isinstance(o, set) or ( if isinstance(o, set) or (
hasattr(o, '__iter__') and hasattr(o, 'next')): hasattr(o, '__iter__') and hasattr(o, 'next')):
return list(o) return list(o)
# Return the repr for object that json can't encode # Return the repr for object that json can't encode

View file

@ -14,6 +14,7 @@ class AsynchronousFileReader(Process):
http://stefaanlippens.net/python-asynchronous-subprocess-pipe-reading http://stefaanlippens.net/python-asynchronous-subprocess-pipe-reading
""" """
def __init__(self, fd, queue): def __init__(self, fd, queue):
assert hasattr(queue, 'put') assert hasattr(queue, 'put')
assert hasattr(queue, 'empty') assert hasattr(queue, 'empty')
@ -48,6 +49,7 @@ def consume_queue(queue, callback):
break break
callback(line) callback(line)
def async_file_reading(fd, callback): def async_file_reading(fd, callback):
"""Helper which instantiate and run an AsynchronousFileReader.""" """Helper which instantiate and run an AsynchronousFileReader."""
queue = SimpleQueue() queue = SimpleQueue()

View file

@ -38,6 +38,7 @@ def search(pattern, text, count=0, flags=0):
return match[0] return match[0]
return match return match
def searchf(pattern, path, count=0, flags=re.MULTILINE): def searchf(pattern, path, count=0, flags=re.MULTILINE):
"""Search for pattern in a file """Search for pattern in a file