Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pytest_xdist_auto_num_workers function cannot be conditionally defined #1102

Open
DetachHead opened this issue Jun 20, 2024 · 1 comment
Open

Comments

@DetachHead
Copy link

DetachHead commented Jun 20, 2024

the problem

i'm trying to create a pytest_xdist_auto_num_workers hook that should only be registered if the user runs pytest with the xdist plugin enabled, otherwise it will crash due to the hook name being unknown:

according to the pytest docs, i can accomplish it like so:

class DeferPlugin:
    @hookimpl(wrapper=True)
    def pytest_xdist_auto_num_workers(config: pytest.Config) -> Generator[None, int, int]:
        return min((yield), len(config.option.file_or_dir))


def pytest_configure(config):
    if config.pluginmanager.hasplugin("xdist"):
        config.pluginmanager.register(DeferPlugin())

however it doesn't seem to work. the DeferPlugin gets registered but the pytest_xdist_auto_num_workers hook never gets called. i believe this is because pytest_xdist_auto_num_workers gets called before pytest_configure.

attempted workarounds

PYTEST_XDIST_AUTO_NUM_WORKERS environment variable

i considered using the PYTEST_XDIST_AUTO_NUM_WORKERS environment variable, but that won't work in this case because the logic i want to use to determine the new value needs to be based on the default value, which the environment variable does not contain.

attempting to import xdist before registering the hook

i tried doing this:

try:
    import xdist
except ModuleNotFoundError:
    pass
else:

    @pytest.hookimpl(wrapper=True)
    def pytest_xdist_auto_num_workers(config: pytest.Config) -> Generator[None, int, int]:
        return min((yield), len(config.option.file_or_dir))

which works most of the time, but if the user runs pytest with -p no:xdist, it will crash because the xdist module exists but the plugin is disabled, causing it to attempt to register the hook when pytest would not recognize it.

@DetachHead
Copy link
Author

this seems to work:

class DeferPlugin:
    @pytest.hookimpl(wrapper=True)
    def pytest_xdist_auto_num_workers(self, config: pytest.Config) -> typing.Generator[None, int, int]:
        return min((yield), len(config.option.file_or_dir))

def pytest_plugin_registered(plugin: object, manager: pytest.PytestPluginManager):
    if manager.hasplugin("xdist") and not isinstance(plugin, DeferPlugin):
        manager.register(DeferPlugin())

perhaps the documentation could be updated to mention this, as believe it would be a common use case to only want to register the hook when the plugin is active.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant