agronholm / typeguard

Run-time type checker for Python
Other
1.5k stars 112 forks source link

4.3.0: pytest 8.2.1 fails in two units with `The hookimpl pytest_pycollect_makeitem uses old-style configuration options` #463

Closed kloczek closed 3 months ago

kloczek commented 3 months ago

Things to check first

Typeguard version

4.3.0

Python version

3.10.14

What happened?

pytest fails in two units with The hookimpl pytest_pycollect_makeitem uses old-style configuration options message

How can we reproduce the bug?

I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

Here is pytest output: ```console + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-typeguard-4.3.0-2.fc37.x86_64/usr/lib64/python3.10/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-typeguard-4.3.0-2.fc37.x86_64/usr/lib/python3.10/site-packages + /usr/bin/pytest -ra -m 'not network' ==================================================================================== test session starts ==================================================================================== platform linux -- Python 3.10.14, pytest-8.2.1, pluggy-1.5.0 rootdir: /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0 configfile: pyproject.toml testpaths: tests plugins: typeguard-4.3.0, asyncio-0.23.7, timeout-2.3.1, twisted-1.14.1, trio-0.8.0, anyio-4.3.0, tornasync-0.6.0.post2 asyncio: mode=strict collected 479 items tests/mypy/test_type_annotations.py .. [ 0%] tests/test_checkers.py ..................................................................s.s......................................................................................... [ 33%] ........................................................ [ 45%] tests/test_importhook.py ... [ 45%] tests/test_instrumentation.py ........xxx..............................................xxx...................................... [ 66%] tests/test_plugins.py . [ 66%] tests/test_pytest_plugin.py FF [ 66%] tests/test_suppression.py ....... [ 68%] tests/test_transformer.py ................................................s............................... [ 84%] tests/test_typechecked.py ..................................................... [ 96%] tests/test_union_transformer.py ............ [ 98%] tests/test_utils.py ..... [ 99%] tests/test_warn_on_error.py .. [100%] ========================================================================================= FAILURES ========================================================================================== ____________________________________________________________________________________ test_config_options ____________________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_pytest_plugin.py:42: in test_config_options pytestconfig = pytester.parseconfigure() /usr/lib/python3.10/site-packages/_pytest/pytester.py:1245: in parseconfigure config = self.parseconfig(*args) /usr/lib/python3.10/site-packages/_pytest/pytester.py:1231: in parseconfig config = _pytest.config._prepareconfig(new_args, self.plugins) # type: ignore[arg-type] /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:346: in _prepareconfig config = pluginmanager.hook.pytest_cmdline_parse( /usr/lib/python3.10/site-packages/pluggy/_hooks.py:513: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:120: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/helpconfig.py:106: in pytest_cmdline_parse config = yield /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:1152: in pytest_cmdline_parse self.parse(args) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:1501: in parse self._preparse(args, addopts=addopts) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:1388: in _preparse self.pluginmanager.load_setuptools_entrypoints("pytest11") /usr/lib/python3.10/site-packages/pluggy/_manager.py:422: in load_setuptools_entrypoints self.register(plugin, name=ep.name) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:508: in register plugin_name = super().register(plugin, name) /usr/lib/python3.10/site-packages/pluggy/_manager.py:157: in register hookimpl_opts = self.parse_hookimpl_opts(plugin, name) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:478: in parse_hookimpl_opts return _get_legacy_hook_marks( # type: ignore[return-value] /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:391: in _get_legacy_hook_marks warn_explicit_for(cast(FunctionType, method), message) /usr/lib/python3.10/site-packages/_pytest/warning_types.py:165: in warn_explicit_for raise type(w)(f"{w}\n at {filename}:{lineno}") from None E pytest.PytestDeprecationWarning: The hookimpl pytest_pycollect_makeitem uses old-style configuration options (marks or attributes). E Please use the pytest.hookimpl(tryfirst=True) decorator instead E to configure the hooks. E See https://docs.pytest.org/en/latest/deprecations.html#configuring-hook-specs-impls-using-markers E at /usr/lib/python3.10/site-packages/pytest_tornasync/plugin.py:33 _________________________________________________________________________________ test_commandline_options __________________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_pytest_plugin.py:66: in test_commandline_options pytestconfig = pytester.parseconfigure( /usr/lib/python3.10/site-packages/_pytest/pytester.py:1245: in parseconfigure config = self.parseconfig(*args) /usr/lib/python3.10/site-packages/_pytest/pytester.py:1231: in parseconfig config = _pytest.config._prepareconfig(new_args, self.plugins) # type: ignore[arg-type] /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:346: in _prepareconfig config = pluginmanager.hook.pytest_cmdline_parse( /usr/lib/python3.10/site-packages/pluggy/_hooks.py:513: in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) /usr/lib/python3.10/site-packages/pluggy/_manager.py:120: in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) /usr/lib/python3.10/site-packages/_pytest/helpconfig.py:106: in pytest_cmdline_parse config = yield /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:1152: in pytest_cmdline_parse self.parse(args) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:1501: in parse self._preparse(args, addopts=addopts) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:1388: in _preparse self.pluginmanager.load_setuptools_entrypoints("pytest11") /usr/lib/python3.10/site-packages/pluggy/_manager.py:422: in load_setuptools_entrypoints self.register(plugin, name=ep.name) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:508: in register plugin_name = super().register(plugin, name) /usr/lib/python3.10/site-packages/pluggy/_manager.py:157: in register hookimpl_opts = self.parse_hookimpl_opts(plugin, name) /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:478: in parse_hookimpl_opts return _get_legacy_hook_marks( # type: ignore[return-value] /usr/lib/python3.10/site-packages/_pytest/config/__init__.py:391: in _get_legacy_hook_marks warn_explicit_for(cast(FunctionType, method), message) /usr/lib/python3.10/site-packages/_pytest/warning_types.py:165: in warn_explicit_for raise type(w)(f"{w}\n at {filename}:{lineno}") from None E pytest.PytestDeprecationWarning: The hookimpl pytest_pycollect_makeitem uses old-style configuration options (marks or attributes). E Please use the pytest.hookimpl(tryfirst=True) decorator instead E to configure the hooks. E See https://docs.pytest.org/en/latest/deprecations.html#configuring-hook-specs-impls-using-markers E at /usr/lib/python3.10/site-packages/pytest_tornasync/plugin.py:33 ========================================================================================= XFAILURES ========================================================================================= ___________________________________________________________________________ test_inner_class_method[typechecked] ____________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:102: in test_inner_class_method retval = dummymodule.Outer().create_inner() /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:118: in create_inner def create_inner(self) -> "Inner": E NameError: name 'Inner' is not defined _________________________________________________________________________ test_inner_class_classmethod[typechecked] _________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:108: in test_inner_class_classmethod retval = dummymodule.Outer.create_inner_classmethod() /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:122: in create_inner_classmethod def create_inner_classmethod(cls) -> "Inner": E NameError: name 'Inner' is not defined ________________________________________________________________________ test_inner_class_staticmethod[typechecked] _________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:114: in test_inner_class_staticmethod retval = dummymodule.Outer.create_inner_staticmethod() /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:126: in create_inner_staticmethod def create_inner_staticmethod() -> "Inner": E NameError: name 'Inner' is not defined ____________________________________________________________________________ test_inner_class_method[importhook] ____________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:102: in test_inner_class_method retval = dummymodule.Outer().create_inner() /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:118: in create_inner def create_inner(self) -> "Inner": E NameError: name 'Inner' is not defined _________________________________________________________________________ test_inner_class_classmethod[importhook] __________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:108: in test_inner_class_classmethod retval = dummymodule.Outer.create_inner_classmethod() /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:122: in create_inner_classmethod def create_inner_classmethod(cls) -> "Inner": E NameError: name 'Inner' is not defined _________________________________________________________________________ test_inner_class_staticmethod[importhook] _________________________________________________________________________ /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:114: in test_inner_class_staticmethod retval = dummymodule.Outer.create_inner_staticmethod() /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:126: in create_inner_staticmethod def create_inner_staticmethod() -> "Inner": E NameError: name 'Inner' is not defined ================================================================================== short test summary info ================================================================================== SKIPPED [1] tests/test_checkers.py:511: 'NotRequired' not found in 'typing' SKIPPED [1] tests/test_checkers.py:523: 'NotRequired' not found in 'typing' SKIPPED [1] tests/test_transformer.py:1230: Requires Python < 3.10 XFAIL tests/test_instrumentation.py::test_inner_class_method[typechecked] - No workaround for this has been implemented yet XFAIL tests/test_instrumentation.py::test_inner_class_classmethod[typechecked] - No workaround for this has been implemented yet XFAIL tests/test_instrumentation.py::test_inner_class_staticmethod[typechecked] - No workaround for this has been implemented yet XFAIL tests/test_instrumentation.py::test_inner_class_method[importhook] - No workaround for this has been implemented yet XFAIL tests/test_instrumentation.py::test_inner_class_classmethod[importhook] - No workaround for this has been implemented yet XFAIL tests/test_instrumentation.py::test_inner_class_staticmethod[importhook] - No workaround for this has been implemented yet FAILED tests/test_pytest_plugin.py::test_config_options - pytest.PytestDeprecationWarning: The hookimpl pytest_pycollect_makeitem uses old-style configuration options (marks or attributes). FAILED tests/test_pytest_plugin.py::test_commandline_options - pytest.PytestDeprecationWarning: The hookimpl pytest_pycollect_makeitem uses old-style configuration options (marks or attributes). =================================================================== 2 failed, 468 passed, 3 skipped, 6 xfailed in 11.26s ==================================================================== ```
List of installed modules in build env: ```console Package Version ----------------------------- ----------- alabaster 0.7.16 Babel 2.15.0 build 1.2.1 charset-normalizer 3.3.2 defusedxml 0.7.1 docutils 0.20.1 exceptiongroup 1.1.3 idna 3.7 imagesize 1.4.1 importlib_metadata 7.1.0 iniconfig 2.0.0 installer 0.7.0 Jinja2 3.1.4 MarkupSafe 2.1.5 mypy 1.10.0 mypy_extensions 1.0.0 packaging 24.0 pluggy 1.5.0 Pygments 2.18.0 pyproject_hooks 1.0.0 pytest 8.2.1 python-dateutil 2.9.0.post0 requests 2.32.2 setuptools 69.4.0 setuptools-scm 8.1.0 snowballstemmer 2.2.0 Sphinx 7.3.7 sphinx-autodoc-typehints 2.1.0 sphinxcontrib-applehelp 1.0.8 sphinxcontrib-devhelp 1.0.6 sphinxcontrib-htmlhelp 2.0.5 sphinxcontrib-jsmath 1.0.1 sphinxcontrib-qthelp 1.0.7 sphinxcontrib-serializinghtml 1.1.10 tokenize_rt 5.2.0 tomli 2.0.1 typing_extensions 4.12.0 urllib3 2.2.1 wheel 0.43.0 zipp 3.19.0 ```

Please let me know if you need more details or want me to perform some diagnostics.

agronholm commented 3 months ago

The pytest plugin tests are failing because the project has not been installed, so pytest cannot find the plugin that is being tested.

agronholm commented 3 months ago

Does the dist-info directory get installed? That would contain the entry point required for the plugin tests to pass.

kloczek commented 3 months ago

Yes it is. installer unpacks all metadata as well as same as pip I'm using installer because it is dedicated tool to only one task without any additional dependencies.

agronholm commented 3 months ago

Yet the list of installed modules does not show typeguard. Why is that?

kloczek commented 3 months ago

List of installed modules is from state before start packaging and fails are not because it is not possible to access to module metadata.

agronholm commented 3 months ago

I'm not sure I understood that. Are you saying that the failures are not caused by missing/inaccessible metadata?

At any rate, can you see typeguard on the installed packages list before starting the pytest run?

kloczek commented 3 months ago

I'm not sure I understood that. Are you saying that the failures are not caused by missing/inaccessible metadata?

Fail massage The hookimpl pytest_pycollect_makeitem uses old-style configuration options (marks or attributes). does not look like it has anything to do with metadata.

agronholm commented 3 months ago

I'm not sure I understood that. Are you saying that the failures are not caused by missing/inaccessible metadata?

Fail massage The hookimpl pytest_pycollect_makeitem uses old-style configuration options (marks or attributes). does not look like it has anything to do with metadata.

Right. But I'm running the test suite with the exact same pytest version and options as you are, and I'm not seeing any failures.

agronholm commented 3 months ago

Have you tried eliminating the other pytest plugins to see if they could cause issues?

kloczek commented 3 months ago

Have you tried eliminating the other pytest plugins to see if they could cause issues?

If it is question for me I'm building all my packages with build envs created to build only one package in which are installed ONLY build dependencies and if you will have look on list of modules installed in build env which I've provided in that build env there is no any additional pytest extensions.

agronholm commented 3 months ago
plugins: typeguard-4.3.0, asyncio-0.23.7, timeout-2.3.1, twisted-1.14.1, trio-0.8.0, anyio-4.3.0, tornasync-0.6.0.post2

This is from your own pytest output above.

kloczek commented 3 months ago

Ops .. I've been looking only on list pytest-* modules😋 AFAIK this or another way those extensions have been required in the past by pytest 🤔 Jusy checked CI output and theoretically on that list should be only typeguard. Will back shortly with results ..

kloczek commented 3 months ago

OK looks like I've reported issue from my devel system and not actual build system where none of those extensions are installed. Without those exts pytest is OK

+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-typeguard-4.3.0-2.fc37.x86_64/usr/lib64/python3.10/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-typeguard-4.3.0-2.fc37.x86_64/usr/lib/python3.10/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.10.14, pytest-8.2.1, pluggy-1.5.0
rootdir: /home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0
configfile: pyproject.toml
testpaths: tests
plugins: typeguard-4.3.0
collected 479 items

tests/mypy/test_type_annotations.py ..                                                                                                                                                [  0%]
tests/test_checkers.py ..................................................................s.s......................................................................................... [ 33%]
........................................................                                                                                                                              [ 45%]
tests/test_importhook.py ...                                                                                                                                                          [ 45%]
tests/test_instrumentation.py ........xxx..............................................xxx......................................                                                      [ 66%]
tests/test_plugins.py .                                                                                                                                                               [ 66%]
tests/test_pytest_plugin.py ..                                                                                                                                                        [ 66%]
tests/test_suppression.py .......                                                                                                                                                     [ 68%]
tests/test_transformer.py ................................................s...............................                                                                            [ 84%]
tests/test_typechecked.py .....................................................                                                                                                       [ 96%]
tests/test_union_transformer.py ............                                                                                                                                          [ 98%]
tests/test_utils.py .....                                                                                                                                                             [ 99%]
tests/test_warn_on_error.py ..                                                                                                                                                        [100%]

========================================================================================= XFAILURES =========================================================================================
___________________________________________________________________________ test_inner_class_method[typechecked] ____________________________________________________________________________
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:102: in test_inner_class_method
    retval = dummymodule.Outer().create_inner()
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:118: in create_inner
    def create_inner(self) -> "Inner":
E   NameError: name 'Inner' is not defined
_________________________________________________________________________ test_inner_class_classmethod[typechecked] _________________________________________________________________________
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:108: in test_inner_class_classmethod
    retval = dummymodule.Outer.create_inner_classmethod()
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:122: in create_inner_classmethod
    def create_inner_classmethod(cls) -> "Inner":
E   NameError: name 'Inner' is not defined
________________________________________________________________________ test_inner_class_staticmethod[typechecked] _________________________________________________________________________
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:114: in test_inner_class_staticmethod
    retval = dummymodule.Outer.create_inner_staticmethod()
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:126: in create_inner_staticmethod
    def create_inner_staticmethod() -> "Inner":
E   NameError: name 'Inner' is not defined
____________________________________________________________________________ test_inner_class_method[importhook] ____________________________________________________________________________
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:102: in test_inner_class_method
    retval = dummymodule.Outer().create_inner()
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:118: in create_inner
    def create_inner(self) -> "Inner":
E   NameError: name 'Inner' is not defined
_________________________________________________________________________ test_inner_class_classmethod[importhook] __________________________________________________________________________
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:108: in test_inner_class_classmethod
    retval = dummymodule.Outer.create_inner_classmethod()
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:122: in create_inner_classmethod
    def create_inner_classmethod(cls) -> "Inner":
E   NameError: name 'Inner' is not defined
_________________________________________________________________________ test_inner_class_staticmethod[importhook] _________________________________________________________________________
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/test_instrumentation.py:114: in test_inner_class_staticmethod
    retval = dummymodule.Outer.create_inner_staticmethod()
/home/tkloczko/rpmbuild/BUILD/typeguard-4.3.0/tests/dummymodule.py:126: in create_inner_staticmethod
    def create_inner_staticmethod() -> "Inner":
E   NameError: name 'Inner' is not defined
================================================================================== short test summary info ==================================================================================
SKIPPED [1] tests/test_checkers.py:511: 'NotRequired' not found in 'typing'
SKIPPED [1] tests/test_checkers.py:523: 'NotRequired' not found in 'typing'
SKIPPED [1] tests/test_transformer.py:1230: Requires Python < 3.10
XFAIL tests/test_instrumentation.py::test_inner_class_method[typechecked] - No workaround for this has been implemented yet
XFAIL tests/test_instrumentation.py::test_inner_class_classmethod[typechecked] - No workaround for this has been implemented yet
XFAIL tests/test_instrumentation.py::test_inner_class_staticmethod[typechecked] - No workaround for this has been implemented yet
XFAIL tests/test_instrumentation.py::test_inner_class_method[importhook] - No workaround for this has been implemented yet
XFAIL tests/test_instrumentation.py::test_inner_class_classmethod[importhook] - No workaround for this has been implemented yet
XFAIL tests/test_instrumentation.py::test_inner_class_staticmethod[importhook] - No workaround for this has been implemented yet
======================================================================== 470 passed, 3 skipped, 6 xfailed in 11.24s =========================================================================

Closing. Thank you very much 👍