Metadata-Version: 2.4
Name: pramiti-export-copilot
Version: 0.1.0
Summary: Standalone semantic model export and delivery — push your data model to dbt, Snowflake, Looker, Tableau, GitHub, GitLab, or dbt Cloud whenever it changes.
License: MIT
Project-URL: Homepage, https://getpramiti.com
Keywords: ai,semantic-model,export,dbt,snowflake,looker,tableau,pramiti
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Dynamic: license-file

# pramiti-export-copilot

Push your semantic data model to dbt, Snowflake, Databricks, Looker, Tableau, GitHub, GitLab, or dbt Cloud whenever it changes. Zero dependencies -- inject any data backend and delivery target via Protocol-based interfaces.

## Install

```bash
pip install pramiti-export-copilot
```

## Quick Start

```python
from pramiti_export_copilot import ExportCopilot, DeliveryConfig
from pramiti_export_copilot.backends import InMemoryBackend
from pramiti_export_copilot.delivery_targets import WebhookTarget

backend = InMemoryBackend(b"dbt schema content")
target = WebhookTarget("https://hooks.mycompany.com/epistom")
copilot = ExportCopilot(backend)
result = copilot.deliver("workspace-1", DeliveryConfig(format="dbt", target=target))

if result.success:
    print(f"Delivered {result.bytes_delivered} bytes, hash={result.export_hash[:8]}...")
elif result.error:
    print(f"Failed: {result.error}")
```

## Supported Formats

| Format | Backend method |
|--------|----------------|
| dbt | `get_dbt_yaml(workspace_id)` |
| Snowflake | `get_snowflake_sql(workspace_id)` |
| Databricks | `get_databricks_json(workspace_id)` |
| Looker | `get_lookml(workspace_id)` |
| Tableau | `get_tableau_tds(workspace_id, connection_info)` |

## Delivery Targets

All targets use `urllib.request` (stdlib) -- no external HTTP dependencies. All support self-hosted/enterprise instances via `endpoint_url`.

| Target | Description |
|--------|-------------|
| `WebhookTarget` | POST to any HTTP endpoint with optional Bearer auth. |
| `GitHubTarget` | Commit via GitHub Contents API. Supports GHE via custom `endpoint_url`. |
| `GitLabTarget` | Commit via GitLab Repository Files API. Supports self-hosted instances. |
| `DbtCloudTarget` | Push via dbt Cloud API. Supports enterprise instances. |

## Hash-Based Skip

Pass `last_hash` to skip delivery when content hasn't changed:

```python
result = copilot.deliver("ws-1", config, last_hash="abc123...")
if result.skipped:
    print(f"Skipped: {result.reason}")  # "no_change"
```

## API

| Export | Description |
|--------|-------------|
| `ExportCopilot` | Core delivery engine. Inject any `IModelDataBackend`. |
| `DeliveryConfig` | Configuration dataclass: `format`, `target`, optional `connection_info` (for Tableau). |
| `DeliveryResult` | Result dataclass: `success`, `skipped`, `reason`, `export_hash`, `bytes_delivered`, `error`. |
| `IModelDataBackend` | Protocol for model data retrieval backends. |
| `InMemoryBackend` | In-memory backend for testing (returns fixed bytes for all formats). |
| `IDeliveryTarget` | Protocol for delivery targets. Implement `deliver(content, metadata) -> int`. |
| `CopilotError` | Base exception for all export copilot errors. |
| `DeliveryError` | Raised when a delivery target rejects the payload. |
| `BackendError` | Raised when the backend cannot produce export bytes. |

## Custom Backend

Implement `IModelDataBackend` (structural subtyping -- no inheritance required):

```python
class MyBackend:
    def get_dbt_yaml(self, workspace_id: str) -> bytes: ...
    def get_snowflake_sql(self, workspace_id: str) -> bytes: ...
    def get_databricks_json(self, workspace_id: str) -> bytes: ...
    def get_lookml(self, workspace_id: str) -> bytes: ...
    def get_tableau_tds(self, workspace_id: str, connection_info: dict) -> bytes: ...
```

## License

MIT -- Pramiti Labs
