@@ -1005,9 +1005,26 @@ def cached_fsdecode(path: pathlib.Path) -> str:
10051005 return _path_to_str_cache [path ]
10061006
10071007
1008- def compact_path (path : pathlib .Path | str , path_base : pathlib .Path ) -> str :
1008+ def compact_path (path : pathlib .Path | str , path_base : pathlib .Path , path_base_str : str ) -> str :
10091009 """Return path relative to path_base when possible without resolving symlinks."""
1010- current_path = pathlib .Path (path )
1010+
1011+ if isinstance (path , str ):
1012+ path_str = path
1013+ current_path = pathlib .Path (path )
1014+ else :
1015+ path_str = str (path )
1016+ current_path = path
1017+
1018+ # pathlib.Path.relative_to is an expensive operation,
1019+ # for common cases where path is nested in path_base and path_base is therefore a prefix
1020+ # we skip the expensive check and just chop off the prefix to yield relative path
1021+ if path_str .startswith (path_base_str ):
1022+ # +1 because pathlib.Path never ends by a trailing separator which we also need to chop off:
1023+ # path_base_str= /some/prefix
1024+ # path_str= /some/prefix/tests/mytest.py
1025+ rel_str = path_str [(len (path_base_str ) + 1 ):]
1026+ return "." if rel_str == "" else rel_str
1027+
10111028 if not current_path .is_absolute ():
10121029 return os .fspath (current_path )
10131030
@@ -1020,17 +1037,19 @@ def compact_path(path: pathlib.Path | str, path_base: pathlib.Path) -> str:
10201037 return relative_path_str or "."
10211038
10221039
1023- def compact_test_id (test_id : str , id_base : pathlib .Path ) -> str :
1040+ def compact_test_id (test_id : str , id_base : pathlib .Path , id_base_str : str ) -> str :
10241041 """Compact the path prefix in a pytest node id while preserving pytest selectors."""
10251042 test_path , separator , selector = test_id .partition ("::" )
1026- compact_test_path = compact_path (test_path , id_base )
1043+ compact_test_path = compact_path (test_path , id_base , id_base_str )
10271044 return f"{ compact_test_path } { separator } { selector } " if separator else compact_test_path
10281045
10291046
10301047def compact_test_node (
10311048 test_node : TestNode | TestItem | None ,
10321049 path_base : pathlib .Path ,
10331050 id_base : pathlib .Path ,
1051+ path_base_str : str ,
1052+ id_base_str : str ,
10341053) -> dict [str , Any ] | None :
10351054 """Create a compact copy of a discovery node for JSON serialization."""
10361055 if test_node is None :
@@ -1039,13 +1058,13 @@ def compact_test_node(
10391058 compact_node : dict [str , Any ] = {}
10401059 for key , value in test_node .items ():
10411060 if key == "path" :
1042- compact_node [key ] = compact_path (cast ("pathlib.Path" , value ), path_base )
1061+ compact_node [key ] = compact_path (cast ("pathlib.Path" , value ), path_base , path_base_str )
10431062 elif key in {"id_" , "runID" }:
1044- compact_node [key ] = compact_test_id (cast ("str" , value ), id_base )
1063+ compact_node [key ] = compact_test_id (cast ("str" , value ), id_base , id_base_str )
10451064 elif key == "children" :
10461065 children_iter = value .values () if isinstance (value , Children ) else value
10471066 compact_node [key ] = [
1048- compact_test_node (child , path_base , id_base )
1067+ compact_test_node (child , path_base , id_base , path_base_str , id_base_str )
10491068 for child in cast ("list[TestNode | TestItem | None]" , children_iter )
10501069 ]
10511070 else :
@@ -1057,12 +1076,14 @@ def create_compact_discovery_payload(
10571076 cwd : str , session_node : TestNode
10581077) -> CompactDiscoveryPayloadDict :
10591078 """Create the compact wire payload after discovery has fully resolved the tree."""
1060- path_base = pathlib .Path (session_node ["path" ])
1079+ path_base_str = str (session_node ["path" ])
1080+ path_base = pathlib .Path (path_base_str )
10611081 id_base = path_base
1082+ id_base_str = path_base_str
10621083 return CompactDiscoveryPayloadDict (
10631084 cwd = cwd ,
10641085 status = "success" if not ERRORS else "error" ,
1065- tests = cast ("TestNode" , compact_test_node (session_node , path_base , id_base )),
1086+ tests = cast ("TestNode" , compact_test_node (session_node , path_base , id_base , path_base_str , id_base_str )),
10661087 error = ERRORS ,
10671088 payloadVersion = 2 ,
10681089 pathBase = os .fspath (path_base ),
0 commit comments