Tackle box is a declarative DSL for building modular workflows and code generators. Tool is plugins based and can easily be extended by writing additional hooks or importing external providers creating a web of interoperable CLIs.
Project description
tackle-box
Tackle-box is an experimental DSL for building modular code generators and declarative CLIs. Built as a fork of cookiecutter, it can make any config file into a CLI with both strong and weakly typed programmable flow control common to a general purpose programming language. Basically you can write a fully functional Turing-complete program out of a config file. It's wild.
With tackle-box, you can build:
- Modular code generators / repo scaffolding tools that can be updated over time
- Declarative makefile alternatives for advanced toolchain management
- Interactive glue code for infrastructure-as-code deployment strategies
- Generic utilities like SSH registries and dotfile managers
- Combinations of all of the above and anything else you can think of
If this project gets enough adoption / stars, it will be re-written in a compiled language. Its current goal is defining the syntax which should remain stable after a rewrite.
Features
- Makes arbitrary yaml / json / toml dynamic
- Embed loops, conditionals, and other custom logic
- Self documenting CLI to call logic
- Ships with a collection of over 100 hooks that act like plugins within your config file
- Modular design allows creating / importing new hooks easy
- Supports both python and declarative hooks which can be imported / called / defined in-line or within jinja templates
Install
Note: tackle can install dependencies on its own. Check docs for advanced installation methods to isolate tackle from your system python.
python -m venv env && source env/bin/activate
pip install tackle-box
Quick Demo: tackle robcxyz/tackle-hello-world
Hello world
Check out the docs for >10 hello worlds that demonstrate the various aspects of the syntax with the simplest one using the print hook.
hello.yaml
# Any time a key ends with `->`, we are calling a hook
hw->: print Hello world!
To run, call tackle hello.yaml
. Can also be version controlled -> tackle robcxyz/tackle-hello-world
.
Can also use loops, conditionals, and other base methods.
hello.yaml
the:
words:
- Hello
- cruel
- world!
one liner->: print --for the.words --if "item != 'cruel'" {{item}}
multiple lines:
->: print
for:
- Hello
- world!
# Or combinations of the above with other methods like try/except
New hooks can be made in python which under the hood is a pydantic model.
from tackle import BaseHook
class Greeter(BaseHook):
hook_type: str = "greeter"
target: str
args: list = ['target']
def exec(self):
expression = f"Hello {self.target}"
print(expression)
return expression
Or can be defined inline within your tackle file..
# Keys ending with `<-` mean we are creating a hook / method
greeter<-:
target: str
args: ['target']
exec<-:
expression->: print Hello {{target}}
return: expression
And both can be called in the same way.
hello: world!
With a flag->: greeter --target {{hello}}
Target in argument->: greeter {{hello}}
Expanded fields:
->: greeter
target: {{hello}}
Jinja template->: {{ greeter(hello) }}
# Or combinations jinja and compact / expanded hooks allowing chaining of hook calls.
With the declarative hooks being callable from the command line:
tackle hello.yaml --target world!
# Or from a github repo
tackle robcxyz/tackle-hello-world --checkout v0.1.0
Documentation can be embedded into the hooks.
<-:
help: This is the default hook
target:
type: str
default->: input
description: The thing to say hello to
exec<-:
greeting->: select Who to greet? --choices ['world',target]
hi->: greeter --target {{greeting}}
greeting-method<-:
help: A method that greets
# ... Greeting options / logic
greeter<-:
help: A reusable greeter object
target: str
exec<-:
hi->: print Hello {{target}}
Which when running tackle hello.yaml help
produces its own help screen.
usage: tackle hello.yaml [--target]
This is the default hook
options:
--target [str] The thing to say hello to
methods:
greeting-method A method that greets
greeter A reusable greeter object
Hooks can be imported, linked, and/or combined creating a web of CLIs.
Use Cases
WIP Tutorials
- Declarative Utilities
- Infrastructure-as-Code Management
- Kubernetes Manifest Management
- Toolchain Management
Topics
- Writing Tackle Files
- Creating Providers
- Python Hooks
- Declarative Hooks
- Blocks and Flow Control
- Memory Management
- Special Variables
- Declarative CLIs
Contributing
Contributions are welcome but please be advised of the following notes.
- This project uses conventional commits which generates the changelog with release-please-action in the release CI workflow. If commits have been made outside of this convention they will be squashed accordingly.
- For making changes to providers, please include test coverage using the existing fixtures and patterns from prior tests or communicate any suggestions that deviate from this style. Tests should be runnable from the test's directory and via
make test
. - For making changes to the core parser, please create a proposal first outlining your suggestions with examples before spending time working on code.
It is very easy to create new providers / hooks with tackle-box. Over time, it will adopt the same import pattern of what Ansible does where all provider / hooks (modules) are stored in version controlled locations. In the meantime, please feel free to contribute to this repository for hooks that have general applicability or create your own hooks in other repositories that are more bespoke / opinionated in nature.
Code of Conduct
Everyone interacting in the tackle-box project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the PyPA Code of Conduct.
Credit
Special thanks to the cookiecutter community for laying the basis for this project.
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 tackle-box-0.4.2.tar.gz
.
File metadata
- Download URL: tackle-box-0.4.2.tar.gz
- Upload date:
- Size: 183.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.7.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | cadec9d6d90adb3224451945f714ef016b02eae23f28c2b92a153d8ac94139f0 |
|
MD5 | be8c3c5d51556a3acab3cf25c26b258d |
|
BLAKE2b-256 | a5855451ac0e18fb51ebf6564ef45bf775c640e577e03128b6c7f928a9a02a1e |
File details
Details for the file tackle_box-0.4.2-py2.py3-none-any.whl
.
File metadata
- Download URL: tackle_box-0.4.2-py2.py3-none-any.whl
- Upload date:
- Size: 254.1 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.7.15
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ce0e3b29962e6c17d5254dca657b080c6619b69b604c398dba8aa01feb49b628 |
|
MD5 | e8952cfc25573433dc68eb477d624afe |
|
BLAKE2b-256 | 8d941d8c87d9792cce37a9f75f7b745fe40bc4b14d961cf575bd0ed6e87bc3e8 |