add plugin files
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
__version__ = "1.0.1"
|
||||
|
||||
_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:
|
||||
"""Try to read __version__ from a package __init__.py without importing."""
|
||||
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 to get version from importlib.metadata (pip-installed packages)."""
|
||||
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:
|
||||
"""Try to read version from pyproject.toml ([project] or [tool.poetry] version)."""
|
||||
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:
|
||||
"""Try to read version from package.json."""
|
||||
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:
|
||||
"""Try __version__ in version.py (or similar) in the package dir."""
|
||||
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:
|
||||
"""True if package_dir is the root of a git repo (has .git)."""
|
||||
return (package_dir / ".git").exists()
|
||||
|
||||
|
||||
def get_installed_modules() -> list[dict]:
|
||||
"""
|
||||
List installed custom node modules (directories under custom_nodes with __init__.py)
|
||||
and their version if discoverable.
|
||||
|
||||
Returns a list of {"name": str, "version": str | null} sorted by name.
|
||||
Version is resolved from: __init__.py, importlib.metadata, pyproject.toml,
|
||||
package.json, version.py; if still unknown and the dir is a git repo, "nightly".
|
||||
Does not import custom node code.
|
||||
"""
|
||||
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:
|
||||
"""
|
||||
Build the JSON payload for GET /workflowui/version_info.
|
||||
|
||||
Includes:
|
||||
- workflowui_plugin_version: this plugin's version
|
||||
- installed_custom_nodes: list of { name, version } for each custom node package
|
||||
"""
|
||||
return {
|
||||
"workflowui_plugin_version": __version__,
|
||||
"installed_custom_nodes": get_installed_modules(),
|
||||
}
|
||||
Reference in New Issue
Block a user