[py-svn] r58034 - in py/trunk/py: misc misc/testing path test

hpk at codespeak.net hpk at codespeak.net
Wed Sep 10 11:47:40 CEST 2008


Author: hpk
Date: Wed Sep 10 11:47:37 2008
New Revision: 58034

Added:
   py/trunk/py/misc/testing/test_warn.py   (contents, props changed)
   py/trunk/py/misc/warn.py   (contents, props changed)
Modified:
   py/trunk/py/path/common.py
   py/trunk/py/test/collect.py
Log:
introduce APIWARN helper 
allow for subscriptions to produced warnings
use it from some places


Added: py/trunk/py/misc/testing/test_warn.py
==============================================================================
--- (empty file)
+++ py/trunk/py/misc/testing/test_warn.py	Wed Sep 10 11:47:37 2008
@@ -0,0 +1,53 @@
+import py
+from py.__.misc.warn import WarningBus
+mypath = py.magic.autopath()
+
+class TestWarningBus:
+    def setup_method(self, method):
+        self.wb = WarningBus()
+        self.warnings = []
+        self.wb.subscribe(self.warnings.append)
+
+    def test_basic(self):
+        self.wb.warn("hello")
+        assert len(self.warnings) == 1
+        self.wb.unsubscribe(self.warnings.append)
+        self.wb.warn("this")
+        assert len(self.warnings) == 1
+        w = self.warnings[0]
+
+    def test_location(self):
+        self.wb.warn("again")
+        warning = self.warnings[0] 
+        lno = self.test_location.im_func.func_code.co_firstlineno + 1
+        assert warning.lineno == lno
+        assert warning.path == mypath 
+        locstr = "%s:%d: " %(mypath, lno+1,)
+        assert repr(warning).startswith(locstr)
+        assert str(warning) == warning.msg 
+
+    def test_stacklevel(self):
+        l = []
+        self.wb.subscribe(l.append)
+        def f():
+            self.wb.warn("x", stacklevel=2)
+        # 5
+        # 6
+        f()
+        lno = self.test_stacklevel.im_func.func_code.co_firstlineno + 7
+        warning = l[0]
+        assert warning.lineno == lno
+
+    def test_forwarding_to_warnings_module(self):
+        self.wb._setforwarding()
+        py.test.deprecated_call(self.wb.warn, "x")
+
+    def test_apiwarn(self):
+        self.wb.apiwarn("3.0", "xxx")
+        warning = self.warnings[0] 
+        assert warning.msg == "xxx (since version 3.0)"
+
+def test_APIWARN():
+    from py.__.misc.warn import APIWARN
+    wb = APIWARN.im_self
+    assert wb._forward in wb._eventbus._subscribers 

Added: py/trunk/py/misc/warn.py
==============================================================================
--- (empty file)
+++ py/trunk/py/misc/warn.py	Wed Sep 10 11:47:37 2008
@@ -0,0 +1,74 @@
+import py, sys
+from py.__.test.event import EventBus
+
+class Warning(py.std.exceptions.DeprecationWarning):
+    def __init__(self, msg, path, lineno):
+        self.msg = msg
+        self.path = path
+        self.lineno = lineno 
+    def __repr__(self):
+        return "%s:%d: %s" %(self.path, self.lineno+1, self.msg)
+    def __str__(self):
+        return self.msg 
+
+class WarningBus(object):
+    def __init__(self):
+        self._eventbus = EventBus()
+
+    def subscribe(self, callable):
+        self._eventbus.subscribe(callable)
+
+    def unsubscribe(self, callable):
+        self._eventbus.unsubscribe(callable)
+
+    def _setforwarding(self):
+        self._eventbus.subscribe(self._forward)
+    def _forward(self, warning):
+        py.std.warnings.warn_explicit(warning, category=Warning, 
+            filename=str(warning.path), 
+            lineno=warning.lineno,
+            registry=py.std.warnings.__dict__.setdefault(
+                "__warningsregistry__", {})
+        )
+        
+    def apiwarn(self, startversion, msg, stacklevel=1):
+        # below is mostly COPIED from python2.4/warnings.py's def warn()
+        # Get context information
+        msg = "%s (since version %s)" %(msg, startversion)
+        self.warn(msg, stacklevel=stacklevel+1)
+
+    def warn(self, msg, stacklevel=1):
+        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 = "<string>"
+        filename = globals.get('__file__')
+        if filename:
+            fnl = filename.lower()
+            if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
+                filename = filename[:-1]
+        else:
+            if module == "__main__":
+                try:
+                    filename = sys.argv[0]
+                except AttributeError:
+                    # embedded interpreters don't have sys.argv, see bug #839151
+                    filename = '__main__'
+            if not filename:
+                filename = module
+        path = py.path.local(filename)
+        warning = Warning(msg, path, lineno)
+        self._eventbus.notify(warning)
+
+# singleton api warner for py lib 
+apiwarner = WarningBus()
+apiwarner._setforwarding()
+APIWARN = apiwarner.apiwarn

Modified: py/trunk/py/path/common.py
==============================================================================
--- py/trunk/py/path/common.py	(original)
+++ py/trunk/py/path/common.py	Wed Sep 10 11:47:37 2008
@@ -5,6 +5,7 @@
 from __future__ import generators
 import os, sys
 import py
+from py.__.misc.warn import APIWARN
 
 def checktype(pathinstance, kw):
     names = ('local', 'svnwc', 'svnurl', 'py', )
@@ -21,9 +22,10 @@
         kwargs-specified specification. 
     """
     def __init__(self, **kwargs):
-        py.std.warnings.warn("py.path.checker is deprecated, construct "
-                             "calls to pathobj.check() instead", 
-                             DeprecationWarning, stacklevel=2)
+        APIWARN("0.9.0", 
+            "py.path.checker is deprecated, construct "
+            "calls to pathobj.check() instead", 
+        )
         self.kwargs = kwargs
     def __call__(self, p):
         return p.check(**self.kwargs)

Modified: py/trunk/py/test/collect.py
==============================================================================
--- py/trunk/py/test/collect.py	(original)
+++ py/trunk/py/test/collect.py	Wed Sep 10 11:47:37 2008
@@ -19,6 +19,7 @@
 
 """ 
 import py
+from py.__.misc.warn import APIWARN
 
 def configproperty(name):
     def fget(self):
@@ -493,10 +494,16 @@
 
 
 def depwarn(msg):
-    py.std.warnings.warn(msg, DeprecationWarning)
+    APIWARN("1.0", msg, stacklevel=2)
 
 def warnoldcollect():
-    return depwarn("implement collector.collect() instead of collector.run() and collector.join()")
+    APIWARN("1.0", 
+        "implement collector.collect() instead of "
+        "collector.run() and collector.join()",
+        stacklevel=2)
 
 def warnoldtestrun():
-    return depwarn("implement item.runtest() instead of item.run() and item.execute()")
+    APIWARN("1.0", 
+        "implement item.runtest() instead of "
+        "item.run() and item.execute()",
+        stacklevel=2)



More information about the pytest-commit mailing list