... eliminates shell scripts right off the bootstrap:
Want your users to run software isolated in a git repo after a single zero-argument command?
./primeSee the Intro doc.
protoprimer employs ubiquitous python for version pinning to provide a robust alternative to shell:
- First, a wild
pythonversion found inPATHexecutes a shim that invokesprotoprimer. - Last,
protoprimerexecutes user code by the requiredpythonversion from the configuredvenv.
Compare:
%%{init: {"look": "handDrawn", "theme": "neutral"}}%%
flowchart TD;
heavy_minus["➖ del `*.sh`"];
shell_exec["any<br>`shell`<br>executable"];
subgraph sh[" "]
sh_entry_script[" `shell`<br>entry script<br>like<br>`prime`"];
embedded_code["re-invented<br>ad-hoc<br>non-modular<br>`shell` hacks"];
end
heavy_plus["➕ add `*.py`"];
python_exec["any<br>`python`<br>executable"];
subgraph py[" "]
py_entry_script[" `python`<br>entry script<br>like<br>`prime`"];
py_bootstrap_code["tested<br>bootstrap code<br>from<br>`protoprimer`"];
end
pinned_python["<br>user code<br>in<br>pinned<br>`python`<br>with<br>dependencies<br> "];
invis_block[ ];
heavy_minus ~~~ shell_exec;
shell_exec --runs--> sh_entry_script;
sh_entry_script --with--> embedded_code;
heavy_plus ~~~ python_exec;
python_exec --runs--> py_entry_script;
py_entry_script --with--> py_bootstrap_code;
embedded_code --bootstraps--> pinned_python;
py_bootstrap_code --bootstraps--> pinned_python;
pinned_python ~~~ invis_block;
style heavy_minus fill:none,stroke:none;
style heavy_plus fill:none,stroke:none;
style sh fill:none;
style py fill:none;
style invis_block fill:none,stroke:none;
It works without shebang for venv to avoid hardcoding absolute paths and keep repo clones relocatable.
-
Bootstrap (default env):
./prime -
Bootstrap (special env):
./prime --env dst/special_env -
Run some app without
venvactivation:./some_app
and more...
-
From scratch: re-create venv, re-solve and re-install deps, re-pin versions:
./prime reset -
Evaluate the effective config:
./prime eval -
Start an interactive
shellwith an activatedvenv:./prime shell -
Run a function from a module in
venv:./prime start "some_module:some_func" -
Run a function from a module in
venvwith some args:./prime start "some_module:some_func" -- some args
See the Tutorial doc.
You need to "seed" your repo with a copy of the proto_kernel.py script:
%%{init: {"look": "handDrawn", "theme": "neutral"}}%%
graph LR;
install_link["<b>1 x install:</b>"]
github_web["<br>from github.com<br>`protoprimer`<br>repo"]
bootstrap_link["<b>N x bootstrap:</b>"];
pypi_web["<br>from pypi.org<br>`protoprimer`<br>package"]
client_repo["client repo<br>with<br><b>own copy</b><br>of<br>`proto_kernel.py`"];
install_link ~~~ github_web;
github_web --manual copy--> client_repo;
bootstrap_link ~~~ pypi_web;
pypi_web --auto update--> client_repo;
style install_link fill:none,stroke:none;
style bootstrap_link fill:none,stroke:none;
-
Copy (one time):
Commit your own copy next to
pyproject.toml:./ ├── proto_kernel.py <--- own copy ├── pyproject.toml └── *The location, name, and details can be changed through optional config.
This entry_script extends the bootstrap sequence via the cmd_boot_env_example script:
./cmd/boot_env_exampleproto_kernel.boot_env triggers the bootstrap process before invoking a user function:
# ./cmd/boot_env_example:
# ...
proto_kernel.boot_env(
# module_name:function_name
"local_doc.cmd_boot_env_example:custom_boot_env_main"
)See Boot env.
This entry_script invokes the cmd_start_app_example script:
./cmd/start_app_exampleproto_kernel.start_app delegates execution to a user function:
# ./cmd/start_app_example:
# ...
proto_kernel.start_app(
# module_name:function_name
"local_doc.cmd_start_app_example:custom_start_app_main"
)See Start app.
See the Dictionary.
Any code designed to be executed by an arbitrary (wild) python version is called proto_code.
In short, proto_code is what runs outside venv (before switching into it).
Your own copy of proto_kernel.py is an example of proto_code.
It implements in-flight python runtime switching - the hard part provided by protoprimer.
An entry_script is also proto_code - a shim to invoke proto_kernel.
It is a convenient wrapper around a venv function - the easy (generatable) part, as it only delegates:
./cmd/boot_env_example./cmd/start_app_exampleThere are two primary entry functions - see details in boot_vs_start:
| Function: | boot_env | start_app |
|---|---|---|
| Purpose: | extend the default bootstrap with custom steps |
run an arbitrary script from venv with the required python |
| Cardinality: | one script per project | many scripts per project |
| Assumes: | venv is not ready |
venv is ready |
| Example: | ./cmd/boot_env_example |
./cmd/start_app_example |