Metadata-Version: 2.4
Name: framespec
Version: 0.0.4
Summary: Declarative DataFrame specifications for PySpark.
Author: RyPy
License-Expression: MIT
Requires-Dist: pyspark>=4.0.0
Requires-Dist: packaging>=24.0
Requires-Dist: typing-extensions>=4.10.0
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# framespec

Declarative DataFrame contracts for PySpark ETL.

## Installation

```bash
pip install framespec
```

Requires Python 3.12+ and PySpark ≥ 4.0.

## Quickstart

```python
from framespec import FrameSpec, String, framespec


@framespec
class Customer:
    spec = FrameSpec()
    status = String(nullable=False, allowed_values=("active", "cancelled"))
    email = String(nullable=True)


Customer.spec.schema          # Spark StructType
Customer.status               # ColRef — use like a column name
Customer.status.spec.rules    # builtin rules from the constraints above
```

> **`….spec` = full scope of that subtree** — the frame contract on `Customer.spec`, that column only on `Customer.status.spec`.

## Common use cases

### Create a DataFrame from the schema

```python
df = spark.createDataFrame(
    [("active", "a@example.com"), ("cancelled", None)],
    schema=Customer.spec.schema,
)
```

### Select and filter with column handles

```python
df.select(Customer.status, Customer.email)
df.filter(Customer.status.col == "active")
```

### Keep only compliant rows

```python
df.filter(Customer.spec.compliant)
```

### Report on a DataFrame

```python
report = Customer.spec.report(df)
report.ok
report.false_rules
report.row_count

Customer.spec.require(df)  # raises if any rule has false rows
```

### Monitor during a write

```python
monitor = Customer.spec.monitor(timeout=30.0)
df = df.transform(monitor)
df.write.saveAsTable("customers")
report = monitor.report
```

### Add a custom rule

```python
from framespec import Rule

Customer.spec.with_rules(
    Rule(
        name="email_when_active",
        expr=(Customer.status.col != "active") | Customer.email.col.isNotNull(),
        sql="status != 'active' OR email IS NOT NULL",
    ),
)
```

## Docs

Detailed documentation — coming soon.

## License

MIT
