Merge pull request #1267 from nicoddemus/remove-pre-2.6
Remove pre-2.6 support code and docs (including obsolete oldinterpret module)
This commit is contained in:
commit
379562107e
|
@ -14,6 +14,10 @@
|
||||||
* New `-rp` and `-rP` reporting options give the summary and full output
|
* New `-rp` and `-rP` reporting options give the summary and full output
|
||||||
of passing tests, respectively. Thanks to David Vierra for the PR.
|
of passing tests, respectively. Thanks to David Vierra for the PR.
|
||||||
|
|
||||||
|
* fix #1226: Removed code and documentation for Python 2.5 or lower versions,
|
||||||
|
including removal of the obsolete ``_pytest.assertion.oldinterpret`` module.
|
||||||
|
Thanks Bruno Oliveira for the PR.
|
||||||
|
|
||||||
|
|
||||||
2.8.6.dev1
|
2.8.6.dev1
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -88,9 +88,6 @@ class FastFilesCompleter:
|
||||||
return completion
|
return completion
|
||||||
|
|
||||||
if os.environ.get('_ARGCOMPLETE'):
|
if os.environ.get('_ARGCOMPLETE'):
|
||||||
# argcomplete 0.5.6 is not compatible with python 2.5.6: print/with/format
|
|
||||||
if sys.version_info[:2] < (2, 6):
|
|
||||||
sys.exit(1)
|
|
||||||
try:
|
try:
|
||||||
import argcomplete.completers
|
import argcomplete.completers
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
"""
|
"""
|
||||||
Find intermediate evalutation results in assert statements through builtin AST.
|
Find intermediate evalutation results in assert statements through builtin AST.
|
||||||
This should replace oldinterpret.py eventually.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -1,566 +0,0 @@
|
||||||
import traceback
|
|
||||||
import types
|
|
||||||
import py
|
|
||||||
import sys, inspect
|
|
||||||
from compiler import parse, ast, pycodegen
|
|
||||||
from _pytest.assertion.util import format_explanation, BuiltinAssertionError
|
|
||||||
|
|
||||||
passthroughex = py.builtin._sysex
|
|
||||||
|
|
||||||
class Failure:
|
|
||||||
def __init__(self, node):
|
|
||||||
self.exc, self.value, self.tb = sys.exc_info()
|
|
||||||
self.node = node
|
|
||||||
|
|
||||||
class View(object):
|
|
||||||
"""View base class.
|
|
||||||
|
|
||||||
If C is a subclass of View, then C(x) creates a proxy object around
|
|
||||||
the object x. The actual class of the proxy is not C in general,
|
|
||||||
but a *subclass* of C determined by the rules below. To avoid confusion
|
|
||||||
we call view class the class of the proxy (a subclass of C, so of View)
|
|
||||||
and object class the class of x.
|
|
||||||
|
|
||||||
Attributes and methods not found in the proxy are automatically read on x.
|
|
||||||
Other operations like setting attributes are performed on the proxy, as
|
|
||||||
determined by its view class. The object x is available from the proxy
|
|
||||||
as its __obj__ attribute.
|
|
||||||
|
|
||||||
The view class selection is determined by the __view__ tuples and the
|
|
||||||
optional __viewkey__ method. By default, the selected view class is the
|
|
||||||
most specific subclass of C whose __view__ mentions the class of x.
|
|
||||||
If no such subclass is found, the search proceeds with the parent
|
|
||||||
object classes. For example, C(True) will first look for a subclass
|
|
||||||
of C with __view__ = (..., bool, ...) and only if it doesn't find any
|
|
||||||
look for one with __view__ = (..., int, ...), and then ..., object,...
|
|
||||||
If everything fails the class C itself is considered to be the default.
|
|
||||||
|
|
||||||
Alternatively, the view class selection can be driven by another aspect
|
|
||||||
of the object x, instead of the class of x, by overriding __viewkey__.
|
|
||||||
See last example at the end of this module.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_viewcache = {}
|
|
||||||
__view__ = ()
|
|
||||||
|
|
||||||
def __new__(rootclass, obj, *args, **kwds):
|
|
||||||
self = object.__new__(rootclass)
|
|
||||||
self.__obj__ = obj
|
|
||||||
self.__rootclass__ = rootclass
|
|
||||||
key = self.__viewkey__()
|
|
||||||
try:
|
|
||||||
self.__class__ = self._viewcache[key]
|
|
||||||
except KeyError:
|
|
||||||
self.__class__ = self._selectsubclass(key)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
# attributes not found in the normal hierarchy rooted on View
|
|
||||||
# are looked up in the object's real class
|
|
||||||
return getattr(object.__getattribute__(self, '__obj__'), attr)
|
|
||||||
|
|
||||||
def __viewkey__(self):
|
|
||||||
return self.__obj__.__class__
|
|
||||||
|
|
||||||
def __matchkey__(self, key, subclasses):
|
|
||||||
if inspect.isclass(key):
|
|
||||||
keys = inspect.getmro(key)
|
|
||||||
else:
|
|
||||||
keys = [key]
|
|
||||||
for key in keys:
|
|
||||||
result = [C for C in subclasses if key in C.__view__]
|
|
||||||
if result:
|
|
||||||
return result
|
|
||||||
return []
|
|
||||||
|
|
||||||
def _selectsubclass(self, key):
|
|
||||||
subclasses = list(enumsubclasses(self.__rootclass__))
|
|
||||||
for C in subclasses:
|
|
||||||
if not isinstance(C.__view__, tuple):
|
|
||||||
C.__view__ = (C.__view__,)
|
|
||||||
choices = self.__matchkey__(key, subclasses)
|
|
||||||
if not choices:
|
|
||||||
return self.__rootclass__
|
|
||||||
elif len(choices) == 1:
|
|
||||||
return choices[0]
|
|
||||||
else:
|
|
||||||
# combine the multiple choices
|
|
||||||
return type('?', tuple(choices), {})
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '%s(%r)' % (self.__rootclass__.__name__, self.__obj__)
|
|
||||||
|
|
||||||
|
|
||||||
def enumsubclasses(cls):
|
|
||||||
for subcls in cls.__subclasses__():
|
|
||||||
for subsubclass in enumsubclasses(subcls):
|
|
||||||
yield subsubclass
|
|
||||||
yield cls
|
|
||||||
|
|
||||||
|
|
||||||
class Interpretable(View):
|
|
||||||
"""A parse tree node with a few extra methods."""
|
|
||||||
explanation = None
|
|
||||||
|
|
||||||
def is_builtin(self, frame):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def eval(self, frame):
|
|
||||||
# fall-back for unknown expression nodes
|
|
||||||
try:
|
|
||||||
expr = ast.Expression(self.__obj__)
|
|
||||||
expr.filename = '<eval>'
|
|
||||||
self.__obj__.filename = '<eval>'
|
|
||||||
co = pycodegen.ExpressionCodeGenerator(expr).getCode()
|
|
||||||
result = frame.eval(co)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
self.result = result
|
|
||||||
self.explanation = self.explanation or frame.repr(self.result)
|
|
||||||
|
|
||||||
def run(self, frame):
|
|
||||||
# fall-back for unknown statement nodes
|
|
||||||
try:
|
|
||||||
expr = ast.Module(None, ast.Stmt([self.__obj__]))
|
|
||||||
expr.filename = '<run>'
|
|
||||||
co = pycodegen.ModuleCodeGenerator(expr).getCode()
|
|
||||||
frame.exec_(co)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
|
|
||||||
def nice_explanation(self):
|
|
||||||
return format_explanation(self.explanation)
|
|
||||||
|
|
||||||
|
|
||||||
class Name(Interpretable):
|
|
||||||
__view__ = ast.Name
|
|
||||||
|
|
||||||
def is_local(self, frame):
|
|
||||||
source = '%r in locals() is not globals()' % self.name
|
|
||||||
try:
|
|
||||||
return frame.is_true(frame.eval(source))
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_global(self, frame):
|
|
||||||
source = '%r in globals()' % self.name
|
|
||||||
try:
|
|
||||||
return frame.is_true(frame.eval(source))
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_builtin(self, frame):
|
|
||||||
source = '%r not in locals() and %r not in globals()' % (
|
|
||||||
self.name, self.name)
|
|
||||||
try:
|
|
||||||
return frame.is_true(frame.eval(source))
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def eval(self, frame):
|
|
||||||
super(Name, self).eval(frame)
|
|
||||||
if not self.is_local(frame):
|
|
||||||
self.explanation = self.name
|
|
||||||
|
|
||||||
class Compare(Interpretable):
|
|
||||||
__view__ = ast.Compare
|
|
||||||
|
|
||||||
def eval(self, frame):
|
|
||||||
expr = Interpretable(self.expr)
|
|
||||||
expr.eval(frame)
|
|
||||||
for operation, expr2 in self.ops:
|
|
||||||
if hasattr(self, 'result'):
|
|
||||||
# shortcutting in chained expressions
|
|
||||||
if not frame.is_true(self.result):
|
|
||||||
break
|
|
||||||
expr2 = Interpretable(expr2)
|
|
||||||
expr2.eval(frame)
|
|
||||||
self.explanation = "%s %s %s" % (
|
|
||||||
expr.explanation, operation, expr2.explanation)
|
|
||||||
source = "__exprinfo_left %s __exprinfo_right" % operation
|
|
||||||
try:
|
|
||||||
self.result = frame.eval(source,
|
|
||||||
__exprinfo_left=expr.result,
|
|
||||||
__exprinfo_right=expr2.result)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
expr = expr2
|
|
||||||
|
|
||||||
class And(Interpretable):
|
|
||||||
__view__ = ast.And
|
|
||||||
|
|
||||||
def eval(self, frame):
|
|
||||||
explanations = []
|
|
||||||
for expr in self.nodes:
|
|
||||||
expr = Interpretable(expr)
|
|
||||||
expr.eval(frame)
|
|
||||||
explanations.append(expr.explanation)
|
|
||||||
self.result = expr.result
|
|
||||||
if not frame.is_true(expr.result):
|
|
||||||
break
|
|
||||||
self.explanation = '(' + ' and '.join(explanations) + ')'
|
|
||||||
|
|
||||||
class Or(Interpretable):
|
|
||||||
__view__ = ast.Or
|
|
||||||
|
|
||||||
def eval(self, frame):
|
|
||||||
explanations = []
|
|
||||||
for expr in self.nodes:
|
|
||||||
expr = Interpretable(expr)
|
|
||||||
expr.eval(frame)
|
|
||||||
explanations.append(expr.explanation)
|
|
||||||
self.result = expr.result
|
|
||||||
if frame.is_true(expr.result):
|
|
||||||
break
|
|
||||||
self.explanation = '(' + ' or '.join(explanations) + ')'
|
|
||||||
|
|
||||||
|
|
||||||
# == Unary operations ==
|
|
||||||
keepalive = []
|
|
||||||
for astclass, astpattern in {
|
|
||||||
ast.Not : 'not __exprinfo_expr',
|
|
||||||
ast.Invert : '(~__exprinfo_expr)',
|
|
||||||
}.items():
|
|
||||||
|
|
||||||
class UnaryArith(Interpretable):
|
|
||||||
__view__ = astclass
|
|
||||||
|
|
||||||
def eval(self, frame, astpattern=astpattern):
|
|
||||||
expr = Interpretable(self.expr)
|
|
||||||
expr.eval(frame)
|
|
||||||
self.explanation = astpattern.replace('__exprinfo_expr',
|
|
||||||
expr.explanation)
|
|
||||||
try:
|
|
||||||
self.result = frame.eval(astpattern,
|
|
||||||
__exprinfo_expr=expr.result)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
|
|
||||||
keepalive.append(UnaryArith)
|
|
||||||
|
|
||||||
# == Binary operations ==
|
|
||||||
for astclass, astpattern in {
|
|
||||||
ast.Add : '(__exprinfo_left + __exprinfo_right)',
|
|
||||||
ast.Sub : '(__exprinfo_left - __exprinfo_right)',
|
|
||||||
ast.Mul : '(__exprinfo_left * __exprinfo_right)',
|
|
||||||
ast.Div : '(__exprinfo_left / __exprinfo_right)',
|
|
||||||
ast.Mod : '(__exprinfo_left % __exprinfo_right)',
|
|
||||||
ast.Power : '(__exprinfo_left ** __exprinfo_right)',
|
|
||||||
}.items():
|
|
||||||
|
|
||||||
class BinaryArith(Interpretable):
|
|
||||||
__view__ = astclass
|
|
||||||
|
|
||||||
def eval(self, frame, astpattern=astpattern):
|
|
||||||
left = Interpretable(self.left)
|
|
||||||
left.eval(frame)
|
|
||||||
right = Interpretable(self.right)
|
|
||||||
right.eval(frame)
|
|
||||||
self.explanation = (astpattern
|
|
||||||
.replace('__exprinfo_left', left .explanation)
|
|
||||||
.replace('__exprinfo_right', right.explanation))
|
|
||||||
try:
|
|
||||||
self.result = frame.eval(astpattern,
|
|
||||||
__exprinfo_left=left.result,
|
|
||||||
__exprinfo_right=right.result)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
|
|
||||||
keepalive.append(BinaryArith)
|
|
||||||
|
|
||||||
|
|
||||||
class CallFunc(Interpretable):
|
|
||||||
__view__ = ast.CallFunc
|
|
||||||
|
|
||||||
def is_bool(self, frame):
|
|
||||||
source = 'isinstance(__exprinfo_value, bool)'
|
|
||||||
try:
|
|
||||||
return frame.is_true(frame.eval(source,
|
|
||||||
__exprinfo_value=self.result))
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def eval(self, frame):
|
|
||||||
node = Interpretable(self.node)
|
|
||||||
node.eval(frame)
|
|
||||||
explanations = []
|
|
||||||
vars = {'__exprinfo_fn': node.result}
|
|
||||||
source = '__exprinfo_fn('
|
|
||||||
for a in self.args:
|
|
||||||
if isinstance(a, ast.Keyword):
|
|
||||||
keyword = a.name
|
|
||||||
a = a.expr
|
|
||||||
else:
|
|
||||||
keyword = None
|
|
||||||
a = Interpretable(a)
|
|
||||||
a.eval(frame)
|
|
||||||
argname = '__exprinfo_%d' % len(vars)
|
|
||||||
vars[argname] = a.result
|
|
||||||
if keyword is None:
|
|
||||||
source += argname + ','
|
|
||||||
explanations.append(a.explanation)
|
|
||||||
else:
|
|
||||||
source += '%s=%s,' % (keyword, argname)
|
|
||||||
explanations.append('%s=%s' % (keyword, a.explanation))
|
|
||||||
if self.star_args:
|
|
||||||
star_args = Interpretable(self.star_args)
|
|
||||||
star_args.eval(frame)
|
|
||||||
argname = '__exprinfo_star'
|
|
||||||
vars[argname] = star_args.result
|
|
||||||
source += '*' + argname + ','
|
|
||||||
explanations.append('*' + star_args.explanation)
|
|
||||||
if self.dstar_args:
|
|
||||||
dstar_args = Interpretable(self.dstar_args)
|
|
||||||
dstar_args.eval(frame)
|
|
||||||
argname = '__exprinfo_kwds'
|
|
||||||
vars[argname] = dstar_args.result
|
|
||||||
source += '**' + argname + ','
|
|
||||||
explanations.append('**' + dstar_args.explanation)
|
|
||||||
self.explanation = "%s(%s)" % (
|
|
||||||
node.explanation, ', '.join(explanations))
|
|
||||||
if source.endswith(','):
|
|
||||||
source = source[:-1]
|
|
||||||
source += ')'
|
|
||||||
try:
|
|
||||||
self.result = frame.eval(source, **vars)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
if not node.is_builtin(frame) or not self.is_bool(frame):
|
|
||||||
r = frame.repr(self.result)
|
|
||||||
self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
|
|
||||||
|
|
||||||
class Getattr(Interpretable):
|
|
||||||
__view__ = ast.Getattr
|
|
||||||
|
|
||||||
def eval(self, frame):
|
|
||||||
expr = Interpretable(self.expr)
|
|
||||||
expr.eval(frame)
|
|
||||||
source = '__exprinfo_expr.%s' % self.attrname
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
self.result = frame.eval(source, __exprinfo_expr=expr.result)
|
|
||||||
except AttributeError:
|
|
||||||
# Maybe the attribute name needs to be mangled?
|
|
||||||
if (not self.attrname.startswith("__") or
|
|
||||||
self.attrname.endswith("__")):
|
|
||||||
raise
|
|
||||||
source = "getattr(__exprinfo_expr.__class__, '__name__', '')"
|
|
||||||
class_name = frame.eval(source, __exprinfo_expr=expr.result)
|
|
||||||
mangled_attr = "_" + class_name + self.attrname
|
|
||||||
source = "__exprinfo_expr.%s" % (mangled_attr,)
|
|
||||||
self.result = frame.eval(source, __exprinfo_expr=expr.result)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
self.explanation = '%s.%s' % (expr.explanation, self.attrname)
|
|
||||||
# if the attribute comes from the instance, its value is interesting
|
|
||||||
source = ('hasattr(__exprinfo_expr, "__dict__") and '
|
|
||||||
'%r in __exprinfo_expr.__dict__' % self.attrname)
|
|
||||||
try:
|
|
||||||
from_instance = frame.is_true(
|
|
||||||
frame.eval(source, __exprinfo_expr=expr.result))
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
from_instance = True
|
|
||||||
if from_instance:
|
|
||||||
r = frame.repr(self.result)
|
|
||||||
self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
|
|
||||||
|
|
||||||
# == Re-interpretation of full statements ==
|
|
||||||
|
|
||||||
class Assert(Interpretable):
|
|
||||||
__view__ = ast.Assert
|
|
||||||
|
|
||||||
def run(self, frame):
|
|
||||||
test = Interpretable(self.test)
|
|
||||||
test.eval(frame)
|
|
||||||
# print the result as 'assert <explanation>'
|
|
||||||
self.result = test.result
|
|
||||||
self.explanation = 'assert ' + test.explanation
|
|
||||||
if not frame.is_true(test.result):
|
|
||||||
try:
|
|
||||||
raise BuiltinAssertionError
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
|
|
||||||
class Assign(Interpretable):
|
|
||||||
__view__ = ast.Assign
|
|
||||||
|
|
||||||
def run(self, frame):
|
|
||||||
expr = Interpretable(self.expr)
|
|
||||||
expr.eval(frame)
|
|
||||||
self.result = expr.result
|
|
||||||
self.explanation = '... = ' + expr.explanation
|
|
||||||
# fall-back-run the rest of the assignment
|
|
||||||
ass = ast.Assign(self.nodes, ast.Name('__exprinfo_expr'))
|
|
||||||
mod = ast.Module(None, ast.Stmt([ass]))
|
|
||||||
mod.filename = '<run>'
|
|
||||||
co = pycodegen.ModuleCodeGenerator(mod).getCode()
|
|
||||||
try:
|
|
||||||
frame.exec_(co, __exprinfo_expr=expr.result)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
raise Failure(self)
|
|
||||||
|
|
||||||
class Discard(Interpretable):
|
|
||||||
__view__ = ast.Discard
|
|
||||||
|
|
||||||
def run(self, frame):
|
|
||||||
expr = Interpretable(self.expr)
|
|
||||||
expr.eval(frame)
|
|
||||||
self.result = expr.result
|
|
||||||
self.explanation = expr.explanation
|
|
||||||
|
|
||||||
class Stmt(Interpretable):
|
|
||||||
__view__ = ast.Stmt
|
|
||||||
|
|
||||||
def run(self, frame):
|
|
||||||
for stmt in self.nodes:
|
|
||||||
stmt = Interpretable(stmt)
|
|
||||||
stmt.run(frame)
|
|
||||||
|
|
||||||
|
|
||||||
def report_failure(e):
|
|
||||||
explanation = e.node.nice_explanation()
|
|
||||||
if explanation:
|
|
||||||
explanation = ", in: " + explanation
|
|
||||||
else:
|
|
||||||
explanation = ""
|
|
||||||
sys.stdout.write("%s: %s%s\n" % (e.exc.__name__, e.value, explanation))
|
|
||||||
|
|
||||||
def check(s, frame=None):
|
|
||||||
if frame is None:
|
|
||||||
frame = sys._getframe(1)
|
|
||||||
frame = py.code.Frame(frame)
|
|
||||||
expr = parse(s, 'eval')
|
|
||||||
assert isinstance(expr, ast.Expression)
|
|
||||||
node = Interpretable(expr.node)
|
|
||||||
try:
|
|
||||||
node.eval(frame)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except Failure:
|
|
||||||
e = sys.exc_info()[1]
|
|
||||||
report_failure(e)
|
|
||||||
else:
|
|
||||||
if not frame.is_true(node.result):
|
|
||||||
sys.stderr.write("assertion failed: %s\n" % node.nice_explanation())
|
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
|
||||||
# API / Entry points
|
|
||||||
# #########################################################
|
|
||||||
|
|
||||||
def interpret(source, frame, should_fail=False):
|
|
||||||
module = Interpretable(parse(source, 'exec').node)
|
|
||||||
#print "got module", module
|
|
||||||
if isinstance(frame, types.FrameType):
|
|
||||||
frame = py.code.Frame(frame)
|
|
||||||
try:
|
|
||||||
module.run(frame)
|
|
||||||
except Failure:
|
|
||||||
e = sys.exc_info()[1]
|
|
||||||
return getfailure(e)
|
|
||||||
except passthroughex:
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
traceback.print_exc()
|
|
||||||
if should_fail:
|
|
||||||
return ("(assertion failed, but when it was re-run for "
|
|
||||||
"printing intermediate values, it did not fail. Suggestions: "
|
|
||||||
"compute assert expression before the assert or use --assert=plain)")
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def getmsg(excinfo):
|
|
||||||
if isinstance(excinfo, tuple):
|
|
||||||
excinfo = py.code.ExceptionInfo(excinfo)
|
|
||||||
#frame, line = gettbline(tb)
|
|
||||||
#frame = py.code.Frame(frame)
|
|
||||||
#return interpret(line, frame)
|
|
||||||
|
|
||||||
tb = excinfo.traceback[-1]
|
|
||||||
source = str(tb.statement).strip()
|
|
||||||
x = interpret(source, tb.frame, should_fail=True)
|
|
||||||
if not isinstance(x, str):
|
|
||||||
raise TypeError("interpret returned non-string %r" % (x,))
|
|
||||||
return x
|
|
||||||
|
|
||||||
def getfailure(e):
|
|
||||||
explanation = e.node.nice_explanation()
|
|
||||||
if str(e.value):
|
|
||||||
lines = explanation.split('\n')
|
|
||||||
lines[0] += " << %s" % (e.value,)
|
|
||||||
explanation = '\n'.join(lines)
|
|
||||||
text = "%s: %s" % (e.exc.__name__, explanation)
|
|
||||||
if text.startswith('AssertionError: assert '):
|
|
||||||
text = text[16:]
|
|
||||||
return text
|
|
||||||
|
|
||||||
def run(s, frame=None):
|
|
||||||
if frame is None:
|
|
||||||
frame = sys._getframe(1)
|
|
||||||
frame = py.code.Frame(frame)
|
|
||||||
module = Interpretable(parse(s, 'exec').node)
|
|
||||||
try:
|
|
||||||
module.run(frame)
|
|
||||||
except Failure:
|
|
||||||
e = sys.exc_info()[1]
|
|
||||||
report_failure(e)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# example:
|
|
||||||
def f():
|
|
||||||
return 5
|
|
||||||
|
|
||||||
def g():
|
|
||||||
return 3
|
|
||||||
|
|
||||||
def h(x):
|
|
||||||
return 'never'
|
|
||||||
|
|
||||||
check("f() * g() == 5")
|
|
||||||
check("not f()")
|
|
||||||
check("not (f() and g() or 0)")
|
|
||||||
check("f() == g()")
|
|
||||||
i = 4
|
|
||||||
check("i == f()")
|
|
||||||
check("len(f()) == 0")
|
|
||||||
check("isinstance(2+3+4, float)")
|
|
||||||
|
|
||||||
run("x = i")
|
|
||||||
check("x == 5")
|
|
||||||
|
|
||||||
run("assert not f(), 'oops'")
|
|
||||||
run("a, b, c = 1, 2")
|
|
||||||
run("a, b, c = f()")
|
|
||||||
|
|
||||||
check("max([f(),g()]) == 4")
|
|
||||||
check("'hello'[g()] == 'h'")
|
|
||||||
run("'guk%d' % h(f())")
|
|
|
@ -46,7 +46,4 @@ class AssertionError(BuiltinAssertionError):
|
||||||
if sys.version_info > (3, 0):
|
if sys.version_info > (3, 0):
|
||||||
AssertionError.__module__ = "builtins"
|
AssertionError.__module__ = "builtins"
|
||||||
|
|
||||||
if sys.version_info >= (2, 6) or sys.platform.startswith("java"):
|
|
||||||
from _pytest.assertion.newinterpret import interpret as reinterpret
|
from _pytest.assertion.newinterpret import interpret as reinterpret
|
||||||
else:
|
|
||||||
from _pytest.assertion.oldinterpret import interpret as reinterpret
|
|
||||||
|
|
|
@ -243,10 +243,9 @@ recording the intermediate values. Which technique is used depends on the
|
||||||
location of the assert, ``pytest`` configuration, and Python version being used
|
location of the assert, ``pytest`` configuration, and Python version being used
|
||||||
to run ``pytest``.
|
to run ``pytest``.
|
||||||
|
|
||||||
By default, if the Python version is greater than or equal to 2.6, ``pytest``
|
By default, ``pytest`` rewrites assert statements in test modules.
|
||||||
rewrites assert statements in test modules. Rewritten assert statements put
|
Rewritten assert statements put introspection information into the assertion failure message.
|
||||||
introspection information into the assertion failure message. ``pytest`` only
|
``pytest`` only rewrites test modules directly discovered by its test collection process, so
|
||||||
rewrites test modules directly discovered by its test collection process, so
|
|
||||||
asserts in supporting modules which are not themselves test modules will not be
|
asserts in supporting modules which are not themselves test modules will not be
|
||||||
rewritten.
|
rewritten.
|
||||||
|
|
||||||
|
|
|
@ -234,8 +234,8 @@ For an example on how to add and work with markers from a plugin, see
|
||||||
Marking whole classes or modules
|
Marking whole classes or modules
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
If you are programming with Python 2.6 or later you may use ``pytest.mark``
|
You may use ``pytest.mark`` decorators with classes to apply markers to all of
|
||||||
decorators with classes to apply markers to all of its test methods::
|
its test methods::
|
||||||
|
|
||||||
# content of test_mark_classlevel.py
|
# content of test_mark_classlevel.py
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -66,9 +66,8 @@ This completely avoids previous issues of confusing assertion-reporting.
|
||||||
It also means, that you can use Python's ``-O`` optimization without losing
|
It also means, that you can use Python's ``-O`` optimization without losing
|
||||||
assertions in test modules.
|
assertions in test modules.
|
||||||
|
|
||||||
``pytest`` contains a second, mostly obsolete, assert debugging technique,
|
``pytest`` contains a second, mostly obsolete, assert debugging technique
|
||||||
invoked via ``--assert=reinterpret``, activated by default on
|
invoked via ``--assert=reinterpret``: When an ``assert`` statement fails, ``pytest`` re-interprets
|
||||||
Python-2.5: When an ``assert`` statement fails, ``pytest`` re-interprets
|
|
||||||
the expression part to show intermediate values. This technique suffers
|
the expression part to show intermediate values. This technique suffers
|
||||||
from a caveat that the rewriting does not: If your expression has side
|
from a caveat that the rewriting does not: If your expression has side
|
||||||
effects (better to avoid them anyway!) the intermediate values may not
|
effects (better to avoid them anyway!) the intermediate values may not
|
||||||
|
|
|
@ -89,9 +89,7 @@ between test modules so it's no longer advertised as the primary method.
|
||||||
Skip all test functions of a class or module
|
Skip all test functions of a class or module
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
As with all function :ref:`marking <mark>` you can skip test functions at the
|
You can use the ``skipif`` decorator (and any other marker) on classes::
|
||||||
`whole class- or module level`_. If your code targets python2.6 or above you
|
|
||||||
use the skipif decorator (and any other marker) on classes::
|
|
||||||
|
|
||||||
@pytest.mark.skipif(sys.platform == 'win32',
|
@pytest.mark.skipif(sys.platform == 'win32',
|
||||||
reason="does not run on windows")
|
reason="does not run on windows")
|
||||||
|
@ -103,19 +101,6 @@ use the skipif decorator (and any other marker) on classes::
|
||||||
If the condition is true, this marker will produce a skip result for
|
If the condition is true, this marker will produce a skip result for
|
||||||
each of the test methods.
|
each of the test methods.
|
||||||
|
|
||||||
If your code targets python2.5 where class-decorators are not available,
|
|
||||||
you can set the ``pytestmark`` attribute of a class::
|
|
||||||
|
|
||||||
class TestPosixCalls:
|
|
||||||
pytestmark = pytest.mark.skipif(sys.platform == 'win32',
|
|
||||||
reason="does not run on windows")
|
|
||||||
|
|
||||||
def test_function(self):
|
|
||||||
"will not be setup or run under 'win32' platform"
|
|
||||||
|
|
||||||
As with the class-decorator, the ``pytestmark`` special name tells
|
|
||||||
``pytest`` to apply it to each test function in the class.
|
|
||||||
|
|
||||||
If you want to skip all test functions of a module, you must use
|
If you want to skip all test functions of a module, you must use
|
||||||
the ``pytestmark`` name on the global level:
|
the ``pytestmark`` name on the global level:
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ Specifying test exec environments in a conftest.py
|
||||||
Instead of specifying command line options, you can
|
Instead of specifying command line options, you can
|
||||||
put options values in a ``conftest.py`` file like this::
|
put options values in a ``conftest.py`` file like this::
|
||||||
|
|
||||||
option_tx = ['ssh=myhost//python=python2.5', 'popen//python=python2.5']
|
option_tx = ['ssh=myhost//python=python2.7', 'popen//python=python2.7']
|
||||||
option_dist = True
|
option_dist = True
|
||||||
|
|
||||||
Any commandline ``--tx`` specifications will add to the list of
|
Any commandline ``--tx`` specifications will add to the list of
|
||||||
|
@ -163,7 +163,7 @@ command line options
|
||||||
|
|
||||||
(default) no: run tests inprocess, don't distribute.
|
(default) no: run tests inprocess, don't distribute.
|
||||||
``--tx=xspec``
|
``--tx=xspec``
|
||||||
add a test execution environment. some examples: --tx popen//python=python2.5 --tx socket=192.168.1.102:8888 --tx ssh=user@codespeak.net//chdir=testcache
|
add a test execution environment. some examples: --tx popen//python=python2.7 --tx socket=192.168.1.102:8888 --tx ssh=user@codespeak.net//chdir=testcache
|
||||||
``-d``
|
``-d``
|
||||||
load-balance tests. shortcut for '--dist=load'
|
load-balance tests. shortcut for '--dist=load'
|
||||||
``--rsyncdir=dir1``
|
``--rsyncdir=dir1``
|
||||||
|
|
|
@ -12,8 +12,7 @@ Calling pytest through ``python -m pytest``
|
||||||
|
|
||||||
.. versionadded:: 2.0
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
If you use Python-2.5 or later you can invoke testing through the
|
You can invoke testing through the Python interpreter from the command line::
|
||||||
Python interpreter from the command line::
|
|
||||||
|
|
||||||
python -m pytest [...]
|
python -m pytest [...]
|
||||||
|
|
||||||
|
|
|
@ -61,16 +61,16 @@ a lot of I/O this can lead to considerable speed ups.
|
||||||
Running tests in a Python subprocess
|
Running tests in a Python subprocess
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
To instantiate a Python-2.4 subprocess and send tests to it, you may type::
|
To instantiate a Python-2.7 subprocess and send tests to it, you may type::
|
||||||
|
|
||||||
py.test -d --tx popen//python=python2.4
|
py.test -d --tx popen//python=python2.7
|
||||||
|
|
||||||
This will start a subprocess which is run with the "python2.4"
|
This will start a subprocess which is run with the "python2.7"
|
||||||
Python interpreter, found in your system binary lookup path.
|
Python interpreter, found in your system binary lookup path.
|
||||||
|
|
||||||
If you prefix the --tx option value like this::
|
If you prefix the --tx option value like this::
|
||||||
|
|
||||||
py.test -d --tx 3*popen//python=python2.4
|
py.test -d --tx 3*popen//python=python2.7
|
||||||
|
|
||||||
then three subprocesses would be created and the tests
|
then three subprocesses would be created and the tests
|
||||||
will be distributed to three subprocesses and run simultanously.
|
will be distributed to three subprocesses and run simultanously.
|
||||||
|
@ -170,7 +170,7 @@ For example, you could make running with three subprocesses your default::
|
||||||
You can also add default environments like this::
|
You can also add default environments like this::
|
||||||
|
|
||||||
[pytest]
|
[pytest]
|
||||||
addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python2.6
|
addopts = --tx ssh=myhost//python=python2.7 --tx ssh=myhost//python=python2.6
|
||||||
|
|
||||||
and then just type::
|
and then just type::
|
||||||
|
|
||||||
|
|
|
@ -450,19 +450,16 @@ class TestInvocationVariants:
|
||||||
"*1 passed*",
|
"*1 passed*",
|
||||||
])
|
])
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_python_minus_m_invocation_ok(self, testdir):
|
def test_python_minus_m_invocation_ok(self, testdir):
|
||||||
p1 = testdir.makepyfile("def test_hello(): pass")
|
p1 = testdir.makepyfile("def test_hello(): pass")
|
||||||
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
||||||
assert res.ret == 0
|
assert res.ret == 0
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_python_minus_m_invocation_fail(self, testdir):
|
def test_python_minus_m_invocation_fail(self, testdir):
|
||||||
p1 = testdir.makepyfile("def test_fail(): 0/0")
|
p1 = testdir.makepyfile("def test_fail(): 0/0")
|
||||||
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
||||||
assert res.ret == 1
|
assert res.ret == 1
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_python_pytest_package(self, testdir):
|
def test_python_pytest_package(self, testdir):
|
||||||
p1 = testdir.makepyfile("def test_pass(): pass")
|
p1 = testdir.makepyfile("def test_pass(): pass")
|
||||||
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
|
||||||
|
|
|
@ -69,11 +69,8 @@ class FilesCompleter(object):
|
||||||
completion += [f + '/' for f in anticomp]
|
completion += [f + '/' for f in anticomp]
|
||||||
return completion
|
return completion
|
||||||
|
|
||||||
# the following barfs with a syntax error on py2.5
|
|
||||||
# @pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
class TestArgComplete:
|
class TestArgComplete:
|
||||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_compare_with_compgen(self):
|
def test_compare_with_compgen(self):
|
||||||
from _pytest._argcomplete import FastFilesCompleter
|
from _pytest._argcomplete import FastFilesCompleter
|
||||||
ffc = FastFilesCompleter()
|
ffc = FastFilesCompleter()
|
||||||
|
@ -82,7 +79,6 @@ class TestArgComplete:
|
||||||
assert equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
|
assert equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_remove_dir_prefix(self):
|
def test_remove_dir_prefix(self):
|
||||||
"""this is not compatible with compgen but it is with bash itself:
|
"""this is not compatible with compgen but it is with bash itself:
|
||||||
ls /usr/<TAB>
|
ls /usr/<TAB>
|
||||||
|
|
|
@ -79,7 +79,6 @@ def test_is():
|
||||||
assert s.startswith("assert 1 is 2")
|
assert s.startswith("assert 1 is 2")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_attrib():
|
def test_attrib():
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
b = 1
|
b = 1
|
||||||
|
@ -91,7 +90,6 @@ def test_attrib():
|
||||||
s = str(e)
|
s = str(e)
|
||||||
assert s.startswith("assert 1 == 2")
|
assert s.startswith("assert 1 == 2")
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_attrib_inst():
|
def test_attrib_inst():
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
b = 1
|
b = 1
|
||||||
|
@ -197,66 +195,6 @@ def test_power():
|
||||||
assert "assert (2 ** 3) == 7" in e.msg
|
assert "assert (2 ** 3) == 7" in e.msg
|
||||||
|
|
||||||
|
|
||||||
class TestView:
|
|
||||||
|
|
||||||
def setup_class(cls):
|
|
||||||
cls.View = pytest.importorskip("_pytest.assertion.oldinterpret").View
|
|
||||||
|
|
||||||
def test_class_dispatch(self):
|
|
||||||
### Use a custom class hierarchy with existing instances
|
|
||||||
|
|
||||||
class Picklable(self.View):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Simple(Picklable):
|
|
||||||
__view__ = object
|
|
||||||
def pickle(self):
|
|
||||||
return repr(self.__obj__)
|
|
||||||
|
|
||||||
class Seq(Picklable):
|
|
||||||
__view__ = list, tuple, dict
|
|
||||||
def pickle(self):
|
|
||||||
return ';'.join(
|
|
||||||
[Picklable(item).pickle() for item in self.__obj__])
|
|
||||||
|
|
||||||
class Dict(Seq):
|
|
||||||
__view__ = dict
|
|
||||||
def pickle(self):
|
|
||||||
return Seq.pickle(self) + '!' + Seq(self.values()).pickle()
|
|
||||||
|
|
||||||
assert Picklable(123).pickle() == '123'
|
|
||||||
assert Picklable([1,[2,3],4]).pickle() == '1;2;3;4'
|
|
||||||
assert Picklable({1:2}).pickle() == '1!2'
|
|
||||||
|
|
||||||
def test_viewtype_class_hierarchy(self):
|
|
||||||
# Use a custom class hierarchy based on attributes of existing instances
|
|
||||||
class Operation:
|
|
||||||
"Existing class that I don't want to change."
|
|
||||||
def __init__(self, opname, *args):
|
|
||||||
self.opname = opname
|
|
||||||
self.args = args
|
|
||||||
|
|
||||||
existing = [Operation('+', 4, 5),
|
|
||||||
Operation('getitem', '', 'join'),
|
|
||||||
Operation('setattr', 'x', 'y', 3),
|
|
||||||
Operation('-', 12, 1)]
|
|
||||||
|
|
||||||
class PyOp(self.View):
|
|
||||||
def __viewkey__(self):
|
|
||||||
return self.opname
|
|
||||||
def generate(self):
|
|
||||||
return '%s(%s)' % (self.opname, ', '.join(map(repr, self.args)))
|
|
||||||
|
|
||||||
class PyBinaryOp(PyOp):
|
|
||||||
__view__ = ('+', '-', '*', '/')
|
|
||||||
def generate(self):
|
|
||||||
return '%s %s %s' % (self.args[0], self.opname, self.args[1])
|
|
||||||
|
|
||||||
codelines = [PyOp(op).generate() for op in existing]
|
|
||||||
assert codelines == ["4 + 5", "getitem('', 'join')",
|
|
||||||
"setattr('x', 'y', 3)", "12 - 1"]
|
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_assert_customizable_reprcompare(monkeypatch):
|
def test_assert_customizable_reprcompare(monkeypatch):
|
||||||
monkeypatch.setattr(util, '_reprcompare', lambda *args: 'hello')
|
monkeypatch.setattr(util, '_reprcompare', lambda *args: 'hello')
|
||||||
try:
|
try:
|
||||||
|
@ -306,7 +244,6 @@ def test_assert_raise_alias(testdir):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_assert_raise_subclass():
|
def test_assert_raise_subclass():
|
||||||
class SomeEx(AssertionError):
|
class SomeEx(AssertionError):
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
|
@ -334,18 +271,3 @@ def test_assert_raises_in_nonzero_of_object_pytest_issue10():
|
||||||
e = exvalue()
|
e = exvalue()
|
||||||
s = str(e)
|
s = str(e)
|
||||||
assert "<MY42 object> < 0" in s
|
assert "<MY42 object> < 0" in s
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info >= (2,6)")
|
|
||||||
def test_oldinterpret_importation():
|
|
||||||
# we had a cyclic import there
|
|
||||||
# requires pytest on sys.path
|
|
||||||
res = py.std.subprocess.call([
|
|
||||||
py.std.sys.executable, '-c', str(py.code.Source("""
|
|
||||||
try:
|
|
||||||
from _pytest.assertion.newinterpret import interpret
|
|
||||||
except ImportError:
|
|
||||||
from _pytest.assertion.oldinterpret import interpret
|
|
||||||
"""))
|
|
||||||
])
|
|
||||||
|
|
||||||
assert res == 0
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import _pytest.assertion as plugin
|
||||||
from _pytest.assertion import reinterpret
|
from _pytest.assertion import reinterpret
|
||||||
from _pytest.assertion import util
|
from _pytest.assertion import util
|
||||||
|
|
||||||
needsnewassert = pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
PY3 = sys.version_info >= (3, 0)
|
PY3 = sys.version_info >= (3, 0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +25,6 @@ def interpret(expr):
|
||||||
return reinterpret.reinterpret(expr, py.code.Frame(sys._getframe(1)))
|
return reinterpret.reinterpret(expr, py.code.Frame(sys._getframe(1)))
|
||||||
|
|
||||||
class TestBinReprIntegration:
|
class TestBinReprIntegration:
|
||||||
pytestmark = needsnewassert
|
|
||||||
|
|
||||||
def test_pytest_assertrepr_compare_called(self, testdir):
|
def test_pytest_assertrepr_compare_called(self, testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
|
@ -361,7 +359,6 @@ def test_python25_compile_issue257(testdir):
|
||||||
*1 failed*
|
*1 failed*
|
||||||
""")
|
""")
|
||||||
|
|
||||||
@needsnewassert
|
|
||||||
def test_rewritten(testdir):
|
def test_rewritten(testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_rewritten():
|
def test_rewritten():
|
||||||
|
@ -374,7 +371,6 @@ def test_reprcompare_notin(mock_config):
|
||||||
mock_config, 'not in', 'foo', 'aaafoobbb')[1:]
|
mock_config, 'not in', 'foo', 'aaafoobbb')[1:]
|
||||||
assert detail == ["'foo' is contained here:", ' aaafoobbb', '? +++']
|
assert detail == ["'foo' is contained here:", ' aaafoobbb', '? +++']
|
||||||
|
|
||||||
@needsnewassert
|
|
||||||
def test_pytest_assertrepr_compare_integration(testdir):
|
def test_pytest_assertrepr_compare_integration(testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
@ -391,7 +387,6 @@ def test_pytest_assertrepr_compare_integration(testdir):
|
||||||
"*E*50*",
|
"*E*50*",
|
||||||
])
|
])
|
||||||
|
|
||||||
@needsnewassert
|
|
||||||
def test_sequence_comparison_uses_repr(testdir):
|
def test_sequence_comparison_uses_repr(testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
def test_hello():
|
def test_hello():
|
||||||
|
@ -410,7 +405,6 @@ def test_sequence_comparison_uses_repr(testdir):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail("sys.version_info < (2,6)")
|
|
||||||
def test_assert_compare_truncate_longmessage(testdir):
|
def test_assert_compare_truncate_longmessage(testdir):
|
||||||
testdir.makepyfile(r"""
|
testdir.makepyfile(r"""
|
||||||
def test_long():
|
def test_long():
|
||||||
|
@ -438,7 +432,6 @@ def test_assert_compare_truncate_longmessage(testdir):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@needsnewassert
|
|
||||||
def test_assertrepr_loaded_per_dir(testdir):
|
def test_assertrepr_loaded_per_dir(testdir):
|
||||||
testdir.makepyfile(test_base=['def test_base(): assert 1 == 2'])
|
testdir.makepyfile(test_base=['def test_base(): assert 1 == 2'])
|
||||||
a = testdir.mkdir('a')
|
a = testdir.mkdir('a')
|
||||||
|
@ -547,7 +540,7 @@ def test_traceback_failure(testdir):
|
||||||
"*test_traceback_failure.py:4: AssertionError"
|
"*test_traceback_failure.py:4: AssertionError"
|
||||||
])
|
])
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5) or '__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')" )
|
@pytest.mark.skipif("'__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')" )
|
||||||
def test_warn_missing(testdir):
|
def test_warn_missing(testdir):
|
||||||
testdir.makepyfile("")
|
testdir.makepyfile("")
|
||||||
result = testdir.run(sys.executable, "-OO", "-m", "pytest", "-h")
|
result = testdir.run(sys.executable, "-OO", "-m", "pytest", "-h")
|
||||||
|
|
|
@ -129,7 +129,6 @@ def test_cache_show(testdir):
|
||||||
|
|
||||||
|
|
||||||
class TestLastFailed:
|
class TestLastFailed:
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_lastfailed_usecase(self, testdir, monkeypatch):
|
def test_lastfailed_usecase(self, testdir, monkeypatch):
|
||||||
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
|
@ -197,7 +196,6 @@ class TestLastFailed:
|
||||||
"test_a.py*",
|
"test_a.py*",
|
||||||
])
|
])
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_lastfailed_difference_invocations(self, testdir, monkeypatch):
|
def test_lastfailed_difference_invocations(self, testdir, monkeypatch):
|
||||||
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
||||||
testdir.makepyfile(test_a="""
|
testdir.makepyfile(test_a="""
|
||||||
|
@ -233,7 +231,6 @@ class TestLastFailed:
|
||||||
"*1 failed*1 desel*",
|
"*1 failed*1 desel*",
|
||||||
])
|
])
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_lastfailed_usecase_splice(self, testdir, monkeypatch):
|
def test_lastfailed_usecase_splice(self, testdir, monkeypatch):
|
||||||
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
|
|
@ -316,7 +316,6 @@ class TestFunctional:
|
||||||
assert 'hello' in keywords
|
assert 'hello' in keywords
|
||||||
assert 'world' in keywords
|
assert 'world' in keywords
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_mark_per_class_decorator(self, testdir):
|
def test_mark_per_class_decorator(self, testdir):
|
||||||
item = testdir.getitem("""
|
item = testdir.getitem("""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -328,7 +327,6 @@ class TestFunctional:
|
||||||
keywords = item.keywords
|
keywords = item.keywords
|
||||||
assert 'hello' in keywords
|
assert 'hello' in keywords
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_mark_per_class_decorator_plus_existing_dec(self, testdir):
|
def test_mark_per_class_decorator_plus_existing_dec(self, testdir):
|
||||||
item = testdir.getitem("""
|
item = testdir.getitem("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -300,7 +300,6 @@ def test_apiwrapper_problem_issue260(testdir):
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.assert_outcomes(passed=1)
|
result.assert_outcomes(passed=1)
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_setup_teardown_linking_issue265(testdir):
|
def test_setup_teardown_linking_issue265(testdir):
|
||||||
# we accidentally didnt integrate nose setupstate with normal setupstate
|
# we accidentally didnt integrate nose setupstate with normal setupstate
|
||||||
# this test ensures that won't happen again
|
# this test ensures that won't happen again
|
||||||
|
|
|
@ -171,7 +171,6 @@ class TestParser:
|
||||||
assert option.this == 42
|
assert option.this == 42
|
||||||
assert option.no is False
|
assert option.no is False
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_drop_short_helper(self):
|
def test_drop_short_helper(self):
|
||||||
parser = py.std.argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
|
parser = py.std.argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
|
||||||
parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
|
parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
|
||||||
|
@ -213,20 +212,17 @@ class TestParser:
|
||||||
assert args.abc_def is False
|
assert args.abc_def is False
|
||||||
assert args.klm_hij is True
|
assert args.klm_hij is True
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_drop_short_2(self, parser):
|
def test_drop_short_2(self, parser):
|
||||||
parser.addoption('--func-arg', '--doit', action='store_true')
|
parser.addoption('--func-arg', '--doit', action='store_true')
|
||||||
args = parser.parse(['--doit'])
|
args = parser.parse(['--doit'])
|
||||||
assert args.func_arg is True
|
assert args.func_arg is True
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_drop_short_3(self, parser):
|
def test_drop_short_3(self, parser):
|
||||||
parser.addoption('--func-arg', '--funcarg', '--doit', action='store_true')
|
parser.addoption('--func-arg', '--funcarg', '--doit', action='store_true')
|
||||||
args = parser.parse(['abcd'])
|
args = parser.parse(['abcd'])
|
||||||
assert args.func_arg is False
|
assert args.func_arg is False
|
||||||
assert args.file_or_dir == ['abcd']
|
assert args.file_or_dir == ['abcd']
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_drop_short_help0(self, parser, capsys):
|
def test_drop_short_help0(self, parser, capsys):
|
||||||
parser.addoption('--func-args', '--doit', help = 'foo',
|
parser.addoption('--func-args', '--doit', help = 'foo',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
@ -235,7 +231,6 @@ class TestParser:
|
||||||
assert '--func-args, --doit foo' in help
|
assert '--func-args, --doit foo' in help
|
||||||
|
|
||||||
# testing would be more helpful with all help generated
|
# testing would be more helpful with all help generated
|
||||||
@pytest.mark.skipif("sys.version_info < (2,5)")
|
|
||||||
def test_drop_short_help1(self, parser, capsys):
|
def test_drop_short_help1(self, parser, capsys):
|
||||||
group = parser.getgroup("general")
|
group = parser.getgroup("general")
|
||||||
group.addoption('--doit', '--func-args', action='store_true', help='foo')
|
group.addoption('--doit', '--func-args', action='store_true', help='foo')
|
||||||
|
@ -246,7 +241,6 @@ class TestParser:
|
||||||
assert '-doit, --func-args foo' in help
|
assert '-doit, --func-args foo' in help
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif("sys.version_info < (2,6)")
|
|
||||||
def test_argcomplete(testdir, monkeypatch):
|
def test_argcomplete(testdir, monkeypatch):
|
||||||
if not py.path.local.sysfind('bash'):
|
if not py.path.local.sysfind('bash'):
|
||||||
pytest.skip("bash not available")
|
pytest.skip("bash not available")
|
||||||
|
|
Loading…
Reference in New Issue