From 9c285dfc1d1c79f71a532e8618a8eb9b443f9df8 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 6 Dec 2016 09:13:25 +0100 Subject: [PATCH 1/4] fix #2118 - rework Node._getcustomclass and Node compat properties --- CHANGELOG.rst | 4 +++- _pytest/main.py | 47 ++++++++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d49214e3f4a..ff6efb7ef05 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,9 @@ 3.0.6.dev0 ========== -* +* fix issue #2118 - protect against internal deprecationerrors by changing the code path of Node._getcustomclass. + This also turns a internal deprecation into a real deprecation. + Thanks to `@nicoddemus`_ for the report and `@RonnyPfannschmidt`_ for the PR. * diff --git a/_pytest/main.py b/_pytest/main.py index 52876c12a40..905b35d83d8 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -3,6 +3,8 @@ import os import sys +import warnings + import _pytest import _pytest._code import py @@ -190,14 +192,21 @@ def __getattr__(self, name): self.__dict__[name] = x return x -def compatproperty(name): - def fget(self): - import warnings - warnings.warn("This usage is deprecated, please use pytest.{0} instead".format(name), - PendingDeprecationWarning, stacklevel=2) - return getattr(pytest, name) +class _CompatProperty(object): + def __init__(self, name): + self.name = name + + def __get__(self, obj, owner): + if obj is None: + return self + + warnings.warn( + "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format( + name=self.name, owner=type(owner).__name__), + PendingDeprecationWarning, stacklevel=2) + return getattr(pytest, self.name) + - return property(fget) class NodeKeywords(MappingMixin): def __init__(self, node): @@ -269,19 +278,23 @@ def ihook(self): """ fspath sensitive hook proxy used to call pytest hooks""" return self.session.gethookproxy(self.fspath) - Module = compatproperty("Module") - Class = compatproperty("Class") - Instance = compatproperty("Instance") - Function = compatproperty("Function") - File = compatproperty("File") - Item = compatproperty("Item") + Module = _CompatProperty("Module") + Class = _CompatProperty("Class") + Instance = _CompatProperty("Instance") + Function = _CompatProperty("Function") + File = _CompatProperty("File") + Item = _CompatProperty("Item") def _getcustomclass(self, name): - cls = getattr(self, name) - if cls != getattr(pytest, name): - py.log._apiwarn("2.0", "use of node.%s is deprecated, " + maybe_compatprop = getattr(type(self), name) + if isinstance(maybe_compatprop, _CompatProperty): + return getattr(pytest, name) + else: + cls = getattr(self, name) + + warnings.warn("use of node.%s is deprecated, " "use pytest_pycollect_makeitem(...) to create custom " - "collection nodes" % name) + "collection nodes" % name, category=DeprecationWarning) return cls def __repr__(self): From 4082f4024a1ea9333e55a5af3954733e2c200c00 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 11:25:48 +0100 Subject: [PATCH 2/4] comment out compatproperty deprecations todo: reenable in the features branch --- _pytest/main.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/_pytest/main.py b/_pytest/main.py index 905b35d83d8..0aa97da64a7 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -200,10 +200,11 @@ def __get__(self, obj, owner): if obj is None: return self - warnings.warn( - "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format( - name=self.name, owner=type(owner).__name__), - PendingDeprecationWarning, stacklevel=2) + # TODO: reenable in the features branch + # warnings.warn( + # "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format( + # name=self.name, owner=type(owner).__name__), + # PendingDeprecationWarning, stacklevel=2) return getattr(pytest, self.name) @@ -291,10 +292,10 @@ def _getcustomclass(self, name): return getattr(pytest, name) else: cls = getattr(self, name) - - warnings.warn("use of node.%s is deprecated, " - "use pytest_pycollect_makeitem(...) to create custom " - "collection nodes" % name, category=DeprecationWarning) + # TODO: reenable in the features branch + # warnings.warn("use of node.%s is deprecated, " + # "use pytest_pycollect_makeitem(...) to create custom " + # "collection nodes" % name, category=DeprecationWarning) return cls def __repr__(self): From 7b4afd89465596d5d003bb250b5e0531d0e5f172 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 12:09:49 +0100 Subject: [PATCH 3/4] remove unused import --- _pytest/main.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/_pytest/main.py b/_pytest/main.py index 0aa97da64a7..a3235279397 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -3,8 +3,6 @@ import os import sys -import warnings - import _pytest import _pytest._code import py From 6a96b464abf6b3c808f918e6c5cc9c795d2416c8 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 15:26:59 +0100 Subject: [PATCH 4/4] update changelog as suggested --- CHANGELOG.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ff6efb7ef05..fae302fd37f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,11 @@ 3.0.6.dev0 ========== -* fix issue #2118 - protect against internal deprecationerrors by changing the code path of Node._getcustomclass. - This also turns a internal deprecation into a real deprecation. +* pytest no longer generates ``PendingDeprecationWarning`` from its own operations, which was introduced by mistake in version ``3.0.5`` (`#2118`_). Thanks to `@nicoddemus`_ for the report and `@RonnyPfannschmidt`_ for the PR. + + * * @@ -14,6 +15,7 @@ * +.. _#2118: https://github.com/pytest-dev/pytest/issues/2118 3.0.5 =====