Skip to content
This repository was archived by the owner on Jan 23, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/googleclouddebugger/module_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@
import os
import sys

def NormalizePath(path):
"""Normalizes a path.

E.g. One example is it will convert "/a/b/./c" -> "/a/b/c"
"""
# TODO: Calling os.path.normpath "may change the meaning of a
# path that contains symbolic links" (e.g., "A/foo/../B" != "A/B" if foo is a
# symlink). This might cause trouble when matching against loaded module
# paths. We should try to avoid using it.
# Example:
# > import symlink.a
# > symlink.a.__file__
# symlink/a.py
# > import target.a
# > starget.a.__file__
# target/a.py
# Python interpreter treats these as two separate modules. So, we also need to
# handle them the same way.
return os.path.normpath(path)


def IsPathSuffix(mod_path, path):
"""Checks whether path is a full path suffix of mod_path.
Expand Down Expand Up @@ -69,6 +89,11 @@ def GetLoadedModuleBySuffix(path):
if not os.path.isabs(mod_root):
mod_root = os.path.join(os.getcwd(), mod_root)

# In the following invocation 'python3 ./main.py' (using the ./), the
# mod_root variable will '/base/path/./main'. In order to correctly compare
# it with the root variable, it needs to be '/base/path/main'.
mod_root = NormalizePath(mod_root)

if IsPathSuffix(mod_root, root):
return module

Expand Down
15 changes: 1 addition & 14 deletions src/googleclouddebugger/python_breakpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,20 +134,7 @@ def _MultipleModulesFoundError(path, candidates):

def _NormalizePath(path):
"""Removes surrounding whitespace, leading separator and normalize."""
# TODO: Calling os.path.normpath "may change the meaning of a
# path that contains symbolic links" (e.g., "A/foo/../B" != "A/B" if foo is a
# symlink). This might cause trouble when matching against loaded module
# paths. We should try to avoid using it.
# Example:
# > import symlink.a
# > symlink.a.__file__
# symlink/a.py
# > import target.a
# > starget.a.__file__
# target/a.py
# Python interpreter treats these as two separate modules. So, we also need to
# handle them the same way.
return os.path.normpath(path.strip().lstrip(os.sep))
return module_utils.NormalizePath(path.strip().lstrip(os.sep))


class PythonBreakpoint(object):
Expand Down
7 changes: 7 additions & 0 deletions tests/py/module_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ def testMainLoadedModuleFromSuffix(self):
self.assertTrue(m1, 'Module not found')
self.assertEqual('/a/b/p/m.pyc', m1.__file__)

def testMainWithDotSlashLoadedModuleFromSuffix(self):
# Lookup module started via 'python3 ./m.py', notice the './'
_AddSysModule('__main__', '/a/b/p/./m.pyc')
m1 = module_utils.GetLoadedModuleBySuffix('/a/b/p/m.py')
self.assertIsNotNone(m1)
self.assertTrue(m1, 'Module not found')
self.assertEqual('/a/b/p/./m.pyc', m1.__file__)

if __name__ == '__main__':
absltest.main()