8
8
import weakref
9
9
from collections import deque
10
10
from enum import Enum
11
- from pathlib import Path
11
+ from pathlib import Path , PurePath
12
12
from typing import (
13
13
Any ,
14
14
Deque ,
@@ -182,7 +182,7 @@ def global_id(self) -> int:
182
182
183
183
184
184
class HitCountEntry (NamedTuple ):
185
- source : str
185
+ source : pathlib . PurePath
186
186
line : int
187
187
type : str
188
188
@@ -408,7 +408,7 @@ def set_breakpoints(
408
408
) -> List [Breakpoint ]:
409
409
410
410
if self .is_windows_path (source .path or "" ):
411
- path = pathlib .PureWindowsPath (source .path or "" )
411
+ path : pathlib . PurePath = pathlib .PureWindowsPath (source .path or "" )
412
412
else :
413
413
path = pathlib .PurePath (source .path or "" )
414
414
@@ -486,9 +486,9 @@ def process_start_state(self, source: str, line_no: int, type: str, status: str)
486
486
self .requested_state = RequestedState .Nothing
487
487
488
488
if source is not None :
489
- source = self .map_path_to_client (str (Path (source ).absolute ()))
490
- if source in self .breakpoints :
491
- breakpoints = [v for v in self .breakpoints [source ].breakpoints if v .line == line_no ]
489
+ source_path = self .map_path_to_client (str (Path (source ).absolute ()))
490
+ if source_path in self .breakpoints :
491
+ breakpoints = [v for v in self .breakpoints [source_path ].breakpoints if v .line == line_no ]
492
492
if len (breakpoints ) > 0 :
493
493
for point in breakpoints :
494
494
if point .condition is not None :
@@ -505,7 +505,7 @@ def process_start_state(self, source: str, line_no: int, type: str, status: str)
505
505
return
506
506
if point .hit_condition is not None :
507
507
hit = False
508
- entry = HitCountEntry (source , line_no , type )
508
+ entry = HitCountEntry (source_path , line_no , type )
509
509
if entry not in self .hit_counts :
510
510
self .hit_counts [entry ] = 0
511
511
self .hit_counts [entry ] += 1
@@ -531,7 +531,7 @@ def process_start_state(self, source: str, line_no: int, type: str, status: str)
531
531
body = OutputEventBody (
532
532
output = message + os .linesep ,
533
533
category = OutputCategory .CONSOLE ,
534
- source = Source (path = str (source )) if source else None ,
534
+ source = Source (path = str (source_path )) ,
535
535
line = line_no ,
536
536
)
537
537
),
@@ -878,24 +878,35 @@ def get_threads(self) -> List[Thread]:
878
878
WINDOW_PATH_REGEX = re .compile (r"^(([a-z]:[\\/])|(\\\\)).*$" , re .RegexFlag .IGNORECASE )
879
879
880
880
@classmethod
881
- def is_windows_path (cls , path : os .PathLike [str ]) -> bool :
881
+ def is_windows_path (cls , path : Union [ os .PathLike [str ], str ]) -> bool :
882
882
return bool (cls .WINDOW_PATH_REGEX .fullmatch (str (path )))
883
883
884
- def map_path_to_client (self , path : os .PathLike [str ]) -> pathlib .PurePath :
884
+ @staticmethod
885
+ def relative_to (path : pathlib .PurePath , * other : pathlib .PurePath ) -> Optional [pathlib .PurePath ]:
886
+ try :
887
+ return path .relative_to (* other )
888
+ except ValueError :
889
+ return None
890
+
891
+ def map_path_to_client (self , path : Union [os .PathLike [str ], str ]) -> pathlib .PurePath :
892
+ if not isinstance (path , PurePath ):
893
+ path = PurePath (path )
894
+
885
895
if not self .path_mappings :
886
- return pathlib . PurePath ( path )
896
+ return path
887
897
888
898
for mapping in self .path_mappings :
889
899
890
900
remote_root_path = Path (mapping .remote_root or "." ).absolute ()
891
901
892
- if Path (path ).is_relative_to (remote_root_path ):
902
+ if (
903
+ mapping .local_root is not None
904
+ and (relative_path := self .relative_to (Path (path ), remote_root_path )) is not None
905
+ ):
893
906
if self .is_windows_path (mapping .local_root ):
894
- local_root_path = str (pathlib .PureWindowsPath (mapping .local_root ))
895
- return pathlib .PureWindowsPath (path .replace (str (remote_root_path ), local_root_path or "" ))
907
+ return pathlib .PureWindowsPath (mapping .local_root , relative_path )
896
908
else :
897
- local_root_path = str (pathlib .PurePath (mapping .local_root ))
898
- return pathlib .PurePath (path .replace (str (remote_root_path ), local_root_path or "" ))
909
+ return pathlib .PurePath (mapping .local_root , relative_path )
899
910
900
911
return path
901
912
@@ -962,7 +973,11 @@ def log_message(self, message: Dict[str, Any]) -> None:
962
973
self .last_fail_message = msg
963
974
964
975
current_frame = self .full_stack_frames [0 ] if self .full_stack_frames else None
965
- source = Source (path = str (self .map_path_to_client (current_frame .source ))) if current_frame else None
976
+ source = (
977
+ Source (path = str (self .map_path_to_client (current_frame .source )))
978
+ if current_frame and current_frame .source
979
+ else None
980
+ )
966
981
line = current_frame .line if current_frame else None
967
982
968
983
if self .output_log :
0 commit comments