From 0da4760715bebb130cc8bb84bdd6715cc9a2e0c4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 27 Dec 2021 11:22:00 +0200 Subject: [PATCH] code: accept any `os.PathLike[str]` in `Traceback.cut` Before 7.0.0rc1, the function accepted `Union[str, py.path.local]`, and `py.path.local` compares equal to the string path, so a user was able to pass the path as a string and it would work. In 7.0.0rc1 we changed the `py.path.local` to `Path` which doesn't compare equal to the string path, which breaks compatibility (e.g. the `sybil` package). This restores compatibility for this function by accepting any `os.PathLike[str]` and only comparing the string representations. --- src/_pytest/_code/code.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b19ee7c64..291d8890c 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1,5 +1,6 @@ import ast import inspect +import os import re import sys import traceback @@ -343,10 +344,10 @@ class Traceback(List[TracebackEntry]): def cut( self, - path: Optional[Union[Path, str]] = None, + path: Optional[Union["os.PathLike[str]", str]] = None, lineno: Optional[int] = None, firstlineno: Optional[int] = None, - excludepath: Optional[Path] = None, + excludepath: Optional["os.PathLike[str]"] = None, ) -> "Traceback": """Return a Traceback instance wrapping part of this Traceback. @@ -357,15 +358,17 @@ class Traceback(List[TracebackEntry]): for formatting reasons (removing some uninteresting bits that deal with handling of the exception/traceback). """ + path_ = None if path is None else os.fspath(path) + excludepath_ = None if excludepath is None else os.fspath(excludepath) for x in self: code = x.frame.code codepath = code.path - if path is not None and codepath != path: + if path is not None and str(codepath) != path_: continue if ( excludepath is not None and isinstance(codepath, Path) - and excludepath in codepath.parents + and excludepath_ in (str(p) for p in codepath.parents) # type: ignore[operator] ): continue if lineno is not None and x.lineno != lineno: