Skip to main content

psrunner

PyPI Python License: MIT

The Python SDK of PythonScriptRunner, a .NET library that runs Python scripts with a typed contract.

A stage is one Python script with typed inputs and outputs. The .NET runner validates the inputs, runs the script in an isolated process with a timeout and a memory limit, and validates the outputs. psrunner handles the protocol between the two sides, so the script only contains the logic.

Documentation: Python SDK guide | guia em português

Installation

The .NET runner installs psrunner in every environment it creates, so stages never list it in their requirements. Install it yourself to write and test scripts locally:

pip install psrunner             # Python 3.10 or newer
pip install "psrunner[pandas]"   # table inputs arrive as pandas.DataFrame

Writing a stage

from psrunner import stage, StageError

@stage
def run(inputs, ctx):
    a1, ratio, n = inputs["a1"], inputs["ratio"], inputs["n"]
    if n < 1:
        raise StageError("n must be at least 1.", code="INVALID_N")

    terms = [a1 * ratio**i for i in range(n)]
    ctx.log.info("generated %d terms", n)
    return {"terms": terms}

The contract lives in stage.json, next to the script:

{
  "key": "progression-terms",
  "version": 1,
  "name": "Progression terms",
  "inputs": [
    { "name": "a1", "type": "number" },
    { "name": "ratio", "type": "number" },
    { "name": "n", "type": "integer" }
  ],
  "outputs": [ { "name": "terms", "type": "list", "itemType": "number" } ]
}

The rules:

  • One entry point: exactly one function per script is marked with @stage. It receives the inputs, already converted, and the context.
  • Return value: it returns a dict with the outputs. Required outputs must be present, and outputs outside the contract are an error.

Types

Contract type Python value
number float (NaN and infinity are rejected)
integer int
decimal decimal.Decimal
string str
bool bool
date datetime.date
datetime datetime.datetime with a UTC offset
enum str, one of enumValues
json dict, list, str, number, bool or None
table list[dict], or pandas.DataFrame with the pandas extra
file psrunner.File
list list of the item type

The context

Member Description
ctx.log A logging.Logger; its lines appear in the run's logs.
ctx.secrets Read-only mapping with the secrets the stage declares.
ctx.new_file(name, content_type=None) Reserves an output file and returns a File; write to file.path and return it.
ctx.run_id, ctx.step_key, ctx.attempt Identify the run, the pipeline step and the attempt.
ctx.stage_key, ctx.stage_version, ctx.is_test The stage being run, and whether this is a test of a draft.
ctx.work_dir, ctx.out_dir, ctx.tmp_dir The attempt's own folders.

A File has path, name, content_type, size and sha256, and the methods read_bytes(), read_text() and open().

@stage
def run(inputs, ctx):
    report = ctx.new_file("report.csv", "text/csv")
    report.path.write_text("x,y\n1,2\n", encoding="utf-8")
    return {"report": report}

Errors

  • Business errors: StageError(message, code="CODE", details={...}) fails the run as ScriptError with that code.
  • Unexpected exceptions: any other exception also becomes ScriptError, with the traceback of your script.
  • Contract violations: a missing output, a wrong type or a non-finite number becomes OutputContractViolation.

Testing with pytest

psrunner.testing.run_stage runs the function with the same conversions and validations as the real runner, without .NET:

from psrunner.testing import run_stage

def test_terms():
    result = run_stage(
        "stages/progression-terms/script.py",
        {"a1": 1, "ratio": 2, "n": 4},
        stage_json="stages/progression-terms/stage.json",
    )
    assert result.ok
    assert result.outputs == {"terms": [1, 2, 4, 8]}

run_stage also accepts secrets, files (file fields mapped to local paths), work_dir and run_id. The result has ok, outputs, wire_outputs, error (kind, code, message, traceback), logs and work_dir.

Command line

psrunner validate stages/progression-terms
psrunner run stages/progression-terms --input sample.json --secret NAME=value --keep
Command What it does
validate <folder> Checks stage.json and that the script has exactly one @stage function.
run <folder> Runs the stage with the real protocol, in a separate process and a temporary folder. In sample.json, file inputs are written as {"$path": "relative/path"}.

The same commands work as python -m psrunner.

Compatibility

psrunner follows protocol 1, the format exchanged with the .NET runner, for as long as that protocol is in use.

psrunner Protocol PythonScriptRunner (NuGet) Python
0.1.x 1 0.1.x 3.10 to 3.13

License

MIT

Metadata

Release files for psrunner 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for psrunner 0.1.1
File Size Uploaded Provenance Actions
psrunner-0.1.1.tar.gz 94.3 kB With provenance Details for psrunner-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for psrunner 0.1.1
File Interpreter ABI Platform Actions
psrunner-0.1.1-py3-none-any.whl Python 3 none any Details for psrunner-0.1.1-py3-none-any.whl

Total release size: 122.2 kB

Release files / psrunner-0.1.1.tar.gz

Download URL psrunner-0.1.1.tar.gz
Size 94.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ccf5b90c86056eea33e237ee87619d7be284d000b5f0620504bd2f6e9a477b1c
BLAKE2b-256 checksum
How to use checksums
2ab56862cce3b2b6c994c57ef6163ec505f6dc2e961267b240226b9b26eccdcb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

Release files / psrunner-0.1.1-py3-none-any.whl

Download URL psrunner-0.1.1-py3-none-any.whl
Size 27.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a85f499278acb5859bd5d3093e5a74b7144698c296827c592b61be317c2eae8e
BLAKE2b-256 checksum
How to use checksums
6f0d5db1b926321c7d04675375a64adbec34d9449d22dc143d906e8c114f58cf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

Security for psrunner 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for psrunner-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page