-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #102 from da-h/fix_register_default_module_order
Fix ambiguous register_default_module order
- Loading branch information
0 parents
commit 57f6484
Showing
18 changed files
with
1,015 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
{theme=documentation} | ||
|
||
\include{"../include.md"} | ||
|
||
> A long time ago in a galaxy full of plugin-engines ... | ||
# Geting Started with Miniflask {section-contentlist=False} | ||
## Miniflask is a **small** research-oriented **plugin**-engine for **python**. | ||
|
||
|
||
|
||
Quick Start | ||
=========== | ||
|
||
For a quick look into miniflask, just install it using | ||
```shell | ||
pip install miniflask | ||
``` | ||
|
||
|
||
Short Example | ||
============= | ||
|
||
|
||
**Module Definition** | ||
Let's start a new project first by creating a new directory: | ||
```shell | ||
> ls | ||
main.py | ||
modules/ | ||
module1/__init__.py | ||
module2/__init__.py | ||
module1/__init__.py | ||
``` | ||
|
||
Let's define a simple module, `modules/module1/__init__.py`: | ||
```python | ||
def main(state, event): | ||
print("main event called by module1") | ||
|
||
def register(mf): | ||
mf.register_event('main', main, unique=False) | ||
``` | ||
|
||
Let's define another module, `modules/module2/__init__.py`: | ||
```python | ||
def main(state, event): | ||
print("main event called by module2") | ||
print("it uses a variable var:", state["var"]) | ||
|
||
def register(mf): | ||
mf.register_defaults({ | ||
"var": 42 | ||
}) | ||
mf.register_event('main', main, unique=False) | ||
``` | ||
|
||
|
||
|
||
Our main.py looks like this: | ||
```python | ||
import miniflask | ||
|
||
# initialize miniflask | ||
mf = miniflask.init(module_dirs="./modules") | ||
mf.parse_args() | ||
|
||
# check if all requested modules are loaded | ||
if not mf.halt_parse: | ||
|
||
# call event "main" if exists | ||
if hasattr(mf.event, 'main'): | ||
mf.event.main() | ||
else: | ||
print("There is nothing to do.") | ||
``` | ||
|
||
|
||
**Usage**: | ||
Now, we can use our program in the following ways: | ||
```sh | ||
> python main.py | ||
There is nothing to do. | ||
``` | ||
|
||
```sh | ||
> python main.py module1 | ||
main event called by module1 | ||
``` | ||
|
||
```sh | ||
> python main.py module2,module1 | ||
main event called by module2 | ||
it uses a variable var: 42 | ||
main event called by module1 | ||
``` | ||
|
||
```sh | ||
> python main.py module2,module1 --module2.var 9001 | ||
main event called by module2 | ||
it uses a variable var: 9001 | ||
main event called by module1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{theme=documentation} | ||
|
||
# Launching MiniFlask | ||
Things to do in the launch file. | ||
|
||
\include{"../include.md"} | ||
|
||
|
||
## Launch file | ||
|
||
The first step in creating a new MiniFlask project is to create the launch file. The launch file initializes MiniFlask and tells it where modules are located. | ||
**Typically, you will never need to touch this file ever again!** | ||
|
||
The following function calls have to be included: | ||
**Example file:** do.py | ||
```python | ||
import miniflask | ||
|
||
# tells MiniFlask where the modules are located | ||
# simply feed it a list of module folders | ||
mf = miniflask.init(["module_collection_1","module_collection_2"]) | ||
|
||
# Parses arguments from the command line and runs the modules that have been specified | ||
# as entrypoints. The run command first launches the `init` event if it exists and then | ||
# the `main` events of all modules. If multiple modules with a main method are loaded, | ||
# the main methods are executed in the order modules are specified using the CLI. | ||
mf.run() | ||
``` | ||
|
||
## Executing the launch file | ||
In order to start our MiniFlask project, simply execute the `do.py` file and list all modules to load separated by a comma. To overwrite the default arguments, simply pass the new parameters precising the modules after the modules. | ||
|
||
```python | ||
> python main.py module2,module1 --module2.var 9001 | ||
main event called by module2 | ||
it uses a variable var: 9001 | ||
main event called by module1 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
{theme=documentation} | ||
|
||
\include{"../include.md"} | ||
|
||
# Register Modules {section-contentlist=False} | ||
Telling MiniFlask what exists. | ||
|
||
### Initialize Miniflask | ||
\include{"../08-API/02-miniflask-Instance/01-miniflask.init.md"} | ||
|
||
\main | ||
|
||
|
||
**Example Launch File** | ||
```python | ||
import miniflask | ||
|
||
# tell miniflask where to look for modules | ||
mf = miniflask.init(module_dirs="./modules") | ||
|
||
# parse CLI-args & run the main event | ||
mf.run() | ||
``` | ||
|
||
Project structure may be very project specific. Miniflask allows various way to organize your projects. | ||
Other possibilities are to define modules directly or to specify multiple distinct folders that contain miniflask modules. | ||
|
||
\examples | ||
|
||
### What is a Module? | ||
> A miniflask module is a self-contained functional unit with a persistent variable store. In principle, it's a singleton class. | ||
**Module Declaration** | ||
- **A MiniFlask module is a folder that contains at least these two files**: | ||
- `__init__.py` containing a method called `register(mf)`. | ||
The method `register(mf)` is called whenever a module is loaded. | ||
It's purpose is to tell miniflask in which way the module is to be used. | ||
- `.module` *(empty file)* | ||
|
||
|
||
### Unique & Short Module Identifiers | ||
When working with miniflask modules we will want to reference modules uniquely. | ||
The unique module identifier is just the path to the folder (starting with the base directory defined during initialization), where the module seperator is a dot (`.`). | ||
|
||
|
||
**Example** | ||
For instance, we could organize the folder `./modules` like this: | ||
```shell | ||
> ls | ||
main.py | ||
modules/ | ||
module1/__init__.py | ||
... /.module | ||
module2/__init__.py | ||
... /.module | ||
... /.noshortid | ||
subfolder1/module3/__init__.py | ||
... / ... /.module | ||
subfolder1/module4/__init__.py | ||
... / ... /.module | ||
... and so on ... | ||
``` | ||
|
||
Further, we initialized miniflask using the line | ||
```py | ||
mf = miniflask.init({ | ||
"mods": "./modules", | ||
}) | ||
``` | ||
by specifying the name `mods` for our main repository contained in the folder `./modules/`. | ||
|
||
|
||
Every module in this repository can now be referenced in two ways: \block[ | ||
| **Type** | unique module identifier | (short) module identifier | | ||
| ---------- | -------------------- | --------------------- | | ||
| **Description** | unique identification by specifying the whole module path | any subset of the unique identifier if only one module matches that description | | ||
| **Availability** | Always | Not available if \block[ | ||
- two modules would share the same short identifier | ||
- module-folder contains the file `.noshortid` | ||
] | | ||
| **Example** | `module1`,\n (has no shorter id)\n `subfolder1.module3` or also `mods.module3`,\n `subfolder1.module4` or also `mods.module4`| `mods.module1`\n`mods.module2`\n`mods.subfolder1.module3`\n`mods.subfolder1.module4` | | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
{theme=documentation} | ||
|
||
\include{"../include.md"} | ||
|
||
\include{"../08-API/02-miniflask-Instance/08-register_defaults.md"} | ||
|
||
# Register Module Settings: | ||
\shortdescr | ||
|
||
\main | ||
|
||
|
||
## Example | ||
A typical used case are variables that can be overridden freely using CLI. | ||
Example file: `modules/module1/__init__.py` | ||
\examples | ||
|
||
## Overriding these using the CLI | ||
Whenever we load `module1`, e.g. by using | ||
```shell | ||
python main.py module1 | ||
``` | ||
we also load these variables into the argument parser of miniflask. | ||
For the example above, we list all arguments that can be used for `module1`: | ||
```shell | ||
> python main.py module1 -h | ||
usage: main.py modulelist [optional arguments] | ||
|
||
optional arguments: | ||
-h, --help show this help message and exit | ||
--module1.variableA int | ||
--module1.variableB string | ||
--module1.variableC | ||
--no-module1.variableC | ||
--module1.variableD [int] | ||
``` | ||
|
||
Thus, to turn `variableC` off, we can just add `--no-module1.variableC` to the above command. | ||
|
||
## Overriding Booleans | ||
For a boolean typed variable, the following arguments are possible: | ||
|
||
| **Set to True** | **Set to False** | | ||
| ---------------- | ---------------- | | ||
| \block[ | ||
``` | ||
--module.var | ||
--module.var true | ||
--module.var TrUe (well, boolean values are case insensitive) | ||
--module.var yes | ||
--module.var y | ||
--module.var t | ||
--module.var 1 | ||
``` | ||
] | \block[ | ||
``` | ||
--no-module.var | ||
--module.var false | ||
--module.var FalSE (well, boolean values are case-insensitive) | ||
--module.var no | ||
--module.var n | ||
--module.var f | ||
--module.var 0 | ||
``` | ||
] | | ||
|
||
**Overriding Lists of basic types**: | ||
List arguments are just as easy as | ||
``` | ||
--module.var 1 2 3 4 5 | ||
``` | ||
|
||
|
||
|
||
## Required Arguments | ||
Set any basic data type (`str`, `bool`, `int`, `float`) or list of any basic data type as default value to register an argument that has to be specified by the CLI. | ||
```python | ||
def register(mf): | ||
mf.register_defaults({ | ||
"variableA": int, | ||
"variableB": str, | ||
"variableC": bool, | ||
"variableD": [float] # only lists of same type are supported | ||
}) | ||
``` | ||
|
||
|
||
|
||
|
||
## Nested Arguments | ||
Given nested modules, it is possible to group variables in the CLI using the folllowing syntax: | ||
```python | ||
--module1.submodule [ --var1 42 --var2 43 ] | ||
``` | ||
or | ||
```python | ||
--module1 [ --submodule [ --var1 42 --var2 43 ] ] | ||
``` | ||
|
||
These calls would translate to the following: | ||
``` | ||
--module1.submodule.var1 42 | ||
--module1.submodule.var2 43 | ||
``` | ||
|
||
|
||
|
||
|
Oops, something went wrong.