from pathlib import Path ALIASES = { "bs4": "beautifulsoup4", "python3-discogs-client": "discogs-client", "typing_extensions": "typing-extensions", } ALLOWLIST = { "httpx-socks", "pysocks", "socksio", } def normalize(pkg: str) -> str: pkg = pkg.strip().lower().replace("_", "-") return ALIASES.get(pkg, pkg) def clean_line(line: str): line = line.strip() if not line: return None if line.startswith("#"): return None if " #" in line: line = line.split(" #", 1)[0].strip() return line def parse_with_versions(data: str): result = {} for raw in data.splitlines(): line = clean_line(raw) if not line: continue name, *version = line.split("==") name = normalize(name) result[name] = version[0] if version else None return result def parse_simple(data: str): result = set() for raw in data.splitlines(): line = clean_line(raw) if not line: continue result.add(normalize(line)) return result base_path = Path(__file__).parent req_new_path = base_path / "requirements.txt" req_old_path = base_path / "requirements-old.txt" if not req_new_path.exists(): raise FileNotFoundError("requirements.txt не найден") if not req_old_path.exists(): raise FileNotFoundError("requirements-old.txt не найден") list1 = req_new_path.read_text(encoding="utf-8") list2 = req_old_path.read_text(encoding="utf-8") a = parse_with_versions(list1) b = parse_simple(list2) a_names = set(a.keys()) only_in_list2 = sorted(b - a_names) only_in_list2_clean = [pkg for pkg in only_in_list2 if pkg not in ALLOWLIST] ignored = [pkg for pkg in only_in_list2 if pkg in ALLOWLIST] print("Только в list1:") print(sorted(a_names - b)) print("\nТолько в list2 (кандидаты на удаление):") print(only_in_list2_clean) print("\nИгнорируемые (allowlist):") print(sorted(ignored)) print("\nПодозрительные дубли (алиасы):") for k, v in ALIASES.items(): if k in a_names: print(f"{k} -> {v}")