This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.1.5 instead.
narwhals-datafusion
Apache DataFusion backend for
Narwhals, implemented as an
out-of-tree plugin via the narwhals.plugins entry-point system.
Usage
import narwhals as nw
import pyarrow as pa
from datafusion import SessionContext
ctx = SessionContext()
df = ctx.from_arrow(pa.table({"a": [1, 2, 3], "b": ["x", "y", "x"]}))
lf = nw.from_native(df) # -> nw.LazyFrame, dispatched to this plugin
result = (
lf.group_by("b")
.agg(nw.col("a").sum())
.sort("b")
.collect(backend="pyarrow")
)
Everything stays lazy until .collect(): narwhals expressions are translated to
datafusion.Expr, frame verbs to datafusion.DataFrame methods, and the plan
executes in DataFusion's Rust engine. Dtypes are pyarrow end-to-end.
Architecture
The backend sits on narwhals' shared SQL layer (narwhals._sql), the same
abstraction DuckDB, Ibis, and Spark use. It targets narwhals==2.25 internals
(narwhals._sql, narwhals._compliant), vendored as the narwhals/ git
submodule pinned to that release. The plugin provides:
| Module | Class |
|---|---|
dataframe.py |
DataFusionLazyFrame — frame verbs over datafusion.DataFrame |
expr.py |
DataFusionExpr — the six SQLExpr hooks + backend specifics |
namespace.py |
DataFusionNamespace — the four SQLNamespace primitives, IO, horizontal fns |
group_by.py, selectors.py, expr_str/dt/list/struct.py |
supporting surface |
utils.py |
function-name remapping, window/sort builders, dtype bridge (delegates to narwhals._arrow) |
mode, skew, kurtosis via datafusion-extra-functions
DataFusion core deliberately keeps its function library lean, so aggregates
like mode/skewness/kurtosis live in the contrib
datafusion-extra-functions
crate (Rust-only, no wheel on PyPI). The
datafusion-extra-functions-ffi
package — a required dependency, installed as a prebuilt wheel — exposes its
aggregate UDFs to datafusion-python via the __datafusion_aggregate_udf__
PyCapsule protocol; they back Expr.mode, Expr.skew, and Expr.kurtosis.
Its FFI ABI is tied to the datafusion major it was compiled against
(currently 54), which the wheel's own dependency pin enforces.
API coverage
Status of the narwhals public API on this backend (narwhals==2.25,
datafusion==54). ⚠️ entries work with the caveat in parentheses; details in
Known limitations.
| Namespace | ✅ Supported | ⚠️ Partial | ❌ Not supported |
|---|---|---|---|
Expr |
abs alias all any any_value ceil clip cos count cum_count cum_max cum_min cum_sum diff exp fill_nan first floor is_between is_close is_duplicated is_finite is_first_distinct is_in is_last_distinct is_nan is_null is_unique kurtosis last len log max mean median min null_count over pipe rank rolling_mean rolling_std rolling_sum rolling_var round shift sin skew sqrt std sum var |
cast (no Enum) · fill_null (no strategy + limit) · mode (keep="any" only) · n_unique (not over windows) · replace_strict (explicit default required) |
cum_prod quantile |
Expr.str |
contains ends_with head len_chars pad_end pad_start replace_all slice split starts_with strip_chars strip_chars_end strip_chars_start tail to_lowercase to_uppercase zfill |
to_date/to_datetime (explicit format required) · to_time ("HH:MM:SS"-style only) · to_titlecase (no word breaks on digits) |
replace (use replace_all) |
Expr.dt |
convert_time_zone date day hour microsecond millisecond minute month nanosecond ordinal_day second to_string truncate weekday year |
replace_time_zone (None/"UTC" only) |
offset_by timestamp total_microseconds total_milliseconds total_minutes total_nanoseconds total_seconds |
Expr.list |
contains get len max min sort |
unique (maintain_order=False only) |
mean median sum |
Expr.struct |
field |
||
LazyFrame |
collect collect_schema drop drop_nulls filter group_by head join rename select sort top_k unique unpivot with_columns with_row_index |
explode (single column) · sink_parquet (file path only) |
join_asof |
Not listed: methods narwhals itself doesn't support on any lazy/SQL backend
(Expr.filter, Expr.drop_nulls, Expr.unique, Expr.map_batches,
Expr.ewm_mean, LazyFrame.tail, LazyFrame.gather_every).
Known limitations (as of datafusion 54)
join_asof, exactquantile,cum_prod,list.sum/mean/median,dt.total_*,dt.offset_by,dt.timestamp,str.replace,Enumcasts — no engine support; raiseNotImplementedError.n_unique().over(...)raises: DataFusion silently ignoresDISTINCTinside window aggregates, which would return wrong results. (The same engine quirk dropsORDER BY/IGNORE NULLSdeclared inside window aggregates — this backend moves those modifiers onto the window itself.)fill_null(strategy=..., limit=n)raises: bounded window frames withfirst_value/last_valueneedretract_batch, unimplemented engine-side.replace_time_zonesupportsNone(strip) and"UTC"only; useconvert_time_zonefor instant-preserving conversions.str.to_datetime/to_daterequire an explicitformat;str.to_timeparses"HH:MM:SS"-style strings via Arrow's cast, ignoring custom formats.replace_strictrequires an explicitdefault.str.to_titlecaseusesinitcap, which doesn't break words on digits.- No row-order guarantees except after
sort(standard for SQL engines); backwardfill_nullmay reorder rows.
Development
git submodule update --init # narwhals, pinned to the targeted release
uv sync --group tests
Running narwhals' own test suite against this backend
The narwhals repo is vendored as a git submodule pinned to the targeted release:
git submodule update --init
uv run --group tests python run_tests.py # known failures deselected
For the full, unfiltered run:
uv run --group tests pytest narwhals/tests -c narwhals/pyproject.toml \
-p narwhals_datafusion.testing -p env --use-external-constructor
Regenerate the deselect list after fixing tests or bumping the submodule with
uv run --group tests python update_run_tests.py.
Release files for narwhals-datafusion 0.1.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 | |
|---|---|---|---|
| narwhals_datafusion-0.1.0.tar.gz | 21.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| narwhals_datafusion-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 48.9 kB
Release files / narwhals_datafusion-0.1.0.tar.gz
| Download URL | narwhals_datafusion-0.1.0.tar.gz |
|---|---|
| Size | 21.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9884bb9a5408ed0b29cede4096c5cea8e1b7ae8a168954a80fc8e57667a90462
|
|
BLAKE2b-256 checksum How to use checksums |
b0958c30b5adef88dc90851a73ed44481af6918e506fb216321c386773216a02
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency logRelease files / narwhals_datafusion-0.1.0-py3-none-any.whl
| Download URL | narwhals_datafusion-0.1.0-py3-none-any.whl |
|---|---|
| Size | 27.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2cd11c0c46c4e23c59b0fd6032552df18e1c551130dbbaca88edf2054ed6fb5b
|
|
BLAKE2b-256 checksum How to use checksums |
d638d31fe8e52c5d99e6eada4cf4e4e2fa8516a505d96f58f77dd226fb463a9a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 2, 2026.
Transparency log