{"id":35731205,"url":"https://github.com/eventdbx/eventdbx-python","last_synced_at":"2026-01-20T16:57:10.071Z","repository":{"id":323824955,"uuid":"1094865191","full_name":"eventdbx/eventdbx-python","owner":"eventdbx","description":"Python Client for EventDBX","archived":false,"fork":false,"pushed_at":"2025-11-25T09:02:36.000Z","size":49,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-28T15:47:31.439Z","etag":null,"topics":["capnp","client","event-sourcing","eventdbx"],"latest_commit_sha":null,"homepage":"https://docs.eventdbx.com/client-sdks/python","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eventdbx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-12T09:23:13.000Z","updated_at":"2025-11-25T09:04:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eventdbx/eventdbx-python","commit_stats":null,"previous_names":["eventdbx/eventdbx-python"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eventdbx/eventdbx-python","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eventdbx%2Feventdbx-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eventdbx%2Feventdbx-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eventdbx%2Feventdbx-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eventdbx%2Feventdbx-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eventdbx","download_url":"https://codeload.github.com/eventdbx/eventdbx-python/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eventdbx%2Feventdbx-python/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28225027,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2026-01-06T02:00:07.049Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["capnp","client","event-sourcing","eventdbx"],"created_at":"2026-01-06T11:03:33.815Z","updated_at":"2026-01-06T11:04:22.456Z","avatar_url":"https://github.com/eventdbx.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EventDBX Client\n\nOfficial (preview) Python client for the [EventDBX](https://eventdbx.com) control-plane TCP protocol. This SDK mirrors the ergonomics of the existing JavaScript (`eventdbxjs`) and Rust (`eventdbx-client`) libraries so that Python developers can integrate EventDBX with only a few lines of code.\n\n## Installation\n\n```bash\npython -m pip install --upgrade pip\npython -m pip install eventdbx\n```\n\n\u003e **System requirement**: `pycapnp` depends on the native Cap'n Proto toolkit. Install it first (e.g. `brew install capnp` on macOS, `apt-get install capnproto libcapnp-dev` on Debian/Ubuntu) before running `pip install`.\n\n## Quickstart\n\n```python\nimport json\n\nfrom eventdbx import EventDBXClient, RetryOptions\n\nwith EventDBXClient(\n    token=\"control_token\",\n    tenant_id=\"tenant-123\",\n    host=\"127.0.0.1\",\n    port=6363,\n    verbose=True,  # set False to mirror verbose_responses = false on the server\n    retry=RetryOptions(attempts=3, initial_delay_ms=100, max_delay_ms=1_000),\n) as client:\n    # Create a brand-new aggregate via the control plane\n    created = client.create(\n        aggregate_type=\"orders\",\n        aggregate_id=\"ord_123\",\n        event_type=\"created\",\n        payload_json=json.dumps({\"total\": 42.15}),\n    )\n\n    # Append follow-up events to the aggregate\n    updated = client.apply(\n        aggregate_type=\"orders\",\n        aggregate_id=\"ord_123\",\n        event_type=\"paid\",\n        payload_json=json.dumps({\"status\": \"paid\"}),\n    )\n\n    # List aggregates or fetch events for a specific aggregate\n    aggregates = client.list(take=50, sort=\"created_at:desc, aggregate_id:asc\")\n    events_page = client.events(aggregate_type=\"orders\", aggregate_id=\"ord_123\")\n\n    # Fetch full aggregate, run projections, or verify integrity\n    latest = client.get(aggregate_type=\"orders\", aggregate_id=\"ord_123\")\n    projection = client.select(\n        aggregate_type=\"orders\",\n        aggregate_id=\"ord_123\",\n        fields=[\"payload.total\", \"metadata.region\"],\n    )\n    merkle_root = client.verify(aggregate_type=\"orders\", aggregate_id=\"ord_123\")\n\n    # Apply JSON Patch documents to historical events\n    patched = client.patch(\n        aggregate_type=\"orders\",\n        aggregate_id=\"ord_123\",\n        event_type=\"created\",\n        patches=[{\"op\": \"replace\", \"path\": \"/total\", \"value\": 45.10}],\n    )\n\n    # Archive / restore lifecycle management\n    client.archive(aggregate_type=\"orders\", aggregate_id=\"ord_123\", note=\"customer request\")\n    client.restore(aggregate_type=\"orders\", aggregate_id=\"ord_123\")\n```\n\n`client.create(...)` bootstraps new aggregates, `client.list(...)` pages through aggregates, and `client.events(...)` lists events for an existing aggregate (optionally filtered via `filter_expr`; use `client.apply(...)` or the lower-level `send_event(...)` helper to append new events).\n\nUnder the hood the client establishes a persistent TCP session, performs a Noise XX handshake, and exchanges Cap'n Proto encoded control messages with the EventDBX control plane.\n\n\u003e **Note**: Noise transport security is enabled by default and should remain on outside of tightly controlled test scenarios.\n\n### Verbose responses\n\n`EventDBXClient` returns the stored JSON payloads for mutation commands by default (`apply`, `create`, `patch`, `archive`, and `restore`). To match deployments where the server is configured with `verbose_responses = false`, pass `verbose=False` to the client constructor. When verbose responses are disabled those methods resolve to a simple boolean acknowledgement instead of the serialized aggregate/event blob.\n\n```python\nclient = EventDBXClient(token=\"control_token\", tenant_id=\"tenant-123\", verbose=False)\nassert client.archive(aggregate_type=\"orders\", aggregate_id=\"ord_123\") is True\n```\n\n### Retry configuration\n\nYou can ask the client to automatically retry connection attempts and RPCs that fail due to transport/capnp errors. Retries are opt-in; by default each operation runs once and propagates the first error that surfaces. Pass a `retry` mapping (either snake_case or camelCase key names) or a `RetryOptions` instance to configure the behaviour:\n\n```python\nfrom eventdbx import EventDBXClient, RetryOptions\n\nclient = EventDBXClient(\n    token=\"control_token\",\n    tenant_id=\"tenant-123\",\n    retry=RetryOptions(\n        attempts=4,          # initial try + 3 retries\n        initial_delay_ms=100,\n        max_delay_ms=2_000,\n    ),\n)\n```\n\nOnly IO-level errors are retried—logical API errors are still raised immediately so you can handle them explicitly.\n\n## Control plane schemas \u0026 Noise helpers\n\nIf you need to work with the binary control plane, the package bundles the Cap'n Proto schemas and exposes a helper to load them on demand:\n\n```python\nfrom eventdbx.control_schema import build_control_hello\n\nhello = build_control_hello(protocol_version=1, token=\"api\", tenant_id=\"tenant\")\nserialized = hello.to_bytes()\n```\n\nFor encrypted transport the `eventdbx.noise.NoiseSession` class wraps the `noiseprotocol` implementation using the `Noise_NNpsk0_25519_ChaChaPoly_SHA256` pattern with a derived pre-shared key:\n\n```python\nfrom eventdbx.noise import NoiseSession, derive_psk\n\npsk = derive_psk(\"control-token\")\ninitiator = NoiseSession(is_initiator=True, psk=psk)\nresponder = NoiseSession(is_initiator=False, psk=psk)\n\nstep1 = initiator.write_message()  # e, psk\nresponder.read_message(step1)\nstep2 = responder.write_message()  # e, psk\ninitiator.read_message(step2)\n\nencrypted = initiator.encrypt(b\"payload\")\nplaintext = responder.decrypt(encrypted)\n```\n\n## Development\n\n```bash\npython3 -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -e .\"[dev]\"\npytest\n```\n\n## Release automation\n\nMerges to `main` automatically trigger `.github/workflows/publish.yml`, which installs system dependencies, runs the test suite, builds the wheel/sdist via `python -m build`, and then publishes the artifacts to PyPI with `pypa/gh-action-pypi-publish`. To enable publishing you must create a PyPI API token with project-scoped permissions and save it as the `PYPI_API_TOKEN` repository secret; the workflow will fail safely if the secret is missing.\n\n## Troubleshooting\n\n- `Getting requirements to build wheel ... error`: ensure Cap'n Proto is installed (`brew install capnp` or `apt-get install capnproto libcapnp-dev`) and retry `pip install pycapnp`. Installing the wheel ahead of time with `pip install pycapnp` inside your virtualenv often resolves lingering build issues.\n\n## Contributing\n\n1. Fork and clone the repository, then create a feature branch.\n2. Follow the development setup above (`pip install -e .[dev]`) and ensure formatting/linting still pass if you add new tools.\n3. Add or update tests alongside your changes (`pytest` should be green locally).\n4. Open a pull request with a clear description of the motivation and any follow-up work.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feventdbx%2Feventdbx-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feventdbx%2Feventdbx-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feventdbx%2Feventdbx-python/lists"}