Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pytest for openSUSE:Factory checked in at 2023-09-22 21:46:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pytest (Old) and /work/SRC/openSUSE:Factory/.python-pytest.new.1770 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pytest" Fri Sep 22 21:46:51 2023 rev:80 rq:1112015 version:7.4.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pytest/python-pytest.changes 2023-09-17 19:28:41.636288656 +0200 +++ /work/SRC/openSUSE:Factory/.python-pytest.new.1770/python-pytest.changes 2023-09-22 21:47:18.664635915 +0200 @@ -1,0 +2,20 @@ +Mon Sep 18 15:04:41 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 7.4.2: + * Fix doctest collection of + `functools.cached_property` objects. + * Fixed bug using + ``--importmode=importlib`` which would cause package + ``__init__.py`` files to be imported more than once in some + cases. + * Fixed bug where `user_properties` + where not being saved in the JUnit XML file if a fixture + failed during teardown. + * Fixed crash when parsing long + command line arguments that might be interpreted as files. + * Improved Documentation + * Improved disclaimer on pytest + plugin reference page to better indicate this is an + automated, non-curated listing. + +------------------------------------------------------------------- Old: ---- pytest-7.4.1.tar.gz New: ---- pytest-7.4.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pytest.spec ++++++ --- /var/tmp/diff_new_pack.SdyGq1/_old 2023-09-22 21:47:19.880680062 +0200 +++ /var/tmp/diff_new_pack.SdyGq1/_new 2023-09-22 21:47:19.884680206 +0200 @@ -33,7 +33,7 @@ %{?sle15_python_module_pythons} Name: python-pytest%{psuffix} -Version: 7.4.1 +Version: 7.4.2 Release: 0 Summary: Simple powerful testing with Python License: MIT ++++++ pytest-7.4.1.tar.gz -> pytest-7.4.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/.github/workflows/deploy.yml new/pytest-7.4.2/.github/workflows/deploy.yml --- old/pytest-7.4.1/.github/workflows/deploy.yml 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/.github/workflows/deploy.yml 2023-09-07 20:43:41.000000000 +0200 @@ -37,6 +37,7 @@ permissions: id-token: write steps: + - uses: actions/checkout@v3 - name: Download Package uses: actions/download-artifact@v3 with: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/AUTHORS new/pytest-7.4.2/AUTHORS --- old/pytest-7.4.1/AUTHORS 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/AUTHORS 2023-09-07 20:43:41.000000000 +0200 @@ -166,6 +166,8 @@ Ian Lesperance Ilya Konstantinov IonuÈ TurturicÄ +Isaac Virshup +Israel Fruchter Itxaso Aizpurua Iwan Briquemont Jaap Broekhuizen @@ -339,6 +341,7 @@ Simon Kerr Skylar Downes Srinivas Reddy Thatiparthy +Stefaan Lippens Stefan Farmbauer Stefan Scherfke Stefan Zimmermann @@ -371,6 +374,7 @@ Tor Colvin Trevor Bekolay Tyler Goodlet +Tyler Smart Tzu-ping Chung Vasily Kuznetsov Victor Maryama diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/PKG-INFO new/pytest-7.4.2/PKG-INFO --- old/pytest-7.4.1/PKG-INFO 2023-09-02 17:00:18.888728000 +0200 +++ new/pytest-7.4.2/PKG-INFO 2023-09-07 20:44:07.151998800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pytest -Version: 7.4.1 +Version: 7.4.2 Summary: pytest: simple powerful testing with Python Home-page: https://docs.pytest.org/en/latest/ Author: Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others @@ -34,8 +34,24 @@ Classifier: Topic :: Utilities Requires-Python: >=3.7 Description-Content-Type: text/x-rst -Provides-Extra: testing License-File: LICENSE +Requires-Dist: iniconfig +Requires-Dist: packaging +Requires-Dist: pluggy<2.0,>=0.12 +Requires-Dist: colorama; sys_platform == "win32" +Requires-Dist: exceptiongroup>=1.0.0rc8; python_version < "3.11" +Requires-Dist: importlib-metadata>=0.12; python_version < "3.8" +Requires-Dist: tomli>=1.0.0; python_version < "3.11" +Provides-Extra: testing +Requires-Dist: argcomplete; extra == "testing" +Requires-Dist: attrs>=19.2.0; extra == "testing" +Requires-Dist: hypothesis>=3.56; extra == "testing" +Requires-Dist: mock; extra == "testing" +Requires-Dist: nose; extra == "testing" +Requires-Dist: pygments>=2.7.2; extra == "testing" +Requires-Dist: requests; extra == "testing" +Requires-Dist: setuptools; extra == "testing" +Requires-Dist: xmlschema; extra == "testing" .. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg :target: https://docs.pytest.org/en/stable/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/announce/index.rst new/pytest-7.4.2/doc/en/announce/index.rst --- old/pytest-7.4.1/doc/en/announce/index.rst 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/doc/en/announce/index.rst 2023-09-07 20:43:41.000000000 +0200 @@ -6,6 +6,7 @@ :maxdepth: 2 + release-7.4.2 release-7.4.1 release-7.4.0 release-7.3.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/announce/release-7.4.2.rst new/pytest-7.4.2/doc/en/announce/release-7.4.2.rst --- old/pytest-7.4.1/doc/en/announce/release-7.4.2.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/pytest-7.4.2/doc/en/announce/release-7.4.2.rst 2023-09-07 20:43:41.000000000 +0200 @@ -0,0 +1,18 @@ +pytest-7.4.2 +======================================= + +pytest 7.4.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira + + +Happy testing, +The pytest Development Team diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/builtin.rst new/pytest-7.4.2/doc/en/builtin.rst --- old/pytest-7.4.1/doc/en/builtin.rst 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/doc/en/builtin.rst 2023-09-07 20:43:41.000000000 +0200 @@ -105,7 +105,7 @@ captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:737 + doctest_namespace [session scope] -- .../_pytest/doctest.py:757 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/changelog.rst new/pytest-7.4.2/doc/en/changelog.rst --- old/pytest-7.4.1/doc/en/changelog.rst 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/doc/en/changelog.rst 2023-09-07 20:43:41.000000000 +0200 @@ -28,6 +28,31 @@ .. towncrier release notes start +pytest 7.4.2 (2023-09-07) +========================= + +Bug Fixes +--------- + +- `#11237 <https://github.com/pytest-dev/pytest/issues/11237>`_: Fix doctest collection of `functools.cached_property` objects. + + +- `#11306 <https://github.com/pytest-dev/pytest/issues/11306>`_: Fixed bug using ``--importmode=importlib`` which would cause package ``__init__.py`` files to be imported more than once in some cases. + + +- `#11367 <https://github.com/pytest-dev/pytest/issues/11367>`_: Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown. + + +- `#11394 <https://github.com/pytest-dev/pytest/issues/11394>`_: Fixed crash when parsing long command line arguments that might be interpreted as files. + + + +Improved Documentation +---------------------- + +- `#11391 <https://github.com/pytest-dev/pytest/issues/11391>`_: Improved disclaimer on pytest plugin reference page to better indicate this is an automated, non-curated listing. + + pytest 7.4.1 (2023-09-02) ========================= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/example/reportingdemo.rst new/pytest-7.4.2/doc/en/example/reportingdemo.rst --- old/pytest-7.4.1/doc/en/example/reportingdemo.rst 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/doc/en/example/reportingdemo.rst 2023-09-07 20:43:41.000000000 +0200 @@ -554,13 +554,13 @@ E AssertionError: assert False E + where False = <built-in method startswith of str object at 0xdeadbeef0027>('456') E + where <built-in method startswith of str object at 0xdeadbeef0027> = '123'.startswith - E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0xdeadbeef0006>() - E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0xdeadbeef0029>() + E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0xdeadbeef0029>() + E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0xdeadbeef002a>() failure_demo.py:235: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = <failure_demo.TestMoreErrors object at 0xdeadbeef002a> + self = <failure_demo.TestMoreErrors object at 0xdeadbeef002b> def test_global_func(self): > assert isinstance(globf(42), float) @@ -571,18 +571,18 @@ failure_demo.py:238: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = <failure_demo.TestMoreErrors object at 0xdeadbeef002b> + self = <failure_demo.TestMoreErrors object at 0xdeadbeef002c> def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = <failure_demo.TestMoreErrors object at 0xdeadbeef002b>.x + E + where 42 = <failure_demo.TestMoreErrors object at 0xdeadbeef002c>.x failure_demo.py:242: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = <failure_demo.TestMoreErrors object at 0xdeadbeef002c> + self = <failure_demo.TestMoreErrors object at 0xdeadbeef002d> def test_compare(self): > assert globf(10) < 5 @@ -592,7 +592,7 @@ failure_demo.py:245: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = <failure_demo.TestMoreErrors object at 0xdeadbeef002d> + self = <failure_demo.TestMoreErrors object at 0xdeadbeef002e> def test_try_finally(self): x = 1 @@ -603,7 +603,7 @@ failure_demo.py:250: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef002e> + self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef002f> def test_single_line(self): class A: @@ -618,7 +618,7 @@ failure_demo.py:261: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef002f> + self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef0030> def test_multiline(self): class A: @@ -637,7 +637,7 @@ failure_demo.py:268: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef0030> + self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef0031> def test_custom_repr(self): class JSON: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/getting-started.rst new/pytest-7.4.2/doc/en/getting-started.rst --- old/pytest-7.4.1/doc/en/getting-started.rst 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/doc/en/getting-started.rst 2023-09-07 20:43:41.000000000 +0200 @@ -22,7 +22,7 @@ .. code-block:: bash $ pytest --version - pytest 7.4.1 + pytest 7.4.2 .. _`simpletest`: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/index.rst new/pytest-7.4.2/doc/en/index.rst --- old/pytest-7.4.1/doc/en/index.rst 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/doc/en/index.rst 2023-09-07 20:43:41.000000000 +0200 @@ -2,7 +2,6 @@ .. sidebar:: Next Open Trainings - - `pytest: Professionelles Testen (nicht nur) für Python <https://workshoptage.ch/workshops/2023/pytest-professionelles-testen-nicht-nur-fuer-python-2/>`_, at `Workshoptage 2023 <https://workshoptage.ch/>`_, **September 5th**, `OST <https://www.ost.ch/en>`_ Campus **Rapperswil, Switzerland** - `Professional Testing with Python <https://python-academy.com/courses/python_course_testing.html>`_, via `Python Academy <https://www.python-academy.com/>`_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** Also see :doc:`previous talks and blogposts <talks>`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/doc/en/reference/plugin_list.rst new/pytest-7.4.2/doc/en/reference/plugin_list.rst --- old/pytest-7.4.1/doc/en/reference/plugin_list.rst 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/doc/en/reference/plugin_list.rst 2023-09-07 20:43:41.000000000 +0200 @@ -1,14 +1,26 @@ .. _plugin-list: -Plugin List -=========== +Pytest Plugin List +================== -PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically together with a manually-maintained list in `the source -code <https://github.com/pytest-dev/pytest/blob/main/scripts/update-plugin-list.py>`_. +Below is an automated compilation of ``pytest``` plugins available on `PyPI <https://pypi.org>`_. +It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. Packages classified as inactive are excluded. +For detailed insights into how this list is generated, +please refer to `the update script <https://github.com/pytest-dev/pytest/blob/main/scripts/update-plugin-list.py>`_. + +.. warning:: + + Please be aware that this list is not a curated collection of projects + and does not undergo a systematic review process. + It serves purely as an informational resource to aid in the discovery of ``pytest`` plugins. + + Do not presume any endorsement from the ``pytest`` project or its developers, + and always conduct your own quality assessment before incorporating any of these plugins into your own projects. + + .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the page. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/scripts/update-plugin-list.py new/pytest-7.4.2/scripts/update-plugin-list.py --- old/pytest-7.4.1/scripts/update-plugin-list.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/scripts/update-plugin-list.py 2023-09-07 20:43:41.000000000 +0200 @@ -13,14 +13,26 @@ FILE_HEAD = r""" .. _plugin-list: -Plugin List -=========== +Pytest Plugin List +================== -PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically together with a manually-maintained list in `the source -code <https://github.com/pytest-dev/pytest/blob/main/scripts/update-plugin-list.py>`_. +Below is an automated compilation of ``pytest``` plugins available on `PyPI <https://pypi.org>`_. +It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. Packages classified as inactive are excluded. +For detailed insights into how this list is generated, +please refer to `the update script <https://github.com/pytest-dev/pytest/blob/main/scripts/update-plugin-list.py>`_. + +.. warning:: + + Please be aware that this list is not a curated collection of projects + and does not undergo a systematic review process. + It serves purely as an informational resource to aid in the discovery of ``pytest`` plugins. + + Do not presume any endorsement from the ``pytest`` project or its developers, + and always conduct your own quality assessment before incorporating any of these plugins into your own projects. + + .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the page. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/_pytest/_version.py new/pytest-7.4.2/src/_pytest/_version.py --- old/pytest-7.4.1/src/_pytest/_version.py 2023-09-02 17:00:18.000000000 +0200 +++ new/pytest-7.4.2/src/_pytest/_version.py 2023-09-07 20:44:06.000000000 +0200 @@ -1,4 +1,4 @@ # file generated by setuptools_scm # don't change, don't track in version control -__version__ = version = '7.4.1' -__version_tuple__ = version_tuple = (7, 4, 1) +__version__ = version = '7.4.2' +__version_tuple__ = version_tuple = (7, 4, 2) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/_pytest/config/__init__.py new/pytest-7.4.2/src/_pytest/config/__init__.py --- old/pytest-7.4.1/src/_pytest/config/__init__.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/src/_pytest/config/__init__.py 2023-09-07 20:43:41.000000000 +0200 @@ -57,6 +57,7 @@ from _pytest.pathlib import import_path from _pytest.pathlib import ImportMode from _pytest.pathlib import resolve_package_path +from _pytest.pathlib import safe_exists from _pytest.stash import Stash from _pytest.warning_types import PytestConfigWarning from _pytest.warning_types import warn_explicit_for @@ -557,12 +558,8 @@ anchor = absolutepath(current / path) # Ensure we do not break if what appears to be an anchor - # is in fact a very long option (#10169). - try: - anchor_exists = anchor.exists() - except OSError: # pragma: no cover - anchor_exists = False - if anchor_exists: + # is in fact a very long option (#10169, #11394). + if safe_exists(anchor): self._try_load_conftest(anchor, importmode, rootpath) foundanchor = True if not foundanchor: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/_pytest/config/findpaths.py new/pytest-7.4.2/src/_pytest/config/findpaths.py --- old/pytest-7.4.1/src/_pytest/config/findpaths.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/src/_pytest/config/findpaths.py 2023-09-07 20:43:41.000000000 +0200 @@ -16,6 +16,7 @@ from _pytest.outcomes import fail from _pytest.pathlib import absolutepath from _pytest.pathlib import commonpath +from _pytest.pathlib import safe_exists if TYPE_CHECKING: from . import Config @@ -151,14 +152,6 @@ return path return path.parent - def safe_exists(path: Path) -> bool: - # This can throw on paths that contain characters unrepresentable at the OS level, - # or with invalid syntax on Windows (https://bugs.python.org/issue35306) - try: - return path.exists() - except OSError: - return False - # These look like paths but may not exist possible_paths = ( absolutepath(get_file_part_from_node_id(arg)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/_pytest/doctest.py new/pytest-7.4.2/src/_pytest/doctest.py --- old/pytest-7.4.1/src/_pytest/doctest.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/src/_pytest/doctest.py 2023-09-07 20:43:41.000000000 +0200 @@ -1,5 +1,6 @@ """Discover and run doctests in modules and test files.""" import bdb +import functools import inspect import os import platform @@ -536,6 +537,25 @@ tests, obj, name, module, source_lines, globs, seen ) + if sys.version_info < (3, 13): + + def _from_module(self, module, object): + """`cached_property` objects are never considered a part + of the 'current module'. As such they are skipped by doctest. + Here we override `_from_module` to check the underlying + function instead. https://github.com/python/cpython/issues/107995 + """ + if hasattr(functools, "cached_property") and isinstance( + object, functools.cached_property + ): + object = object.func + + # Type ignored because this is a private function. + return super()._from_module(module, object) # type: ignore[misc] + + else: # pragma: no cover + pass + if self.path.name == "conftest.py": module = self.config.pluginmanager._importconftest( self.path, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/_pytest/junitxml.py new/pytest-7.4.2/src/_pytest/junitxml.py --- old/pytest-7.4.1/src/_pytest/junitxml.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/src/_pytest/junitxml.py 2023-09-07 20:43:41.000000000 +0200 @@ -502,6 +502,10 @@ # Local hack to handle xdist report order. workernode = getattr(report, "node", None) reporter = self.node_reporters.pop((nodeid, workernode)) + + for propname, propvalue in report.user_properties: + reporter.add_property(propname, str(propvalue)) + if reporter is not None: reporter.finalize() @@ -599,9 +603,6 @@ reporter = self._opentestcase(report) reporter.write_captured_output(report) - for propname, propvalue in report.user_properties: - reporter.add_property(propname, str(propvalue)) - self.finalize(report) report_wid = getattr(report, "worker_id", None) report_ii = getattr(report, "item_index", None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/_pytest/main.py new/pytest-7.4.2/src/_pytest/main.py --- old/pytest-7.4.1/src/_pytest/main.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/src/_pytest/main.py 2023-09-07 20:43:41.000000000 +0200 @@ -36,6 +36,7 @@ from _pytest.pathlib import absolutepath from _pytest.pathlib import bestrelpath from _pytest.pathlib import fnmatch_ex +from _pytest.pathlib import safe_exists from _pytest.pathlib import visit from _pytest.reports import CollectReport from _pytest.reports import TestReport @@ -895,7 +896,7 @@ strpath = search_pypath(strpath) fspath = invocation_path / strpath fspath = absolutepath(fspath) - if not fspath.exists(): + if not safe_exists(fspath): msg = ( "module or package not found: {arg} (missing __init__.py?)" if as_pypath diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/_pytest/pathlib.py new/pytest-7.4.2/src/_pytest/pathlib.py --- old/pytest-7.4.1/src/_pytest/pathlib.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/src/_pytest/pathlib.py 2023-09-07 20:43:41.000000000 +0200 @@ -623,6 +623,10 @@ # Use the parts for the relative path to the root path. path_parts = relative_path.parts + # Module name for packages do not contain the __init__ file. + if path_parts[-1] == "__init__": + path_parts = path_parts[:-1] + return ".".join(path_parts) @@ -787,3 +791,13 @@ shutil.copyfile(x, newx) elif x.is_dir(): newx.mkdir(exist_ok=True) + + +def safe_exists(p: Path) -> bool: + """Like Path.exists(), but account for input arguments that might be too long (#11394).""" + try: + return p.exists() + except (ValueError, OSError): + # ValueError: stat: path too long for Windows + # OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect + return False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/pytest.egg-info/PKG-INFO new/pytest-7.4.2/src/pytest.egg-info/PKG-INFO --- old/pytest-7.4.1/src/pytest.egg-info/PKG-INFO 2023-09-02 17:00:18.000000000 +0200 +++ new/pytest-7.4.2/src/pytest.egg-info/PKG-INFO 2023-09-07 20:44:06.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pytest -Version: 7.4.1 +Version: 7.4.2 Summary: pytest: simple powerful testing with Python Home-page: https://docs.pytest.org/en/latest/ Author: Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others @@ -34,8 +34,24 @@ Classifier: Topic :: Utilities Requires-Python: >=3.7 Description-Content-Type: text/x-rst -Provides-Extra: testing License-File: LICENSE +Requires-Dist: iniconfig +Requires-Dist: packaging +Requires-Dist: pluggy<2.0,>=0.12 +Requires-Dist: colorama; sys_platform == "win32" +Requires-Dist: exceptiongroup>=1.0.0rc8; python_version < "3.11" +Requires-Dist: importlib-metadata>=0.12; python_version < "3.8" +Requires-Dist: tomli>=1.0.0; python_version < "3.11" +Provides-Extra: testing +Requires-Dist: argcomplete; extra == "testing" +Requires-Dist: attrs>=19.2.0; extra == "testing" +Requires-Dist: hypothesis>=3.56; extra == "testing" +Requires-Dist: mock; extra == "testing" +Requires-Dist: nose; extra == "testing" +Requires-Dist: pygments>=2.7.2; extra == "testing" +Requires-Dist: requests; extra == "testing" +Requires-Dist: setuptools; extra == "testing" +Requires-Dist: xmlschema; extra == "testing" .. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg :target: https://docs.pytest.org/en/stable/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/src/pytest.egg-info/SOURCES.txt new/pytest-7.4.2/src/pytest.egg-info/SOURCES.txt --- old/pytest-7.4.1/src/pytest.egg-info/SOURCES.txt 2023-09-02 17:00:18.000000000 +0200 +++ new/pytest-7.4.2/src/pytest.egg-info/SOURCES.txt 2023-09-07 20:44:07.000000000 +0200 @@ -233,6 +233,7 @@ doc/en/announce/release-7.3.2.rst doc/en/announce/release-7.4.0.rst doc/en/announce/release-7.4.1.rst +doc/en/announce/release-7.4.2.rst doc/en/announce/sprint2016.rst doc/en/example/attic.rst doc/en/example/conftest.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/testing/test_doctest.py new/pytest-7.4.2/testing/test_doctest.py --- old/pytest-7.4.1/testing/test_doctest.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/testing/test_doctest.py 2023-09-07 20:43:41.000000000 +0200 @@ -482,6 +482,27 @@ reprec = pytester.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) + @pytest.mark.skipif( + sys.version_info[:2] <= (3, 7), reason="Only Python 3.7 or less" + ) + def test_doctest_cached_property(self, pytester: Pytester): + p = pytester.makepyfile( + """ + import functools + + class Foo: + @functools.cached_property + def foo(self): + ''' + >>> assert False, "Tacos!" + ''' + ... + """ + ) + result = pytester.runpytest(p, "--doctest-modules") + result.assert_outcomes(failed=1) + assert "Tacos!" in result.stdout.str() + def test_doctestmodule_external_and_issue116(self, pytester: Pytester): p = pytester.mkpydir("hello") p.joinpath("__init__.py").write_text( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/testing/test_junitxml.py new/pytest-7.4.2/testing/test_junitxml.py --- old/pytest-7.4.1/testing/test_junitxml.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/testing/test_junitxml.py 2023-09-07 20:43:41.000000000 +0200 @@ -1228,6 +1228,36 @@ result.stdout.fnmatch_lines(["*= 1 passed in *"]) +def test_record_property_on_test_and_teardown_failure( + pytester: Pytester, run_and_parse: RunAndParse +) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def other(record_property): + record_property("bar", 1) + yield + assert 0 + + def test_record(record_property, other): + record_property("foo", "<1") + assert 0 + """ + ) + result, dom = run_and_parse() + node = dom.find_first_by_tag("testsuite") + tnodes = node.find_by_tag("testcase") + for tnode in tnodes: + psnode = tnode.find_first_by_tag("properties") + assert psnode, f"testcase didn't had expected properties:\n{tnode}" + pnodes = psnode.find_by_tag("property") + pnodes[0].assert_attr(name="bar", value="1") + pnodes[1].assert_attr(name="foo", value="<1") + result.stdout.fnmatch_lines(["*= 1 failed, 1 error *"]) + + def test_record_property_same_name( pytester: Pytester, run_and_parse: RunAndParse ) -> None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/testing/test_main.py new/pytest-7.4.2/testing/test_main.py --- old/pytest-7.4.1/testing/test_main.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/testing/test_main.py 2023-09-07 20:43:41.000000000 +0200 @@ -262,3 +262,34 @@ "* 1 passed in *", ] ) + + +def test_very_long_cmdline_arg(pytester: Pytester) -> None: + """ + Regression test for #11394. + + Note: we could not manage to actually reproduce the error with this code, we suspect + GitHub runners are configured to support very long paths, however decided to leave + the test in place in case this ever regresses in the future. + """ + pytester.makeconftest( + """ + import pytest + + def pytest_addoption(parser): + parser.addoption("--long-list", dest="long_list", action="store", default="all", help="List of things") + + @pytest.fixture(scope="module") + def specified_feeds(request): + list_string = request.config.getoption("--long-list") + return list_string.split(',') + """ + ) + pytester.makepyfile( + """ + def test_foo(specified_feeds): + assert len(specified_feeds) == 100_000 + """ + ) + result = pytester.runpytest("--long-list", ",".join(["helloworld"] * 100_000)) + result.stdout.fnmatch_lines("* 1 passed *") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-7.4.1/testing/test_pathlib.py new/pytest-7.4.2/testing/test_pathlib.py --- old/pytest-7.4.1/testing/test_pathlib.py 2023-09-02 16:59:58.000000000 +0200 +++ new/pytest-7.4.2/testing/test_pathlib.py 2023-09-07 20:43:41.000000000 +0200 @@ -1,3 +1,4 @@ +import errno import os.path import pickle import sys @@ -18,11 +19,13 @@ from _pytest.pathlib import get_extended_length_path_str from _pytest.pathlib import get_lock_path from _pytest.pathlib import import_path +from _pytest.pathlib import ImportMode from _pytest.pathlib import ImportPathMismatchError from _pytest.pathlib import insert_missing_modules from _pytest.pathlib import maybe_delete_a_numbered_dir from _pytest.pathlib import module_name_from_path from _pytest.pathlib import resolve_package_path +from _pytest.pathlib import safe_exists from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit from _pytest.tmpdir import TempPathFactory @@ -585,6 +588,10 @@ result = module_name_from_path(Path("/home/foo/test_foo.py"), Path("/bar")) assert result == "home.foo.test_foo" + # Importing __init__.py files should return the package as module name. + result = module_name_from_path(tmp_path / "src/app/__init__.py", tmp_path) + assert result == "src.app" + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: @@ -615,3 +622,72 @@ assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"] assert modules["xxx"].tests is modules["xxx.tests"] assert modules["xxx.tests"].foo is modules["xxx.tests.foo"] + + def test_importlib_package(self, monkeypatch: MonkeyPatch, tmp_path: Path): + """ + Importing a package using --importmode=importlib should not import the + package's __init__.py file more than once (#11306). + """ + monkeypatch.chdir(tmp_path) + monkeypatch.syspath_prepend(tmp_path) + + package_name = "importlib_import_package" + tmp_path.joinpath(package_name).mkdir() + init = tmp_path.joinpath(f"{package_name}/__init__.py") + init.write_text( + dedent( + """ + from .singleton import Singleton + + instance = Singleton() + """ + ), + encoding="ascii", + ) + singleton = tmp_path.joinpath(f"{package_name}/singleton.py") + singleton.write_text( + dedent( + """ + class Singleton: + INSTANCES = [] + + def __init__(self) -> None: + self.INSTANCES.append(self) + if len(self.INSTANCES) > 1: + raise RuntimeError("Already initialized") + """ + ), + encoding="ascii", + ) + + mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) + assert len(mod.instance.INSTANCES) == 1 + + +def test_safe_exists(tmp_path: Path) -> None: + d = tmp_path.joinpath("some_dir") + d.mkdir() + assert safe_exists(d) is True + + f = tmp_path.joinpath("some_file") + f.touch() + assert safe_exists(f) is True + + # Use unittest.mock() as a context manager to have a very narrow + # patch lifetime. + p = tmp_path.joinpath("some long filename" * 100) + with unittest.mock.patch.object( + Path, + "exists", + autospec=True, + side_effect=OSError(errno.ENAMETOOLONG, "name too long"), + ): + assert safe_exists(p) is False + + with unittest.mock.patch.object( + Path, + "exists", + autospec=True, + side_effect=ValueError("name too long"), + ): + assert safe_exists(p) is False