127 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
| import os
 | |
| import six
 | |
| import sys
 | |
| import platform
 | |
| import traceback
 | |
| 
 | |
| from . import MarkDecorator, MarkInfo
 | |
| from ..outcomes import fail, TEST_OUTCOME
 | |
| 
 | |
| 
 | |
| def cached_eval(config, expr, d):
 | |
|     if not hasattr(config, '_evalcache'):
 | |
|         config._evalcache = {}
 | |
|     try:
 | |
|         return config._evalcache[expr]
 | |
|     except KeyError:
 | |
|         import _pytest._code
 | |
|         exprcode = _pytest._code.compile(expr, mode="eval")
 | |
|         config._evalcache[expr] = x = eval(exprcode, d)
 | |
|         return x
 | |
| 
 | |
| 
 | |
| class MarkEvaluator(object):
 | |
|     def __init__(self, item, name):
 | |
|         self.item = item
 | |
|         self._marks = None
 | |
|         self._mark = None
 | |
|         self._mark_name = name
 | |
| 
 | |
|     def __bool__(self):
 | |
|         self._marks = self._get_marks()
 | |
|         return bool(self._marks)
 | |
|     __nonzero__ = __bool__
 | |
| 
 | |
|     def wasvalid(self):
 | |
|         return not hasattr(self, 'exc')
 | |
| 
 | |
|     def _get_marks(self):
 | |
| 
 | |
|         keyword = self.item.keywords.get(self._mark_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):
 | |
|         raises = self.get('raises')
 | |
|         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):
 | |
|                 msg = [" " * (self.exc[1].offset + 4) + "^", ]
 | |
|                 msg.append("SyntaxError: invalid syntax")
 | |
|             else:
 | |
|                 msg = traceback.format_exception_only(*self.exc[:2])
 | |
|             fail("Error evaluating %r expression\n"
 | |
|                  "    %s\n"
 | |
|                  "%s"
 | |
|                  % (self._mark_name, self.expr, "\n".join(msg)),
 | |
|                  pytrace=False)
 | |
| 
 | |
|     def _getglobals(self):
 | |
|         d = {'os': os, 'sys': sys, 'platform': platform, 'config': self.item.config}
 | |
|         if hasattr(self.item, 'obj'):
 | |
|             d.update(self.item.obj.__globals__)
 | |
|         return d
 | |
| 
 | |
|     def _istrue(self):
 | |
|         if hasattr(self, 'result'):
 | |
|             return self.result
 | |
|         self._marks = self._get_marks()
 | |
| 
 | |
|         if self._marks:
 | |
|             self.result = False
 | |
|             for mark in self._marks:
 | |
|                 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
 | |
|                         return self.result
 | |
| 
 | |
|                 if not args:
 | |
|                     self.result = True
 | |
|                     self.reason = mark.kwargs.get('reason', None)
 | |
|                     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):
 | |
|         expl = getattr(self, 'reason', None) or self.get('reason', None)
 | |
|         if not expl:
 | |
|             if not hasattr(self, 'expr'):
 | |
|                 return ""
 | |
|             else:
 | |
|                 return "condition: " + str(self.expr)
 | |
|         return expl
 |