[Pytest-commit] commit/pytest: 2 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Fri Sep 27 12:34:52 CEST 2013


2 new commits in pytest:

https://bitbucket.org/hpk42/pytest/commits/23278f23f092/
Changeset:   23278f23f092
User:        hpk42
Date:        2013-09-27 12:28:34
Summary:     fix some tests wrt to expecting output now that pytest does no
introduce unwanted "buffering" on "-s" calls.
Affected #:  4 files

diff -r 8f4c9f56a90fa62074cc2c52a4158f1f09adb084 -r 23278f23f0923076011f554bb875e332fde21125 _pytest/python.py
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -1623,7 +1623,7 @@
                 assert not name.startswith(self._argprefix)
             fixturedef = FixtureDef(self, nodeid, name, obj,
                                     marker.scope, marker.params,
-                                    marker.yieldctx,
+                                    yieldctx=marker.yieldctx,
                                     unittest=unittest)
             faclist = self._arg2fixturedefs.setdefault(name, [])
             if not fixturedef.has_location:

diff -r 8f4c9f56a90fa62074cc2c52a4158f1f09adb084 -r 23278f23f0923076011f554bb875e332fde21125 testing/python/fixture.py
--- a/testing/python/fixture.py
+++ b/testing/python/fixture.py
@@ -1993,12 +1993,12 @@
         """)
         result = testdir.runpytest("-s")
         result.stdout.fnmatch_lines("""
-            setup
-            test1 1
-            teardown
-            setup
-            test2 1
-            teardown
+            *setup*
+            *test1 1*
+            *teardown*
+            *setup*
+            *test2 1*
+            *teardown*
         """)
 
     def test_scoped(self, testdir):
@@ -2016,10 +2016,10 @@
         """)
         result = testdir.runpytest("-s")
         result.stdout.fnmatch_lines("""
-            setup
-            test1 1
-            test2 1
-            teardown
+            *setup*
+            *test1 1*
+            *test2 1*
+            *teardown*
         """)
 
     def test_setup_exception(self, testdir):

diff -r 8f4c9f56a90fa62074cc2c52a4158f1f09adb084 -r 23278f23f0923076011f554bb875e332fde21125 testing/test_fixture_finalizer.py
--- a/testing/test_fixture_finalizer.py
+++ b/testing/test_fixture_finalizer.py
@@ -28,4 +28,4 @@
     """))
     reprec = testdir.runpytest("-s")
     for test in ['test_browser']:
-        reprec.stdout.fnmatch_lines('Finalized')
+        reprec.stdout.fnmatch_lines('*Finalized*')

diff -r 8f4c9f56a90fa62074cc2c52a4158f1f09adb084 -r 23278f23f0923076011f554bb875e332fde21125 testing/test_terminal.py
--- a/testing/test_terminal.py
+++ b/testing/test_terminal.py
@@ -672,7 +672,7 @@
             stdout = k.pop()
             stdout.close()
     """)
-    result = testdir.runpytest("-s")
+    result = testdir.runpytest()
     result.stdout.fnmatch_lines([
         "*2 passed*"
     ])


https://bitbucket.org/hpk42/pytest/commits/95a817c87a02/
Changeset:   95a817c87a02
User:        hpk42
Date:        2013-09-27 12:33:06
Summary:     merge monkeypatch.replace into monkeypatch.setattr, also support monkeypatch.delattr.
Affected #:  4 files

diff -r 23278f23f0923076011f554bb875e332fde21125 -r 95a817c87a020ef2c325244d6f596943eaf5d0ae CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,10 +17,10 @@
 - PR27: correctly handle nose.SkipTest during collection.  Thanks
   Antonio Cuni, Ronny Pfannschmidt.
 
-- new monkeypatch.replace() to avoid imports and provide a shorter
+- new monkeypatch.setattr() variant to provide a shorter
   invocation for patching out classes/functions from modules:
 
-     monkeypatch.replace("requests.get", myfunc
+     monkeypatch.setattr("requests.get", myfunc)
 
   will replace the "get" function of the "requests" module with ``myfunc``.
 

diff -r 23278f23f0923076011f554bb875e332fde21125 -r 95a817c87a020ef2c325244d6f596943eaf5d0ae _pytest/monkeypatch.py
--- a/_pytest/monkeypatch.py
+++ b/_pytest/monkeypatch.py
@@ -25,6 +25,39 @@
     request.addfinalizer(mpatch.undo)
     return mpatch
 
+
+
+def derive_importpath(import_path):
+    if not isinstance(import_path, str) or "." not in import_path:
+        raise TypeError("must be absolute import path string, not %r" %
+                        (import_path,))
+    rest = []
+    target = import_path
+    while target:
+        try:
+            obj = __import__(target, None, None, "__doc__")
+        except ImportError:
+            if "." not in target:
+                __tracebackhide__ = True
+                pytest.fail("could not import any sub part: %s" %
+                            import_path)
+            target, name = target.rsplit(".", 1)
+            rest.append(name)
+        else:
+            assert rest
+            try:
+                while len(rest) > 1:
+                    attr = rest.pop()
+                    obj = getattr(obj, attr)
+                attr = rest[0]
+                getattr(obj, attr)
+            except AttributeError:
+                __tracebackhide__ = True
+                pytest.fail("object %r has no attribute %r" % (obj, attr))
+            return attr, obj
+
+
+
 notset = object()
 
 class monkeypatch:
@@ -34,70 +67,66 @@
         self._setitem = []
         self._cwd = None
 
-    def replace(self, import_path, value):
-        """ replace the object specified by a dotted ``import_path``
-        with the given ``value``.
+    def setattr(self, target, name, value=notset, raising=True):
+        """ set attribute value on target, memorizing the old value.
+        By default raise AttributeError if the attribute did not exist.
 
-        For example ``replace("os.path.abspath", value)`` will
-        trigger an ``import os.path`` and a subsequent
-        setattr(os.path, "abspath", value).  Or to prevent
-        the requests library from performing requests you can call
-        ``replace("requests.sessions.Session.request", None)``
-        which will lead to an import of ``requests.sessions`` and a call
-        to ``setattr(requests.sessions.Session, "request", None)``.
+        For convenience you can specify a string as ``target`` which
+        will be interpreted as a dotted import path, with the last part
+        being the attribute name.  Example:
+        ``monkeypatch.setattr("os.getcwd", lambda x: "/")``
+        would set the ``getcwd`` function of the ``os`` module.
+
+        The ``raising`` value determines if the setattr should fail
+        if the attribute is not already present (defaults to True
+        which means it will raise).
         """
-        if not isinstance(import_path, str) or "." not in import_path:
-            raise TypeError("must be absolute import path string, not %r" %
-                            (import_path,))
-        rest = []
-        target = import_path
-        while target:
-            try:
-                obj = __import__(target, None, None, "__doc__")
-            except ImportError:
-                if "." not in target:
-                    __tracebackhide__ = True
-                    pytest.fail("could not import any sub part: %s" %
-                                import_path)
-                target, name = target.rsplit(".", 1)
-                rest.append(name)
-            else:
-                assert rest
-                try:
-                    while len(rest) > 1:
-                        attr = rest.pop()
-                        obj = getattr(obj, attr)
-                    attr = rest[0]
-                    getattr(obj, attr)
-                except AttributeError:
-                    __tracebackhide__ = True
-                    pytest.fail("object %r has no attribute %r" % (obj, attr))
-                return self.setattr(obj, attr, value)
+        __tracebackhide__ = True
 
-    def setattr(self, obj, name, value, raising=True):
-        """ set attribute ``name`` on ``obj`` to ``value``, by default
-        raise AttributeEror if the attribute did not exist.
+        if value is notset:
+            if not isinstance(target, str):
+                raise TypeError("use setattr(target, name, value) or "
+                   "setattr(target, value) with target being a dotted "
+                   "import string")
+            value = name
+            name, target = derive_importpath(target)
 
-        """
-        oldval = getattr(obj, name, notset)
+        oldval = getattr(target, name, notset)
         if raising and oldval is notset:
-            raise AttributeError("%r has no attribute %r" %(obj, name))
+            raise AttributeError("%r has no attribute %r" %(target, name))
 
         # avoid class descriptors like staticmethod/classmethod
-        if inspect.isclass(obj):
-            oldval = obj.__dict__.get(name, notset)
-        self._setattr.insert(0, (obj, name, oldval))
-        setattr(obj, name, value)
+        if inspect.isclass(target):
+            oldval = target.__dict__.get(name, notset)
+        self._setattr.insert(0, (target, name, oldval))
+        setattr(target, name, value)
 
-    def delattr(self, obj, name, raising=True):
-        """ delete attribute ``name`` from ``obj``, by default raise
-        AttributeError it the attribute did not previously exist. """
-        if not hasattr(obj, name):
+    def delattr(self, target, name=notset, raising=True):
+        """ delete attribute ``name`` from ``target``, by default raise
+        AttributeError it the attribute did not previously exist.
+
+        If no ``name`` is specified and ``target`` is a string
+        it will be interpreted as a dotted import path with the
+        last part being the attribute name.
+
+        If raising is set to false, the attribute is allowed to not
+        pre-exist.
+        """
+        __tracebackhide__ = True
+        if name is notset:
+            if not isinstance(target, str):
+                raise TypeError("use delattr(target, name) or "
+                                "delattr(target) with target being a dotted "
+                                "import string")
+            name, target = derive_importpath(target)
+
+        if not hasattr(target, name):
             if raising:
                 raise AttributeError(name)
         else:
-            self._setattr.insert(0, (obj, name, getattr(obj, name, notset)))
-            delattr(obj, name)
+            self._setattr.insert(0, (target, name,
+                                     getattr(target, name, notset)))
+            delattr(target, name)
 
     def setitem(self, dic, name, value):
         """ set dictionary entry ``name`` to value. """

diff -r 23278f23f0923076011f554bb875e332fde21125 -r 95a817c87a020ef2c325244d6f596943eaf5d0ae doc/en/monkeypatch.txt
--- a/doc/en/monkeypatch.txt
+++ b/doc/en/monkeypatch.txt
@@ -48,11 +48,28 @@
     import pytest
     @pytest.fixture(autouse=True)
     def no_requests(monkeypatch):
-        monkeypatch.replace("requests.session.Session.request", None)
+        monkeypatch.delattr("requests.session.Session.request")
 
-This autouse fixture will be executed for all test functions and it
-will replace the method ``request.session.Session.request`` with the
-value None so that any attempts to create http requests will fail.
+This autouse fixture will be executed for each test function and it
+will delete the method ``request.session.Session.request`` 
+so that any attempts within tests to create http requests will fail.
+
+example: setting an attribute on some class
+------------------------------------------------------
+
+If you need to patch out ``os.getcwd()`` to return an artifical
+value::
+
+    def test_some_interaction(monkeypatch):
+        monkeypatch.setattr("os.getcwd", lambda: "/")
+
+which is equivalent to the long form::
+
+    def test_some_interaction(monkeypatch):
+        import os
+        monkeypatch.setattr(os, "getcwd", lambda: "/")
+    
+
 
 Method reference of the monkeypatch function argument
 -----------------------------------------------------

diff -r 23278f23f0923076011f554bb875e332fde21125 -r 95a817c87a020ef2c325244d6f596943eaf5d0ae testing/test_monkeypatch.py
--- a/testing/test_monkeypatch.py
+++ b/testing/test_monkeypatch.py
@@ -35,26 +35,32 @@
     monkeypatch.undo() # double-undo makes no modification
     assert A.x == 5
 
-class TestReplace:
+class TestSetattrWithImportPath:
     def test_string_expression(self, monkeypatch):
-        monkeypatch.replace("os.path.abspath", lambda x: "hello2")
+        monkeypatch.setattr("os.path.abspath", lambda x: "hello2")
         assert os.path.abspath("123") == "hello2"
 
     def test_string_expression_class(self, monkeypatch):
-        monkeypatch.replace("_pytest.config.Config", 42)
+        monkeypatch.setattr("_pytest.config.Config", 42)
         import _pytest
         assert _pytest.config.Config == 42
 
     def test_wrong_target(self, monkeypatch):
-        pytest.raises(TypeError, lambda: monkeypatch.replace(None, None))
+        pytest.raises(TypeError, lambda: monkeypatch.setattr(None, None))
 
     def test_unknown_import(self, monkeypatch):
         pytest.raises(pytest.fail.Exception,
-                      lambda: monkeypatch.replace("unkn123.classx", None))
+                      lambda: monkeypatch.setattr("unkn123.classx", None))
 
     def test_unknown_attr(self, monkeypatch):
         pytest.raises(pytest.fail.Exception,
-                      lambda: monkeypatch.replace("os.path.qweqwe", None))
+                      lambda: monkeypatch.setattr("os.path.qweqwe", None))
+
+    def test_delattr(self, monkeypatch):
+        monkeypatch.delattr("os.path.abspath")
+        assert not hasattr(os.path, "abspath")
+        monkeypatch.undo()
+        assert os.path.abspath
 
 def test_delattr():
     class A:
@@ -262,3 +268,5 @@
 
     monkeypatch.undo()
     assert Sample.hello()
+
+

Repository URL: https://bitbucket.org/hpk42/pytest/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.


More information about the pytest-commit mailing list