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.
- comfy_import_guard-1.0.0/.gitignore +12 -0
- comfy_import_guard-1.0.0/LICENSE +21 -0
- comfy_import_guard-1.0.0/PKG-INFO +304 -0
- comfy_import_guard-1.0.0/README.md +278 -0
- comfy_import_guard-1.0.0/comfy_import_guard/__init__.py +102 -0
- comfy_import_guard-1.0.0/comfy_import_guard/blame.py +184 -0
- comfy_import_guard-1.0.0/comfy_import_guard/cli.py +245 -0
- comfy_import_guard-1.0.0/comfy_import_guard/derive.py +175 -0
- comfy_import_guard-1.0.0/comfy_import_guard/errors.py +21 -0
- comfy_import_guard-1.0.0/comfy_import_guard/extract.py +294 -0
- comfy_import_guard-1.0.0/comfy_import_guard/ledger.py +120 -0
- comfy_import_guard-1.0.0/comfy_import_guard/repo.py +246 -0
- comfy_import_guard-1.0.0/comfy_import_guard/report.py +148 -0
- comfy_import_guard-1.0.0/comfy_import_guard/resolve.py +175 -0
- comfy_import_guard-1.0.0/comfy_import_guard/version.py +31 -0
- comfy_import_guard-1.0.0/icon.svg +16 -0
- comfy_import_guard-1.0.0/ledger.json +32 -0
- comfy_import_guard-1.0.0/pyproject.toml +70 -0
- comfy_import_guard-1.0.0/tests/conftest.py +27 -0
- comfy_import_guard-1.0.0/tests/packs/ancient_pack/__init__.py +6 -0
- comfy_import_guard-1.0.0/tests/packs/recent_pack/__init__.py +9 -0
- comfy_import_guard-1.0.0/tests/test_derive.py +119 -0
- comfy_import_guard-1.0.0/tests/test_extract.py +182 -0
- comfy_import_guard-1.0.0/tests/test_known_breakages.py +274 -0
|
@@ -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
|
+
[](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
|
+
[](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
|