Reference Python executor for the Lace probe scripting language. Depends on lacelang-validator for parsing and semantic checks.
Project description
lacelang-executor (python)
Canonical Python executor for Lace —
the reference implementation with 100% spec conformance. Runs .lace
scripts against real HTTP endpoints and emits ProbeResult JSON.
This is the executor that the Lace specification is developed and tested against. Conformance vectors, error codes, and wire-format schemas are verified against this implementation before each spec release.
Parsing and semantic validation are delegated to
lacelang-validator — this package contains
only the runtime (HTTP client, assertion evaluation, cookie jars, extension
dispatch). See lace-spec.md §15 for the validator / executor package
separation rule.
Install
pip install lacelang-executor
This automatically installs lacelang-validator as a dependency.
Or from source:
pip install git+https://github.com/tracedown/lacelang-python-executor.git
Usage
# Parse (delegates to validator)
lacelang-executor parse script.lace
# Validate (delegates to validator)
lacelang-executor validate script.lace --context context.json --vars-list vars.json
# Run — full HTTP execution
lacelang-executor run script.lace \
--vars vars.json \
--prev prev.json \
--bodies-dir ./bodies
# Enable extensions (laceNotifications is built in)
lacelang-executor run script.lace --enable-extension laceNotifications
All subcommands support --pretty for indented JSON.
Library usage
Project layout
The executor expects Lace files under a dedicated lace/ directory:
my-project/
lace/
lace.config # executor config (auto-discovered)
config.staging.json # env-specific overrides (optional)
extensions/ # third-party extensions
myext/
myext.laceext
myext.config
scripts/
health/
health.lace # script (name = directory name)
vars.json # default variables
vars.staging.json # env-specific variables
auth-flow/
auth-flow.lace
vars.json
All paths are overridable at runtime — the layout is a convention, not a requirement.
LaceExecutor + LaceProbe
from lacelang_executor import LaceExecutor
# Point to the lace/ directory — config loaded once
executor = LaceExecutor("lace")
# Or override the config path directly
executor = LaceExecutor(config="path/to/lace.config", env="staging")
# Register third-party extensions
executor.extension("lace/extensions/myext") # directory (finds myext.laceext + myext.config)
executor.extension("path/to/custom.laceext", "path/to/custom.config") # explicit paths
# Prepare a probe by name — resolves to lace/scripts/health/health.lace
# AST is parsed and validated once, reused across runs
probe = executor.probe("health")
# Run — returns a ProbeResult dict
result = probe.run(vars={"base_url": "https://api.example.com"})
# Run again — prev result from last run injected automatically
result = probe.run()
# All inputs accept file paths or dicts
result = probe.run(
vars="lace/scripts/health/vars.staging.json",
prev="results/last_run.json", # explicit prev overrides auto-tracking
)
One-shot execution
# No probe caching, no prev tracking
result = executor.run("lace/scripts/health/health.lace", vars={"key": "val"})
# Inline source
result = executor.run('''
get("https://api.example.com/health")
.expect(status: 200)
''')
Development mode
# Re-read and re-parse the script file on every run()
probe = executor.probe("health", always_reparse=True)
API reference
LaceExecutor(root, *, config, env, extensions, track_prev)
| Parameter | Type | Default | Description |
|---|---|---|---|
root |
str | None |
None |
Path to the lace/ directory. Discovers lace.config and resolves script names relative to {root}/scripts/. |
config |
str | None |
None |
Explicit path to lace.config (overrides root-based discovery). |
env |
str | None |
None |
Selects [lace.config.{env}] section (overrides LACE_ENV). |
extensions |
list[str] | None |
None |
Built-in extensions to activate (e.g. ["laceNotifications"]). |
track_prev |
bool |
True |
Auto-store last result as prev for next run on each probe. |
executor.extension(path, config_path=None) — register a third-party extension.
executor.probe(script, *, vars, always_reparse) — prepare a reusable probe.
| Parameter | Type | Default | Description |
|---|---|---|---|
script |
str |
— | Script name ("health"), file path ("path/to.lace"), or inline source. |
always_reparse |
bool |
False |
Re-read script file on every run(). |
probe.run(vars, prev, *, reparse) — execute and return ProbeResult.
| Parameter | Type | Default | Description |
|---|---|---|---|
vars |
str | dict | None |
None |
Script variables — dict or path to JSON. |
prev |
str | dict | None |
None |
Previous result — dict or path to JSON. Overrides auto-tracking. |
reparse |
bool |
False |
Re-read script from disk for this run only. |
Config and environment overrides
There is exactly one config file per executor. The env parameter
selects a section within that file, not a different file.
# lace/lace.config
[executor]
maxRedirects = 10
maxTimeoutMs = 300000
# Staging overlay — deep-merged on top of base.
# Only the keys you specify are overridden; the rest is inherited.
[lace.config.staging]
[lace.config.staging.executor]
maxTimeoutMs = 60000 # overridden
# maxRedirects is inherited (10)
[lace.config.production]
[lace.config.production.executor]
user_agent = "lace-probe/0.9.1 (acme-platform)"
Resolution by constructor arguments:
| Constructor | Config file | Env overlay |
|---|---|---|
LaceExecutor("lace") |
lace/lace.config |
none (base only) |
LaceExecutor("lace", env="staging") |
lace/lace.config |
[lace.config.staging] merged on base |
LaceExecutor(config="/path/lace.config", env="prod") |
/path/lace.config |
[lace.config.prod] merged on base |
LaceExecutor("lace", config="/other/lace.config") |
/other/lace.config |
none (root still used for script names) |
LACE_ENV=staging + LaceExecutor("lace") |
lace/lace.config |
[lace.config.staging] (from env var) |
LACE_ENV=staging + LaceExecutor("lace", env="prod") |
lace/lace.config |
[lace.config.prod] (kwarg wins) |
The config= kwarg overrides where the file is loaded from.
The env= kwarg (or LACE_ENV) selects which section inside
that file is overlaid. They are independent — setting one does
not affect the other.
Return value
Both probe.run() and executor.run() return a dict matching the
ProbeResult wire format (spec §9):
{
"outcome": "success", # "success" | "failure" | "timeout"
"startedAt": "2026-04-20T10:00:00.000Z",
"endedAt": "2026-04-20T10:00:01.234Z",
"elapsedMs": 1234,
"runVars": {}, # run-scoped variables from .store()
"calls": [...], # per-call result records
"actions": {}, # write-back variables, notifications, etc.
}
Low-level API
The stateless run_script() function is available for callers that need
full control over parsing, validation, and config:
from lacelang_validator.parser import parse
from lacelang_executor.executor import run_script
from lacelang_executor.config import load_config
ast = parse(open("script.lace").read())
config = load_config(explicit_path="lace.config")
result = run_script(ast, script_vars={"key": "val"}, config=config)
User-Agent
Per lace-spec.md §3.6, this executor sets a default User-Agent on
outgoing requests:
User-Agent: lace-probe/<version> (lacelang-python)
Precedence (highest first): per-request headers: { "User-Agent": ... } →
lace.config [executor].user_agent → the default above.
Responsible use
This software is designed for monitoring endpoints you own or have
explicit authorization to probe. You are solely responsible for
ensuring your use complies with all applicable laws, terms of service,
and acceptable use policies. See NOTICE for the full statement.
License
Apache License 2.0
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lacelang_executor-0.1.0.tar.gz.
File metadata
- Download URL: lacelang_executor-0.1.0.tar.gz
- Upload date:
- Size: 70.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00329a130e5bbbf2bc2bf61d8d1b83164082c9c83b84ef0b41f417dd2baee15e
|
|
| MD5 |
db88dc1c083461e5c98ab49fa34968c6
|
|
| BLAKE2b-256 |
fc67b96f07e11dcf9cc3db93ac416cf202ed3d51b7030072759eab37a8e53425
|
Provenance
The following attestation bundles were made for lacelang_executor-0.1.0.tar.gz:
Publisher:
release.yml on tracedown/lacelang-python-executor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lacelang_executor-0.1.0.tar.gz -
Subject digest:
00329a130e5bbbf2bc2bf61d8d1b83164082c9c83b84ef0b41f417dd2baee15e - Sigstore transparency entry: 1361950608
- Sigstore integration time:
-
Permalink:
tracedown/lacelang-python-executor@2599eb8ee5c1abf6de8186755d7e8b2068757e64 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tracedown
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2599eb8ee5c1abf6de8186755d7e8b2068757e64 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lacelang_executor-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lacelang_executor-0.1.0-py3-none-any.whl
- Upload date:
- Size: 73.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d538c0a53b9269e2bbcea5dbe5f5d8aeca3f897132cfc69e784c594ea624e04
|
|
| MD5 |
a09e4b06f1b2b2aad506ee14acd2f845
|
|
| BLAKE2b-256 |
c2a1f9bc5b36d45f9ab8a6e24537483ff1e591a4b54da45a75f31950a4723c2e
|
Provenance
The following attestation bundles were made for lacelang_executor-0.1.0-py3-none-any.whl:
Publisher:
release.yml on tracedown/lacelang-python-executor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lacelang_executor-0.1.0-py3-none-any.whl -
Subject digest:
4d538c0a53b9269e2bbcea5dbe5f5d8aeca3f897132cfc69e784c594ea624e04 - Sigstore transparency entry: 1361950678
- Sigstore integration time:
-
Permalink:
tracedown/lacelang-python-executor@2599eb8ee5c1abf6de8186755d7e8b2068757e64 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tracedown
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2599eb8ee5c1abf6de8186755d7e8b2068757e64 -
Trigger Event:
push
-
Statement type: