Python SDK for the DMN mesh — call tenant APIs from your code.
Project description
dmn-sdk
Python client for the DMN mesh. Call tenant APIs from your own code with one import.
Install
From a checkout:
pip install ./sdk/python/
From PyPI (v0.282.3+):
pip install dmn-sdk
Requires Python 3.9+. Pulls in requests and websocket-client.
Quickstart
import dmn_sdk as dmn
client = dmn.connect() # reads DMN_API_TOKEN env
ingestor = client.tenant("/tata/dmn/acme").app("ingestor")
# Unary POST
resp = ingestor.post("/telemetry", json={"sensor": "s1", "value": 23.4})
print(resp.status_code, resp.json())
# Subscribe to a topic
for msg in ingestor.subscribe("telemetry"):
print(msg.seq, msg.payload)
Authentication
Three sources, in priority order:
- Explicit kwargs to
dmn.connect(token=..., base_url=...) - Environment:
DMN_API_TOKEN+DMN_API_BASE_URL+ (optional)DMN_PROFILE - Config file
~/.dmn/credentials(INI-style)
Env var setup
# Mint a token at /ui/dev/tokens/ on the dashboard,
# then export:
export DMN_API_TOKEN="eyJhbGc...the wire JWT..."
export DMN_API_BASE_URL="https://console.dmn.inno8cube.com"
Config file setup
~/.dmn/credentials:
[default]
token = eyJhbGc...
base_url = https://console.dmn.inno8cube.com
[acme-prod]
token = eyJhbGc...
base_url = https://console.dmn.acme.io
Pick a profile:
client = dmn.connect(profile="acme-prod")
Or via env: export DMN_PROFILE=acme-prod.
API reference
dmn.connect(...)
def connect(
token: str | None = None,
base_url: str | None = None,
*,
profile: str | None = None,
config_path: str | None = None,
timeout: float = 30,
ws_timeout: float = 30,
verify_tls: bool = True,
user_agent: str | None = None,
) -> Client
Returns a Client. Raises dmn.ConfigError if no source can supply token + base_url.
Client.tenant(name)
def tenant(self, name: str) -> Tenant
name must be a full NDN name starting with /, e.g. "/tata/dmn/acme". Returns a Tenant.
Tenant.app(name)
def app(self, name: str) -> App
Returns an App handle.
Unary methods on App
app.get(path, **kwargs) -> Response
app.post(path, **kwargs) -> Response
app.put(path, **kwargs) -> Response
app.patch(path, **kwargs) -> Response
app.delete(path, **kwargs) -> Response
**kwargs are passed through to requests.Session.request — most useful ones: json=, data=, params=, headers=, timeout=.
App.subscribe(topic)
def subscribe(self, topic: str) -> Iterator[Message]
Opens a WebSocket to the gateway's subscribe bridge. Yields Message(seq, topic, payload, ts) objects as they arrive. The iterator runs until the server closes the connection or you break. Re-iterating opens a fresh connection.
Response
resp.status_code -> int
resp.ok -> bool # True for 2xx
resp.headers -> dict[str,str]
resp.text -> str
resp.content -> bytes
resp.json() -> Any
resp.raw -> requests.Response # power-user escape hatch
Message
@dataclass(frozen=True)
class Message:
seq: int # per-topic monotonic sequence number
topic: str # which topic this message was on
payload: Any # decoded JSON body
ts: int # unix timestamp (seconds) at the publisher
Errors
All raised by the SDK descend from dmn.DMNError:
| Exception | When |
|---|---|
dmn.ConfigError |
Missing token/base_url, malformed config file, unknown profile |
dmn.AuthError |
Gateway returned 401 or 403 |
dmn.NotFoundError |
Gateway returned 404 (tenant/app not in routing table) |
dmn.BackendError |
5xx from the backend, transport failures, gateway-streamed error frame |
dmn.APIError |
Other non-2xx responses |
Most application code wants:
try:
resp = ingestor.post("/telemetry", json={...})
except dmn.AuthError:
# Token issue — re-mint or re-auth
raise
except dmn.NotFoundError:
# Misconfigured route
raise
except dmn.BackendError as e:
# Retryable
print(f"retrying: {e}")
Examples
See examples/:
post_telemetry.py— single-shot POST to the reference ingestorsubscribe_topic.py— WebSocket-backed iterator consuming a topic
Dev notes
# Run tests
cd sdk/python
pip install -e ".[dev]"
pytest -v
# Lint (if installed)
ruff check dmn_sdk tests
Versioning
The SDK version tracks the DMN agent's compatible wire format. v0.282.x is the first stable line; breaking changes to the gateway's REST/WS surface will bump the major. Backwards-compatible additions bump the minor.
License
Restricted-Use Evaluation Licence — see ../../docs/RESTRICTED-USE-LICENSE.md.
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 dmn_sdk-0.4.0.tar.gz.
File metadata
- Download URL: dmn_sdk-0.4.0.tar.gz
- Upload date:
- Size: 63.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02f929f94a5690e36447c1614195f1ccb19f00033a5c8c15d3448a1e169a7490
|
|
| MD5 |
e7a0707c066a82de9ae89532a17f4583
|
|
| BLAKE2b-256 |
82df0f9ede47d7050e52b410d601facca9f508e09f0f0a2d3dd18f793fa64451
|
File details
Details for the file dmn_sdk-0.4.0-py3-none-any.whl.
File metadata
- Download URL: dmn_sdk-0.4.0-py3-none-any.whl
- Upload date:
- Size: 60.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4eb8e419b68e7f688daf6b299639a2dd03eda1d0b3e84a71fe3e0e73f9642ae3
|
|
| MD5 |
dac03f2f0a78ee296b37826d822bc2ee
|
|
| BLAKE2b-256 |
2348d9ebaacf49353f410a47dd0d2b2d9a925673f7de4b9ac27df6100c23b474
|