mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
[mod] autopep8
This commit is contained in:
parent
c0291ff479
commit
897ad08183
14 changed files with 192 additions and 163 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"""
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue