Skip to content

Commit

Permalink
Improve documentation (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
faradox committed Nov 24, 2023
1 parent 14d8d88 commit cede997
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 37 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,8 @@ and then run it using nendo:
from nendo import Nendo

nd = Nendo(plugins=["nendo_plugin_musicgen"])
song = nd.plugins.musicgen(prompt="funky 70s disco", bpm=120)
song.export("funky_disco.mp3")

songs = nd.plugins.musicgen(prompt="funky 70s disco", bpm=120)
songs[0].export("funky_disco.mp3")
```

Please refer to the [documentation](https://okio.ai/docs/usage/) to learn more about how to use nendo.
Expand All @@ -117,7 +116,7 @@ Nendo thrives on its rich [plugin](https://okio.ai/docs/plugins) ecosystem. Ther
- Audio Quantization
- Audio Loop-Extraction

If you want to develop your own plugin for nendo, consult the [plugin development documentation](https://okio.ai/docs/development/pluginsdev/), you'll be surprised how simple it is.
If you want to develop your own plugin for nendo, consult the [plugin development documentation](https://okio.ai/docs/development/plugindev/), you'll be surprised how simple it is.

## Contributors

Expand Down
60 changes: 32 additions & 28 deletions docs/development/libraryplugindev.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Writing a `LibraryPlugin`

We'll go step by step through all the files you need to create and what they'll do.
Writing a `LibraryPlugin` differs significantly from implementing any of the other plugin types. It requires the implementation of all functions defined by the `NendoLibraryPlugin`, which can be found in the [API Reference](https://okio.ai/docs/reference/schema/plugin/#nendo.schema.plugin.NendoLibraryPlugin). The following is a preliminary introduction and will be heavily extended in the future.

Remember the directory structure from before:
The plugin's directory structure is exactly the same as with any other kind of plugin:

```shell
├── README.md
Expand All @@ -15,19 +15,37 @@ Remember the directory structure from before:
│   └── plugin.py
```

Let's look into the different files now.

## Files

### plugin.py

The most important thing in your plugin. Here is where all your magic happens.
Below, you'll find a simple implementation that just implements the library initializationa method.
We'll go through it step by step.
Below, you'll find a simple implementation that just implements the library initialization method and the `play()` method.

- To implement a new library plugin, you have two options:

1. Inherit from the `SqlAlchemyNendoLibrary`, if your taget DBMS is compatible with SQLAlchemy, i.e. an SQLAlchemy driver exists for it. In this case, you only have to implement the initialization of the library as shown above.
1. Inherit from the `NendoLibraryPlugin`, and implement a general library plugin that does not use SQLAlchemy to connect to the DBMS backend. In this case, you have to implement/override all public methods defined in the `NendoLibraryPlugin`. Refer to the [API Reference](https://okio.ai/docs/reference/schema/plugin/#nendo.schema.plugin.NendoLibraryPlugin) to see the full list of functions that have to be implemented.

Below, we show how to implement a nendo library that uses the first approach, inheriting from the `SqlAlchemyNendoLibrary` plugin and implementing a `MongoDB` backend.

```python
from logging import Logger
from nendo import Nendo, NendoConfig, SqlAlchemyNendoLibrary, NendoStorageLocalFS, NendoTrack
from nendo import (
NendoConfig,
NendoStorage,
NendoStorageLocalFS,
NendoUser,
SqlAlchemyNendoLibrary,
)
from sqlalchemy import Engine, MetaData, create_engine
from sqlalchemy.orm import declarative_base

from .config import MongoDBConfig

plugin_package = metadata.metadata(__package__ or __name__)
plugin_config = MongoDBConfig()
Base = declarative_base(metadata=MetaData())
logger = logging.getLogger("nendo")


class MongoDBLibrary(SqlAlchemyNendoLibrary):
Expand Down Expand Up @@ -71,41 +89,27 @@ class MongoDBLibrary(SqlAlchemyNendoLibrary):
Base.metadata.create_all(bind=self.db)
self.user = self.default_user
return None

def play(self, track: schema.NendoTrack) -> None:
"""Preview an audio track on mac & linux.
Args:
track (NendoTrack): The track to play.
"""
play_signal(track.signal, track.sr)

```

The basics are very simple:

- To implement a new library plugin, you have two options:a
1. Inherit from the `SqlAlchemyNendoLibrary`, if your taget DBMS is compatible with SQLAlchemy, i.e. an SQLAlchemy driver exists for it. In this case, you only have to implement the initialization of the library as shown bove.
1. Inherit from the `NendoLibraryPlugin`, and implement a general library plugin that does not use SQLAlchemy to connect to the DBMS backend. In this case, you have to implement/override all public methods defined in the `NendoLibraryPlugin`. Refer to the [API Reference](https://okio.ai/docs/reference/schema/plugin/#nendo.schema.plugin.NendoLibraryPlugin) to see the full list of functions that have to be implemented.a
- Use nendo's `NendoStorageLocalFS` storage driver or implement your own.
- Overwrite any methods whose behavior you want to change
- Make sure that your implementation of the nendo library passes the library tests defined in `tests/test_library.py`.
- Use nendo's `NendoStorageLocalFS` storage driver or implement your own. Refer to the [API reference](https://okio.ai/docs/reference/schema/core/#nendo.schema.core.NendoStorage) to see which methods you need to implement for a `StorageDriver` to work.
- Overwrite any methods whose behavior you want to change but make sure that your implementation of the nendo library passes the library tests defined in `tests/test_library.py`.

### config.py

```python
from nendo import NendoConfig


class MongoDBLibraryConfig(NendoConfig):
class MongoDBConfig(NendoConfig):
"""Configuration defaults for the mongodb library plugin."""
model_config = ConfigDict(arbitrary_types_allowed=True)

my_default_param: bool = False
```

This class extends the base `NendoConfig` and allows you to define some default and overridable parameters for your
plugin.
This class extends the base `NendoConfig` and allows you to define some default and overridable parameters for your plugin.
It behaves just like `NendoConfig`, read up more on basic `nendo` configuration [here](../usage/config.md).

### setup.py
Expand All @@ -117,13 +121,13 @@ if __name__ == "__main__":
setup(
name="nendo-plugin-library-mongodb",
version="0.1.0",
description="Nendo mongodb librarya plugin",
description="Nendo mongodb library plugin",
author="Felix Lorenz <[email protected]>",
)
```

This is a standard `setup.py` file.
You can read up more on how tao configure it [here](https://packaging.python.org/tutorials/packaging-projects/).
You can read up more on how to configure it [here](https://packaging.python.org/tutorials/packaging-projects/).
You just need to define some basics like the name of your plugin, a version number and a description.

### pyproject.toml
Expand Down
11 changes: 6 additions & 5 deletions docs/development/plugindev.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ In nendo we currently differentiate between four types of plugins.
!!! warning
Library plugins are a special type of plugin, they differ a lot from other plugins and should only be used if you know what you are doing.

Plugins that add new or completely different functionality to the `NendoLibrary` are called library plugins.
Plugins that implement new DBMS backends for the nendo library are called _library plugins_. To implement a new library plugin, you have two options:

TODO write more here Felix please, thanks

Examples:
1. Inherit from the `SqlAlchemyNendoLibrary`, if your taget DBMS is compatible with SQLAlchemy, i.e. an SQLAlchemy driver exists for it. In this case, you only have to implement the initialization of the library as shown bove.
1. Inherit from the `NendoLibraryPlugin`, and implement a general library plugin that does not use SQLAlchemy to connect to the DBMS backend. In this case, you have to implement/override all public methods defined in the `NendoLibraryPlugin`. Refer to the [API Reference](https://okio.ai/docs/reference/schema/plugin/#nendo.schema.plugin.NendoLibraryPlugin) to see the full list of functions that have to be implemented.

Examples:

- [nendo_plugin_library_postgres](https://github.com/okio-ai/nendo_plugin_library_postgres)
- [duckdb_library](https://okio.ai/docs/reference/library/duckdb_library/)

!!! note
Make sure that you understand the different plugin types before you start writing your own plugin.
Expand Down

0 comments on commit cede997

Please sign in to comment.