[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:
+4
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
|
||||
@@ -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
@@ -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__), "..")))
|
||||
|
||||
@@ -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",)
|
||||
|
||||
Reference in New Issue
Block a user