Python Scripting (spec: script-py)

Napper runs Python scripts (.py files) via Python 3 for pre/post request hooks and test orchestration. Scripts run on the real Python runtime with full access to PyPI — no sandbox, no limits.

Pre/post request hooks (spec: script-pre, script-post)

Reference scripts in your .nap file:

[script]
pre = ./scripts/setup_auth.py
post = ./scripts/validate_response.py

Import the injected ctx from the bundled napper module — no pip install required:

Pre-request scripts (spec: script-pre)

Run before the HTTP request is sent. Use them to set up authentication, generate dynamic data, or modify variables.

# setup_auth.py
from napper import ctx

token = generate_token()
ctx.set("token", token)
ctx.log(f"Token generated: {token[:8]}...")

Post-request scripts (spec: script-post)

Run after the response is received. Use them for complex validation, data extraction, or chaining.

# validate_response.py
from napper import ctx

body = ctx.response.json

# Extract and pass to the next step
ctx.set("userId", str(body["id"]))

# Complex validation
if body["id"] <= 0:
    ctx.fail("User ID must be positive")

ctx.log(f"Created user {body['id']}")

NapContext (spec: script-context)

Scripts receive a ctx object with these members:

Member Available Description
ctx.vars Pre + Post Dict of all resolved variables
ctx.request Pre + Post The request about to be sent (method, url, headers, body)
ctx.response Post only Response with status, headers, body, json, duration_ms
ctx.env Pre + Post Current environment name
ctx.set(key, value) Pre + Post Set a variable for downstream steps
ctx.fail(message) Pre + Post Fail the test with a message
ctx.log(message) Pre + Post Write to test output

Orchestration scripts (spec: script-orchestration)

For complex flows, a .py file can be the entry point and drive requests directly with the injected nap runner:

# orchestration.py
from napper import nap

# Run a request and get the result
login = nap.run("./auth/login.nap")

# Extract token from the response
nap.vars["token"] = login.response.json["token"]

# Run a suite of tests with the token
results = nap.run_list("./crud-tests.naplist")

# Data-driven testing
for user_id in (1, 2, 3, 42, 99):
    nap.vars["userId"] = str(user_id)
    result = nap.run("./users/get-user.nap")
    if result.response.status != 200:
        nap.fail(f"User {user_id} failed")

Reference orchestration scripts in a .naplist:

[steps]
./scripts/orchestration.py

NapRunner (spec: script-runner)

Orchestration scripts receive a nap object:

Member Description
nap.run(path) Run a .nap file, returns a result (status, json, body, headers, duration_ms, passed)
nap.run_list(path) Run a .naplist file, returns a list of results
nap.vars Shared, mutable variable dict
nap.log(message) Write to test output
nap.fail(message) Fail the orchestration with a message

How it works (spec: script-protocol)

Napper hands the context to your script as JSON and reads back any set/fail/log calls — the bundled napper SDK wraps this protocol into the idiomatic ctx / nap objects above. Orchestration calls (nap.run) invoke the Napper binary itself with --output json, so script-driven and direct runs behave identically.

Editor autocomplete

The bundled SDK ships .pyi type stubs, so editors give full completion on ctx and nap. For explicit vendoring or CI caching, install the published package:

pip install napper

Requirements (spec: script-runtime)

Python scripts require Python 3.9+ on the machine. The Napper CLI binary itself is self-contained; .py scripts are executed via python3 (falling back to python), resolved from the nap.pythonPath setting, the NAPPER_PYTHON environment variable, or your PATH. Plain .nap and .naplist files need no runtime at all.

Prefer JavaScript? See JavaScript Scripting. Already in .NET? F# and C# give the same surface.