Files

121 lines
3.5 KiB
Python

from __future__ import annotations
import json
import re
from pathlib import Path
__version__ = "1.0.11"
_PLUGIN_DIR = Path(__file__).resolve().parent
_CUSTOM_NODES_DIR = _PLUGIN_DIR.parent
_VERSION_RE = re.compile(r'__version__\s*=\s*["\']([^"\']+)["\']')
_PYPROJECT_VERSION_RE = re.compile(r'^\s*version\s*=\s*["\']([^"\']+)["\']', re.MULTILINE)
def _version_from_init_py(init_path: Path) -> str | None:
if not init_path.is_file():
return None
try:
text = init_path.read_text(encoding="utf-8", errors="replace")
m = _VERSION_RE.search(text)
return m.group(1).strip() if m else None
except Exception:
return None
def _version_from_metadata(package_name: str) -> str | None:
try:
from importlib.metadata import version
for name in (package_name, package_name.replace("_", "-"), package_name.replace("-", "_")):
try:
return version(name)
except Exception:
continue
except Exception:
pass
return None
def _version_from_pyproject_toml(package_dir: Path) -> str | None:
path = package_dir / "pyproject.toml"
if not path.is_file():
return None
try:
text = path.read_text(encoding="utf-8", errors="replace")
for m in _PYPROJECT_VERSION_RE.finditer(text):
return m.group(1).strip()
except Exception:
pass
return None
def _version_from_package_json(package_dir: Path) -> str | None:
path = package_dir / "package.json"
if not path.is_file():
return None
try:
data = json.loads(path.read_text(encoding="utf-8", errors="replace"))
if isinstance(data.get("version"), str) and data["version"].strip():
return data["version"].strip()
except Exception:
pass
return None
def _version_from_version_file(package_dir: Path) -> str | None:
for name in ("version.py", "version.json"):
path = package_dir / name
if not path.is_file():
continue
try:
text = path.read_text(encoding="utf-8", errors="replace")
if name.endswith(".json"):
data = json.loads(text)
if isinstance(data.get("version"), str) and data["version"].strip():
return data["version"].strip()
else:
m = _VERSION_RE.search(text)
if m:
return m.group(1).strip()
except Exception:
pass
return None
def _is_git_repo(package_dir: Path) -> bool:
return (package_dir / ".git").exists()
def get_installed_modules() -> list[dict]:
result: list[dict] = []
if not _CUSTOM_NODES_DIR.is_dir():
return result
for path in sorted(_CUSTOM_NODES_DIR.iterdir()):
if not path.is_dir():
continue
init_py = path / "__init__.py"
if not init_py.is_file():
continue
name = path.name
version = (
_version_from_init_py(init_py)
or _version_from_metadata(name)
or _version_from_pyproject_toml(path)
or _version_from_package_json(path)
or _version_from_version_file(path)
)
if version is None and _is_git_repo(path):
version = "nightly"
result.append({"name": name, "version": version})
return result
def get_version_info_payload() -> dict:
return {
"workflowui_plugin_version": __version__,
"installed_custom_nodes": get_installed_modules(),
}