Creating an extension package#

This guide explains how to create an OrangeQS Juice extension that can be installed inside the OrangeQS Juice framework.

What is a Juice extension?#

An OrangeQS Juice extension is a Python package that extends the functionality of the OrangeQS Juice framework. It can define new components, such as dashboard pages, configuration schemas, database models, client methods and more. A full list of extension capabilities can be found below:

  • Dashboard pages

  • Configuration schemas

  • Client methods

  • Service implementations

  • Database models

  • Task models

  • Pub/sub models

Setting up a Python package#

As an OrangeQS Juice extension is a standard Python package, start by setting up an empty Python package structure following the Python Packaging User Guide. Ensure that your package is pip installable in your local environment, e.g. using uv pip install -e . from the root folder of your package. For the following sections we assume you have set up a package with the following structure:

juice_extension_example/
├── pyproject.toml
└── src/
    └── juice_extension_example/
        └── __init__.py

Adding a configuration folder#

To interact with the Juice configuration, your extension can bundle configuration files that are automatically loaded when the extension is installed. This can be used to for example add a new dashboard page. To do this, follow these steps:

  1. Create a config folder in your package, e.g. src/juice_extension_example/config. This means the import path of this folder will be juice_extension_example.config. You will need this import path in the next steps!

  2. Add a dummy configuration file there, e.g. dummy.toml: src/juice_extension_example/config/dummy.toml

    [example]
    value = "This is a dummy configuration file."
    
  3. Configure your extension to package all files in the config folder. It depends on the build backend that you are using how do this. For example, if you are using setuptools (the default), this can be done as follows in pyproject.toml:

    [tool.setuptools.package-data]
    "juice_extension_example.config" = ["**/*"]
    
  4. Register the configuration folder with Juice in pyproject.toml:

    [project.entry-points."juice.config"]
    config = "juice_extension_example.config"
    
  5. Reinstall your package in your local environment. If you are using uv, run uv pip install -e . from the root folder of your package.

  6. The configuration file should now be picked up by Juice. Run the following command in your local environment to test this. It should display the contents of the dummy.toml file.

    juice config list dummy
    

Your file structure should now look like this:

juice_extension_example/
├── pyproject.toml
└── src/
    └── juice_extension_example/
        ├── __init__.py
        └── config/
            └── dummy.toml

Example: Adding a client method#

As a proof of concept, we will add a simple client method to our extension. Client methods are Python functions that are available from the Juice Client.

To add a client method, create a new Python module in your package, e.g. client_methods.py, and define a function that you want to expose as a client method. For example:

src/juice_extension_example/client_methods.py

def hello_world():
    print("Hello, world!")

Next, let’s register this function as a client method in our extension. We do this by defining an entrypoint in pyproject.toml:

pyproject.toml

[project.entry-points."juice.client"]
hello_world = "juice_extension_example.client_methods:hello_world"

Your extension is now ready to be installed in an OrangeQS Juice development environment.

Note

After installing the extension package, this method can be called as follows:

from orangeqs.juice import Client

client = Client()
client.hello_world()