Coverage for /usr/local/lib/python3.7/site-packages/_pytest/mark/evaluate.py : 13%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import os
2import platform
3import sys
4import traceback
6from ..outcomes import fail
7from ..outcomes import TEST_OUTCOME
10def cached_eval(config, expr, d):
11 if not hasattr(config, "_evalcache"):
12 config._evalcache = {}
13 try:
14 return config._evalcache[expr]
15 except KeyError:
16 import _pytest._code
18 exprcode = _pytest._code.compile(expr, mode="eval")
19 config._evalcache[expr] = x = eval(exprcode, d)
20 return x
23class MarkEvaluator:
24 def __init__(self, item, name):
25 self.item = item
26 self._marks = None
27 self._mark = None
28 self._mark_name = name
30 def __bool__(self):
31 # don't cache here to prevent staleness
32 return bool(self._get_marks())
34 __nonzero__ = __bool__
36 def wasvalid(self):
37 return not hasattr(self, "exc")
39 def _get_marks(self):
40 return list(self.item.iter_markers(name=self._mark_name))
42 def invalidraise(self, exc):
43 raises = self.get("raises")
44 if not raises:
45 return
46 return not isinstance(exc, raises)
48 def istrue(self):
49 try:
50 return self._istrue()
51 except TEST_OUTCOME:
52 self.exc = sys.exc_info()
53 if isinstance(self.exc[1], SyntaxError):
54 # TODO: Investigate why SyntaxError.offset is Optional, and if it can be None here.
55 assert self.exc[1].offset is not None
56 msg = [" " * (self.exc[1].offset + 4) + "^"]
57 msg.append("SyntaxError: invalid syntax")
58 else:
59 msg = traceback.format_exception_only(*self.exc[:2])
60 fail(
61 "Error evaluating %r expression\n"
62 " %s\n"
63 "%s" % (self._mark_name, self.expr, "\n".join(msg)),
64 pytrace=False,
65 )
67 def _getglobals(self):
68 d = {"os": os, "sys": sys, "platform": platform, "config": self.item.config}
69 if hasattr(self.item, "obj"):
70 d.update(self.item.obj.__globals__)
71 return d
73 def _istrue(self):
74 if hasattr(self, "result"):
75 return self.result
76 self._marks = self._get_marks()
78 if self._marks:
79 self.result = False
80 for mark in self._marks:
81 self._mark = mark
82 if "condition" in mark.kwargs:
83 args = (mark.kwargs["condition"],)
84 else:
85 args = mark.args
87 for expr in args:
88 self.expr = expr
89 if isinstance(expr, str):
90 d = self._getglobals()
91 result = cached_eval(self.item.config, expr, d)
92 else:
93 if "reason" not in mark.kwargs:
94 # XXX better be checked at collection time
95 msg = (
96 "you need to specify reason=STRING "
97 "when using booleans as conditions."
98 )
99 fail(msg)
100 result = bool(expr)
101 if result:
102 self.result = True
103 self.reason = mark.kwargs.get("reason", None)
104 self.expr = expr
105 return self.result
107 if not args:
108 self.result = True
109 self.reason = mark.kwargs.get("reason", None)
110 return self.result
111 return False
113 def get(self, attr, default=None):
114 if self._mark is None:
115 return default
116 return self._mark.kwargs.get(attr, default)
118 def getexplanation(self):
119 expl = getattr(self, "reason", None) or self.get("reason", None)
120 if not expl:
121 if not hasattr(self, "expr"):
122 return ""
123 else:
124 return "condition: " + str(self.expr)
125 return expl