From f2322ead4d71e6bfbc883a7f9afb292a5497a953 Mon Sep 17 00:00:00 2001 From: StableLlama Date: Tue, 3 Jun 2025 19:41:05 +0200 Subject: [PATCH] Update README and description --- README.md | 335 +++++++++++++++++++++++++++++++----------- pyproject.toml | 23 ++- web/js/dynamicnode.js | 27 ---- 3 files changed, 268 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index e310275..6b24d18 100644 --- a/README.md +++ b/README.md @@ -16,91 +16,271 @@ These nodes are very lightweight and require no additional dependencies. # Features -- **STRING**: String manipulation nodes - - Basic functions: capitalize, casefold, center, concat, count, encode/decode, find/rfind, join, lower/upper, replace, split, strip, etc. - - String checking: contains, endswith, startswith - - Case conversion: lower, upper, swapcase, title, capitalize - - Validation: isalnum, isalpha, isdigit, isnumeric, etc. +## Nodes -- **LIST**: Python list manipulation nodes (as a single variable) - - Conversion: convert to data list - - Creation: any to LIST - - Modification: append, extend, insert, remove, pop, clear, set_item - - Access: get_item, slice, index, contains - - Information: length, count - - Operations: sort, reverse, min, max +### BOOLEAN: Boolean logic nodes +- Logic operations: and, or, not, xor, nand, nor -- **SET**: Python set manipulation nodes (as a single variable) - - Conversion: convert to data list, to LIST - - Creation: any to SET, LIST to SET - - Modification: add, remove, discard, pop, clear - - Information: length, contains - - Set operations: union, intersection, difference, symmetric_difference - - Comparison: is_subset, is_superset, is_disjoint +### cast: Type conversion nodes for ComfyUI data types +- Basic data type conversions: + - to BOOLEAN - Converts any input to a Boolean using Python's truthy/falsy rules + - to FLOAT - Converts numeric input to a floating-point number (raises ValueError for invalid inputs) + - to INT - Converts numeric input to an integer (raises ValueError for invalid inputs) + - to STRING - Converts any input to a string using Python's str() function +- Collection type conversions: + - to DICT - Converts compatible inputs (mappings or lists of key-value pairs) to a dictionary + - to LIST - Converts input to a LIST (wraps single items in a list, preserves existing lists) + - to SET - Converts input to a SET (creates a set from single items or collections, removing duplicates) -- **data list**: ComfyUI list manipulation nodes (for processing individual items) - - Creation: create_empty - - Modification: append, filter, extend, insert, remove, pop, clear, set_item - - Access: get_item, slice, index, contains - - Information: length, count - - Operations: sort, reverse, copy, zip, min, max +### Comparison: Value comparison nodes +- Basic comparisons: equal (==), not equal (!=), greater than (>), greater than or equal (>=), less than (<), less than or equal (<=) +- String comparison: StringComparison node with case-sensitive/insensitive options and various operators (==, !=, >, <, >=, <=) +- Special comparisons: NumberInRange (check if a value is within specified bounds), IsNull (check if a value is null) +- Container operations: CompareLength (compare the length of strings, lists, and other containers) -- **cast**: Type conversion nodes for ComfyUI data types - - Basic conversions: to STRING, to INT, to FLOAT, to BOOLEAN - - Collection conversions: to LIST, to SET, to DICT - - Special conversions: data list to LIST, data list to SET +### data list: ComfyUI list manipulation nodes (for processing individual items) +- Creation: + - create Data List - Generic creation from any type inputs (dynamically expandable) + - Type-specific creation: + - create Data List from BOOLEANs - Creates a data list from Boolean values + - create Data List from FLOATs - Creates a data list from floating-point values + - create Data List from INTs - Creates a data list from integer values + - create Data List from STRINGs - Creates a data list from string values +- Modification: + - append - Adds an item to the end of a data list + - extend - Combines elements from multiple data lists + - insert - Inserts an item at a specified position + - set item - Replaces an item at a specified position + - remove - Removes the first occurrence of a specified value + - pop - Removes and returns an item at a specified position + - pop random - Removes and returns a random element +- Filtering: + - filter - Filters a data list using boolean values + - filter select - Separates items into two lists based on boolean filters +- Access: + - get item - Retrieves an item at a specified position + - first - Returns the first element in a data list + - last - Returns the last element in a data list + - slice - Creates a subset of a data list using start/stop/step parameters + - index - Finds the position of a value in a data list + - contains - Checks if a data list contains a specified value +- Information: + - length - Returns the number of items in a data list + - count - Counts occurrences of a value in a data list +- Operations: + - sort - Orders items (with optional reverse parameter) + - reverse - Reverses the order of items + - zip - Combines multiple data lists element-wise + - min - Finds the minimum value in a list of numbers + - max - Finds the maximum value in a list of numbers +- Conversion: + - convert to LIST - Converts a data list to a LIST object + - convert to SET - Converts a data list to a SET (removing duplicates) -- **path**: File system path manipulation nodes - - Basic operations: join, split, splitext, basename, dirname, normalize - - Path information: abspath, exists, is_file, is_dir, is_absolute, get_size, get_extension - - Directory operations: list_dir, get_cwd - - Path searching: glob, common_prefix - - Path conversions: relative, expand_vars +### DICT: Dictionary manipulation nodes +- Creation: create (generic and type-specific versions), create from items (data list and LIST versions), create from lists, fromkeys +- Access: get, get_multiple, keys, values, items +- Modification: set, update, setdefault, merge +- Removal: pop, popitem, pop random, remove +- Information: length, contains_key +- Operations: filter_by_keys, exclude_keys, invert, compare +- Conversion: get_keys_values -- **DICT**: Dictionary manipulation nodes - - Creation: create, from_items, from_lists, fromkeys, any_to_DICT - - Access: get, get_multiple, keys, values, items - - Modification: set, update, setdefault, merge - - Removal: pop, popitem, remove, clear - - Information: length, contains_key - - Operations: copy, filter_by_keys, exclude_keys, invert, compare - - Conversion: get_keys_values +### FLOAT: Floating-point operation nodes +- Creation: create FLOAT from string +- Basic arithmetic: add, subtract, multiply, divide, divide (zero safe), power +- Formatting: round (to specified decimal places) +- Conversion: to_hex (hexadecimal representation), from_hex (create from hex string) +- Analysis: is_integer (check if float has no fractional part), as_integer_ratio (get numerator/denominator) -- **INT**: Integer operation nodes - - Basic operations: add, subtract, multiply, divide, modulus, power - - Bit operations: bit_length, to_bytes, from_bytes, bit_count +### Flow Control: Workflow control nodes +- Conditional branching: + - if/else - Basic conditional that returns one of two values based on a condition + - if/elif/.../else - Extended conditional with multiple conditions and outcomes +- Selection: + - switch/case - Selects from multiple options based on an integer index + - flow select - Directs a value to either "true" or "false" output path based on a condition +- Execution control: + - force execution order - Coordinates the execution sequence of nodes in a workflow -- **FLOAT**: Floating-point operation nodes - - Basic operations: add, subtract, multiply, divide, power, round - - Specialized: is_integer, as_integer_ratio, to_hex, from_hex +### INT: Integer operation nodes +- Creation: create INT (from string), create INT with base (convert string with specified base) +- Basic arithmetic: add, subtract, multiply, divide, divide (zero safe), modulus, power +- Bit operations: bit_length (bits needed to represent number), bit_count (count of 1 bits) +- Byte conversion: to_bytes (convert integer to bytes), from_bytes (convert bytes to integer) -- **BOOLEAN**: Boolean logic nodes - - Logic operations: and, or, not, xor, nand, nor +### LIST: Python list manipulation nodes (as a single variable) +- Creation: create LIST (generic), create from type-specific values (BOOLEANs, FLOATs, INTs, STRINGs) +- Modification: append, extend, insert, remove, pop, pop random, set_item +- Access: get_item, first, last, slice, index, contains +- Information: length, count +- Operations: sort (with optional reverse), reverse, min, max +- Conversion: convert to data list, convert to SET -- **Comparison**: Value comparison nodes - - Basic comparisons: equal (==), not equal (!=), greater than (>), less than (<), etc. - - String comparison: case-sensitive/insensitive string comparison with various operators - - Special comparisons: number in range, is null, compare length - - Container operations: length comparison for strings, lists, and other containers +### Math: Mathematical operations +- Trigonometric functions: + - Basic: sin, cos, tan - Calculate sine, cosine, and tangent of angles (in degrees or radians) + - Inverse: asin, acos, atan - Calculate inverse sine, cosine, and tangent (returns degrees or radians) + - Special: atan2 - Calculate arc tangent of y/x with correct quadrant handling +- Logarithmic/Exponential functions: + - log - Natural logarithm (base e) with optional custom base + - log10 - Base-10 logarithm + - exp - Exponential function (e^x) + - sqrt - Square root +- Constants: + - pi - Mathematical constant π (3.14159...) + - e - Mathematical constant e (2.71828...) +- Angle conversion: + - degrees - Convert radians to degrees + - radians - Convert degrees to radians +- Rounding operations: + - floor - Return largest integer less than or equal to input + - ceil - Return smallest integer greater than or equal to input +- Min/Max functions: + - min - Return minimum of two values + - max - Return maximum of two values +- Other: + - abs - Absolute value (magnitude without sign) -- **Flow Control**: Workflow control nodes - - Conditional: if/else for branching logic based on conditions - - Selection: switch/case for selecting from multiple options based on an index +### path: File system path manipulation nodes +- Basic operations: + - join - Joins multiple path components intelligently with correct separators + - split - Splits a path into directory and filename components + - splitext - Splits a path into name and extension components + - basename - Extracts the filename component from a path + - dirname - Extracts the directory component from a path + - normalize - Collapses redundant separators and resolves up-level references +- Path information: + - abspath - Returns the absolute (full) path by resolving relative components + - exists - Checks if a path exists in the filesystem + - is_file - Checks if a path points to a regular file + - is_dir - Checks if a path points to a directory + - is_absolute - Checks if a path is absolute (begins at root directory) + - get_size - Returns the size of a file in bytes + - get_extension - Extracts the file extension from a path (including the dot) +- Directory operations: + - list_dir - Lists files and directories in a specified path with filtering options + - get_cwd - Returns the current working directory +- Path searching: + - glob - Finds paths matching a pattern with wildcard support + - common_prefix - Finds the longest common leading component of given paths +- Path conversions: + - relative - Computes a relative path from a start path to a target path + - expand_vars - Replaces environment variables in a path with their values -- **Math**: Mathematical operations - - Trigonometric: sin, cos, tan, asin, acos, atan, atan2 - - Logarithmic/Exponential: log, log10, exp, sqrt - - Numerical: min, max - - Constants: pi, e - - Conversion: degrees/radians - - Rounding: floor, ceil - - Other: abs (absolute value) +### SET: Python set manipulation nodes (as a single variable) +- Creation: + - create SET - Generic creation from any type inputs (dynamically expandable) + - Type-specific creation: + - create SET from BOOLEANs - Creates a set from Boolean values + - create SET from FLOATs - Creates a set from floating-point values + - create SET from INTs - Creates a set from integer values + - create SET from STRINGs - Creates a set from string values +- Modification: + - add - Adds an item to a set + - remove - Removes an item from a set (raises error if not present) + - discard - Removes an item if present (no error if missing) + - pop - Removes and returns an arbitrary element + - pop random - Removes and returns a random element +- Information: + - length - Returns the number of items in a set + - contains - Checks if a set contains a specified value +- Set operations: + - union - Combines elements from multiple sets + - intersection - Returns elements common to all input sets + - difference - Returns elements in first set but not in second set + - symmetric_difference - Returns elements in either set but not in both +- Set comparison: + - is_subset - Checks if first set is a subset of second set + - is_superset - Checks if first set is a superset of second set + - is_disjoint - Checks if two sets have no common elements +- Conversion: + - convert to data list - Converts a SET to a ComfyUI data list + - convert to LIST - Converts a SET to a LIST + +### STRING: String manipulation nodes +Available nodes grouped by functionality: + +#### Text case conversion +- capitalize - Converts first character to uppercase, rest to lowercase +- casefold - Aggressive lowercase for case-insensitive comparisons +- lower - Converts string to lowercase +- swapcase - Swaps case of all characters +- title - Converts string to titlecase +- upper - Converts string to uppercase + +#### Text inspection and validation +- contains (in) - Checks if string contains a substring +- endswith - Checks if string ends with a specific suffix +- find - Finds first occurrence of a substring +- length - Returns the number of characters in the string +- rfind - Finds last occurrence of a substring +- startswith - Checks if string starts with a specific prefix + +#### Character type checking +- isalnum - Checks if all characters are alphanumeric +- isalpha - Checks if all characters are alphabetic +- isascii - Checks if all characters are ASCII +- isdecimal - Checks if all characters are decimal +- isdigit - Checks if all characters are digits +- isidentifier - Checks if string is a valid Python identifier +- islower - Checks if all characters are lowercase +- isnumeric - Checks if all characters are numeric +- isprintable - Checks if all characters are printable +- isspace - Checks if all characters are whitespace +- istitle - Checks if string is titlecased +- isupper - Checks if all characters are uppercase + +#### Text formatting and alignment +- center - Centers text within specified width +- expandtabs - Replaces tabs with spaces +- ljust - Left-aligns text within specified width +- rjust - Right-aligns text within specified width +- zfill - Pads string with zeros on the left + +#### Text splitting and joining +- join (from data list) - Joins strings from a data list +- join (from LIST) - Joins strings from a LIST +- rsplit (from data list) - Splits string from right into a data list +- rsplit (from LIST) - Splits string from right into a LIST +- split (to data list) - Splits string into a data list +- split (to LIST) - Splits string into a LIST +- splitlines (from data list) - Splits string at line boundaries into a data list +- splitlines (to LIST) - Splits string at line boundaries into a LIST + +#### Text modification +- concat - Combines two strings together +- count - Counts occurrences of a substring +- replace - Replaces occurrences of a substring +- strip - Removes leading and trailing characters +- lstrip - Removes leading characters +- rstrip - Removes trailing characters +- removeprefix - Removes prefix if present +- removesuffix - Removes suffix if present + +#### Encoding and escaping +- decode - Converts bytes-like string to text +- encode - Converts string to bytes +- escape - Converts special characters to escape sequences +- unescape - Converts escape sequences to actual characters +- format_map - Formats string using values from dictionary ## Understanding LIST vs. data list vs. SET ComfyUI has different data types that serve different purposes: -### 1. LIST datatype +### 1. data list +- A native ComfyUI list where **items are processed individually** +- Acts like a standard array/list in most programming contexts +- Items can be accessed individually by compatible nodes +- Supports built-in ComfyUI iteration over each item +- Best for: + - Working directly with multiple items in parallel + - Batch processing scenarios + - When you need to apply the same operation to multiple inputs + - When your operation needs to work with individual items separately + +### 2. LIST datatype - A Python list represented as a **single variable** in the workflow - Treated as a self-contained object that can be passed between nodes - Cannot directly connect to nodes that expect individual items @@ -110,7 +290,7 @@ ComfyUI has different data types that serve different purposes: - Passing collections between different parts of your workflow - Complex data storage that shouldn't be split apart -### 2. SET datatype +### 3. SET datatype - A Python set represented as a **single variable** in the workflow - Stores unique values with no duplicates - Supports mathematical set operations (union, intersection, etc.) @@ -120,23 +300,6 @@ ComfyUI has different data types that serve different purposes: - Set operations (union, difference, etc.) - When element order doesn't matter -### 3. data list -- A native ComfyUI list where **items are processed individually** -- Acts like a standard array/list in most programming contexts -- Items can be accessed individually by compatible nodes -- Supports built-in ComfyUI iteration over each item -- Best for: - - Working directly with multiple items in parallel - - Batch processing scenarios - - When you need to apply the same operation to multiple inputs - - When your operation needs to work with individual items separately - -### Converting between types -- Use `convert to data list` node to transform a LIST or SET into a ComfyUI data list -- Use `convert to LIST` node to transform a ComfyUI data list into a LIST object -- Use `LIST to SET` to convert a LIST to a SET (removing duplicates) -- Use `SET to LIST` to convert a SET to a LIST - ### When to use which type - Use **LIST** when you need: - Ordered collection with potential duplicates diff --git a/pyproject.toml b/pyproject.toml index ff70645..cc8688d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,11 +6,26 @@ build-backend = "setuptools.build_meta" name = "basic_data_handling" version = "0.3.5" description = """NOTE: Still in development! Expect breaking changes! + Basic Python functions for manipulating data that every programmer is used to. -Currently supported ComfyUI data types: BOOLEAN, FLOAT, INT, STRING and data lists. -Additionally supported Python data types as custom data types: DICT, LIST. -Data handling is supported with comparisons and control flow operations. -Also contains math, regex, and file system path manipulation functions.""" +Comprehensive node collection for data manipulation in ComfyUI workflows. + +Supported data types: +- ComfyUI native: BOOLEAN, FLOAT, INT, STRING, and data lists +- Python types as custom data types: DICT, LIST, SET + +Feature categories: +- Boolean logic operations (and, or, not, xor, nand, nor) +- Type casting/conversion between all supported data types +- Comparison operations (equality, numerical comparison, range checking) +- Data structures manipulation (data lists, LIST, DICT, SET) +- Flow control (conditionals, branching, execution order) +- Mathematical operations (arithmetic, trigonometry, logarithmic functions) +- String manipulation (case conversion, formatting, splitting, validation) +- File system path handling (path operations, information, searching) +- SET operations (creation, modification, comparison, mathematical set theory) + +All nodes are lightweight with no additional dependencies required.""" authors = [ {name = "StableLlama"} ] diff --git a/web/js/dynamicnode.js b/web/js/dynamicnode.js index db620fe..a3b170c 100644 --- a/web/js/dynamicnode.js +++ b/web/js/dynamicnode.js @@ -565,33 +565,6 @@ app.registerExtension({ return originalReturn; }; - // --- Core Dynamic Methods (swapInputs, getDynamicSlots, addNewDynamicInputForGroup) --- - nodeType.prototype.swapInputs = function(indexA, indexB) { // (Content unchanged) - if (indexA < 0 || indexB < 0 || indexA >= this.inputs.length || indexB >= this.inputs.length || indexA === indexB) { - console.error("[Basic Data Handling] Invalid input indices for swapping:", indexA, indexB); return; - } - const hasWidgetA = this.inputs[indexA].widget !== undefined; - const hasWidgetB = this.inputs[indexB].widget !== undefined; - if (hasWidgetA && hasWidgetB) { - const widgetIdxA = this.widgets.findIndex((w) => w.name === this.inputs[indexA].widget.name); - const widgetIdxB = this.widgets.findIndex((w) => w.name === this.inputs[indexB].widget.name); - if(widgetIdxA !== -1 && widgetIdxB !== -1) { - [this.widgets[widgetIdxA].y, this.widgets[widgetIdxB].y] = [this.widgets[widgetIdxB].y, this.widgets[widgetIdxA].y]; - [this.widgets[widgetIdxA].last_y, this.widgets[widgetIdxB].last_y] = [this.widgets[widgetIdxB].last_y, this.widgets[widgetIdxA].last_y]; - [this.widgets[widgetIdxA], this.widgets[widgetIdxB]] = [this.widgets[widgetIdxB], this.widgets[widgetIdxA]]; - if (this.widgets_values) { - [this.widgets_values[widgetIdxA], this.widgets_values[widgetIdxB]] = [this.widgets_values[widgetIdxB], this.widgets_values[widgetIdxA]]; - } - } - } else if (hasWidgetA || hasWidgetB) { - console.error("[Basic Data Handling] Bad swap: one input has a widget but the other doesn't", indexA, indexB); - } - [this.inputs[indexA].boundingRect, this.inputs[indexB].boundingRect] = [this.inputs[indexB].boundingRect, this.inputs[indexA].boundingRect]; - [this.inputs[indexA].pos, this.inputs[indexB].pos] = [this.inputs[indexB].pos, this.inputs[indexA].pos]; - [this.inputs[indexA], this.inputs[indexB]] = [this.inputs[indexB], this.inputs[indexA]]; - updateSlotIndices(this); - }; - nodeType.prototype.getDynamicSlots = function(filterDynamicGroup = null) { // (Content largely unchanged, relies on isDynamicInputEmpty which is updated) const dynamicSlotsResult = []; const dynamicGroupCount = {};