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,40 +116,51 @@ 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:
self.result = False def needs_eval(mark):
# "holder" might be a MarkInfo or a MarkDecorator; only return mark.args or 'condition' in mark.kwargs
# MarkInfo keeps track of all parameters it received in an
# _arglist attribute if self._marks:
marks = getattr(self.holder, '_marks', None) \ self.result = False
or [self.holder.mark] # "holder" might be a MarkInfo or a MarkDecorator; only
for _, args, kwargs in marks: # MarkInfo keeps track of all parameters it received in an
if 'condition' in kwargs: # _arglist attribute
args = (kwargs['condition'],) for mark in self._marks:
for expr in args: self._mark = mark
if 'condition' in mark.kwargs:
args = (mark.kwargs['condition'],)
else:
args = mark.args
for expr in args:
self.expr = expr
if isinstance(expr, six.string_types):
d = self._getglobals()
result = cached_eval(self.item.config, expr, d)
else:
if "reason" not in mark.kwargs:
# XXX better be checked at collection time
msg = "you need to specify reason=STRING " \
"when using booleans as conditions."
fail(msg)
result = bool(expr)
if result:
self.result = True
self.reason = mark.kwargs.get('reason', None)
self.expr = expr self.expr = expr
if isinstance(expr, six.string_types): return self.result
d = self._getglobals()
result = cached_eval(self.item.config, expr, d) if not args:
else: self.result = True
if "reason" not in kwargs: self.reason = mark.kwargs.get('reason', None)
# XXX better be checked at collection time return self.result
msg = "you need to specify reason=STRING " \ return False
"when using booleans as conditions."
fail(msg)
result = bool(expr)
if result:
self.result = True
self.reason = kwargs.get('reason', None)
self.expr = expr
return self.result
else:
self.result = True
return getattr(self, 'result', 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)