comfy-import-guard 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .venv/
7
+ venv/
8
+ .pytest_cache/
9
+ .coverage
10
+ htmlcov/
11
+ *.json.tmp
12
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Booyaka101
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,304 @@
1
+ Metadata-Version: 2.5
2
+ Name: comfy-import-guard
3
+ Version: 1.0.0
4
+ Summary: Predict and attribute ComfyUI custom-node import breakage caused by removals in comfy.* internals.
5
+ Project-URL: Repository, https://github.com/Booyaka101/comfy-import-guard
6
+ Project-URL: Issues, https://github.com/Booyaka101/comfy-import-guard/issues
7
+ Author: Booyaka101
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: ast,breaking-changes,comfyui,compatibility,custom-nodes,import-error,static-analysis
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Multimedia :: Graphics
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Requires-Python: >=3.10
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # comfy-import-guard
28
+
29
+ [![tests](https://github.com/Booyaka101/comfy-import-guard/actions/workflows/test.yml/badge.svg)](https://github.com/Booyaka101/comfy-import-guard/actions/workflows/test.yml)
30
+
31
+ Predicts which of your ComfyUI custom-node packs will die on the next `git pull`,
32
+ and names the commit and PR that killed them.
33
+
34
+ Zero third-party dependencies. It has to load inside a ComfyUI whose other packs
35
+ are already broken, so it uses nothing but the standard library and `git`.
36
+
37
+ ## The problem
38
+
39
+ ComfyUI's `comfy.*` modules are internal. There is no deprecation policy, no
40
+ `__all__`, no shim. Packs import from them anyway, because there is no other way
41
+ to hook the sampler or patch a model. So a refactor lands and a pack stops loading:
42
+
43
+ ```
44
+ ImportError: cannot import name 'precompute_freqs_cis' from 'comfy.ldm.lightricks.model'
45
+ ```
46
+
47
+ That one broke ComfyUI-TeaCache and ComfyUI-MagCache on 2026-01-05
48
+ ([Comfy-Org/ComfyUI#11660](https://github.com/Comfy-Org/ComfyUI/issues/11660), still open).
49
+ The same shape hit `comfy.ldm.minimax.model.time_shift_slope` on 2026-08-06
50
+ ([T8mars/comfyui-minimax-h3-blockcache-T8#1](https://github.com/T8mars/comfyui-minimax-h3-blockcache-T8/issues/1)).
51
+
52
+ You find out when the console scrolls past at startup. This tells you before.
53
+
54
+ **Why grep does not work here.** PR #11632 deleted the module-level
55
+ `def precompute_freqs_cis(...)` and added a private `_precompute_freqs_cis`
56
+ *method* on the model class. The string `precompute_freqs_cis` still appears
57
+ twice in that file on master today. Any substring or grep-based checker reports
58
+ SAFE and is wrong. comfy-import-guard builds the importable-name set from
59
+ top-level `ast.FunctionDef` / `AsyncFunctionDef` / `ClassDef` / `Assign` /
60
+ `AnnAssign` / `ImportFrom` nodes only, so a function demoted to a method or
61
+ renamed with a leading underscore is correctly reported as gone.
62
+
63
+ ## Install
64
+
65
+ ```bash
66
+ pip install comfy-import-guard
67
+ ```
68
+
69
+ Or as a ComfyUI node pack (it registers zero nodes; it adds one read-only
70
+ report route):
71
+
72
+ ```bash
73
+ cd ComfyUI/custom_nodes
74
+ git clone https://github.com/Booyaka101/comfy-import-guard
75
+ ```
76
+
77
+ Needs Python 3.10+ and `git` on PATH. On first use it clones ComfyUI
78
+ (~1 min, anonymous, no token) into a cache directory:
79
+
80
+ | platform | default cache |
81
+ | --- | --- |
82
+ | Windows | `%LOCALAPPDATA%\comfy-import-guard\cache` |
83
+ | Linux / macOS | `$XDG_CACHE_HOME/comfy-import-guard` or `~/.cache/comfy-import-guard` |
84
+
85
+ Override with `--cache-dir` or `COMFY_IMPORT_GUARD_CACHE`.
86
+
87
+ ## Usage
88
+
89
+ ### `check`: will my install survive the next update?
90
+
91
+ ```
92
+ $ comfy-import-guard check --comfy-dir D:/ComfyUI_windows_portable/ComfyUI
93
+ comfy-import-guard check
94
+ install : D:\ComfyUI_windows_portable\ComfyUI\custom_nodes
95
+ target : origin/master (bd34f338a)
96
+
97
+ [ok] comfyui_controlnet_aux SAFE
98
+ 667 python file(s), 86 comfy.* reference(s)
99
+
100
+ 1 pack(s): 0 will break, 1 safe, 0 warn, 0 skipped; 0 missing symbol(s)
101
+ ```
102
+
103
+ Against a set of packs with real breakage:
104
+
105
+ ```
106
+ $ comfy-import-guard check --comfy-dir /scratch/comfy
107
+ comfy-import-guard check
108
+ install : /scratch/comfy/custom_nodes
109
+ target : origin/master (bd34f338a)
110
+
111
+ [!!] ComfyUI-MagCache WILL BREAK
112
+ 3 python file(s), 21 comfy.* reference(s)
113
+ MISSING comfy.ldm.lightricks.model.precompute_freqs_cis
114
+ nodes.py:13 (from)
115
+ removed by f2b002372 in PR #11632 on 2026-01-05
116
+ last good v0.7.0, first bad v0.8.0
117
+ MISSING comfy.ldm.lightricks.model.precompute_freqs_cis
118
+ nodes_calibration.py:13 (from)
119
+ removed by f2b002372 in PR #11632 on 2026-01-05
120
+ last good v0.7.0, first bad v0.8.0
121
+
122
+ [!!] ComfyUI-TeaCache WILL BREAK
123
+ 8 python file(s), 12 comfy.* reference(s)
124
+ MISSING comfy.ldm.lightricks.model.precompute_freqs_cis
125
+ nodes.py:12 (from)
126
+ removed by f2b002372 in PR #11632 on 2026-01-05
127
+ last good v0.7.0, first bad v0.8.0
128
+
129
+ [??] comfyui-minimax-h3-blockcache-T8 WARN
130
+ 5 python file(s), 25 comfy.* reference(s)
131
+ SOFT comfy.ldm.minimax.model.time_shift_slope nodes.py:15 (guarded by try/except)
132
+ note: 1 guarded import(s) that would fail
133
+
134
+ 3 pack(s): 2 will break, 0 safe, 1 warn, 0 skipped; 3 missing symbol(s)
135
+ Run `comfy-import-guard blame <module.Symbol>` for the commit that removed it.
136
+ ```
137
+
138
+ Exit code is 1 when anything will break, so it drops straight into CI.
139
+
140
+ `--target` takes any ref: a tag (`v0.31.0`), a sha, or `origin/master` (default).
141
+ Check what a specific update will do to you before you take it.
142
+
143
+ ### `blame`: who removed this symbol?
144
+
145
+ ```
146
+ $ comfy-import-guard blame comfy.ldm.minimax.model.time_shift_slope
147
+ comfy.ldm.minimax.model.time_shift_slope
148
+ (from ledger; pass --no-ledger to re-derive from git)
149
+ removed in : bdcb886a4
150
+ commit : Fix sampler issues for audio with minimax, support more samplers. (#15243)
151
+ pull request : Comfy-Org/ComfyUI#15243
152
+ https://github.com/comfyanonymous/ComfyUI/pull/15243
153
+ removed on : 2026-08-06T13:36:34-07:00
154
+ last good tag : v0.30.2
155
+ first bad tag : v0.31.0
156
+ known packs : comfyui-minimax-h3-blockcache-T8
157
+ ```
158
+
159
+ The shipped `ledger.json` answers instantly and offline for known removals.
160
+ Anything not in it is derived from git and can be written back with `--record`:
161
+
162
+ ```
163
+ $ comfy-import-guard blame comfy.ldm.lightricks.model.precompute_freqs_cis --no-ledger
164
+ comfy.ldm.lightricks.model.precompute_freqs_cis
165
+ removed in : f2b002372
166
+ commit : Support the LTXV 2 model. (#11632)
167
+ pull request : Comfy-Org/ComfyUI#11632
168
+ https://github.com/comfyanonymous/ComfyUI/pull/11632
169
+ removed on : 2026-01-05T01:58:59-05:00
170
+ last good tag : v0.7.0
171
+ first bad tag : v0.8.0
172
+ introduced in : 5e16f1d24 (2024-11-22)
173
+ ```
174
+
175
+ ### `derive-requires`: what should my pyproject claim?
176
+
177
+ For pack authors. Finds the oldest ComfyUI release in which every symbol your
178
+ pack references already exists, and the first release in which one of them stops
179
+ existing.
180
+
181
+ ```
182
+ $ comfy-import-guard derive-requires ./ComfyUI-TeaCache
183
+ derive-requires: ComfyUI-TeaCache
184
+ 8 python file(s), 11 hard comfy.* reference(s)
185
+ already removed at head:
186
+ comfy.ldm.lightricks.model.precompute_freqs_cis (nodes.py:12)
187
+ floor set by : comfy.ldm.flux.layers.apply_mod
188
+ probed 8 release tag(s)
189
+
190
+ Paste under [tool.comfy] in the pack's pyproject.toml:
191
+
192
+ requires-comfyui = ">=0.3.25,<0.8.0"
193
+ ```
194
+
195
+ The upper bound only appears when the pack references something that is already
196
+ gone. A healthy pack gets a plain floor:
197
+
198
+ ```
199
+ $ comfy-import-guard derive-requires ./tests/packs/recent_pack
200
+ derive-requires: recent_pack
201
+ 1 python file(s), 2 hard comfy.* reference(s)
202
+ floor set by : comfy.ldm.minimax, comfy.ldm.minimax.model
203
+ probed 8 release tag(s)
204
+
205
+ Paste under [tool.comfy] in the pack's pyproject.toml:
206
+
207
+ requires-comfyui = ">=0.30.0"
208
+ ```
209
+
210
+ `requires-comfyui` is the [Comfy Registry field](https://docs.comfy.org/registry/specifications)
211
+ that tells ComfyUI-Manager which ComfyUI versions your node supports.
212
+
213
+ ### HTTP route
214
+
215
+ Installed as a node pack, it adds one read-only route:
216
+
217
+ ```
218
+ GET /comfy_import_guard/report?target=origin/master
219
+ ```
220
+
221
+ It returns the same JSON as `check --json` for the running install. It is
222
+ deliberately offline: it uses whatever clone the CLI already made and never
223
+ downloads anything from inside the server process. If no clone exists yet it
224
+ returns `{"ok": false, "hint": "..."}` telling you which command to run once.
225
+
226
+ ## Configuration
227
+
228
+ | flag | effect |
229
+ | --- | --- |
230
+ | `--comfy-dir` | ComfyUI install root, or a `custom_nodes` directory directly |
231
+ | `--target` | ref to resolve against (tag, sha, `origin/master`) |
232
+ | `--pack NAME` | check only these packs (repeatable) |
233
+ | `--cache-dir` | where the ComfyUI clone lives |
234
+ | `--ledger` | alternate `ledger.json` |
235
+ | `--offline` | never touch the network; answer from the existing clone and the ledger |
236
+ | `--no-update` | skip the `git fetch` before checking |
237
+ | `--json` | machine-readable output for every command |
238
+ | `--quiet` | suppress progress notes on stderr |
239
+
240
+ Global flags work before or after the subcommand.
241
+
242
+ ### Verdicts
243
+
244
+ | verdict | meaning |
245
+ | --- | --- |
246
+ | `SAFE` | every reference resolves at the target ref |
247
+ | `WILL BREAK` | at least one unguarded reference is gone; exit code 1 |
248
+ | `WARN` | only guarded (`try/except ImportError`) references fail, or something could not be resolved statically |
249
+ | `SKIPPED` | the pack vendors its own `comfy/` package, so it resolves pack-locally |
250
+
251
+ ## How it works
252
+
253
+ 1. `ast.walk` every `.py` in each pack. Collect `from comfy.… import x`, plain
254
+ `import comfy.x.y as z` plus attribute chains rooted at those aliases, and
255
+ `getattr(comfy.x, "literal")`.
256
+ 2. `git show <ref>:comfy/…/model.py` for each referenced module, parse it, and
257
+ build the set of names bound at module scope.
258
+ 3. Anything referenced but not bound is a break. `git log -S'\bsymbol\b'
259
+ --pickaxe-regex` finds the commit that changed it; `git tag --contains` turns
260
+ that into a release boundary.
261
+
262
+ Only the public ComfyUI git repository is used. No API, no token, no account.
263
+
264
+ ## Limitations
265
+
266
+ - **Static only.** It never imports a pack and never runs one. A pack that
267
+ builds an import name at runtime out of non-literal strings is invisible to it.
268
+ - **`from comfy.x import *`** is reported as unresolvable, not guessed.
269
+ - **Attribute chains are best-effort.** `comfy.samplers.KSampler.SAMPLERS`
270
+ is checked as far as `KSampler`; class internals are not tracked.
271
+ - **Local shadowing is not modelled.** A local variable that happens to reuse an
272
+ alias name can produce a spurious reference. It shows up as `WARN`/`MISSING`
273
+ with a file and line, so it is cheap to dismiss.
274
+ - **Import success is not load success.** A pack whose imports all resolve can
275
+ still fail on a changed function signature or a changed return type. This tool
276
+ answers the import question only.
277
+ - **Files this interpreter cannot parse are counted and printed**, never
278
+ silently skipped. If you see `UNPARSED`, the pack uses syntax newer than your
279
+ Python and that file was not analysed.
280
+ - **Not a dependency checker.** pip conflicts belong to ComfyUI-Manager. No
281
+ auto-fixing, no runtime import hooks, no model downloads.
282
+
283
+ ## Tests
284
+
285
+ ```bash
286
+ pip install pytest
287
+ python -m pytest tests -q
288
+ ```
289
+
290
+ 59 tests. They assert against live public ComfyUI history rather than recorded
291
+ fixtures: the real commits `f2b002372` and `bdcb886a4`, the real tags
292
+ `v0.7.0`/`v0.8.0` and `v0.30.2`/`v0.31.0`. They need `git` and a one-time clone,
293
+ and skip cleanly if neither is available.
294
+
295
+ ## Publishing
296
+
297
+ `pyproject.toml` is already registry-shaped. Before `comfy node publish`, set
298
+ `[tool.comfy] PublisherId` to your Comfy Registry publisher ID (the placeholder
299
+ is a GitHub handle, not a verified publisher ID) and confirm the `Icon` URL
300
+ resolves once the repo is public.
301
+
302
+ ## License
303
+
304
+ MIT
@@ -0,0 +1,278 @@
1
+ # comfy-import-guard
2
+
3
+ [![tests](https://github.com/Booyaka101/comfy-import-guard/actions/workflows/test.yml/badge.svg)](https://github.com/Booyaka101/comfy-import-guard/actions/workflows/test.yml)
4
+
5
+ Predicts which of your ComfyUI custom-node packs will die on the next `git pull`,
6
+ and names the commit and PR that killed them.
7
+
8
+ Zero third-party dependencies. It has to load inside a ComfyUI whose other packs
9
+ are already broken, so it uses nothing but the standard library and `git`.
10
+
11
+ ## The problem
12
+
13
+ ComfyUI's `comfy.*` modules are internal. There is no deprecation policy, no
14
+ `__all__`, no shim. Packs import from them anyway, because there is no other way
15
+ to hook the sampler or patch a model. So a refactor lands and a pack stops loading:
16
+
17
+ ```
18
+ ImportError: cannot import name 'precompute_freqs_cis' from 'comfy.ldm.lightricks.model'
19
+ ```
20
+
21
+ That one broke ComfyUI-TeaCache and ComfyUI-MagCache on 2026-01-05
22
+ ([Comfy-Org/ComfyUI#11660](https://github.com/Comfy-Org/ComfyUI/issues/11660), still open).
23
+ The same shape hit `comfy.ldm.minimax.model.time_shift_slope` on 2026-08-06
24
+ ([T8mars/comfyui-minimax-h3-blockcache-T8#1](https://github.com/T8mars/comfyui-minimax-h3-blockcache-T8/issues/1)).
25
+
26
+ You find out when the console scrolls past at startup. This tells you before.
27
+
28
+ **Why grep does not work here.** PR #11632 deleted the module-level
29
+ `def precompute_freqs_cis(...)` and added a private `_precompute_freqs_cis`
30
+ *method* on the model class. The string `precompute_freqs_cis` still appears
31
+ twice in that file on master today. Any substring or grep-based checker reports
32
+ SAFE and is wrong. comfy-import-guard builds the importable-name set from
33
+ top-level `ast.FunctionDef` / `AsyncFunctionDef` / `ClassDef` / `Assign` /
34
+ `AnnAssign` / `ImportFrom` nodes only, so a function demoted to a method or
35
+ renamed with a leading underscore is correctly reported as gone.
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ pip install comfy-import-guard
41
+ ```
42
+
43
+ Or as a ComfyUI node pack (it registers zero nodes; it adds one read-only
44
+ report route):
45
+
46
+ ```bash
47
+ cd ComfyUI/custom_nodes
48
+ git clone https://github.com/Booyaka101/comfy-import-guard
49
+ ```
50
+
51
+ Needs Python 3.10+ and `git` on PATH. On first use it clones ComfyUI
52
+ (~1 min, anonymous, no token) into a cache directory:
53
+
54
+ | platform | default cache |
55
+ | --- | --- |
56
+ | Windows | `%LOCALAPPDATA%\comfy-import-guard\cache` |
57
+ | Linux / macOS | `$XDG_CACHE_HOME/comfy-import-guard` or `~/.cache/comfy-import-guard` |
58
+
59
+ Override with `--cache-dir` or `COMFY_IMPORT_GUARD_CACHE`.
60
+
61
+ ## Usage
62
+
63
+ ### `check`: will my install survive the next update?
64
+
65
+ ```
66
+ $ comfy-import-guard check --comfy-dir D:/ComfyUI_windows_portable/ComfyUI
67
+ comfy-import-guard check
68
+ install : D:\ComfyUI_windows_portable\ComfyUI\custom_nodes
69
+ target : origin/master (bd34f338a)
70
+
71
+ [ok] comfyui_controlnet_aux SAFE
72
+ 667 python file(s), 86 comfy.* reference(s)
73
+
74
+ 1 pack(s): 0 will break, 1 safe, 0 warn, 0 skipped; 0 missing symbol(s)
75
+ ```
76
+
77
+ Against a set of packs with real breakage:
78
+
79
+ ```
80
+ $ comfy-import-guard check --comfy-dir /scratch/comfy
81
+ comfy-import-guard check
82
+ install : /scratch/comfy/custom_nodes
83
+ target : origin/master (bd34f338a)
84
+
85
+ [!!] ComfyUI-MagCache WILL BREAK
86
+ 3 python file(s), 21 comfy.* reference(s)
87
+ MISSING comfy.ldm.lightricks.model.precompute_freqs_cis
88
+ nodes.py:13 (from)
89
+ removed by f2b002372 in PR #11632 on 2026-01-05
90
+ last good v0.7.0, first bad v0.8.0
91
+ MISSING comfy.ldm.lightricks.model.precompute_freqs_cis
92
+ nodes_calibration.py:13 (from)
93
+ removed by f2b002372 in PR #11632 on 2026-01-05
94
+ last good v0.7.0, first bad v0.8.0
95
+
96
+ [!!] ComfyUI-TeaCache WILL BREAK
97
+ 8 python file(s), 12 comfy.* reference(s)
98
+ MISSING comfy.ldm.lightricks.model.precompute_freqs_cis
99
+ nodes.py:12 (from)
100
+ removed by f2b002372 in PR #11632 on 2026-01-05
101
+ last good v0.7.0, first bad v0.8.0
102
+
103
+ [??] comfyui-minimax-h3-blockcache-T8 WARN
104
+ 5 python file(s), 25 comfy.* reference(s)
105
+ SOFT comfy.ldm.minimax.model.time_shift_slope nodes.py:15 (guarded by try/except)
106
+ note: 1 guarded import(s) that would fail
107
+
108
+ 3 pack(s): 2 will break, 0 safe, 1 warn, 0 skipped; 3 missing symbol(s)
109
+ Run `comfy-import-guard blame <module.Symbol>` for the commit that removed it.
110
+ ```
111
+
112
+ Exit code is 1 when anything will break, so it drops straight into CI.
113
+
114
+ `--target` takes any ref: a tag (`v0.31.0`), a sha, or `origin/master` (default).
115
+ Check what a specific update will do to you before you take it.
116
+
117
+ ### `blame`: who removed this symbol?
118
+
119
+ ```
120
+ $ comfy-import-guard blame comfy.ldm.minimax.model.time_shift_slope
121
+ comfy.ldm.minimax.model.time_shift_slope
122
+ (from ledger; pass --no-ledger to re-derive from git)
123
+ removed in : bdcb886a4
124
+ commit : Fix sampler issues for audio with minimax, support more samplers. (#15243)
125
+ pull request : Comfy-Org/ComfyUI#15243
126
+ https://github.com/comfyanonymous/ComfyUI/pull/15243
127
+ removed on : 2026-08-06T13:36:34-07:00
128
+ last good tag : v0.30.2
129
+ first bad tag : v0.31.0
130
+ known packs : comfyui-minimax-h3-blockcache-T8
131
+ ```
132
+
133
+ The shipped `ledger.json` answers instantly and offline for known removals.
134
+ Anything not in it is derived from git and can be written back with `--record`:
135
+
136
+ ```
137
+ $ comfy-import-guard blame comfy.ldm.lightricks.model.precompute_freqs_cis --no-ledger
138
+ comfy.ldm.lightricks.model.precompute_freqs_cis
139
+ removed in : f2b002372
140
+ commit : Support the LTXV 2 model. (#11632)
141
+ pull request : Comfy-Org/ComfyUI#11632
142
+ https://github.com/comfyanonymous/ComfyUI/pull/11632
143
+ removed on : 2026-01-05T01:58:59-05:00
144
+ last good tag : v0.7.0
145
+ first bad tag : v0.8.0
146
+ introduced in : 5e16f1d24 (2024-11-22)
147
+ ```
148
+
149
+ ### `derive-requires`: what should my pyproject claim?
150
+
151
+ For pack authors. Finds the oldest ComfyUI release in which every symbol your
152
+ pack references already exists, and the first release in which one of them stops
153
+ existing.
154
+
155
+ ```
156
+ $ comfy-import-guard derive-requires ./ComfyUI-TeaCache
157
+ derive-requires: ComfyUI-TeaCache
158
+ 8 python file(s), 11 hard comfy.* reference(s)
159
+ already removed at head:
160
+ comfy.ldm.lightricks.model.precompute_freqs_cis (nodes.py:12)
161
+ floor set by : comfy.ldm.flux.layers.apply_mod
162
+ probed 8 release tag(s)
163
+
164
+ Paste under [tool.comfy] in the pack's pyproject.toml:
165
+
166
+ requires-comfyui = ">=0.3.25,<0.8.0"
167
+ ```
168
+
169
+ The upper bound only appears when the pack references something that is already
170
+ gone. A healthy pack gets a plain floor:
171
+
172
+ ```
173
+ $ comfy-import-guard derive-requires ./tests/packs/recent_pack
174
+ derive-requires: recent_pack
175
+ 1 python file(s), 2 hard comfy.* reference(s)
176
+ floor set by : comfy.ldm.minimax, comfy.ldm.minimax.model
177
+ probed 8 release tag(s)
178
+
179
+ Paste under [tool.comfy] in the pack's pyproject.toml:
180
+
181
+ requires-comfyui = ">=0.30.0"
182
+ ```
183
+
184
+ `requires-comfyui` is the [Comfy Registry field](https://docs.comfy.org/registry/specifications)
185
+ that tells ComfyUI-Manager which ComfyUI versions your node supports.
186
+
187
+ ### HTTP route
188
+
189
+ Installed as a node pack, it adds one read-only route:
190
+
191
+ ```
192
+ GET /comfy_import_guard/report?target=origin/master
193
+ ```
194
+
195
+ It returns the same JSON as `check --json` for the running install. It is
196
+ deliberately offline: it uses whatever clone the CLI already made and never
197
+ downloads anything from inside the server process. If no clone exists yet it
198
+ returns `{"ok": false, "hint": "..."}` telling you which command to run once.
199
+
200
+ ## Configuration
201
+
202
+ | flag | effect |
203
+ | --- | --- |
204
+ | `--comfy-dir` | ComfyUI install root, or a `custom_nodes` directory directly |
205
+ | `--target` | ref to resolve against (tag, sha, `origin/master`) |
206
+ | `--pack NAME` | check only these packs (repeatable) |
207
+ | `--cache-dir` | where the ComfyUI clone lives |
208
+ | `--ledger` | alternate `ledger.json` |
209
+ | `--offline` | never touch the network; answer from the existing clone and the ledger |
210
+ | `--no-update` | skip the `git fetch` before checking |
211
+ | `--json` | machine-readable output for every command |
212
+ | `--quiet` | suppress progress notes on stderr |
213
+
214
+ Global flags work before or after the subcommand.
215
+
216
+ ### Verdicts
217
+
218
+ | verdict | meaning |
219
+ | --- | --- |
220
+ | `SAFE` | every reference resolves at the target ref |
221
+ | `WILL BREAK` | at least one unguarded reference is gone; exit code 1 |
222
+ | `WARN` | only guarded (`try/except ImportError`) references fail, or something could not be resolved statically |
223
+ | `SKIPPED` | the pack vendors its own `comfy/` package, so it resolves pack-locally |
224
+
225
+ ## How it works
226
+
227
+ 1. `ast.walk` every `.py` in each pack. Collect `from comfy.… import x`, plain
228
+ `import comfy.x.y as z` plus attribute chains rooted at those aliases, and
229
+ `getattr(comfy.x, "literal")`.
230
+ 2. `git show <ref>:comfy/…/model.py` for each referenced module, parse it, and
231
+ build the set of names bound at module scope.
232
+ 3. Anything referenced but not bound is a break. `git log -S'\bsymbol\b'
233
+ --pickaxe-regex` finds the commit that changed it; `git tag --contains` turns
234
+ that into a release boundary.
235
+
236
+ Only the public ComfyUI git repository is used. No API, no token, no account.
237
+
238
+ ## Limitations
239
+
240
+ - **Static only.** It never imports a pack and never runs one. A pack that
241
+ builds an import name at runtime out of non-literal strings is invisible to it.
242
+ - **`from comfy.x import *`** is reported as unresolvable, not guessed.
243
+ - **Attribute chains are best-effort.** `comfy.samplers.KSampler.SAMPLERS`
244
+ is checked as far as `KSampler`; class internals are not tracked.
245
+ - **Local shadowing is not modelled.** A local variable that happens to reuse an
246
+ alias name can produce a spurious reference. It shows up as `WARN`/`MISSING`
247
+ with a file and line, so it is cheap to dismiss.
248
+ - **Import success is not load success.** A pack whose imports all resolve can
249
+ still fail on a changed function signature or a changed return type. This tool
250
+ answers the import question only.
251
+ - **Files this interpreter cannot parse are counted and printed**, never
252
+ silently skipped. If you see `UNPARSED`, the pack uses syntax newer than your
253
+ Python and that file was not analysed.
254
+ - **Not a dependency checker.** pip conflicts belong to ComfyUI-Manager. No
255
+ auto-fixing, no runtime import hooks, no model downloads.
256
+
257
+ ## Tests
258
+
259
+ ```bash
260
+ pip install pytest
261
+ python -m pytest tests -q
262
+ ```
263
+
264
+ 59 tests. They assert against live public ComfyUI history rather than recorded
265
+ fixtures: the real commits `f2b002372` and `bdcb886a4`, the real tags
266
+ `v0.7.0`/`v0.8.0` and `v0.30.2`/`v0.31.0`. They need `git` and a one-time clone,
267
+ and skip cleanly if neither is available.
268
+
269
+ ## Publishing
270
+
271
+ `pyproject.toml` is already registry-shaped. Before `comfy node publish`, set
272
+ `[tool.comfy] PublisherId` to your Comfy Registry publisher ID (the placeholder
273
+ is a GitHub handle, not a verified publisher ID) and confirm the `Icon` URL
274
+ resolves once the repo is public.
275
+
276
+ ## License
277
+
278
+ MIT