Name | AutomationFlow JSON |
Version |
0.1.1
JSON |
| download |
home_page | |
Summary | A 'literate' script execution framework. Makes writing more readable scripts easier. |
upload_time | 2023-06-19 19:35:32 |
maintainer | |
docs_url | None |
author | gkegke |
requires_python | >=3.8 |
license | MIT |
keywords |
script
execution
framework
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# 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](#automationflow)
- [Table of Contents](#table-of-contents)
- [General Approach](#general-approach)
- [The Runner Class](#the-runner-class)
- [Main Rules](#main-rules)
- [Comment block](#comment-block)
- [Inline functions](#inline-functions)
- [text block](#text-block)
- [template block](#template-block)
- [code block](#code-block)
- [markdown block](#markdown-block)
- [conditional block](#conditional-block)
- [Misc/Design Decisions](#miscdesign-decisions)
- [Why use it?](#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.
1) Scripts can and do go wrong.
2) Scripts shouldn't be black boxes.
3) 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.
Raw data
{
"_id": null,
"home_page": "",
"name": "AutomationFlow",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "script,execution,framework",
"author": "gkegke",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/2a/53/37f31091c4fa9cf6d007d58befaa27168d14ab8fd2b7cb67874450573858/AutomationFlow-0.1.1.tar.gz",
"platform": null,
"description": "# AutomationFlow\n\nA jupyter inspired automation 'language' for creating more readable (literate programming) automation (python) scripts.\n\nI like to use jupyter for scripting nowadays, but it's not always an option especially when in the terminal.\n\nTable of Contents\n=================\n\n- [AutomationFlow](#automationflow)\n- [Table of Contents](#table-of-contents)\n- [General Approach](#general-approach)\n- [The Runner Class](#the-runner-class)\n- [Main Rules](#main-rules)\n - [Comment block](#comment-block)\n - [Inline functions](#inline-functions)\n - [text block](#text-block)\n - [template block](#template-block)\n - [code block](#code-block)\n - [markdown block](#markdown-block)\n - [conditional block](#conditional-block)\n- [Misc/Design Decisions](#miscdesign-decisions)\n- [Why use it?](#why-use-it)\n\n# General Approach\n\nTurns something like,\n\n````\n```markdown\n# Dictionary Example\n```\n\n```text\n\ninitializing dictionary, please wait..\n\n```\n\n```code\nimport time\n\nT = initialize()\n```\n\n```text\nInitialization complete! (actual initialization of the Trie is faster, this just for \"pretty\" reasons)\n\n\n```\n\n```code\nprefixsearch(T)\n```\n\n%% print_green | \"exiting... see you next time\\n\" %%\n\n```code\ntime.sleep(1)\n```\n````\n\ninto \n\n```\n\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n\u2503 Dictionary Example \u2503\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u251b\n\ninitializing dictionary, please wait..\n466500/466550 words [###################]\nInitialization complete! (actual initialization of the Trie is faster, this just for \"pretty\" reasons)\n\nPlease enter a word or a prefix to search for,\nor enter HELP for more options\nor enter EXIT close this application\n\n> hello\n\nResults: 5 words in total that start with hello\n\nhello\nhelloed\nhelloes\nhelloing\nhellos\n\n\nPlease enter a word or a prefix to search for,\nor enter HELP for more options\nor enter EXIT close this application\n\n> goodby\n\nResults: 4 words in total that start with goodby\n\ngoodby\ngoodbye\ngoodbyes\ngoodbys\n\n\nPlease enter a word or a prefix to search for,\nor enter HELP for more options\nor enter EXIT close this application\n\n> EXIT\nexiting... see you next time\n```\n\nwhere the file being run looks like,\n\n```\n\nfrom Trie import DTrie\nfrom AutomationFlow.AutomationFlow import Runner\n\nr = Runner(script_fpath=\"script.md\",\n _context = {\n \"initialize\" : initialize,\n \"prefixsearch\" : prefix_search,\n})\n\nr.run()\n\n```\n\ncheck out the examples directory for more..\n\n# The Runner Class \n\nArguments,\n\nscript_text str\n - The script as a text. If provided script_fpath cannot be provided.\n\nscript_fpath\n - path to the script file. If provided script_text cannot be provided.\n\n_context\n - A dictionary with keys and values that will be reference-able within the script.\n\nprint_delay=0.01\n - Time delay between the printing of each character. 0.01 default, which is relatively fast.\n\n# Main Rules\n\n### Comment block\n\nOpen with **{#**, close with **#}**.\n\n````\n{# this is a comment #}\n\n{#\n this is a comment to\n#}\n````\n\n### Inline functions\n\nOpen with **%%**, and close with **%%**.\n\n````\n%% countdown | 50 | 5 %%\n````\n\n=> countdown(50, 5)\n\n````\n%% func | arg1 | arg2 | func2 | arg3 %%\n````\n\n=> func(arg1, arg2, func2(arg3))\n\nInline functions are for quick calling of functions, for more complicated code it's better to use a code block.\n\nFunctions have to be findable in the context dictionary of the Runner.\n\nThere are a few inbuilt functions provided in the context. \n\nnote. inline functions have to have a default state variable, that allows the function to access things in the context.\n\n```\ndef get_meaning(state, word):\n return state['Dictionary'].get_meaning(word)\n```\n\n### text block\n\nText blocks start with a \\```text, then have a newline for the text block's content, and then finally they end with another set of \\```.\n\n````\n```text\nhello there this is a text block\n```\n````\n\nThis is a generic text block.\n\n````\n```text\nyou can also display variables stored in the context here. e.g.\n\nhello my name is ${name} will display what the variable name references.\n```\n````\n\n````\n```text\nHi there {{ print_yellow | name }}\n```\n````\n\nYou can call inline functions in text blocks, however instead of starting and ending with **%%**, you start with **{{** and end with **}}**.\n\n````\n```text=\"block_name\"\nsomething something\n```\n````\n\nThis 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.\n\n````\n{? block \"block_name\" ?}\n\n{? block \"block_name\" ?}\n````\n\nThis will display the text block \"block_name\" two times.\n\n#### template block\n\nTemplate blocks start with **{?** and end with **?}**, and MUST have either a\nblock or a string indentifier prior to a string.\n\n````\n{? block \"block_name\" ?}\n\n{? script \"path/to/script\" ?}\n````\n\nblock => this is a template block that will display a block stored in the context\n\nscript => this is a script block that will open and parse a script in the given location\n\n#### code block\n\nCode blocks are equivilent to text blocks and start with \\```code and end with \\```.\n\n````\n```code\nimport math\n\nn = 4\nprint(math.sqrt(n))\n```\n````\n\n=> prints 2.0\n\nvariables defined in the code block will be stored in the context for later use.\n\nThe handling for code blocks isn't the most sophisiticated and it's intented use is meant\nto be assistive for than for complex action.\n\n````\n```code=\"code_block_name\"\n# some code\n```\n````\n\nSame with text blocks, code blocks can have block names and be called via a template block.o\n\n#### markdown block\n\n````\n```markdown\n# hi there\n```\n````\n\nUses the rich library to display markdown. Added more as a nice to have than anything, hence it's not majorly supported.\n\n#### conditional block\n\nLike most templating frameworks, it's possible to do basic conditional handling in AutomationFlow\n\nConditional blocks start with **{%** and end with **%}**.\n\n````\n\n```code\nn = 10\n```\n\n{% if func | n %}\n\n {# do this if func(n) == True #}\n\n{% elif func2 | n %}\n\n {# do this instead if func2(n) == True after func(n) turns out to be False # }\n\n{% else %}\n\n {# do this if the previous two don't result in True #}\n\n{% endif %}\n````\n\nConditional blocks have to start with {% if something %} and have to have a {% endif %} block.\n\n# Misc/Design Decisions\n\nI had initially created a more writing like system, one that preserved white space so the resulting\nscript looked more like it was in one single block.\n\nHowever, I eventually ended up choosing to go with a more jupyter inspired system, seperating\ncode and text oriented blocks as while it's less pretty, it's significantly easier to follow\nwhat is going on.\n\nSome more coding related choices\n\n- Lexer -> Parser\n- Uses a simple recursive descent technique.\n\n# Why use it?\n\nLiterate Automation scripting.\n\n1) Scripts can and do go wrong.\n2) Scripts shouldn't be black boxes.\n3) Providing help and explainations to the reader can be boring to do when\n code and user facing 'text' is seperated. Seperation causes friction.\n\nBy being able to mix the coding part of scripting, with the user facing part,\nit's a lot smoother and friction-less to add more explainations.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A 'literate' script execution framework. Makes writing more readable scripts easier.",
"version": "0.1.1",
"project_urls": {
"Homepage": "https://github.com/gkegke/AutomationFlow"
},
"split_keywords": [
"script",
"execution",
"framework"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "573cdc3ecd015282bbaaf9d3ff4781f596fae0577d6267734c3614cd7557a91c",
"md5": "44dc2aab1482d074fe85d8867d2adb4f",
"sha256": "b81d4eeda58a1a8ec8f4bc3efe80ad2bd5a7db76e30207c43b90ba4ae9166a1e"
},
"downloads": -1,
"filename": "AutomationFlow-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "44dc2aab1482d074fe85d8867d2adb4f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 9397,
"upload_time": "2023-06-19T19:35:31",
"upload_time_iso_8601": "2023-06-19T19:35:31.007964Z",
"url": "https://files.pythonhosted.org/packages/57/3c/dc3ecd015282bbaaf9d3ff4781f596fae0577d6267734c3614cd7557a91c/AutomationFlow-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2a5337f31091c4fa9cf6d007d58befaa27168d14ab8fd2b7cb67874450573858",
"md5": "489c9a45537b3fc8d528243c19ce0e56",
"sha256": "4d36afe0ad42467bc51c754c26293cdff7150e5f4a3a5df888f6b2f898e67ee8"
},
"downloads": -1,
"filename": "AutomationFlow-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "489c9a45537b3fc8d528243c19ce0e56",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 9642,
"upload_time": "2023-06-19T19:35:32",
"upload_time_iso_8601": "2023-06-19T19:35:32.627564Z",
"url": "https://files.pythonhosted.org/packages/2a/53/37f31091c4fa9cf6d007d58befaa27168d14ab8fd2b7cb67874450573858/AutomationFlow-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-19 19:35:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "gkegke",
"github_project": "AutomationFlow",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "automationflow"
}