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:
Vito Sansevero
2026-10-08 18:01:34 -07:00
parent 6c7e4d5b35
commit 5093cb213f
8 changed files with 127 additions and 33 deletions
+3
View File
@@ -14,6 +14,9 @@ omit =
*/node_modules/*
*/static/*
*/media/*
*/htmlcov/*
restart_gallery.py
standalone_tagger.py
branch = true
parallel = true
+4
View File
@@ -0,0 +1,4 @@
[flake8]
max-line-length = 88
extend-ignore = E203, W503
exclude = reference/, .git, __pycache__, web/, venv/, htmlcov/, build/, dist/
+6
View File
@@ -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/
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+100
View File
@@ -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()