graphlens-python 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/PKG-INFO +1 -1
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/pyproject.toml +1 -1
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/src/graphlens_python/_adapter.py +8 -1
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/src/graphlens_python/_project_detector.py +20 -32
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/src/graphlens_python/__init__.py +0 -0
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/src/graphlens_python/_deps.py +0 -0
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/src/graphlens_python/_module_resolver.py +0 -0
- {graphlens_python-0.2.1 → graphlens_python-0.3.0}/src/graphlens_python/_visitor.py +0 -0
|
@@ -14,6 +14,7 @@ from graphlens import (
|
|
|
14
14
|
RelationKind,
|
|
15
15
|
)
|
|
16
16
|
from graphlens.utils import make_node_id
|
|
17
|
+
from graphlens.utils.roots import filter_nested_root_files
|
|
17
18
|
|
|
18
19
|
from graphlens_python._deps import (
|
|
19
20
|
PYTHON_DEFAULT_DEP_PARSERS,
|
|
@@ -95,8 +96,14 @@ class PythonAdapter(LanguageAdapter):
|
|
|
95
96
|
self._dep_parsers,
|
|
96
97
|
)
|
|
97
98
|
else:
|
|
98
|
-
|
|
99
|
+
py_roots = find_python_roots(project_root)
|
|
100
|
+
for py_root in py_roots:
|
|
99
101
|
root_files = self.collect_files(py_root)
|
|
102
|
+
root_files = filter_nested_root_files(
|
|
103
|
+
root_files,
|
|
104
|
+
py_root,
|
|
105
|
+
py_roots,
|
|
106
|
+
)
|
|
100
107
|
_analyze_root(
|
|
101
108
|
graph,
|
|
102
109
|
project_root,
|
|
@@ -6,6 +6,8 @@ import configparser
|
|
|
6
6
|
import tomllib
|
|
7
7
|
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
|
+
from graphlens.utils import collect_marker_roots
|
|
10
|
+
|
|
9
11
|
if TYPE_CHECKING:
|
|
10
12
|
from pathlib import Path
|
|
11
13
|
|
|
@@ -47,38 +49,21 @@ def find_python_roots(search_root: Path) -> list[Path]:
|
|
|
47
49
|
"""
|
|
48
50
|
Find the actual Python project roots within search_root.
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
Walks for marker files and returns their parent directories — one per
|
|
53
|
+
distinct Python sub-project. A marker at ``search_root`` does not hide
|
|
54
|
+
nested marker roots. This ensures that ``detect_project_name`` and
|
|
55
|
+
source-root resolution use the *correct* root rather than treating the
|
|
56
|
+
whole monorepo as one project.
|
|
55
57
|
|
|
56
58
|
Falls back to ``[search_root]`` when no markers are found anywhere (the
|
|
57
59
|
directory contains only bare .py scripts with no packaging metadata).
|
|
58
60
|
"""
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
rel_parts = marker_file.relative_to(search_root).parts
|
|
66
|
-
if _EXCLUDED_DIRS & set(rel_parts):
|
|
67
|
-
continue
|
|
68
|
-
if marker == "pyproject.toml" and not (
|
|
69
|
-
_pyproject_has_project_section(marker_file)
|
|
70
|
-
):
|
|
71
|
-
continue
|
|
72
|
-
candidate = marker_file.parent
|
|
73
|
-
# Skip if already covered by a previously found (ancestor) root
|
|
74
|
-
if any(
|
|
75
|
-
candidate == r or candidate.is_relative_to(r)
|
|
76
|
-
for r in roots
|
|
77
|
-
):
|
|
78
|
-
continue
|
|
79
|
-
roots.append(candidate)
|
|
80
|
-
|
|
81
|
-
return sorted(roots) if roots else [search_root]
|
|
61
|
+
return collect_marker_roots(
|
|
62
|
+
search_root,
|
|
63
|
+
PYTHON_MARKERS,
|
|
64
|
+
excluded_dirs=_EXCLUDED_DIRS,
|
|
65
|
+
marker_filter=_is_valid_python_marker,
|
|
66
|
+
)
|
|
82
67
|
|
|
83
68
|
|
|
84
69
|
def detect_project_name(project_root: Path) -> str:
|
|
@@ -121,14 +106,17 @@ def _has_python_markers(directory: Path) -> bool:
|
|
|
121
106
|
path = directory / marker
|
|
122
107
|
if not path.exists():
|
|
123
108
|
continue
|
|
124
|
-
if
|
|
125
|
-
if _pyproject_has_project_section(path):
|
|
126
|
-
return True
|
|
127
|
-
else:
|
|
109
|
+
if _is_valid_python_marker(path):
|
|
128
110
|
return True
|
|
129
111
|
return False
|
|
130
112
|
|
|
131
113
|
|
|
114
|
+
def _is_valid_python_marker(path: Path) -> bool:
|
|
115
|
+
if path.name == "pyproject.toml":
|
|
116
|
+
return _pyproject_has_project_section(path)
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
|
|
132
120
|
def _pyproject_has_project_section(path: Path) -> bool:
|
|
133
121
|
try:
|
|
134
122
|
with path.open("rb") as f:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|