Merge pull request #11152 from Zac-HD/drop-py37
This commit is contained in:
		
						commit
						a50ea1b8e7
					
				| 
						 | 
					@ -45,7 +45,7 @@ jobs:
 | 
				
			||||||
    - name: Set up Python
 | 
					    - name: Set up Python
 | 
				
			||||||
      uses: actions/setup-python@v4
 | 
					      uses: actions/setup-python@v4
 | 
				
			||||||
      with:
 | 
					      with:
 | 
				
			||||||
        python-version: "3.7"
 | 
					        python-version: "3.11"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Install tox
 | 
					    - name: Install tox
 | 
				
			||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,25 +37,23 @@ jobs:
 | 
				
			||||||
      fail-fast: false
 | 
					      fail-fast: false
 | 
				
			||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        name: [
 | 
					        name: [
 | 
				
			||||||
          "windows-py37",
 | 
					 | 
				
			||||||
          "windows-py37-pluggy",
 | 
					 | 
				
			||||||
          "windows-py38",
 | 
					          "windows-py38",
 | 
				
			||||||
 | 
					          "windows-py38-pluggy",
 | 
				
			||||||
          "windows-py39",
 | 
					          "windows-py39",
 | 
				
			||||||
          "windows-py310",
 | 
					          "windows-py310",
 | 
				
			||||||
          "windows-py311",
 | 
					          "windows-py311",
 | 
				
			||||||
          "windows-py312",
 | 
					          "windows-py312",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          "ubuntu-py37",
 | 
					 | 
				
			||||||
          "ubuntu-py37-pluggy",
 | 
					 | 
				
			||||||
          "ubuntu-py37-freeze",
 | 
					 | 
				
			||||||
          "ubuntu-py38",
 | 
					          "ubuntu-py38",
 | 
				
			||||||
 | 
					          "ubuntu-py38-pluggy",
 | 
				
			||||||
 | 
					          "ubuntu-py38-freeze",
 | 
				
			||||||
          "ubuntu-py39",
 | 
					          "ubuntu-py39",
 | 
				
			||||||
          "ubuntu-py310",
 | 
					          "ubuntu-py310",
 | 
				
			||||||
          "ubuntu-py311",
 | 
					          "ubuntu-py311",
 | 
				
			||||||
          "ubuntu-py312",
 | 
					          "ubuntu-py312",
 | 
				
			||||||
          "ubuntu-pypy3",
 | 
					          "ubuntu-pypy3",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          "macos-py37",
 | 
					          "macos-py38",
 | 
				
			||||||
          "macos-py39",
 | 
					          "macos-py39",
 | 
				
			||||||
          "macos-py310",
 | 
					          "macos-py310",
 | 
				
			||||||
          "macos-py312",
 | 
					          "macos-py312",
 | 
				
			||||||
| 
						 | 
					@ -66,19 +64,15 @@ jobs:
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        include:
 | 
					        include:
 | 
				
			||||||
          - name: "windows-py37"
 | 
					 | 
				
			||||||
            python: "3.7"
 | 
					 | 
				
			||||||
            os: windows-latest
 | 
					 | 
				
			||||||
            tox_env: "py37-numpy"
 | 
					 | 
				
			||||||
          - name: "windows-py37-pluggy"
 | 
					 | 
				
			||||||
            python: "3.7"
 | 
					 | 
				
			||||||
            os: windows-latest
 | 
					 | 
				
			||||||
            tox_env: "py37-pluggymain-pylib-xdist"
 | 
					 | 
				
			||||||
          - name: "windows-py38"
 | 
					          - name: "windows-py38"
 | 
				
			||||||
            python: "3.8"
 | 
					            python: "3.8"
 | 
				
			||||||
            os: windows-latest
 | 
					            os: windows-latest
 | 
				
			||||||
            tox_env: "py38-unittestextras"
 | 
					            tox_env: "py38-unittestextras"
 | 
				
			||||||
            use_coverage: true
 | 
					            use_coverage: true
 | 
				
			||||||
 | 
					          - name: "windows-py38-pluggy"
 | 
				
			||||||
 | 
					            python: "3.8"
 | 
				
			||||||
 | 
					            os: windows-latest
 | 
				
			||||||
 | 
					            tox_env: "py38-pluggymain-pylib-xdist"
 | 
				
			||||||
          - name: "windows-py39"
 | 
					          - name: "windows-py39"
 | 
				
			||||||
            python: "3.9"
 | 
					            python: "3.9"
 | 
				
			||||||
            os: windows-latest
 | 
					            os: windows-latest
 | 
				
			||||||
| 
						 | 
					@ -96,23 +90,19 @@ jobs:
 | 
				
			||||||
            os: windows-latest
 | 
					            os: windows-latest
 | 
				
			||||||
            tox_env: "py312"
 | 
					            tox_env: "py312"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          - name: "ubuntu-py37"
 | 
					 | 
				
			||||||
            python: "3.7"
 | 
					 | 
				
			||||||
            os: ubuntu-latest
 | 
					 | 
				
			||||||
            tox_env: "py37-lsof-numpy-pexpect"
 | 
					 | 
				
			||||||
            use_coverage: true
 | 
					 | 
				
			||||||
          - name: "ubuntu-py37-pluggy"
 | 
					 | 
				
			||||||
            python: "3.7"
 | 
					 | 
				
			||||||
            os: ubuntu-latest
 | 
					 | 
				
			||||||
            tox_env: "py37-pluggymain-pylib-xdist"
 | 
					 | 
				
			||||||
          - name: "ubuntu-py37-freeze"
 | 
					 | 
				
			||||||
            python: "3.7"
 | 
					 | 
				
			||||||
            os: ubuntu-latest
 | 
					 | 
				
			||||||
            tox_env: "py37-freeze"
 | 
					 | 
				
			||||||
          - name: "ubuntu-py38"
 | 
					          - name: "ubuntu-py38"
 | 
				
			||||||
            python: "3.8"
 | 
					            python: "3.8"
 | 
				
			||||||
            os: ubuntu-latest
 | 
					            os: ubuntu-latest
 | 
				
			||||||
            tox_env: "py38-xdist"
 | 
					            tox_env: "py38-lsof-numpy-pexpect"
 | 
				
			||||||
 | 
					            use_coverage: true
 | 
				
			||||||
 | 
					          - name: "ubuntu-py38-pluggy"
 | 
				
			||||||
 | 
					            python: "3.8"
 | 
				
			||||||
 | 
					            os: ubuntu-latest
 | 
				
			||||||
 | 
					            tox_env: "py38-pluggymain-pylib-xdist"
 | 
				
			||||||
 | 
					          - name: "ubuntu-py38-freeze"
 | 
				
			||||||
 | 
					            python: "3.8"
 | 
				
			||||||
 | 
					            os: ubuntu-latest
 | 
				
			||||||
 | 
					            tox_env: "py38-freeze"
 | 
				
			||||||
          - name: "ubuntu-py39"
 | 
					          - name: "ubuntu-py39"
 | 
				
			||||||
            python: "3.9"
 | 
					            python: "3.9"
 | 
				
			||||||
            os: ubuntu-latest
 | 
					            os: ubuntu-latest
 | 
				
			||||||
| 
						 | 
					@ -132,14 +122,14 @@ jobs:
 | 
				
			||||||
            tox_env: "py312"
 | 
					            tox_env: "py312"
 | 
				
			||||||
            use_coverage: true
 | 
					            use_coverage: true
 | 
				
			||||||
          - name: "ubuntu-pypy3"
 | 
					          - name: "ubuntu-pypy3"
 | 
				
			||||||
            python: "pypy-3.7"
 | 
					            python: "pypy-3.8"
 | 
				
			||||||
            os: ubuntu-latest
 | 
					            os: ubuntu-latest
 | 
				
			||||||
            tox_env: "pypy3-xdist"
 | 
					            tox_env: "pypy3-xdist"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          - name: "macos-py37"
 | 
					          - name: "macos-py38"
 | 
				
			||||||
            python: "3.7"
 | 
					            python: "3.8"
 | 
				
			||||||
            os: macos-latest
 | 
					            os: macos-latest
 | 
				
			||||||
            tox_env: "py37-xdist"
 | 
					            tox_env: "py38-xdist"
 | 
				
			||||||
          - name: "macos-py39"
 | 
					          - name: "macos-py39"
 | 
				
			||||||
            python: "3.9"
 | 
					            python: "3.9"
 | 
				
			||||||
            os: macos-latest
 | 
					            os: macos-latest
 | 
				
			||||||
| 
						 | 
					@ -160,11 +150,11 @@ jobs:
 | 
				
			||||||
            tox_env: "plugins"
 | 
					            tox_env: "plugins"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          - name: "docs"
 | 
					          - name: "docs"
 | 
				
			||||||
            python: "3.7"
 | 
					            python: "3.8"
 | 
				
			||||||
            os: ubuntu-latest
 | 
					            os: ubuntu-latest
 | 
				
			||||||
            tox_env: "docs"
 | 
					            tox_env: "docs"
 | 
				
			||||||
          - name: "doctesting"
 | 
					          - name: "doctesting"
 | 
				
			||||||
            python: "3.7"
 | 
					            python: "3.8"
 | 
				
			||||||
            os: ubuntu-latest
 | 
					            os: ubuntu-latest
 | 
				
			||||||
            tox_env: "doctesting"
 | 
					            tox_env: "doctesting"
 | 
				
			||||||
            use_coverage: true
 | 
					            use_coverage: true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,12 +40,12 @@ repos:
 | 
				
			||||||
    rev: v3.10.0
 | 
					    rev: v3.10.0
 | 
				
			||||||
    hooks:
 | 
					    hooks:
 | 
				
			||||||
    -   id: reorder-python-imports
 | 
					    -   id: reorder-python-imports
 | 
				
			||||||
        args: ['--application-directories=.:src', --py37-plus]
 | 
					        args: ['--application-directories=.:src', --py38-plus]
 | 
				
			||||||
-   repo: https://github.com/asottile/pyupgrade
 | 
					-   repo: https://github.com/asottile/pyupgrade
 | 
				
			||||||
    rev: v3.7.0
 | 
					    rev: v3.7.0
 | 
				
			||||||
    hooks:
 | 
					    hooks:
 | 
				
			||||||
    -   id: pyupgrade
 | 
					    -   id: pyupgrade
 | 
				
			||||||
        args: [--py37-plus]
 | 
					        args: [--py38-plus]
 | 
				
			||||||
-   repo: https://github.com/asottile/setup-cfg-fmt
 | 
					-   repo: https://github.com/asottile/setup-cfg-fmt
 | 
				
			||||||
    rev: v2.3.0
 | 
					    rev: v2.3.0
 | 
				
			||||||
    hooks:
 | 
					    hooks:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,7 +201,7 @@ Short version
 | 
				
			||||||
#. Follow **PEP-8** for naming and `black <https://github.com/psf/black>`_ for formatting.
 | 
					#. Follow **PEP-8** for naming and `black <https://github.com/psf/black>`_ for formatting.
 | 
				
			||||||
#. Tests are run using ``tox``::
 | 
					#. Tests are run using ``tox``::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox -e linting,py37
 | 
					    tox -e linting,py39
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   The test environments above are usually enough to cover most cases locally.
 | 
					   The test environments above are usually enough to cover most cases locally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -272,24 +272,24 @@ Here is a simple overview, with pytest-specific bits:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#. Run all the tests
 | 
					#. Run all the tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   You need to have Python 3.7 available in your system.  Now
 | 
					   You need to have Python 3.8 or later available in your system.  Now
 | 
				
			||||||
   running tests is as simple as issuing this command::
 | 
					   running tests is as simple as issuing this command::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $ tox -e linting,py37
 | 
					    $ tox -e linting,py39
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   This command will run tests via the "tox" tool against Python 3.7
 | 
					   This command will run tests via the "tox" tool against Python 3.9
 | 
				
			||||||
   and also perform "lint" coding-style checks.
 | 
					   and also perform "lint" coding-style checks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#. You can now edit your local working copy and run the tests again as necessary. Please follow PEP-8 for naming.
 | 
					#. You can now edit your local working copy and run the tests again as necessary. Please follow PEP-8 for naming.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   You can pass different options to ``tox``. For example, to run tests on Python 3.7 and pass options to pytest
 | 
					   You can pass different options to ``tox``. For example, to run tests on Python 3.9 and pass options to pytest
 | 
				
			||||||
   (e.g. enter pdb on failure) to pytest you can do::
 | 
					   (e.g. enter pdb on failure) to pytest you can do::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $ tox -e py37 -- --pdb
 | 
					    $ tox -e py39 -- --pdb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   Or to only run tests in a particular test module on Python 3.7::
 | 
					   Or to only run tests in a particular test module on Python 3.9::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $ tox -e py37 -- testing/test_config.py
 | 
					    $ tox -e py39 -- testing/test_config.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   When committing, ``pre-commit`` will re-format the files if necessary.
 | 
					   When committing, ``pre-commit`` will re-format the files if necessary.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,7 @@ Features
 | 
				
			||||||
- Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial),
 | 
					- Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial),
 | 
				
			||||||
  `nose <https://docs.pytest.org/en/stable/how-to/nose.html>`_ test suites out of the box
 | 
					  `nose <https://docs.pytest.org/en/stable/how-to/nose.html>`_ test suites out of the box
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Python 3.7+ or PyPy3
 | 
					- Python 3.8+ or PyPy3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Rich plugin architecture, with over 850+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community
 | 
					- Rich plugin architecture, with over 850+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27
 | 
				
			||||||
 | 
					<https://devguide.python.org/versions/>`__.
 | 
				
			||||||
| 
						 | 
					@ -87,6 +87,7 @@ Released pytest versions support all Python versions that are actively maintaine
 | 
				
			||||||
==============  ===================
 | 
					==============  ===================
 | 
				
			||||||
pytest version  min. Python version
 | 
					pytest version  min. Python version
 | 
				
			||||||
==============  ===================
 | 
					==============  ===================
 | 
				
			||||||
 | 
					8.0+            3.8+
 | 
				
			||||||
7.1+            3.7+
 | 
					7.1+            3.7+
 | 
				
			||||||
6.2 - 7.0       3.6+
 | 
					6.2 - 7.0       3.6+
 | 
				
			||||||
5.0 - 6.1       3.5+
 | 
					5.0 - 6.1       3.5+
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,12 +15,10 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# The full version, including alpha/beta/rc tags.
 | 
					# The full version, including alpha/beta/rc tags.
 | 
				
			||||||
# The short X.Y version.
 | 
					# The short X.Y version.
 | 
				
			||||||
import ast
 | 
					 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import shutil
 | 
					import shutil
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
from textwrap import dedent
 | 
					from textwrap import dedent
 | 
				
			||||||
from typing import List
 | 
					 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					from typing import TYPE_CHECKING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest import __version__ as version
 | 
					from _pytest import __version__ as version
 | 
				
			||||||
| 
						 | 
					@ -451,25 +449,6 @@ def setup(app: "sphinx.application.Sphinx") -> None:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    configure_logging(app)
 | 
					    configure_logging(app)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Make Sphinx mark classes with "final" when decorated with @final.
 | 
					 | 
				
			||||||
    # We need this because we import final from pytest._compat, not from
 | 
					 | 
				
			||||||
    # typing (for Python < 3.8 compat), so Sphinx doesn't detect it.
 | 
					 | 
				
			||||||
    # To keep things simple we accept any `@final` decorator.
 | 
					 | 
				
			||||||
    # Ref: https://github.com/pytest-dev/pytest/pull/7780
 | 
					 | 
				
			||||||
    import sphinx.pycode.ast
 | 
					 | 
				
			||||||
    import sphinx.pycode.parser
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    original_is_final = sphinx.pycode.parser.VariableCommentPicker.is_final
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def patched_is_final(self, decorators: List[ast.expr]) -> bool:
 | 
					 | 
				
			||||||
        if original_is_final(self, decorators):
 | 
					 | 
				
			||||||
            return True
 | 
					 | 
				
			||||||
        return any(
 | 
					 | 
				
			||||||
            sphinx.pycode.ast.unparse(decorator) == "final" for decorator in decorators
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sphinx.pycode.parser.VariableCommentPicker.is_final = patched_is_final
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # legacypath.py monkey-patches pytest.Testdir in. Import the file so
 | 
					    # legacypath.py monkey-patches pytest.Testdir in. Import the file so
 | 
				
			||||||
    # that autodoc can discover references to it.
 | 
					    # that autodoc can discover references to it.
 | 
				
			||||||
    import _pytest.legacypath  # noqa: F401
 | 
					    import _pytest.legacypath  # noqa: F401
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ Get Started
 | 
				
			||||||
Install ``pytest``
 | 
					Install ``pytest``
 | 
				
			||||||
----------------------------------------
 | 
					----------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
``pytest`` requires: Python 3.7+ or PyPy3.
 | 
					``pytest`` requires: Python 3.8+ or PyPy3.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Run the following command in your command line:
 | 
					1. Run the following command in your command line:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Can run :ref:`unittest <unittest>` (including trial) and :ref:`nose <noseintegration>` test suites out of the box
 | 
					- Can run :ref:`unittest <unittest>` (including trial) and :ref:`nose <noseintegration>` test suites out of the box
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Python 3.7+ or PyPy 3
 | 
					- Python 3.8+ or PyPy 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Rich plugin architecture, with over 800+ :ref:`external plugins <plugin-list>` and thriving community
 | 
					- Rich plugin architecture, with over 800+ :ref:`external plugins <plugin-list>` and thriving community
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,6 @@ classifiers =
 | 
				
			||||||
    Operating System :: POSIX
 | 
					    Operating System :: POSIX
 | 
				
			||||||
    Programming Language :: Python :: 3
 | 
					    Programming Language :: Python :: 3
 | 
				
			||||||
    Programming Language :: Python :: 3 :: Only
 | 
					    Programming Language :: Python :: 3 :: Only
 | 
				
			||||||
    Programming Language :: Python :: 3.7
 | 
					 | 
				
			||||||
    Programming Language :: Python :: 3.8
 | 
					    Programming Language :: Python :: 3.8
 | 
				
			||||||
    Programming Language :: Python :: 3.9
 | 
					    Programming Language :: Python :: 3.9
 | 
				
			||||||
    Programming Language :: Python :: 3.10
 | 
					    Programming Language :: Python :: 3.10
 | 
				
			||||||
| 
						 | 
					@ -50,9 +49,8 @@ install_requires =
 | 
				
			||||||
    pluggy>=0.12,<2.0
 | 
					    pluggy>=0.12,<2.0
 | 
				
			||||||
    colorama;sys_platform=="win32"
 | 
					    colorama;sys_platform=="win32"
 | 
				
			||||||
    exceptiongroup>=1.0.0rc8;python_version<"3.11"
 | 
					    exceptiongroup>=1.0.0rc8;python_version<"3.11"
 | 
				
			||||||
    importlib-metadata>=0.12;python_version<"3.8"
 | 
					 | 
				
			||||||
    tomli>=1.0.0;python_version<"3.11"
 | 
					    tomli>=1.0.0;python_version<"3.11"
 | 
				
			||||||
python_requires = >=3.7
 | 
					python_requires = >=3.8
 | 
				
			||||||
package_dir =
 | 
					package_dir =
 | 
				
			||||||
    =src
 | 
					    =src
 | 
				
			||||||
setup_requires =
 | 
					setup_requires =
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,18 +17,21 @@ from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import ClassVar
 | 
					from typing import ClassVar
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import Final
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generic
 | 
					from typing import Generic
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					from typing import Literal
 | 
				
			||||||
from typing import Mapping
 | 
					from typing import Mapping
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
from typing import overload
 | 
					from typing import overload
 | 
				
			||||||
from typing import Pattern
 | 
					from typing import Pattern
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Sequence
 | 
				
			||||||
from typing import Set
 | 
					from typing import Set
 | 
				
			||||||
 | 
					from typing import SupportsIndex
 | 
				
			||||||
from typing import Tuple
 | 
					from typing import Tuple
 | 
				
			||||||
from typing import Type
 | 
					from typing import Type
 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					 | 
				
			||||||
from typing import TypeVar
 | 
					from typing import TypeVar
 | 
				
			||||||
from typing import Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,22 +45,16 @@ from _pytest._code.source import Source
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest._io.saferepr import safeformat
 | 
					from _pytest._io.saferepr import safeformat
 | 
				
			||||||
from _pytest._io.saferepr import saferepr
 | 
					from _pytest._io.saferepr import saferepr
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import get_real_func
 | 
					from _pytest.compat import get_real_func
 | 
				
			||||||
from _pytest.deprecated import check_ispytest
 | 
					from _pytest.deprecated import check_ispytest
 | 
				
			||||||
from _pytest.pathlib import absolutepath
 | 
					from _pytest.pathlib import absolutepath
 | 
				
			||||||
from _pytest.pathlib import bestrelpath
 | 
					from _pytest.pathlib import bestrelpath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					 | 
				
			||||||
    from typing_extensions import Final
 | 
					 | 
				
			||||||
    from typing_extensions import Literal
 | 
					 | 
				
			||||||
    from typing_extensions import SupportsIndex
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if sys.version_info[:2] < (3, 11):
 | 
					if sys.version_info[:2] < (3, 11):
 | 
				
			||||||
    from exceptiongroup import BaseExceptionGroup
 | 
					    from exceptiongroup import BaseExceptionGroup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Code:
 | 
					class Code:
 | 
				
			||||||
    """Wrapper around Python code objects."""
 | 
					    """Wrapper around Python code objects."""
 | 
				
			||||||
| 
						 | 
					@ -633,7 +630,7 @@ class ExceptionInfo(Generic[E]):
 | 
				
			||||||
    def getrepr(
 | 
					    def getrepr(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        showlocals: bool = False,
 | 
					        showlocals: bool = False,
 | 
				
			||||||
        style: "_TracebackStyle" = "long",
 | 
					        style: _TracebackStyle = "long",
 | 
				
			||||||
        abspath: bool = False,
 | 
					        abspath: bool = False,
 | 
				
			||||||
        tbfilter: Union[
 | 
					        tbfilter: Union[
 | 
				
			||||||
            bool, Callable[["ExceptionInfo[BaseException]"], Traceback]
 | 
					            bool, Callable[["ExceptionInfo[BaseException]"], Traceback]
 | 
				
			||||||
| 
						 | 
					@ -725,7 +722,7 @@ class FormattedExcinfo:
 | 
				
			||||||
    fail_marker: ClassVar = "E"
 | 
					    fail_marker: ClassVar = "E"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    showlocals: bool = False
 | 
					    showlocals: bool = False
 | 
				
			||||||
    style: "_TracebackStyle" = "long"
 | 
					    style: _TracebackStyle = "long"
 | 
				
			||||||
    abspath: bool = True
 | 
					    abspath: bool = True
 | 
				
			||||||
    tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True
 | 
					    tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True
 | 
				
			||||||
    funcargs: bool = False
 | 
					    funcargs: bool = False
 | 
				
			||||||
| 
						 | 
					@ -1090,7 +1087,7 @@ class ReprExceptionInfo(ExceptionRepr):
 | 
				
			||||||
class ReprTraceback(TerminalRepr):
 | 
					class ReprTraceback(TerminalRepr):
 | 
				
			||||||
    reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]]
 | 
					    reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]]
 | 
				
			||||||
    extraline: Optional[str]
 | 
					    extraline: Optional[str]
 | 
				
			||||||
    style: "_TracebackStyle"
 | 
					    style: _TracebackStyle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    entrysep: ClassVar = "_ "
 | 
					    entrysep: ClassVar = "_ "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1124,7 +1121,7 @@ class ReprTracebackNative(ReprTraceback):
 | 
				
			||||||
class ReprEntryNative(TerminalRepr):
 | 
					class ReprEntryNative(TerminalRepr):
 | 
				
			||||||
    lines: Sequence[str]
 | 
					    lines: Sequence[str]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    style: ClassVar["_TracebackStyle"] = "native"
 | 
					    style: ClassVar[_TracebackStyle] = "native"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def toterminal(self, tw: TerminalWriter) -> None:
 | 
					    def toterminal(self, tw: TerminalWriter) -> None:
 | 
				
			||||||
        tw.write("".join(self.lines))
 | 
					        tw.write("".join(self.lines))
 | 
				
			||||||
| 
						 | 
					@ -1136,7 +1133,7 @@ class ReprEntry(TerminalRepr):
 | 
				
			||||||
    reprfuncargs: Optional["ReprFuncArgs"]
 | 
					    reprfuncargs: Optional["ReprFuncArgs"]
 | 
				
			||||||
    reprlocals: Optional["ReprLocals"]
 | 
					    reprlocals: Optional["ReprLocals"]
 | 
				
			||||||
    reprfileloc: Optional["ReprFileLocation"]
 | 
					    reprfileloc: Optional["ReprFileLocation"]
 | 
				
			||||||
    style: "_TracebackStyle"
 | 
					    style: _TracebackStyle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _write_entry_lines(self, tw: TerminalWriter) -> None:
 | 
					    def _write_entry_lines(self, tw: TerminalWriter) -> None:
 | 
				
			||||||
        """Write the source code portions of a list of traceback entries with syntax highlighting.
 | 
					        """Write the source code portions of a list of traceback entries with syntax highlighting.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,8 +149,7 @@ def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[i
 | 
				
			||||||
    values: List[int] = []
 | 
					    values: List[int] = []
 | 
				
			||||||
    for x in ast.walk(node):
 | 
					    for x in ast.walk(node):
 | 
				
			||||||
        if isinstance(x, (ast.stmt, ast.ExceptHandler)):
 | 
					        if isinstance(x, (ast.stmt, ast.ExceptHandler)):
 | 
				
			||||||
            # Before Python 3.8, the lineno of a decorated class or function pointed at the decorator.
 | 
					            # The lineno points to the class/def, so need to include the decorators.
 | 
				
			||||||
            # Since Python 3.8, the lineno points to the class/def, so need to include the decorators.
 | 
					 | 
				
			||||||
            if isinstance(x, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
 | 
					            if isinstance(x, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
 | 
				
			||||||
                for d in x.decorator_list:
 | 
					                for d in x.decorator_list:
 | 
				
			||||||
                    values.append(d.lineno - 1)
 | 
					                    values.append(d.lineno - 1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,12 +2,12 @@
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import shutil
 | 
					import shutil
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Sequence
 | 
				
			||||||
from typing import TextIO
 | 
					from typing import TextIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .wcwidth import wcswidth
 | 
					from .wcwidth import wcswidth
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# This code was initially copied from py 1.8.1, file _io/terminalwriter.py.
 | 
					# This code was initially copied from py 1.8.1, file _io/terminalwriter.py.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,17 +44,6 @@ from _pytest.stash import StashKey
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
    from _pytest.assertion import AssertionState
 | 
					    from _pytest.assertion import AssertionState
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if sys.version_info >= (3, 8):
 | 
					 | 
				
			||||||
    namedExpr = ast.NamedExpr
 | 
					 | 
				
			||||||
    astNameConstant = ast.Constant
 | 
					 | 
				
			||||||
    astStr = ast.Constant
 | 
					 | 
				
			||||||
    astNum = ast.Constant
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
    namedExpr = ast.Expr
 | 
					 | 
				
			||||||
    astNameConstant = ast.NameConstant
 | 
					 | 
				
			||||||
    astStr = ast.Str
 | 
					 | 
				
			||||||
    astNum = ast.Num
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
assertstate_key = StashKey["AssertionState"]()
 | 
					assertstate_key = StashKey["AssertionState"]()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -686,12 +675,9 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
            if (
 | 
					            if (
 | 
				
			||||||
                expect_docstring
 | 
					                expect_docstring
 | 
				
			||||||
                and isinstance(item, ast.Expr)
 | 
					                and isinstance(item, ast.Expr)
 | 
				
			||||||
                and isinstance(item.value, astStr)
 | 
					                and isinstance(item.value, ast.Constant)
 | 
				
			||||||
            ):
 | 
					            ):
 | 
				
			||||||
                if sys.version_info >= (3, 8):
 | 
					                doc = item.value.value
 | 
				
			||||||
                    doc = item.value.value
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    doc = item.value.s
 | 
					 | 
				
			||||||
                if self.is_rewrite_disabled(doc):
 | 
					                if self.is_rewrite_disabled(doc):
 | 
				
			||||||
                    return
 | 
					                    return
 | 
				
			||||||
                expect_docstring = False
 | 
					                expect_docstring = False
 | 
				
			||||||
| 
						 | 
					@ -823,7 +809,7 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
        current = self.stack.pop()
 | 
					        current = self.stack.pop()
 | 
				
			||||||
        if self.stack:
 | 
					        if self.stack:
 | 
				
			||||||
            self.explanation_specifiers = self.stack[-1]
 | 
					            self.explanation_specifiers = self.stack[-1]
 | 
				
			||||||
        keys = [astStr(key) for key in current.keys()]
 | 
					        keys = [ast.Constant(key) for key in current.keys()]
 | 
				
			||||||
        format_dict = ast.Dict(keys, list(current.values()))
 | 
					        format_dict = ast.Dict(keys, list(current.values()))
 | 
				
			||||||
        form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
 | 
					        form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
 | 
				
			||||||
        name = "@py_format" + str(next(self.variable_counter))
 | 
					        name = "@py_format" + str(next(self.variable_counter))
 | 
				
			||||||
| 
						 | 
					@ -877,16 +863,16 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
        negation = ast.UnaryOp(ast.Not(), top_condition)
 | 
					        negation = ast.UnaryOp(ast.Not(), top_condition)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.enable_assertion_pass_hook:  # Experimental pytest_assertion_pass hook
 | 
					        if self.enable_assertion_pass_hook:  # Experimental pytest_assertion_pass hook
 | 
				
			||||||
            msg = self.pop_format_context(astStr(explanation))
 | 
					            msg = self.pop_format_context(ast.Constant(explanation))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Failed
 | 
					            # Failed
 | 
				
			||||||
            if assert_.msg:
 | 
					            if assert_.msg:
 | 
				
			||||||
                assertmsg = self.helper("_format_assertmsg", assert_.msg)
 | 
					                assertmsg = self.helper("_format_assertmsg", assert_.msg)
 | 
				
			||||||
                gluestr = "\n>assert "
 | 
					                gluestr = "\n>assert "
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                assertmsg = astStr("")
 | 
					                assertmsg = ast.Constant("")
 | 
				
			||||||
                gluestr = "assert "
 | 
					                gluestr = "assert "
 | 
				
			||||||
            err_explanation = ast.BinOp(astStr(gluestr), ast.Add(), msg)
 | 
					            err_explanation = ast.BinOp(ast.Constant(gluestr), ast.Add(), msg)
 | 
				
			||||||
            err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation)
 | 
					            err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation)
 | 
				
			||||||
            err_name = ast.Name("AssertionError", ast.Load())
 | 
					            err_name = ast.Name("AssertionError", ast.Load())
 | 
				
			||||||
            fmt = self.helper("_format_explanation", err_msg)
 | 
					            fmt = self.helper("_format_explanation", err_msg)
 | 
				
			||||||
| 
						 | 
					@ -902,8 +888,8 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
            hook_call_pass = ast.Expr(
 | 
					            hook_call_pass = ast.Expr(
 | 
				
			||||||
                self.helper(
 | 
					                self.helper(
 | 
				
			||||||
                    "_call_assertion_pass",
 | 
					                    "_call_assertion_pass",
 | 
				
			||||||
                    astNum(assert_.lineno),
 | 
					                    ast.Constant(assert_.lineno),
 | 
				
			||||||
                    astStr(orig),
 | 
					                    ast.Constant(orig),
 | 
				
			||||||
                    fmt_pass,
 | 
					                    fmt_pass,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
| 
						 | 
					@ -922,7 +908,7 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
                variables = [
 | 
					                variables = [
 | 
				
			||||||
                    ast.Name(name, ast.Store()) for name in self.format_variables
 | 
					                    ast.Name(name, ast.Store()) for name in self.format_variables
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
                clear_format = ast.Assign(variables, astNameConstant(None))
 | 
					                clear_format = ast.Assign(variables, ast.Constant(None))
 | 
				
			||||||
                self.statements.append(clear_format)
 | 
					                self.statements.append(clear_format)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        else:  # Original assertion rewriting
 | 
					        else:  # Original assertion rewriting
 | 
				
			||||||
| 
						 | 
					@ -933,9 +919,9 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
                assertmsg = self.helper("_format_assertmsg", assert_.msg)
 | 
					                assertmsg = self.helper("_format_assertmsg", assert_.msg)
 | 
				
			||||||
                explanation = "\n>assert " + explanation
 | 
					                explanation = "\n>assert " + explanation
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                assertmsg = astStr("")
 | 
					                assertmsg = ast.Constant("")
 | 
				
			||||||
                explanation = "assert " + explanation
 | 
					                explanation = "assert " + explanation
 | 
				
			||||||
            template = ast.BinOp(assertmsg, ast.Add(), astStr(explanation))
 | 
					            template = ast.BinOp(assertmsg, ast.Add(), ast.Constant(explanation))
 | 
				
			||||||
            msg = self.pop_format_context(template)
 | 
					            msg = self.pop_format_context(template)
 | 
				
			||||||
            fmt = self.helper("_format_explanation", msg)
 | 
					            fmt = self.helper("_format_explanation", msg)
 | 
				
			||||||
            err_name = ast.Name("AssertionError", ast.Load())
 | 
					            err_name = ast.Name("AssertionError", ast.Load())
 | 
				
			||||||
| 
						 | 
					@ -947,7 +933,7 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
        # Clear temporary variables by setting them to None.
 | 
					        # Clear temporary variables by setting them to None.
 | 
				
			||||||
        if self.variables:
 | 
					        if self.variables:
 | 
				
			||||||
            variables = [ast.Name(name, ast.Store()) for name in self.variables]
 | 
					            variables = [ast.Name(name, ast.Store()) for name in self.variables]
 | 
				
			||||||
            clear = ast.Assign(variables, astNameConstant(None))
 | 
					            clear = ast.Assign(variables, ast.Constant(None))
 | 
				
			||||||
            self.statements.append(clear)
 | 
					            self.statements.append(clear)
 | 
				
			||||||
        # Fix locations (line numbers/column offsets).
 | 
					        # Fix locations (line numbers/column offsets).
 | 
				
			||||||
        for stmt in self.statements:
 | 
					        for stmt in self.statements:
 | 
				
			||||||
| 
						 | 
					@ -955,26 +941,26 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
                ast.copy_location(node, assert_)
 | 
					                ast.copy_location(node, assert_)
 | 
				
			||||||
        return self.statements
 | 
					        return self.statements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def visit_NamedExpr(self, name: namedExpr) -> Tuple[namedExpr, str]:
 | 
					    def visit_NamedExpr(self, name: ast.NamedExpr) -> Tuple[ast.NamedExpr, str]:
 | 
				
			||||||
        # This method handles the 'walrus operator' repr of the target
 | 
					        # This method handles the 'walrus operator' repr of the target
 | 
				
			||||||
        # name if it's a local variable or _should_repr_global_name()
 | 
					        # name if it's a local variable or _should_repr_global_name()
 | 
				
			||||||
        # thinks it's acceptable.
 | 
					        # thinks it's acceptable.
 | 
				
			||||||
        locs = ast.Call(self.builtin("locals"), [], [])
 | 
					        locs = ast.Call(self.builtin("locals"), [], [])
 | 
				
			||||||
        target_id = name.target.id  # type: ignore[attr-defined]
 | 
					        target_id = name.target.id  # type: ignore[attr-defined]
 | 
				
			||||||
        inlocs = ast.Compare(astStr(target_id), [ast.In()], [locs])
 | 
					        inlocs = ast.Compare(ast.Constant(target_id), [ast.In()], [locs])
 | 
				
			||||||
        dorepr = self.helper("_should_repr_global_name", name)
 | 
					        dorepr = self.helper("_should_repr_global_name", name)
 | 
				
			||||||
        test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
 | 
					        test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
 | 
				
			||||||
        expr = ast.IfExp(test, self.display(name), astStr(target_id))
 | 
					        expr = ast.IfExp(test, self.display(name), ast.Constant(target_id))
 | 
				
			||||||
        return name, self.explanation_param(expr)
 | 
					        return name, self.explanation_param(expr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]:
 | 
					    def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]:
 | 
				
			||||||
        # Display the repr of the name if it's a local variable or
 | 
					        # Display the repr of the name if it's a local variable or
 | 
				
			||||||
        # _should_repr_global_name() thinks it's acceptable.
 | 
					        # _should_repr_global_name() thinks it's acceptable.
 | 
				
			||||||
        locs = ast.Call(self.builtin("locals"), [], [])
 | 
					        locs = ast.Call(self.builtin("locals"), [], [])
 | 
				
			||||||
        inlocs = ast.Compare(astStr(name.id), [ast.In()], [locs])
 | 
					        inlocs = ast.Compare(ast.Constant(name.id), [ast.In()], [locs])
 | 
				
			||||||
        dorepr = self.helper("_should_repr_global_name", name)
 | 
					        dorepr = self.helper("_should_repr_global_name", name)
 | 
				
			||||||
        test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
 | 
					        test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
 | 
				
			||||||
        expr = ast.IfExp(test, self.display(name), astStr(name.id))
 | 
					        expr = ast.IfExp(test, self.display(name), ast.Constant(name.id))
 | 
				
			||||||
        return name, self.explanation_param(expr)
 | 
					        return name, self.explanation_param(expr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]:
 | 
					    def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]:
 | 
				
			||||||
| 
						 | 
					@ -993,10 +979,10 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
                # cond is set in a prior loop iteration below
 | 
					                # cond is set in a prior loop iteration below
 | 
				
			||||||
                self.expl_stmts.append(ast.If(cond, fail_inner, []))  # noqa
 | 
					                self.expl_stmts.append(ast.If(cond, fail_inner, []))  # noqa
 | 
				
			||||||
                self.expl_stmts = fail_inner
 | 
					                self.expl_stmts = fail_inner
 | 
				
			||||||
                # Check if the left operand is a namedExpr and the value has already been visited
 | 
					                # Check if the left operand is a ast.NamedExpr and the value has already been visited
 | 
				
			||||||
                if (
 | 
					                if (
 | 
				
			||||||
                    isinstance(v, ast.Compare)
 | 
					                    isinstance(v, ast.Compare)
 | 
				
			||||||
                    and isinstance(v.left, namedExpr)
 | 
					                    and isinstance(v.left, ast.NamedExpr)
 | 
				
			||||||
                    and v.left.target.id
 | 
					                    and v.left.target.id
 | 
				
			||||||
                    in [
 | 
					                    in [
 | 
				
			||||||
                        ast_expr.id
 | 
					                        ast_expr.id
 | 
				
			||||||
| 
						 | 
					@ -1012,7 +998,7 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
            self.push_format_context()
 | 
					            self.push_format_context()
 | 
				
			||||||
            res, expl = self.visit(v)
 | 
					            res, expl = self.visit(v)
 | 
				
			||||||
            body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
 | 
					            body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
 | 
				
			||||||
            expl_format = self.pop_format_context(astStr(expl))
 | 
					            expl_format = self.pop_format_context(ast.Constant(expl))
 | 
				
			||||||
            call = ast.Call(app, [expl_format], [])
 | 
					            call = ast.Call(app, [expl_format], [])
 | 
				
			||||||
            self.expl_stmts.append(ast.Expr(call))
 | 
					            self.expl_stmts.append(ast.Expr(call))
 | 
				
			||||||
            if i < levels:
 | 
					            if i < levels:
 | 
				
			||||||
| 
						 | 
					@ -1024,7 +1010,7 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
                self.statements = body = inner
 | 
					                self.statements = body = inner
 | 
				
			||||||
        self.statements = save
 | 
					        self.statements = save
 | 
				
			||||||
        self.expl_stmts = fail_save
 | 
					        self.expl_stmts = fail_save
 | 
				
			||||||
        expl_template = self.helper("_format_boolop", expl_list, astNum(is_or))
 | 
					        expl_template = self.helper("_format_boolop", expl_list, ast.Constant(is_or))
 | 
				
			||||||
        expl = self.pop_format_context(expl_template)
 | 
					        expl = self.pop_format_context(expl_template)
 | 
				
			||||||
        return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
 | 
					        return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1098,7 +1084,7 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
            comp.left = self.variables_overwrite[
 | 
					            comp.left = self.variables_overwrite[
 | 
				
			||||||
                comp.left.id
 | 
					                comp.left.id
 | 
				
			||||||
            ]  # type:ignore[assignment]
 | 
					            ]  # type:ignore[assignment]
 | 
				
			||||||
        if isinstance(comp.left, namedExpr):
 | 
					        if isinstance(comp.left, ast.NamedExpr):
 | 
				
			||||||
            self.variables_overwrite[
 | 
					            self.variables_overwrite[
 | 
				
			||||||
                comp.left.target.id
 | 
					                comp.left.target.id
 | 
				
			||||||
            ] = comp.left  # type:ignore[assignment]
 | 
					            ] = comp.left  # type:ignore[assignment]
 | 
				
			||||||
| 
						 | 
					@ -1114,7 +1100,7 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
        results = [left_res]
 | 
					        results = [left_res]
 | 
				
			||||||
        for i, op, next_operand in it:
 | 
					        for i, op, next_operand in it:
 | 
				
			||||||
            if (
 | 
					            if (
 | 
				
			||||||
                isinstance(next_operand, namedExpr)
 | 
					                isinstance(next_operand, ast.NamedExpr)
 | 
				
			||||||
                and isinstance(left_res, ast.Name)
 | 
					                and isinstance(left_res, ast.Name)
 | 
				
			||||||
                and next_operand.target.id == left_res.id
 | 
					                and next_operand.target.id == left_res.id
 | 
				
			||||||
            ):
 | 
					            ):
 | 
				
			||||||
| 
						 | 
					@ -1127,9 +1113,9 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
				
			||||||
                next_expl = f"({next_expl})"
 | 
					                next_expl = f"({next_expl})"
 | 
				
			||||||
            results.append(next_res)
 | 
					            results.append(next_res)
 | 
				
			||||||
            sym = BINOP_MAP[op.__class__]
 | 
					            sym = BINOP_MAP[op.__class__]
 | 
				
			||||||
            syms.append(astStr(sym))
 | 
					            syms.append(ast.Constant(sym))
 | 
				
			||||||
            expl = f"{left_expl} {sym} {next_expl}"
 | 
					            expl = f"{left_expl} {sym} {next_expl}"
 | 
				
			||||||
            expls.append(astStr(expl))
 | 
					            expls.append(ast.Constant(expl))
 | 
				
			||||||
            res_expr = ast.Compare(left_res, [op], [next_res])
 | 
					            res_expr = ast.Compare(left_res, [op], [next_res])
 | 
				
			||||||
            self.statements.append(ast.Assign([store_names[i]], res_expr))
 | 
					            self.statements.append(ast.Assign([store_names[i]], res_expr))
 | 
				
			||||||
            left_res, left_expl = next_res, next_expl
 | 
					            left_res, left_expl = next_res, next_expl
 | 
				
			||||||
| 
						 | 
					@ -1173,7 +1159,7 @@ def try_makedirs(cache_dir: Path) -> bool:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_cache_dir(file_path: Path) -> Path:
 | 
					def get_cache_dir(file_path: Path) -> Path:
 | 
				
			||||||
    """Return the cache directory to write .pyc files for the given .py file path."""
 | 
					    """Return the cache directory to write .pyc files for the given .py file path."""
 | 
				
			||||||
    if sys.version_info >= (3, 8) and sys.pycache_prefix:
 | 
					    if sys.pycache_prefix:
 | 
				
			||||||
        # given:
 | 
					        # given:
 | 
				
			||||||
        #   prefix = '/tmp/pycs'
 | 
					        #   prefix = '/tmp/pycs'
 | 
				
			||||||
        #   path = '/home/user/proj/test_app.py'
 | 
					        #   path = '/home/user/proj/test_app.py'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ import json
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
| 
						 | 
					@ -18,7 +19,6 @@ from .pathlib import rm_rf
 | 
				
			||||||
from .reports import CollectReport
 | 
					from .reports import CollectReport
 | 
				
			||||||
from _pytest import nodes
 | 
					from _pytest import nodes
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.config import ExitCode
 | 
					from _pytest.config import ExitCode
 | 
				
			||||||
from _pytest.config import hookimpl
 | 
					from _pytest.config import hookimpl
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,11 +11,14 @@ from types import TracebackType
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import AnyStr
 | 
					from typing import AnyStr
 | 
				
			||||||
from typing import BinaryIO
 | 
					from typing import BinaryIO
 | 
				
			||||||
 | 
					from typing import Final
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import Generic
 | 
					from typing import Generic
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
from typing import Iterator
 | 
					from typing import Iterator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					from typing import Literal
 | 
				
			||||||
from typing import NamedTuple
 | 
					from typing import NamedTuple
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
from typing import TextIO
 | 
					from typing import TextIO
 | 
				
			||||||
| 
						 | 
					@ -24,7 +27,6 @@ from typing import Type
 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					from typing import TYPE_CHECKING
 | 
				
			||||||
from typing import Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.config import hookimpl
 | 
					from _pytest.config import hookimpl
 | 
				
			||||||
from _pytest.config.argparsing import Parser
 | 
					from _pytest.config.argparsing import Parser
 | 
				
			||||||
| 
						 | 
					@ -35,11 +37,7 @@ from _pytest.nodes import Collector
 | 
				
			||||||
from _pytest.nodes import File
 | 
					from _pytest.nodes import File
 | 
				
			||||||
from _pytest.nodes import Item
 | 
					from _pytest.nodes import Item
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
 | 
				
			||||||
    from typing_extensions import Final
 | 
					 | 
				
			||||||
    from typing_extensions import Literal
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_addoption(parser: Parser) -> None:
 | 
					def pytest_addoption(parser: Parser) -> None:
 | 
				
			||||||
| 
						 | 
					@ -687,7 +685,7 @@ class MultiCapture(Generic[AnyStr]):
 | 
				
			||||||
        return CaptureResult(out, err)  # type: ignore[arg-type]
 | 
					        return CaptureResult(out, err)  # type: ignore[arg-type]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _get_multicapture(method: "_CaptureMethod") -> MultiCapture[str]:
 | 
					def _get_multicapture(method: _CaptureMethod) -> MultiCapture[str]:
 | 
				
			||||||
    if method == "fd":
 | 
					    if method == "fd":
 | 
				
			||||||
        return MultiCapture(in_=FDCapture(0), out=FDCapture(1), err=FDCapture(2))
 | 
					        return MultiCapture(in_=FDCapture(0), out=FDCapture(1), err=FDCapture(2))
 | 
				
			||||||
    elif method == "sys":
 | 
					    elif method == "sys":
 | 
				
			||||||
| 
						 | 
					@ -723,7 +721,7 @@ class CaptureManager:
 | 
				
			||||||
      needed to ensure the fixtures take precedence over the global capture.
 | 
					      needed to ensure the fixtures take precedence over the global capture.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, method: "_CaptureMethod") -> None:
 | 
					    def __init__(self, method: _CaptureMethod) -> None:
 | 
				
			||||||
        self._method: Final = method
 | 
					        self._method: Final = method
 | 
				
			||||||
        self._global_capturing: Optional[MultiCapture[str]] = None
 | 
					        self._global_capturing: Optional[MultiCapture[str]] = None
 | 
				
			||||||
        self._capture_fixture: Optional[CaptureFixture[Any]] = None
 | 
					        self._capture_fixture: Optional[CaptureFixture[Any]] = None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,26 +12,12 @@ from inspect import signature
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import Generic
 | 
					from typing import Final
 | 
				
			||||||
from typing import NoReturn
 | 
					from typing import NoReturn
 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					 | 
				
			||||||
from typing import TypeVar
 | 
					from typing import TypeVar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import py
 | 
					import py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# fmt: off
 | 
					 | 
				
			||||||
# Workaround for https://github.com/sphinx-doc/sphinx/issues/10351.
 | 
					 | 
				
			||||||
# If `overload` is imported from `compat` instead of from `typing`,
 | 
					 | 
				
			||||||
# Sphinx doesn't recognize it as `overload` and the API docs for
 | 
					 | 
				
			||||||
# overloaded functions look good again. But type checkers handle
 | 
					 | 
				
			||||||
# it fine.
 | 
					 | 
				
			||||||
# fmt: on
 | 
					 | 
				
			||||||
if True:
 | 
					 | 
				
			||||||
    from typing import overload as overload
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if TYPE_CHECKING:
 | 
					 | 
				
			||||||
    from typing_extensions import Final
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
_T = TypeVar("_T")
 | 
					_T = TypeVar("_T")
 | 
				
			||||||
_S = TypeVar("_S")
 | 
					_S = TypeVar("_S")
 | 
				
			||||||
| 
						 | 
					@ -58,17 +44,6 @@ class NotSetType(enum.Enum):
 | 
				
			||||||
NOTSET: Final = NotSetType.token  # noqa: E305
 | 
					NOTSET: Final = NotSetType.token  # noqa: E305
 | 
				
			||||||
# fmt: on
 | 
					# fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if sys.version_info >= (3, 8):
 | 
					 | 
				
			||||||
    import importlib.metadata
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    importlib_metadata = importlib.metadata
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
    import importlib_metadata as importlib_metadata  # noqa: F401
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _format_args(func: Callable[..., Any]) -> str:
 | 
					 | 
				
			||||||
    return str(signature(func))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def is_generator(func: object) -> bool:
 | 
					def is_generator(func: object) -> bool:
 | 
				
			||||||
    genfunc = inspect.isgeneratorfunction(func)
 | 
					    genfunc = inspect.isgeneratorfunction(func)
 | 
				
			||||||
| 
						 | 
					@ -338,47 +313,6 @@ def safe_isclass(obj: object) -> bool:
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					 | 
				
			||||||
    if sys.version_info >= (3, 8):
 | 
					 | 
				
			||||||
        from typing import final as final
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        from typing_extensions import final as final
 | 
					 | 
				
			||||||
elif sys.version_info >= (3, 8):
 | 
					 | 
				
			||||||
    from typing import final as final
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def final(f):
 | 
					 | 
				
			||||||
        return f
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if sys.version_info >= (3, 8):
 | 
					 | 
				
			||||||
    from functools import cached_property as cached_property
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    class cached_property(Generic[_S, _T]):
 | 
					 | 
				
			||||||
        __slots__ = ("func", "__doc__")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def __init__(self, func: Callable[[_S], _T]) -> None:
 | 
					 | 
				
			||||||
            self.func = func
 | 
					 | 
				
			||||||
            self.__doc__ = func.__doc__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @overload
 | 
					 | 
				
			||||||
        def __get__(
 | 
					 | 
				
			||||||
            self, instance: None, owner: type[_S] | None = ...
 | 
					 | 
				
			||||||
        ) -> cached_property[_S, _T]:
 | 
					 | 
				
			||||||
            ...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @overload
 | 
					 | 
				
			||||||
        def __get__(self, instance: _S, owner: type[_S] | None = ...) -> _T:
 | 
					 | 
				
			||||||
            ...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def __get__(self, instance, owner=None):
 | 
					 | 
				
			||||||
            if instance is None:
 | 
					 | 
				
			||||||
                return self
 | 
					 | 
				
			||||||
            value = instance.__dict__[self.func.__name__] = self.func(instance)
 | 
					 | 
				
			||||||
            return value
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_user_id() -> int | None:
 | 
					def get_user_id() -> int | None:
 | 
				
			||||||
    """Return the current user id, or None if we cannot get it reliably on the current platform."""
 | 
					    """Return the current user id, or None if we cannot get it reliably on the current platform."""
 | 
				
			||||||
    # win32 does not have a getuid() function.
 | 
					    # win32 does not have a getuid() function.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import copy
 | 
				
			||||||
import dataclasses
 | 
					import dataclasses
 | 
				
			||||||
import enum
 | 
					import enum
 | 
				
			||||||
import glob
 | 
					import glob
 | 
				
			||||||
 | 
					import importlib.metadata
 | 
				
			||||||
import inspect
 | 
					import inspect
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
| 
						 | 
					@ -21,6 +22,7 @@ from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import IO
 | 
					from typing import IO
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
| 
						 | 
					@ -48,8 +50,6 @@ from .findpaths import determine_setup
 | 
				
			||||||
from _pytest._code import ExceptionInfo
 | 
					from _pytest._code import ExceptionInfo
 | 
				
			||||||
from _pytest._code import filter_traceback
 | 
					from _pytest._code import filter_traceback
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import importlib_metadata  # type: ignore[attr-defined]
 | 
					 | 
				
			||||||
from _pytest.outcomes import fail
 | 
					from _pytest.outcomes import fail
 | 
				
			||||||
from _pytest.outcomes import Skipped
 | 
					from _pytest.outcomes import Skipped
 | 
				
			||||||
from _pytest.pathlib import absolutepath
 | 
					from _pytest.pathlib import absolutepath
 | 
				
			||||||
| 
						 | 
					@ -257,7 +257,8 @@ default_plugins = essential_plugins + (
 | 
				
			||||||
    "logging",
 | 
					    "logging",
 | 
				
			||||||
    "reports",
 | 
					    "reports",
 | 
				
			||||||
    "python_path",
 | 
					    "python_path",
 | 
				
			||||||
    *(["unraisableexception", "threadexception"] if sys.version_info >= (3, 8) else []),
 | 
					    "unraisableexception",
 | 
				
			||||||
 | 
					    "threadexception",
 | 
				
			||||||
    "faulthandler",
 | 
					    "faulthandler",
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1216,7 +1217,7 @@ class Config:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        package_files = (
 | 
					        package_files = (
 | 
				
			||||||
            str(file)
 | 
					            str(file)
 | 
				
			||||||
            for dist in importlib_metadata.distributions()
 | 
					            for dist in importlib.metadata.distributions()
 | 
				
			||||||
            if any(ep.group == "pytest11" for ep in dist.entry_points)
 | 
					            if any(ep.group == "pytest11" for ep in dist.entry_points)
 | 
				
			||||||
            for file in dist.files or []
 | 
					            for file in dist.files or []
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Mapping
 | 
					from typing import Mapping
 | 
				
			||||||
from typing import NoReturn
 | 
					from typing import NoReturn
 | 
				
			||||||
| 
						 | 
					@ -17,7 +18,6 @@ from typing import TYPE_CHECKING
 | 
				
			||||||
from typing import Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import _pytest._io
 | 
					import _pytest._io
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.config.exceptions import UsageError
 | 
					from _pytest.config.exceptions import UsageError
 | 
				
			||||||
from _pytest.deprecated import ARGUMENT_PERCENT_DEFAULT
 | 
					from _pytest.deprecated import ARGUMENT_PERCENT_DEFAULT
 | 
				
			||||||
from _pytest.deprecated import ARGUMENT_TYPE_STR
 | 
					from _pytest.deprecated import ARGUMENT_TYPE_STR
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
from _pytest.compat import final
 | 
					from typing import final
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@final
 | 
					@final
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import Generic
 | 
					from typing import Generic
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
| 
						 | 
					@ -21,6 +22,7 @@ from typing import List
 | 
				
			||||||
from typing import MutableMapping
 | 
					from typing import MutableMapping
 | 
				
			||||||
from typing import NoReturn
 | 
					from typing import NoReturn
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
 | 
					from typing import overload
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Sequence
 | 
				
			||||||
from typing import Set
 | 
					from typing import Set
 | 
				
			||||||
from typing import Tuple
 | 
					from typing import Tuple
 | 
				
			||||||
| 
						 | 
					@ -35,10 +37,8 @@ from _pytest._code import getfslineno
 | 
				
			||||||
from _pytest._code.code import FormattedExcinfo
 | 
					from _pytest._code.code import FormattedExcinfo
 | 
				
			||||||
from _pytest._code.code import TerminalRepr
 | 
					from _pytest._code.code import TerminalRepr
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest.compat import _format_args
 | 
					 | 
				
			||||||
from _pytest.compat import _PytestWrapper
 | 
					from _pytest.compat import _PytestWrapper
 | 
				
			||||||
from _pytest.compat import assert_never
 | 
					from _pytest.compat import assert_never
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import get_real_func
 | 
					from _pytest.compat import get_real_func
 | 
				
			||||||
from _pytest.compat import get_real_method
 | 
					from _pytest.compat import get_real_method
 | 
				
			||||||
from _pytest.compat import getfuncargnames
 | 
					from _pytest.compat import getfuncargnames
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,6 @@ from _pytest.compat import getlocation
 | 
				
			||||||
from _pytest.compat import is_generator
 | 
					from _pytest.compat import is_generator
 | 
				
			||||||
from _pytest.compat import NOTSET
 | 
					from _pytest.compat import NOTSET
 | 
				
			||||||
from _pytest.compat import NotSetType
 | 
					from _pytest.compat import NotSetType
 | 
				
			||||||
from _pytest.compat import overload
 | 
					 | 
				
			||||||
from _pytest.compat import safe_getattr
 | 
					from _pytest.compat import safe_getattr
 | 
				
			||||||
from _pytest.config import _PluggyPlugin
 | 
					from _pytest.config import _PluggyPlugin
 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
| 
						 | 
					@ -729,8 +728,10 @@ class FixtureRequest:
 | 
				
			||||||
                p = bestrelpath(session.path, fs)
 | 
					                p = bestrelpath(session.path, fs)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                p = fs
 | 
					                p = fs
 | 
				
			||||||
            args = _format_args(factory)
 | 
					            lines.append(
 | 
				
			||||||
            lines.append("%s:%d:  def %s%s" % (p, lineno + 1, factory.__name__, args))
 | 
					                "%s:%d:  def %s%s"
 | 
				
			||||||
 | 
					                % (p, lineno + 1, factory.__name__, inspect.signature(factory))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
        return lines
 | 
					        return lines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __repr__(self) -> str:
 | 
					    def __repr__(self) -> str:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,8 @@ import dataclasses
 | 
				
			||||||
import shlex
 | 
					import shlex
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					from typing import Final
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					from typing import TYPE_CHECKING
 | 
				
			||||||
| 
						 | 
					@ -11,7 +13,6 @@ from typing import Union
 | 
				
			||||||
from iniconfig import SectionWrapper
 | 
					from iniconfig import SectionWrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest.cacheprovider import Cache
 | 
					from _pytest.cacheprovider import Cache
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import LEGACY_PATH
 | 
					from _pytest.compat import LEGACY_PATH
 | 
				
			||||||
from _pytest.compat import legacy_path
 | 
					from _pytest.compat import legacy_path
 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
| 
						 | 
					@ -32,8 +33,6 @@ from _pytest.terminal import TerminalReporter
 | 
				
			||||||
from _pytest.tmpdir import TempPathFactory
 | 
					from _pytest.tmpdir import TempPathFactory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
    from typing_extensions import Final
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    import pexpect
 | 
					    import pexpect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ from logging import LogRecord
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from typing import AbstractSet
 | 
					from typing import AbstractSet
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Mapping
 | 
					from typing import Mapping
 | 
				
			||||||
| 
						 | 
					@ -25,7 +26,6 @@ from typing import Union
 | 
				
			||||||
from _pytest import nodes
 | 
					from _pytest import nodes
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest.capture import CaptureManager
 | 
					from _pytest.capture import CaptureManager
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.config import _strtobool
 | 
					from _pytest.config import _strtobool
 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.config import create_terminal_writer
 | 
					from _pytest.config import create_terminal_writer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,10 +9,12 @@ import sys
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import FrozenSet
 | 
					from typing import FrozenSet
 | 
				
			||||||
from typing import Iterator
 | 
					from typing import Iterator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
 | 
					from typing import overload
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Sequence
 | 
				
			||||||
from typing import Set
 | 
					from typing import Set
 | 
				
			||||||
from typing import Tuple
 | 
					from typing import Tuple
 | 
				
			||||||
| 
						 | 
					@ -22,8 +24,6 @@ from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import _pytest._code
 | 
					import _pytest._code
 | 
				
			||||||
from _pytest import nodes
 | 
					from _pytest import nodes
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import overload
 | 
					 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.config import directory_arg
 | 
					from _pytest.config import directory_arg
 | 
				
			||||||
from _pytest.config import ExitCode
 | 
					from _pytest.config import ExitCode
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,6 @@ import ast
 | 
				
			||||||
import dataclasses
 | 
					import dataclasses
 | 
				
			||||||
import enum
 | 
					import enum
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
import types
 | 
					import types
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import Iterator
 | 
					from typing import Iterator
 | 
				
			||||||
| 
						 | 
					@ -27,12 +26,6 @@ from typing import NoReturn
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Sequence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if sys.version_info >= (3, 8):
 | 
					 | 
				
			||||||
    astNameConstant = ast.Constant
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
    astNameConstant = ast.NameConstant
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__all__ = [
 | 
					__all__ = [
 | 
				
			||||||
    "Expression",
 | 
					    "Expression",
 | 
				
			||||||
    "ParseError",
 | 
					    "ParseError",
 | 
				
			||||||
| 
						 | 
					@ -138,7 +131,7 @@ IDENT_PREFIX = "$"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def expression(s: Scanner) -> ast.Expression:
 | 
					def expression(s: Scanner) -> ast.Expression:
 | 
				
			||||||
    if s.accept(TokenType.EOF):
 | 
					    if s.accept(TokenType.EOF):
 | 
				
			||||||
        ret: ast.expr = astNameConstant(False)
 | 
					        ret: ast.expr = ast.Constant(False)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        ret = expr(s)
 | 
					        ret = expr(s)
 | 
				
			||||||
        s.accept(TokenType.EOF, reject=True)
 | 
					        s.accept(TokenType.EOF, reject=True)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import warnings
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import Collection
 | 
					from typing import Collection
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
from typing import Iterator
 | 
					from typing import Iterator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
| 
						 | 
					@ -23,7 +24,6 @@ from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .._code import getfslineno
 | 
					from .._code import getfslineno
 | 
				
			||||||
from ..compat import ascii_escaped
 | 
					from ..compat import ascii_escaped
 | 
				
			||||||
from ..compat import final
 | 
					 | 
				
			||||||
from ..compat import NOTSET
 | 
					from ..compat import NOTSET
 | 
				
			||||||
from ..compat import NotSetType
 | 
					from ..compat import NotSetType
 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import sys
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from contextlib import contextmanager
 | 
					from contextlib import contextmanager
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Mapping
 | 
					from typing import Mapping
 | 
				
			||||||
| 
						 | 
					@ -15,7 +16,6 @@ from typing import Tuple
 | 
				
			||||||
from typing import TypeVar
 | 
					from typing import TypeVar
 | 
				
			||||||
from typing import Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.fixtures import fixture
 | 
					from _pytest.fixtures import fixture
 | 
				
			||||||
from _pytest.warning_types import PytestWarning
 | 
					from _pytest.warning_types import PytestWarning
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
 | 
					from functools import cached_property
 | 
				
			||||||
from inspect import signature
 | 
					from inspect import signature
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
| 
						 | 
					@ -23,7 +24,6 @@ from _pytest._code import getfslineno
 | 
				
			||||||
from _pytest._code.code import ExceptionInfo
 | 
					from _pytest._code.code import ExceptionInfo
 | 
				
			||||||
from _pytest._code.code import TerminalRepr
 | 
					from _pytest._code.code import TerminalRepr
 | 
				
			||||||
from _pytest._code.code import Traceback
 | 
					from _pytest._code.code import Traceback
 | 
				
			||||||
from _pytest.compat import cached_property
 | 
					 | 
				
			||||||
from _pytest.compat import LEGACY_PATH
 | 
					from _pytest.compat import LEGACY_PATH
 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.config import ConftestImportFailure
 | 
					from _pytest.config import ConftestImportFailure
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,23 +7,12 @@ from typing import Callable
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import NoReturn
 | 
					from typing import NoReturn
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
 | 
					from typing import Protocol
 | 
				
			||||||
from typing import Type
 | 
					from typing import Type
 | 
				
			||||||
from typing import TypeVar
 | 
					from typing import TypeVar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest.deprecated import KEYWORD_MSG_ARG
 | 
					from _pytest.deprecated import KEYWORD_MSG_ARG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TYPE_CHECKING = False  # Avoid circular import through compat.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if TYPE_CHECKING:
 | 
					 | 
				
			||||||
    from typing_extensions import Protocol
 | 
					 | 
				
			||||||
else:
 | 
					 | 
				
			||||||
    # typing.Protocol is only available starting from Python 3.8. It is also
 | 
					 | 
				
			||||||
    # available from typing_extensions, but we don't want a runtime dependency
 | 
					 | 
				
			||||||
    # on that. So use a dummy runtime implementation.
 | 
					 | 
				
			||||||
    from typing import Generic
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Protocol = Generic
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OutcomeException(BaseException):
 | 
					class OutcomeException(BaseException):
 | 
				
			||||||
    """OutcomeException and its subclass instances indicate and contain info
 | 
					    """OutcomeException and its subclass instances indicate and contain info
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,10 +20,13 @@ from pathlib import Path
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import Final
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import IO
 | 
					from typing import IO
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
 | 
					from typing import Literal
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
from typing import overload
 | 
					from typing import overload
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Sequence
 | 
				
			||||||
| 
						 | 
					@ -40,7 +43,6 @@ from iniconfig import SectionWrapper
 | 
				
			||||||
from _pytest import timing
 | 
					from _pytest import timing
 | 
				
			||||||
from _pytest._code import Source
 | 
					from _pytest._code import Source
 | 
				
			||||||
from _pytest.capture import _get_multicapture
 | 
					from _pytest.capture import _get_multicapture
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import NOTSET
 | 
					from _pytest.compat import NOTSET
 | 
				
			||||||
from _pytest.compat import NotSetType
 | 
					from _pytest.compat import NotSetType
 | 
				
			||||||
from _pytest.config import _PluggyPlugin
 | 
					from _pytest.config import _PluggyPlugin
 | 
				
			||||||
| 
						 | 
					@ -68,11 +70,7 @@ from _pytest.reports import TestReport
 | 
				
			||||||
from _pytest.tmpdir import TempPathFactory
 | 
					from _pytest.tmpdir import TempPathFactory
 | 
				
			||||||
from _pytest.warning_types import PytestWarning
 | 
					from _pytest.warning_types import PytestWarning
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
if TYPE_CHECKING:
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
    from typing_extensions import Final
 | 
					 | 
				
			||||||
    from typing_extensions import Literal
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    import pexpect
 | 
					    import pexpect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ from pathlib import Path
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
from typing import Iterator
 | 
					from typing import Iterator
 | 
				
			||||||
| 
						 | 
					@ -40,7 +41,6 @@ from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest._io.saferepr import saferepr
 | 
					from _pytest._io.saferepr import saferepr
 | 
				
			||||||
from _pytest.compat import ascii_escaped
 | 
					from _pytest.compat import ascii_escaped
 | 
				
			||||||
from _pytest.compat import assert_never
 | 
					from _pytest.compat import assert_never
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import get_default_arg_names
 | 
					from _pytest.compat import get_default_arg_names
 | 
				
			||||||
from _pytest.compat import get_real_func
 | 
					from _pytest.compat import get_real_func
 | 
				
			||||||
from _pytest.compat import getimfunc
 | 
					from _pytest.compat import getimfunc
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,9 +9,11 @@ from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import ContextManager
 | 
					from typing import ContextManager
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Mapping
 | 
					from typing import Mapping
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
 | 
					from typing import overload
 | 
				
			||||||
from typing import Pattern
 | 
					from typing import Pattern
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Sequence
 | 
				
			||||||
from typing import Tuple
 | 
					from typing import Tuple
 | 
				
			||||||
| 
						 | 
					@ -20,17 +22,14 @@ from typing import TYPE_CHECKING
 | 
				
			||||||
from typing import TypeVar
 | 
					from typing import TypeVar
 | 
				
			||||||
from typing import Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import _pytest._code
 | 
				
			||||||
 | 
					from _pytest.compat import STRING_TYPES
 | 
				
			||||||
 | 
					from _pytest.outcomes import fail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
    from numpy import ndarray
 | 
					    from numpy import ndarray
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import _pytest._code
 | 
					 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import STRING_TYPES
 | 
					 | 
				
			||||||
from _pytest.compat import overload
 | 
					 | 
				
			||||||
from _pytest.outcomes import fail
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _non_numeric_type_error(value, at: Optional[str]) -> TypeError:
 | 
					def _non_numeric_type_error(value, at: Optional[str]) -> TypeError:
 | 
				
			||||||
    at_str = f" at {at}" if at else ""
 | 
					    at_str = f" at {at}" if at else ""
 | 
				
			||||||
    return TypeError(
 | 
					    return TypeError(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,18 +5,18 @@ from pprint import pformat
 | 
				
			||||||
from types import TracebackType
 | 
					from types import TracebackType
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import Iterator
 | 
					from typing import Iterator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
 | 
					from typing import overload
 | 
				
			||||||
from typing import Pattern
 | 
					from typing import Pattern
 | 
				
			||||||
from typing import Tuple
 | 
					from typing import Tuple
 | 
				
			||||||
from typing import Type
 | 
					from typing import Type
 | 
				
			||||||
from typing import TypeVar
 | 
					from typing import TypeVar
 | 
				
			||||||
from typing import Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.compat import overload
 | 
					 | 
				
			||||||
from _pytest.deprecated import check_ispytest
 | 
					from _pytest.deprecated import check_ispytest
 | 
				
			||||||
from _pytest.deprecated import WARNS_NONE_ARG
 | 
					from _pytest.deprecated import WARNS_NONE_ARG
 | 
				
			||||||
from _pytest.fixtures import fixture
 | 
					from _pytest.fixtures import fixture
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ from pprint import pprint
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Iterable
 | 
					from typing import Iterable
 | 
				
			||||||
from typing import Iterator
 | 
					from typing import Iterator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
| 
						 | 
					@ -29,7 +30,6 @@ from _pytest._code.code import ReprLocals
 | 
				
			||||||
from _pytest._code.code import ReprTraceback
 | 
					from _pytest._code.code import ReprTraceback
 | 
				
			||||||
from _pytest._code.code import TerminalRepr
 | 
					from _pytest._code.code import TerminalRepr
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.nodes import Collector
 | 
					from _pytest.nodes import Collector
 | 
				
			||||||
from _pytest.nodes import Item
 | 
					from _pytest.nodes import Item
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ import sys
 | 
				
			||||||
from typing import Callable
 | 
					from typing import Callable
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generic
 | 
					from typing import Generic
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
| 
						 | 
					@ -23,7 +24,6 @@ from _pytest import timing
 | 
				
			||||||
from _pytest._code.code import ExceptionChainRepr
 | 
					from _pytest._code.code import ExceptionChainRepr
 | 
				
			||||||
from _pytest._code.code import ExceptionInfo
 | 
					from _pytest._code.code import ExceptionInfo
 | 
				
			||||||
from _pytest._code.code import TerminalRepr
 | 
					from _pytest._code.code import TerminalRepr
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.config.argparsing import Parser
 | 
					from _pytest.config.argparsing import Parser
 | 
				
			||||||
from _pytest.deprecated import check_ispytest
 | 
					from _pytest.deprecated import check_ispytest
 | 
				
			||||||
from _pytest.nodes import Collector
 | 
					from _pytest.nodes import Collector
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ from typing import Callable
 | 
				
			||||||
from typing import cast
 | 
					from typing import cast
 | 
				
			||||||
from typing import ClassVar
 | 
					from typing import ClassVar
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from typing import Mapping
 | 
					from typing import Mapping
 | 
				
			||||||
| 
						 | 
					@ -40,7 +41,6 @@ from _pytest._code.code import ExceptionRepr
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest._io.wcwidth import wcswidth
 | 
					from _pytest._io.wcwidth import wcswidth
 | 
				
			||||||
from _pytest.assertion.util import running_on_ci
 | 
					from _pytest.assertion.util import running_on_ci
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
from _pytest.config import _PluggyPlugin
 | 
					from _pytest.config import _PluggyPlugin
 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.config import ExitCode
 | 
					from _pytest.config import ExitCode
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,38 +7,32 @@ from pathlib import Path
 | 
				
			||||||
from shutil import rmtree
 | 
					from shutil import rmtree
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
from typing import Dict
 | 
					from typing import Dict
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generator
 | 
					from typing import Generator
 | 
				
			||||||
 | 
					from typing import Literal
 | 
				
			||||||
from typing import Optional
 | 
					from typing import Optional
 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					 | 
				
			||||||
from typing import Union
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest.nodes import Item
 | 
					from .pathlib import cleanup_dead_symlinks
 | 
				
			||||||
from _pytest.reports import CollectReport
 | 
					 | 
				
			||||||
from _pytest.stash import StashKey
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if TYPE_CHECKING:
 | 
					 | 
				
			||||||
    from typing_extensions import Literal
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    RetentionType = Literal["all", "failed", "none"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from _pytest.config.argparsing import Parser
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from .pathlib import LOCK_TIMEOUT
 | 
					from .pathlib import LOCK_TIMEOUT
 | 
				
			||||||
from .pathlib import make_numbered_dir
 | 
					from .pathlib import make_numbered_dir
 | 
				
			||||||
from .pathlib import make_numbered_dir_with_cleanup
 | 
					from .pathlib import make_numbered_dir_with_cleanup
 | 
				
			||||||
from .pathlib import rm_rf
 | 
					from .pathlib import rm_rf
 | 
				
			||||||
from .pathlib import cleanup_dead_symlinks
 | 
					from _pytest.compat import get_user_id
 | 
				
			||||||
from _pytest.compat import final, get_user_id
 | 
					 | 
				
			||||||
from _pytest.config import Config
 | 
					from _pytest.config import Config
 | 
				
			||||||
from _pytest.config import ExitCode
 | 
					from _pytest.config import ExitCode
 | 
				
			||||||
from _pytest.config import hookimpl
 | 
					from _pytest.config import hookimpl
 | 
				
			||||||
 | 
					from _pytest.config.argparsing import Parser
 | 
				
			||||||
from _pytest.deprecated import check_ispytest
 | 
					from _pytest.deprecated import check_ispytest
 | 
				
			||||||
from _pytest.fixtures import fixture
 | 
					from _pytest.fixtures import fixture
 | 
				
			||||||
from _pytest.fixtures import FixtureRequest
 | 
					from _pytest.fixtures import FixtureRequest
 | 
				
			||||||
from _pytest.monkeypatch import MonkeyPatch
 | 
					from _pytest.monkeypatch import MonkeyPatch
 | 
				
			||||||
 | 
					from _pytest.nodes import Item
 | 
				
			||||||
 | 
					from _pytest.reports import CollectReport
 | 
				
			||||||
 | 
					from _pytest.stash import StashKey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tmppath_result_key = StashKey[Dict[str, bool]]()
 | 
					tmppath_result_key = StashKey[Dict[str, bool]]()
 | 
				
			||||||
 | 
					RetentionType = Literal["all", "failed", "none"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@final
 | 
					@final
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,12 +3,11 @@ import inspect
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from types import FunctionType
 | 
					from types import FunctionType
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
 | 
					from typing import final
 | 
				
			||||||
from typing import Generic
 | 
					from typing import Generic
 | 
				
			||||||
from typing import Type
 | 
					from typing import Type
 | 
				
			||||||
from typing import TypeVar
 | 
					from typing import TypeVar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from _pytest.compat import final
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PytestWarning(UserWarning):
 | 
					class PytestWarning(UserWarning):
 | 
				
			||||||
    """Base class for all warnings emitted by pytest."""
 | 
					    """Base class for all warnings emitted by pytest."""
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
import dataclasses
 | 
					import dataclasses
 | 
				
			||||||
 | 
					import importlib.metadata
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import types
 | 
					import types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from _pytest.compat import importlib_metadata
 | 
					 | 
				
			||||||
from _pytest.config import ExitCode
 | 
					from _pytest.config import ExitCode
 | 
				
			||||||
from _pytest.pathlib import symlink_or_skip
 | 
					from _pytest.pathlib import symlink_or_skip
 | 
				
			||||||
from _pytest.pytester import Pytester
 | 
					from _pytest.pytester import Pytester
 | 
				
			||||||
| 
						 | 
					@ -139,7 +139,7 @@ class TestGeneralUsage:
 | 
				
			||||||
        def my_dists():
 | 
					        def my_dists():
 | 
				
			||||||
            return (DummyDist(entry_points),)
 | 
					            return (DummyDist(entry_points),)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        monkeypatch.setattr(importlib_metadata, "distributions", my_dists)
 | 
					        monkeypatch.setattr(importlib.metadata, "distributions", my_dists)
 | 
				
			||||||
        params = ("-p", "mycov") if load_cov_early else ()
 | 
					        params = ("-p", "mycov") if load_cov_early else ()
 | 
				
			||||||
        pytester.runpytest_inprocess(*params)
 | 
					        pytester.runpytest_inprocess(*params)
 | 
				
			||||||
        if load_cov_early:
 | 
					        if load_cov_early:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -439,14 +439,9 @@ comment 4
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
    for line in range(2, 6):
 | 
					    for line in range(2, 6):
 | 
				
			||||||
        assert str(getstatement(line, source)) == "    x = 1"
 | 
					        assert str(getstatement(line, source)) == "    x = 1"
 | 
				
			||||||
    if sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"):
 | 
					    for line in range(6, 8):
 | 
				
			||||||
        tqs_start = 8
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        tqs_start = 10
 | 
					 | 
				
			||||||
        assert str(getstatement(10, source)) == '"""'
 | 
					 | 
				
			||||||
    for line in range(6, tqs_start):
 | 
					 | 
				
			||||||
        assert str(getstatement(line, source)) == "    assert False"
 | 
					        assert str(getstatement(line, source)) == "    assert False"
 | 
				
			||||||
    for line in range(tqs_start, 10):
 | 
					    for line in range(8, 10):
 | 
				
			||||||
        assert str(getstatement(line, source)) == '"""\ncomment 4\n"""'
 | 
					        assert str(getstatement(line, source)) == '"""\ncomment 4\n"""'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,6 @@ from hypothesis import strategies
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from _pytest import fixtures
 | 
					from _pytest import fixtures
 | 
				
			||||||
from _pytest import python
 | 
					from _pytest import python
 | 
				
			||||||
from _pytest.compat import _format_args
 | 
					 | 
				
			||||||
from _pytest.compat import getfuncargnames
 | 
					from _pytest.compat import getfuncargnames
 | 
				
			||||||
from _pytest.compat import NOTSET
 | 
					from _pytest.compat import NOTSET
 | 
				
			||||||
from _pytest.outcomes import fail
 | 
					from _pytest.outcomes import fail
 | 
				
			||||||
| 
						 | 
					@ -1036,27 +1035,6 @@ class TestMetafunc:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_format_args(self) -> None:
 | 
					 | 
				
			||||||
        def function1():
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert _format_args(function1) == "()"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def function2(arg1):
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert _format_args(function2) == "(arg1)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def function3(arg1, arg2="qwe"):
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert _format_args(function3) == "(arg1, arg2='qwe')"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def function4(arg1, *args, **kwargs):
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert _format_args(function4) == "(arg1, *args, **kwargs)"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestMetafuncFunctional:
 | 
					class TestMetafuncFunctional:
 | 
				
			||||||
    def test_attributes(self, pytester: Pytester) -> None:
 | 
					    def test_attributes(self, pytester: Pytester) -> None:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -199,8 +199,8 @@ class TestImportHookInstallation:
 | 
				
			||||||
                return check
 | 
					                return check
 | 
				
			||||||
            """,
 | 
					            """,
 | 
				
			||||||
            "mainwrapper.py": """\
 | 
					            "mainwrapper.py": """\
 | 
				
			||||||
 | 
					            import importlib.metadata
 | 
				
			||||||
            import pytest
 | 
					            import pytest
 | 
				
			||||||
            from _pytest.compat import importlib_metadata
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            class DummyEntryPoint(object):
 | 
					            class DummyEntryPoint(object):
 | 
				
			||||||
                name = 'spam'
 | 
					                name = 'spam'
 | 
				
			||||||
| 
						 | 
					@ -220,7 +220,7 @@ class TestImportHookInstallation:
 | 
				
			||||||
            def distributions():
 | 
					            def distributions():
 | 
				
			||||||
                return (DummyDistInfo(),)
 | 
					                return (DummyDistInfo(),)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            importlib_metadata.distributions = distributions
 | 
					            importlib.metadata.distributions = distributions
 | 
				
			||||||
            pytest.main()
 | 
					            pytest.main()
 | 
				
			||||||
            """,
 | 
					            """,
 | 
				
			||||||
            "test_foo.py": """\
 | 
					            "test_foo.py": """\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,9 +131,8 @@ class TestAssertionRewrite:
 | 
				
			||||||
            for n in [node, *ast.iter_child_nodes(node)]:
 | 
					            for n in [node, *ast.iter_child_nodes(node)]:
 | 
				
			||||||
                assert n.lineno == 3
 | 
					                assert n.lineno == 3
 | 
				
			||||||
                assert n.col_offset == 0
 | 
					                assert n.col_offset == 0
 | 
				
			||||||
                if sys.version_info >= (3, 8):
 | 
					                assert n.end_lineno == 6
 | 
				
			||||||
                    assert n.end_lineno == 6
 | 
					                assert n.end_col_offset == 3
 | 
				
			||||||
                    assert n.end_col_offset == 3
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dont_rewrite(self) -> None:
 | 
					    def test_dont_rewrite(self) -> None:
 | 
				
			||||||
        s = """'PYTEST_DONT_REWRITE'\nassert 14"""
 | 
					        s = """'PYTEST_DONT_REWRITE'\nassert 14"""
 | 
				
			||||||
| 
						 | 
					@ -1270,9 +1269,6 @@ class TestIssue2121:
 | 
				
			||||||
        result.stdout.fnmatch_lines(["*E*assert (1 + 1) == 3"])
 | 
					        result.stdout.fnmatch_lines(["*E*assert (1 + 1) == 3"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					 | 
				
			||||||
    sys.version_info < (3, 8), reason="walrus operator not available in py<38"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
class TestIssue10743:
 | 
					class TestIssue10743:
 | 
				
			||||||
    def test_assertion_walrus_operator(self, pytester: Pytester) -> None:
 | 
					    def test_assertion_walrus_operator(self, pytester: Pytester) -> None:
 | 
				
			||||||
        pytester.makepyfile(
 | 
					        pytester.makepyfile(
 | 
				
			||||||
| 
						 | 
					@ -1441,9 +1437,6 @@ class TestIssue10743:
 | 
				
			||||||
        assert result.ret == 0
 | 
					        assert result.ret == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					 | 
				
			||||||
    sys.version_info < (3, 8), reason="walrus operator not available in py<38"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
class TestIssue11028:
 | 
					class TestIssue11028:
 | 
				
			||||||
    def test_assertion_walrus_operator_in_operand(self, pytester: Pytester) -> None:
 | 
					    def test_assertion_walrus_operator_in_operand(self, pytester: Pytester) -> None:
 | 
				
			||||||
        pytester.makepyfile(
 | 
					        pytester.makepyfile(
 | 
				
			||||||
| 
						 | 
					@ -1957,16 +1950,10 @@ class TestPyCacheDir:
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_get_cache_dir(self, monkeypatch, prefix, source, expected) -> None:
 | 
					    def test_get_cache_dir(self, monkeypatch, prefix, source, expected) -> None:
 | 
				
			||||||
        monkeypatch.delenv("PYTHONPYCACHEPREFIX", raising=False)
 | 
					        monkeypatch.delenv("PYTHONPYCACHEPREFIX", raising=False)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if prefix is not None and sys.version_info < (3, 8):
 | 
					 | 
				
			||||||
            pytest.skip("pycache_prefix not available in py<38")
 | 
					 | 
				
			||||||
        monkeypatch.setattr(sys, "pycache_prefix", prefix, raising=False)
 | 
					        monkeypatch.setattr(sys, "pycache_prefix", prefix, raising=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert get_cache_dir(Path(source)) == Path(expected)
 | 
					        assert get_cache_dir(Path(source)) == Path(expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(
 | 
					 | 
				
			||||||
        sys.version_info < (3, 8), reason="pycache_prefix not available in py<38"
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    @pytest.mark.skipif(
 | 
					    @pytest.mark.skipif(
 | 
				
			||||||
        sys.version_info[:2] == (3, 9) and sys.platform.startswith("win"),
 | 
					        sys.version_info[:2] == (3, 9) and sys.platform.startswith("win"),
 | 
				
			||||||
        reason="#9298",
 | 
					        reason="#9298",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
import enum
 | 
					import enum
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					from functools import cached_property
 | 
				
			||||||
from functools import partial
 | 
					from functools import partial
 | 
				
			||||||
from functools import wraps
 | 
					from functools import wraps
 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					from typing import TYPE_CHECKING
 | 
				
			||||||
| 
						 | 
					@ -8,7 +9,6 @@ from typing import Union
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from _pytest.compat import _PytestWrapper
 | 
					from _pytest.compat import _PytestWrapper
 | 
				
			||||||
from _pytest.compat import assert_never
 | 
					from _pytest.compat import assert_never
 | 
				
			||||||
from _pytest.compat import cached_property
 | 
					 | 
				
			||||||
from _pytest.compat import get_real_func
 | 
					from _pytest.compat import get_real_func
 | 
				
			||||||
from _pytest.compat import is_generator
 | 
					from _pytest.compat import is_generator
 | 
				
			||||||
from _pytest.compat import safe_getattr
 | 
					from _pytest.compat import safe_getattr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
import dataclasses
 | 
					import dataclasses
 | 
				
			||||||
 | 
					import importlib.metadata
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
| 
						 | 
					@ -13,7 +14,6 @@ from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import _pytest._code
 | 
					import _pytest._code
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from _pytest.compat import importlib_metadata
 | 
					 | 
				
			||||||
from _pytest.config import _get_plugin_specs_as_list
 | 
					from _pytest.config import _get_plugin_specs_as_list
 | 
				
			||||||
from _pytest.config import _iter_rewritable_modules
 | 
					from _pytest.config import _iter_rewritable_modules
 | 
				
			||||||
from _pytest.config import _strtobool
 | 
					from _pytest.config import _strtobool
 | 
				
			||||||
| 
						 | 
					@ -475,7 +475,7 @@ class TestParseIni:
 | 
				
			||||||
        pytester.makepyfile(myplugin1_module="# my plugin module")
 | 
					        pytester.makepyfile(myplugin1_module="# my plugin module")
 | 
				
			||||||
        pytester.syspathinsert()
 | 
					        pytester.syspathinsert()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        monkeypatch.setattr(importlib_metadata, "distributions", my_dists)
 | 
					        monkeypatch.setattr(importlib.metadata, "distributions", my_dists)
 | 
				
			||||||
        monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False)
 | 
					        monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pytester.makeini(ini_file_text)
 | 
					        pytester.makeini(ini_file_text)
 | 
				
			||||||
| 
						 | 
					@ -1003,7 +1003,7 @@ def test_preparse_ordering_with_setuptools(
 | 
				
			||||||
    def my_dists():
 | 
					    def my_dists():
 | 
				
			||||||
        return (Dist,)
 | 
					        return (Dist,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monkeypatch.setattr(importlib_metadata, "distributions", my_dists)
 | 
					    monkeypatch.setattr(importlib.metadata, "distributions", my_dists)
 | 
				
			||||||
    pytester.makeconftest(
 | 
					    pytester.makeconftest(
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        pytest_plugins = "mytestplugin",
 | 
					        pytest_plugins = "mytestplugin",
 | 
				
			||||||
| 
						 | 
					@ -1036,7 +1036,7 @@ def test_setuptools_importerror_issue1479(
 | 
				
			||||||
    def distributions():
 | 
					    def distributions():
 | 
				
			||||||
        return (Distribution(),)
 | 
					        return (Distribution(),)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monkeypatch.setattr(importlib_metadata, "distributions", distributions)
 | 
					    monkeypatch.setattr(importlib.metadata, "distributions", distributions)
 | 
				
			||||||
    with pytest.raises(ImportError):
 | 
					    with pytest.raises(ImportError):
 | 
				
			||||||
        pytester.parseconfig()
 | 
					        pytester.parseconfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1063,7 +1063,7 @@ def test_importlib_metadata_broken_distribution(
 | 
				
			||||||
    def distributions():
 | 
					    def distributions():
 | 
				
			||||||
        return (Distribution(),)
 | 
					        return (Distribution(),)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monkeypatch.setattr(importlib_metadata, "distributions", distributions)
 | 
					    monkeypatch.setattr(importlib.metadata, "distributions", distributions)
 | 
				
			||||||
    pytester.parseconfig()
 | 
					    pytester.parseconfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1091,7 +1091,7 @@ def test_plugin_preparse_prevents_setuptools_loading(
 | 
				
			||||||
    def distributions():
 | 
					    def distributions():
 | 
				
			||||||
        return (Distribution(),)
 | 
					        return (Distribution(),)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monkeypatch.setattr(importlib_metadata, "distributions", distributions)
 | 
					    monkeypatch.setattr(importlib.metadata, "distributions", distributions)
 | 
				
			||||||
    args = ("-p", "no:mytestplugin") if block_it else ()
 | 
					    args = ("-p", "no:mytestplugin") if block_it else ()
 | 
				
			||||||
    config = pytester.parseconfig(*args)
 | 
					    config = pytester.parseconfig(*args)
 | 
				
			||||||
    config.pluginmanager.import_plugin("mytestplugin")
 | 
					    config.pluginmanager.import_plugin("mytestplugin")
 | 
				
			||||||
| 
						 | 
					@ -1140,7 +1140,7 @@ def test_disable_plugin_autoload(
 | 
				
			||||||
        return (Distribution(),)
 | 
					        return (Distribution(),)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1")
 | 
					    monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1")
 | 
				
			||||||
    monkeypatch.setattr(importlib_metadata, "distributions", distributions)
 | 
					    monkeypatch.setattr(importlib.metadata, "distributions", distributions)
 | 
				
			||||||
    monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin())  # type: ignore[misc]
 | 
					    monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin())  # type: ignore[misc]
 | 
				
			||||||
    config = pytester.parseconfig(*parse_args)
 | 
					    config = pytester.parseconfig(*parse_args)
 | 
				
			||||||
    has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None
 | 
					    has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
from _pytest.compat import importlib_metadata
 | 
					import importlib.metadata
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pytest_entry_points_are_identical():
 | 
					def test_pytest_entry_points_are_identical():
 | 
				
			||||||
    dist = importlib_metadata.distribution("pytest")
 | 
					    dist = importlib.metadata.distribution("pytest")
 | 
				
			||||||
    entry_map = {ep.name: ep for ep in dist.entry_points}
 | 
					    entry_map = {ep.name: ep for ep in dist.entry_points}
 | 
				
			||||||
    assert entry_map["pytest"].value == entry_map["py.test"].value
 | 
					    assert entry_map["pytest"].value == entry_map["py.test"].value
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1142,12 +1142,10 @@ def test_errors_in_xfail_skip_expressions(pytester: Pytester) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    result = pytester.runpytest()
 | 
					    result = pytester.runpytest()
 | 
				
			||||||
    markline = "                ^"
 | 
					    markline = "            ^"
 | 
				
			||||||
    pypy_version_info = getattr(sys, "pypy_version_info", None)
 | 
					    pypy_version_info = getattr(sys, "pypy_version_info", None)
 | 
				
			||||||
    if pypy_version_info is not None and pypy_version_info < (6,):
 | 
					    if pypy_version_info is not None and pypy_version_info < (6,):
 | 
				
			||||||
        markline = markline[5:]
 | 
					        markline = markline[1:]
 | 
				
			||||||
    elif sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"):
 | 
					 | 
				
			||||||
        markline = markline[4:]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if sys.version_info[:2] >= (3, 10):
 | 
					    if sys.version_info[:2] >= (3, 10):
 | 
				
			||||||
        expected = [
 | 
					        expected = [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,7 @@
 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from _pytest.pytester import Pytester
 | 
					from _pytest.pytester import Pytester
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if sys.version_info < (3, 8):
 | 
					 | 
				
			||||||
    pytest.skip("threadexception plugin needs Python>=3.8", allow_module_level=True)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning")
 | 
					@pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning")
 | 
				
			||||||
def test_unhandled_thread_exception(pytester: Pytester) -> None:
 | 
					def test_unhandled_thread_exception(pytester: Pytester) -> None:
 | 
				
			||||||
    pytester.makepyfile(
 | 
					    pytester.makepyfile(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1354,9 +1354,6 @@ def test_plain_unittest_does_not_support_async(pytester: Pytester) -> None:
 | 
				
			||||||
    result.stdout.fnmatch_lines(expected_lines)
 | 
					    result.stdout.fnmatch_lines(expected_lines)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					 | 
				
			||||||
    sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
def test_do_class_cleanups_on_success(pytester: Pytester) -> None:
 | 
					def test_do_class_cleanups_on_success(pytester: Pytester) -> None:
 | 
				
			||||||
    testpath = pytester.makepyfile(
 | 
					    testpath = pytester.makepyfile(
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -1382,9 +1379,6 @@ def test_do_class_cleanups_on_success(pytester: Pytester) -> None:
 | 
				
			||||||
    assert passed == 3
 | 
					    assert passed == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					 | 
				
			||||||
    sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
def test_do_class_cleanups_on_setupclass_failure(pytester: Pytester) -> None:
 | 
					def test_do_class_cleanups_on_setupclass_failure(pytester: Pytester) -> None:
 | 
				
			||||||
    testpath = pytester.makepyfile(
 | 
					    testpath = pytester.makepyfile(
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -1409,9 +1403,6 @@ def test_do_class_cleanups_on_setupclass_failure(pytester: Pytester) -> None:
 | 
				
			||||||
    assert passed == 1
 | 
					    assert passed == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					 | 
				
			||||||
    sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
def test_do_class_cleanups_on_teardownclass_failure(pytester: Pytester) -> None:
 | 
					def test_do_class_cleanups_on_teardownclass_failure(pytester: Pytester) -> None:
 | 
				
			||||||
    testpath = pytester.makepyfile(
 | 
					    testpath = pytester.makepyfile(
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,10 @@ import sys
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from _pytest.pytester import Pytester
 | 
					from _pytest.pytester import Pytester
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PYPY = hasattr(sys, "pypy_version_info")
 | 
				
			||||||
if sys.version_info < (3, 8):
 | 
					 | 
				
			||||||
    pytest.skip("unraisableexception plugin needs Python>=3.8", allow_module_level=True)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky")
 | 
				
			||||||
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
 | 
					@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
 | 
				
			||||||
def test_unraisable(pytester: Pytester) -> None:
 | 
					def test_unraisable(pytester: Pytester) -> None:
 | 
				
			||||||
    pytester.makepyfile(
 | 
					    pytester.makepyfile(
 | 
				
			||||||
| 
						 | 
					@ -40,6 +39,7 @@ def test_unraisable(pytester: Pytester) -> None:
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky")
 | 
				
			||||||
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
 | 
					@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
 | 
				
			||||||
def test_unraisable_in_setup(pytester: Pytester) -> None:
 | 
					def test_unraisable_in_setup(pytester: Pytester) -> None:
 | 
				
			||||||
    pytester.makepyfile(
 | 
					    pytester.makepyfile(
 | 
				
			||||||
| 
						 | 
					@ -76,6 +76,7 @@ def test_unraisable_in_setup(pytester: Pytester) -> None:
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky")
 | 
				
			||||||
@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
 | 
					@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning")
 | 
				
			||||||
def test_unraisable_in_teardown(pytester: Pytester) -> None:
 | 
					def test_unraisable_in_teardown(pytester: Pytester) -> None:
 | 
				
			||||||
    pytester.makepyfile(
 | 
					    pytester.makepyfile(
 | 
				
			||||||
| 
						 | 
					@ -116,7 +117,7 @@ def test_unraisable_in_teardown(pytester: Pytester) -> None:
 | 
				
			||||||
@pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning")
 | 
					@pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning")
 | 
				
			||||||
def test_unraisable_warning_error(pytester: Pytester) -> None:
 | 
					def test_unraisable_warning_error(pytester: Pytester) -> None:
 | 
				
			||||||
    pytester.makepyfile(
 | 
					    pytester.makepyfile(
 | 
				
			||||||
        test_it="""
 | 
					        test_it=f"""
 | 
				
			||||||
        class BrokenDel:
 | 
					        class BrokenDel:
 | 
				
			||||||
            def __del__(self) -> None:
 | 
					            def __del__(self) -> None:
 | 
				
			||||||
                raise ValueError("del is broken")
 | 
					                raise ValueError("del is broken")
 | 
				
			||||||
| 
						 | 
					@ -124,6 +125,7 @@ def test_unraisable_warning_error(pytester: Pytester) -> None:
 | 
				
			||||||
        def test_it() -> None:
 | 
					        def test_it() -> None:
 | 
				
			||||||
            obj = BrokenDel()
 | 
					            obj = BrokenDel()
 | 
				
			||||||
            del obj
 | 
					            del obj
 | 
				
			||||||
 | 
					            {"import gc; gc.collect()" * PYPY}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def test_2(): pass
 | 
					        def test_2(): pass
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								tox.ini
								
								
								
								
							
							
						
						
									
										9
									
								
								tox.ini
								
								
								
								
							| 
						 | 
					@ -4,17 +4,16 @@ minversion = 3.20.0
 | 
				
			||||||
distshare = {homedir}/.tox/distshare
 | 
					distshare = {homedir}/.tox/distshare
 | 
				
			||||||
envlist =
 | 
					envlist =
 | 
				
			||||||
    linting
 | 
					    linting
 | 
				
			||||||
    py37
 | 
					 | 
				
			||||||
    py38
 | 
					    py38
 | 
				
			||||||
    py39
 | 
					    py39
 | 
				
			||||||
    py310
 | 
					    py310
 | 
				
			||||||
    py311
 | 
					    py311
 | 
				
			||||||
    py312
 | 
					    py312
 | 
				
			||||||
    pypy3
 | 
					    pypy3
 | 
				
			||||||
    py37-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib}
 | 
					    py38-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib}
 | 
				
			||||||
    doctesting
 | 
					    doctesting
 | 
				
			||||||
    plugins
 | 
					    plugins
 | 
				
			||||||
    py37-freeze
 | 
					    py38-freeze
 | 
				
			||||||
    docs
 | 
					    docs
 | 
				
			||||||
    docs-checklinks
 | 
					    docs-checklinks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +42,7 @@ setenv =
 | 
				
			||||||
    PYTHONWARNDEFAULTENCODING=1
 | 
					    PYTHONWARNDEFAULTENCODING=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Configuration to run with coverage similar to CI, e.g.
 | 
					    # Configuration to run with coverage similar to CI, e.g.
 | 
				
			||||||
    # "tox -e py37-coverage".
 | 
					    # "tox -e py38-coverage".
 | 
				
			||||||
    coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
 | 
					    coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
 | 
				
			||||||
    coverage: _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
 | 
					    coverage: _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
 | 
				
			||||||
    coverage: COVERAGE_FILE={toxinidir}/.coverage
 | 
					    coverage: COVERAGE_FILE={toxinidir}/.coverage
 | 
				
			||||||
| 
						 | 
					@ -136,7 +135,7 @@ commands =
 | 
				
			||||||
    pytest pytest_twisted_integration.py
 | 
					    pytest pytest_twisted_integration.py
 | 
				
			||||||
    pytest simple_integration.py --force-sugar --flakes
 | 
					    pytest simple_integration.py --force-sugar --flakes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[testenv:py37-freeze]
 | 
					[testenv:py38-freeze]
 | 
				
			||||||
changedir = testing/freeze
 | 
					changedir = testing/freeze
 | 
				
			||||||
deps =
 | 
					deps =
 | 
				
			||||||
    pyinstaller
 | 
					    pyinstaller
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue