From 36ee318babc829868db399314b06558e47f23ee3 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Thu, 16 Feb 2023 01:16:07 +0000 Subject: [PATCH 1/2] Add main conceptual overview and example workflows --- docs/articles/modules.md | 24 +++++++++++ docs/articles/overview.md | 63 ++++++++++++++++++++++++++-- docs/articles/toc.yml | 4 +- docs/templates/html/styles/main.css | 3 +- docs/workflows/create-module.bonsai | 22 ++++++++++ docs/workflows/create-module.svg | 3 ++ docs/workflows/create-runtime.bonsai | 16 +++++++ docs/workflows/create-runtime.svg | 3 ++ docs/workflows/exec-eval.bonsai | 29 +++++++++++++ docs/workflows/exec-eval.svg | 3 ++ docs/workflows/get-set.bonsai | 38 +++++++++++++++++ docs/workflows/get-set.svg | 3 ++ docs/workflows/hello-python.bonsai | 23 ++++++++++ docs/workflows/hello-python.svg | 3 ++ docs/workflows/share-module.bonsai | 51 ++++++++++++++++++++++ docs/workflows/share-module.svg | 3 ++ 16 files changed, 285 insertions(+), 6 deletions(-) create mode 100644 docs/articles/modules.md create mode 100644 docs/workflows/create-module.bonsai create mode 100644 docs/workflows/create-module.svg create mode 100644 docs/workflows/create-runtime.bonsai create mode 100644 docs/workflows/create-runtime.svg create mode 100644 docs/workflows/exec-eval.bonsai create mode 100644 docs/workflows/exec-eval.svg create mode 100644 docs/workflows/get-set.bonsai create mode 100644 docs/workflows/get-set.svg create mode 100644 docs/workflows/hello-python.bonsai create mode 100644 docs/workflows/hello-python.svg create mode 100644 docs/workflows/share-module.bonsai create mode 100644 docs/workflows/share-module.svg diff --git a/docs/articles/modules.md b/docs/articles/modules.md new file mode 100644 index 0000000..1873bab --- /dev/null +++ b/docs/articles/modules.md @@ -0,0 +1,24 @@ +# Dynamic Modules + +The Python Scripting package allows you to define dynamic modules at runtime. This is useful if you need to isolate specific scripts, or keep track of state variables evolving independently in different parts of the workflow. + +To create a new module, you can use the [CreateModule](xref:Bonsai.Scripting.Python.CreateModule) operator together with a [ResourceSubject](xref:Bonsai.Reactive.ResourceSubject): + +:::workflow +![CreateModule](~/workflows/create-module.bonsai) +::: + +> [!Warning] +> Make sure to always pair the [CreateModule](xref:Bonsai.Scripting.Python.CreateModule) operator together with a [ResourceSubject](xref:Bonsai.Reactive.ResourceSubject) to ensure that your module is correctly destroyed when your workflow terminates. + +Once the module is declared, you can now pass it to any of your Python operators to make sure they run their code in the correct scope: + +:::workflow +![ShareModule](~/workflows/share-module.bonsai) +::: + +> [!Tip] +> You can think of modules as "objects", as they encapsulate all their state variables inside a unique Python scope. + +> [!Warning] +> If you do not provide a specific module for a Python scripting operator to run in, it will always run in the global Python main module. \ No newline at end of file diff --git a/docs/articles/overview.md b/docs/articles/overview.md index 6955c8c..e2b3d9b 100644 --- a/docs/articles/overview.md +++ b/docs/articles/overview.md @@ -2,10 +2,65 @@ uid: overview --- -Bonsai.Scripting.Python is a [Bonsai](https://bonsai-rx.org/) interface for the [Python](https://www.python.org/) programming language. It uses [Python.NET](https://pythonnet.github.io/pythonnet/) under the hood to provide a seamless integration between the CPython runtime and data streaming in a Bonsai workflow. +The Python Scripting package is a [Bonsai](https://bonsai-rx.org/) interface for the [Python](https://www.python.org/) programming language. It uses [Python.NET](https://pythonnet.github.io/pythonnet/) under the hood to provide a seamless integration between the CPython runtime and data streaming in a Bonsai workflow. -You can use Bonsai.Scripting.Python to run native Python scripts, import any module available to Python, and read or write to any variable in a named scope. The package is designed to work with any Python version from 3.7 onwards, and you can also use it in combination with [Python virtual environments](https://docs.python.org/3/tutorial/venv.html) to fully isolate your project dependencies. +You can use the Python Scripting package to run native Python scripts, import any module available to Python, and read or write to any variable in a named scope. The package is designed to work with any Python version from 3.7 onwards, and you can also use it in combination with [Python virtual environments](https://docs.python.org/3/tutorial/venv.html) to fully isolate your project dependencies. -## Installing the package +## How to install -To install Bonsai.Scripting.Python use the Bonsai package manager and search for the **Bonsai - Python Scripting** package. \ No newline at end of file +1. Download [Bonsai](https://bonsai-rx.org/). +2. From the package manager, search and install the **Bonsai - Python Scripting** package. + +## Create a Python environment + +In addition to the Python Scripting package you need to have a version of [Python](https://www.python.org/) installed in your system. We recommend installing the official distributions and using `venv` to create virtual environments to run your specific projects. + +To create a virtual environment you can run the following command from inside the folder where you want to install the environment: + +```ps +python -m venv example-env +``` + +## Create a Python runtime + +The [CreateRuntime](xref:Bonsai.Scripting.Python.CreateRuntime) node launches the Python kernel and creates the main global scope for running Python scripts. You must set the [PythonHome](xref:Bonsai.Scripting.Python.CreateRuntime.PythonHome) property to the environment folder (or your Python home directory) before starting the workflow: + +:::workflow +![CreateRuntime](~/workflows/create-runtime.bonsai) +::: + +Alternatively, you can activate the virtual environment *before* starting Bonsai. In this case you do not need to specify the Python home directory. + +> [!Tip] +> You can set the value of the [**ScriptPath**](xref:Bonsai.Scripting.Python.CreateRuntime.ScriptPath) property to specify a main script that will be run when the Python runtime is initialized. This script can be used to import all the main modules to be used in your workflow, or initialize any state variables to be manipulated during execution. + +## Run Python code + +The [Eval](xref:Bonsai.Scripting.Python.Eval) operator can be used anywhere in your workflow to interact with the Python runtime, just as if you were writing code in the Python REPL: + +:::workflow +![HelloPython](~/workflows/hello-python.bonsai) +::: + +You can also use the [Exec](xref:Bonsai.Scripting.Python.Exec) operator to run Python statements dynamically, for example to import new modules: + +:::workflow +![HelloPython](~/workflows/exec-eval.bonsai) +::: + +## Read and write state variables + +To interface with Python state variables, you can use the [Get](xref:Bonsai.Scripting.Python.Get) and [Set](xref:Bonsai.Scripting.Python.Set) operators: + +:::workflow +![GetSet](~/workflows/get-set.bonsai) +::: + +> [!Warning] +> All the operators in the Python Scripting package run under the Python [Global Interpreter Lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock). This means that although execution of Python code can be triggered asynchronously anywhere in the workflow, there will be a bottleneck when accessing the interpreter. Because of this, we currently do not recommend running large number of parallel calls to Python. + +## Scripting Extensions + +Custom script files can be executed when creating the Python runtime with [CreateRuntime](xref:Bonsai.Scripting.Python.CreateRuntime) or when creating a new module with [CreateModule](xref:Bonsai.Scripting.Python.CreateModule). + +To edit script files we recommend [Visual Studio Code](https://code.visualstudio.com/) and the [Python extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-python.python). If both your virtual environment and your custom Python scripts are placed relative to your main workflow, VS Code can be launched from the Bonsai IDE and will be able to correctly pick up the right environment when editing the scripts. \ No newline at end of file diff --git a/docs/articles/toc.yml b/docs/articles/toc.yml index dccf8c8..cc73e8f 100644 --- a/docs/articles/toc.yml +++ b/docs/articles/toc.yml @@ -2,4 +2,6 @@ href: intro.md items: - name: Quickstart - href: intro.md \ No newline at end of file + href: intro.md + - name: Dynamic Modules + href: modules.md \ No newline at end of file diff --git a/docs/templates/html/styles/main.css b/docs/templates/html/styles/main.css index e359389..b53f655 100644 --- a/docs/templates/html/styles/main.css +++ b/docs/templates/html/styles/main.css @@ -20,7 +20,8 @@ .workflow { border: 1px solid #e3e3e3; - padding: 1px; + padding: 2px; + margin-bottom: 10px; } .workflow > p > img { diff --git a/docs/workflows/create-module.bonsai b/docs/workflows/create-module.bonsai new file mode 100644 index 0000000..ed760e6 --- /dev/null +++ b/docs/workflows/create-module.bonsai @@ -0,0 +1,22 @@ + + + + + + + NewModule + + + + NewModule + + + + + + + \ No newline at end of file diff --git a/docs/workflows/create-module.svg b/docs/workflows/create-module.svg new file mode 100644 index 0000000..043e0f6 --- /dev/null +++ b/docs/workflows/create-module.svg @@ -0,0 +1,3 @@ + +]>NewModuleCreateModule \ No newline at end of file diff --git a/docs/workflows/create-runtime.bonsai b/docs/workflows/create-runtime.bonsai new file mode 100644 index 0000000..81e77cf --- /dev/null +++ b/docs/workflows/create-runtime.bonsai @@ -0,0 +1,16 @@ + + + + + + + example-env + + + + + + \ No newline at end of file diff --git a/docs/workflows/create-runtime.svg b/docs/workflows/create-runtime.svg new file mode 100644 index 0000000..8603573 --- /dev/null +++ b/docs/workflows/create-runtime.svg @@ -0,0 +1,3 @@ + +]>CreateRuntime \ No newline at end of file diff --git a/docs/workflows/exec-eval.bonsai b/docs/workflows/exec-eval.bonsai new file mode 100644 index 0000000..e926a80 --- /dev/null +++ b/docs/workflows/exec-eval.bonsai @@ -0,0 +1,29 @@ + + + + + + + example-env + + + + + from datetime import datetime + + + + + print(datetime.now()) + + + + + + + + + \ No newline at end of file diff --git a/docs/workflows/exec-eval.svg b/docs/workflows/exec-eval.svg new file mode 100644 index 0000000..5293e8f --- /dev/null +++ b/docs/workflows/exec-eval.svg @@ -0,0 +1,3 @@ + +]>EvalExecCreateRuntime \ No newline at end of file diff --git a/docs/workflows/get-set.bonsai b/docs/workflows/get-set.bonsai new file mode 100644 index 0000000..d2be94e --- /dev/null +++ b/docs/workflows/get-set.bonsai @@ -0,0 +1,38 @@ + + + + + + + PT0S + PT1S + + + + + time + + + + + None + false + + + + + time + + + + + + + + + \ No newline at end of file diff --git a/docs/workflows/get-set.svg b/docs/workflows/get-set.svg new file mode 100644 index 0000000..42cea7f --- /dev/null +++ b/docs/workflows/get-set.svg @@ -0,0 +1,3 @@ + +]>SetGetTimerKeyDown \ No newline at end of file diff --git a/docs/workflows/hello-python.bonsai b/docs/workflows/hello-python.bonsai new file mode 100644 index 0000000..bec9ae0 --- /dev/null +++ b/docs/workflows/hello-python.bonsai @@ -0,0 +1,23 @@ + + + + + + + example-env + + + + + print("Hello python") + + + + + + + + \ No newline at end of file diff --git a/docs/workflows/hello-python.svg b/docs/workflows/hello-python.svg new file mode 100644 index 0000000..c6e564f --- /dev/null +++ b/docs/workflows/hello-python.svg @@ -0,0 +1,3 @@ + +]>EvalCreateRuntime \ No newline at end of file diff --git a/docs/workflows/share-module.bonsai b/docs/workflows/share-module.bonsai new file mode 100644 index 0000000..f234c0c --- /dev/null +++ b/docs/workflows/share-module.bonsai @@ -0,0 +1,51 @@ + + + + + + + NewModule + + + + NewModule + + + + PT1S + PT0.01S + + + + NewModule + + + + + + + + + x + + + + + x**2 + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/workflows/share-module.svg b/docs/workflows/share-module.svg new file mode 100644 index 0000000..2c6b3fc --- /dev/null +++ b/docs/workflows/share-module.svg @@ -0,0 +1,3 @@ + +]>NewModuleEvalCreateModuleSetTimerModuleNewModule \ No newline at end of file From d46a040e4230604b45157bce708c009e3c11e83f Mon Sep 17 00:00:00 2001 From: glopesdev Date: Thu, 16 Feb 2023 01:21:28 +0000 Subject: [PATCH 2/2] Update README --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c8af60..71bd80b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ # Bonsai - Python Scripting -Bonsai.Scripting.Python is a [Bonsai](https://bonsai-rx.org/) interface for the [Python](https://www.python.org/) programming language. It uses [Python.NET](https://pythonnet.github.io/pythonnet/) under the hood to provide a seamless integration between the CPython runtime and data streaming in a Bonsai workflow. \ No newline at end of file +Bonsai.Scripting.Python is a [Bonsai](https://bonsai-rx.org/) interface for the [Python](https://www.python.org/) programming language. It uses [Python.NET](https://pythonnet.github.io/pythonnet/) under the hood to provide a seamless integration between the CPython runtime and data streaming in a Bonsai workflow. + +You can use the Python Scripting package to run native Python scripts, import any module available to Python, and read or write to any variable in a named scope. The package is designed to work with any Python version from 3.7 onwards, and you can also use it in combination with [Python virtual environments](https://docs.python.org/3/tutorial/venv.html) to fully isolate your project dependencies. + +## Documentation + +Both conceptual and reference documentation can be found [here](https://bonsai-rx.org/python-scripting/). \ No newline at end of file