def _register_setup_module_fixture(self) -> None:
        """Register an autouse, module-scoped fixture for the collected module object
        that invokes setUpModule/tearDownModule if either or both are available.

        Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
        other fixtures (#517).
        """
        setup_module = _get_first_non_fixture_func(
            self.obj, ("setUpModule", "setup_module")
        )
        teardown_module = _get_first_non_fixture_func(
            self.obj, ("tearDownModule", "teardown_module")
        )

        if setup_module is None and teardown_module is None:
            return

        def xunit_setup_module_fixture(request) -> Generator[None]:
            module = request.module
            if setup_module is not None:
                _call_with_optional_argument(setup_module, module)
            yield
            if teardown_module is not None:
                _call_with_optional_argument(teardown_module, module)

        self.session._fixturemanager._register_fixture(
            # Use a unique name to speed up lookup.
            name=f"_xunit_setup_module_fixture_{self.obj.__name__}",
            func=xunit_setup_module_fixture,
            nodeid=self.nodeid,
            scope="module",
            autouse=True,
        )
Register an autouse, module-scoped fixture for the collected module object
        that invokes setUpModule/tearDownModule if either or both are available.

        Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
        other fixtures (#517).
        
src/_pytest/python.py