Skip to content

Commit e1037b0

Browse files
committed
amélioration analyser de deps
1 parent 6cd0987 commit e1037b0

1 file changed

Lines changed: 131 additions & 23 deletions

File tree

Core/deps_analyser/analyser.py

Lines changed: 131 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,110 @@ def _is_stdlib_module(module_name: str) -> bool:
181181
return False
182182

183183

184+
def _normalize_realpath(path: str | None) -> str:
185+
if not path:
186+
return ""
187+
try:
188+
return os.path.realpath(path)
189+
except Exception:
190+
return path
191+
192+
193+
def _is_path_under(path: str, root: str) -> bool:
194+
if not path or not root:
195+
return False
196+
try:
197+
return os.path.commonpath([path, root]) == root
198+
except Exception:
199+
return False
200+
201+
202+
def _collect_workspace_module_roots(
203+
filtered_files: list[str], workspace_dir: str | None
204+
) -> set[str]:
205+
"""
206+
Build a conservative set of internal module roots from workspace files.
207+
Handles common src-layout aliases (src/, lib/, python/).
208+
"""
209+
roots: set[str] = set()
210+
ws = _normalize_realpath(workspace_dir)
211+
src_aliases = {"src", "lib", "python"}
212+
for f in filtered_files:
213+
try:
214+
abs_f = _normalize_realpath(f)
215+
base = os.path.splitext(os.path.basename(abs_f))[0]
216+
if base and base != "__init__":
217+
roots.add(base)
218+
if not ws or not _is_path_under(abs_f, ws):
219+
continue
220+
rel = os.path.relpath(abs_f, ws)
221+
parts = rel.split(os.sep)
222+
if not parts:
223+
continue
224+
first = parts[0]
225+
if first and first not in {"", ".", "__pycache__"}:
226+
roots.add(first)
227+
if first in src_aliases and len(parts) > 1:
228+
second = parts[1]
229+
if second and second not in {"", ".", "__pycache__"}:
230+
roots.add(second)
231+
except Exception:
232+
pass
233+
return roots
234+
235+
236+
@functools.lru_cache(maxsize=1024)
237+
def _classify_module_origin(module_name: str, workspace_dir: str) -> str:
238+
"""
239+
Classify module origin:
240+
- stdlib: Python standard library / builtins
241+
- internal: module resolved under workspace_dir
242+
- third_party: resolved in site-packages/purelib/platlib/dist-packages
243+
- unknown: cannot resolve safely
244+
"""
245+
if not module_name:
246+
return "unknown"
247+
if _is_stdlib_module(module_name):
248+
return "stdlib"
249+
try:
250+
import importlib.util
251+
import sysconfig
252+
253+
ws = _normalize_realpath(workspace_dir)
254+
spec = importlib.util.find_spec(module_name)
255+
if spec is None:
256+
return "unknown"
257+
origin = getattr(spec, "origin", None)
258+
if origin in ("built-in", "frozen"):
259+
return "stdlib"
260+
261+
candidates: list[str] = []
262+
if origin:
263+
candidates.append(_normalize_realpath(origin))
264+
for loc in spec.submodule_search_locations or []:
265+
candidates.append(_normalize_realpath(loc))
266+
267+
stdlib_path = _normalize_realpath(sysconfig.get_path("stdlib") or "")
268+
purelib_path = _normalize_realpath(sysconfig.get_path("purelib") or "")
269+
platlib_path = _normalize_realpath(sysconfig.get_path("platlib") or "")
270+
271+
for c in candidates:
272+
if ws and _is_path_under(c, ws):
273+
return "internal"
274+
if stdlib_path and _is_path_under(c, stdlib_path):
275+
return "stdlib"
276+
if purelib_path and _is_path_under(c, purelib_path):
277+
return "third_party"
278+
if platlib_path and _is_path_under(c, platlib_path):
279+
return "third_party"
280+
if "site-packages" in c or "dist-packages" in c:
281+
return "third_party"
282+
283+
return "unknown"
284+
except Exception:
285+
return "unknown"
286+
287+
184288
def _check_module_installed(module: str) -> bool:
185289
"""
186290
Vérifie si un module est installé via importlib.metadata (plus rPluginsde que subprocess pip show).
@@ -431,35 +535,39 @@ def _t(_key: str, fr: str, en: str) -> str:
431535
if analysis_progress:
432536
analysis_progress.set_message(self.tr("Analyse terminée", "Analysis completed"))
433537
analysis_progress.set_progress(len(filtered_files), len(filtered_files))
434-
# Exclure les modules standards Python (stdlib)
435-
import sys
436-
import sysconfig
437-
438-
stdlib = set(sys.builtin_module_names)
439-
# Ajoute les modules de la vraie stdlib (trouvés dans le dossier stdlib)
440-
stdlib_paths = [sysconfig.get_path("stdlib")]
441-
try:
442-
import pkgutil
443-
444-
for finder, name, ispkg in pkgutil.iter_modules(stdlib_paths):
445-
stdlib.add(name)
446-
except Exception:
447-
pass
448-
# Exclure les modules internes du projet (présents dans le workspace)
449-
internal_modules = set()
450-
for f in filtered_files:
451-
base = os.path.splitext(os.path.basename(f))[0]
452-
internal_modules.add(base)
538+
# Classify imports as stdlib/internal/third-party/unknown.
539+
ws_root = _normalize_realpath(getattr(self, "workspace_dir", None) or "")
540+
internal_modules = _collect_workspace_module_roots(filtered_files, ws_root)
453541
# Mise à jour du message de progression
454542
if analysis_progress:
455543
analysis_progress.set_message(
456544
self.tr("Vérification des modules...", "Checking modules...")
457545
)
458546

459-
# Liste des modules à vérifier (hors standard et hors modules internes)
460-
suggestions = [
461-
m for m in modules if not _is_stdlib_module(m) and m not in internal_modules
462-
]
547+
suggestions = []
548+
category_stats = {"stdlib": 0, "internal": 0, "third_party": 0, "unknown": 0}
549+
for m in sorted(modules):
550+
if m in internal_modules:
551+
category = "internal"
552+
else:
553+
category = _classify_module_origin(m, ws_root)
554+
if category == "unknown" and m in internal_modules:
555+
category = "internal"
556+
category_stats[category] = category_stats.get(category, 0) + 1
557+
if category in ("third_party", "unknown"):
558+
suggestions.append(m)
559+
560+
try:
561+
_log_append(
562+
self,
563+
"ℹ️ Imports classes: "
564+
f"stdlib={category_stats.get('stdlib', 0)}, "
565+
f"internal={category_stats.get('internal', 0)}, "
566+
f"third_party={category_stats.get('third_party', 0)}, "
567+
f"unknown={category_stats.get('unknown', 0)}",
568+
)
569+
except Exception:
570+
pass
463571
# Alerte spéciale pour tkinter (std lib optionnelle non installable via pip)
464572
try:
465573
import importlib.util as _il_util

0 commit comments

Comments
 (0)