From 853b0a4c299d909b7e543a4307f16e3746d642cd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Oct 2021 21:33:12 +0300 Subject: [PATCH 1/7] nodes: fix bug in Node() fspath compat Since path <-> fspath are converted to each other, we need to check both before looking at the parent, in case fspath is set but path is not. --- src/_pytest/nodes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 3b70e111789..37b0b3d2b70 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -210,9 +210,9 @@ def __init__( self.session = parent.session #: Filesystem path where this node was collected from (can be None). - self.path = _imply_path_only( - path or getattr(parent, "path", None), fspath=fspath - ) + if path is None and fspath is None: + path = getattr(parent, "path", None) + self.path = _imply_path_only(path, fspath=fspath) # The explicit annotation is to avoid publicly exposing NodeKeywords. #: Keywords/markers collected from all scopes. From 6be3f31dba3f4832577e46c8dbaa0a7048980a83 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Oct 2021 21:18:51 +0300 Subject: [PATCH 2/7] nodes: remove redundent _imply_path call The Node ctor will take care of the check. --- src/_pytest/nodes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 37b0b3d2b70..0a5acbad918 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -634,7 +634,6 @@ def from_parent( **kw, ): """The public constructor.""" - path, fspath = _imply_path(path, fspath=fspath) return super().from_parent(parent=parent, fspath=fspath, path=path, **kw) def gethookproxy(self, fspath: "os.PathLike[str]"): From afc7442e22e629038b84990200d066058f6be4c6 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Oct 2021 21:40:57 +0300 Subject: [PATCH 3/7] nodes: inline `_imply_path` Only one usage left, and we certainly don't expect more! Rename `_imply_path_only` to `_imply_path`, that's a less confusing name now. --- src/_pytest/config/compat.py | 13 +++++++++++-- src/_pytest/nodes.py | 22 +++------------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/_pytest/config/compat.py b/src/_pytest/config/compat.py index c93f3738d4f..731641ddebf 100644 --- a/src/_pytest/config/compat.py +++ b/src/_pytest/config/compat.py @@ -4,8 +4,9 @@ from typing import Optional from ..compat import LEGACY_PATH +from ..compat import legacy_path from ..deprecated import HOOK_LEGACY_PATH_ARG -from _pytest.nodes import _imply_path +from _pytest.nodes import _check_path # hookname: (Path, LEGACY_PATH) imply_paths_hooks = { @@ -52,7 +53,15 @@ def fixed_hook(**kw): ), stacklevel=2, ) - path_value, fspath_value = _imply_path(path_value, fspath_value) + if path_value is not None: + if fspath_value is not None: + _check_path(path_value, fspath_value) + else: + fspath_value = legacy_path(path_value) + else: + assert fspath_value is not None + path_value = Path(fspath_value) + kw[path_var] = path_value kw[fspath_var] = fspath_value return hook(**kw) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 0a5acbad918..33bf1062b02 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -101,23 +101,7 @@ def _check_path(path: Path, fspath: LEGACY_PATH) -> None: ) -def _imply_path( - path: Optional[Path], fspath: Optional[LEGACY_PATH] -) -> Tuple[Path, LEGACY_PATH]: - if path is not None: - if fspath is not None: - _check_path(path, fspath) - else: - fspath = legacy_path(path) - return path, fspath - else: - assert fspath is not None - return Path(fspath), fspath - - -# Optimization: use _imply_path_only over _imply_path when only need Path. -# This is to avoid `legacy_path(path)` which is surprisingly heavy. -def _imply_path_only(path: Optional[Path], fspath: Optional[LEGACY_PATH]) -> Path: +def _imply_path(path: Optional[Path], fspath: Optional[LEGACY_PATH]) -> Path: if path is not None: if fspath is not None: _check_path(path, fspath) @@ -212,7 +196,7 @@ def __init__( #: Filesystem path where this node was collected from (can be None). if path is None and fspath is None: path = getattr(parent, "path", None) - self.path = _imply_path_only(path, fspath=fspath) + self.path = _imply_path(path, fspath=fspath) # The explicit annotation is to avoid publicly exposing NodeKeywords. #: Keywords/markers collected from all scopes. @@ -589,7 +573,7 @@ def __init__( assert path is None path = path_or_parent - path = _imply_path_only(path, fspath=fspath) + path = _imply_path(path, fspath=fspath) if name is None: name = path.name if parent is not None and parent.path != path: From 755ce9bc808a5a6eb63d601a27aab6064e1faeaa Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Oct 2021 22:29:20 +0300 Subject: [PATCH 4/7] hookspec: improve legacy path deprecation docs --- changelog/7259.deprecation.rst | 1 + doc/en/deprecations.rst | 16 +++++++++------ src/_pytest/hookspec.py | 36 ++++++++++++++++++++-------------- 3 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 changelog/7259.deprecation.rst diff --git a/changelog/7259.deprecation.rst b/changelog/7259.deprecation.rst new file mode 100644 index 00000000000..e450b359991 --- /dev/null +++ b/changelog/7259.deprecation.rst @@ -0,0 +1 @@ +``py.path.local`` arguments for hooks have been deprecated. See :ref:`the deprecation note ` for full details. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 775bc1958a3..ddddcfb0e6b 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -19,16 +19,20 @@ Below is a complete list of all pytest features which are considered deprecated. :class:`PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. +.. _legacy-path-hooks-deprecated: + ``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In order to support the transition to :mod:`pathlib`, the following hooks now receive additional arguments: +.. deprecated:: 7.0 + +In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the following hooks now receive additional arguments: -* :func:`pytest_ignore_collect(fspath: pathlib.Path) <_pytest.hookspec.pytest_ignore_collect>` -* :func:`pytest_collect_file(fspath: pathlib.Path) <_pytest.hookspec.pytest_collect_file>` -* :func:`pytest_pycollect_makemodule(fspath: pathlib.Path) <_pytest.hookspec.pytest_pycollect_makemodule>` -* :func:`pytest_report_header(startpath: pathlib.Path) <_pytest.hookspec.pytest_report_header>` -* :func:`pytest_report_collectionfinish(startpath: pathlib.Path) <_pytest.hookspec.pytest_report_collectionfinish>` +* :func:`pytest_ignore_collect(fspath: pathlib.Path) <_pytest.hookspec.pytest_ignore_collect>` instead of ``path`` +* :func:`pytest_collect_file(fspath: pathlib.Path) <_pytest.hookspec.pytest_collect_file>` instead of ``path`` +* :func:`pytest_pycollect_makemodule(fspath: pathlib.Path) <_pytest.hookspec.pytest_pycollect_makemodule>` instead of ``path`` +* :func:`pytest_report_header(startpath: pathlib.Path) <_pytest.hookspec.pytest_report_header>` instead of ``startdir`` +* :func:`pytest_report_collectionfinish(startpath: pathlib.Path) <_pytest.hookspec.pytest_report_collectionfinish>` instead of ``startdir`` The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments. diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 29a713b007d..e3cfc07186e 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -272,12 +272,13 @@ def pytest_ignore_collect( Stops at first non-None result, see :ref:`firstresult`. :param pathlib.Path fspath: The path to analyze. - :param LEGACY_PATH path: The path to analyze. + :param LEGACY_PATH path: The path to analyze (deprecated). :param pytest.Config config: The pytest config object. - .. versionchanged:: 6.3.0 + .. versionchanged:: 7.0.0 The ``fspath`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``path`` parameter. + equivalent of the ``path`` parameter. The ``path`` parameter + has been deprecated. """ @@ -289,11 +290,12 @@ def pytest_collect_file( The new node needs to have the specified ``parent`` as a parent. :param pathlib.Path fspath: The path to analyze. - :param LEGACY_PATH path: The path to collect. + :param LEGACY_PATH path: The path to collect (deprecated). - .. versionchanged:: 6.3.0 + .. versionchanged:: 7.0.0 The ``fspath`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``path`` parameter. + equivalent of the ``path`` parameter. The ``path`` parameter + has been deprecated. """ @@ -345,11 +347,13 @@ def pytest_pycollect_makemodule( Stops at first non-None result, see :ref:`firstresult`. :param pathlib.Path fspath: The path of the module to collect. - :param legacy_path path: The path of the module to collect. + :param LEGACY_PATH path: The path of the module to collect (deprecated). - .. versionchanged:: 6.3.0 + .. versionchanged:: 7.0.0 The ``fspath`` parameter was added as a :class:`pathlib.Path` equivalent of the ``path`` parameter. + + The ``path`` parameter has been deprecated in favor of ``fspath``. """ @@ -674,7 +678,7 @@ def pytest_report_header( :param pytest.Config config: The pytest config object. :param Path startpath: The starting dir. - :param LEGACY_PATH startdir: The starting dir. + :param LEGACY_PATH startdir: The starting dir (deprecated). .. note:: @@ -689,9 +693,10 @@ def pytest_report_header( files situated at the tests root directory due to how pytest :ref:`discovers plugins during startup `. - .. versionchanged:: 6.3.0 + .. versionchanged:: 7.0.0 The ``startpath`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``startdir`` parameter. + equivalent of the ``startdir`` parameter. The ``startdir`` parameter + has been deprecated. """ @@ -709,8 +714,8 @@ def pytest_report_collectionfinish( .. versionadded:: 3.2 :param pytest.Config config: The pytest config object. - :param Path startpath: The starting path. - :param LEGACY_PATH startdir: The starting dir. + :param Path startpath: The starting dir. + :param LEGACY_PATH startdir: The starting dir (deprecated). :param items: List of pytest items that are going to be executed; this list should not be modified. .. note:: @@ -720,9 +725,10 @@ def pytest_report_collectionfinish( If you want to have your line(s) displayed first, use :ref:`trylast=True `. - .. versionchanged:: 6.3.0 + .. versionchanged:: 7.0.0 The ``startpath`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``startdir`` parameter. + equivalent of the ``startdir`` parameter. The ``startdir`` parameter + has been deprecated. """ From 60ca83746ba107473bbaee870fc8cdd98766961e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Oct 2021 22:34:17 +0300 Subject: [PATCH 5/7] docs: change references to 6.3 -> 7.0 The plans have changed, next version will be 7.0 not 6.3. --- doc/en/deprecations.rst | 4 ++-- src/_pytest/cacheprovider.py | 2 +- src/_pytest/config/argparsing.py | 2 +- src/_pytest/main.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index ddddcfb0e6b..cfe7f489f7e 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -63,7 +63,7 @@ Implement the :func:`pytest_load_initial_conftests <_pytest.hookspec.pytest_load Diamond inheritance between :class:`pytest.File` and :class:`pytest.Item` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. deprecated:: 6.3 +.. deprecated:: 7.0 Inheriting from both Item and file at once has never been supported officially, however some plugins providing linting/code analysis have been using this as a hack. @@ -90,7 +90,7 @@ scheduled for removal in pytest 7 (deprecated since pytest 2.4.0): Raising ``unittest.SkipTest`` during collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. deprecated:: 6.3 +.. deprecated:: 7.0 Raising :class:`unittest.SkipTest` to skip collection of tests during the pytest collection phase is deprecated. Use :func:`pytest.skip` instead. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 78cec709337..78edf9ac5c6 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -128,7 +128,7 @@ def mkdir(self, name: str) -> Path: it to manage files to e.g. store/retrieve database dumps across test sessions. - .. versionadded:: 6.3 + .. versionadded:: 7.0 :param name: Must be a string not containing a ``/`` separator. diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index b3aff258a78..b0bb3f168ff 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -185,7 +185,7 @@ def addini( * ``paths``: a list of :class:`pathlib.Path`, separated as in a shell * ``pathlist``: a list of ``py.path``, separated as in a shell - .. versionadded:: 6.3 + .. versionadded:: 7.0 The ``paths`` variable type. Defaults to ``string`` if ``None`` or not passed. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index cfdc091e1d6..c482224094a 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -500,7 +500,7 @@ def __repr__(self) -> str: def startpath(self) -> Path: """The path from which pytest was invoked. - .. versionadded:: 6.3.0 + .. versionadded:: 7.0.0 """ return self.config.invocation_params.dir From 99363ad7ffefcb006183070ada497c9d143ed25e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Oct 2021 23:17:35 +0300 Subject: [PATCH 6/7] recwarn: fix was -> were in DID NOT WARN message --- doc/en/how-to/capture-warnings.rst | 2 +- src/_pytest/recwarn.py | 6 +++--- testing/test_recwarn.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index ae76b5bce2f..1a3d1873c41 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -268,7 +268,7 @@ argument ``match`` to assert that the exception matches a text or regex:: ... warnings.warn("this is not here", UserWarning) Traceback (most recent call last): ... - Failed: DID NOT WARN. No warnings of type ...UserWarning... was emitted... + Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted... You can also call :func:`pytest.warns` on a function or code string: diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 950d853f51d..175b571a80c 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -136,7 +136,7 @@ def warns( ... warnings.warn("this is not here", UserWarning) Traceback (most recent call last): ... - Failed: DID NOT WARN. No warnings of type ...UserWarning... was emitted... + Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted... """ __tracebackhide__ = True @@ -274,7 +274,7 @@ def __exit__( if not any(issubclass(r.category, self.expected_warning) for r in self): __tracebackhide__ = True fail( - "DID NOT WARN. No warnings of type {} was emitted. " + "DID NOT WARN. No warnings of type {} were emitted. " "The list of emitted warnings is: {}.".format( self.expected_warning, [each.message for each in self] ) @@ -287,7 +287,7 @@ def __exit__( else: fail( "DID NOT WARN. No warnings of type {} matching" - " ('{}') was emitted. The list of emitted warnings" + " ('{}') were emitted. The list of emitted warnings" " is: {}.".format( self.expected_warning, self.match_expr, diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index b82fd9a865b..d3f218f1660 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -263,7 +263,7 @@ def test_as_contextmanager(self) -> None: with pytest.warns(RuntimeWarning): warnings.warn("user", UserWarning) excinfo.match( - r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) was emitted. " + r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) were emitted. " r"The list of emitted warnings is: \[UserWarning\('user',?\)\]." ) @@ -271,7 +271,7 @@ def test_as_contextmanager(self) -> None: with pytest.warns(UserWarning): warnings.warn("runtime", RuntimeWarning) excinfo.match( - r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. " + r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted. " r"The list of emitted warnings is: \[RuntimeWarning\('runtime',?\)\]." ) @@ -279,7 +279,7 @@ def test_as_contextmanager(self) -> None: with pytest.warns(UserWarning): pass excinfo.match( - r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. " + r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted. " r"The list of emitted warnings is: \[\]." ) @@ -290,7 +290,7 @@ def test_as_contextmanager(self) -> None: warnings.warn("import", ImportWarning) message_template = ( - "DID NOT WARN. No warnings of type {0} was emitted. " + "DID NOT WARN. No warnings of type {0} were emitted. " "The list of emitted warnings is: {1}." ) excinfo.match( From 7706fd68401c7730ad06103577c10cc4cf031221 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Oct 2021 22:05:56 +0300 Subject: [PATCH 7/7] nodes: deprecate fspath arguments to node constructors This is unfortunately a dependency on `py.path` which cannot be moved to an external plugins or eased in any way, so has to be deprecated in order for pytest to be able to eventually remove the dependency on `py`. --- changelog/7259.deprecation.rst | 2 ++ doc/en/deprecations.rst | 19 +++++++++++++++++++ src/_pytest/deprecated.py | 8 ++++++++ src/_pytest/nodes.py | 18 +++++++++++++++--- testing/deprecated_test.py | 13 +++++++++++++ testing/plugins_integration/requirements.txt | 2 +- 6 files changed, 58 insertions(+), 4 deletions(-) diff --git a/changelog/7259.deprecation.rst b/changelog/7259.deprecation.rst index e450b359991..c0307740d55 100644 --- a/changelog/7259.deprecation.rst +++ b/changelog/7259.deprecation.rst @@ -1 +1,3 @@ ``py.path.local`` arguments for hooks have been deprecated. See :ref:`the deprecation note ` for full details. + +``py.path.local`` arguments to Node constructors have been deprecated. See :ref:`the deprecation note ` for full details. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index cfe7f489f7e..b82dd8521e8 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -18,6 +18,25 @@ Deprecated Features Below is a complete list of all pytest features which are considered deprecated. Using those features will issue :class:`PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. +.. _node-ctor-fspath-deprecation: + +``fspath`` argument for Node constructors replaced with ``pathlib.Path`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 + +In order to support the transition from ``py.path.local`` to :mod:`pathlib`, +the ``fspath`` argument to :class:`~_pytest.nodes.Node` constructors like +:func:`pytest.Function.from_parent()` and :func:`pytest.Class.from_parent()` +is now deprecated. + +Plugins which construct nodes should pass the ``path`` argument, of type +:class:`pathlib.Path`, instead of the ``fspath`` argument. + +Plugins which implement custom items and collectors are encouraged to replace +``py.path.local`` ``fspath`` parameters with ``pathlib.Path`` parameters, and +drop any other usage of the ``py`` library if possible. + .. _legacy-path-hooks-deprecated: diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 0c5db6d5335..452128d07b9 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -101,6 +101,14 @@ "#py-path-local-arguments-for-hooks-replaced-with-pathlib-path", ) +NODE_CTOR_FSPATH_ARG = UnformattedWarning( + PytestDeprecationWarning, + "The (fspath: py.path.local) argument to {node_type_name} is deprecated. " + "Please use the (path: pathlib.Path) argument instead.\n" + "See https://docs.pytest.org/en/latest/deprecations.html" + "#fspath-argument-for-node-constructors-replaced-with-pathlib-path", +) + WARNS_NONE_ARG = PytestDeprecationWarning( "Passing None to catch any warning has been deprecated, pass no arguments instead:\n" " Replace pytest.warns(None) by simply pytest.warns()." diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 33bf1062b02..05cf01fc6c4 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -28,6 +28,7 @@ from _pytest.config import Config from _pytest.config import ConftestImportFailure from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH +from _pytest.deprecated import NODE_CTOR_FSPATH_ARG from _pytest.mark.structures import Mark from _pytest.mark.structures import MarkDecorator from _pytest.mark.structures import NodeKeywords @@ -101,7 +102,18 @@ def _check_path(path: Path, fspath: LEGACY_PATH) -> None: ) -def _imply_path(path: Optional[Path], fspath: Optional[LEGACY_PATH]) -> Path: +def _imply_path( + node_type: Type["Node"], + path: Optional[Path], + fspath: Optional[LEGACY_PATH], +) -> Path: + if fspath is not None: + warnings.warn( + NODE_CTOR_FSPATH_ARG.format( + node_type_name=node_type.__name__, + ), + stacklevel=3, + ) if path is not None: if fspath is not None: _check_path(path, fspath) @@ -196,7 +208,7 @@ def __init__( #: Filesystem path where this node was collected from (can be None). if path is None and fspath is None: path = getattr(parent, "path", None) - self.path = _imply_path(path, fspath=fspath) + self.path = _imply_path(type(self), path, fspath=fspath) # The explicit annotation is to avoid publicly exposing NodeKeywords. #: Keywords/markers collected from all scopes. @@ -573,7 +585,7 @@ def __init__( assert path is None path = path_or_parent - path = _imply_path(path, fspath=fspath) + path = _imply_path(type(self), path, fspath=fspath) if name is None: name = path.name if parent is not None and parent.path != path: diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index bf796a3396f..0f5e483ce38 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -215,3 +215,16 @@ def pytest_cmdline_preparse(config, args): "*Please use pytest_load_initial_conftests hook instead.*", ] ) + + +def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: + mod = pytester.getmodulecol("") + + with pytest.warns( + pytest.PytestDeprecationWarning, + match=re.escape("The (fspath: py.path.local) argument to File is deprecated."), + ): + pytest.File.from_parent( + parent=mod.parent, + fspath=legacy_path("bla"), + ) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 8ef321fd3f8..89e8b0890c5 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -4,7 +4,7 @@ pytest-asyncio==0.16.0 pytest-bdd==4.1.0 pytest-cov==3.0.0 pytest-django==4.4.0 -pytest-flakes==4.0.3 +pytest-flakes==4.0.4 pytest-html==3.1.1 pytest-mock==3.6.1 pytest-rerunfailures==10.2