resuffle markevaluator internal structure

This commit is contained in:
Ronny Pfannschmidt 2017-09-14 09:31:07 +02:00
parent 9ad2b75038
commit 8480075f01
1 changed files with 59 additions and 39 deletions

View File

@ -60,22 +60,31 @@ def pytest_configure(config):
) )
class MarkEvaluator: class MarkEvaluator(object):
def __init__(self, item, name): def __init__(self, item, name):
self.item = item self.item = item
self.name = name self._marks = None
self._mark = None
@property self._repr_name = name
def holder(self):
return self.item.keywords.get(self.name)
def __bool__(self): def __bool__(self):
return bool(self.holder) self._marks = self._get_marks()
return bool(self._marks)
__nonzero__ = __bool__ __nonzero__ = __bool__
def wasvalid(self): def wasvalid(self):
return not hasattr(self, 'exc') return not hasattr(self, 'exc')
def _get_marks(self):
keyword = self.item.keywords.get(self._repr_name)
if isinstance(keyword, MarkDecorator):
return [keyword.mark]
elif isinstance(keyword, MarkInfo):
return [x.combined for x in keyword]
else:
return []
def invalidraise(self, exc): def invalidraise(self, exc):
raises = self.get('raises') raises = self.get('raises')
if not raises: if not raises:
@ -95,7 +104,7 @@ class MarkEvaluator:
fail("Error evaluating %r expression\n" fail("Error evaluating %r expression\n"
" %s\n" " %s\n"
"%s" "%s"
% (self.name, self.expr, "\n".join(msg)), % (self._repr_name, self.expr, "\n".join(msg)),
pytrace=False) pytrace=False)
def _getglobals(self): def _getglobals(self):
@ -107,24 +116,30 @@ class MarkEvaluator:
def _istrue(self): def _istrue(self):
if hasattr(self, 'result'): if hasattr(self, 'result'):
return self.result return self.result
if self.holder: self._marks = self._get_marks()
if self.holder.args or 'condition' in self.holder.kwargs:
def needs_eval(mark):
return mark.args or 'condition' in mark.kwargs
if self._marks:
self.result = False self.result = False
# "holder" might be a MarkInfo or a MarkDecorator; only # "holder" might be a MarkInfo or a MarkDecorator; only
# MarkInfo keeps track of all parameters it received in an # MarkInfo keeps track of all parameters it received in an
# _arglist attribute # _arglist attribute
marks = getattr(self.holder, '_marks', None) \ for mark in self._marks:
or [self.holder.mark] self._mark = mark
for _, args, kwargs in marks: if 'condition' in mark.kwargs:
if 'condition' in kwargs: args = (mark.kwargs['condition'],)
args = (kwargs['condition'],) else:
args = mark.args
for expr in args: for expr in args:
self.expr = expr self.expr = expr
if isinstance(expr, six.string_types): if isinstance(expr, six.string_types):
d = self._getglobals() d = self._getglobals()
result = cached_eval(self.item.config, expr, d) result = cached_eval(self.item.config, expr, d)
else: else:
if "reason" not in kwargs: if "reason" not in mark.kwargs:
# XXX better be checked at collection time # XXX better be checked at collection time
msg = "you need to specify reason=STRING " \ msg = "you need to specify reason=STRING " \
"when using booleans as conditions." "when using booleans as conditions."
@ -132,15 +147,20 @@ class MarkEvaluator:
result = bool(expr) result = bool(expr)
if result: if result:
self.result = True self.result = True
self.reason = kwargs.get('reason', None) self.reason = mark.kwargs.get('reason', None)
self.expr = expr self.expr = expr
return self.result return self.result
else:
if not args:
self.result = True self.result = True
return getattr(self, 'result', False) self.reason = mark.kwargs.get('reason', None)
return self.result
return False
def get(self, attr, default=None): def get(self, attr, default=None):
return self.holder.kwargs.get(attr, default) if self._mark is None:
return default
return self._mark.kwargs.get(attr, default)
def getexplanation(self): def getexplanation(self):
expl = getattr(self, 'reason', None) or self.get('reason', None) expl = getattr(self, 'reason', None) or self.get('reason', None)