From 5603a0cd4b6adf4fbf5e490216ebfcc0befbf10a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 31 Jul 2014 19:13:40 -0300 Subject: [PATCH 1/4] Removing py.std usage from _pytest --- _pytest/assertion/oldinterpret.py | 5 ++-- _pytest/assertion/util.py | 16 +++++++------ _pytest/config.py | 35 +++++++++++++++------------ _pytest/core.py | 5 ++-- _pytest/doctest.py | 15 ++++++------ _pytest/genscript.py | 12 ++++++---- _pytest/junitxml.py | 5 ++-- _pytest/main.py | 5 ++-- _pytest/pdb.py | 20 +++++++++------- _pytest/pytester.py | 39 +++++++++++++++++-------------- _pytest/recwarn.py | 26 +++++++++------------ _pytest/runner.py | 7 +++--- _pytest/skipping.py | 11 +++++---- _pytest/terminal.py | 10 ++++---- _pytest/tmpdir.py | 8 +++++-- _pytest/unittest.py | 12 +++++++--- 16 files changed, 134 insertions(+), 97 deletions(-) diff --git a/_pytest/assertion/oldinterpret.py b/_pytest/assertion/oldinterpret.py index df737b7d5..40c6d3936 100644 --- a/_pytest/assertion/oldinterpret.py +++ b/_pytest/assertion/oldinterpret.py @@ -1,3 +1,5 @@ +import traceback +import types import py import sys, inspect from compiler import parse, ast, pycodegen @@ -477,7 +479,7 @@ def check(s, frame=None): def interpret(source, frame, should_fail=False): module = Interpretable(parse(source, 'exec').node) #print "got module", module - if isinstance(frame, py.std.types.FrameType): + if isinstance(frame, types.FrameType): frame = py.code.Frame(frame) try: module.run(frame) @@ -487,7 +489,6 @@ def interpret(source, frame, should_fail=False): except passthroughex: raise except: - import traceback traceback.print_exc() if should_fail: return ("(assertion failed, but when it was re-run for " diff --git a/_pytest/assertion/util.py b/_pytest/assertion/util.py index 3564e4882..95d308518 100644 --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -1,4 +1,5 @@ """Utilities for assertion debugging""" +import pprint import py try: @@ -168,6 +169,7 @@ def _diff_text(left, right, verbose=False): If the input are bytes they will be safely converted to text. """ + from difflib import ndiff explanation = [] if isinstance(left, py.builtin.bytes): left = u(repr(left)[1:-1]).replace(r'\n', '\n') @@ -195,8 +197,8 @@ def _diff_text(left, right, verbose=False): left = left[:-i] right = right[:-i] explanation += [line.strip('\n') - for line in py.std.difflib.ndiff(left.splitlines(), - right.splitlines())] + for line in ndiff(left.splitlines(), + right.splitlines())] return explanation @@ -214,8 +216,8 @@ def _compare_eq_sequence(left, right, verbose=False): explanation += [ u('Right contains more items, first extra item: %s') % py.io.saferepr(right[len(left)],)] - return explanation # + _diff_text(py.std.pprint.pformat(left), - # py.std.pprint.pformat(right)) + return explanation # + _diff_text(pprint.pformat(left), + # pprint.pformat(right)) def _compare_eq_set(left, right, verbose=False): @@ -242,7 +244,7 @@ def _compare_eq_dict(left, right, verbose=False): len(same)] elif same: explanation += [u('Common items:')] - explanation += py.std.pprint.pformat(same).splitlines() + explanation += pprint.pformat(same).splitlines() diff = set(k for k in common if left[k] != right[k]) if diff: explanation += [u('Differing items:')] @@ -252,12 +254,12 @@ def _compare_eq_dict(left, right, verbose=False): extra_left = set(left) - set(right) if extra_left: explanation.append(u('Left contains more items:')) - explanation.extend(py.std.pprint.pformat( + explanation.extend(pprint.pformat( dict((k, left[k]) for k in extra_left)).splitlines()) extra_right = set(right) - set(left) if extra_right: explanation.append(u('Right contains more items:')) - explanation.extend(py.std.pprint.pformat( + explanation.extend(pprint.pformat( dict((k, right[k]) for k in extra_right)).splitlines()) return explanation diff --git a/_pytest/config.py b/_pytest/config.py index 1eeb6b3b7..12adc21f8 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -1,4 +1,9 @@ """ command line options, ini-file and conftest.py processing. """ +import argparse +import shlex +import traceback +import types +import warnings import py # DON't import pytest here because it causes import cycle troubles @@ -29,7 +34,7 @@ def main(args=None, plugins=None): except ConftestImportFailure: e = sys.exc_info()[1] tw = py.io.TerminalWriter(sys.stderr) - for line in py.std.traceback.format_exception(*e.excinfo): + for line in traceback.format_exception(*e.excinfo): tw.line(line.rstrip(), red=True) tw.line("ERROR: could not load %s\n" % (e.path), red=True) return 4 @@ -71,7 +76,7 @@ def _prepareconfig(args=None, plugins=None): elif not isinstance(args, (tuple, list)): if not isinstance(args, str): raise ValueError("not a string or argument list: %r" % (args,)) - args = py.std.shlex.split(args) + args = shlex.split(args) pluginmanager = get_plugin_manager() try: if plugins: @@ -229,7 +234,7 @@ class ArgumentError(Exception): class Argument: - """class that mimics the necessary behaviour of py.std.optparse.Option """ + """class that mimics the necessary behaviour of optparse.Option """ _typ_map = { 'int': int, 'string': str, @@ -247,7 +252,7 @@ class Argument: try: help = attrs['help'] if '%default' in help: - py.std.warnings.warn( + warnings.warn( 'pytest now uses argparse. "%default" should be' ' changed to "%(default)s" ', FutureWarning, @@ -263,7 +268,7 @@ class Argument: if isinstance(typ, py.builtin._basestring): if typ == 'choice': if self.TYPE_WARN: - py.std.warnings.warn( + warnings.warn( 'type argument to addoption() is a string %r.' ' For parsearg this is optional and when supplied ' ' should be a type.' @@ -275,7 +280,7 @@ class Argument: attrs['type'] = type(attrs['choices'][0]) else: if self.TYPE_WARN: - py.std.warnings.warn( + warnings.warn( 'type argument to addoption() is a string %r.' ' For parsearg this should be a type.' ' (options: %s)' % (typ, names), @@ -395,10 +400,10 @@ class OptionGroup: self.options.append(option) -class MyOptionParser(py.std.argparse.ArgumentParser): +class MyOptionParser(argparse.ArgumentParser): def __init__(self, parser): self._parser = parser - py.std.argparse.ArgumentParser.__init__(self, usage=parser._usage, + argparse.ArgumentParser.__init__(self, usage=parser._usage, add_help=False, formatter_class=DropShorterLongHelpFormatter) def parse_args(self, args=None, namespace=None): @@ -407,12 +412,12 @@ class MyOptionParser(py.std.argparse.ArgumentParser): if argv: for arg in argv: if arg and arg[0] == '-': - msg = py.std.argparse._('unrecognized arguments: %s') + msg = argparse._('unrecognized arguments: %s') self.error(msg % ' '.join(argv)) getattr(args, FILE_OR_DIR).extend(argv) return args -class DropShorterLongHelpFormatter(py.std.argparse.HelpFormatter): +class DropShorterLongHelpFormatter(argparse.HelpFormatter): """shorten help for long options that differ only in extra hyphens - collapse **long** options that are the same except for extra hyphens @@ -422,7 +427,7 @@ class DropShorterLongHelpFormatter(py.std.argparse.HelpFormatter): - cache result on action object as this is called at least 2 times """ def _format_action_invocation(self, action): - orgstr = py.std.argparse.HelpFormatter._format_action_invocation(self, action) + orgstr = argparse.HelpFormatter._format_action_invocation(self, action) if orgstr and orgstr[0] != '-': # only optional arguments return orgstr res = getattr(action, '_formatted_action_invocation', None) @@ -746,7 +751,7 @@ class Config(object): self.hook.pytest_cmdline_preparse(config=self, args=args) args = self._parser.parse_setoption(args, self.option) if not args: - args.append(py.std.os.getcwd()) + args.append(os.getcwd()) self.args = args def addinivalue_line(self, name, line): @@ -784,11 +789,11 @@ class Config(object): if type == "pathlist": dp = py.path.local(self.inicfg.config.path).dirpath() l = [] - for relpath in py.std.shlex.split(value): + for relpath in shlex.split(value): l.append(dp.join(relpath, abs=True)) return l elif type == "args": - return py.std.shlex.split(value) + return shlex.split(value) elif type == "linelist": return [t for t in map(lambda x: x.strip(), value.split("\n")) if t] else: @@ -876,7 +881,7 @@ def setns(obj, dic): mod = getattr(obj, name, None) if mod is None: modname = "pytest.%s" % name - mod = py.std.types.ModuleType(modname) + mod = types.ModuleType(modname) sys.modules[modname] = mod mod.__all__ = [] setattr(obj, name, mod) diff --git a/_pytest/core.py b/_pytest/core.py index 6ede18d95..de422e149 100644 --- a/_pytest/core.py +++ b/_pytest/core.py @@ -1,6 +1,7 @@ """ pytest PluginManager, basic initialization and tracing. """ +import os import sys import inspect import py @@ -154,7 +155,7 @@ class PluginManager(object): # API for bootstrapping # def _envlist(self, varname): - val = py.std.os.environ.get(varname, None) + val = os.environ.get(varname, None) if val is not None: return val.split(',') return () @@ -221,7 +222,7 @@ class PluginManager(object): return self.import_plugin(modname[7:]) raise except: - e = py.std.sys.exc_info()[1] + e = sys.exc_info()[1] import pytest if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception): raise diff --git a/_pytest/doctest.py b/_pytest/doctest.py index 82bbc4b49..f61730717 100644 --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -1,5 +1,6 @@ """ discover and run doctests in modules and test files.""" - +from __future__ import absolute_import +import traceback import pytest, py from _pytest.python import FixtureRequest, FuncFixtureInfo from py._code.code import TerminalRepr, ReprFileLocation @@ -43,7 +44,7 @@ class DoctestItem(pytest.Item): self.runner.run(self.dtest) def repr_failure(self, excinfo): - doctest = py.std.doctest + import doctest if excinfo.errisinstance((doctest.DocTestFailure, doctest.UnexpectedException)): doctestfailure = excinfo.value @@ -56,8 +57,8 @@ class DoctestItem(pytest.Item): lineno = test.lineno + example.lineno + 1 message = excinfo.type.__name__ reprlocation = ReprFileLocation(filename, lineno, message) - checker = py.std.doctest.OutputChecker() - REPORT_UDIFF = py.std.doctest.REPORT_UDIFF + checker = doctest.OutputChecker() + REPORT_UDIFF = doctest.REPORT_UDIFF filelines = py.path.local(filename).readlines(cr=0) lines = [] if lineno is not None: @@ -78,7 +79,7 @@ class DoctestItem(pytest.Item): inner_excinfo = py.code.ExceptionInfo(excinfo.value.exc_info) lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)] - lines += py.std.traceback.format_exception(*excinfo.value.exc_info) + lines += traceback.format_exception(*excinfo.value.exc_info) return ReprFailDoctest(reprlocation, lines) else: return super(DoctestItem, self).repr_failure(excinfo) @@ -88,7 +89,7 @@ class DoctestItem(pytest.Item): class DoctestTextfile(DoctestItem, pytest.File): def runtest(self): - doctest = py.std.doctest + import doctest # satisfy `FixtureRequest` constructor... self.funcargs = {} fm = self.session._fixturemanager @@ -106,7 +107,7 @@ class DoctestTextfile(DoctestItem, pytest.File): class DoctestModule(pytest.File): def collect(self): - doctest = py.std.doctest + import doctest if self.fspath.basename == "conftest.py": module = self.config._conftest.importconftest(self.fspath) else: diff --git a/_pytest/genscript.py b/_pytest/genscript.py index 25e8e6a0f..7dddcfc57 100755 --- a/_pytest/genscript.py +++ b/_pytest/genscript.py @@ -1,9 +1,13 @@ """ generate a single-file self-contained version of pytest """ +import base64 +import pickle import py import sys +import zlib + def find_toplevel(name): - for syspath in py.std.sys.path: + for syspath in sys.path: base = py.path.local(syspath) lib = base/name if lib.check(dir=1): @@ -29,9 +33,9 @@ def pkg_to_mapping(name): return name2src def compress_mapping(mapping): - data = py.std.pickle.dumps(mapping, 2) - data = py.std.zlib.compress(data, 9) - data = py.std.base64.encodestring(data) + data = pickle.dumps(mapping, 2) + data = zlib.compress(data, 9) + data = base64.encodestring(data) data = data.decode('ascii') return data diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py index bc4c72590..2a86c8dee 100644 --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -2,6 +2,7 @@ Based on initial code from Ross Lawley. """ +import codecs import py import os @@ -206,8 +207,8 @@ class LogXML(object): self.suite_start_time = time.time() def pytest_sessionfinish(self): - if py.std.sys.version_info[0] < 3: - logfile = py.std.codecs.open(self.logfile, 'w', encoding='utf-8') + if sys.version_info[0] < 3: + logfile = codecs.open(self.logfile, 'w', encoding='utf-8') else: logfile = open(self.logfile, 'w', encoding='utf-8') diff --git a/_pytest/main.py b/_pytest/main.py index 9ab13abd3..cbe2fabda 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -1,4 +1,5 @@ """ core implementation of testing process: init, session, runtest loop. """ +import re import py import pytest, _pytest @@ -19,7 +20,7 @@ EXIT_INTERRUPTED = 2 EXIT_INTERNALERROR = 3 EXIT_USAGEERROR = 4 -name_re = py.std.re.compile("^[a-zA-Z_]\w*$") +name_re = re.compile("^[a-zA-Z_]\w*$") def pytest_addoption(parser): parser.addini("norecursedirs", "directory patterns to avoid for recursion", @@ -315,7 +316,7 @@ class Node(object): except py.builtin._sysex: raise except: - failure = py.std.sys.exc_info() + failure = sys.exc_info() setattr(self, exattrname, failure) raise setattr(self, attrname, res) diff --git a/_pytest/pdb.py b/_pytest/pdb.py index 9a0dd9aa7..607a4582b 100644 --- a/_pytest/pdb.py +++ b/_pytest/pdb.py @@ -1,8 +1,12 @@ """ interactive debugging with PDB, the Python Debugger. """ - -import pytest, py +from __future__ import absolute_import +import pdb import sys +import pytest +import py + + def pytest_addoption(parser): group = parser.getgroup("general") group._addoption('--pdb', @@ -16,10 +20,10 @@ def pytest_configure(config): if config.getvalue("usepdb"): config.pluginmanager.register(PdbInvoke(), 'pdbinvoke') - old = (py.std.pdb.set_trace, pytestPDB._pluginmanager) + old = (pdb.set_trace, pytestPDB._pluginmanager) def fin(): - py.std.pdb.set_trace, pytestPDB._pluginmanager = old - py.std.pdb.set_trace = pytest.set_trace + pdb.set_trace, pytestPDB._pluginmanager = old + pdb.set_trace = pytest.set_trace pytestPDB._pluginmanager = config.pluginmanager config._cleanup.append(fin) @@ -38,7 +42,7 @@ class pytestPDB: tw = py.io.TerminalWriter() tw.line() tw.sep(">", "PDB set_trace (IO-capturing turned off)") - py.std.pdb.Pdb().set_trace(frame) + pdb.Pdb().set_trace(frame) class PdbInvoke: @@ -74,7 +78,8 @@ def _enter_pdb(node, excinfo, rep): def _postmortem_traceback(excinfo): # A doctest.UnexpectedException is not useful for post_mortem. # Use the underlying exception instead: - if isinstance(excinfo.value, py.std.doctest.UnexpectedException): + from doctest import UnexpectedException + if isinstance(excinfo.value, UnexpectedException): return excinfo.value.exc_info[2] else: return excinfo._excinfo[2] @@ -88,7 +93,6 @@ def _find_last_non_hidden_frame(stack): def post_mortem(t): - pdb = py.std.pdb class Pdb(pdb.Pdb): def get_stack(self, f, t): stack, i = pdb.Pdb.get_stack(self, f, t) diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 36713bf2c..9e987ae03 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -1,15 +1,21 @@ """ (disabled by default) support for testing pytest and pytest plugins. """ - -import py, pytest -import sys, os +import inspect +import sys +import os import codecs import re import time +import platform from fnmatch import fnmatch -from _pytest.main import Session, EXIT_OK +import subprocess + +import py +import pytest from py.builtin import print_ from _pytest.core import HookRelay +from _pytest.main import Session, EXIT_OK + def get_public_names(l): """Only return names from iterator l without a leading underscore.""" @@ -87,10 +93,10 @@ class HookRecorder: def _makecallparser(self, method): name = method.__name__ - args, varargs, varkw, default = py.std.inspect.getargspec(method) + args, varargs, varkw, default = inspect.getargspec(method) if not args or args[0] != "self": args.insert(0, 'self') - fspec = py.std.inspect.formatargspec(args, varargs, varkw, default) + fspec = inspect.formatargspec(args, varargs, varkw, default) # we use exec because we want to have early type # errors on wrong input arguments, using # *args/**kwargs delays this and gives errors @@ -122,7 +128,7 @@ class HookRecorder: __tracebackhide__ = True i = 0 entries = list(entries) - backlocals = py.std.sys._getframe(1).f_locals + backlocals = sys._getframe(1).f_locals while entries: name, check = entries.pop(0) for ind, call in enumerate(self.calls[i:]): @@ -210,7 +216,7 @@ class TmpTestdir: def finalize(self): for p in self._syspathremove: - py.std.sys.path.remove(p) + sys.path.remove(p) if hasattr(self, '_olddir'): self._olddir.chdir() # delete modules that have been loaded from tmpdir @@ -283,7 +289,7 @@ class TmpTestdir: def syspathinsert(self, path=None): if path is None: path = self.tmpdir - py.std.sys.path.insert(0, str(path)) + sys.path.insert(0, str(path)) self._syspathremove.append(str(path)) def mkdir(self, name): @@ -426,9 +432,8 @@ class TmpTestdir: env['PYTHONPATH'] = os.pathsep.join(filter(None, [ str(os.getcwd()), env.get('PYTHONPATH', '')])) kw['env'] = env - #print "env", env - return py.std.subprocess.Popen(cmdargs, - stdout=stdout, stderr=stderr, **kw) + return subprocess.Popen(cmdargs, + stdout=stdout, stderr=stderr, **kw) def run(self, *cmdargs): return self._run(*cmdargs) @@ -474,9 +479,9 @@ class TmpTestdir: def _getpybinargs(self, scriptname): if not self.request.config.getvalue("notoolsonpath"): # XXX we rely on script referring to the correct environment - # we cannot use "(py.std.sys.executable,script)" + # we cannot use "(sys.executable,script)" # because on windows the script is e.g. a py.test.exe - return (py.std.sys.executable, _pytest_fullpath,) # noqa + return (sys.executable, _pytest_fullpath,) # noqa else: pytest.skip("cannot run %r with --no-tools-on-path" % scriptname) @@ -496,7 +501,7 @@ class TmpTestdir: def runpython_c(self, command): command = self._getsysprepend() + command - return self.run(py.std.sys.executable, "-c", command) + return self.run(sys.executable, "-c", command) def runpytest(self, *args): p = py.path.local.make_numbered_dir(prefix="runpytest-", @@ -523,7 +528,7 @@ class TmpTestdir: def spawn(self, cmd, expect_timeout=10.0): pexpect = pytest.importorskip("pexpect", "3.0") - if hasattr(sys, 'pypy_version_info') and '64' in py.std.platform.machine(): + if hasattr(sys, 'pypy_version_info') and '64' in platform.machine(): pytest.skip("pypy-64 bit not supported") if sys.platform == "darwin": pytest.xfail("pexpect does not work reliably on darwin?!") @@ -670,7 +675,7 @@ class LineMatcher: def fnmatch_lines(self, lines2): def show(arg1, arg2): - py.builtin.print_(arg1, arg2, file=py.std.sys.stderr) + py.builtin.print_(arg1, arg2, file=sys.stderr) lines2 = self._getlines(lines2) lines1 = self.lines[:] nextline = None diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py index 987ff8f97..482b78b0e 100644 --- a/_pytest/recwarn.py +++ b/_pytest/recwarn.py @@ -1,7 +1,8 @@ """ recording warnings during test function execution. """ -import py import sys +import warnings + def pytest_funcarg__recwarn(request): """Return a WarningsRecorder instance that provides these methods: @@ -13,7 +14,6 @@ def pytest_funcarg__recwarn(request): on warning categories. """ if sys.version_info >= (2,7): - import warnings oldfilters = warnings.filters[:] warnings.simplefilter('default') def reset_filters(): @@ -30,26 +30,24 @@ def deprecated_call(func, *args, **kwargs): """ assert that calling ``func(*args, **kwargs)`` triggers a DeprecationWarning. """ - warningmodule = py.std.warnings l = [] - oldwarn_explicit = getattr(warningmodule, 'warn_explicit') + oldwarn_explicit = getattr(warnings, 'warn_explicit') def warn_explicit(*args, **kwargs): l.append(args) oldwarn_explicit(*args, **kwargs) - oldwarn = getattr(warningmodule, 'warn') + oldwarn = getattr(warnings, 'warn') def warn(*args, **kwargs): l.append(args) oldwarn(*args, **kwargs) - warningmodule.warn_explicit = warn_explicit - warningmodule.warn = warn + warnings.warn_explicit = warn_explicit + warnings.warn = warn try: ret = func(*args, **kwargs) finally: - warningmodule.warn_explicit = warn_explicit - warningmodule.warn = warn + warnings.warn_explicit = warn_explicit + warnings.warn = warn if not l: - #print warningmodule __tracebackhide__ = True raise AssertionError("%r did not produce DeprecationWarning" %(func,)) return ret @@ -65,7 +63,6 @@ class RecordedWarning: class WarningsRecorder: def __init__(self): - warningmodule = py.std.warnings self.list = [] def showwarning(message, category, filename, lineno, line=0): self.list.append(RecordedWarning( @@ -76,8 +73,8 @@ class WarningsRecorder: except TypeError: # < python2.6 self.old_showwarning(message, category, filename, lineno) - self.old_showwarning = warningmodule.showwarning - warningmodule.showwarning = showwarning + self.old_showwarning = warnings.showwarning + warnings.showwarning = showwarning def pop(self, cls=Warning): """ pop the first recorded warning, raise exception if not exists.""" @@ -88,7 +85,6 @@ class WarningsRecorder: assert 0, "%r not found in %r" %(cls, self.list) #def resetregistry(self): - # import warnings # warnings.onceregistry.clear() # warnings.__warningregistry__.clear() @@ -96,4 +92,4 @@ class WarningsRecorder: self.list[:] = [] def finalize(self): - py.std.warnings.showwarning = self.old_showwarning + warnings.showwarning = self.old_showwarning diff --git a/_pytest/runner.py b/_pytest/runner.py index 428e6ec42..2932f14c3 100644 --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -1,9 +1,10 @@ """ basic collect and runtest protocol implementations """ +import bdb +import sys +from time import time import py import pytest -import sys -from time import time from py._code.code import TerminalRepr def pytest_namespace(): @@ -118,7 +119,7 @@ def check_interactive_exception(call, report): return call.excinfo and not ( hasattr(report, "wasxfail") or call.excinfo.errisinstance(skip.Exception) or - call.excinfo.errisinstance(py.std.bdb.BdbQuit)) + call.excinfo.errisinstance(bdb.BdbQuit)) def call_runtest_hook(item, when, **kwds): hookname = "pytest_runtest_" + when diff --git a/_pytest/skipping.py b/_pytest/skipping.py index aee98ffa8..56f28b118 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -1,7 +1,10 @@ """ support for skip/xfail functions and markers. """ - -import py, pytest +import os import sys +import traceback + +import py +import pytest def pytest_addoption(parser): group = parser.getgroup("general") @@ -79,7 +82,7 @@ class MarkEvaluator: msg = [" " * (self.exc[1].offset + 4) + "^",] msg.append("SyntaxError: invalid syntax") else: - msg = py.std.traceback.format_exception_only(*self.exc[:2]) + msg = traceback.format_exception_only(*self.exc[:2]) pytest.fail("Error evaluating %r expression\n" " %s\n" "%s" @@ -87,7 +90,7 @@ class MarkEvaluator: pytrace=False) def _getglobals(self): - d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config} + d = {'os': os, 'sys': sys, 'config': self.item.config} func = self.item.obj try: d.update(func.__globals__) diff --git a/_pytest/terminal.py b/_pytest/terminal.py index abb8f1549..f60d8495e 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -5,6 +5,8 @@ This is a good source for looking at the various reporting hooks. import pytest import py import sys +import time + def pytest_addoption(parser): group = parser.getgroup("terminal reporting", "reporting", after="general") @@ -49,7 +51,7 @@ def getreportopt(config): optvalue = config.option.report if optvalue: py.builtin.print_("DEPRECATED: use -r instead of --report option.", - file=py.std.sys.stderr) + file=sys.stderr) if optvalue: for setting in optvalue.split(","): setting = setting.strip() @@ -95,7 +97,7 @@ class TerminalReporter: self.stats = {} self.startdir = self.curdir = py.path.local() if file is None: - file = py.std.sys.stdout + file = sys.stdout self._tw = self.writer = py.io.TerminalWriter(file) if self.config.option.color == 'yes': self._tw.hasmarkup = True @@ -265,7 +267,7 @@ class TerminalReporter: @pytest.mark.trylast def pytest_sessionstart(self, session): - self._sessionstarttime = py.std.time.time() + self._sessionstarttime = time.time() if not self.showheader: return self.write_sep("=", "test session starts", bold=True) @@ -469,7 +471,7 @@ class TerminalReporter: self._tw.line(content) def summary_stats(self): - session_duration = py.std.time.time() - self._sessionstarttime + session_duration = time.time() - self._sessionstarttime keys = ("failed passed skipped deselected " "xfailed xpassed warnings").split() diff --git a/_pytest/tmpdir.py b/_pytest/tmpdir.py index 8eb0cdec0..53c396b76 100644 --- a/_pytest/tmpdir.py +++ b/_pytest/tmpdir.py @@ -1,7 +1,11 @@ """ support for providing temporary directories to test functions. """ -import pytest, py +import re + +import pytest +import py from _pytest.monkeypatch import monkeypatch + class TempdirHandler: def __init__(self, config): self.config = config @@ -63,7 +67,7 @@ def tmpdir(request): path object. """ name = request.node.name - name = py.std.re.sub("[\W]", "_", name) + name = re.sub("[\W]", "_", name) MAXVAL = 30 if len(name) > MAXVAL: name = name[:MAXVAL] diff --git a/_pytest/unittest.py b/_pytest/unittest.py index 435a93514..666519129 100644 --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -1,7 +1,13 @@ """ discovery and running of std-library "unittest" style tests. """ -import pytest, py +from __future__ import absolute_import +import traceback +import unittest import sys +import pytest +import py + + # for transfering markers from _pytest.python import transfer_markers @@ -45,7 +51,7 @@ class UnitTestCase(pytest.Class): if not getattr(cls, "__test__", True): return self.session._fixturemanager.parsefactories(self, unittest=True) - loader = py.std.unittest.TestLoader() + loader = unittest.TestLoader() module = self.getparent(pytest.Module).obj foundsomething = False for name in loader.getTestCaseNames(self.obj): @@ -90,7 +96,7 @@ class TestCaseFunction(pytest.Function): except TypeError: try: try: - l = py.std.traceback.format_exception(*rawexcinfo) + l = traceback.format_exception(*rawexcinfo) l.insert(0, "NOTE: Incompatible Exception Representation, " "displaying natively:\n\n") pytest.fail("".join(l), pytrace=False) From b1f8038abfb6203d4bf08cefff56cf5c81b2c87f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 31 Jul 2014 19:52:08 -0300 Subject: [PATCH 2/4] Minor fixed in test_capture This test failed only in py34. We don't import logging directly, but it seems that one of the standard modules that are now globally imported started including this on py34. Just removed the assert as it doesn't seem central to the test's objective. --- testing/test_capture.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/testing/test_capture.py b/testing/test_capture.py index 591b6761d..02b952be3 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -340,8 +340,6 @@ class TestLoggingInteraction: p = testdir.makepyfile(""" import sys def test_something(): - # pytest does not import logging - assert 'logging' not in sys.modules import logging logging.basicConfig() logging.warn("hello432") From d6fc489b2bb52fd021bdf6f0513c78bb8d9287e1 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 1 Aug 2014 08:13:44 +0200 Subject: [PATCH 3/4] Backed out changeset e57017ad86ce -- logging should not be imported --- testing/test_capture.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testing/test_capture.py b/testing/test_capture.py index 02b952be3..591b6761d 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -340,6 +340,8 @@ class TestLoggingInteraction: p = testdir.makepyfile(""" import sys def test_something(): + # pytest does not import logging + assert 'logging' not in sys.modules import logging logging.basicConfig() logging.warn("hello432") From 97b671057d119709ab5baf69fe4aae6b8bd6a5f1 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 1 Aug 2014 10:12:53 +0200 Subject: [PATCH 4/4] put some imports back to function-level and streamline py2/py3 compat in one place --- CHANGELOG | 3 +++ _pytest/__init__.py | 2 +- _pytest/genscript.py | 4 +--- _pytest/junitxml.py | 21 ++++----------------- _pytest/unittest.py | 27 ++++++++++----------------- setup.py | 2 +- 6 files changed, 20 insertions(+), 39 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c2f53fef6..88ac07419 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,9 @@ NEXT - fix issue544 by only removing "@NUM" at the end of "::" separated parts and if the part has an ".py" extension +- don't use py.std import helper, rather import things directly. + Thanks Bruno Oliveira. + 2.6 ----------------------------------- diff --git a/_pytest/__init__.py b/_pytest/__init__.py index f8d003fcf..35cf9d652 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.6.1.dev1' +__version__ = '2.6.1.dev2' diff --git a/_pytest/genscript.py b/_pytest/genscript.py index 7dddcfc57..9104dcab8 100755 --- a/_pytest/genscript.py +++ b/_pytest/genscript.py @@ -1,9 +1,6 @@ """ generate a single-file self-contained version of pytest """ -import base64 -import pickle import py import sys -import zlib def find_toplevel(name): @@ -33,6 +30,7 @@ def pkg_to_mapping(name): return name2src def compress_mapping(mapping): + import base64, pickle, zlib data = pickle.dumps(mapping, 2) data = zlib.compress(data, 9) data = base64.encodestring(data) diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py index 2a86c8dee..2371e17ba 100644 --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -2,8 +2,6 @@ Based on initial code from Ross Lawley. """ -import codecs - import py import os import re @@ -11,20 +9,13 @@ import sys import time # Python 2.X and 3.X compatibility -try: - unichr(65) -except NameError: +if sys.version_info[0] < 3: + from codecs import open +else: unichr = chr -try: - unicode('A') -except NameError: unicode = str -try: - long(1) -except NameError: long = int - class Junit(py.xml.Namespace): pass @@ -207,11 +198,7 @@ class LogXML(object): self.suite_start_time = time.time() def pytest_sessionfinish(self): - if sys.version_info[0] < 3: - logfile = codecs.open(self.logfile, 'w', encoding='utf-8') - else: - logfile = open(self.logfile, 'w', encoding='utf-8') - + logfile = open(self.logfile, 'w', encoding='utf-8') suite_stop_time = time.time() suite_time_delta = suite_stop_time - self.suite_start_time numtests = self.passed + self.failed diff --git a/_pytest/unittest.py b/_pytest/unittest.py index 666519129..af2aa9357 100644 --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -1,7 +1,6 @@ """ discovery and running of std-library "unittest" style tests. """ from __future__ import absolute_import import traceback -import unittest import sys import pytest @@ -12,22 +11,15 @@ import py from _pytest.python import transfer_markers -def is_unittest(obj): - """Is obj a subclass of unittest.TestCase?""" - unittest = sys.modules.get('unittest') - if unittest is None: - return # nobody can have derived unittest.TestCase - try: - return issubclass(obj, unittest.TestCase) - except KeyboardInterrupt: - raise - except: - return False - - def pytest_pycollect_makeitem(collector, name, obj): - if is_unittest(obj): - return UnitTestCase(name, parent=collector) + # has unittest been imported and is obj a subclass of its TestCase? + try: + if not issubclass(obj, sys.modules["unittest"].TestCase): + return + except Exception: + return + # yes, so let's collect it + return UnitTestCase(name, parent=collector) class UnitTestCase(pytest.Class): @@ -47,11 +39,12 @@ class UnitTestCase(pytest.Class): super(UnitTestCase, self).setup() def collect(self): + from unittest import TestLoader cls = self.obj if not getattr(cls, "__test__", True): return self.session._fixturemanager.parsefactories(self, unittest=True) - loader = unittest.TestLoader() + loader = TestLoader() module = self.getparent(pytest.Module).obj foundsomething = False for name in loader.getTestCaseNames(self.obj): diff --git a/setup.py b/setup.py index e3ad2ad15..1c34bb2c0 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def main(): name='pytest', description='pytest: simple powerful testing with Python', long_description=long_description, - version='2.6.1.dev1', + version='2.6.1.dev2', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],