[Lint] Set 99 char line length and bulk reformat

Set up ruff to enforce a 99 char line limit, mirroring other OpenAssetIO
projects.

Configure yml with 2-space tabs, mirroring other OpenAssetIO projects
(and the ComfyUI cookiecutter project's defaults).

Bulk reformat using PyCharm configured to use ruff - i.e. Python files
are reformatted using ruff, whilst other files are reformatted
according to .editorconfig and/or PyCharm defaults.

Signed-off-by: David Feltell <david.feltell@foundry.com>
This commit is contained in:
David Feltell
2025-09-05 16:25:17 +01:00
parent 1f51166b29
commit 7b9843a862
7 changed files with 96 additions and 60 deletions
+4 -1
View File
@@ -13,7 +13,7 @@ trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf
max_line_length = 140
max_line_length = 99
# For docstrings and comments.
ij_visual_guides = 72
@@ -26,3 +26,6 @@ insert_final_newline = false
[Makefile]
indent_style = tab
[{*.yml,*.yaml}]
indent_size = 2
+2 -2
View File
@@ -16,8 +16,8 @@ jobs:
PYTHONIOENCODING: "utf8"
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.12"]
os: [ ubuntu-latest ]
python-version: [ "3.12" ]
steps:
- uses: actions/checkout@v4
+34 -13
View File
@@ -3,13 +3,17 @@
OpenAssetIO ingress and egress
> [!NOTE]
> This projected was created with a [cookiecutter](https://github.com/Comfy-Org/cookiecutter-comfy-extension) template. It helps you start writing custom nodes without worrying about the Python setup.
> This projected was created with
> a [cookiecutter](https://github.com/Comfy-Org/cookiecutter-comfy-extension) template. It helps you
> start
> writing custom nodes without worrying about the Python setup.
## Quickstart
1. Install [ComfyUI](https://docs.comfy.org/get_started).
1. Install [ComfyUI-Manager](https://github.com/ltdrdata/ComfyUI-Manager)
1. Look up this extension in ComfyUI-Manager. If you are installing manually, clone this repository under `ComfyUI/custom_nodes`.
1. Look up this extension in ComfyUI-Manager. If you are installing manually, clone this repository
under `ComfyUI/custom_nodes`.
1. Restart ComfyUI.
# Features
@@ -26,14 +30,19 @@ pip install -e .[dev]
pre-commit install
```
The `-e` flag above will result in a "live" install, in the sense that any changes you make to your node extension will automatically be picked up the next time you run ComfyUI.
The `-e` flag above will result in a "live" install, in the sense that any changes you make to your
node extension will automatically be
picked up the next time you run ComfyUI.
## Publish to Github
Install Github Desktop or follow these [instructions](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) for ssh.
Install Github Desktop or follow
these [instructions](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)
for ssh.
1. Create a Github repository that matches the directory name.
2. Push the files to Git
```
git add .
git commit -m "project scaffolding"
@@ -42,26 +51,38 @@ git push
## Writing custom nodes
An example custom node is located in [node.py](src/openassetio-comfyui/nodes.py). To learn more, read the [docs](https://docs.comfy.org/essentials/custom_node_overview).
An example custom node is located in [node.py](src/openassetio-comfyui/nodes.py). To learn more,
read
the [docs](https://docs.comfy.org/essentials/custom_node_overview).
## Tests
This repo contains unit tests written in Pytest in the `tests/` directory. It is recommended to unit test your custom node.
This repo contains unit tests written in Pytest in the `tests/` directory. It is recommended to
unit test your custom node.
- [build-pipeline.yml](.github/workflows/build-pipeline.yml) will run pytest and linter on any open PRs
- [validate.yml](.github/workflows/validate.yml) will run [node-diff](https://github.com/Comfy-Org/node-diff) to check for breaking changes
- [build-pipeline.yml](.github/workflows/build-pipeline.yml) will run pytest and linter on any open
PRs
- [validate.yml](.github/workflows/validate.yml) will
run [node-diff](https://github.com/Comfy-Org/node-diff) to check for breaking changes
## Publishing to Registry
If you wish to share this custom node with others in the community, you can publish it to the registry. We've already auto-populated some fields in `pyproject.toml` under `tool.comfy`, but please double-check that they are correct.
If you wish to share this custom node with others in the community, you can publish it to the
registry. We've already auto-populated some
fields in `pyproject.toml` under `tool.comfy`, but please double-check that they are correct.
You need to make an account on https://registry.comfy.org and create an API key token.
- [ ] Go to the [registry](https://registry.comfy.org). Login and create a publisher id (everything after the `@` sign on your registry profile).
- [ ] Go to the [registry](https://registry.comfy.org). Login and create a publisher id (everything
after the `@` sign on your registry
profile).
- [ ] Add the publisher id into the pyproject.toml file.
- [ ] Create an api key on the Registry for publishing from Github. [Instructions](https://docs.comfy.org/registry/publishing#create-an-api-key-for-publishing).
- [ ] Create an api key on the Registry for publishing from
Github. [Instructions](https://docs.comfy.org/registry/publishing#create-an-api-key-for-publishing).
- [ ] Add it to your Github Repository Secrets as `REGISTRY_ACCESS_TOKEN`.
A Github action will run on every git push. You can also run the Github action manually. Full instructions [here](https://docs.comfy.org/registry/publishing). Join our [discord](https://discord.com/invite/comfyorg) if you have any questions!
A Github action will run on every git push. You can also run the Github action manually. Full
instructions [here](https://docs.comfy.org/registry/publishing). Join
our [discord](https://discord.com/invite/comfyorg) if you have any
questions!
+1 -1
View File
@@ -70,7 +70,7 @@ disable_error_code = "attr-defined"
[tool.ruff]
# extend-exclude = ["static", "ci/templates"]
line-length = 140
line-length = 99
src = ["src", "tests"]
target-version = "py311"
+51 -42
View File
@@ -3,6 +3,8 @@
# SPDX-License-Identifier: Apache-2.0
from inspect import cleandoc
class Example:
"""
A example node
@@ -32,57 +34,68 @@ class Example:
The entry point method. The name of this method must be the same as the value of property `FUNCTION`.
For example, if `FUNCTION = "execute"` then this method's name must be `execute`, if `FUNCTION = "foo"` then it must be `foo`.
"""
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
"""
Return a dictionary which contains config for all input fields.
Some types (string): "MODEL", "VAE", "CLIP", "CONDITIONING", "LATENT", "IMAGE", "INT", "STRING", "FLOAT".
Input types "INT", "STRING" or "FLOAT" are special values for fields on the node.
The type can be a list for selection.
Return a dictionary which contains config for all input fields.
Some types (string): "MODEL", "VAE", "CLIP", "CONDITIONING", "LATENT", "IMAGE", "INT", "STRING", "FLOAT".
Input types "INT", "STRING" or "FLOAT" are special values for fields on the node.
The type can be a list for selection.
Returns: `dict`:
- Key input_fields_group (`string`): Can be either required, hidden or optional. A node class must have property `required`
- Value input_fields (`dict`): Contains input fields config:
* Key field_name (`string`): Name of a entry-point method's argument
* Value field_config (`tuple`):
+ First value is a string indicate the type of field or a list for selection.
+ Secound value is a config for type "INT", "STRING" or "FLOAT".
Returns: `dict`:
- Key input_fields_group (`string`): Can be either required, hidden or optional. A node class must have property `required`
- Value input_fields (`dict`): Contains input fields config:
* Key field_name (`string`): Name of a entry-point method's argument
* Value field_config (`tuple`):
+ First value is a string indicate the type of field or a list for selection.
+ Secound value is a config for type "INT", "STRING" or "FLOAT".
"""
return {
"required": {
"image": ("Image", { "tooltip": "This is an image"}),
"int_field": ("INT", {
"default": 0,
"min": 0, #Minimum value
"max": 4096, #Maximum value
"step": 64, #Slider's step
"display": "number" # Cosmetic only: display as "number" or "slider"
}),
"float_field": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 10.0,
"step": 0.01,
"round": 0.001, #The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
"display": "number"}),
"image": ("Image", {"tooltip": "This is an image"}),
"int_field": (
"INT",
{
"default": 0,
"min": 0, # Minimum value
"max": 4096, # Maximum value
"step": 64, # Slider's step
"display": "number", # Cosmetic only: display as "number" or "slider"
},
),
"float_field": (
"FLOAT",
{
"default": 1.0,
"min": 0.0,
"max": 10.0,
"step": 0.01,
"round": 0.001, # The value represeting the precision to round to, will be set to the step value by default. Can be set to False to disable rounding.
"display": "number",
},
),
"print_to_screen": (["enable", "disable"],),
"string_field": ("STRING", {
"multiline": False, #True if you want the field to look like the one on the ClipTextEncode node
"default": "Hello World!"
}),
"string_field": (
"STRING",
{
"multiline": False, # True if you want the field to look like the one on the ClipTextEncode node
"default": "Hello World!",
},
),
},
}
RETURN_TYPES = ("IMAGE",)
#RETURN_NAMES = ("image_output_name",)
# RETURN_NAMES = ("image_output_name",)
DESCRIPTION = cleandoc(__doc__)
FUNCTION = "test"
#OUTPUT_NODE = False
#OUTPUT_TOOLTIPS = ("",) # Tooltips for the output node
# OUTPUT_NODE = False
# OUTPUT_TOOLTIPS = ("",) # Tooltips for the output node
CATEGORY = "Example"
@@ -93,7 +106,7 @@ class Example:
int_field: {int_field}
float_field: {float_field}
""")
#do some processing on the image, in this example I just invert it
# do some processing on the image, in this example I just invert it
image = 1.0 - image
return (image,)
@@ -105,18 +118,14 @@ class Example:
This method is used in the core repo for the LoadImage node where they return the image hash as a string, if the image hash
changes between executions the LoadImage node is executed again.
"""
#@classmethod
#def IS_CHANGED(s, image, string_field, int_field, float_field, print_to_screen):
# @classmethod
# def IS_CHANGED(s, image, string_field, int_field, float_field, print_to_screen):
# return ""
# A dictionary that contains all nodes you want to export with their names
# NOTE: names should be globally unique
NODE_CLASS_MAPPINGS = {
"Example": Example
}
NODE_CLASS_MAPPINGS = {"Example": Example}
# A dictionary that contains the friendly/humanly readable titles for the nodes
NODE_DISPLAY_NAME_MAPPINGS = {
"Example": "Example Node"
}
NODE_DISPLAY_NAME_MAPPINGS = {"Example": "Example Node"}
+1 -1
View File
@@ -7,4 +7,4 @@ import sys
# Add the project root directory to Python path
# This allows the tests to import the project
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
+3
View File
@@ -8,15 +8,18 @@
import pytest
from src.openassetio_comfyui.nodes import Example
@pytest.fixture
def example_node():
"""Fixture to create an Example node instance."""
return Example()
def test_example_node_initialization(example_node):
"""Test that the node can be instantiated."""
assert isinstance(example_node, Example)
def test_return_types():
"""Test the node's metadata."""
assert Example.RETURN_TYPES == ("IMAGE",)