def _register_setup_class_fixture(self) -> None:
        """Register an autouse, class scoped fixture into the collected class object
        that invokes setup_class/teardown_class if either or both are available.

        Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
        other fixtures (#517).
        """
        setup_class = _get_first_non_fixture_func(self.obj, ("setup_class",))
        teardown_class = _get_first_non_fixture_func(self.obj, ("teardown_class",))
        if setup_class is None and teardown_class is None:
            return

        def xunit_setup_class_fixture(request) -> Generator[None]:
            cls = request.cls
            if setup_class is not None:
                func = getimfunc(setup_class)
                _call_with_optional_argument(func, cls)
            yield
            if teardown_class is not None:
                func = getimfunc(teardown_class)
                _call_with_optional_argument(func, cls)

        self.session._fixturemanager._register_fixture(
            # Use a unique name to speed up lookup.
            name=f"_xunit_setup_class_fixture_{self.obj.__qualname__}",
            func=xunit_setup_class_fixture,
            nodeid=self.nodeid,
            scope="class",
            autouse=True,
        )
Register an autouse, class scoped fixture into the collected class object
        that invokes setup_class/teardown_class 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