Metadata-Version: 2.4
Name: masterly
Version: 0.1.1
Summary: Python client for Masterly — extract governed data products and ingest records from your lakehouse
Project-URL: Homepage, https://masterlydata.com
Project-URL: Documentation, https://masterlydata.com/docs/reference/python-sdk/
Project-URL: Repository, https://github.com/masterly-data/masterly-python-sdk
Project-URL: Changelog, https://github.com/masterly-data/masterly-python-sdk/releases
License: Apache-2.0
License-File: LICENSE
Keywords: data products,databricks,fabric,lakehouse,master data,mdm,snowflake
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
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: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Provides-Extra: pandas
Requires-Dist: pandas>=2.0; extra == 'pandas'
Description-Content-Type: text/markdown

# masterly — Python client

Extract governed data products and ingest records from Python — notebooks on Databricks,
Microsoft Fabric, or anywhere else your pipelines run.

```python
from masterly import Client

client = Client(
    base_url="https://app.example.com",       # your Masterly install
    token="<session or service-account token>",
    environment="env_prod_eu",
)

# Extract: page through a data product (cursor-managed for you)
for row in client.products.read("Customer 360"):
    ...

# Or straight into a DataFrame
df = client.products.read("Customer 360").to_pandas()

# Follow the change feed with a resumable cursor
feed = client.products.changes("Customer 360", cursor=saved_cursor)
for change in feed:
    ...
save(feed.cursor)  # persist for the next run

# Ingest: deliver records to a source (chunked automatically)
report = client.sources.ingest("crm", records)
print(report.records, "records in", report.batches, "batches")
```

## Tokens: two personas

- **Consumer** (extract in a Databricks/Fabric job): use a **service-account token**
  (minted under Users → Service accounts). It pins its Environment and consumes published
  products — reference them **by product id** (`dp_…`), since listing products needs a
  session. Access policies (row rules, masks) apply per consumer automatically.
- **Integrator** (ingest + golden reads): use a **session token**. Sources and products can
  be referenced by name.

The client is a thin, typed wrapper over the stable `/v1` REST contract — the same API
every other channel uses. Errors raise `masterly.ApiError` carrying the server's error
code and message. Re-delivery is idempotent: records upsert by their source key, so
running the same notebook twice never duplicates data.

`pandas` is an optional dependency: `pip install masterly[pandas]`.

## License

Apache-2.0 — see [LICENSE](LICENSE).
