This project has been archived by its maintainers, and is no longer receiving any updates.
planframe
Core package for PlanFrame (typed planning layer). Import as planframe.
Documentation (ReadTheDocs):
- Core (adapter authors):
https://planframe.readthedocs.io/en/latest/planframe/ - Migrating since v1.1.0 (v1.2.0+ through v1.3.0):
https://planframe.readthedocs.io/en/latest/planframe/guides/migrating-since-1-1/ - Design docs:
https://planframe.readthedocs.io/en/latest/planframe/design/ - Light API reference:
https://planframe.readthedocs.io/en/latest/planframe/reference/api/ - Streaming rows:
https://planframe.readthedocs.io/en/latest/planframe/guides/streaming-rows/ - Adapter conformance kit (third-party
BaseAdapterCI):https://planframe.readthedocs.io/en/latest/planframe/guides/adapter-conformance/ - Optional API skins: PySpark-like (
planframe.spark), pandas-like (planframe.pandas)
Install
planframe is backend-agnostic; you typically install an adapter package like planframe-polars or planframe-pandas.
If you only want the core planning layer:
pip install planframe
What you get
planframe.Frame: immutable, schema-aware transformation plan (always lazy)planframe.expr: typed expression IR (col,lit, arithmetic/compare/boolean ops,coalesce,if_else, etc.); operator overloads onExpr(==,!=,&,|,~, …) build IR nodes—see Typing design. Aggregation wrappers forgroup_by(...).agg(...):agg_sum,agg_mean,agg_min,agg_max,agg_count,agg_n_unique(these buildAggExprnodes)planframe.groupby.GroupedFrame: produced byFrame.group_by;group_byaccepts column names and/or expressions (expression keys show up as__pf_g0,__pf_g1, … in the result schema).aggaccepts(op, column)tuples and/orAggExprvalues—not arbitrary bare expressionsplanframe.schema: schema reflection (dataclass + Pydantic) and materializationplanframe.spark: optional PySpark-likeSparkFrame/Column/functions(importfrom planframe.spark import SparkFrame, orfrom planframe import spark)planframe.pandas: optional pandas-likePandasLikeFrame/Series(importfrom planframe.pandas import PandasLikeFrame, orfrom planframe import pandas); mix with anyFramesubclass for familiar naming without new backend dependenciesplanframe.adapter_conformance: minimalrun_minimal_adapter_conformancehelper for adapter authors; optional extraplanframe[adapter-dev]includes pytest for local runs
Common transforms
Some commonly used Frame transforms:
with_row_index(name="row_nr", offset=0): add a monotonically increasing row number column.clip(lower=..., upper=..., subset=...): clamp numeric columns (ifsubset=None, clamps all numeric schema fields).drop_nulls(subset=..., how="any"|"all", threshold=...): drop rows by null pattern over a column subset.select_schema(selector, strict=True): schema-only selectors (backend-independent);ColumnSelectoris runtime-checkable.cast_many(mapping, strict=True)/cast_subset(*columns, dtype, strict=True): multi-column cast helpers.fill_null_subset(value|strategy, *columns)/fill_null_many(mapping, strict=True): multi-column fill-null helpers.rename_upper/lower/title/strip(...): schema-driven rename helpers.pivot_longer(...)/pivot_wider(...): reshape convenience wrappers aroundunpivot/pivot.
Materialization accepts optional ExecutionOptions on collect / to_dicts / to_dict (and async counterparts). JoinOptions on Frame.join carries execution hints (including engine_streaming where the backend supports it).
planframe.materialize: materialize_columns / materialize_into (and amaterialize_*) forward the same options as Frame.to_dict / ato_dict—useful for adapter and host-library boundaries (Creating an adapter — columnar helpers).
execute_plan / execute_plan_async: the supported plan interpreters; execute_plan_async runs the sync interpreter in asyncio.to_thread so you can await without blocking the event loop (Core layout).
Note on backends
planframe is backend-agnostic. It does not execute anything until collect() (even for eager backends). To execute plans you need an adapter package (e.g. planframe-polars).
For async stacks, use Frame.acollect() / ato_dicts() / ato_dict() or the discoverable aliases collect_async, to_dicts_async, to_dict_async (same behavior). These await adapter hooks (BaseAdapter.acollect and friends); defaults run sync methods in a thread pool. See Backend adapter design and Creating an adapter — Async execution.
Typing
PlanFrame includes py.typed plus generated stubs (notably planframe/frame/__init__.pyi) to improve static typing in editors and Pyright.
If you modify the Frame API, regenerate stubs from the repo root:
python scripts/generate_typing_stubs.py
python scripts/generate_typing_stubs.py --check
Metadata
Release files for planframe 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| planframe-1.3.0.tar.gz | 61.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| planframe-1.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 143.9 kB
Release files / planframe-1.3.0.tar.gz
| Download URL | planframe-1.3.0.tar.gz |
|---|---|
| Size | 61.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
40f4745f049e2b7a17c08bf37e7fec3db8070be533b1be103284f4543ba0d847
|
|
BLAKE2b-256 checksum How to use checksums |
cea05f65e7cca4322972e3fc2890ef5c3a07b98b08daefec5e6fc629ca6d4946
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / planframe-1.3.0-py3-none-any.whl
| Download URL | planframe-1.3.0-py3-none-any.whl |
|---|---|
| Size | 82.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6e9a1bc0fa3c4df108ff47d1d309690b5a704febaf9375183cbcaf9d306dab68
|
|
BLAKE2b-256 checksum How to use checksums |
7691fa9560d0c4f54dea1dea3b46754790e4cafec1148b47bf4293992a21f446
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|