fix #6341 - disallow session/config in Node.from_parent
This commit is contained in:
		
							parent
							
								
									466bbbf8e8
								
							
						
					
					
						commit
						8ba0b7bc2a
					
				| 
						 | 
					@ -4,3 +4,7 @@ Instead they are new constructed via ``Node.from_parent``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This transitional mechanism enables us to detangle the very intensely
 | 
					This transitional mechanism enables us to detangle the very intensely
 | 
				
			||||||
entangled ``Node`` relationships by enforcing more controlled creation/configruation patterns.
 | 
					entangled ``Node`` relationships by enforcing more controlled creation/configruation patterns.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As part of that session/config are already disallowed parameters and as we work on the details we might need disallow a few more as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Subclasses are expected to use `super().from_parent` if they intend to expand the creation of `Nodes`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,8 +216,14 @@ class DoctestItem(pytest.Item):
 | 
				
			||||||
        self.fixture_request = None
 | 
					        self.fixture_request = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def from_parent(cls, parent, *, name, runner, dtest):
 | 
					    def from_parent(  # type: ignore
 | 
				
			||||||
        return cls._create(name=name, parent=parent, runner=runner, dtest=dtest)
 | 
					        cls, parent: "Union[DoctestTextfile, DoctestModule]", *, name, runner, dtest
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        # incompatible signature due to to imposed limits on sublcass
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        the public named constructor
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setup(self):
 | 
					    def setup(self):
 | 
				
			||||||
        if self.dtest is not None:
 | 
					        if self.dtest is not None:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -144,8 +144,22 @@ class Node(metaclass=NodeMeta):
 | 
				
			||||||
                self._nodeid += "::" + self.name
 | 
					                self._nodeid += "::" + self.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def from_parent(cls, parent, *, name):
 | 
					    def from_parent(cls, parent: "Node", **kw):
 | 
				
			||||||
        return cls._create(parent=parent, name=name)
 | 
					        """
 | 
				
			||||||
 | 
					        Public Constructor for Nodes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This indirection got introduced in order to enable removing
 | 
				
			||||||
 | 
					        the fragile logic from the node constructors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Subclasses can use ``super().from_parent(...)`` when overriding the construction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param parent: the parent node of this test Node
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if "config" in kw:
 | 
				
			||||||
 | 
					            raise TypeError("config is not a valid argument for from_parent")
 | 
				
			||||||
 | 
					        if "session" in kw:
 | 
				
			||||||
 | 
					            raise TypeError("session is not a valid argument for from_parent")
 | 
				
			||||||
 | 
					        return cls._create(parent=parent, **kw)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def ihook(self):
 | 
					    def ihook(self):
 | 
				
			||||||
| 
						 | 
					@ -434,7 +448,10 @@ class FSCollector(Collector):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def from_parent(cls, parent, *, fspath):
 | 
					    def from_parent(cls, parent, *, fspath):
 | 
				
			||||||
        return cls._create(parent=parent, fspath=fspath)
 | 
					        """
 | 
				
			||||||
 | 
					        The public constructor
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return super().from_parent(parent=parent, fspath=fspath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class File(FSCollector):
 | 
					class File(FSCollector):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -679,7 +679,10 @@ class Class(PyCollector):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def from_parent(cls, parent, *, name, obj=None):
 | 
					    def from_parent(cls, parent, *, name, obj=None):
 | 
				
			||||||
        return cls._create(name=name, parent=parent)
 | 
					        """
 | 
				
			||||||
 | 
					        The public constructor
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return super().from_parent(name=name, parent=parent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def collect(self):
 | 
					    def collect(self):
 | 
				
			||||||
        if not safe_getattr(self.obj, "__test__", True):
 | 
					        if not safe_getattr(self.obj, "__test__", True):
 | 
				
			||||||
| 
						 | 
					@ -1458,8 +1461,11 @@ class Function(FunctionMixin, nodes.Item):
 | 
				
			||||||
        self.originalname = originalname
 | 
					        self.originalname = originalname
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def from_parent(cls, parent, **kw):
 | 
					    def from_parent(cls, parent, **kw):  # todo: determine sound type limitations
 | 
				
			||||||
        return cls._create(parent=parent, **kw)
 | 
					        """
 | 
				
			||||||
 | 
					        The public  constructor
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return super().from_parent(parent=parent, **kw)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _initrequest(self):
 | 
					    def _initrequest(self):
 | 
				
			||||||
        self.funcargs = {}
 | 
					        self.funcargs = {}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -284,7 +284,7 @@ class TestFunction:
 | 
				
			||||||
        session = testdir.Session.from_config(config)
 | 
					        session = testdir.Session.from_config(config)
 | 
				
			||||||
        session._fixturemanager = FixtureManager(session)
 | 
					        session._fixturemanager = FixtureManager(session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return pytest.Function.from_parent(config=config, parent=session, **kwargs)
 | 
					        return pytest.Function.from_parent(parent=session, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_function_equality(self, testdir, tmpdir):
 | 
					    def test_function_equality(self, testdir, tmpdir):
 | 
				
			||||||
        def func1():
 | 
					        def func1():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,13 @@ def test_ischildnode(baseid, nodeid, expected):
 | 
				
			||||||
    assert result is expected
 | 
					    assert result is expected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_node_from_parent_disallowed_arguments():
 | 
				
			||||||
 | 
					    with pytest.raises(TypeError, match="session is"):
 | 
				
			||||||
 | 
					        nodes.Node.from_parent(None, session=None)
 | 
				
			||||||
 | 
					    with pytest.raises(TypeError, match="config is"):
 | 
				
			||||||
 | 
					        nodes.Node.from_parent(None, config=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_std_warn_not_pytestwarning(testdir):
 | 
					def test_std_warn_not_pytestwarning(testdir):
 | 
				
			||||||
    items = testdir.getitems(
 | 
					    items = testdir.getitems(
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue