Merge branch 'dev/nkendallbar/node_docs' into 'main'

add node documentation and a repo tool to generate them

See merge request lightspeedrtx/lss-ai-tools/comfyui-rtx_remix!5
This commit is contained in:
Nicolas Kendall-Bar
2024-06-18 15:24:24 -07:00
8 changed files with 181 additions and 2 deletions
+31 -1
View File
@@ -8,4 +8,34 @@
You should see RTX Remix nodes:
![RTX Remix](images/remix_nodes.png "RTX Remix")
![RTX Remix](images/remix_nodes.png "RTX Remix")
## Nodes
### Textures
- **RTX Remix Get Textures**: Read the textures matching provided criteria from the currently open project
- **RTX Remix Texture Type To USD Attribute**: Use this node to get the proper texture attribute on the same asset but for a different texture type
- **RTX Remix Set Texture**: Set the texture path on an asset
- **RTX Remix Texture Type**: Select from a list of supported texture types.
- **RTX Remix Texture Types**: Select multiple texture types from a list of supported texture types.
### Ingestion
- **RTX Remix Ingest Texture**: Ingest an image as a texture and save it to disk
### Common
- **RTX Remix Rest API Details**: Provide the port information to connect to the RTX Remix Toolkit
- **RTX Remix String Constant**: Declare a string constant
- **RTX Remix Start Context**: Use this node to begin a graph, then pass context along to determine execution order.
- **RTX Remix End Context**: Put this node at the end of your graph to evaluate prior nodes
### Layers
- **RTX Remix Define Layer ID**: Helper node to define a layer path relative to project or another layer
- **RTX Remix Create Layer**: Create or Insert a sublayer in the current stage
- **RTX Remix Get Layers**: Query layer ids from the currently open project
- **RTX Remix Remove Layer**: Remove a layer from the project
- **RTX Remix Save Layer**: Save a project layer
- **RTX Remix Mute Layer**: Mute or unmute a project layer
- **RTX Remix Set Edit Target**: Designate the edit target on the open project to receive modifications
- **RTX Remix Get Edit Target**: Get the edit target from the currently open project
- **RTX Remix Layer Types**: Select multiple layer types from a list of supported layer types.
- **RTX Remix Layer Type**: Select from a list of supported layer types.
+1 -1
View File
@@ -72,7 +72,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"RTXRemixStringConstant": "RTX Remix String Constant",
"RTXRemixTexturesType": "RTX Remix Texture Type",
"RTXRemixTexturesTypes": "RTX Remix Texture Types",
"RTXRemixDefineLayerId": "RTX Remix Define Layer",
"RTXRemixDefineLayerId": "RTX Remix Define Layer ID",
"RTXRemixCreateLayer": "RTX Remix Create Layer",
"RTXRemixGetLayers": "RTX Remix Get Layers",
"RTXRemixRemoveLayer": "RTX Remix Remove Layer",
+5
View File
@@ -92,6 +92,7 @@ def add_context_input_and_output(cls):
class RestAPIDetails:
"""Provide the port information to connect to the RTX Remix Toolkit"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -124,6 +125,7 @@ class RestAPIDetails:
@add_context_outputs
class StartContext:
"""Use this node to begin a graph, then pass context along to determine execution order."""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -143,6 +145,7 @@ class StartContext:
class EndContext:
"""Put this node at the end of your graph to evaluate prior nodes"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -162,6 +165,8 @@ class EndContext:
class StringConstant:
"""Declare a string constant"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
return {
+1
View File
@@ -34,6 +34,7 @@ _file_name = pathlib.Path(__file__).stem
@add_context_input_and_output
class IngestTexture:
"""Ingest an image as a texture and save it to disk"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
+9
View File
@@ -119,6 +119,7 @@ class DefineLayerId:
@add_context_input_and_output
class CreateLayer:
"""Create or Insert a sublayer in the current stage"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -198,6 +199,7 @@ class CreateLayer:
@add_context_input_and_output
class LayerType:
"""Select from a list of supported layer types."""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -223,6 +225,7 @@ class LayerType:
@add_context_input_and_output
class LayerTypes:
"""Select multiple layer types from a list of supported layer types."""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -255,6 +258,7 @@ class LayerTypes:
@add_context_input_and_output
class GetLayers:
"""Query layer ids from the currently open project"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -385,6 +389,7 @@ class _LayerOp:
@add_context_input_and_output
class MuteLayer(_LayerOp):
"""Mute or unmute a project layer"""
@classmethod
def INPUT_TYPES(cls):
@@ -416,6 +421,7 @@ class MuteLayer(_LayerOp):
@add_context_input_and_output
class RemoveLayer(_LayerOp):
"""Remove a layer from the project"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -447,6 +453,7 @@ class RemoveLayer(_LayerOp):
@add_context_input_and_output
class SaveLayer(_LayerOp):
"""Save a project layer"""
def execute(self, layer_id: str) -> tuple[str]:
address, port = self.context
@@ -460,6 +467,7 @@ class SaveLayer(_LayerOp):
@add_context_input_and_output
class GetEditTarget:
"""Get the edit target from the currently open project"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -493,6 +501,7 @@ class GetEditTarget:
@add_context_input_and_output
class SetEditTarget(_LayerOp):
"""Designate the edit target on the open project to receive modifications"""
def execute(self, layer_id: str) -> tuple[str]:
address, port = self.context
+5
View File
@@ -61,6 +61,7 @@ def validate_texture_types(texture_types: list[str], address: str, port: str):
@add_context_input_and_output
class GetTextures:
"""Read the textures matching provided criteria from the currently open project"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -185,6 +186,7 @@ class GetTextures:
@add_context_input_and_output
class TexturesTypes:
"""Select multiple texture types from a list of supported texture types."""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -218,6 +220,7 @@ class TexturesTypes:
@add_context_input_and_output
class TexturesType:
"""Select from a list of supported texture types."""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -242,6 +245,7 @@ class TexturesType:
@add_context_input_and_output
class SetTexture:
"""Set the texture path on an asset"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
@@ -284,6 +288,7 @@ class SetTexture:
@add_context_input_and_output
class TextureTypeToUSDAttribute:
"""Use this node to get the proper texture attribute on the same asset but for a different texture type"""
@classmethod
def INPUT_TYPES(cls): # noqa N802
+14
View File
@@ -0,0 +1,14 @@
[repo_class_docs]
# Tool name
command = "class_docs"
# [python module name or path]:[function name]
entry_point = "${root}/tools/repoman/class_docs.py:setup_repo_tool"
# Python install to use
python_install = "${root}/../../../python_embeded/python.exe"
# Root module to import
module_name = "nodes"
module = "${root}/nodes/__init__.py"
# README to modify
file_path = "${root}/README.md"
# Header of section where change is required
section_header = "## Nodes"
+115
View File
@@ -0,0 +1,115 @@
"""
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
"""
import os
import re
import subprocess
import sys
import textwrap
def update_comfyui_rtx_remix_readme(module, readme_path, section_header):
"""Generate docs for node types"""
section_header_style = section_header.split(' ')[0]
header_num = section_header_style.count('#')
output = []
nodes_by_module = {}
for name, node in module.NODE_CLASS_MAPPINGS.items():
nodes_by_module.setdefault(node.__module__, []).append((name, node))
for node_module, nodes in nodes_by_module.items():
output.append(f"{'#' * (header_num + 1)} {node_module.split('.')[-1].capitalize()}\n")
for node_info in nodes:
name, node_class = node_info
display_name = module.NODE_DISPLAY_NAME_MAPPINGS[name]
if node_class.__doc__:
# first line only
doc = node_class.__doc__.strip("\n")
line_break_index = doc.find("\n")
if line_break_index > 0:
doc = doc[:]
output.append(f"- **{display_name}**: {doc}\n")
else:
output.append(f"**{display_name}**\n")
output.append("\n")
replace_section(readme_path, section_header, output)
def replace_section(readme_path, section_header, contents):
"""Replace a section under a specific markdown header with new contents"""
section_header_style = section_header.split(' ')[0]
with open(readme_path, 'r') as f:
data = f.readlines()
new = []
start = -1
end = None
found = False
for i, line in enumerate(data):
# search for the first occurence of the special section header string
if not found:
if line.strip() == section_header:
found = True
start = i + 1
# search for the next header of the same magnitude
elif re.match(f"{section_header_style}[^#].*", line):
end = i
break
final = data[:start] + contents
if end:
final += data[end:]
with open(readme_path, 'w') as f:
f.writelines(final)
def update_readme(module, readme_path, section_header):
"""Generic `class_docs` entry point. Add repo-specific implementation here!"""
update_comfyui_rtx_remix_readme(module, readme_path, section_header)
def setup_repo_tool(parser, _):
parser.prog = "class_docs"
parser.description = "Generate summary documentation for a bunch of classes"
def run_repo_tool(options, config):
import subprocess
settings = config["repo_class_docs"]
# Some projects will require using their own python in order to be able to import and inspect
# classes so we use a subprocess
python_code = textwrap.dedent(f"""\
import sys
sys.path.append("{os.path.dirname(__file__)}")
import class_docs
import importlib.util
module_name = "{settings["module_name"]}"
spec = importlib.util.spec_from_file_location(module_name, "{settings["module"]}")
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
class_docs.update_readme(module, "{settings["file_path"]}", "{settings["section_header"]}")
""")
python_cmd = settings["python_install"]
if subprocess.call([python_cmd, "-c", python_code]) == 0:
print("Success!")
return run_repo_tool