comfy-cli icon indicating copy to clipboard operation
comfy-cli copied to clipboard

Add support to `pyproject.toml` dynamic values, i.e. "version"

Open set-soft opened this issue 5 months ago • 10 comments

Describe the solution you'd like The setuptools supports reading the version from the source code itself, avoiding repetition and sync problems, like this:

[project]
name = "image-misc"
description = """
Miscellaneous nodes for image manipulation.
Currently just download image with bypass, so you can create workflows including image examples.
No extra dependencies, just an internal module.
"""
dynamic = ["version"]
license = "GPL-3.0-or-later"
dependencies = ["seconohe"]

[project.urls]
Repository = "https://github.com/set-soft/ComfyUI-ImageMisc"

[tool.comfy]
PublisherId = "set-soft"
DisplayName = "Image Misc"

[tool.setuptools.dynamic]
version = {attr = "nodes.__version__"}

But when using it comfy-cli fails to find the version.

In the specs example it looks like the dependencies can be dynamic. So I think dynamic version should also be supported.

set-soft avatar Jul 25 '25 14:07 set-soft

This approach cannot be applied because relying on a Python module for part of the pyproject.toml data causes various issues. The Python module must be properly loaded and readable, which makes the process highly sensitive to Python environment issues.

There is additional overhead in interpreting the Python module. The version information in the pyproject.toml is not used only once during CNR registration—it is also needed when ComfyUI-Manager quickly scans installed node packs to construct installed nodepack information. In that case as well, it cannot be handled simply.

ltdrdata avatar Jul 26 '25 01:07 ltdrdata

Hi @ltdrdata ! Are you sure this is not solved by setuptools? Are you sure the module is actually loaded and not quickly parsed? At the current state the use of the project section in the pyproject.toml looks quite bad to me:

  • Mechanism to ensure the version consistency doesn't work
  • The current mechanism for the license doesn't work, you must use a deprecated mechanism (No SPDX support, only file="")
  • Dependencies are ignored by the ComfyUI-Manager, which just goes for requirements.txt

Things get really confusing for people that already uses pyproject.toml. Of course: if you never used it and you follow the tutorial for the ComfyUI Registry things goes smooth, but as soon as you really use pyproject.toml problems start to pop-up.

I understand Python modules are broken by design, and dynamic plug-ins are complex, but adding confusion pretending ComfyUI uses pyproject.toml, when in fact needs some kind of mocked version of it ...

set-soft avatar Jul 26 '25 12:07 set-soft

Are you sure this is not solved by setuptools? Are you sure the module is actually loaded and not quickly parsed?

You are correct that for typical Python packages, setuptools and tools like pip or uv handle dynamic metadata, such as the version, by parsing this information during the installation process and storing it in the package's metadata.

However, ComfyUI custom nodes are not standard Python packages that are "installed" in the traditional sense. This distinction is key to understanding the current limitations. Implementing the full dynamic metadata resolution that setuptools provides would introduce significant overhead. It would essentially require reimplementing the complex logic that packaging tools have already perfected for handling Python modules, which is not a trivial task.

While the current situation may not be ideal for experienced Python developers accustomed to the full capabilities of pyproject.toml, the primary goal was to offer a familiar configuration file format for developers.

The points you've raised about version consistencyis an area that can be definetly improved in a future.

bigcat88 avatar Jul 29 '25 17:07 bigcat88

Bump.

According to the up-to-date python packaging docs and docs for recommended Hatchling build backend, the dynamic version is done by a simple regex parsing. What overhead are you talking about? With dynamic version, Hatchling expects a pyproject.toml like this:

[build-system]
requires = ["hatchling >= 1.26"]
build-backend = "hatchling.build"

[project]
name = "my-package"
# No version here
dynamic = ["version"]

# ...

[tool.hatch.version]
path = "src/my_package/__package_meta.py"

And in this example, it would simply read the src/my_package/__package_meta.py file (not load it as a module - read it as text), and it simply uses a regex like this to extract the version:

in_single_quotes = "'(?P<version>[^']+)'"
in_double_quotes = '"(?P<version>[^"]+)"'
pattern = f"^(?:VERSION|__version__)[\\t ]*=[\\t ]*(?:{in_single_quotes}|{in_double_quotes})"

([\t ] here instead of \s - to match only tabs and spaces, not other whitespace chars)

No actual python evaluation, no handling of special cases (like escaped quotes inside the string). Just one regex, searching for the very first occurrence. In a file specified in pyproject.toml. How comes it impossible to do the same for comfy-cli?

Lex-DRL avatar Oct 04 '25 07:10 Lex-DRL

  1. How will this work if someone puts the "same" text with a different version in the comment and regex will parse it instead of a defined version in the _version.py file under __version__?
  2. _version.py file can be named differently - how we can handle it without loading a module and searching for __version__?

Is using regular expressions to retrieve the version from a file with a potentially unknown format a good idea?

bigcat88 avatar Oct 04 '25 07:10 bigcat88

  1. The same string in a single-line comment will be skipped (see ^ at the beginning of regex). Though, in a multiline comment - yes, it will be parsed as the version. But the package-meta submodule is supposed to be as simple as possible. Just module-level "constant" variables and nothing else. MAYBE a one-line docstring. Even if such restriction is explicitly stated as a limitation for dynamic versions, it's still better to have at least this compared to no dynamic version at all.
  2. You already read pyproject.toml, don't you? In this case, after reading it, you see that version is specified dynamically. You look for a file specified in path. You read it, you parse it with the regex I provided. That's it. Just one more file read. No need to load any python module.

Lex-DRL avatar Oct 04 '25 07:10 Lex-DRL

You look for a file specified in path.

[tool.hatch.version]
path = "src/my_package/__package_meta.py"

How comes it impossible to do the same for comfy-cli?

This will work only for hatchling. Initial message was about setuptools

bigcat88 avatar Oct 04 '25 08:10 bigcat88

potentially unknown format

You already strongly encourage node authors to stick to semantic versioning. That, by definition, means that there could be no quotes inside the version string. For those who strictly want to have quotes as part of the version, no matter what - you simply shrug and say "the dynamic version only supports semantic versioning, in a separate file, as a constant-like string, with no fancy stuff".

This will work only for hatchling.

I show hatchling solution as an example. You have your own build system anyway. Does it matter what build system to follow? Hatchling is the current officially recommended build backend for PyPI.

Lex-DRL avatar Oct 04 '25 08:10 Lex-DRL

We can definitely add support only for Hatchling, with correct error messages that will raise when setuptools or other backends used with dynamic version.

@ltdrdata wdyt, regarding this?

bigcat88 avatar Oct 04 '25 08:10 bigcat88

You don't need to mimic the hatchling itself. I've shown it only as a good example. Nothing stops you from doing it "like hatchling", but explicitly showing that it's your implementation:

[project]
name = "my-package"
dynamic = ["version"]

# ...

[tool.comfy.version]
path = "__package_meta.py"

Lex-DRL avatar Oct 04 '25 08:10 Lex-DRL