diff --git a/py/log/testing/test_warning.py b/py/log/testing/test_warning.py index 9a46dca2c..83610250e 100644 --- a/py/log/testing/test_warning.py +++ b/py/log/testing/test_warning.py @@ -26,3 +26,15 @@ def test_stacklevel(): lno = test_stacklevel.func_code.co_firstlineno + 6 warning = str(err) assert warning.find(":%s" % lno) != -1 + +def test_function(): + capture = py.io.StdCapture() + py.log._apiwarn("x.y.z", "something", function=test_function) + out, err = capture.reset() + print "out", out + print "err", err + assert err.find("x.y.z") != -1 + lno = test_function.func_code.co_firstlineno + exp = "%s:%s" % (mypath, lno) + assert err.find(exp) != -1 + diff --git a/py/log/warning.py b/py/log/warning.py index c6f078b0f..74a7a94a0 100644 --- a/py/log/warning.py +++ b/py/log/warning.py @@ -10,26 +10,30 @@ class Warning(py.std.exceptions.DeprecationWarning): def __str__(self): return self.msg -def _apiwarn(startversion, msg, stacklevel=1): +def _apiwarn(startversion, msg, stacklevel=1, function=None): # below is mostly COPIED from python2.4/warnings.py's def warn() # Get context information msg = "%s (since version %s)" %(msg, startversion) - warn(msg, stacklevel=stacklevel+1) + warn(msg, stacklevel=stacklevel+1, function=function) -def warn(msg, stacklevel=1): - try: - caller = sys._getframe(stacklevel) - except ValueError: - globals = sys.__dict__ - lineno = 1 +def warn(msg, stacklevel=1, function=None): + if function is not None: + filename = py.std.inspect.getfile(function) + lineno = function.func_code.co_firstlineno else: - globals = caller.f_globals - lineno = caller.f_lineno - if '__name__' in globals: - module = globals['__name__'] - else: - module = "" - filename = globals.get('__file__') + try: + caller = sys._getframe(stacklevel) + except ValueError: + globals = sys.__dict__ + lineno = 1 + else: + globals = caller.f_globals + lineno = caller.f_lineno + if '__name__' in globals: + module = globals['__name__'] + else: + module = "" + filename = globals.get('__file__') if filename: fnl = filename.lower() if fnl.endswith(".pyc") or fnl.endswith(".pyo"): diff --git a/py/test/collect.py b/py/test/collect.py index 8e92422c2..7c3c46497 100644 --- a/py/test/collect.py +++ b/py/test/collect.py @@ -347,7 +347,7 @@ class Collector(Node): setattr(self, attrname, True) method = getattr(self.__class__, 'run', None) if method is not None and method != Collector.run: - warnoldcollect() + warnoldcollect(function=method) names = self.run() return filter(None, [self.join(name) for name in names]) @@ -356,14 +356,12 @@ class Collector(Node): You can return an empty list. Callers of this method must take care to catch exceptions properly. """ - warnoldcollect() return [colitem.name for colitem in self._memocollect()] def join(self, name): """ DEPRECATED: return a child collector or item for the given name. If the return value is None there is no such child. """ - warnoldcollect() return self.collect_by_name(name) class FSCollector(Collector): @@ -451,20 +449,21 @@ class Item(Node): """ a basic test item. """ def _deprecated_testexecution(self): if self.__class__.run != Item.run: - warnoldtestrun() + warnoldtestrun(function=self.run) self.run() return True elif self.__class__.execute != Item.execute: - warnoldtestrun() + warnoldtestrun(function=self.execute) self.execute(self.obj, *self._args) return True def run(self): - warnoldtestrun() + """ deprecated, here because subclasses might call it. """ return self.execute(self.obj, *self._args) def execute(self, obj, *args): - warnoldtestrun() + """ deprecated, here because subclasses might call it. """ + warnoldtestrun(function=self.execute) return obj(*args) def repr_metainfo(self): @@ -477,14 +476,14 @@ class Item(Node): def runtest(self): """ execute this test item.""" -def warnoldcollect(): +def warnoldcollect(function=None): py.log._apiwarn("1.0", "implement collector.collect() instead of " "collector.run() and collector.join()", - stacklevel=2) + stacklevel=2, function=function) -def warnoldtestrun(): +def warnoldtestrun(function=None): py.log._apiwarn("1.0", "implement item.runtest() instead of " "item.run() and item.execute()", - stacklevel=2) + stacklevel=2, function=function) diff --git a/py/test/plugin/pytest_recwarn.py b/py/test/plugin/pytest_recwarn.py index 8b1f56036..49a67c29c 100644 --- a/py/test/plugin/pytest_recwarn.py +++ b/py/test/plugin/pytest_recwarn.py @@ -44,6 +44,7 @@ class WarningsRecorder: for i, w in py.builtin.enumerate(self.list): if issubclass(w.category, cls): return self.list.pop(i) + __tracebackhide__ = True assert 0, "%r not found in %r" %(cls, self.list) #def resetregistry(self): @@ -51,7 +52,7 @@ class WarningsRecorder: # warnings.onceregistry.clear() # warnings.__warningregistry__.clear() - def reset(self): + def clear(self): self.list[:] = [] def finalize(self): @@ -69,7 +70,7 @@ def test_WarningRecorder(): warn = rec.pop() assert str(warn.message) == "hello" l = rec.list - rec.reset() + rec.clear() assert len(rec.list) == 0 assert l is rec.list py.test.raises(AssertionError, "rec.pop()") diff --git a/py/test/testing/test_collect.py b/py/test/testing/test_collect.py index ae7084752..670f141f1 100644 --- a/py/test/testing/test_collect.py +++ b/py/test/testing/test_collect.py @@ -131,13 +131,6 @@ class TestCollectFS: names = [x.name for x in col.collect()] assert names == ["dir1", "dir2", "test_one.py", "test_two.py", "x"] - def test_collector_deprecated_run_method(self, testdir, recwarn): - modcol = testdir.getmodulecol("pass") - res1 = modcol.run() - recwarn.pop(DeprecationWarning) - res2 = modcol.collect() - assert res1 == [x.name for x in res2] - class TestCollectPluginHooks: def test_pytest_collect_file(self, testdir): tmpdir = testdir.tmpdir diff --git a/py/test/testing/test_deprecated_api.py b/py/test/testing/test_deprecated_api.py index 9f4ac9de0..1c9f83302 100644 --- a/py/test/testing/test_deprecated_api.py +++ b/py/test/testing/test_deprecated_api.py @@ -2,15 +2,8 @@ import py class TestCollectDeprecated: - def test_directory_run_join_warnings(self, testdir): - p = testdir.makepyfile(test_one="") - config = testdir.parseconfig(p) - dirnode = config.getfsnode(p.dirpath()) - py.test.deprecated_call(dirnode.run) - # XXX for directories we still have join() - #py.test.deprecated_call(dirnode.join, 'test_one') - def test_collect_with_deprecated_run_and_join(self, testdir): + def test_collect_with_deprecated_run_and_join(self, testdir, recwarn): testdir.makepyfile(conftest=""" import py @@ -52,23 +45,31 @@ class TestCollectDeprecated: """) config = testdir.parseconfig() dirnode = config.getfsnode(p.dirpath()) - colitems = py.test.deprecated_call(dirnode.collect) + colitems = dirnode.collect() + w = recwarn.pop(DeprecationWarning) + assert w.filename.find("conftest.py") != -1 + #recwarn.resetregistry() + #assert 0, (w.message, w.filename, w.lineno) assert len(colitems) == 1 modcol = colitems[0] assert modcol.name == "somefile.py" - colitems = py.test.deprecated_call(modcol.collect) + colitems = modcol.collect() + recwarn.pop(DeprecationWarning) assert len(colitems) == 2 assert colitems[0].name == 'check' assert colitems[1].name == 'Cls' clscol = colitems[1] - colitems = py.test.deprecated_call(clscol.collect) + + colitems = clscol.collect() + recwarn.pop(DeprecationWarning) assert len(colitems) == 1 icol = colitems[0] - colitems = py.test.deprecated_call(icol.collect) + colitems = icol.collect() + recwarn.pop(DeprecationWarning) assert len(colitems) == 1 assert colitems[0].name == 'check2' - def test_collect_with_deprecated_join_but_no_run(self, testdir): + def test_collect_with_deprecated_join_but_no_run(self, testdir, recwarn): testdir.makepyfile(conftest=""" import py @@ -87,42 +88,57 @@ class TestCollectDeprecated: def check_one(): pass class SomeClass: pass """) - colitems = py.test.deprecated_call(col.collect) + colitems = col.collect() + recwarn.pop(DeprecationWarning) assert len(colitems) == 1 funcitem = colitems[0] assert funcitem.name == "check_one" - def test_function_custom_run(self, testdir): + def test_function_custom_run(self, testdir, recwarn): testdir.makepyfile(conftest=""" import py - class MyFunction(py.test.collect.Function): + class Function(py.test.collect.Function): def run(self): pass - Function=MyFunction """) modcol = testdir.getmodulecol("def test_func(): pass") funcitem = modcol.collect()[0] assert funcitem.name == 'test_func' - py.test.deprecated_call(funcitem.runtest) + recwarn.clear() + funcitem.runtest() + recwarn.pop(DeprecationWarning) - def test_function_custom_execute(self, testdir): + def test_function_custom_execute(self, testdir, recwarn): testdir.makepyfile(conftest=""" import py + class MyFunction(py.test.collect.Function): def execute(self, obj, *args): pass Function=MyFunction """) - modcol = testdir.getmodulecol("def test_func(): pass") + modcol = testdir.getmodulecol("def test_func2(): pass") funcitem = modcol.collect()[0] - assert funcitem.name == 'test_func' - py.test.deprecated_call(funcitem.runtest) + assert funcitem.name == 'test_func2' + funcitem._deprecated_testexecution() + w = recwarn.pop(DeprecationWarning) + assert w.filename.find("conftest.py") != -1 - def test_function_deprecated_run_execute(self, testdir): - modcol = testdir.getmodulecol("def test_some(): pass") + def test_function_deprecated_run_execute(self, testdir, recwarn): + testdir.makepyfile(conftest=""" + import py + + class Function(py.test.collect.Function): + + def run(self): + pass + """) + modcol = testdir.getmodulecol("def test_some2(): pass") funcitem = modcol.collect()[0] - py.test.deprecated_call(funcitem.run) - py.test.deprecated_call(funcitem.execute, funcitem.obj) + + recwarn.clear() + funcitem._deprecated_testexecution() + recwarn.pop(DeprecationWarning) def test_function_deprecated_run_recursive(self, testdir): testdir.makepyfile(conftest="""