Skip to content

Commit

Permalink
:fix: resolver.registry UTs
Browse files Browse the repository at this point in the history
  • Loading branch information
b3j0f committed Feb 26, 2016
1 parent d10201d commit 1020bda
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 452 deletions.
46 changes: 36 additions & 10 deletions b3j0f/conf/model/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class Parameter(ModelElement):

__slots__ = (
'_name', 'ptype', 'parser', '_svalue', '_value', '_error', 'conf',
'local', 'scope', 'configurable', 'serializer'
'local', 'scope', 'configurable', 'serializer', 'besteffort'
) + ModelElement.__slots__

class Error(Exception):
Expand All @@ -142,12 +142,16 @@ class Error(Exception):
DEFAULT_NAME = re_compile('.*')
DEFAULT_VTYPE = object #: default ptype.
DEFAULT_LOCAL = True #: default local value.
DEFAULT_BESTEFFORT = False #: default best effort.
DEFAULT_SAFE = True #: default safe
DEFAULT_SCOPE = None #: default scope

def __init__(
self, name=DEFAULT_NAME, ptype=DEFAULT_VTYPE, value=None,
parser=parse, serializer=serialize, svalue=None,
conf=None, configurable=None,
local=DEFAULT_LOCAL, scope=None,
local=DEFAULT_LOCAL, scope=DEFAULT_SCOPE, safe=DEFAULT_SAFE,
besteffort=DEFAULT_BESTEFFORT,
*args, **kwargs
):
"""
Expand Down Expand Up @@ -185,14 +189,18 @@ def __init__(
# init public attributes
self.parser = parser
self.serializer = serializer
self.name = name
self.ptype = ptype
self.conf = conf
self.configurable = configurable
self.local = local
self.scope = scope
self.besteffort = besteffort
self.safe = safe

# init setters
self.name = name
self.svalue = svalue
self.value = value
self.scope = scope

def __eq__(self, other):
"""
Expand Down Expand Up @@ -318,22 +326,26 @@ def svalue(self, value):

def resolve(
self,
configurable=None, conf=None, scope=None,
parser=None, error=True, safe=True
configurable=None, conf=None, scope=None, _type=None,
parser=None, error=True, svalue=None,
safe=None, besteffort=None
):
"""Resolve this parameter value related to a configurable and a
configuration.
Save error in this attribute `error` in case of failure.
:param str svalue: serialized value too resolve. Default is this svalue.
:param Configurable configurable: configurable to use for foreign
parameter resolution.
:param Configuration conf: configuration to use for
cross-value resolution.
:param dict scope: variables to use for local expression evaluation.
:param type _type: return type. Default is this vtype.
:param parser: specific parser to use. Default this parser.
:param bool error: raise an error if True (False by default).
:param bool safe: if True (default) resolve without builtins functions.
:param bool besteffort: best effort flag. Default is this besteffort.
:return: newly resolved value.
:raises: Parameter.Error for any raised exception.
"""
Expand All @@ -345,9 +357,15 @@ def resolve(

self._error = None # nonify error.

if _type is None:
_type = self.ptype

if parser is None: # init parser
parser = self.parser

if svalue is None:
svalue = self._svalue

if conf is None: # init conf
conf = self.conf

Expand All @@ -361,12 +379,18 @@ def resolve(
scope, selfscope = deepcopy(self.scope), scope
scope.update(selfscope)

if safe is None:
safe = self.safe

if besteffort is None:
besteffort = self.besteffort

# parse value if str and if parser exists
try:
result = self._value = parser(
svalue=self._svalue, conf=conf,
configurable=configurable, _type=self.ptype,
scope=scope, safe=safe
svalue=svalue, conf=conf,
configurable=configurable, _type=_type,
scope=scope, safe=safe, besteffort=besteffort
)

except Exception as ex:
Expand Down Expand Up @@ -441,7 +465,9 @@ def copy(self, cleaned=False, *args, **kwargs):
:return: new parameter.
"""

props = ('name', 'parser', 'local', 'ptype', 'conf', 'scope')
props = (
'name', 'parser', 'local', 'ptype', 'conf', 'scope', 'besteffort'
)
for prop in props:
kwargs.setdefault(prop, getattr(self, prop))

Expand Down
8 changes: 3 additions & 5 deletions b3j0f/conf/parser/resolver/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ class _MetaExprResolver(type):
Register automatically ExprResolver classes."""

def __new__(mcs, *args, **kwargs):
def __new__(cls, *args, **kwargs):

result = type.__new__(mcs, *args, **kwargs)
result = super(_MetaExprResolver, cls).__new__(cls, *args, **kwargs)

register(exprresolver=result)

Expand All @@ -72,10 +72,8 @@ class ExprResolver(object):
All sub classes are automatically registered."""

__registry__ = None #: registry name.

def __call__(
self, expr, safe=True, tostr=False, scope=None, besteffort=True
self, expr, safe=True, tostr=False, scope=None, besteffort=True
):
"""Resolve input expression.
Expand Down
60 changes: 32 additions & 28 deletions b3j0f/conf/parser/resolver/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
from b3j0f.utils.path import lookup
from b3j0f.utils.version import OrderedDict

from inspect import isroutine, isclass
from inspect import isclass

from six import string_types

Expand All @@ -70,8 +70,7 @@
if EXPRRES_PATH: # load modules
loadresolvers(EXPRRES_PATH.split(','))


__RESOLVER__ = '__resolver__' #: resolver name for class resolvers.
__RESOLVER__ = '__resolver__' #: resolver name for class IoC


class ResolverRegistry(object):
Expand Down Expand Up @@ -158,6 +157,7 @@ def loadresolvers(paths):
for path in paths:
lookup(path)


def register(name=None, exprresolver=None, params=None, reg=None):
"""Register an expression resolver.
Expand Down Expand Up @@ -212,38 +212,40 @@ def _register(exprresolver, _name=name, _params=params):
:param exprresolver: function/class able to resolve an expression.
:param str _name: private parameter used to set the name.
:param dict _params: private parameter used to set resolver class
constructor parameters.
"""
constructor parameters."""

if _name is None:
_name = getname(exprresolver)
_exprresolver = exprresolver

if isclass(exprresolver): # try to instanciate exprresolver
if _params is None:
_params = {}
exprresolver = exprresolver(**_params)

reg.resolvers[_name] = exprresolver
_exprresolver = _exprresolver(**_params)

if _name is None:
_name = getname(exprresolver)

reg.resolvers[_name] = _exprresolver

if reg.default is None:
reg.default = _name

return exprresolver

if name is None:
name = getname(exprresolver)

if reg is None:
reg = _RESOLVER_REGISTRY

if exprresolver is None:
return _register
result = _register

else:
if name is None:
name = getname(exprresolver)
result = name
_register(exprresolver)

reg.resolvers[name] = exprresolver

return name
return result


def defaultname(name=None):
Expand All @@ -268,7 +270,7 @@ def names():

return _RESOLVER_REGISTRY.names

def resolve(**kwargs):
def resolve(*args, **kwargs):
"""Resolve an expression with possibly a dedicated expression resolvers.
:param str name: expression resolver registered name. Default is the
Expand All @@ -283,26 +285,28 @@ def resolve(**kwargs):
name does not exist in expression resolvers.
"""

return _RESOLVER_REGISTRY.resolve(**kwargs)
return _RESOLVER_REGISTRY.resolve(*args, **kwargs)

def getname(exprresolver):
"""Get expression resolver name.
Expression resolver name is given by the attribute __resolver__.
If not exist, then the it is given by the attribute __name__.
Otherwise, given by the __class__.__name__ attribute.
:raises: TypeError if exprresolver is not callable."""

result = None

if isroutine(exprresolver):
result = exprresolver.__name__

elif isclass(exprresolver):
result = getattr(exprresolver, __RESOLVER__, exprresolver.__name__)

elif callable(exprresolver):
cls = exprresolver.__class__
result = getname(cls)

else:
if not callable(exprresolver):
raise TypeError('Expression resolver must be a callable object.')

result = getattr(
exprresolver, __RESOLVER__, getattr(
exprresolver, '__name__', getattr(
exprresolver.__class__, '__name__'
)
)
)

return result

0 comments on commit 1020bda

Please sign in to comment.