forked from pytest-dev/pytest
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
split most fixture related code into own plugin
- Loading branch information
1 parent
7a2058e
commit 8c49561
Showing
9 changed files
with
1,348 additions
and
1,271 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: https://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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.