diff --git a/captain/blocks/slider.py b/blocks/flojoy/control/slider.py similarity index 100% rename from captain/blocks/slider.py rename to blocks/flojoy/control/slider.py diff --git a/captain/blocks/add.py b/blocks/flojoy/math/arithmetic/add.py similarity index 100% rename from captain/blocks/add.py rename to blocks/flojoy/math/arithmetic/add.py diff --git a/captain/blocks/subtract.py b/blocks/flojoy/math/arithmetic/subtract.py similarity index 100% rename from captain/blocks/subtract.py rename to blocks/flojoy/math/arithmetic/subtract.py diff --git a/captain/blocks/constant.py b/blocks/flojoy/math/constant.py similarity index 100% rename from captain/blocks/constant.py rename to blocks/flojoy/math/constant.py diff --git a/captain/blocks/bignum.py b/blocks/flojoy/visualization/bignum.py similarity index 100% rename from captain/blocks/bignum.py rename to blocks/flojoy/visualization/bignum.py diff --git a/captain/blocks/button.py b/captain/blocks/button.py deleted file mode 100644 index 6b53b31..0000000 --- a/captain/blocks/button.py +++ /dev/null @@ -1,6 +0,0 @@ -from captain.decorators import ui_input - - -@ui_input -def button(x): - return x diff --git a/captain/blocks/gamepad.py b/captain/blocks/gamepad.py deleted file mode 100644 index 31b4338..0000000 --- a/captain/blocks/gamepad.py +++ /dev/null @@ -1,6 +0,0 @@ -from captain.decorators import ui_input - - -@ui_input -def gamepad(x): - return x diff --git a/captain/controllers/reactive.py b/captain/controllers/reactive.py index 3940f02..8fb34f8 100644 --- a/captain/controllers/reactive.py +++ b/captain/controllers/reactive.py @@ -12,7 +12,7 @@ from captain.types.flowchart import BlockID, FCBlock, FlowChart from captain.utils.blocks import import_blocks, is_ui_input -BLOCKS_DIR = os.path.join("captain", "blocks") +BLOCKS_DIR = os.path.join("blocks") ZIPPED_BLOCKS = [] # TODO: I (sasha) am anti zip in all cases. @@ -183,6 +183,8 @@ def __init__( funcs = import_blocks(BLOCKS_DIR) + print(funcs, flush=True) + for block in flowchart.blocks: if is_ui_input(funcs[block.block_type]): logger.debug(f"Creating UI input for {block.id}") diff --git a/captain/types/flowchart.py b/captain/types/flowchart.py index ead5c8b..77fcbd8 100644 --- a/captain/types/flowchart.py +++ b/captain/types/flowchart.py @@ -4,7 +4,11 @@ # TODO: This is hardcoded for now BlockType = Literal[ - "slider", "gamepad", "button", "bignum", "add", "subtract", "constant" + "flojoy.control.slider", + "flojoy.visualization.bignum", + "flojoy.math.arithmetic.add", + "flojoy.math.arithmetic.subtract", + "flojoy.math.constant", ] BlockID: TypeAlias = str diff --git a/captain/utils/blocks.py b/captain/utils/blocks.py index 1a893cc..52592f3 100644 --- a/captain/utils/blocks.py +++ b/captain/utils/blocks.py @@ -2,30 +2,47 @@ import os from typing import Callable, Mapping +from captain.logging import logger + def import_blocks(blocks_dir: str) -> Mapping[str, Callable]: + # example key: "flojoy.math.arithmetic.add" functions = {} - for file in os.listdir(blocks_dir): - full_path = os.path.join(blocks_dir, file) - if not os.path.isfile(full_path) or not file.endswith(".py"): - continue - block_name = file.strip(".py") - spec = importlib.util.spec_from_file_location(block_name, full_path) + for root, _, files in os.walk(blocks_dir): + for file in files: + if not file.endswith(".py"): + continue + + block_name = file.strip(".py") + + block_path = os.path.join(root, file) + + # block_type is something like "flojoy.math.arithmetic.add" + block_type = os.path.relpath( + os.path.splitext(block_path)[0], blocks_dir + ).replace("/", ".") - if not spec: - raise ValueError(f"Invalid block spec from {full_path}") + spec = importlib.util.spec_from_file_location(block_name, block_path) - module = importlib.util.module_from_spec(spec) - if not spec.loader: - raise ValueError(f"Could not get loader from {full_path}") + if not spec: + raise ValueError(f"Invalid block spec from {block_path}") - spec.loader.exec_module(module) - func = getattr(module, block_name) - functions[block_name] = func + module = importlib.util.module_from_spec(spec) + if not spec.loader: + raise ValueError(f"Could not get loader from {block_path}") + + spec.loader.exec_module(module) + func = getattr(module, block_name) + + logger.info(f"importing {block_type}") + functions[block_type] = func return functions def is_ui_input(func: Callable) -> bool: return getattr(func, "ui_input", False) + + +import_blocks("blocks") diff --git a/src/renderer/src/components/flow/BlockCard.tsx b/src/renderer/src/components/flow/BlockCard.tsx index 5703e60..3960f92 100644 --- a/src/renderer/src/components/flow/BlockCard.tsx +++ b/src/renderer/src/components/flow/BlockCard.tsx @@ -3,11 +3,11 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/ type Props = { name: string; - block_id: string; + block_type: string; desc: string; }; -const BlockCard = ({ name, desc, block_id }: Props): JSX.Element => { +const BlockCard = ({ name, desc, block_type }: Props): JSX.Element => { const onDragStart = (event, nodeType) => { event.dataTransfer.setData('application/reactflow', nodeType); event.dataTransfer.effectAllowed = 'move'; @@ -24,7 +24,7 @@ const BlockCard = ({ name, desc, block_id }: Props): JSX.Element => { className="" variant="secondary" draggable - onDragStart={(event) => onDragStart(event, block_id)} + onDragStart={(event) => onDragStart(event, block_type)} >