Metadata-Version: 2.4
Name: supercargo
Version: 0.7.0
Summary: Native Python annotations for Supercargo type-safe metadata
Author: Supercargo
Author-email: support@supercargo.dev
Requires-Python: >=3.9,<4.0
Classifier: Programming Language :: Python :: 3
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: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Provides-Extra: dlt
Requires-Dist: dlt (>=0.4.0) ; extra == "dlt"
Requires-Dist: google-auth (>=2.0.0)
Requires-Dist: grpcio (>=1.50.0)
Requires-Dist: protobuf (>=4.21.0)
Requires-Dist: pydantic (>=2.0.0)
Project-URL: Homepage, https://supercargo.dev
Description-Content-Type: text/markdown

# Supercargo Python SDK

The official Python SDK for [Supercargo](https://supercargo.dev), providing native decorators and `typing.Annotated` metadata bindings for Pydantic and standard Python dataclasses to define type-safe Data Contracts, governance metadata, and schema constraints.

## Installation

```bash
pip install supercargo
```

---

## Defining Data Contracts

Decorate your Pydantic models (or dataclasses) with `@supercargo.contract` and attach metadata to fields using `typing.Annotated` with `supercargo.field(...)`.

### Example

```python
from typing import Annotated
from pydantic import BaseModel, Field
import supercargo
from supercargo import ValidationPolicy

@supercargo.contract(
    urn="urn:supercargo:contract:user_signup:v1",
    version="1.0.0",
    owner_team="identity-team",
    data_asset="users_v1",
    validation_policy=ValidationPolicy.STRICT,
)
class UserSignup(BaseModel):
    # Federated entity anchor with UUID semantic hint and PII metadata
    user_id: Annotated[str, supercargo.field(
        as_type="UUID",
        pii=True,
        context_id="user_salt",
        identity_domain="urn:supercargo:identity_domain:user",
        rank=1,
        entity_ref="urn:supercargo:entity:identity-team:user",
    )] = Field(alias="userId")

    # String with regex constraint and min length (using Pydantic Field or supercargo.field)
    email: Annotated[str, Field(pattern=r"^\S+@\S+$", min_length=1), supercargo.field(pii=True)]

    # Numerical constraint
    age: Annotated[int, Field(gt=18, lt=120)]

    # Standard boolean field
    is_active: bool = Field(alias="isActive")
```

---

## Decorator & Field Options Reference

### `@supercargo.contract(...)`

| Option | Type | Description |
| :--- | :--- | :--- |
| `urn` | `str` | Canonical URN for the contract. |
| `version` | `str` | Semantic version string. |
| `owner_team` / `ownerTeam` | `str` | Owning team name. |
| `data_asset` / `dataAsset` | `str` | Associated data asset or topic name. |
| `validation_policy` | `ValidationPolicy` \| `str` | Validation policy enum (`STRICT`, `LENIENT`, `MUTATE`). |

### `supercargo.field(...)`

| Option | Type | Description |
| :--- | :--- | :--- |
| `as_type` | `str` | Semantic data type hint (`UUID`, `TIMESTAMP`, `EMAIL`, etc.). |
| `pii` | `bool` \| `str` | Marks field as containing PII. |
| `context_id` | `str` | Salt / hashing context for pseudonymization. |
| `identity_domain` | `str` | Identity Domain URN for cross-system joining. |
| `rank` | `int` | Identity domain priority rank (1 = Primary). |
| `entity_ref` / `entity` | `str` | Entity reference URN for federated identity anchoring. |
| `not_empty` | `bool` | Enforces non-empty constraint. |
| `min_length` | `int` | Minimum string length. |
| `max_length` | `int` | Maximum string length. |
| `pattern` | `str` | Regular expression pattern. |
| `greater_than` / `gt` | `int` \| `float` | Numerical lower bound (exclusive). |
| `greater_than_or_equal` / `ge` | `int` \| `float` | Numerical lower bound (inclusive). |
| `less_than` / `lt` | `int` \| `float` | Numerical upper bound (exclusive). |
| `less_than_or_equal` / `le` | `int` \| `float` | Numerical upper bound (inclusive). |

---

## Testing & Validation Harness

Use `assert_validates` in your pytest test suite to verify constraint compliance:

```python
from supercargo import assert_validates

def test_user_signup_validation():
    # Assert validation failure when age is below minimum
    assert_validates(
        factory_callable=lambda: UserSignup(
            userId="550e8400-e29b-41d4-a716-446655440000",
            email="alice@example.com",
            age=15,
            isActive=True,
        ),
        expected_errors=["greaterThan", "gt"],
    )
```

---

## dlt Integration (`dlt-supercargo`)

The Supercargo Python SDK includes a first-class adapter for **dlt** (data load tool) to enforce Data Contracts and execute in-stream batch PII pseudonymization via the Vault service.

### Installation

```bash
pip install "supercargo[dlt]"
```

### Usage Example

```python
import dlt
from dlt_supercargo import SupercargoShield

# 1. Initialize shield (fetches contract and precomputes Pydantic model + PII mappings)
shield = SupercargoShield(
    contract_urn="urn:sc:contract:hubspot_contacts:v1",
    hub_url="hub.internal:50051",
    vault_url="vault.internal:50051",
)
Model = shield.pydantic_model

# 2. Declare dlt resource with Pydantic model and frozen columns
@dlt.resource(
    name="contacts",
    write_disposition="append",
    columns=Model,
    schema_contract={"tables": "evolve", "columns": "freeze", "data_type": "freeze"},
)
def fetch_hubspot_contacts():
    for page in hubspot_api_client.paginate():
        yield page

# 3. Add buffered batch pseudonymization transformer
fetch_hubspot_contacts.add_map(shield.transform_batch)

# 4. Run pipeline
pipeline = dlt.pipeline(pipeline_name="hubspot_sync", destination="duckdb", dataset_name="raw_crm")
pipeline.run(fetch_hubspot_contacts)
```


