runnee 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ .venv/
2
+ __pycache__/
3
+ .pytest_cache/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+
10
+ .env
11
+ .env.*
12
+ !.env.example
13
+ coverage/
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 — Unreleased
4
+
5
+ Explicit API-key constructor arguments are supported; existing configuration remains compatible.
6
+
7
+ Initial remote-only Runnee Cloud client: execution, retained history, saved scripts and versions, encrypted secret management, usage, sandbox limits, public plan/health information and scoped telemetry. Includes typed errors, bounded responses, timeouts, cancellation, safe retries and pagination.
8
+
9
+ No package has been published by this implementation. API-key issuance, account management, payment mutations and remote cancellation remain unavailable to SDK API keys.
@@ -0,0 +1,29 @@
1
+ # Contributing
2
+
3
+ Thank you for contributing to the official Runnee Cloud SDK. This repository contains the remote API client only. Keep runtime, infrastructure and customer data out of changes.
4
+
5
+ ## Local checks
6
+
7
+ Use Python 3.11 or later in a virtual environment.
8
+
9
+ ```sh
10
+ python -m venv .venv
11
+ # Activate .venv using your shell.
12
+ python -m pip install -e ".[dev]"
13
+ python -m pytest
14
+ python -m mypy
15
+ python -m ruff check .
16
+ python -m ruff format --check .
17
+ python -m build
18
+ python -m twine check dist/*
19
+ ```
20
+
21
+ ## Pull requests
22
+
23
+ Add regression coverage for behavior changes. Keep public names compatible and document changes in CHANGELOG.md. Never commit real API keys, secret values, .env files or customer responses. Tests use synthetic keys and local HTTP mocks; they neither execute customer scripts nor require production credentials. Live API verification belongs in an isolated staging account.
24
+
25
+ The checked-in openapi.json is the public API contract snapshot. Coordinate API changes with the platform maintainers, then update this snapshot, client types, validation and tests together. Do not add methods for unimplemented endpoints.
26
+
27
+ ## Releases and security
28
+
29
+ Follow [RELEASING.md](RELEASING.md). Use semantic versioning; breaking public changes require a major release (during 0.x, a new minor release). Security reports follow [SECURITY.md](SECURITY.md), rather than public issue reports.
runnee-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Runnee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
runnee-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.5
2
+ Name: runnee
3
+ Version: 0.1.0
4
+ Summary: Official synchronous and asynchronous Python SDK for Runnee Cloud
5
+ Project-URL: Homepage, https://runnee.cloud/docs#sdk
6
+ Project-URL: Repository, https://github.com/Runnee-cloud/runnee-sdk-python
7
+ Project-URL: Issues, https://github.com/Runnee-cloud/runnee-sdk-python/issues
8
+ Author: Runnee
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: runnee,sdk,serverless
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Typing :: Typed
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: httpx<1,>=0.27
17
+ Provides-Extra: dev
18
+ Requires-Dist: build>=1.2; extra == 'dev'
19
+ Requires-Dist: mypy>=1.15; extra == 'dev'
20
+ Requires-Dist: pytest-asyncio>=0.25; extra == 'dev'
21
+ Requires-Dist: pytest>=8; extra == 'dev'
22
+ Requires-Dist: ruff>=0.11; extra == 'dev'
23
+ Requires-Dist: twine>=6; extra == 'dev'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # runnee
27
+
28
+ Official synchronous and asynchronous Python SDK for Runnee Cloud. Remote execution only; no interpreter is distributed. Python 3.11+; one runtime dependency, HTTPX.
29
+
30
+ ## Installation
31
+
32
+ Release candidate: registry commands apply after publication. Local installation from this repository: pip install .
33
+
34
+ ```sh
35
+ pip install runnee
36
+ uv add runnee
37
+ ```
38
+
39
+ ## Quickstart
40
+
41
+ Create a dashboard API key with scripts:execute and set RUNNEE_API_KEY on your server.
42
+
43
+ ```python
44
+ import os
45
+ from runnee import Runnee
46
+
47
+ with Runnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
48
+ result = client.execute(code="function main() { return 10 + 20; }", mode="dry-run")
49
+ if result["success"] and "executionResult" in result:
50
+ print(result["executionResult"].get("returnValue"))
51
+ ```
52
+
53
+ ```python
54
+ import os
55
+ import asyncio
56
+ from runnee import AsyncRunnee
57
+
58
+
59
+ async def main():
60
+ async with AsyncRunnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
61
+ result = await client.execute(code="function main() { return 30; }")
62
+ print(result)
63
+
64
+
65
+ asyncio.run(main())
66
+ ```
67
+
68
+ Use AsyncRunnee in FastAPI async routes; Runnee suits synchronous Flask/Django views and jobs. Clients own reusable connection pools; close them or use context managers.
69
+
70
+ ## Configuration
71
+
72
+ Runnee(api_key=..., base_url="https://api.runnee.cloud", timeout=30, max_retries=2) and AsyncRunnee accept identical configuration. RUNNEE_BASE_URL is an optional fallback. timeout is seconds. HTTP requires loopback or explicit allow_insecure_http development use; redirects and environment proxy inheritance are disabled. Custom HTTPX transports support controlled testing.
73
+
74
+ RequestOptions(timeout=..., max_retries=..., idempotency_key=..., cancel_event=..., on_response=...) supplies per-call behavior. Async client cancellation uses asyncio task cancellation. Sync cancel_event is checked between attempts and received response chunks; an in-flight socket can wait until its HTTPX timeout. Async timeout bounds the complete operation; sync uses the remaining budget for network timeouts and checks the deadline while receiving chunks and between attempts. A client timeout does not change the script execution budget.
75
+
76
+ ## API reference
77
+
78
+ - execute(code=..., mode="dry-run", event=..., retain_source=False, script_name=..., secret_names=..., script_id=..., options=...)
79
+ - executions.list(before=..., status=..., mode=...), get(id), iterate(...). Use for in sync or async for in async code. Pages contain at most20 items; history retention is3days.
80
+ - scripts.list(), create(name=..., code=...), get(id), update(id,name=...,code=...,expected_version=...), delete(id), get_version(id,version), restore(id,version=...,expected_version=...), storage().
81
+ - secrets.list(), get(name), create(name=...,value=...,allow_inline=False,script_ids=...), update(name,value=...,allow_inline=...,script_ids=...), delete(name).
82
+ - usage.get(), summary(), history(days=7|30|90); sandbox.get(); billing.plans(); health.get().
83
+ - telemetry.record_execution(input), record_event(input). External execution records consume quota.
84
+
85
+ Async methods use the same names with await. Returned dictionaries follow API camelCase names and have generated TypedDict definitions in runnee.types. Arguments follow Python snake_case. SDK API-key issuance/revocation, account/payment mutations and remote execution cancellation are not supported.
86
+
87
+ ## Secret usage
88
+
89
+ ```python
90
+ import os
91
+ from runnee import Runnee
92
+
93
+ with Runnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
94
+ client.secrets.create(name="EXTERNAL_API_KEY", value=os.environ["EXTERNAL_API_KEY"], allow_inline=True)
95
+ result = client.execute(
96
+ code='use("secrets"); function main() { return secrets.has("EXTERNAL_API_KEY"); }',
97
+ secret_names=["EXTERNAL_API_KEY"],
98
+ )
99
+ client.secrets.update("EXTERNAL_API_KEY", value=os.environ["REPLACEMENT_API_KEY"])
100
+ client.secrets.delete("EXTERNAL_API_KEY")
101
+ ```
102
+
103
+ Metadata is readable with secrets:read; writes require secrets:write; grants require scripts:execute and secrets:use. Prefer script_ids policies over allow_inline; execute with script_id and the exact current saved source. Secrets remain inaccessible until explicitly named on an execution. Management responses never contain values. See SECURITY.md for disclosure boundaries.
104
+
105
+ ## Reliability and errors
106
+
107
+ Read requests retry transient network failures and 429/500/502/503/504 with exponential jitter and Retry-After. Auth failures are never retried. Writes are not retried by default. Execute retries require an idempotency_key in RequestOptions. Reuse it after an uncertain network failure. Receipts expire after24hours and replay only summaries, not original output; HTTP409 can mean the original execution is pending. Inspect history before choosing a new key.
108
+
109
+ RunneeError subclasses: RunneeAuthenticationError, RunneePermissionError, RunneeValidationError, RunneeRateLimitError, RunneeTimeoutError, RunneeNetworkError, RunneeServerError, RunneeConflictError, RunneeNotFoundError, RunneeResponseError, RunneeCancelledError. Errors expose status/request_id; RateLimit exposes retry_after seconds. Script failures return success=False instead of raising an HTTP exception.
110
+
111
+ ## Development
112
+
113
+ pip install -e '.[dev]'; pytest; mypy; ruff check .; ruff format --check .; python -m build. CI tests supported Python versions and both clients. See CONTRIBUTING.md, CHANGELOG.md and RELEASING.md. MIT licensed. Publication is a separate approved release step.
runnee-0.1.0/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # runnee
2
+
3
+ Official synchronous and asynchronous Python SDK for Runnee Cloud. Remote execution only; no interpreter is distributed. Python 3.11+; one runtime dependency, HTTPX.
4
+
5
+ ## Installation
6
+
7
+ Release candidate: registry commands apply after publication. Local installation from this repository: pip install .
8
+
9
+ ```sh
10
+ pip install runnee
11
+ uv add runnee
12
+ ```
13
+
14
+ ## Quickstart
15
+
16
+ Create a dashboard API key with scripts:execute and set RUNNEE_API_KEY on your server.
17
+
18
+ ```python
19
+ import os
20
+ from runnee import Runnee
21
+
22
+ with Runnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
23
+ result = client.execute(code="function main() { return 10 + 20; }", mode="dry-run")
24
+ if result["success"] and "executionResult" in result:
25
+ print(result["executionResult"].get("returnValue"))
26
+ ```
27
+
28
+ ```python
29
+ import os
30
+ import asyncio
31
+ from runnee import AsyncRunnee
32
+
33
+
34
+ async def main():
35
+ async with AsyncRunnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
36
+ result = await client.execute(code="function main() { return 30; }")
37
+ print(result)
38
+
39
+
40
+ asyncio.run(main())
41
+ ```
42
+
43
+ Use AsyncRunnee in FastAPI async routes; Runnee suits synchronous Flask/Django views and jobs. Clients own reusable connection pools; close them or use context managers.
44
+
45
+ ## Configuration
46
+
47
+ Runnee(api_key=..., base_url="https://api.runnee.cloud", timeout=30, max_retries=2) and AsyncRunnee accept identical configuration. RUNNEE_BASE_URL is an optional fallback. timeout is seconds. HTTP requires loopback or explicit allow_insecure_http development use; redirects and environment proxy inheritance are disabled. Custom HTTPX transports support controlled testing.
48
+
49
+ RequestOptions(timeout=..., max_retries=..., idempotency_key=..., cancel_event=..., on_response=...) supplies per-call behavior. Async client cancellation uses asyncio task cancellation. Sync cancel_event is checked between attempts and received response chunks; an in-flight socket can wait until its HTTPX timeout. Async timeout bounds the complete operation; sync uses the remaining budget for network timeouts and checks the deadline while receiving chunks and between attempts. A client timeout does not change the script execution budget.
50
+
51
+ ## API reference
52
+
53
+ - execute(code=..., mode="dry-run", event=..., retain_source=False, script_name=..., secret_names=..., script_id=..., options=...)
54
+ - executions.list(before=..., status=..., mode=...), get(id), iterate(...). Use for in sync or async for in async code. Pages contain at most20 items; history retention is3days.
55
+ - scripts.list(), create(name=..., code=...), get(id), update(id,name=...,code=...,expected_version=...), delete(id), get_version(id,version), restore(id,version=...,expected_version=...), storage().
56
+ - secrets.list(), get(name), create(name=...,value=...,allow_inline=False,script_ids=...), update(name,value=...,allow_inline=...,script_ids=...), delete(name).
57
+ - usage.get(), summary(), history(days=7|30|90); sandbox.get(); billing.plans(); health.get().
58
+ - telemetry.record_execution(input), record_event(input). External execution records consume quota.
59
+
60
+ Async methods use the same names with await. Returned dictionaries follow API camelCase names and have generated TypedDict definitions in runnee.types. Arguments follow Python snake_case. SDK API-key issuance/revocation, account/payment mutations and remote execution cancellation are not supported.
61
+
62
+ ## Secret usage
63
+
64
+ ```python
65
+ import os
66
+ from runnee import Runnee
67
+
68
+ with Runnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
69
+ client.secrets.create(name="EXTERNAL_API_KEY", value=os.environ["EXTERNAL_API_KEY"], allow_inline=True)
70
+ result = client.execute(
71
+ code='use("secrets"); function main() { return secrets.has("EXTERNAL_API_KEY"); }',
72
+ secret_names=["EXTERNAL_API_KEY"],
73
+ )
74
+ client.secrets.update("EXTERNAL_API_KEY", value=os.environ["REPLACEMENT_API_KEY"])
75
+ client.secrets.delete("EXTERNAL_API_KEY")
76
+ ```
77
+
78
+ Metadata is readable with secrets:read; writes require secrets:write; grants require scripts:execute and secrets:use. Prefer script_ids policies over allow_inline; execute with script_id and the exact current saved source. Secrets remain inaccessible until explicitly named on an execution. Management responses never contain values. See SECURITY.md for disclosure boundaries.
79
+
80
+ ## Reliability and errors
81
+
82
+ Read requests retry transient network failures and 429/500/502/503/504 with exponential jitter and Retry-After. Auth failures are never retried. Writes are not retried by default. Execute retries require an idempotency_key in RequestOptions. Reuse it after an uncertain network failure. Receipts expire after24hours and replay only summaries, not original output; HTTP409 can mean the original execution is pending. Inspect history before choosing a new key.
83
+
84
+ RunneeError subclasses: RunneeAuthenticationError, RunneePermissionError, RunneeValidationError, RunneeRateLimitError, RunneeTimeoutError, RunneeNetworkError, RunneeServerError, RunneeConflictError, RunneeNotFoundError, RunneeResponseError, RunneeCancelledError. Errors expose status/request_id; RateLimit exposes retry_after seconds. Script failures return success=False instead of raising an HTTP exception.
85
+
86
+ ## Development
87
+
88
+ pip install -e '.[dev]'; pytest; mypy; ruff check .; ruff format --check .; python -m build. CI tests supported Python versions and both clients. See CONTRIBUTING.md, CHANGELOG.md and RELEASING.md. MIT licensed. Publication is a separate approved release step.
@@ -0,0 +1,31 @@
1
+ # Releasing
2
+
3
+ This repository is prepared for public release but no registry publication is implied by its presence. Never publish before the matching API and secrets features have passed staging verification. The SDK does not deploy or configure the service.
4
+
5
+ ## GitHub setup (maintainer)
6
+
7
+ Create an empty **public** repository named runnee-sdk-python under `Runnee-cloud` (or update all repository URLs first). From the prepared SDK folder:
8
+
9
+ ```sh
10
+ git init -b main
11
+ git add .
12
+ git commit -m "Initial public SDK release"
13
+ git remote add origin https://github.com/Runnee-cloud/runnee-sdk-python.git
14
+ git push -u origin main
15
+ ```
16
+
17
+ Review `git diff --cached` before committing. Never upload the parent application repository. Enable GitHub private vulnerability reporting, dependency alerts and branch protection. Create the `pypi` GitHub Actions environment; restrict it to main and require a maintainer review if available for your account. The workflow only publishes when manually requested with publish=true on main. Ordinary pushes and tags run CI only. A manual run with publish=false builds downloadable artifacts without publishing.
18
+
19
+ ## Versioning
20
+
21
+ Use semantic versioning. Update all version constants and CHANGELOG.md together. Search for the previous version in tracked files, including HTTP User-Agent strings; review the diff and regenerate distribution files. The workflow checks the expected version before building. Once published, treat versioned artifacts as immutable. After publication, tag the exact tested commit `vVERSION` and attach checksums and artifacts to a GitHub release.
22
+
23
+ ## PyPI
24
+
25
+ 1. Confirm `runnee` availability and ownership at https://pypi.org/project/runnee/. A 404 does not reserve the name. If unavailable, select another distribution name and update pyproject.toml and installation documentation consistently.
26
+ 2. Run the checks in CONTRIBUTING.md, `python -m build`, and `python -m twine check dist/*`. Inspect both the wheel and source archive.
27
+ 3. In your PyPI account, add a **pending publisher** for project `runnee`: owner `Runnee-cloud`, repository `runnee-sdk-python`, workflow `release.yml`, environment `pypi`. For an existing project, add the same configuration in its Publishing settings.
28
+ 4. Actions → Release → Run workflow on main; set the expected version and publish=true. Approve the pypi environment job. The workflow publishes the previously built distributions using OIDC; no PyPI token belongs in GitHub secrets.
29
+ 5. Verify in a clean environment using `pip install runnee==VERSION` and check sync and async imports. Also verify `uv add runnee==VERSION`.
30
+
31
+ See [PyPI pending publishers](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/) and [publishing with OIDC](https://docs.pypi.org/trusted-publishers/using-a-publisher/).
@@ -0,0 +1,11 @@
1
+ # Security policy
2
+
3
+ Report vulnerabilities privately through GitHub private vulnerability reporting for the repository, when enabled. If unavailable, use the Runnee contact form and request a private security channel; do not post credentials or exploitable details publicly.
4
+
5
+ API keys belong only on trusted servers. These SDKs execute code remotely and contain no interpreter. Requests use HTTPS by default, do not follow redirects, and do not log credentials or retain raw response bodies in exceptions. HTTP is limited to loopback unless explicitly enabled for development. Never disable TLS verification in production.
6
+
7
+ Only the latest released minor version receives fixes while the SDK is pre-1.0. Dependencies should be patched promptly. Caller-provided transports are trusted code and must preserve authentication and TLS protections.
8
+
9
+ Execution retries require an idempotency key. Receipt replays omit the original output, and a pending result is not evidence that execution failed. Client cancellation stops waiting; it does not guarantee remote cancellation.
10
+
11
+ Secrets are encrypted by Runnee and granted explicitly to executions. Management returns metadata only. Do not put credentials in script source, events, telemetry, replies or errors. Redaction covers common accidental verbatim/encoded disclosure; it cannot stop an authorized malicious script from transforming or sending a secret to an external endpoint. Review secret-enabled scripts and narrow HTTP permissions. SDK request bodies necessarily contain values during create/rotate; configure application/APM instrumentation to omit them.
@@ -0,0 +1,13 @@
1
+ import os
2
+ import asyncio
3
+ from runnee import AsyncRunnee
4
+
5
+
6
+ async def main() -> None:
7
+ async with AsyncRunnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
8
+ result = await client.execute(code="function main(){return 10+20;}")
9
+ print(result)
10
+
11
+
12
+ if __name__ == "__main__":
13
+ asyncio.run(main())
@@ -0,0 +1,6 @@
1
+ import os
2
+ from runnee import Runnee
3
+
4
+ with Runnee(api_key=os.environ["RUNNEE_API_KEY"]) as client:
5
+ result = client.execute(code="function main(){return 10+20;}", mode="dry-run")
6
+ print(result)