1919import enum
2020import inspect
2121import os
22+ import pathlib
2223import posixpath
2324import pprint
2425import re
@@ -601,26 +602,25 @@ def get_defined_in(
601602 base_dirs_and_prefixes = zip (parser_config .base_dir ,
602603 parser_config .code_url_prefix )
603604 try :
604- obj_path = inspect .getfile (_unwrap_obj (py_object ))
605+ obj_path = pathlib . Path ( inspect .getfile (_unwrap_obj (py_object ) ))
605606 except TypeError : # getfile throws TypeError if py_object is a builtin.
606607 return None
607608
608- if not obj_path .endswith (( '.py' , '.pyc' ) ):
609+ if obj_path .suffix not in ( '.py' , '.pyc' ):
609610 return None
610611
611612 code_url_prefix = None
612613 for base_dir , temp_prefix in base_dirs_and_prefixes :
613- rel_path = os .path .relpath (path = obj_path , start = base_dir )
614- # A leading ".." indicates that the file is not inside `base_dir`, and
615- # the search should continue.
616- if rel_path .startswith ('..' ):
614+ try :
615+ rel_path = obj_path .relative_to (base_dir )
616+ except ValueError :
617617 continue
618- else :
619- code_url_prefix = temp_prefix
620- # rel_path is currently a platform-specific path, so we need to convert
621- # it to a posix path (for lack of a URL path).
622- rel_path = posixpath . join ( * rel_path . split ( os . path . sep ))
623- break
618+
619+ code_url_prefix = temp_prefix
620+ # rel_path is currently a platform-specific path, so we need to convert
621+ # it to a posix path (for lack of a URL path).
622+ posix_rel_path_str = str ( pathlib . PurePosixPath ( rel_path ))
623+ break
624624
625625 # No link if the file was not found in a `base_dir`, or the prefix is None.
626626 if code_url_prefix is None :
@@ -637,30 +637,31 @@ def get_defined_in(
637637 end_line = None
638638
639639 # In case this is compiled, point to the original
640- if rel_path .endswith ('.pyc' ):
640+ if posix_rel_path_str .endswith ('.pyc' ):
641641 # If a PY3 __pycache__/ subdir is being used, omit it.
642- rel_path = rel_path .replace ('__pycache__' + os . sep , '' )
642+ posix_rel_path_str = posix_rel_path_str .replace ('__pycache__/' , '' )
643643 # Strip everything after the first . so that variants such as .pyc and
644644 # .cpython-3x.pyc or similar are all handled.
645- rel_path = rel_path .partition ('.' )[0 ] + '.py'
645+ posix_rel_path_str = posix_rel_path_str .partition ('.' )[0 ] + '.py'
646646
647- if re .search (r'<[\w\s]+>' , rel_path ):
647+ if re .search (r'<[\w\s]+>' , posix_rel_path_str ):
648648 # Built-ins emit paths like <embedded stdlib>, <string>, etc.
649649 return None
650- if '<attrs generated' in rel_path :
650+ if '<attrs generated' in posix_rel_path_str :
651651 return None
652652
653- if re .match (r'.*/gen_[^/]*\.py$' , rel_path ):
653+ if re .match (r'.*/gen_[^/]*\.py$' , posix_rel_path_str ):
654654 return FileLocation ()
655- if 'genfiles' in rel_path :
655+ if 'genfiles' in posix_rel_path_str :
656656 return FileLocation ()
657- elif re . match ( r'.* _pb2\ .py$' , rel_path ):
657+ elif posix_rel_path_str . endswith ( ' _pb2.py' ):
658658 # The _pb2.py files all appear right next to their defining .proto file.
659- rel_path = rel_path [:- 7 ] + '.proto'
660- return FileLocation (base_url = posixpath .join (code_url_prefix , rel_path ))
659+ posix_rel_path_str = posix_rel_path_str [:- 7 ] + '.proto'
660+ return FileLocation (
661+ base_url = posixpath .join (code_url_prefix , posix_rel_path_str ))
661662 else :
662663 return FileLocation (
663- base_url = posixpath .join (code_url_prefix , rel_path ),
664+ base_url = posixpath .join (code_url_prefix , posix_rel_path_str ),
664665 start_line = start_line ,
665666 end_line = end_line )
666667
0 commit comments