Skip to content

Commit

Permalink
experiment with node metaclass for ctor warning
Browse files Browse the repository at this point in the history
  • Loading branch information
RonnyPfannschmidt committed Oct 27, 2019
1 parent e0ad722 commit aec6cb6
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 42 deletions.
3 changes: 1 addition & 2 deletions src/_pytest/main.py
Expand Up @@ -384,10 +384,9 @@ def __init__(self, config):

self.config.pluginmanager.register(self, name="session")

@nodes.Node.constructor
@classmethod
def from_config(cls, config):
return cls(config)
return cls._create(config)

def __repr__(self):
return "<%s %s exitstatus=%r testsfailed=%d testscollected=%d>" % (
Expand Down
52 changes: 24 additions & 28 deletions src/_pytest/nodes.py
Expand Up @@ -67,12 +67,32 @@ def ischildnode(baseid, nodeid):
return node_parts[: len(base_parts)] == base_parts


class Node:
class NodeMeta(type):
__in_named_ctor = False

def __call__(self, *k, **kw):
if not self.__in_named_ctor:
warnings.warn(
NODE_USE_FROM_PARENT.format(name=self.__name__),
stacklevel=3,
)
return self._create(*k, **kw)

@contextmanager
def __ctor_entered(self):
self.__in_named_ctor = True
yield
self.__in_named_ctor = False

def _create(self, *k, **kw):
with self.__ctor_entered():
return super().__call__(*k, **kw)


class Node(metaclass=NodeMeta):
""" base class for Collector and Item the test collection tree.
Collector subclasses have children, Items are terminal nodes."""

__in_named_ctor = False

def __init__(
self, name, parent=None, config=None, session=None, fspath=None, nodeid=None
):
Expand Down Expand Up @@ -111,33 +131,9 @@ def __init__(
if self.name != "()":
self._nodeid += "::" + self.name

if not type(self).__in_named_ctor:
warnings.warn(
NODE_USE_FROM_PARENT.format(name=type(self).__name__),
stacklevel=3,
)

@classmethod
@contextmanager
def __ctor_entered(cls):
cls.__in_named_ctor = True
yield
cls.__in_named_ctor = False

@staticmethod
def constructor(ctor):
@classmethod
@wraps(ctor)
def wrapped(cls, *k, **kw):
with cls.__ctor_entered():
return ctor.__get__(None, cls)(*k, **kw)

return wrapped

@classmethod
def from_parent(cls, parent, **kw):
with cls.__ctor_entered():
return cls(**kw, parent=parent)
return cls._create(**kw, parent=parent)

@property
def ihook(self):
Expand Down
13 changes: 1 addition & 12 deletions src/_pytest/python.py
Expand Up @@ -429,11 +429,6 @@ def _genfunctions(self, name, funcobj):
class Module(nodes.File, PyCollector):
""" Collector for test classes and functions. """

@nodes.Node.constructor
@classmethod
def from_parent(cls, parent, **kw):
return cls(parent=parent, **kw)

def _getobj(self):
return self._importtestmodule()

Expand Down Expand Up @@ -689,10 +684,9 @@ def _get_first_non_fixture_func(obj, names):
class Class(PyCollector):
""" Collector for test methods. """

@nodes.Node.constructor
@classmethod
def from_parent(cls, parent, *, name, obj=None):
return cls(name=name, parent=parent)
return cls._create(name=name, parent=parent)

def collect(self):
if not safe_getattr(self.obj, "__test__", True):
Expand Down Expand Up @@ -1407,11 +1401,6 @@ def __init__(
#: .. versionadded:: 3.0
self.originalname = originalname

@nodes.Node.constructor
@classmethod
def from_parent(cls, parent, **kw):
return cls(parent=parent, **kw)

def _initrequest(self):
self.funcargs = {}
self._request = fixtures.FixtureRequest(self)
Expand Down

0 comments on commit aec6cb6

Please sign in to comment.