test_ok1/_pytest/mark/evaluate.py

122 lines
3.7 KiB
Python
Raw Normal View History

2018-02-22 21:05:10 +08:00
import os
import six
import sys
import platform
2018-02-22 21:05:10 +08:00
import traceback
from ..outcomes import fail, TEST_OUTCOME
def cached_eval(config, expr, d):
2018-05-23 22:48:46 +08:00
if not hasattr(config, "_evalcache"):
2018-02-22 21:05:10 +08:00
config._evalcache = {}
try:
return config._evalcache[expr]
except KeyError:
import _pytest._code
2018-05-23 22:48:46 +08:00
2018-02-22 21:05:10 +08:00
exprcode = _pytest._code.compile(expr, mode="eval")
config._evalcache[expr] = x = eval(exprcode, d)
return x
class MarkEvaluator(object):
2018-05-23 22:48:46 +08:00
2018-02-22 21:05:10 +08:00
def __init__(self, item, name):
self.item = item
self._marks = None
self._mark = None
self._mark_name = name
def __bool__(self):
# dont cache here to prevent staleness
return bool(self._get_marks())
2018-05-23 22:48:46 +08:00
2018-02-22 21:05:10 +08:00
__nonzero__ = __bool__
def wasvalid(self):
2018-05-23 22:48:46 +08:00
return not hasattr(self, "exc")
2018-02-22 21:05:10 +08:00
def _get_marks(self):
return list(self.item.iter_markers(name=self._mark_name))
2018-02-22 21:05:10 +08:00
def invalidraise(self, exc):
2018-05-23 22:48:46 +08:00
raises = self.get("raises")
2018-02-22 21:05:10 +08:00
if not raises:
return
return not isinstance(exc, raises)
def istrue(self):
try:
return self._istrue()
except TEST_OUTCOME:
self.exc = sys.exc_info()
if isinstance(self.exc[1], SyntaxError):
2018-05-23 22:48:46 +08:00
msg = [" " * (self.exc[1].offset + 4) + "^"]
2018-02-22 21:05:10 +08:00
msg.append("SyntaxError: invalid syntax")
else:
msg = traceback.format_exception_only(*self.exc[:2])
2018-05-23 22:48:46 +08:00
fail(
"Error evaluating %r expression\n"
" %s\n"
"%s" % (self._mark_name, self.expr, "\n".join(msg)),
pytrace=False,
)
2018-02-22 21:05:10 +08:00
def _getglobals(self):
2018-05-23 22:48:46 +08:00
d = {"os": os, "sys": sys, "platform": platform, "config": self.item.config}
if hasattr(self.item, "obj"):
2018-02-22 21:05:10 +08:00
d.update(self.item.obj.__globals__)
return d
def _istrue(self):
2018-05-23 22:48:46 +08:00
if hasattr(self, "result"):
2018-02-22 21:05:10 +08:00
return self.result
self._marks = self._get_marks()
if self._marks:
self.result = False
for mark in self._marks:
self._mark = mark
2018-05-23 22:48:46 +08:00
if "condition" in mark.kwargs:
args = (mark.kwargs["condition"],)
2018-02-22 21:05:10 +08:00
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
2018-05-23 22:48:46 +08:00
msg = "you need to specify reason=STRING " "when using booleans as conditions."
2018-02-22 21:05:10 +08:00
fail(msg)
result = bool(expr)
if result:
self.result = True
2018-05-23 22:48:46 +08:00
self.reason = mark.kwargs.get("reason", None)
2018-02-22 21:05:10 +08:00
self.expr = expr
return self.result
if not args:
self.result = True
2018-05-23 22:48:46 +08:00
self.reason = mark.kwargs.get("reason", None)
2018-02-22 21:05:10 +08:00
return self.result
return False
def get(self, attr, default=None):
if self._mark is None:
return default
return self._mark.kwargs.get(attr, default)
def getexplanation(self):
2018-05-23 22:48:46 +08:00
expl = getattr(self, "reason", None) or self.get("reason", None)
2018-02-22 21:05:10 +08:00
if not expl:
2018-05-23 22:48:46 +08:00
if not hasattr(self, "expr"):
2018-02-22 21:05:10 +08:00
return ""
else:
return "condition: " + str(self.expr)
return expl