[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
## Package functions
# Package functions
def init(logging_config=None, **kwargs):
"""Package initialization
@ -68,7 +68,7 @@ def init(logging_config=None, **kwargs):
sys.path.insert(0, pkg.libdir)
## Easy access to interfaces
# Easy access to interfaces
def api(namespaces, host='localhost', port=80, routes={},
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'))
return 0
def cli(namespaces, args, use_cache=True, output_as=None,
password=None, timeout=None, parser_kwargs={}):
"""Command line interface

View file

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

View file

@ -27,6 +27,7 @@ class BaseAuthenticator(object):
- name -- The authenticator profile name
"""
def __init__(self, name):
self._name = name
@ -35,8 +36,7 @@ class BaseAuthenticator(object):
"""Return the name of the authenticator instance"""
return self._name
## Virtual properties
# Virtual properties
# Each authenticator classes must implement these properties.
"""The vendor name of the authenticator"""
@ -45,11 +45,10 @@ class BaseAuthenticator(object):
@property
def is_authenticated(self):
"""Either the instance is authenticated or not"""
raise NotImplementedError("derived class '%s' must override this property" % \
self.__class__.__name__)
raise NotImplementedError("derived class '%s' must override this property" %
self.__class__.__name__)
## Virtual methods
# Virtual methods
# Each authenticator classes must implement these methods.
def authenticate(password=None):
@ -62,11 +61,10 @@ class BaseAuthenticator(object):
- password -- A clear text password
"""
raise NotImplementedError("derived class '%s' must override this method" % \
self.__class__.__name__)
raise NotImplementedError("derived class '%s' must override this method" %
self.__class__.__name__)
## Authentication methods
# Authentication methods
def __call__(self, password=None, token=None):
"""Attempt to authenticate
@ -127,8 +125,7 @@ class BaseAuthenticator(object):
return self
## Private methods
# Private methods
def _open_sessionfile(self, session_id, mode='r'):
"""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
"""
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)
super(Authenticator, self).__init__(name)
@ -48,8 +49,7 @@ class Authenticator(BaseAuthenticator):
if self.con:
self.con.unbind_s()
## Implement virtual properties
# Implement virtual properties
vendor = 'ldap'
@ -65,8 +65,7 @@ class Authenticator(BaseAuthenticator):
return True
return False
## Implement virtual methods
# Implement virtual methods
def authenticate(self, password):
try:
@ -83,8 +82,7 @@ class Authenticator(BaseAuthenticator):
else:
self.con = con
## Additional LDAP methods
# Additional LDAP methods
# TODO: Review these methods
def search(self, base=None, filter='(objectClass=*)', attrs=['dn']):
@ -108,7 +106,7 @@ class Authenticator(BaseAuthenticator):
try:
result = self.con.search_s(base, ldap.SCOPE_SUBTREE, filter, attrs)
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)
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
@ -139,7 +137,7 @@ class Authenticator(BaseAuthenticator):
try:
self.con.add_s(dn, ldif)
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)
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
else:
@ -189,7 +187,7 @@ class Authenticator(BaseAuthenticator):
self.con.modify_ext_s(dn, ldif)
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)
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
else:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
import os
import logging
from logging import *
from logging import addLevelName, setLoggerClass, Logger, getLogger
# Global configuration and functions -----------------------------------
@ -31,6 +31,7 @@ DEFAULT_LOGGING = {
},
}
def configure_logging(logging_config=None):
"""Configure logging with default and optionally given configuration
@ -49,6 +50,7 @@ def configure_logging(logging_config=None):
if logging_config:
dictConfig(logging_config)
def getHandlersByClass(classinfo, limit=0):
"""Retrieve registered handlers of a given class."""
handlers = []
@ -59,7 +61,7 @@ def getHandlersByClass(classinfo, limit=0):
return o
handlers.append(o)
if limit != 0 and len(handlers) > limit:
return handlers[:limit-1]
return handlers[:limit - 1]
return handlers
@ -111,9 +113,11 @@ class MoulinetteLogger(Logger):
pid = os.getpid()
action_id = 0
def _get_action_id():
return '%d.%d' % (pid, action_id)
def start_action_logging():
"""Configure logging for a new action
@ -126,6 +130,7 @@ def start_action_logging():
return _get_action_id()
def getActionLogger(name=None, logger=None, action_id=None):
"""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.
Either a name or a logger must be specified.
"""
if not name and not logger:
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.
"""
def __init__(self, message_key='fmessage', strict=False):
self.message_key = message_key
self.strict = strict

View file

@ -1,9 +1,5 @@
import time
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
@ -145,17 +141,17 @@ def check_commands(cmds, raise_on_error=False, callback=None,
raise CalledProcessError(r, c, o)
else:
# Continue commands execution
callback = lambda r,c,o: True
callback = lambda r, c, o: True
elif not callable(callback):
raise ValueError('callback argument must be callable')
# Manage stderr
if separate_stderr:
_stderr = subprocess.PIPE
_get_output = lambda o,e: (o,e)
_get_output = lambda o, e: (o, e)
else:
_stderr = subprocess.STDOUT
_get_output = lambda o,e: o
_get_output = lambda o, e: o
# Iterate over commands
for cmd in cmds:

View file

@ -16,11 +16,12 @@ class JSONExtendedEncoder(JSONEncoder):
- set: converted into list
"""
def default(self, o):
"""Return a serializable object"""
# Convert compatible containers into list
if isinstance(o, set) or (
hasattr(o, '__iter__') and hasattr(o, 'next')):
hasattr(o, '__iter__') and hasattr(o, 'next')):
return list(o)
# 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
"""
def __init__(self, fd, queue):
assert hasattr(queue, 'put')
assert hasattr(queue, 'empty')
@ -48,6 +49,7 @@ def consume_queue(queue, callback):
break
callback(line)
def async_file_reading(fd, callback):
"""Helper which instantiate and run an AsynchronousFileReader."""
queue = SimpleQueue()

View file

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