# Generated by tools/gen_stubs.py from the package source. Do not edit. # `make stubs` regenerates; test/test_stubs.py refuses any difference. """Submit DKE Python to a store, and read what came back. The rest of this package produces a program. This module is the other end: it carries one to your store and hands you the answer as an object instead of a JSON envelope you have to take apart. from dke import FactProgram from dke.client import Client client = Client.from_env() # reads DKE_API_KEY result = client.run("c = current(Sensor.room.temp)\nprint(c.value)") print(result.text, result.ops) IMPORTING THIS MODULE IS A DELIBERATE ACT, AND THAT IS THE DESIGN. `import dke`, `dke.factwriter` and `dke.ingest` reach nothing here, so a producer still opens no socket and still needs no key: you can run a reader over your own source without granting it anything, and read the program it wrote before deciding to send it. This module is the only one in the package that talks to a network, you have to name it to get it, and `test_client.py` asserts both halves — that this module reaches the network and that the producing half cannot reach this module. WHAT IT SPEAKS. The published wire at : MCP over HTTPS, JSON-RPC 2.0, bearer auth, the twelve tools. Reference: . Nothing here is a private protocol — every field this module reads is one that reference names, so a reader can check this file against it line by line. WHY THE ERRORS ARE THREE FAMILIES AND NOT ONE. A failure arrives at one of three levels and they clear by different actions, so collapsing them costs you the fix: * `TransportError` — the call never reached the tool surface at all (HTTP was not 200). Auth, rate limiting, service reachability. * `ProtocolError` — the tool surface answered and refused the request. `PaymentRequired` and `RateLimited` are separate subclasses on purpose: one clears by paying and one by waiting, and a client that cannot tell them apart will back off when it should top up. * a `Result` with `ok == False` — the call completed and the WORK failed. This is not raised, because a compile error is a normal step in writing a program: you read the diagnostics, fix the source, resubmit. Call `raise_for_status()` when you would rather have an exception.""" import json import os import urllib.error import urllib.request from typing import Any from dke import __version__ __all__ = ['Client', 'Result', 'DkeError', 'TransportError', 'ProtocolError', 'PaymentRequired', 'RateLimited', 'DEFAULT_ENDPOINT'] DEFAULT_ENDPOINT: ... PROTOCOL_VERSION: ... class DkeError(Exception): """Base for everything this module raises. Catch it to catch all three.""" class TransportError(DkeError): """The request never reached the tool surface — HTTP was not 200. `code` is the short machine token from the body when there was one (`AUTH_MISSING`, `RATE_LIMITED`, `UPSTREAM_UNAVAILABLE`, …), and `None` when the failure happened before any body could be read at all — a DNS failure, a refused connection, a timeout. Those two are distinguishable and worth distinguishing: one is an answer, the other is silence.""" def __init__(self, message: str, *, status: int | None=None, code: str | None=None) -> None: ... class ProtocolError(DkeError): """The tool surface answered with a JSON-RPC `error` member.""" def __init__(self, message: str, *, code: int) -> None: ... class PaymentRequired(ProtocolError): """-32001 — the account cannot cover the call. Clears by paying.""" class RateLimited(ProtocolError): """-32002 — too many calls. Clears by waiting. `retry_after` is the published `Retry-After` value in seconds when the response carried one, and `None` when it did not. Sleep on the number if you have it; do not invent one if you do not.""" def __init__(self, message: str, *, code: int, retry_after: int | None=None) -> None: ... class Result: """One completed call, with the envelope already taken apart. A call that completed and FAILED is still a Result — see the module docstring. `ok` is the single thing to route on; the published contract guarantees it is exactly `status == "success"`, so the two can never disagree and there is no need to read the prose to find out which happened.""" __slots__: ... def __init__(self, result: dict[str, Any]) -> None: ... def raise_for_status(self) -> Result: """Return self when the work succeeded; raise `DkeError` when it did not. For callers who would rather not branch. The message leads with the status and carries the first diagnostic or the refusal category, since those are the parts that say what to do next.""" ... def value(self, name: str) -> Any: """The value bound to `name`, from the transcript. A program that binds several intermediates produces several entries, and the identifier you used is what separates them — spelled exactly as you wrote it. Raises `KeyError` when no binding by that name appears, which includes the case where the statement ran but bound nothing.""" ... def prints(self) -> list[Any]: """Everything the program printed, in order.""" ... def __repr__(self) -> str: ... class Client: """A connection to one store, over the published wire. `key` is a consumer key — the `dke_c_` kind, from your account dashboard. Your key addresses exactly one store; there is no store to choose per call, and `store_id` exists only for the accounts that hold more than the default one.""" def __init__(self, key: str, *, endpoint: str=DEFAULT_ENDPOINT, store_id: str | None=None, timeout: float=30.0, client_name: str='dkepy', client_version: str=__version__) -> None: ... @classmethod def from_env(cls, var: str='DKE_API_KEY', **kwargs: Any) -> Client: """A client keyed from the environment. Separate from `__init__` deliberately: a key that arrives without the caller naming where it came from is a surprise, and a producer that silently acquired credentials from its environment is exactly the property this package is careful not to have.""" ... def compile(self, name: str, source: str | None=None, *, version: str | None=None, edition: str='python', language: str='eng') -> Result: """Compile a module and KEEP it. Omit `source` to reload a stored one.""" ... def run(self, source: str, *, edition: str='python', language: str='eng') -> Result: """Run instructions WITHOUT storing them. Facts they record persist.""" ... def spec(self, topic: str | None=None, *, edition: str='python') -> Result: """The language contract, whole or one topic slice.""" ... def list(self, target: str='scripts') -> Result: """Stored script signatures, standing-rule names, or the kinds held.""" ... def info(self, name: str) -> Result: """One script's compile provenance. `name` is qualified `module.script`.""" ... def forget(self, name: str) -> Result: """Remove one script, by qualified `module.script` name. Idempotent.""" ... def forget_rule(self, name: str) -> Result: """Remove one standing rule, by qualified `module.rule` name.""" ... def list_modules(self) -> Result: """Module handles: name, script count, created-at.""" ... def info_module(self, name: str) -> Result: """One module's record. `name` is BARE, never `module.script`.""" ... def forget_module(self, name: str, *, confirm: bool=False) -> Result: """Remove a module and everything it owns. NOT reversible. `confirm` must be passed explicitly. It is a keyword with no useful default because the cascade takes the module's kinds and the DATA IN THEM, and a positional `True` at a call site says nothing about what it is agreeing to.""" ... def checkup(self) -> Result: """Does this store meet the reasoning standing over it?""" ... def stores(self) -> Result: """Your store's id, size and created-at. Touches nothing, so it is the call to make first: a success proves the key, the transport and the store before you have written a line.""" ... def tools(self) -> list[str]: """The tool names this endpoint actually serves. Read from the endpoint rather than from a constant in this file, so a client built against an older release can still find out what it is talking to instead of asserting what it remembers.""" ... def call(self, tool: str, arguments: dict[str, Any] | None=None) -> Result: """Call any tool by name — including one newer than this client.""" ...