/plugins` for global plugins
A plugin can be used either via the `Environment` class instance,
or by regular module importing:
```python
from datumaro.components.project import Environment, Project
from datumaro.plugins.yolo_format.converter import YoloConverter
# Import a dataset
dataset = Environment().make_importer('voc')(src_dir).make_dataset()
# Load an existing project, save the dataset in some project-specific format
project = Project.load('project/dir')
project.env.converters.get('custom_format').convert(dataset, save_dir=dst_dir)
# Save the dataset in some built-in format
Environment().converters.get('yolo').convert(dataset, save_dir=dst_dir)
YoloConverter.convert(dataset, save_dir=dst_dir)
```
### Writing a plugin
A plugin is a Python module with any name, which exports some symbols. Symbols,
starting with `_` are not exported by default. To export a symbol,
inherit it from one of the special classes:
```python
from datumaro.components.extractor import Importer, Extractor, Transform
from datumaro.components.launcher import Launcher
from datumaro.components.converter import Converter
```
The `exports` list of the module can be used to override default behaviour:
```python
class MyComponent1: ...
class MyComponent2: ...
exports = [MyComponent2] # exports only MyComponent2
```
There is also an additional class to modify plugin appearance in command line:
```python
from datumaro.components.cli_plugin import CliPlugin
class MyPlugin(Converter, CliPlugin):
"""
Optional documentation text, which will appear in command-line help
"""
NAME = 'optional_custom_plugin_name'
def build_cmdline_parser(self, **kwargs):
parser = super().build_cmdline_parser(**kwargs)
# set up argparse.ArgumentParser instance
# the parsed args are supposed to be used as invocation options
return parser
```
#### Plugin example
```
datumaro/plugins/
- my_plugin1/file1.py
- my_plugin1/file2.py
- my_plugin2.py
```
`my_plugin1/file2.py` contents:
```python
from datumaro.components.extractor import Transform, CliPlugin
from .file1 import something, useful
class MyTransform(Transform, CliPlugin):
NAME = "custom_name" # could be generated automatically
"""
Some description. The text will be displayed in the command line output.
"""
@classmethod
def build_cmdline_parser(cls, **kwargs):
parser = super().build_cmdline_parser(**kwargs)
parser.add_argument('-q', help="Very useful parameter")
return parser
def __init__(self, extractor, q):
super().__init__(extractor)
self.q = q
def transform_item(self, item):
return item
```
`my_plugin2.py` contents:
```python
from datumaro.components.extractor import Extractor
class MyFormat: ...
class _MyFormatConverter(Converter): ...
class MyFormatExtractor(Extractor): ...
exports = [MyFormat] # explicit exports declaration
# MyFormatExtractor and _MyFormatConverter won't be exported
```
## Command-line
Basically, the interface is divided on contexts and single commands.
Contexts are semantically grouped commands, related to a single topic or target.
Single commands are handy shorter alternatives for the most used commands
and also special commands, which are hard to be put into any specific context.
[Docker](https://www.docker.com/) is an example of similar approach.
```{mermaid}
%%{init { 'theme':'neutral' }}%%
flowchart LR
d(("#0009; datum #0009;")):::mainclass
s(source):::nofillclass
m(model):::nofillclass
p(project):::nofillclass
d===s
s===id1[add]:::hideclass
s===id2[remove]:::hideclass
s===id3[info]:::hideclass
d===m
m===id4[add]:::hideclass
m===id5[remove]:::hideclass
m===id6[run]:::hideclass
m===id7[info]:::hideclass
d===p
p===migrate:::hideclass
p===info:::hideclass
d====str1[create]:::filloneclass
d====str2[add]:::filloneclass
d====str3[remove]:::filloneclass
d====str4[export]:::filloneclass
d====str5[info]:::filloneclass
d====str6[transform]:::filltwoclass
d====str7[filter]:::filltwoclass
d====str8[diff]:::fillthreeclass
d====str9[merge]:::fillthreeclass
d====str10[validate]:::fillthreeclass
d====str11[explain]:::fillthreeclass
d====str12[stats]:::fillthreeclass
d====str13[commit]:::fillfourclass
d====str14[checkout]:::fillfourclass
d====str15[status]:::fillfourclass
d====str16[log]:::fillfourclass
classDef nofillclass fill-opacity:0;
classDef hideclass fill-opacity:0,stroke-opacity:0;
classDef filloneclass fill:#CCCCFF,stroke-opacity:0;
classDef filltwoclass fill:#FFFF99,stroke-opacity:0;
classDef fillthreeclass fill:#CCFFFF,stroke-opacity:0;
classDef fillfourclass fill:#CCFFCC,stroke-opacity:0;
```
Model-View-ViewModel (MVVM) UI pattern is used.
```{mermaid}
%%{init { 'theme':'neutral' }}%%
flowchart LR
```