A 'literate' script execution framework. Makes writing more readable scripts easier.
Project description
AutomationFlow
A jupyter inspired automation 'language' for creating more readable (literate programming) automation (python) scripts.
I like to use jupyter for scripting nowadays, but it's not always an option especially when in the terminal.
Table of Contents
- AutomationFlow
- Table of Contents
- General Approach
- The Runner Class
- Main Rules
- Misc/Design Decisions
- Why use it?
General Approach
Turns something like,
```markdown
# Dictionary Example
```
```text
initializing dictionary, please wait..
```
```code
import time
T = initialize()
```
```text
Initialization complete! (actual initialization of the Trie is faster, this just for "pretty" reasons)
```
```code
prefixsearch(T)
```
%% print_green | "exiting... see you next time\n" %%
```code
time.sleep(1)
```
into
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Dictionary Example ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
initializing dictionary, please wait..
466500/466550 words [###################]
Initialization complete! (actual initialization of the Trie is faster, this just for "pretty" reasons)
Please enter a word or a prefix to search for,
or enter HELP for more options
or enter EXIT close this application
> hello
Results: 5 words in total that start with hello
hello
helloed
helloes
helloing
hellos
Please enter a word or a prefix to search for,
or enter HELP for more options
or enter EXIT close this application
> goodby
Results: 4 words in total that start with goodby
goodby
goodbye
goodbyes
goodbys
Please enter a word or a prefix to search for,
or enter HELP for more options
or enter EXIT close this application
> EXIT
exiting... see you next time
where the file being run looks like,
from Trie import DTrie
from AutomationFlow.AutomationFlow import Runner
r = Runner(script_fpath="script.md",
_context = {
"initialize" : initialize,
"prefixsearch" : prefix_search,
})
r.run()
check out the examples directory for more..
The Runner Class
Arguments,
script_text str
- The script as a text. If provided script_fpath cannot be provided.
script_fpath
- path to the script file. If provided script_text cannot be provided.
_context
- A dictionary with keys and values that will be reference-able within the script.
print_delay=0.01
- Time delay between the printing of each character. 0.01 default, which is relatively fast.
Main Rules
Comment block
Open with {#, close with #}.
{# this is a comment #}
{#
this is a comment to
#}
Inline functions
Open with %%, and close with %%.
%% countdown | 50 | 5 %%
=> countdown(50, 5)
%% func | arg1 | arg2 | func2 | arg3 %%
=> func(arg1, arg2, func2(arg3))
Inline functions are for quick calling of functions, for more complicated code it's better to use a code block.
Functions have to be findable in the context dictionary of the Runner.
There are a few inbuilt functions provided in the context.
note. inline functions have to have a default state variable, that allows the function to access things in the context.
def get_meaning(state, word):
return state['Dictionary'].get_meaning(word)
text block
Text blocks start with a ```text, then have a newline for the text block's content, and then finally they end with another set of ```.
```text
hello there this is a text block
```
This is a generic text block.
```text
you can also display variables stored in the context here. e.g.
hello my name is ${name} will display what the variable name references.
```
```text
Hi there {{ print_yellow | name }}
```
You can call inline functions in text blocks, however instead of starting and ending with %%, you start with {{ and end with }}.
```text="block_name"
something something
```
This is a text with a block name, it won't be displayed straight away, instead you can reference it and display it once or many times over using a template block.
{? block "block_name" ?}
{? block "block_name" ?}
This will display the text block "block_name" two times.
template block
Template blocks start with {? and end with ?}, and MUST have either a block or a string indentifier prior to a string.
{? block "block_name" ?}
{? script "path/to/script" ?}
block => this is a template block that will display a block stored in the context
script => this is a script block that will open and parse a script in the given location
code block
Code blocks are equivilent to text blocks and start with ```code and end with ```.
```code
import math
n = 4
print(math.sqrt(n))
```
=> prints 2.0
variables defined in the code block will be stored in the context for later use.
The handling for code blocks isn't the most sophisiticated and it's intented use is meant to be assistive for than for complex action.
```code="code_block_name"
# some code
```
Same with text blocks, code blocks can have block names and be called via a template block.o
markdown block
```markdown
# hi there
```
Uses the rich library to display markdown. Added more as a nice to have than anything, hence it's not majorly supported.
conditional block
Like most templating frameworks, it's possible to do basic conditional handling in AutomationFlow
Conditional blocks start with {% and end with %}.
```code
n = 10
```
{% if func | n %}
{# do this if func(n) == True #}
{% elif func2 | n %}
{# do this instead if func2(n) == True after func(n) turns out to be False # }
{% else %}
{# do this if the previous two don't result in True #}
{% endif %}
Conditional blocks have to start with {% if something %} and have to have a {% endif %} block.
Misc/Design Decisions
I had initially created a more writing like system, one that preserved white space so the resulting script looked more like it was in one single block.
However, I eventually ended up choosing to go with a more jupyter inspired system, seperating code and text oriented blocks as while it's less pretty, it's significantly easier to follow what is going on.
Some more coding related choices
- Lexer -> Parser
- Uses a simple recursive descent technique.
Why use it?
Literate Automation scripting.
- Scripts can and do go wrong.
- Scripts shouldn't be black boxes.
- Providing help and explainations to the reader can be boring to do when code and user facing 'text' is seperated. Seperation causes friction.
By being able to mix the coding part of scripting, with the user facing part, it's a lot smoother and friction-less to add more explainations.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file AutomationFlow-0.1.1.tar.gz
.
File metadata
- Download URL: AutomationFlow-0.1.1.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.8.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4d36afe0ad42467bc51c754c26293cdff7150e5f4a3a5df888f6b2f898e67ee8 |
|
MD5 | 489c9a45537b3fc8d528243c19ce0e56 |
|
BLAKE2b-256 | 2a5337f31091c4fa9cf6d007d58befaa27168d14ab8fd2b7cb67874450573858 |
File details
Details for the file AutomationFlow-0.1.1-py3-none-any.whl
.
File metadata
- Download URL: AutomationFlow-0.1.1-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.8.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b81d4eeda58a1a8ec8f4bc3efe80ad2bd5a7db76e30207c43b90ba4ae9166a1e |
|
MD5 | 44dc2aab1482d074fe85d8867d2adb4f |
|
BLAKE2b-256 | 573cdc3ecd015282bbaaf9d3ff4781f596fae0577d6267734c3614cd7557a91c |