aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '_pytest/skipping.py')
-rw-r--r--_pytest/skipping.py61
1 files changed, 47 insertions, 14 deletions
diff --git a/_pytest/skipping.py b/_pytest/skipping.py
index 106c8518c3..fe69f295e7 100644
--- a/_pytest/skipping.py
+++ b/_pytest/skipping.py
@@ -1,6 +1,7 @@
""" support for skip/xfail functions and markers. """
import py, pytest
+import sys
def pytest_addoption(parser):
group = parser.getgroup("general")
@@ -32,9 +33,39 @@ class MarkEvaluator:
return bool(self.holder)
__nonzero__ = __bool__
+ def wasvalid(self):
+ return not hasattr(self, 'exc')
+
def istrue(self):
+ try:
+ return self._istrue()
+ except KeyboardInterrupt:
+ raise
+ except:
+ self.exc = sys.exc_info()
+ if isinstance(self.exc[1], SyntaxError):
+ msg = [" " * (self.exc[1].offset + 4) + "^",]
+ msg.append("SyntaxError: invalid syntax")
+ else:
+ msg = py.std.traceback.format_exception_only(*self.exc[:2])
+ pytest.fail("Error evaluating %r expression\n"
+ " %s\n"
+ "%s"
+ %(self.name, self.expr, "\n".join(msg)),
+ pytrace=False)
+
+ def _getglobals(self):
+ d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config}
+ func = self.item.obj
+ try:
+ d.update(func.__globals__)
+ except AttributeError:
+ d.update(func.func_globals)
+ return d
+
+ def _istrue(self):
if self.holder:
- d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config}
+ d = self._getglobals()
if self.holder.args:
self.result = False
for expr in self.holder.args:
@@ -42,7 +73,7 @@ class MarkEvaluator:
if isinstance(expr, str):
result = cached_eval(self.item.config, expr, d)
else:
- result = expr
+ pytest.fail("expression is not a string")
if result:
self.result = True
self.expr = expr
@@ -60,7 +91,7 @@ class MarkEvaluator:
if not hasattr(self, 'expr'):
return ""
else:
- return "condition: " + self.expr
+ return "condition: " + str(self.expr)
return expl
@@ -99,16 +130,17 @@ def pytest_runtest_makereport(__multicall__, item, call):
return rep
rep = __multicall__.execute()
evalxfail = item._evalxfail
- if not item.config.option.runxfail and evalxfail.istrue():
- if call.excinfo:
- rep.outcome = "skipped"
- rep.keywords['xfail'] = evalxfail.getexplanation()
- elif call.when == "call":
- rep.outcome = "failed"
- rep.keywords['xfail'] = evalxfail.getexplanation()
- else:
- if 'xfail' in rep.keywords:
- del rep.keywords['xfail']
+ if not item.config.option.runxfail:
+ if evalxfail.wasvalid() and evalxfail.istrue():
+ if call.excinfo:
+ rep.outcome = "skipped"
+ rep.keywords['xfail'] = evalxfail.getexplanation()
+ elif call.when == "call":
+ rep.outcome = "failed"
+ rep.keywords['xfail'] = evalxfail.getexplanation()
+ return rep
+ if 'xfail' in rep.keywords:
+ del rep.keywords['xfail']
return rep
# called by terminalreporter progress reporting
@@ -179,7 +211,8 @@ def cached_eval(config, expr, d):
except KeyError:
#import sys
#print >>sys.stderr, ("cache-miss: %r" % expr)
- config._evalcache[expr] = x = eval(expr, d)
+ exprcode = py.code.compile(expr, mode="eval")
+ config._evalcache[expr] = x = eval(exprcode, d)
return x