- Rename py/ directory to meld/ to eliminate PyPI 'py' package shadowing, which required conftest.py/path.py workarounds in the test suite - Remove meld/path.py (pytest stub no longer needed after rename) - Empty meld/__init__.py (removed redundant 'from . import path as path') - Replace 87-line conftest.py monkeypatch with minimal Package.setup() shim - Extract create_schema(cursor) from schema.py as single DDL source of truth, called by both init_db() and test helpers - Add permanent_delete, soft_delete, soft_delete_to_trash, restore_image, restore_image_with_rename, and collect_deleted_ancestors to repository.py to eliminate duplicated inline SQL across router.py and importer/service.py - Update all import paths, pyproject.toml, Makefile, CI config, and check_scripts to reference meld/ instead of py/
204 lines
4.1 KiB
Python
204 lines
4.1 KiB
Python
import ast
|
|
import os
|
|
import sys
|
|
|
|
from .abstract_check import ASTChecker # pyre-ignore[21]
|
|
|
|
# Allowed packages list from original check_dependencies.py
|
|
ALLOWED_PACKAGES = {
|
|
# Python Standard Library (Major ones)
|
|
"ast",
|
|
"os",
|
|
"sys",
|
|
"asyncio",
|
|
"json",
|
|
"logging",
|
|
"shutil",
|
|
"threading",
|
|
"time",
|
|
"typing",
|
|
"dataclasses",
|
|
"hashlib",
|
|
"re",
|
|
"datetime",
|
|
"fnmatch",
|
|
"random",
|
|
"collections",
|
|
"difflib",
|
|
"unittest",
|
|
"tempfile",
|
|
"abc",
|
|
"inspect",
|
|
"pathlib",
|
|
"sqlite3",
|
|
"base64",
|
|
"io",
|
|
"math",
|
|
"copy",
|
|
"itertools",
|
|
"functools",
|
|
"enum",
|
|
"struct",
|
|
"pickle",
|
|
"uuid",
|
|
"warnings",
|
|
"weakref",
|
|
"glob",
|
|
"cgi",
|
|
"contextlib",
|
|
"bisect",
|
|
"heapq",
|
|
"array",
|
|
"queue",
|
|
"concurrent",
|
|
"subprocess",
|
|
"socket",
|
|
"select",
|
|
"signal",
|
|
"errno",
|
|
"traceback",
|
|
"linecache",
|
|
"tokenize",
|
|
"token",
|
|
"keyword",
|
|
"operator",
|
|
"types",
|
|
"mimetypes",
|
|
"urllib",
|
|
"http",
|
|
"ftplib",
|
|
"poplib",
|
|
"imaplib",
|
|
"smtplib",
|
|
"telnetlib",
|
|
"nntplib",
|
|
"xml",
|
|
"html",
|
|
"csv",
|
|
"configparser",
|
|
"netrc",
|
|
"xdrlib",
|
|
"plistlib",
|
|
"hmac",
|
|
"secrets",
|
|
"multiprocessing",
|
|
"platform",
|
|
"resource",
|
|
"syslog",
|
|
"posix",
|
|
"pwd",
|
|
"grp",
|
|
"termios",
|
|
"tty",
|
|
"pty",
|
|
"fcntl",
|
|
"pipes",
|
|
"getpass",
|
|
"curses",
|
|
"dbm",
|
|
"gdbm",
|
|
# ComfyUI related
|
|
"folder_paths",
|
|
"server",
|
|
"comfy",
|
|
"nodes",
|
|
"node_helpers",
|
|
"execution",
|
|
"app",
|
|
"api",
|
|
"main",
|
|
"cli_args",
|
|
# ComfyUI prerequisite packages
|
|
"torch",
|
|
"torchsde",
|
|
"torchvision",
|
|
"torchaudio",
|
|
"numpy",
|
|
"PIL",
|
|
"aiohttp",
|
|
"yarl",
|
|
"yaml",
|
|
"tqdm",
|
|
"requests",
|
|
"psutil",
|
|
"einops",
|
|
"transformers",
|
|
"tokenizers",
|
|
"sentencepiece",
|
|
"safetensors",
|
|
"alembic",
|
|
"sqlalchemy",
|
|
"av",
|
|
"kornia",
|
|
"spandrel",
|
|
"pydantic",
|
|
"git",
|
|
"github",
|
|
"nio",
|
|
"huggingface_hub",
|
|
"typer",
|
|
"rich",
|
|
"typing_extensions",
|
|
"toml",
|
|
"uv",
|
|
"chardet",
|
|
# Allowed external dependencies in requirements.txt
|
|
"imagehash",
|
|
"scipy",
|
|
"pywt",
|
|
"zipfile",
|
|
}
|
|
|
|
|
|
class DependencyChecker(ASTChecker):
|
|
def __init__(self, file_path: str) -> None:
|
|
super().__init__(file_path)
|
|
self.found_imports: set[str] = set()
|
|
|
|
def get_target_files(self) -> list[str]:
|
|
# Logic to find all .py files in py/ and root __init__.py
|
|
targets = []
|
|
for root, _, files in os.walk("meld"):
|
|
if any(x in root for x in ["node_modules", ".git", "__pycache__"]):
|
|
continue
|
|
for file in files:
|
|
if file.endswith(".py"):
|
|
targets.append(os.path.join(root, file))
|
|
|
|
if os.path.exists("__init__.py"):
|
|
targets.append("__init__.py")
|
|
return targets
|
|
|
|
def visit_Import(self, node: ast.Import) -> None:
|
|
for n in node.names:
|
|
self._check_import(n.name, node.lineno)
|
|
self.generic_visit(node)
|
|
|
|
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
|
|
if node.level == 0 and node.module:
|
|
module: str = node.module
|
|
self._check_import(module, node.lineno)
|
|
self.generic_visit(node)
|
|
|
|
def _check_import(self, module_name: str, lineno: int) -> None:
|
|
imp = module_name.split(".")[0]
|
|
# Allow self-referencing modules
|
|
if imp == "meld" or imp == "":
|
|
return
|
|
|
|
if imp not in ALLOWED_PACKAGES and not self._is_standard_library(imp):
|
|
# Dynamic check for standard library
|
|
try:
|
|
import importlib.util
|
|
|
|
spec = importlib.util.find_spec(imp)
|
|
if spec and (spec.origin == "built-in" or "lib/python" in (spec.origin or "")):
|
|
return
|
|
except (ImportError, ValueError):
|
|
pass
|
|
|
|
self.add_error(lineno, f"Unallowed dependency found: '{imp}'")
|
|
|
|
def _is_standard_library(self, module_name: str) -> bool:
|
|
return module_name in sys.builtin_module_names
|