greatly refine deprecaction warnings and use new "recwarn" plugin for it.

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-05-05 22:31:18 +02:00
parent 671684be5c
commit 3245b0c1af
6 changed files with 86 additions and 61 deletions

View File

@ -26,3 +26,15 @@ def test_stacklevel():
lno = test_stacklevel.func_code.co_firstlineno + 6 lno = test_stacklevel.func_code.co_firstlineno + 6
warning = str(err) warning = str(err)
assert warning.find(":%s" % lno) != -1 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

View File

@ -10,13 +10,17 @@ class Warning(py.std.exceptions.DeprecationWarning):
def __str__(self): def __str__(self):
return self.msg 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() # below is mostly COPIED from python2.4/warnings.py's def warn()
# Get context information # Get context information
msg = "%s (since version %s)" %(msg, startversion) msg = "%s (since version %s)" %(msg, startversion)
warn(msg, stacklevel=stacklevel+1) warn(msg, stacklevel=stacklevel+1, function=function)
def warn(msg, stacklevel=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:
try: try:
caller = sys._getframe(stacklevel) caller = sys._getframe(stacklevel)
except ValueError: except ValueError:

View File

@ -347,7 +347,7 @@ class Collector(Node):
setattr(self, attrname, True) setattr(self, attrname, True)
method = getattr(self.__class__, 'run', None) method = getattr(self.__class__, 'run', None)
if method is not None and method != Collector.run: if method is not None and method != Collector.run:
warnoldcollect() warnoldcollect(function=method)
names = self.run() names = self.run()
return filter(None, [self.join(name) for name in names]) 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 You can return an empty list. Callers of this method
must take care to catch exceptions properly. must take care to catch exceptions properly.
""" """
warnoldcollect()
return [colitem.name for colitem in self._memocollect()] return [colitem.name for colitem in self._memocollect()]
def join(self, name): def join(self, name):
""" DEPRECATED: return a child collector or item for the given name. """ DEPRECATED: return a child collector or item for the given name.
If the return value is None there is no such child. If the return value is None there is no such child.
""" """
warnoldcollect()
return self.collect_by_name(name) return self.collect_by_name(name)
class FSCollector(Collector): class FSCollector(Collector):
@ -451,20 +449,21 @@ class Item(Node):
""" a basic test item. """ """ a basic test item. """
def _deprecated_testexecution(self): def _deprecated_testexecution(self):
if self.__class__.run != Item.run: if self.__class__.run != Item.run:
warnoldtestrun() warnoldtestrun(function=self.run)
self.run() self.run()
return True return True
elif self.__class__.execute != Item.execute: elif self.__class__.execute != Item.execute:
warnoldtestrun() warnoldtestrun(function=self.execute)
self.execute(self.obj, *self._args) self.execute(self.obj, *self._args)
return True return True
def run(self): def run(self):
warnoldtestrun() """ deprecated, here because subclasses might call it. """
return self.execute(self.obj, *self._args) return self.execute(self.obj, *self._args)
def execute(self, obj, *args): def execute(self, obj, *args):
warnoldtestrun() """ deprecated, here because subclasses might call it. """
warnoldtestrun(function=self.execute)
return obj(*args) return obj(*args)
def repr_metainfo(self): def repr_metainfo(self):
@ -477,14 +476,14 @@ class Item(Node):
def runtest(self): def runtest(self):
""" execute this test item.""" """ execute this test item."""
def warnoldcollect(): def warnoldcollect(function=None):
py.log._apiwarn("1.0", py.log._apiwarn("1.0",
"implement collector.collect() instead of " "implement collector.collect() instead of "
"collector.run() and collector.join()", "collector.run() and collector.join()",
stacklevel=2) stacklevel=2, function=function)
def warnoldtestrun(): def warnoldtestrun(function=None):
py.log._apiwarn("1.0", py.log._apiwarn("1.0",
"implement item.runtest() instead of " "implement item.runtest() instead of "
"item.run() and item.execute()", "item.run() and item.execute()",
stacklevel=2) stacklevel=2, function=function)

View File

@ -44,6 +44,7 @@ class WarningsRecorder:
for i, w in py.builtin.enumerate(self.list): for i, w in py.builtin.enumerate(self.list):
if issubclass(w.category, cls): if issubclass(w.category, cls):
return self.list.pop(i) return self.list.pop(i)
__tracebackhide__ = True
assert 0, "%r not found in %r" %(cls, self.list) assert 0, "%r not found in %r" %(cls, self.list)
#def resetregistry(self): #def resetregistry(self):
@ -51,7 +52,7 @@ class WarningsRecorder:
# warnings.onceregistry.clear() # warnings.onceregistry.clear()
# warnings.__warningregistry__.clear() # warnings.__warningregistry__.clear()
def reset(self): def clear(self):
self.list[:] = [] self.list[:] = []
def finalize(self): def finalize(self):
@ -69,7 +70,7 @@ def test_WarningRecorder():
warn = rec.pop() warn = rec.pop()
assert str(warn.message) == "hello" assert str(warn.message) == "hello"
l = rec.list l = rec.list
rec.reset() rec.clear()
assert len(rec.list) == 0 assert len(rec.list) == 0
assert l is rec.list assert l is rec.list
py.test.raises(AssertionError, "rec.pop()") py.test.raises(AssertionError, "rec.pop()")

View File

@ -131,13 +131,6 @@ class TestCollectFS:
names = [x.name for x in col.collect()] names = [x.name for x in col.collect()]
assert names == ["dir1", "dir2", "test_one.py", "test_two.py", "x"] 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: class TestCollectPluginHooks:
def test_pytest_collect_file(self, testdir): def test_pytest_collect_file(self, testdir):
tmpdir = testdir.tmpdir tmpdir = testdir.tmpdir

View File

@ -2,15 +2,8 @@
import py import py
class TestCollectDeprecated: 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=""" testdir.makepyfile(conftest="""
import py import py
@ -52,23 +45,31 @@ class TestCollectDeprecated:
""") """)
config = testdir.parseconfig() config = testdir.parseconfig()
dirnode = config.getfsnode(p.dirpath()) 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 assert len(colitems) == 1
modcol = colitems[0] modcol = colitems[0]
assert modcol.name == "somefile.py" assert modcol.name == "somefile.py"
colitems = py.test.deprecated_call(modcol.collect) colitems = modcol.collect()
recwarn.pop(DeprecationWarning)
assert len(colitems) == 2 assert len(colitems) == 2
assert colitems[0].name == 'check' assert colitems[0].name == 'check'
assert colitems[1].name == 'Cls' assert colitems[1].name == 'Cls'
clscol = colitems[1] clscol = colitems[1]
colitems = py.test.deprecated_call(clscol.collect)
colitems = clscol.collect()
recwarn.pop(DeprecationWarning)
assert len(colitems) == 1 assert len(colitems) == 1
icol = colitems[0] icol = colitems[0]
colitems = py.test.deprecated_call(icol.collect) colitems = icol.collect()
recwarn.pop(DeprecationWarning)
assert len(colitems) == 1 assert len(colitems) == 1
assert colitems[0].name == 'check2' 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=""" testdir.makepyfile(conftest="""
import py import py
@ -87,42 +88,57 @@ class TestCollectDeprecated:
def check_one(): pass def check_one(): pass
class SomeClass: pass class SomeClass: pass
""") """)
colitems = py.test.deprecated_call(col.collect) colitems = col.collect()
recwarn.pop(DeprecationWarning)
assert len(colitems) == 1 assert len(colitems) == 1
funcitem = colitems[0] funcitem = colitems[0]
assert funcitem.name == "check_one" assert funcitem.name == "check_one"
def test_function_custom_run(self, testdir): def test_function_custom_run(self, testdir, recwarn):
testdir.makepyfile(conftest=""" testdir.makepyfile(conftest="""
import py import py
class MyFunction(py.test.collect.Function): class Function(py.test.collect.Function):
def run(self): def run(self):
pass pass
Function=MyFunction
""") """)
modcol = testdir.getmodulecol("def test_func(): pass") modcol = testdir.getmodulecol("def test_func(): pass")
funcitem = modcol.collect()[0] funcitem = modcol.collect()[0]
assert funcitem.name == 'test_func' 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=""" testdir.makepyfile(conftest="""
import py import py
class MyFunction(py.test.collect.Function): class MyFunction(py.test.collect.Function):
def execute(self, obj, *args): def execute(self, obj, *args):
pass pass
Function=MyFunction Function=MyFunction
""") """)
modcol = testdir.getmodulecol("def test_func(): pass") modcol = testdir.getmodulecol("def test_func2(): pass")
funcitem = modcol.collect()[0] funcitem = modcol.collect()[0]
assert funcitem.name == 'test_func' assert funcitem.name == 'test_func2'
py.test.deprecated_call(funcitem.runtest) funcitem._deprecated_testexecution()
w = recwarn.pop(DeprecationWarning)
assert w.filename.find("conftest.py") != -1
def test_function_deprecated_run_execute(self, testdir): def test_function_deprecated_run_execute(self, testdir, recwarn):
modcol = testdir.getmodulecol("def test_some(): pass") 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] 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): def test_function_deprecated_run_recursive(self, testdir):
testdir.makepyfile(conftest=""" testdir.makepyfile(conftest="""