Skip to main content

Python client for the SynergyPlus distributed EnergyPlus runner.

Project description

SynergyPlus Python SDK

synergyplus is the official Python client for the SynergyPlus distributed EnergyPlus runner. It wraps the apiserver's HTTP API for submitting simulations and parametric batches, polling their state, and fetching results.

Install

pip install synergyplus

# Optional: enable local-file upload (submit a "./model.idf" path) and result
# download (download_results) against S3-compatible storage (MinIO, AWS S3, ...).
pip install "synergyplus[s3]"

Requires Python 3.9+. boto3 is an optional dependency — it is imported lazily and only on the upload/download code path, so submitting s3://... refs or ArtifactRefs never requires it.

Quickstart (S3 refs)

from synergyplus import SynergyClient, ArtifactRef

sp = SynergyClient("http://localhost:8090", token="synergy-dev-key")

sim = sp.submit_simulation(
    engine_version="24.1.0",
    model=ArtifactRef("s3://models/sample/baseline.idf"),
    weather=ArtifactRef("s3://weather/sample/chicago.epw"),
)

sp.wait(sim["id"])
print(sp.get_results(sim["id"]))

Worked example: local file → wait → download results

Pass local filesystem paths for model/weather and the SDK uploads them to object storage, hashes them (sha256), and submits {ref, sha256} so the content-hash cache works. Then download the result artifacts straight to disk.

from synergyplus import SynergyClient

# S3 config can come from kwargs (shown) or env: S3_ENDPOINT / S3_ACCESS_KEY /
# S3_SECRET_KEY / S3_REGION.
sp = SynergyClient(
    "http://localhost:8090",
    token="synergy-dev-key",
    s3_endpoint="http://localhost:9000",   # omit on AWS to use the default endpoint
    s3_access_key="synergy",
    s3_secret_key="synergypass",
    s3_region="us-east-1",
)

# 1. Submit with LOCAL paths — uploaded to the models/ and weather/ buckets at
#    uploads/<sha256>-<basename>. Identical files are not re-uploaded.
sim = sp.submit_simulation(
    engine_version="24.1.0",
    model="./tower.idf",
    weather="./chicago.epw",
)

# 2. Wait for it to finish.
sp.wait(sim["id"])

# 3. Download every result artifact (eplusout.err, *.sql, synergy-summary.json,
#    ...) into a local directory; returns the local file paths.
paths = sp.download_results(sim["id"], "./out")
print(paths)

# 4. Or just grab the metrics dict.
print(sp.get_metrics(sim["id"]))   # {'site_eui': ..., 'total_site_energy': ..., ...}

Batches work the same way — a variant's model (and the shared weather) may be a local path, an s3://... string, or an ArtifactRef; a local model repeated across variants is hashed and uploaded only once (content-addressed).

API

SynergyClient(base_url, token=None, timeout=30.0, *, s3_endpoint=None, s3_access_key=None, s3_secret_key=None, s3_region=None, storage=None)

The s3_* kwargs configure direct object-storage access for local-file upload and result download (each also falls back to the S3_ENDPOINT / S3_ACCESS_KEY / S3_SECRET_KEY / S3_REGION env vars). storage= lets you inject an alternative StorageBackend (see Production below).

Method Description
healthz() GET /healthz — returns True if the apiserver is up.
submit_simulation(*, engine_version, model, weather, priority=None, extraction_spec=None) POST /v1/simulations{id, state}. model/weather may be a local path (auto-uploaded), an s3://... string, or an ArtifactRef.
get_simulation(sim_id) GET /v1/simulations/{id}{id, state, verdict?, result?}.
get_results(sim_id) GET /v1/results/{simId}{verdict, metrics, artifactUri}.
get_metrics(sim_id) Convenience → just the metrics dict (CONTRACT §5).
download_results(sim_id, dest_dir) Download every artifact under the result's artifactUri (s3://results/<hash>/) into dest_dir; returns local file paths. Requires the s3 extra.
wait(sim_id, *, poll=2.0, deadline=None) Block until the simulation reaches a terminal state (succeeded/failed).
submit_batch(*, engine_version, weather, variants, priority=None, max_parallelism=None, idempotency_key=None) POST /v1/batches{batchId, state}. Variant model / shared weather may be local paths (auto-uploaded).
get_batch(batch_id) GET /v1/batches/{id}{id, state, total, succeeded, failed}.
list_batch_simulations(batch_id, *, limit=100, offset=0) GET /v1/batches/{id}/simulations{items, total}.
upload_input(local_path, ref=None, *, bucket=None, prefix="uploads") Manually upload a local file → ArtifactRef (sha256). With ref="s3://..." uploads to that exact key; otherwise content-addressed into bucket (default models). Requires the s3 extra.

model/weather/variant model accept a local path, an s3://... string, or an ArtifactRef. Local-path upload and download_results need S3 config + the s3 extra; a missing file, missing S3 config, or missing boto3 raises a clear StorageError.

Batch example

from synergyplus import SynergyClient, ArtifactRef, Variant

sp = SynergyClient("http://localhost:8090", token="synergy-dev-key")

batch = sp.submit_batch(
    engine_version="24.1.0",
    weather=ArtifactRef("s3://weather/sample/chicago.epw"),
    variants=[
        Variant(model=ArtifactRef("s3://models/a.idf")),
        Variant(model=ArtifactRef("s3://models/b.idf")),
    ],
    max_parallelism=8,
)
print(batch["batchId"])

Production: presigned URLs (recommended)

The local-file upload/download implemented here talks to object storage directly with static S3 credentials. That is great for local MinIO and for AWS-with-credentials, but it is not ideal for production: handing every researcher's laptop long-lived S3 keys is exactly the static-credential / no-IRSA problem called out in the gap analysis.

The production-grade approach is presigned upload/download URLs minted by the apiserver, so the researcher needs only their API key — no S3 credentials ever leave the cluster:

  • POST /v1/uploads{url, ref, fields?} — the API issues a short-lived presigned PUT (or POST-policy) into the correct models/weather bucket; the SDK PUTs the file bytes to url and submits the returned ref + the locally computed sha256.
  • GET /v1/results/{id}/artifacts (or adding presigned download URLs to the existing GET /v1/results/{id} payload) → a list of {name, url} short-lived GET URLs the SDK streams to disk.

This SDK is already structured for that swap: all S3/boto3 knowledge lives behind the StorageBackend interface (synergyplus/storage.py), and SynergyClient takes a storage= injection point. A future PresignedURLBackend implements the same upload_input / download_prefix methods (calling the endpoints above with the API key) and slots in behind the unchanged submit_simulation / download_results methods — no caller changes, and boto3 stops being needed on the client at all.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

synergyplus-0.3.0.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

synergyplus-0.3.0-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file synergyplus-0.3.0.tar.gz.

File metadata

  • Download URL: synergyplus-0.3.0.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for synergyplus-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7a8ecdd1ca337aa59c67283335aac65e6a5acdd499ae3c7f7558ab79f32e456a
MD5 4a0c95a17bda241a0df90c1db0ea4af7
BLAKE2b-256 c4512e353c65a5bf5e383926bf15a53c72d3e2c72622c4291a5b59bc696a2dce

See more details on using hashes here.

Provenance

The following attestation bundles were made for synergyplus-0.3.0.tar.gz:

Publisher: release-pypi.yml on City-Syntax/SynergyPlus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file synergyplus-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: synergyplus-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for synergyplus-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 11b481214f995912d0d875f9872eb524d17b2678b9fadee27231ae0b5e17d4b1
MD5 3543d8d919f02b7c8c6736bc33425fb5
BLAKE2b-256 3ae83a6539389ae6e5361a4f3703e6bc5f5eef3599c14011549a588aefe76991

See more details on using hashes here.

Provenance

The following attestation bundles were made for synergyplus-0.3.0-py3-none-any.whl:

Publisher: release-pypi.yml on City-Syntax/SynergyPlus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page