Merge remote-tracking branch 'upstream/features' into invocation-scoped-fixtures
This commit is contained in:
commit
fb4da00a32
|
@ -0,0 +1,203 @@
|
||||||
|
"""
|
||||||
|
python version compatibility code
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import inspect
|
||||||
|
import types
|
||||||
|
import re
|
||||||
|
import functools
|
||||||
|
|
||||||
|
import py
|
||||||
|
|
||||||
|
import _pytest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
import enum
|
||||||
|
except ImportError: # pragma: no cover
|
||||||
|
# Only available in Python 3.4+ or as a backport
|
||||||
|
enum = None
|
||||||
|
|
||||||
|
_PY3 = sys.version_info > (3, 0)
|
||||||
|
_PY2 = not _PY3
|
||||||
|
|
||||||
|
|
||||||
|
NoneType = type(None)
|
||||||
|
NOTSET = object()
|
||||||
|
|
||||||
|
if hasattr(inspect, 'signature'):
|
||||||
|
def _format_args(func):
|
||||||
|
return str(inspect.signature(func))
|
||||||
|
else:
|
||||||
|
def _format_args(func):
|
||||||
|
return inspect.formatargspec(*inspect.getargspec(func))
|
||||||
|
|
||||||
|
isfunction = inspect.isfunction
|
||||||
|
isclass = inspect.isclass
|
||||||
|
# used to work around a python2 exception info leak
|
||||||
|
exc_clear = getattr(sys, 'exc_clear', lambda: None)
|
||||||
|
# The type of re.compile objects is not exposed in Python.
|
||||||
|
REGEX_TYPE = type(re.compile(''))
|
||||||
|
|
||||||
|
|
||||||
|
def is_generator(func):
|
||||||
|
try:
|
||||||
|
return _pytest._code.getrawcode(func).co_flags & 32 # generator function
|
||||||
|
except AttributeError: # builtin functions have no bytecode
|
||||||
|
# assume them to not be generators
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def getlocation(function, curdir):
|
||||||
|
import inspect
|
||||||
|
fn = py.path.local(inspect.getfile(function))
|
||||||
|
lineno = py.builtin._getcode(function).co_firstlineno
|
||||||
|
if fn.relto(curdir):
|
||||||
|
fn = fn.relto(curdir)
|
||||||
|
return "%s:%d" %(fn, lineno+1)
|
||||||
|
|
||||||
|
|
||||||
|
def num_mock_patch_args(function):
|
||||||
|
""" return number of arguments used up by mock arguments (if any) """
|
||||||
|
patchings = getattr(function, "patchings", None)
|
||||||
|
if not patchings:
|
||||||
|
return 0
|
||||||
|
mock = sys.modules.get("mock", sys.modules.get("unittest.mock", None))
|
||||||
|
if mock is not None:
|
||||||
|
return len([p for p in patchings
|
||||||
|
if not p.attribute_name and p.new is mock.DEFAULT])
|
||||||
|
return len(patchings)
|
||||||
|
|
||||||
|
|
||||||
|
def getfuncargnames(function, startindex=None):
|
||||||
|
# XXX merge with main.py's varnames
|
||||||
|
#assert not isclass(function)
|
||||||
|
realfunction = function
|
||||||
|
while hasattr(realfunction, "__wrapped__"):
|
||||||
|
realfunction = realfunction.__wrapped__
|
||||||
|
if startindex is None:
|
||||||
|
startindex = inspect.ismethod(function) and 1 or 0
|
||||||
|
if realfunction != function:
|
||||||
|
startindex += num_mock_patch_args(function)
|
||||||
|
function = realfunction
|
||||||
|
if isinstance(function, functools.partial):
|
||||||
|
argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
|
||||||
|
partial = function
|
||||||
|
argnames = argnames[len(partial.args):]
|
||||||
|
if partial.keywords:
|
||||||
|
for kw in partial.keywords:
|
||||||
|
argnames.remove(kw)
|
||||||
|
else:
|
||||||
|
argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
|
||||||
|
defaults = getattr(function, 'func_defaults',
|
||||||
|
getattr(function, '__defaults__', None)) or ()
|
||||||
|
numdefaults = len(defaults)
|
||||||
|
if numdefaults:
|
||||||
|
return tuple(argnames[startindex:-numdefaults])
|
||||||
|
return tuple(argnames[startindex:])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info[:2] == (2, 6):
|
||||||
|
def isclass(object):
|
||||||
|
""" Return true if the object is a class. Overrides inspect.isclass for
|
||||||
|
python 2.6 because it will return True for objects which always return
|
||||||
|
something on __getattr__ calls (see #1035).
|
||||||
|
Backport of https://hg.python.org/cpython/rev/35bf8f7a8edc
|
||||||
|
"""
|
||||||
|
return isinstance(object, (type, types.ClassType))
|
||||||
|
|
||||||
|
|
||||||
|
if _PY3:
|
||||||
|
import codecs
|
||||||
|
|
||||||
|
STRING_TYPES = bytes, str
|
||||||
|
|
||||||
|
def _escape_strings(val):
|
||||||
|
"""If val is pure ascii, returns it as a str(). Otherwise, escapes
|
||||||
|
bytes objects into a sequence of escaped bytes:
|
||||||
|
|
||||||
|
b'\xc3\xb4\xc5\xd6' -> u'\\xc3\\xb4\\xc5\\xd6'
|
||||||
|
|
||||||
|
and escapes unicode objects into a sequence of escaped unicode
|
||||||
|
ids, e.g.:
|
||||||
|
|
||||||
|
'4\\nV\\U00043efa\\x0eMXWB\\x1e\\u3028\\u15fd\\xcd\\U0007d944'
|
||||||
|
|
||||||
|
note:
|
||||||
|
the obvious "v.decode('unicode-escape')" will return
|
||||||
|
valid utf-8 unicode if it finds them in bytes, but we
|
||||||
|
want to return escaped bytes for any byte, even if they match
|
||||||
|
a utf-8 string.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if isinstance(val, bytes):
|
||||||
|
if val:
|
||||||
|
# source: http://goo.gl/bGsnwC
|
||||||
|
encoded_bytes, _ = codecs.escape_encode(val)
|
||||||
|
return encoded_bytes.decode('ascii')
|
||||||
|
else:
|
||||||
|
# empty bytes crashes codecs.escape_encode (#1087)
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return val.encode('unicode_escape').decode('ascii')
|
||||||
|
else:
|
||||||
|
STRING_TYPES = bytes, str, unicode
|
||||||
|
|
||||||
|
def _escape_strings(val):
|
||||||
|
"""In py2 bytes and str are the same type, so return if it's a bytes
|
||||||
|
object, return it unchanged if it is a full ascii string,
|
||||||
|
otherwise escape it into its binary form.
|
||||||
|
|
||||||
|
If it's a unicode string, change the unicode characters into
|
||||||
|
unicode escapes.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if isinstance(val, bytes):
|
||||||
|
try:
|
||||||
|
return val.encode('ascii')
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
return val.encode('string-escape')
|
||||||
|
else:
|
||||||
|
return val.encode('unicode-escape')
|
||||||
|
|
||||||
|
|
||||||
|
def get_real_func(obj):
|
||||||
|
""" gets the real function object of the (possibly) wrapped object by
|
||||||
|
functools.wraps or functools.partial.
|
||||||
|
"""
|
||||||
|
while hasattr(obj, "__wrapped__"):
|
||||||
|
obj = obj.__wrapped__
|
||||||
|
if isinstance(obj, functools.partial):
|
||||||
|
obj = obj.func
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def getfslineno(obj):
|
||||||
|
# xxx let decorators etc specify a sane ordering
|
||||||
|
obj = get_real_func(obj)
|
||||||
|
if hasattr(obj, 'place_as'):
|
||||||
|
obj = obj.place_as
|
||||||
|
fslineno = _pytest._code.getfslineno(obj)
|
||||||
|
assert isinstance(fslineno[1], int), obj
|
||||||
|
return fslineno
|
||||||
|
|
||||||
|
def getimfunc(func):
|
||||||
|
try:
|
||||||
|
return func.__func__
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
return func.im_func
|
||||||
|
except AttributeError:
|
||||||
|
return func
|
||||||
|
|
||||||
|
def safe_getattr(object, name, default):
|
||||||
|
""" Like getattr but return default upon any Exception.
|
||||||
|
|
||||||
|
Attribute access can potentially fail for 'evil' Python objects.
|
||||||
|
See issue214
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return getattr(object, name, default)
|
||||||
|
except Exception:
|
||||||
|
return default
|
|
@ -63,7 +63,7 @@ class UsageError(Exception):
|
||||||
_preinit = []
|
_preinit = []
|
||||||
|
|
||||||
default_plugins = (
|
default_plugins = (
|
||||||
"mark main terminal runner python debugging unittest capture skipping "
|
"mark main terminal runner python fixtures debugging unittest capture skipping "
|
||||||
"tmpdir monkeypatch recwarn pastebin helpconfig nose assertion "
|
"tmpdir monkeypatch recwarn pastebin helpconfig nose assertion "
|
||||||
"junitxml resultlog doctest cacheprovider freeze_support "
|
"junitxml resultlog doctest cacheprovider freeze_support "
|
||||||
"setuponly setupplan").split()
|
"setuponly setupplan").split()
|
||||||
|
|
|
@ -5,7 +5,7 @@ import traceback
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest._code.code import TerminalRepr, ReprFileLocation, ExceptionInfo
|
from _pytest._code.code import TerminalRepr, ReprFileLocation, ExceptionInfo
|
||||||
from _pytest.python import FixtureRequest
|
from _pytest.fixtures import FixtureRequest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
1321
_pytest/python.py
1321
_pytest/python.py
File diff suppressed because it is too large
Load Diff
|
@ -334,7 +334,7 @@ class TestFunction:
|
||||||
reprec.assertoutcome()
|
reprec.assertoutcome()
|
||||||
|
|
||||||
def test_function_equality(self, testdir, tmpdir):
|
def test_function_equality(self, testdir, tmpdir):
|
||||||
from _pytest.python import FixtureManager
|
from _pytest.fixtures import FixtureManager
|
||||||
config = testdir.parseconfigure()
|
config = testdir.parseconfigure()
|
||||||
session = testdir.Session(config)
|
session = testdir.Session(config)
|
||||||
session._fixturemanager = FixtureManager(session)
|
session._fixturemanager = FixtureManager(session)
|
||||||
|
|
|
@ -3,31 +3,30 @@ from textwrap import dedent
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
from _pytest import python as funcargs
|
|
||||||
from _pytest.pytester import get_public_names
|
from _pytest.pytester import get_public_names
|
||||||
from _pytest.python import FixtureLookupError
|
from _pytest.fixtures import FixtureLookupError
|
||||||
|
from _pytest import fixtures
|
||||||
|
|
||||||
def test_getfuncargnames():
|
def test_getfuncargnames():
|
||||||
def f(): pass
|
def f(): pass
|
||||||
assert not funcargs.getfuncargnames(f)
|
assert not fixtures.getfuncargnames(f)
|
||||||
def g(arg): pass
|
def g(arg): pass
|
||||||
assert funcargs.getfuncargnames(g) == ('arg',)
|
assert fixtures.getfuncargnames(g) == ('arg',)
|
||||||
def h(arg1, arg2="hello"): pass
|
def h(arg1, arg2="hello"): pass
|
||||||
assert funcargs.getfuncargnames(h) == ('arg1',)
|
assert fixtures.getfuncargnames(h) == ('arg1',)
|
||||||
def h(arg1, arg2, arg3="hello"): pass
|
def h(arg1, arg2, arg3="hello"): pass
|
||||||
assert funcargs.getfuncargnames(h) == ('arg1', 'arg2')
|
assert fixtures.getfuncargnames(h) == ('arg1', 'arg2')
|
||||||
class A:
|
class A:
|
||||||
def f(self, arg1, arg2="hello"):
|
def f(self, arg1, arg2="hello"):
|
||||||
pass
|
pass
|
||||||
assert funcargs.getfuncargnames(A().f) == ('arg1',)
|
assert fixtures.getfuncargnames(A().f) == ('arg1',)
|
||||||
if sys.version_info < (3,0):
|
if sys.version_info < (3,0):
|
||||||
assert funcargs.getfuncargnames(A.f) == ('arg1',)
|
assert fixtures.getfuncargnames(A.f) == ('arg1',)
|
||||||
|
|
||||||
class TestFillFixtures:
|
class TestFillFixtures:
|
||||||
def test_fillfuncargs_exposed(self):
|
def test_fillfuncargs_exposed(self):
|
||||||
# used by oejskit, kept for compatibility
|
# used by oejskit, kept for compatibility
|
||||||
assert pytest._fillfuncargs == funcargs.fillfixtures
|
assert pytest._fillfuncargs == fixtures.fillfixtures
|
||||||
|
|
||||||
def test_funcarg_lookupfails(self, testdir):
|
def test_funcarg_lookupfails(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -54,7 +53,7 @@ class TestFillFixtures:
|
||||||
def test_func(some, other):
|
def test_func(some, other):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
funcargs.fillfixtures(item)
|
fixtures.fillfixtures(item)
|
||||||
del item.funcargs["request"]
|
del item.funcargs["request"]
|
||||||
assert len(get_public_names(item.funcargs)) == 2
|
assert len(get_public_names(item.funcargs)) == 2
|
||||||
assert item.funcargs['some'] == "test_func"
|
assert item.funcargs['some'] == "test_func"
|
||||||
|
@ -400,7 +399,7 @@ class TestRequestBasic:
|
||||||
def pytest_funcarg__something(request): pass
|
def pytest_funcarg__something(request): pass
|
||||||
def test_func(something): pass
|
def test_func(something): pass
|
||||||
""")
|
""")
|
||||||
req = funcargs.FixtureRequest(item)
|
req = fixtures.FixtureRequest(item)
|
||||||
assert req.function == item.obj
|
assert req.function == item.obj
|
||||||
assert req.keywords == item.keywords
|
assert req.keywords == item.keywords
|
||||||
assert hasattr(req.module, 'test_func')
|
assert hasattr(req.module, 'test_func')
|
||||||
|
@ -431,7 +430,7 @@ class TestRequestBasic:
|
||||||
""")
|
""")
|
||||||
item1, = testdir.genitems([modcol])
|
item1, = testdir.genitems([modcol])
|
||||||
assert item1.name == "test_method"
|
assert item1.name == "test_method"
|
||||||
arg2fixturedefs = funcargs.FixtureRequest(item1)._arg2fixturedefs
|
arg2fixturedefs = fixtures.FixtureRequest(item1)._arg2fixturedefs
|
||||||
assert len(arg2fixturedefs) == 1
|
assert len(arg2fixturedefs) == 1
|
||||||
assert arg2fixturedefs[0].__name__ == "pytest_funcarg__something"
|
assert arg2fixturedefs[0].__name__ == "pytest_funcarg__something"
|
||||||
|
|
||||||
|
@ -558,7 +557,7 @@ class TestRequestBasic:
|
||||||
def test_request_getmodulepath(self, testdir):
|
def test_request_getmodulepath(self, testdir):
|
||||||
modcol = testdir.getmodulecol("def test_somefunc(): pass")
|
modcol = testdir.getmodulecol("def test_somefunc(): pass")
|
||||||
item, = testdir.genitems([modcol])
|
item, = testdir.genitems([modcol])
|
||||||
req = funcargs.FixtureRequest(item)
|
req = fixtures.FixtureRequest(item)
|
||||||
assert req.fspath == modcol.fspath
|
assert req.fspath == modcol.fspath
|
||||||
|
|
||||||
def test_request_fixturenames(self, testdir):
|
def test_request_fixturenames(self, testdir):
|
||||||
|
@ -687,7 +686,7 @@ class TestRequestMarking:
|
||||||
def test_func2(self, something):
|
def test_func2(self, something):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
req1 = funcargs.FixtureRequest(item1)
|
req1 = fixtures.FixtureRequest(item1)
|
||||||
assert 'xfail' not in item1.keywords
|
assert 'xfail' not in item1.keywords
|
||||||
req1.applymarker(pytest.mark.xfail)
|
req1.applymarker(pytest.mark.xfail)
|
||||||
assert 'xfail' in item1.keywords
|
assert 'xfail' in item1.keywords
|
||||||
|
@ -769,7 +768,7 @@ class TestRequestCachedSetup:
|
||||||
|
|
||||||
def test_request_cachedsetup_extrakey(self, testdir):
|
def test_request_cachedsetup_extrakey(self, testdir):
|
||||||
item1 = testdir.getitem("def test_func(): pass")
|
item1 = testdir.getitem("def test_func(): pass")
|
||||||
req1 = funcargs.FixtureRequest(item1)
|
req1 = fixtures.FixtureRequest(item1)
|
||||||
l = ["hello", "world"]
|
l = ["hello", "world"]
|
||||||
def setup():
|
def setup():
|
||||||
return l.pop()
|
return l.pop()
|
||||||
|
@ -784,7 +783,7 @@ class TestRequestCachedSetup:
|
||||||
|
|
||||||
def test_request_cachedsetup_cache_deletion(self, testdir):
|
def test_request_cachedsetup_cache_deletion(self, testdir):
|
||||||
item1 = testdir.getitem("def test_func(): pass")
|
item1 = testdir.getitem("def test_func(): pass")
|
||||||
req1 = funcargs.FixtureRequest(item1)
|
req1 = fixtures.FixtureRequest(item1)
|
||||||
l = []
|
l = []
|
||||||
def setup():
|
def setup():
|
||||||
l.append("setup")
|
l.append("setup")
|
||||||
|
|
|
@ -73,7 +73,7 @@ def test_wrapped_getfslineno():
|
||||||
|
|
||||||
class TestMockDecoration:
|
class TestMockDecoration:
|
||||||
def test_wrapped_getfuncargnames(self):
|
def test_wrapped_getfuncargnames(self):
|
||||||
from _pytest.python import getfuncargnames
|
from _pytest.compat import getfuncargnames
|
||||||
def wrap(f):
|
def wrap(f):
|
||||||
def func():
|
def func():
|
||||||
pass
|
pass
|
||||||
|
@ -86,7 +86,7 @@ class TestMockDecoration:
|
||||||
assert l == ("x",)
|
assert l == ("x",)
|
||||||
|
|
||||||
def test_wrapped_getfuncargnames_patching(self):
|
def test_wrapped_getfuncargnames_patching(self):
|
||||||
from _pytest.python import getfuncargnames
|
from _pytest.compat import getfuncargnames
|
||||||
def wrap(f):
|
def wrap(f):
|
||||||
def func():
|
def func():
|
||||||
pass
|
pass
|
||||||
|
@ -234,7 +234,7 @@ class TestReRunTests:
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def test_pytestconfig_is_session_scoped():
|
def test_pytestconfig_is_session_scoped():
|
||||||
from _pytest.python import pytestconfig
|
from _pytest.fixtures import pytestconfig
|
||||||
assert pytestconfig._pytestfixturefunction.scope == "session"
|
assert pytestconfig._pytestfixturefunction.scope == "session"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import sys
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import python as funcargs
|
from _pytest import python, fixtures
|
||||||
|
|
||||||
import hypothesis
|
import hypothesis
|
||||||
from hypothesis import strategies
|
from hypothesis import strategies
|
||||||
|
@ -22,9 +22,9 @@ class TestMetafunc:
|
||||||
name2fixturedefs = None
|
name2fixturedefs = None
|
||||||
def __init__(self, names):
|
def __init__(self, names):
|
||||||
self.names_closure = names
|
self.names_closure = names
|
||||||
names = funcargs.getfuncargnames(func)
|
names = fixtures.getfuncargnames(func)
|
||||||
fixtureinfo = FixtureInfo(names)
|
fixtureinfo = FixtureInfo(names)
|
||||||
return funcargs.Metafunc(func, fixtureinfo, None)
|
return python.Metafunc(func, fixtureinfo, None)
|
||||||
|
|
||||||
def test_no_funcargs(self, testdir):
|
def test_no_funcargs(self, testdir):
|
||||||
def function(): pass
|
def function(): pass
|
||||||
|
@ -558,16 +558,16 @@ class TestMetafunc:
|
||||||
|
|
||||||
def test_format_args(self):
|
def test_format_args(self):
|
||||||
def function1(): pass
|
def function1(): pass
|
||||||
assert funcargs._format_args(function1) == '()'
|
assert fixtures._format_args(function1) == '()'
|
||||||
|
|
||||||
def function2(arg1): pass
|
def function2(arg1): pass
|
||||||
assert funcargs._format_args(function2) == "(arg1)"
|
assert fixtures._format_args(function2) == "(arg1)"
|
||||||
|
|
||||||
def function3(arg1, arg2="qwe"): pass
|
def function3(arg1, arg2="qwe"): pass
|
||||||
assert funcargs._format_args(function3) == "(arg1, arg2='qwe')"
|
assert fixtures._format_args(function3) == "(arg1, arg2='qwe')"
|
||||||
|
|
||||||
def function4(arg1, *args, **kwargs): pass
|
def function4(arg1, *args, **kwargs): pass
|
||||||
assert funcargs._format_args(function4) == "(arg1, *args, **kwargs)"
|
assert fixtures._format_args(function4) == "(arg1, *args, **kwargs)"
|
||||||
|
|
||||||
|
|
||||||
class TestMetafuncFunctional:
|
class TestMetafuncFunctional:
|
||||||
|
|
Loading…
Reference in New Issue