Skip to main content

TinySDK

Shared service clients for the TinyAI microservices platform — MongoDB, MinIO, Temporal workers, and structured logging with a consistent interface.

Installation

pip install tinysdk

Quick Start

from tinysdk import TinyDBService, TinyStorageService, TinyWorkerService, TinyWorkflowService, get_temporal_client, TinyLogger

# MongoDB
db = TinyDBService()
doc_id = db.create("users", {"name": "John", "email": "john@example.com"})
users = db.read("users", filter={"name": "John"})
count = db.update("users", {"name": "John"}, {"$set": {"active": True}})
count = db.delete("users", {"name": "John"})
exists = db.exists("users", {"email": "john@example.com"})
ids = db.create_multiple("users", [{"name": "Alice"}, {"name": "Bob"}])
db.close()

# MinIO / S3
storage = TinyStorageService()
storage.upload_file("my-bucket", "file.txt", buffer)  # file_size auto-detected
storage.upload_file("my-bucket", "file.txt", buffer, 1024)  # or pass explicitly
file_buffer, name = storage.download_file("my-bucket", "file.txt")
storage.upload_folder("my-bucket", "/local/folder")
storage.download_folder("my-bucket", "folder-name", "/local/dest")
storage.close()

# Temporal (activity/workflow worker for a task queue)
from temporalio import activity


@activity.defn
async def my_activity(payload: dict) -> None: ...


worker = TinyWorkerService()  # logger optional; defaults to TinyLogger()
await worker.start(task_queue="my-queue", activities=[my_activity])  # or workflows=[...]

# Or just a connected client
client = await get_temporal_client()

# Temporal (read-only workflow queries) — async, call from an async function
workflow_svc = TinyWorkflowService()
status = await workflow_svc.get_status("order-123")  # status, timings, task queue
history = await workflow_svc.get_history_summary("order-123")  # condensed event history
summary = await workflow_svc.get_summary("order-123")  # status + history in one call

# Logger
logger = TinyLogger()
logger.log("something happened", level="INFO", context={"key": "value"})
logger.start_heartbeat()  # emits periodic HEARTBEAT events
logger.stop_heartbeat()  # clean shutdown

doc_logger = logger.for_document("doc-id-123")
doc_logger.log("processing started")

Configuration

All clients read credentials from environment variables.

Service Variable Example
MongoDB DB_LINK mongodb://mongo:27017
MongoDB DB_NAME tinyDatabase
MinIO MINIO_ENDPOINT minio:9000
MinIO MINIO_ACCESSKEY minioadmin
MinIO MINIO_SECRETKEY minioadmin
Temporal TEMPORAL_ADDRESS temporal-server:7233
Temporal TEMPORAL_NAMESPACE default
Logger SERVICE_NAME my-service
Logger CLUSTER prod
Logger NAMESPACE default
Logger LOG_LEVEL INFO
Logger HEARTBEAT_INTERVAL 30

Credentials can also be passed directly as constructor arguments.

Storage backends

TinyStorageService addresses storage by logical namespace (customer-documents, tiny-models). A router resolves each namespace to a target and a physical location.

With no TINYSTORAGE_* variables set, every namespace resolves to the platform target — S3, bucket name equal to the namespace. This is the default and needs no configuration.

To route some namespaces to client-owned storage:

TINYSTORAGE_CLIENT_BACKEND=<registered backend name>
TINYSTORAGE_CLIENT_ROOT=/mnt/client-storage
TINYSTORAGE_MAP=customer-documents=client,finalized-documents=client

Both halves of that configuration are validated at startup, because either mistake ends with customer data on Synapze S3 and nothing to notice:

  • mapping a namespace to client with no client backend configured, and
  • configuring a client backend that no namespace is mapped to,

are both startup errors, never a silent fallback. So is mapping the same namespace twice. Namespaces must match [a-z0-9]([a-z0-9.-]*[a-z0-9])? — S3 bucket syntax — because a namespace becomes a path segment under the client root, and anything outside that charset can never match a real call site and would only ever be a typo routed silently to platform S3.

Every reachable backend is constructed at startup, so a malformed endpoint or an option the adapter does not accept fails at boot. This is not a reachability check: no client library performs network I/O in its constructor, so an unreachable host or a wrong secret still surfaces on first use.

TinyStorageService.client exposes the raw Minio client for the platform target and ignores routing entirely. It therefore raises as soon as any namespace is mapped to client — otherwise a caller could read or write customer-owned data straight from Synapze S3. Use list_objects() and the routed methods instead.

Adding a backend

  1. Add a module under src/tinysdk/storage/backends/ implementing StorageBackend.
  2. Add it to REGISTRY in backends/__init__.py.
  3. Add a test subclassing the shipped conformance suite:
from tinysdk.storage.conformance import StorageBackendConformance


class TestMyBackendConformance(StorageBackendConformance):
  def make_backend(self):
    return MyBackend(...)

Path-based backends must:

  • call validate_key on every key, and set enforces_key_policy = True on their conformance subclass so the suite checks it;
  • also confirm the resolved path is still under their root (os.path.realpath(p).startswith(root)) — validate_key vets the key string, but a symlink already inside the root can redirect an otherwise valid key;
  • write via a temporary file in the target directory followed by an atomic rename — a temp file elsewhere makes the rename cross-device, which silently degrades to a copy and loses atomicity;
  • decide how to handle unicode normalization (NFC and NFD spellings collide on APFS and SharePoint) and case-insensitive volumes (A.txt vs a.txt).

Options reach an adapter from TINYSTORAGE_CLIENT_* as strings; an adapter with non-string options must coerce them itself.

License

MIT

Metadata

Release files for tinysdk 0.9.8

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

Source distribution (sdist)

Source distribution for tinysdk 0.9.8
File Size Uploaded
tinysdk-0.9.8.tar.gz 104.0 kB Details

Built distribution (wheel)

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

Total release size: 178.7 kB

Release files / tinysdk-0.9.8.tar.gz

Download URL tinysdk-0.9.8.tar.gz
Size 104.0 kB
Tags Source
SHA-256 checksum
How to use checksums
760949948789493e63b09eca87eb0bd4284e4f02d5f4dafd6be5a1b8fc5c6016
BLAKE2b-256 checksum
How to use checksums
5809669ff6dcc90bba927c89d5fd29bcf03f0ee924dba1395531d02645026dce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 22, 2026.

Transparency log

Release files / tinysdk-0.9.8-py3-none-any.whl

Download URL tinysdk-0.9.8-py3-none-any.whl
Size 74.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4e6717c5b2ea0a143a4ad009911849534b1f0b46cb280b42b920a51c63dfc1c0
BLAKE2b-256 checksum
How to use checksums
8b514b4ff1ae03e8efa1217f2c60098eb0b0c1e479af1556ce527d2bb0917d17
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 22, 2026.

Transparency log

Release history Release notifications | RSS feed

0.11.0

2 release files

0.9.10

2 release files

0.9.9

2 release files

This release

0.9.8 This release

2 release files

0.9.6

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.0

2 release files

0.8.3

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.5

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.8

2 release files

0.5.7

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

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