From a4940401c20478b5a01fb724101962eddf62f2fa Mon Sep 17 00:00:00 2001 From: haixuantao Date: Sat, 4 Jan 2025 21:06:11 +0100 Subject: [PATCH 1/8] Rewrite python template to make them pip installable --- .../src/template/python/dataflow-template.yml | 7 +- .../python/listener/listener-template.py | 4 +- binaries/cli/src/template/python/mod.rs | 71 +++++++++++++++---- .../src/template/python/node-name/README.md | 1 + .../python/node-name/node_name/__init__.py | 11 +++ .../python/node-name/node_name/__main__.py | 5 ++ .../python/node-name/node_name/main.py | 21 ++++++ .../template/python/node-name/pyproject.toml | 23 ++++++ .../python/node-name/tests/test_node_name.py | 9 +++ .../src/template/python/node/node-template.py | 15 ---- 10 files changed, 134 insertions(+), 33 deletions(-) create mode 100644 binaries/cli/src/template/python/node-name/README.md create mode 100644 binaries/cli/src/template/python/node-name/node_name/__init__.py create mode 100644 binaries/cli/src/template/python/node-name/node_name/__main__.py create mode 100644 binaries/cli/src/template/python/node-name/node_name/main.py create mode 100644 binaries/cli/src/template/python/node-name/pyproject.toml create mode 100644 binaries/cli/src/template/python/node-name/tests/test_node_name.py delete mode 100644 binaries/cli/src/template/python/node/node-template.py diff --git a/binaries/cli/src/template/python/dataflow-template.yml b/binaries/cli/src/template/python/dataflow-template.yml index 2fa63651..3797b98c 100644 --- a/binaries/cli/src/template/python/dataflow-template.yml +++ b/binaries/cli/src/template/python/dataflow-template.yml @@ -1,19 +1,20 @@ nodes: - id: talker_1 - path: talker_1/talker_1.py + path: talker-1/talker_1/main.py inputs: tick: dora/timer/millis/100 outputs: - speech + - id: talker_2 - path: talker_2/talker_2.py + path: talker-2/talker_2/main.py inputs: tick: dora/timer/secs/2 outputs: - speech - id: listener_1 - path: listener_1/listener_1.py + path: listener-1/listener_1/main.py inputs: speech-1: talker_1/speech speech-2: talker_2/speech diff --git a/binaries/cli/src/template/python/listener/listener-template.py b/binaries/cli/src/template/python/listener/listener-template.py index 82c8f809..45539e51 100644 --- a/binaries/cli/src/template/python/listener/listener-template.py +++ b/binaries/cli/src/template/python/listener/listener-template.py @@ -6,6 +6,4 @@ node = Node() for event in node: if event["type"] == "INPUT": message = event["value"][0].as_py() - print( - f"""I heard {message} from {event["id"]}""" - ) + print(f"""I heard {message} from {event["id"]}""") diff --git a/binaries/cli/src/template/python/mod.rs b/binaries/cli/src/template/python/mod.rs index 4c8eb435..96c938ad 100644 --- a/binaries/cli/src/template/python/mod.rs +++ b/binaries/cli/src/template/python/mod.rs @@ -4,7 +4,13 @@ use std::{ path::{Path, PathBuf}, }; -const NODE_PY: &str = include_str!("node/node-template.py"); +const MAIN_PY: &str = include_str!("node-name/node_name/main.py"); +const _MAIN_PY: &str = include_str!("node-name/node_name/__main__.py"); +const _INIT_PY: &str = include_str!("node-name/node_name/__init__.py"); +const _TEST_PY: &str = include_str!("node-name/tests/test_node_name.py"); +const PYPROJECT_TOML: &str = include_str!("node-name/pyproject.toml"); +const README_MD: &str = include_str!("node-name/README.md"); + const TALKER_PY: &str = include_str!("talker/talker-template.py"); const LISTENER_PY: &str = include_str!("listener/listener-template.py"); @@ -17,23 +23,64 @@ pub fn create(args: crate::CommandNew) -> eyre::Result<()> { } = args; match kind { - crate::Kind::CustomNode => create_custom_node(name, path, NODE_PY), + crate::Kind::CustomNode => create_custom_node(name, path, MAIN_PY), crate::Kind::Dataflow => create_dataflow(name, path), } } +fn replace_space(file: &str, name: &str) -> String { + let file = file.replace("node-name", &name.replace(" ", "-")); + file.replace("node_name", &name.replace(" ", "_")) +} fn create_custom_node( name: String, path: Option, - template_scripts: &str, + main: &str, ) -> Result<(), eyre::ErrReport> { // create directories - let root = path.as_deref().unwrap_or_else(|| Path::new(&name)); - fs::create_dir(root) - .with_context(|| format!("failed to create directory `{}`", root.display()))?; + let root = path.unwrap_or_else(|| PathBuf::from(name.replace(" ", "-"))); + let module_path = root.join(name.replace(" ", "_")); + fs::create_dir(&root) + .with_context(|| format!("failed to create directory `{}`", &root.display()))?; + + fs::create_dir(&module_path) + .with_context(|| format!("failed to create directory `{}`", &root.display()))?; + + fs::create_dir(&root.join("tests")) + .with_context(|| format!("failed to create directory `{}`", &root.display()))?; + + // PYPROJECT.toml + let node_path = root.join("pyproject.toml"); + let pyproject = replace_space(PYPROJECT_TOML, &name); + fs::write(&node_path, pyproject) + .with_context(|| format!("failed to write `{}`", node_path.display()))?; + + // README.md + let node_path = root.join("README.md"); + fs::write(&node_path, README_MD.replace("name", &name)) + .with_context(|| format!("failed to write `{}`", node_path.display()))?; + + // main.py + let node_path = module_path.join("main.py"); + fs::write(&node_path, main) + .with_context(|| format!("failed to write `{}`", node_path.display()))?; + + // __main__.py + let node_path = module_path.join("__main__.py"); + fs::write(&node_path, _MAIN_PY) + .with_context(|| format!("failed to write `{}`", node_path.display()))?; + + // __init__.py + let node_path = module_path.join("__init__.py"); + fs::write(&node_path, _INIT_PY) + .with_context(|| format!("failed to write `{}`", node_path.display()))?; - let node_path = root.join(format!("{name}.py")); - fs::write(&node_path, template_scripts) + // tests/tests_node_name.py + let node_path = root + .join("tests") + .join(format!("tests_{}.py", name.replace(" ", "_"))); + let file = replace_space(_TEST_PY, &name); + fs::write(&node_path, file) .with_context(|| format!("failed to write `{}`", node_path.display()))?; println!( @@ -64,11 +111,11 @@ fn create_dataflow(name: String, path: Option) -> Result<(), eyre::ErrR fs::write(&dataflow_yml_path, dataflow_yml) .with_context(|| format!("failed to write `{}`", dataflow_yml_path.display()))?; - create_custom_node("talker_1".into(), Some(root.join("talker_1")), TALKER_PY)?; - create_custom_node("talker_2".into(), Some(root.join("talker_2")), TALKER_PY)?; + create_custom_node("talker 1".into(), Some(root.join("talker-1")), TALKER_PY)?; + create_custom_node("talker 2".into(), Some(root.join("talker-2")), TALKER_PY)?; create_custom_node( - "listener_1".into(), - Some(root.join("listener_1")), + "listener 1".into(), + Some(root.join("listener-1")), LISTENER_PY, )?; diff --git a/binaries/cli/src/template/python/node-name/README.md b/binaries/cli/src/template/python/node-name/README.md new file mode 100644 index 00000000..5f4656ae --- /dev/null +++ b/binaries/cli/src/template/python/node-name/README.md @@ -0,0 +1 @@ +# name diff --git a/binaries/cli/src/template/python/node-name/node_name/__init__.py b/binaries/cli/src/template/python/node-name/node_name/__init__.py new file mode 100644 index 00000000..ac3cbef9 --- /dev/null +++ b/binaries/cli/src/template/python/node-name/node_name/__init__.py @@ -0,0 +1,11 @@ +import os + +# Define the path to the README file relative to the package directory +readme_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "README.md") + +# Read the content of the README file +try: + with open(readme_path, "r", encoding="utf-8") as f: + __doc__ = f.read() +except FileNotFoundError: + __doc__ = "README file not found." diff --git a/binaries/cli/src/template/python/node-name/node_name/__main__.py b/binaries/cli/src/template/python/node-name/node_name/__main__.py new file mode 100644 index 00000000..bcbfde6d --- /dev/null +++ b/binaries/cli/src/template/python/node-name/node_name/__main__.py @@ -0,0 +1,5 @@ +from .main import main + + +if __name__ == "__main__": + main() diff --git a/binaries/cli/src/template/python/node-name/node_name/main.py b/binaries/cli/src/template/python/node-name/node_name/main.py new file mode 100644 index 00000000..8b953050 --- /dev/null +++ b/binaries/cli/src/template/python/node-name/node_name/main.py @@ -0,0 +1,21 @@ +import os +from dora import Node + +RUNNER_CI = True if os.getenv("CI") == "true" else False + + +def main(): + node = Node() + + for event in node: + if event["type"] == "INPUT": + print( + f"""Node received: + id: {event["id"]}, + value: {event["value"]}, + metadata: {event["metadata"]}""" + ) + + +if __name__ == "__main__": + main() diff --git a/binaries/cli/src/template/python/node-name/pyproject.toml b/binaries/cli/src/template/python/node-name/pyproject.toml new file mode 100644 index 00000000..3c162807 --- /dev/null +++ b/binaries/cli/src/template/python/node-name/pyproject.toml @@ -0,0 +1,23 @@ +[tool.poetry] +name = "node-name" +version = "0.0.1" +authors = ["author"] +description = "Node Name" +license = "MIT License" +homepage = "https://github.com/dora-rs/dora.git" +documentation = "https://github.com/dora-rs/dora/blob/main/node-hub/node-name/README.md" +readme = "README.md" +packages = [{ include = "node_name" }] + +[tool.poetry.dependencies] +dora-rs = "^0.3.6" +numpy = "< 2.0.0" +pyarrow = ">= 5.0.0" +python = "^3.7" + +[tool.poetry.scripts] +node-name = "node_name.main:main" + +[build-system] +requires = ["poetry-core>=1.8.0"] +build-backend = "poetry.core.masonry.api" diff --git a/binaries/cli/src/template/python/node-name/tests/test_node_name.py b/binaries/cli/src/template/python/node-name/tests/test_node_name.py new file mode 100644 index 00000000..1ed74b07 --- /dev/null +++ b/binaries/cli/src/template/python/node-name/tests/test_node_name.py @@ -0,0 +1,9 @@ +import pytest + + +def test_import_main(): + from node_name.main import main + + # Check that everything is working, and catch dora Runtime Exception as we're not running in a dora dataflow. + with pytest.raises(RuntimeError): + main() diff --git a/binaries/cli/src/template/python/node/node-template.py b/binaries/cli/src/template/python/node/node-template.py deleted file mode 100644 index f29c0a99..00000000 --- a/binaries/cli/src/template/python/node/node-template.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from dora import Node - -node = Node() - -event = node.next() -if event["type"] == "INPUT": - print( - f"""Node received: - id: {event["id"]}, - value: {event["value"]}, - metadata: {event["metadata"]}""" - ) From 0d22903670474b9334800d0254a9d472470da705 Mon Sep 17 00:00:00 2001 From: haixuantao Date: Sat, 4 Jan 2025 21:17:05 +0100 Subject: [PATCH 2/8] Add send_output example --- .../python/node-name/node_name/main.py | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/binaries/cli/src/template/python/node-name/node_name/main.py b/binaries/cli/src/template/python/node-name/node_name/main.py index 8b953050..ae95012c 100644 --- a/binaries/cli/src/template/python/node-name/node_name/main.py +++ b/binaries/cli/src/template/python/node-name/node_name/main.py @@ -1,7 +1,5 @@ -import os from dora import Node - -RUNNER_CI = True if os.getenv("CI") == "true" else False +import pyarrow as pa def main(): @@ -9,12 +7,19 @@ def main(): for event in node: if event["type"] == "INPUT": - print( - f"""Node received: - id: {event["id"]}, - value: {event["value"]}, - metadata: {event["metadata"]}""" - ) + if event["id"] == "TICK": + print( + f"""Node received: + id: {event["id"]}, + value: {event["value"]}, + metadata: {event["metadata"]}""" + ) + + else: + # Warning: Make sure to add the output event_id within the dataflow. + node.send_output( + output_id="event_id", data=pa.array([1, 2, 3]), metadata={} + ) if __name__ == "__main__": From ad6ddb237d4e12c1e7d9a745002add2067119623 Mon Sep 17 00:00:00 2001 From: haixuantao Date: Mon, 6 Jan 2025 10:56:03 +0100 Subject: [PATCH 3/8] Improve dora new template to be compliant with formatting, linting, and testing --- .github/workflows/ci.yml | 9 +++++- .../python/listener/listener-template.py | 16 +++++++---- binaries/cli/src/template/python/mod.rs | 2 +- .../template/python/talker/talker-template.py | 28 +++++++++++-------- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b7882f9..a5bf93a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -310,11 +310,18 @@ jobs: mv .venv/Scripts .venv/bin # venv is placed under `Scripts` on Windows fi source .venv/bin/activate - pip3 install maturin + pip3 install maturin black pylint pytest maturin build -m apis/python/node/Cargo.toml pip3 install target/wheels/* dora new test_python_project --lang python --internal-create-with-path-dependencies cd test_python_project + + # Check Compliancy + black . --check + pylint --disable=C,R --ignored-modules=cv2,pyrealsense2 **/*.py + pip install -e ./*/ + pytest + dora up dora list dora build dataflow.yml diff --git a/binaries/cli/src/template/python/listener/listener-template.py b/binaries/cli/src/template/python/listener/listener-template.py index 45539e51..b94fa167 100644 --- a/binaries/cli/src/template/python/listener/listener-template.py +++ b/binaries/cli/src/template/python/listener/listener-template.py @@ -1,9 +1,13 @@ from dora import Node -import pyarrow as pa -node = Node() -for event in node: - if event["type"] == "INPUT": - message = event["value"][0].as_py() - print(f"""I heard {message} from {event["id"]}""") +def main(): + node = Node() + for event in node: + if event["type"] == "INPUT": + message = event["value"][0].as_py() + print(f"""I heard {message} from {event["id"]}""") + + +if __name__ == "__main__": + main() diff --git a/binaries/cli/src/template/python/mod.rs b/binaries/cli/src/template/python/mod.rs index 96c938ad..6fd6387a 100644 --- a/binaries/cli/src/template/python/mod.rs +++ b/binaries/cli/src/template/python/mod.rs @@ -78,7 +78,7 @@ fn create_custom_node( // tests/tests_node_name.py let node_path = root .join("tests") - .join(format!("tests_{}.py", name.replace(" ", "_"))); + .join(format!("test_{}.py", name.replace(" ", "_"))); let file = replace_space(_TEST_PY, &name); fs::write(&node_path, file) .with_context(|| format!("failed to write `{}`", node_path.display()))?; diff --git a/binaries/cli/src/template/python/talker/talker-template.py b/binaries/cli/src/template/python/talker/talker-template.py index 93324e40..7cc5456a 100644 --- a/binaries/cli/src/template/python/talker/talker-template.py +++ b/binaries/cli/src/template/python/talker/talker-template.py @@ -1,14 +1,20 @@ from dora import Node import pyarrow as pa -node = Node() - -for event in node: - if event["type"] == "INPUT": - print( - f"""Node received: - id: {event["id"]}, - value: {event["value"]}, - metadata: {event["metadata"]}""" - ) - node.send_output("speech", pa.array(["Hello World"])) + +def main(): + node = Node() + + for event in node: + if event["type"] == "INPUT": + print( + f"""Node received: + id: {event["id"]}, + value: {event["value"]}, + metadata: {event["metadata"]}""" + ) + node.send_output("speech", pa.array(["Hello World"])) + + +if __name__ == "__main__": + main() From c07a956b33fd1b00c6ded282c8e6ed164e011c1c Mon Sep 17 00:00:00 2001 From: haixuantao Date: Mon, 6 Jan 2025 11:00:55 +0100 Subject: [PATCH 4/8] Rename CustomNode just Node --- binaries/cli/src/lib.rs | 2 +- binaries/cli/src/template/c/mod.rs | 2 +- binaries/cli/src/template/cxx/mod.rs | 2 +- binaries/cli/src/template/python/mod.rs | 2 +- binaries/cli/src/template/rust/mod.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/binaries/cli/src/lib.rs b/binaries/cli/src/lib.rs index 3bd2c1e6..a59e49cd 100644 --- a/binaries/cli/src/lib.rs +++ b/binaries/cli/src/lib.rs @@ -254,7 +254,7 @@ pub struct CommandNew { #[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)] enum Kind { Dataflow, - CustomNode, + Node, } #[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)] diff --git a/binaries/cli/src/template/c/mod.rs b/binaries/cli/src/template/c/mod.rs index 378c572c..879eeedb 100644 --- a/binaries/cli/src/template/c/mod.rs +++ b/binaries/cli/src/template/c/mod.rs @@ -18,7 +18,7 @@ pub fn create(args: crate::CommandNew, use_path_deps: bool) -> eyre::Result<()> } = args; match kind { - crate::Kind::CustomNode => create_custom_node(name, path, NODE), + crate::Kind::Node => create_custom_node(name, path, NODE), crate::Kind::Dataflow => create_dataflow(name, path, use_path_deps), } } diff --git a/binaries/cli/src/template/cxx/mod.rs b/binaries/cli/src/template/cxx/mod.rs index 09935031..72b7769e 100644 --- a/binaries/cli/src/template/cxx/mod.rs +++ b/binaries/cli/src/template/cxx/mod.rs @@ -17,7 +17,7 @@ pub fn create(args: crate::CommandNew, use_path_deps: bool) -> eyre::Result<()> } = args; match kind { - crate::Kind::CustomNode => create_custom_node(name, path, NODE), + crate::Kind::Node => create_custom_node(name, path, NODE), crate::Kind::Dataflow => create_dataflow(name, path, use_path_deps), } } diff --git a/binaries/cli/src/template/python/mod.rs b/binaries/cli/src/template/python/mod.rs index 6fd6387a..36d8eb79 100644 --- a/binaries/cli/src/template/python/mod.rs +++ b/binaries/cli/src/template/python/mod.rs @@ -23,7 +23,7 @@ pub fn create(args: crate::CommandNew) -> eyre::Result<()> { } = args; match kind { - crate::Kind::CustomNode => create_custom_node(name, path, MAIN_PY), + crate::Kind::Node => create_custom_node(name, path, MAIN_PY), crate::Kind::Dataflow => create_dataflow(name, path), } } diff --git a/binaries/cli/src/template/rust/mod.rs b/binaries/cli/src/template/rust/mod.rs index a0f4717c..f2c9fd9c 100644 --- a/binaries/cli/src/template/rust/mod.rs +++ b/binaries/cli/src/template/rust/mod.rs @@ -18,7 +18,7 @@ pub fn create(args: crate::CommandNew, use_path_deps: bool) -> eyre::Result<()> } = args; match kind { - crate::Kind::CustomNode => create_custom_node(name, path, use_path_deps, MAIN_RS), + crate::Kind::Node => create_custom_node(name, path, use_path_deps, MAIN_RS), crate::Kind::Dataflow => create_dataflow(name, path, use_path_deps), } } From 1ff458392250f9b322b9fe687e699621dafe36e2 Mon Sep 17 00:00:00 2001 From: haixuantao Date: Mon, 6 Jan 2025 11:09:19 +0100 Subject: [PATCH 5/8] Improve compliancy guideline --- .github/workflows/ci.yml | 2 +- binaries/cli/src/template/python/mod.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5bf93a6..e8c55ba3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -318,7 +318,7 @@ jobs: # Check Compliancy black . --check - pylint --disable=C,R --ignored-modules=cv2,pyrealsense2 **/*.py + pylint --disable=C,R **/*.py pip install -e ./*/ pytest diff --git a/binaries/cli/src/template/python/mod.rs b/binaries/cli/src/template/python/mod.rs index 36d8eb79..778d15c4 100644 --- a/binaries/cli/src/template/python/mod.rs +++ b/binaries/cli/src/template/python/mod.rs @@ -85,8 +85,18 @@ fn create_custom_node( println!( "Created new Python node `{name}` at {}", - Path::new(".").join(root).display() + Path::new(".").join(&root).display() + ); + println!( + " pip install -e {} # Install", + Path::new(".").join(&root).display() + ); + println!(" black {} # Format", Path::new(".").join(&root).display()); + println!( + " pylint --disable=C,R {} # Lint", + Path::new(".").join(&root).display() ); + println!(" pytest {} # Test", Path::new(".").join(&root).display()); Ok(()) } From 134e6c94b690730d6279205e25bb5ee3a8ecefde Mon Sep 17 00:00:00 2001 From: haixuantao Date: Mon, 6 Jan 2025 11:12:26 +0100 Subject: [PATCH 6/8] Add compliancy tool in requirements --- binaries/cli/src/template/python/node-name/pyproject.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/binaries/cli/src/template/python/node-name/pyproject.toml b/binaries/cli/src/template/python/node-name/pyproject.toml index 3c162807..cb94c6fd 100644 --- a/binaries/cli/src/template/python/node-name/pyproject.toml +++ b/binaries/cli/src/template/python/node-name/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "node-name" -version = "0.0.1" +version = "0.0.0" authors = ["author"] description = "Node Name" license = "MIT License" @@ -15,6 +15,11 @@ numpy = "< 2.0.0" pyarrow = ">= 5.0.0" python = "^3.7" +[tool.poetry.dev-dependencies] +pytest = ">= 8.3.4" +pylint = ">= 3.3.2" +black = ">= 24.10" + [tool.poetry.scripts] node-name = "node_name.main:main" From 25731176103b6af52f2b64e4c90c0c4760bcd79c Mon Sep 17 00:00:00 2001 From: haixuantao Date: Thu, 9 Jan 2025 18:15:34 +0100 Subject: [PATCH 7/8] Add category within README.md --- binaries/cli/src/template/python/node-name/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/binaries/cli/src/template/python/node-name/README.md b/binaries/cli/src/template/python/node-name/README.md index 5f4656ae..18a052cc 100644 --- a/binaries/cli/src/template/python/node-name/README.md +++ b/binaries/cli/src/template/python/node-name/README.md @@ -1 +1,9 @@ # name + +## YAML Specification + +## Examples + +## License + +name's code are released under the MIT License From 52d883e6b57f666d6232b0eeba08db72172af1c0 Mon Sep 17 00:00:00 2001 From: haixuantao Date: Sun, 12 Jan 2025 14:10:33 +0100 Subject: [PATCH 8/8] Minor template fix --- .../template/python/__node-name__/README.md | 37 +++++++++++++++ .../__node_name__}/__init__.py | 0 .../__node_name__}/__main__.py | 0 .../__node_name__}/main.py | 6 +-- .../pyproject.toml | 8 ++-- .../tests/test___node_name__.py} | 2 +- binaries/cli/src/template/python/mod.rs | 46 +++++++++---------- .../src/template/python/node-name/README.md | 9 ---- 8 files changed, 66 insertions(+), 42 deletions(-) create mode 100644 binaries/cli/src/template/python/__node-name__/README.md rename binaries/cli/src/template/python/{node-name/node_name => __node-name__/__node_name__}/__init__.py (100%) rename binaries/cli/src/template/python/{node-name/node_name => __node-name__/__node_name__}/__main__.py (100%) rename binaries/cli/src/template/python/{node-name/node_name => __node-name__/__node_name__}/main.py (67%) rename binaries/cli/src/template/python/{node-name => __node-name__}/pyproject.toml (79%) rename binaries/cli/src/template/python/{node-name/tests/test_node_name.py => __node-name__/tests/test___node_name__.py} (83%) delete mode 100644 binaries/cli/src/template/python/node-name/README.md diff --git a/binaries/cli/src/template/python/__node-name__/README.md b/binaries/cli/src/template/python/__node-name__/README.md new file mode 100644 index 00000000..81b12cc0 --- /dev/null +++ b/binaries/cli/src/template/python/__node-name__/README.md @@ -0,0 +1,37 @@ +# Node Name + +## Getting started + +- Install it with pip: + +```bash +pip install -e . +``` + +## Contribution Guide + +- Format with [black](https://github.com/psf/black): + +```bash +black . # Format +``` + +- Lint with [pylint](https://github.com/pylint-dev/pylint): + +```bash +pylint --disable=C,R --ignored-modules=cv2 . # Lint +``` + +- Test with [pytest](https://github.com/pytest-dev/pytest) + +```bash +pytest . # Test +``` + +## YAML Specification + +## Examples + +## License + +Node Name's code are released under the MIT License diff --git a/binaries/cli/src/template/python/node-name/node_name/__init__.py b/binaries/cli/src/template/python/__node-name__/__node_name__/__init__.py similarity index 100% rename from binaries/cli/src/template/python/node-name/node_name/__init__.py rename to binaries/cli/src/template/python/__node-name__/__node_name__/__init__.py diff --git a/binaries/cli/src/template/python/node-name/node_name/__main__.py b/binaries/cli/src/template/python/__node-name__/__node_name__/__main__.py similarity index 100% rename from binaries/cli/src/template/python/node-name/node_name/__main__.py rename to binaries/cli/src/template/python/__node-name__/__node_name__/__main__.py diff --git a/binaries/cli/src/template/python/node-name/node_name/main.py b/binaries/cli/src/template/python/__node-name__/__node_name__/main.py similarity index 67% rename from binaries/cli/src/template/python/node-name/node_name/main.py rename to binaries/cli/src/template/python/__node-name__/__node_name__/main.py index ae95012c..823e2e09 100644 --- a/binaries/cli/src/template/python/node-name/node_name/main.py +++ b/binaries/cli/src/template/python/__node-name__/__node_name__/main.py @@ -15,10 +15,10 @@ def main(): metadata: {event["metadata"]}""" ) - else: - # Warning: Make sure to add the output event_id within the dataflow. + elif event["id"] == "my_input_id": + # Warning: Make sure to add my_output_id and my_input_id within the dataflow. node.send_output( - output_id="event_id", data=pa.array([1, 2, 3]), metadata={} + output_id="my_output_id", data=pa.array([1, 2, 3]), metadata={} ) diff --git a/binaries/cli/src/template/python/node-name/pyproject.toml b/binaries/cli/src/template/python/__node-name__/pyproject.toml similarity index 79% rename from binaries/cli/src/template/python/node-name/pyproject.toml rename to binaries/cli/src/template/python/__node-name__/pyproject.toml index cb94c6fd..a54fb19e 100644 --- a/binaries/cli/src/template/python/node-name/pyproject.toml +++ b/binaries/cli/src/template/python/__node-name__/pyproject.toml @@ -1,13 +1,13 @@ [tool.poetry] -name = "node-name" +name = "__node-name__" version = "0.0.0" authors = ["author"] description = "Node Name" license = "MIT License" homepage = "https://github.com/dora-rs/dora.git" -documentation = "https://github.com/dora-rs/dora/blob/main/node-hub/node-name/README.md" +documentation = "https://github.com/dora-rs/dora/blob/main/node-hub/__node-name__/README.md" readme = "README.md" -packages = [{ include = "node_name" }] +packages = [{ include = "__node_name__" }] [tool.poetry.dependencies] dora-rs = "^0.3.6" @@ -21,7 +21,7 @@ pylint = ">= 3.3.2" black = ">= 24.10" [tool.poetry.scripts] -node-name = "node_name.main:main" +__node-name__ = "__node_name__.main:main" [build-system] requires = ["poetry-core>=1.8.0"] diff --git a/binaries/cli/src/template/python/node-name/tests/test_node_name.py b/binaries/cli/src/template/python/__node-name__/tests/test___node_name__.py similarity index 83% rename from binaries/cli/src/template/python/node-name/tests/test_node_name.py rename to binaries/cli/src/template/python/__node-name__/tests/test___node_name__.py index 1ed74b07..7fefda95 100644 --- a/binaries/cli/src/template/python/node-name/tests/test_node_name.py +++ b/binaries/cli/src/template/python/__node-name__/tests/test___node_name__.py @@ -2,7 +2,7 @@ import pytest def test_import_main(): - from node_name.main import main + from __node_name__.main import main # Check that everything is working, and catch dora Runtime Exception as we're not running in a dora dataflow. with pytest.raises(RuntimeError): diff --git a/binaries/cli/src/template/python/mod.rs b/binaries/cli/src/template/python/mod.rs index 778d15c4..911141eb 100644 --- a/binaries/cli/src/template/python/mod.rs +++ b/binaries/cli/src/template/python/mod.rs @@ -4,12 +4,12 @@ use std::{ path::{Path, PathBuf}, }; -const MAIN_PY: &str = include_str!("node-name/node_name/main.py"); -const _MAIN_PY: &str = include_str!("node-name/node_name/__main__.py"); -const _INIT_PY: &str = include_str!("node-name/node_name/__init__.py"); -const _TEST_PY: &str = include_str!("node-name/tests/test_node_name.py"); -const PYPROJECT_TOML: &str = include_str!("node-name/pyproject.toml"); -const README_MD: &str = include_str!("node-name/README.md"); +const MAIN_PY: &str = include_str!("__node-name__/__node_name__/main.py"); +const _MAIN_PY: &str = include_str!("__node-name__/__node_name__/__main__.py"); +const _INIT_PY: &str = include_str!("__node-name__/__node_name__/__init__.py"); +const _TEST_PY: &str = include_str!("__node-name__/tests/test___node_name__.py"); +const PYPROJECT_TOML: &str = include_str!("__node-name__/pyproject.toml"); +const README_MD: &str = include_str!("__node-name__/README.md"); const TALKER_PY: &str = include_str!("talker/talker-template.py"); const LISTENER_PY: &str = include_str!("listener/listener-template.py"); @@ -29,8 +29,9 @@ pub fn create(args: crate::CommandNew) -> eyre::Result<()> { } fn replace_space(file: &str, name: &str) -> String { - let file = file.replace("node-name", &name.replace(" ", "-")); - file.replace("node_name", &name.replace(" ", "_")) + let mut file = file.replace("__node-name__", &name.replace(" ", "-")); + file = file.replace("__node_name__", &name.replace("-", "_").replace(" ", "_")); + file.replace("Node Name", &name) } fn create_custom_node( name: String, @@ -39,15 +40,15 @@ fn create_custom_node( ) -> Result<(), eyre::ErrReport> { // create directories let root = path.unwrap_or_else(|| PathBuf::from(name.replace(" ", "-"))); - let module_path = root.join(name.replace(" ", "_")); + let module_path = root.join(name.replace(" ", "_").replace("-", "_")); fs::create_dir(&root) - .with_context(|| format!("failed to create directory `{}`", &root.display()))?; + .with_context(|| format!("failed to create root directory `{}`", &root.display()))?; fs::create_dir(&module_path) - .with_context(|| format!("failed to create directory `{}`", &root.display()))?; + .with_context(|| format!("failed to create module directory `{}`", &root.display()))?; fs::create_dir(&root.join("tests")) - .with_context(|| format!("failed to create directory `{}`", &root.display()))?; + .with_context(|| format!("failed to create tests directory `{}`", &root.display()))?; // PYPROJECT.toml let node_path = root.join("pyproject.toml"); @@ -57,7 +58,7 @@ fn create_custom_node( // README.md let node_path = root.join("README.md"); - fs::write(&node_path, README_MD.replace("name", &name)) + fs::write(&node_path, README_MD.replace("Node Name", &name)) .with_context(|| format!("failed to write `{}`", node_path.display()))?; // main.py @@ -75,7 +76,7 @@ fn create_custom_node( fs::write(&node_path, _INIT_PY) .with_context(|| format!("failed to write `{}`", node_path.display()))?; - // tests/tests_node_name.py + // tests/tests___node_name__.py let node_path = root .join("tests") .join(format!("test_{}.py", name.replace(" ", "_"))); @@ -87,16 +88,11 @@ fn create_custom_node( "Created new Python node `{name}` at {}", Path::new(".").join(&root).display() ); - println!( - " pip install -e {} # Install", - Path::new(".").join(&root).display() - ); - println!(" black {} # Format", Path::new(".").join(&root).display()); - println!( - " pylint --disable=C,R {} # Lint", - Path::new(".").join(&root).display() - ); - println!(" pytest {} # Test", Path::new(".").join(&root).display()); + println!(" cd {}", Path::new(".").join(&root).display()); + println!(" pip install -e . # Install",); + println!(" black . # Format"); + println!(" pylint --disable=C,R . # Lint",); + println!(" pytest . # Test"); Ok(()) } @@ -114,7 +110,7 @@ fn create_dataflow(name: String, path: Option) -> Result<(), eyre::ErrR // create directories let root = path.as_deref().unwrap_or_else(|| Path::new(&name)); fs::create_dir(root) - .with_context(|| format!("failed to create directory `{}`", root.display()))?; + .with_context(|| format!("failed to create module directory `{}`", root.display()))?; let dataflow_yml = DATAFLOW_YML.replace("___name___", &name); let dataflow_yml_path = root.join("dataflow.yml"); diff --git a/binaries/cli/src/template/python/node-name/README.md b/binaries/cli/src/template/python/node-name/README.md deleted file mode 100644 index 18a052cc..00000000 --- a/binaries/cli/src/template/python/node-name/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# name - -## YAML Specification - -## Examples - -## License - -name's code are released under the MIT License