chore: valid packaging metadata, flake8 config file, ignore local config with secrets
pyproject.toml carried requirements.txt comment lines as dependencies, which fails PEP 508 parsing. flake8 never read [tool.flake8] from pyproject, so the settings move to .flake8 and pre-commit runs the full rule set. config.json (holds the CivitAI API key and machine paths) and other local artifacts are now ignored. coverage joins the dev requirements.
This commit is contained in:
@@ -14,6 +14,9 @@ omit =
|
||||
*/node_modules/*
|
||||
*/static/*
|
||||
*/media/*
|
||||
*/htmlcov/*
|
||||
restart_gallery.py
|
||||
standalone_tagger.py
|
||||
|
||||
branch = true
|
||||
parallel = true
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = E203, W503
|
||||
exclude = reference/, .git, __pycache__, web/, venv/, htmlcov/, build/, dist/
|
||||
@@ -9,6 +9,12 @@ AGENTS.md
|
||||
CLAUDE.md
|
||||
|
||||
# Local files
|
||||
# Local PromptManager state (config.json holds API keys and machine paths)
|
||||
config.json
|
||||
resume.sh
|
||||
*.backup_*
|
||||
promptmanager_logs/
|
||||
custom_data/
|
||||
data/
|
||||
docs/
|
||||
logs/
|
||||
|
||||
@@ -9,7 +9,7 @@ repos:
|
||||
|
||||
- id: flake8
|
||||
name: flake8
|
||||
entry: flake8 --select=E9,F63,F7,F82 --show-source --exclude=reference/,web/
|
||||
entry: flake8 --show-source
|
||||
language: system
|
||||
types: [python]
|
||||
|
||||
|
||||
+6
-6
@@ -3,7 +3,12 @@ name = "promptmanager"
|
||||
description = "A powerful ComfyUI custom node that extends the standard text encoder with persistent prompt storage, advanced search capabilities, and an automatic image gallery system using SQLite."
|
||||
version = "3.2.4"
|
||||
license = {file = "LICENSE"}
|
||||
dependencies = ["# Core dependencies for PromptManager", "# Note: Most dependencies are already included with ComfyUI", "# Already included with Python standard library:", "# - sqlite3", "# - hashlib", "# - json", "# - datetime", "# - os", "# - typing", "# - threading", "# - uuid", "# Required for gallery functionality:", "watchdog>=2.1.0 # For file system monitoring", "Pillow>=8.0.0 # For image metadata extraction (usually included with ComfyUI)", "# Optional dependencies for enhanced search functionality:", "# fuzzywuzzy[speedup]>=0.18.0 # For fuzzy string matching (optional)", "# sqlalchemy>=1.4.0 # For advanced ORM features (optional)", "# Development dependencies (optional):", "# pytest>=6.0.0 # For running tests", "# black>=22.0.0 # For code formatting", "# flake8>=4.0.0 # For linting", "# mypy>=0.910 # For type checking"]
|
||||
requires-python = ">=3.10"
|
||||
dependencies = ["watchdog>=2.1.0", "Pillow>=8.0.0"]
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=61"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/ComfyAssets/ComfyUI_PromptManager"
|
||||
@@ -18,10 +23,5 @@ Icon = "https://avatars.githubusercontent.com/u/213204677?s=200"
|
||||
line-length = 88
|
||||
target-version = ["py310"]
|
||||
|
||||
[tool.flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = ["E203", "W503"]
|
||||
exclude = ["reference/", ".git", "__pycache__", "web/", "venv/"]
|
||||
|
||||
[tool.bandit]
|
||||
exclude_dirs = ["tests", "reference"]
|
||||
|
||||
@@ -3,6 +3,9 @@ watchdog>=2.1.0
|
||||
Pillow>=8.0.0
|
||||
aiohttp>=3.8.0
|
||||
|
||||
# Tests and coverage
|
||||
coverage>=7.0
|
||||
|
||||
# Code quality
|
||||
black>=24.0.0
|
||||
flake8>=7.0.0
|
||||
|
||||
+4
-26
@@ -1,26 +1,4 @@
|
||||
# Core dependencies for PromptManager
|
||||
# Note: Most dependencies are already included with ComfyUI
|
||||
|
||||
# Already included with Python standard library:
|
||||
# - sqlite3
|
||||
# - hashlib
|
||||
# - json
|
||||
# - datetime
|
||||
# - os
|
||||
# - typing
|
||||
# - threading
|
||||
# - uuid
|
||||
|
||||
# Required for gallery functionality:
|
||||
watchdog>=2.1.0 # For file system monitoring
|
||||
Pillow>=8.0.0 # For image metadata extraction (usually included with ComfyUI)
|
||||
|
||||
# Optional dependencies for enhanced search functionality:
|
||||
# fuzzywuzzy[speedup]>=0.18.0 # For fuzzy string matching (optional)
|
||||
# sqlalchemy>=1.4.0 # For advanced ORM features (optional)
|
||||
|
||||
# Development dependencies (optional):
|
||||
# pytest>=6.0.0 # For running tests
|
||||
# black>=22.0.0 # For code formatting
|
||||
# flake8>=4.0.0 # For linting
|
||||
# mypy>=0.910 # For type checking
|
||||
# Runtime dependencies for PromptManager.
|
||||
# aiohttp, numpy and torch come from ComfyUI itself and are not listed here.
|
||||
watchdog>=2.1.0 # Output directory monitoring
|
||||
Pillow>=8.0.0 # Image metadata extraction and thumbnails
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
"""Packaging and repository hygiene contracts.
|
||||
|
||||
These guard the metadata that ComfyUI-Manager, the Comfy Registry and
|
||||
``pip install .`` consume, and the ignore rules that keep local secrets
|
||||
(``config.json`` holds the CivitAI API key) out of the repository.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import unittest
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# PEP 508 requirement: name, optional extras, optional version spec.
|
||||
_VERSION_CLAUSE = r"[<>=!~]=?\s*[A-Za-z0-9.*+!-]+\s*"
|
||||
_REQUIREMENT = re.compile(
|
||||
r"^[A-Za-z0-9][A-Za-z0-9._-]*" # distribution name
|
||||
r"(\[[A-Za-z0-9,._-]+\])?\s*" # optional extras
|
||||
r"(" + _VERSION_CLAUSE + r"(,\s*" + _VERSION_CLAUSE + r")*)?$" # version spec
|
||||
)
|
||||
|
||||
|
||||
def _read(name):
|
||||
with open(os.path.join(ROOT, name), encoding="utf-8") as fh:
|
||||
return fh.read()
|
||||
|
||||
|
||||
def _pyproject():
|
||||
try:
|
||||
import tomllib # Python 3.11+
|
||||
except ImportError: # pragma: no cover - exercised on 3.10 only
|
||||
tomllib = None
|
||||
text = _read("pyproject.toml")
|
||||
if tomllib is not None:
|
||||
return tomllib.loads(text)
|
||||
# Minimal fallback for 3.10: pull the dependency list out with a regex.
|
||||
match = re.search(r"dependencies\s*=\s*\[(.*?)\]", text, re.S)
|
||||
deps = re.findall(r'"([^"]*)"', match.group(1)) if match else []
|
||||
return {
|
||||
"project": {
|
||||
"dependencies": deps,
|
||||
"requires-python": (
|
||||
re.search(r'requires-python\s*=\s*"([^"]+)"', text).group(1)
|
||||
if "requires-python" in text
|
||||
else None
|
||||
),
|
||||
},
|
||||
"build-system": {} if "[build-system]" in text else None,
|
||||
}
|
||||
|
||||
|
||||
class PyprojectContract(unittest.TestCase):
|
||||
def test_dependencies_are_valid_requirements(self):
|
||||
deps = _pyproject()["project"]["dependencies"]
|
||||
self.assertTrue(deps, "dependencies must not be empty")
|
||||
for dep in deps:
|
||||
self.assertRegex(dep, _REQUIREMENT, f"not a PEP 508 requirement: {dep!r}")
|
||||
|
||||
def test_dependencies_match_requirements_txt(self):
|
||||
deps = set(_pyproject()["project"]["dependencies"])
|
||||
wanted = {
|
||||
line.split("#", 1)[0].strip()
|
||||
for line in _read("requirements.txt").splitlines()
|
||||
if line.split("#", 1)[0].strip()
|
||||
}
|
||||
self.assertEqual(deps, wanted)
|
||||
|
||||
def test_requires_python_floor_is_3_10(self):
|
||||
self.assertEqual(_pyproject()["project"]["requires-python"], ">=3.10")
|
||||
|
||||
def test_build_system_is_declared(self):
|
||||
self.assertIsNotNone(_pyproject().get("build-system"))
|
||||
|
||||
|
||||
class IgnoreRulesContract(unittest.TestCase):
|
||||
def test_local_secrets_and_artifacts_are_ignored(self):
|
||||
patterns = {
|
||||
line.strip()
|
||||
for line in _read(".gitignore").splitlines()
|
||||
if line.strip() and not line.startswith("#")
|
||||
}
|
||||
for required in (
|
||||
"config.json",
|
||||
"resume.sh",
|
||||
"*.backup_*",
|
||||
"promptmanager_logs/",
|
||||
):
|
||||
self.assertIn(required, patterns)
|
||||
|
||||
|
||||
class LintConfigContract(unittest.TestCase):
|
||||
def test_flake8_reads_its_own_config_file(self):
|
||||
# flake8 ignores pyproject.toml, so the settings must live in .flake8.
|
||||
text = _read(".flake8")
|
||||
self.assertIn("max-line-length = 88", text)
|
||||
self.assertIn("E203", text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user