# Polars changelog > A DataFrame library built on Apache Arrow with a lazy query engine. - Vendor: Polars - Category: Frameworks & Libraries - Official site: https://pola.rs - Tracked by: What's New (https://whatsnew.fyi/product/polars) - Harvested from: GitHub (pola-rs/polars) - Entries below: 25 (newest first) What's New is an index, not a publisher: every entry below links to the vendor's own release notes, which are the authoritative source. Entries are labelled where they are hand-curated sample data, pre-releases, or drawn from a secondary source such as a developer blog. Reuse: the summaries, labels and curation here are © What's New. Quote freely with attribution and a link back; wholesale republication of the corpus is not permitted — terms: https://whatsnew.fyi/terms. The vendors' own release notes remain their publishers'. ## Releases ### 1.43.2 — Python Polars 1.43.2 - Date: 2026-08-01 - Version: 1.43.2 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.43.2 - Permalink: https://whatsnew.fyi/product/polars/releases/1.43.2 - **deprecated** — Deprecate casts from Categorical to integer dtypes - **deprecated** — Deprecate not setting the plan_stage argument in show_graph() - **changed** — Pushdown len() to concat/union inputs - **security** — Issue FutureWarning on using from_arrow of ArrowStreamExportable - **added** — Add infer_schema_files parameter to scan_csv - **fixed** — Properly propagate enum metadata for iceberg column mapping - **fixed** — Correctly write parquet field IDs for enums and categoricals - **fixed** — Fix arrow C interop binview offset - **fixed** — Fix duplicate hive values in hive pre-partition rewrite - **fixed** — Double-counted offset for Arrow export of sliced Series(Array) - **fixed** — Struct/List/Array equality handling in sort and join - **fixed** — More careful slice pushdown into joins - **fixed** — Preserve ordering in sliced unions - **fixed** — Drop input sortedness when casting to a string - **fixed** — Clear sortedness flags in StringChunked substring kernels - **fixed** — Bad mask handling when reading optional parquet column - **fixed** — Any operation on Unknown(Int) and Unknown(Float) should result in Unknown(Float) - **fixed** — Flip nulls_last after Expr.reverse() - **fixed** — Fix high blocking thread use in sink_parquet with async local path - **fixed** — Serialize LazyFrames backed by bytes ##### ⚠️ Deprecations - Deprecate casts from `Categorical` to integer dtypes (#28525) - Deprecate not setting the `plan_stage` argument in `show_graph()` (#28391) ##### 🚀 Performance improvements - Pushdown `len()` to concat/union inputs (#28570) ##### ✨ Enhancements - Issue FutureWarning on using `from_arrow` of ArrowStreamExportable (#28442) - Add `infer_schema_files` parameter to `scan_csv` (#28440) ##### 🐞 Bug fixes - Properly propagate enum metadata for iceberg column mapping (#28580) - Correctly write parquet field IDs for enums and categoricals (#28581) - Fix arrow C interop binview offset (#28623) - Fix duplicate hive values in hive pre-partition rewrite (#28621) - Double-counted offset for Arrow export of sliced `Series(Array)` (#28602) - Struct/List/Array equality handling in sort and join (#28601) - More careful slice pushdown into joins (#28578) - Preserve ordering in sliced unions (#28576) - Drop input sortedness when casting to a string (#28574) - Clear sortedness flags in `StringChunked` substring kernels (#28573) - Bad mask handling when reading optional parquet column (#28547) - Any operation on `Unknown(Int)` and `Unknown(Float)` should result in `Unknown(Float)` (#28545) - Flip `nulls_last` after `Expr.reverse()` (#28572) - Fix high blocking thread use in sink\_parquet with async local path (#28543) - Serialize LazyFrames backed by bytes (#28568) - Release GIL in `SQLContext.execute()` (#28549) - Propagate `nulls_last` in `function_expr_sortedness` (#28544) - Incorrect slicing when a join requires sorting (#28541) ##### 🛠️ Other improvements - Fix duckdb delta extension install collision (#28607) Thank you to all our contributors for making this release possible! @BitWeaverDev, @Matt711, @Samoilov2004, @borchero, @dancsi, @dsprenkels, @kdn36, @masumi-ryugo, @nameexhaustion and @ritchie46 ### 1.43.1 — Python Polars 1.43.1 - Date: 2026-07-27 - Version: 1.43.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.43.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.43.1 - **changed** — Optimize not(bool_f) to not_bool_f - **added** — Allow callback sinks on cloud - **fixed** — Fix panic on self join of scan_delta / scan_iceberg - **fixed** — Fix UB on first/last_non_null with empty chunk - **fixed** — Do not CSE non-column height expr on streaming engine - **fixed** — Propagate adjusted sortedness through Gather - **fixed** — Deduplicate the expression equality checks - **fixed** — Address 3VL issue with SQL NOT IN interaction with NULL values and joins - **fixed** — Use total comparison in Expr literal values - **fixed** — Ensure SQL SUM and CORR aggregates return NULL for all-null inputs, add TOTAL - **fixed** — Share null_count_dtype helper between Delta and Iceberg, fixing SchemaError - **fixed** — Remove non-output columns from the equi-join and semi/anti-join operators - **fixed** — Fix dropped slice on multiple unions - **fixed** — Fix in-memory engine incorrect slice on maintain order join - **fixed** — Check join schema by position - **fixed** — Block predicate pushdown past overwritten window keys - **added** — Make hive_part extraction a function and public ##### 🚀 Performance improvements - Optimize not(bool\_f) to not\_bool\_f (#28474) ##### ✨ Enhancements - Allow callback sinks on cloud (#28458) ##### 🐞 Bug fixes - Fix panic on self join of scan\_delta / scan\_iceberg (#28468) - Fix UB on first/last\_non\_null with empty chunk (#28495) - Do not CSE non-column height expr on streaming engine (#28480) - Propagate adjusted sortedness through Gather (#28493) - Deduplicate the expression equality checks (#28483) - Address 3VL issue with SQL `NOT IN` interaction with `NULL` values and joins (#28484) - Use total comparison in Expr literal values (#28482) - Ensure SQL `SUM` and `CORR` aggregates return NULL for all-null inputs, add `TOTAL` (#28475) - Share `null_count_dtype` helper between Delta and Iceberg, fixing `SchemaError` (#28479) - Remove non-output columns from the equi-join and semi/anti-join operators (#28446) - Fix dropped slice on multiple unions (#28477) - Fix in-memory engine incorrect slice on maintain order join (#28478) - Check join schema by position (#28455) - Block predicate pushdown past overwritten window keys (#28429) ##### 📖 Documentation - Update and restructure README (#28490) - Minor fixes to Spark migration guide (#27730) - Relocate Polars Cloud \& On-Prem User Guide (#28462) - Add notes on k8s operator (#28445) ##### 🛠️ Other improvements - Make hive\_part extraction a function and public (#28507) - Deduplicate the expression equality checks (#28483) - Bump `ruff` and `mypy` package versions (#28456) - Fix flaky test (#28454) Thank you to all our contributors for making this release possible! @AnirudhRahul, @EndPositive, @Jesse-Bakker, @alexander-beedie, @carnarez, @dancsi, @mdroogh, @mroeschke, @nameexhaustion, @nchammas, @orlp, @r-brink and @ritchie46 ### 1.43.0 — Python Polars 1.43.0 - Date: 2026-07-21 - Version: 1.43.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.43.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.43.0 - **deprecated** — Deprecate casting numeric types to categoricals - **deprecated** — Deprecate cat.get_categories() and cat.to_local() - **deprecated** — Deprecate LazyFrame.profile() - **deprecated** — Deprecate casts from non-nested dtypes into Lists - **deprecated** — Deprecate bitwise ops between integers and booleans - **deprecated** — Deprecate list/arr.to_struct() calls that don't pass field names - **changed** — Rename missing_utf8_is_empty_string to empty_string_is_null - **changed** — Split multiplexers that directly scan from in-memory DataFrame - **changed** — Make DNS cache global - **changed** — Pre-partition on left, right and semi joins on hive partitioned data - **changed** — Rewrite inner joins on hive partitioned data to a union of partitions filtered joins - **added** — Add ewm_sum and ewm_sum_by - **added** — Add scan_arrow_c_stream - **added** — Support Iceberg field initial-default in native scan_iceberg - **added** — Add Series.degrees/radians and clarify trig functions use radians - **added** — Add list expression which consistently packs elements together into new List type - **added** — Add Expr.cat.to and Expr.cat.physical - **added** — Add POLARS_OOC_DISK_BUDGET_MB - **added** — Add build side preference parameter for join - **fixed** — Avoid panic when union slice skips all rows - **fixed** — Solve panic in dt.replace when there were multiple chunks ##### ⚠️ Deprecations - Deprecate casting numeric types to categoricals (#28349) - Deprecate `cat.get_categories()` and `cat.to_local()` (#28299) - Deprecate `LazyFrame.profile()` (#28275) - Deprecate casts from non-nested dtypes into Lists (#28193) - Deprecate bitwise ops between integers and booleans (#28186) - Deprecate `list/arr.to_struct()` calls that don't pass field names (#28243) - Rename `missing_utf8_is_empty_string` to `empty_string_is_null` (#28173) ##### 🚀 Performance improvements - Split multiplexers that directly scan from in-memory DataFrame (#28376) - Make DNS cache global (#28352) - Do not remove cache if predicates not pushed to all inputs (#28341) - Environment variable for logging slow DNS lookup (#28211) - Pre-partition on left, right and semi joins on hive partitioned data (#28374) - Rewrite inner joins on hive partitioned data to a union of partitions filtered joins (#28327) - Tighten redundant comparisons and propagate filter constraints (#27999) - Canonicalize predicates (#28212) - Remove excess memory copy in streaming IPC sink (#28141) - Parallelize scan\_iceberg resolve (#28168) - Chunk-aware morsel splitting on single-file IO sink (#27950) - Don't allocate for `full_null()` with small lengths (#28181) - Use monotonic deque for rolling min\_by/max\_by (O(n)) (#27436) ##### ✨ Enhancements - Pre-partition group-by on hive keys (#28444) - Add ewm\_sum and ewm\_sum\_by #28151 (#28215) - Serve stale records from object\_store DNS cache (#28256) - Make partition\_hive an opt flag (#28345) - Add `scan_arrow_c_stream` (#28340) - When displaying IRExprs, only add parentheses when needed for disambiguation (#28319) - Support Iceberg field `initial-default` in native `scan_iceberg` (#28324) - Show only differing dtypes in `assert_frame_equal` error (#27816) - Expose ewm and rolling \*\_by expressions in Python visitor (#28286) - More accurate rolling moments (#28309) - Remove hard block on native scan for Iceberg V3 tables (#28277) - Add Series.degrees/radians and clarify trig functions use radians (#22961) - Merge sorted with multikey (#28067) - Add `list` expression which consistently packs elements together into new List type (#27990) - Add `read_database` Arrow fast-path for "python-oracledb" (#28230) - Optimize joins with redundant equi-join keys (#28017) - Implement missing datetime options for `CastColumnsPolicy` (#28084) - Add Expr.cat.to and Expr.cat.physical (#28096) - Add POLARS\_OOC\_DISK\_BUDGET\_MB (#28045) - Add build side preference parameter for join (#28154) ##### 🐞 Bug fixes - Avoid panic when union slice skips all rows (#28420) - Solve panic in `dt.replace` when there were multiple chunks (#28437) - Propagate `is_scalar` from the input to the output of `.sort()` and `.sort_by()` (#28438) - Resolve CSV column names overwrite in DSL->IR conversion (#28383) - Avoid IEJoin rewrite for Categorical comparisons (#28427) - Do not rewrite `sort().reverse()` to `sort(descending=True)` when `maintain_order=True` (#28403) - Ensure BinaryView offset+len does not exceed i32::MAX where possible (#28048) - Invalid offset in strptime (#28388) - Incorrect schema type for decimal \<-> primitive division (#28373) - Panic in in-memory CSEE handling (#28371) - Fix offset in arrow ffi export of sliced struct arrays (#28369) - Fix cross filter not applied with sink and CSE (#28297) - Fix panic on projection pushdown with caches (#28280) - Fix `write_json()` null values in `Array` columns being written incorrectly as `null` (#28330) - Fix EntityTooSmall on sink\_ipc to S3 (#28255) - Raise error instead of silent wrapping for `select(len())` (#28355) - Float16 groupby aggregates (#28361) - Respect lexical ordering of Categorical in `top_k`/`bottom_k` (#28359) - Support dtype-list schema overrides in scan\_csv (#28226) - Resolve unknown type in fused multiply add (#28321) - Honor `aws_checksum_algorithm` when provided (#28328) - Remove usage of deprecated `pyarrow.feather.read_table` (#28323) - Fix regress _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.43.0]_ ### 1.42.1 — Python Polars 1.42.1 - Date: 2026-06-30 - Version: 1.42.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.42.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.42.1 - **deprecated** — Deprecate strict parameter of pl.concat, replace with new how='horizontal_extend' - **changed** — Add a sampled resolve mode for multi-file parquet metadata - **changed** — Speed up small dtype series sums with a upcast sum kernel - **changed** — Don't block on path expansion - **fixed** — Fix incorrect sorted fast-path returning nan for grouped max - **fixed** — Fix panic on scan_parquet filter of fixed-size binary column - **fixed** — Fix decimal dynamic float cast - **fixed** — Fix pyiceberg key dot HDFS prefix filter - **fixed** — Fix projection pushdown panic on select(len()) after groupby - **fixed** — Fully resolve remaining ResourceWarning leaks in database and iceberg tests - **fixed** — Fix expiry time loading for AWS DeferredRefreshableCredentials - **fixed** — Avoid panic on temporal extraction for datetime columns with nulls - **fixed** — Prevent panic in replace when old or new contain Expr or object dtype values ##### ⚠️ Deprecations - Deprecate `strict` parameter of `pl.concat`, replace with new `how='horizontal_extend'` (#27965) ##### 🚀 Performance improvements - Add a sampled resolve mode for multi-file parquet metadata (#28111) - Speed up small dtype series sums with a upcast sum kernel (#27958) - Don't block on path expansion (#28073) ##### ✨ Enhancements - Close ResourceWarning leaks in database tests (#28066) ##### 🐞 Bug fixes - Incorrect sorted fast-path returning nan for grouped max (#28129) - Fix panic on scan\_parquet filter of fixed-size binary column (#28122) - Fix decimal dynamic float cast (#28126) - Fix pyiceberg key dot HDFS prefix filter (#28109) - Fix projection pushdown panic on `select(len())` after `groupby` (#28108) - Fully resolve remaining `ResourceWarning` leaks in database/iceberg tests (#28107) - Expiry time loading for AWS `DeferredRefreshableCredentials` (#28099) - Close ResourceWarning leaks in database tests (#28066) - Avoid panic on temporal extraction for datetime columns with nulls (#28054) - Prevent panic in `replace` when `old`/`new` contain Expr or object dtype values (#27433) ##### 📖 Documentation - Fix dataset regression in the examples (#28131) - Emphasize to generally not ever write Rust tests (#28082) - Mention Polars skill in User Guide's LLM section (#28113) ##### 🛠️ Other improvements - Disallow usage of `tokio::spawn` in clippy (#28123) - Improve `Makefile` with respect to `venv` robustness (#28110) - Remove legacy prelude glob imports from leaf files (#28114) - Skip pandas 3.0.4 due to `pd.TimeDelta` segfault (#28125) - Update `mypy` to the new `2.x` release (#28116) - Ensure `pyrefly` checks run as part of `make pre-commit` (#28095) - Fix `test_select_explode_height_filter_order_by` failure when `POLARS_MAX_THREADS=2` (#28090) - Add Morsel::height (#28060) Thank you to all our contributors for making this release possible! @0guban0v, @Kevin-Patyk, @TNieuwdorp, @alexander-beedie, @azimafroozeh, @dsprenkels, @kdn36, @nameexhaustion, @orlp, @raphaelroshan, @ritchie46 and @sar-cheng ### 1.42.0 — Python Polars 1.42.0 - Date: 2026-06-24 - Version: 1.42.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.42.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.42.0 - **deprecated** — Deprecate casts from string to temporal dtypes - **changed** — Add bytes-based concurrency control for cloud IO - **changed** — Stop flushing multiplexer on phase change - **changed** — Prevent empty chunks from triggering copy in rechunk - **changed** — Improve performance of struct unnest inside list eval on streaming - **changed** — Eliminate filters with contradictory predicates - **added** — Add naive out-of-core spilling to Polars - **added** — Add experimental strict mode - **changed** — Optimize non-negative len and null_count comparisons - **changed** — Optimize len and null_count comparisons - **added** — Support SQL's implicit JOIN syntax - **added** — Add Expr.is_sorted - **added** — Add suggestions in wrong api usage or mismatched column names - **added** — Add external object_store support for non-native schemes - **changed** — Skip Delta files and parquet row groups using per-field struct statistics - **changed** — Improve IR sortedness detection for with_row_index and explode - **added** — Add DataFrame.is_sorted() - **added** — Expose fixed-size rolling window expressions in Python visitor - **added** — Add tiered multi-file parquet metadata resolver - **changed** — Cache and shuffle DNS for cloud object_store - **deprecated** — Add a deprecation warning for .explode() without empty_as_null argument ##### ⚠️ Deprecations - Deprecate casts from string to temporal dtypes (#28056) ##### 🚀 Performance improvements - Add bytes-based concurrency control for cloud IO (#27924) - Stop flushing multiplexer on phase change (#28013) - Prevent empty chunks from triggering copy in rechunk (#27953) - Improve performance of struct unnest inside list eval on streaming (#27905) - Eliminate filters with contradictory predicates (#27775) ##### ✨ Enhancements - Deprecate casts from string to temporal dtypes (#28056) - Add naive out-of-core spilling to Polars (#27998) - Add experimental strict mode (#28023) - Optimize non-negative len and null\_count comparisons (#28002) - Optimize len and null\_count comparisons (#27727) - Support SQL's implicit `JOIN` syntax (#27890) - Add `Expr.is_sorted` (#26708) - Add suggestions in wrong api usage or mismatched column names (#27954) - Add external object\_store support for non-native schemes (#27871) - Skip Delta files and parquet row groups using per-field struct statistics (#27887) - Improve IR sortedness detection for with\_row\_index and explode (#27875) - Add `DataFrame.is_sorted()` (#27870) - Expose fixed-size rolling window expressions in Python visitor (#27108) - Fix SchemaError using lazy HConcat->Sink (#27770) - Add tiered multi-file parquet metadata resolver (#27720) - Cache and shuffle DNS for cloud object\_store (#27659) ##### 🐞 Bug fixes - Add a deprecation warning for `.explode()` without `empty_as_null` argument (#28040) - Fix `select(len())` incorrectly returned 0 when using `scan_iceberg` with `pyiceberg` as reader override (#28044) - Ensure slice expr always observes input order (#28041) - Fix projection pushdown with row index out of order (#28043) - Fix cross-join predicates not applied when using `sink_*` functions (#28042) - Grammar corrections (recommend to → recommend, allows to → allows using) (#28038) - Ensure optimisations aren't omitted by cached IR nodes (#28004) - Computed GROUP keys in SQL projections (#27989) - Handle empty DataFrames in `dt.truncate` and `dt.round` (#26120) - Address join alias state leakage in SQL CTEs (#27985) - Support scanning `file://` URIs with percent-encoded paths (#27876) - Lower SQL `[NOT] IN (subquery)` to semi/anti join (#27888) - Check for continuity across morsels in AsOf join node (#27461) - Add test for projection pushdown with hconcat regression (#27937) - Traverse caches only once in explain (#27939) - Preserve null placement when collapsing `sort.reverse()` into single sort (#27918) - Incorrect schema order for hstack in projection pushdown optimizer (#27920) - Fix duplicated map\_elements warning on streaming engine (#27919) - Use block\_in\_place\_on for calls which can come from executor thread (#27855) - Mismatch in max\_threads -> pipeline configuration (#27854) - Keep maintain\_order on sliced unique (#27852) - Fix SchemaError using lazy HConcat->Sink (#27770) - Fix incorrect projection height when selecting only literals (#27825) - Select with expr slice and len gave incorrect len (#27824) - Prevent import panic when environment variable set to unexpected value (#27831) ##### 📖 Documentation - New On-Prem release (#27979) - Add note on OOM behavior on Kubernetes (#27972) - Properly render backslashes in CSV `eol_char` docstrings (#27962) - Add entry for `DataFrame.is_sorted()` (#27913) - Clarify compat\_level export docs (#27715) - Add robots.txt disallowing stale docs and added sitemap for better SEO (#27901) - Update Polars \<> Spark comparison (#27873) - Bump to patched version (#27851) - Replace Typeform sign-up URL with new enterprise link (#27838) - Correct wrong head call (#27848) - Add Polars On-Prem 0.5.0 release (#27849) - Correct onprem license helm values (#27847) - Update connecting Polars Cloud to AWS documentation (#27823) - Correct cost/connectivity sections (#27813) - Add sections about egress (#27805) - Tragic typo in On-Pre _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.42.0]_ ### 1.41.2 — Python Polars 1.41.2 - Date: 2026-05-29 - Version: 1.41.2 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.41.2 - Permalink: https://whatsnew.fyi/product/polars/releases/1.41.2 - **changed** — Update to new jemalloc - **changed** — Do not materialize ScalarColumn in Column split_at - **changed** — Avoid materializing broadcast in array.shift - **changed** — Avoid materializing broadcast list in list.sample(n) and list.sample(frac) - **fixed** — Broken link to AI Policy corrected - **changed** — Harden against async blocking deadlocks ##### 🚀 Performance improvements - Update to new jemalloc (#27797) - Do not materialize `ScalarColumn` in Column `split_at` (#27782) - Avoid materializing broadcast in `array.shift` (#27740) - Avoid materializing broadcast list in `list.sample(n)` and `list.sample(frac)` (#27679) ##### ✨ Enhancements - Update to new jemalloc (#27797) ##### 🐞 Bug fixes - Broken link to AI Policy corrected (#27793) - Update to new jemalloc (#27797) ##### 📖 Documentation - Update Polars On-Prem version stamp (#27799) - Broken link to AI Policy corrected (#27793) - Add release dates to the On-Prem releases page (#27787) - Improve on-prem docs (#27788) - Add query profiler video to On-Prem user guide (#27786) - Add EKS/AKS/GKE guides (#27774) - Add Polars On-Prem 0.4.2 (#27780) ##### 🛠️ Other improvements - Run Pyrefly on `_utils` and `functions` (#27789) - Harden against async blocking deadlocks (take 2) (#27767) Thank you to all our contributors for making this release possible! @ButteryPaws, @EndPositive, @Kevin-Patyk, @MarcoGorelli, @TNieuwdorp, @azimafroozeh, @carnarez, @kdn36, @lun3x, @orlp and @ritchie46 ### 1.41.1 — Python Polars 1.41.1 - Date: 2026-05-27 - Version: 1.41.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.41.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.41.1 - **changed** — Improve performance of agg_n_unique with adaptive size dispatch to hashset or radix sort and capacity-aware reset - **added** — Allow deeper expressions - **fixed** — Raise length mismatch in multiple sort_by in group_by - **fixed** — Respect min_samples for rolling_by ops with nulls - **fixed** — Fix memory usage regression affecting TPCH Q22 - **added** — Add POLARS_ALLOW_NESTED_CSPE env var and make nested CSPE opt-in - **fixed** — Post-apply residual pyarrow predicates - **fixed** — Fix loss of precision for smaller floating types - **fixed** — Fix filter at scan dropped in CSPE filter pushdown - **fixed** — Fix portstate assertion error on is_in - **fixed** — Fix incorrect when/then after forward fill / reverse in groupby - **fixed** — Accept empty Thrift list encoded as bare 0x00 byte in parquet metadata - **fixed** — Stabilize object store credentialprovider cache key ##### 🚀 Performance improvements - Adaptive size dispatch to hashset or radix sort + capacity-aware reset in `agg_n_unique` (#27719) ##### ✨ Enhancements - Allow deeper expressions (#27768) ##### 🐞 Bug fixes - Raise length mismatch in multiple `sort_by` in `group_by` (#27772) - Respect min\_samples for rolling\_by ops with nulls (#27706) - Fix memory usage regression affecting TPCH Q22 (#27758) - Add `POLARS_ALLOW_NESTED_CSPE` env var and make nested CSPE opt-in (#27765) - Post-apply residual pyarrow predicates (#27764) - Fix loss of precision for smaller floating types(#27662) (#27732) - Filter at scan dropped in CSPE filter pushdown (#27763) - Fix portstate assertion error on is\_in (#27757) - Fix incorrect when/then after forward fill / reverse in groupby (#27745) - Accept empty Thrift list encoded as bare 0x00 byte in parquet metadata (#27754) - Stabilize object store `credentialprovider` cache key (#27712) - Add to `merge_sorted` docs that the input must be nulls first (#27743) ##### 📖 Documentation - Docs fixes (#27766) - Sync from Polars Cloud (#27751) - Add to `merge_sorted` docs that the input must be nulls first (#27743) ##### 🛠️ Other improvements - Attribute annotations for `CatalogCredentialProvider` (#27739) - Solve `type: ignore` in \_AioDataFrameResult (#27311) - Remove dead code in `_write_utils.py` (#27721) - Remove unnecessary ``not isinstance(v, DataType)`` check (#27723) Thank you to all our contributors for making this release possible! @EndPositive, @JakubValtar, @MarcoGorelli, @NicoOhR, @azimafroozeh, @carnarez, @dsprenkels, @jorenham, @kdn36, @nameexhaustion, @orlp and @ritchie46 ### 1.41.0 — Python Polars 1.41.0 - Date: 2026-05-22 - Version: 1.41.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.41.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.41.0 - **added** — Add LazyFrame.gather - **added** — Add Expr.is_empty - **added** — Add support for the SQL FILTER clause for aggregate functions, and STRING_AGG - **added** — Add null_on_oob in {Expr/Series}.gather - **added** — Add Rust backend for Expr.has_nulls - **added** — Add streaming GatherNode - **changed** — Stabilize streaming engine - **changed** — Stabilize float16 - **changed** — Use true division for the / operator in Polars SQL - **changed** — Dispatch {list,arr}.{unique,n_unique,reverse} to group_by engine - **changed** — Speed up parquet metadata decode with hand-written Thrift - **fixed** — Panic in scan of empty IPC with slice - **fixed** — Persist object_store rebuild state in cache - **fixed** — Sort flag on GroupsType only applies to first element - **fixed** — Don't unwrap channel send in streaming join_asof - **fixed** — Fix merge_sorted panic when List in frame - **fixed** — Raise TypeError when calling next() directly on GroupBy objects - **fixed** — Data type comparison for extension types - **fixed** — Prevent panic when switching from one extension dtype to another - **deprecated** — Deprecate the StringCache ##### 🏆 Highlights - Add LazyFrame.gather (#27501) - Nested common subplan elimination (#27340) - Stabilize streaming engine (#27497) - Speed up parquet metadata decode with hand-written Thrift (#27427) ##### ⚠️ Deprecations - Deprecate the StringCache (#27580) ##### 🚀 Performance improvements - Dispatch `{list,arr}.{unique,n_unique,reverse}` to group\_by engine (#27278) - Improve in-memory grouped non-null count (#27702) - Factor shared conjuncts out of OR-of-ANDs predicates (#27627) - Skip downloading IPC batches exceeding slice bounds (#27683) - Avoid materializing broadcast list in `list.shift` (#27628) - Optimise `json_decode` Datetime string parsing (#27559) - Speed up `to_numpy` C-order via cache-blocked transpose (#27522) - Optimize `select(len())` for non-strict horizontal concat (#27516) - Pushdown slices to inputs on left/right/full join (#27508) - Don't infer CSV schema if schema is set (#27507) - Nested common subplan elimination (#27340) - Make `is_in` row-group pruning precise on null-containing haystacks (#27495) - Don't do fused-multiply-add on scalars (#27479) - List full fast path (#27477) - Make `is_in` row-group pruning precise on multi-value lists (#27475) - Add streaming GatherNode (#27465) - Lower non-elementwise FunctionExprIR to ColumnarFunctionNode (#27462) - Speed up parquet metadata decode with hand-written Thrift (#27427) ##### ✨ Enhancements - Use true division for the `/` operator in Polars SQL (#27391) - Add Rust backend for Expr.has\_nulls (#27590) - Stabilize float16 (#27607) - Add Expr.is\_empty (#27583) - Add support for the SQL `FILTER` clause for aggregate functions, and `STRING_AGG` (#27564) - Make parquet `FileMetadata` prunable for IR-plan dispatch (#27535) - Broadcast scalar input for `list.slice` (#27487) - Add LazyFrame.gather (#27501) - Add `null_on_oob` in {Expr/Series}.gather (#27327) - Stabilize streaming engine (#27497) - Process batched `arr.eval` on overflow boundaries (#27496) - Process batched `list.eval` on overflow boundaries (#27483) - Print `SLICED UNION` in LazyFrame explain (#27467) ##### 🐞 Bug fixes - Panic in scan of empty IPC with slice (#27708) - Persist object\_store rebuild state in cache (#27707) - Sort flag on GroupsType only applies to first element (#27684) - Invalid unwrap\_unchecked when length isn't exact (#27685) - Don't unwrap channel send in streaming join\_asof (#27688) - Fix `merge_sorted` panic when List in frame (#27568) - Put AsOf join buffered Morsels back the front of the deque if we cannot process them rn (#27658) - Fix skip\_batches logic for NaN (#27673) - Raise `TypeError` when calling `next()` directly on `GroupBy` objects (#27562) - Data type comparison for extension types (#27632) - Share last-morsel split budget across files in streaming multi-scan (#27630) - Bytes scalars were not being broadcast in dataframe constructor (#27621) - Reset the sort-options in `Series::is_sorted()` after row-encoding columns (#27614) - Rayon deadlock with re-entrant io sources (#27600) - Don't push negative-offset slices through `HConcat` (#27570) - Logic error in streaming is\_empty (#27602) - Fix incorrect CSE with large is\_in literal (#27575) - AnonymousFunction can qualify as SQL aggregator (#26986) - Fix CSPE panic in cloud (#27594) - Set merge-join streaming node to `Finished` if its sending port is `Done` (#27572) - Widen decimal precision on sum aggregation at runtime (#27579) - Fix `str.to_time` was raising unnecessarily when input was all nulls (#27574) - Prevent panic when switching from one extension dtype to another (#27566) - Fix `DataFrame.write_database(..., if_table_exists="append", engine="adbc")` not handling missing tables correctly (#26913) - Ensure `json_decode` doesn't fail for Date and Time string deserialization (#27554) - Incorrect RUSTFLAGS passing in Makefile (#27555) - Fix panic on reading IPC with 0-row compressed bitmap (#27551) - Set HEAD\_RESPONSE\_SIZE\_ESTIMATE to 0 (#27548) - Fix lazy concat horizontal didn' _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.41.0]_ ### 1.40.1 — Python Polars 1.40.1 - Date: 2026-04-22 - Version: 1.40.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.40.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.40.1 - **changed** — Skip validity mask processing in __array_ufunc__ when no inputs have nulls - **added** — Add maintain_order parameter to merge_sorted - **fixed** — Honor having predicate in GroupBy iter - **fixed** — Use the physical dtype for NumUnorderedImplodeReducer arrow ListArray - **fixed** — Address bug in reduce_balanced for certain input length lists affecting pl.concat - **fixed** — Ensure list.sample() allows fraction > 1 when with_replacement=True - **fixed** — Ensure append() errors when upcast=False - **fixed** — Always rechunk sorts, prune sorts even in eager execution - **fixed** — Fix typing for DataFrame.__init__ and Series.__init__ so they don't require all optional dependencies to be installed ##### 🚀 Performance improvements - Skip validity mask processing in \_\_array\_ufunc\_\_ when no inputs have nulls (#27358) ##### ✨ Enhancements - Cargo deny (#27363) - Add `maintain_order` parameter to `merge_sorted` (#27263) ##### 🐞 Bug fixes - Honor `having` predicate in `GroupBy` iter (#27370) - Use the physical dtype for `NumUnorderedImplodeReducer` arrow `ListArray` (#27375) - Address bug in `reduce_balanced` for certain input length lists affecting `pl.concat` (#27352) - Ensure `list.sample()` allows `fraction` > 1 when `with_replacement=True` (#27350) - Ensure `append()` errors when `upcast=False` (#27346) - Always rechunk sorts, prune sorts even in eager execution (#27356) - Fix typing for `DataFrame.__init__` and `Series.__init__` so they don't require all optional dependencies to be installed (#27348) ##### 📖 Documentation - Split out openlineage docs into guide and configuration (#27371) - Add explanation on the observatory sqlite db file (#27354) ##### 🛠️ Other improvements - Disable mypy type checking for `pyarrow` calls (#27377) - Disable debug symbols in macos coverage tests (#27361) - Cargo deny (#27363) Thank you to all our contributors for making this release possible! @EndPositive, @Kevin-Patyk, @MarcoGorelli, @carnarez, @dsprenkels, @gab23r, @jonathanchang31, @kdn36, @mzjp2 and @ritchie46 ### 1.40.0 — Python Polars 1.40.0 - Date: 2026-04-18 - Version: 1.40.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.40.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.40.0 - **added** — Add streaming support for grouped AsOf join - **added** — Add `ignore_nulls` to `{list,arr}.{any,all}` - **added** — Add `is_unique` to list/array dtypes - **added** — Add `pl.merge_sorted` operating on multiple frames - **added** — Add native streaming `interpolate` - **changed** — Create IR slice from expr slice pushdown - **changed** — Avoid unnecessary rechunk when sorting already sorted DataFrame - **changed** — Lower basic over() to streaming primitives - **changed** — Lower `drop_{nulls,nans}` in streaming `group_by` aggregations - **changed** — Lower `entropy` to streaming reductions - **changed** — Streaming `strptime` with `format=None` - **changed** — Lower `skew` / `kurtosis` to streaming aggregations - **changed** — Post apply pyarrow filter in Polars' engine instead of pyarrow - **changed** — Optimize `drop_nulls().{first,last}()` to `{first,last}(ignore_nulls=True)` - **changed** — Always process pyarrow scan in batches - **changed** — Make `cut` output `Enum` and mark as elementwise - **changed** — Use delta stats for mixed hive and non-hive predicate pushdown - **changed** — Take into account size per row in join sampling - **changed** — Streaming is_first_distinct and unique(maintain_order=True) - **changed** — Streaming `cov` and `corr` ##### 🏆 Highlights - Add streaming support for grouped AsOf join (#27293) ##### ⚠️ Deprecations - Deprecate support for dataframe interchange protocol (#27214) ##### 🚀 Performance improvements - Create IR slice from expr slice pushdown (#27200) - Add streaming support for grouped AsOf join (#27293) - Avoid unnecessary rechunk when sorting already sorted DataFrame (#27264) - Lower basic over() to streaming primitives (#27303) - Lower `drop_{nulls,nans}` in streaming `group_by` aggregations (#27296) - Lower `entropy` to streaming reductions (#27174) - Add native streaming `interpolate` (#27185) - Streaming `strptime` with `format=None` (#27056) - Lower `skew` / `kurtosis` to streaming aggregations (#27176) - Post apply pyarrow filter in Polars' engine instead of pyarrow (#27192) - Optimize `drop_nulls().{first,last}()` to `{first,last}(ignore_nulls=True)` (#27187) - Always process pyarrow scan in batches (#27183) - Make `cut` output `Enum` and mark as elementwise (#27173) - Remove unused expression sorts (#27075) - Use delta stats for mixed hive and non-hive predicate pushdown (#27102) - Take into account size per row in join sampling (#27098) - Streaming is\_first\_distinct and unique(maintain\_order=True) (#27052) - Streaming `cov` and `corr` (#27008) - Add sorted unique node to streaming engine (#26990) - Ensure Expr.append is lowered in streaming engine (#27022) - Collapse consecutive Sort nodes (#26965) - Drop `maintain_order=True` requirement in `sink_delta` (#27007) ##### ✨ Enhancements - Add `ignore_nulls` to `{list,arr}.{any,all}` (#27186) - Lock-free memory manager with spill-to-disk and fully OOC multiplexer (#26774) - Add `is_unique` to list/array dtypes (#27290) - Streaming pyarrow datasets sources (#27230) - Add `pl.merge_sorted` operating on multiple frames (#27014) - Allow `group_by()` without key exprs (#27141) - Change default scan/read\_lines column name from "lines" to "line" (#27122) - Make unnest() effective on all columns by default (#27029) - Collapse consecutive Sort nodes (#26965) ##### 🐞 Bug fixes - Update `groups` to correct length for `Implode` (#27282) - Fix scan\_csv missing\_columns='insert' overwrote existing data with NULLs (#27297) - Raise on non-numeric inputs in `pl.int_ranges` (#27294) - Fix always-true filter conversion to Iceberg filter (#27119) - Do not skip nulls when enumerating over rows in grouped AsOf join (#27275) - Fix `pivot` dropping data for null `on` values (#27273) - Resolve multiple files deadlock in CSV async reader (#27073) - Widen decimal precision on sum aggregation (#27270) - Correct lf.remote type (#27261) - Default `LazyFrame.map_batches` to no optimizations (#27262) - Extend `StructEval` schema context in `StackOptimizer` (#27243) - Preserve nulls when casting from all-null `Series` to `Struct` (#27241) - Fix `scan_delta` filter on empty dataframe (#27244) - Prevent `DataFrame` creation panic on `list[struct]` with heterogenous types (#27217) - Named aggregation `__structify` was being ignored (#27148) - Skip `null` group entries when collecting AsOf-by groups (#27215) - Fix panic with empty order\_by in over expression (#27088) - Write field ID from `sink_parquet` (#27196) - Fix statistics for Null columns in Parquet (#27021) - Do not prune sort nodes containing slice with dyn predicate (#27140) - Correct grouped `Binary` `arg_min`/`arg_max` and `String` single-element arg indices (#27172) - Resolve multiple files deadlock in NDJSON async reader (#27204) - Overflow panic in interpolate nearest (#27205) - Using checked arithmetic in `int96_to_i64_ns` to prevent overflow panic (#27129) - Don't trigger csv fast count if predicate is pushed down (#27190) - Support all integer dtypes for Series index assignment (#27188) - Streaming sort by-expressions were lowered incorrectly (#27158) - Replace multiprocessing.dummy.Pool with ThreadPoolExecutor (#27175) - Reset IO metrics instead of consuming (#27156) - Output SVG if output\_path ends with '.svg' in show\_grap _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.40.0]_ ### 1.39.3 — Python Polars 1.39.3 - Date: 2026-03-20 - Version: 1.39.3 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.39.3 - Permalink: https://whatsnew.fyi/product/polars/releases/1.39.3 * No changes Thank you to all our contributors for making this release possible! @ritchie46 ### 1.39.2 — Python Polars 1.39.2 - Date: 2026-03-17 - Version: 1.39.2 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.39.2 - Permalink: https://whatsnew.fyi/product/polars/releases/1.39.2 * No changes Thank you to all our contributors for making this release possible! @nameexhaustion and @ritchie46 ### 1.39.1 — Python Polars 1.39.1 - Date: 2026-03-17 - Version: 1.39.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.39.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.39.1 - **fixed** — Handle empty rolling windows in streaming engine ##### 🐞 Bug fixes - Handle empty rolling windows in streaming engine (#26903) ##### 📖 Documentation - Add documentation for on\_columns for LazyFrame pivot (#26859) ##### 🛠️ Other improvements - Bump build deps used in ARM64 Windows release pipeline (#26892) Thank you to all our contributors for making this release possible! @Kevin-Patyk, @RenzoMXD, @TNieuwdorp, @dsprenkels, @gautamvarmadatla, @nameexhaustion, @nicholaslegrand102 and @ritchie46 ### 1.39.0 — Python Polars 1.39.0 - Date: 2026-03-12 - Version: 1.39.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.39.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.39.0 - **changed** — Lower arg_{min,max} to streaming engine - **changed** — Additional IR slice pushdown after filter pushdown - **changed** — Streaming first/last on Enum through physical - **changed** — Fast filter for scalar predicates - **changed** — Allow SimpleProjection in streaming engine to rename - **changed** — Streaming cloud download for scan_csv - **changed** — Drop columns only needed for predicates after the predicate is applied - **changed** — Run projection pushdown after predicate pushdown - **changed** — Comparison literal downcasting - **changed** — Add dynamic predicates for TopK - **changed** — Increase minimum default parquet row group prefetch to 8 - **changed** — Partial predicate conversion to PyArrow - **changed** — Streaming cloud download for scan_ndjson and scan_lines - **changed** — Improve CSV and NDJSON cloud sink performance - **changed** — Tune cloud writer performance - **changed** — Allow parallel InMemorySinks in streaming engine - **added** — Support Expr for holidays in business day calculations - **added** — Parameter for pivot to always include value column name - **added** — Extend Expr.reinterpret to all numeric types of the same size - **added** — Add missing_columns parameter to scan_csv ##### 🚀 Performance improvements - Lower `arg_{min,max}` to streaming engine (#26845) - Additional IR slice pushdown after filter pushdown (#26815) - Streaming first/last on Enum through physical (#26783) - Fast filter for scalar predicates (#26745) - Allow SimpleProjection in streaming engine to rename (#26709) - Streaming cloud download for `scan_csv` (#26637) - Drop columns only needed for predicates after the predicate is applied (#26703) - Run projection pushdown after predicate pushdown (#26688) - Comparison literal downcasting (#26663) - Add dynamic predicates for TopK (#26495) - Increase minimum default parquet row group prefetch to 8 (#26632) - Partial predicate conversion to PyArrow (#26567) - Streaming cloud download for `scan_ndjson` / `scan_lines` (#26563) - Grab GIL fewer times during Object join materialization (#26587) - Improve CSV and NDJSON cloud sink performance (#26545) - Tune cloud writer performance (#26518) - Allow parallel InMemorySinks in streaming engine (#26501) - Add streaming `AsOf` join node (#26398) - Don't always rechunk on gather of nested types (#26478) ##### ✨ Enhancements - Support Expr for holidays in business day calculations (#26193) - Parameter for pivot to always include value column name (#26730) - Raise error in `.collect_schema()` when `arr.get()` is out-of-bounds (#26866) - Extend `Expr.reinterpret` to all numeric types of the same size (#26401) - Add missing\_columns parameter to scan\_csv (#26787) - Clear no-op scan projections (#26858) - Support nested datatypes for `{min,max}_by` (#26849) - Support SQL `ARRAY` init from typed literals (#26622) - Accept table identifier string in `scan_iceberg()` (#26826) - Add a convenience `make fresh` command to the Makefile (#26809) - Expose "use\_zip64" Workbook option for `write_excel` (#26699) - Add unstable `LazyFrame.sink_iceberg` (#26799) - Add maintain order argument on implode (#26782) - Speed up casting primitive to bool by at least 2x (#26823) - Support ASCII format table input to `pl.from_repr` (#26806) - Enable rowgroup skipping for float columns (#26805) - Add expression context to errors (#26716) - Add Decimal support for product reduction (#26725) - Support all Iceberg V2 arrow types in sink\_parquet arrow\_schema parameter (#26669) - Re-work behavior of arrow\_schema parameter on sink\_parquet (#26621) - Add `contains_dtype()` method for `Schema` (#26661) - Implement `truncate` as a "to\_zero" rounding mode (#26677) - More generic streaming GroupBy lowering (#26696) - Create an `Alignment` TypeAlias (#26668) - Add basic MemoryManager to track buffered dataframes for out-of-core support later (#26443) - Add `truncate` Expression for numeric values (#26666) - Better error messages for hex literal conversion issues in the SQL interface (#26657) - Add SQL support for `LPAD` and `RPAD` string functions (#26631) - Support SQL "FROM-first" `SELECT` query syntax (#26598) - Improve `base_type` typing (#26602) - Bump Chrono to 0.4.24, enabling stricter parsing of `%.3f`/`%.6f`/`%.9f` specifiers (#26075) - Expose unstable `assert_schema_equal` in py-polars (#24869) - Allow parsing of compact ISO 8601 strings (#24629) - Add optional "label" param to DataFrame `corr` (#26588) - Streaming cloud download for `scan_ndjson` / `scan_lines` (#26563) - Configuration to cast integers to floats in `cast_options` for `scan_parquet` (#26492) - Add escaping to quotes and newlines when reading JSON object into string (#26578) - Standardise on RFC-5545 when doing datetime arithmetic on timezone-aware datetimes (#26425) - Support `sas_token` in Azure credential provider (#26565) - Relax SQL requirement for derived tables and subqueries to have aliases (#26543) - Add polars-config and pl.Config.reload\_env\_vars() (#26524) - Record path for object store error raised from sinks (#26541) - Use CRC64NVME for checksum in aws sinks (#26522) - Add `get()` for binary Series (#26514) - Add streaming `AsOf` join node (#26398) - Add primitive filter -> agg low _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.39.0]_ ### 1.38.1 — Python Polars 1.38.1 - Date: 2026-02-06 - Version: 1.38.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.38.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.38.1 - **added** — Add get() to retrieve a byte from binary data - **changed** — Remove with_context in SQL lowering - **fixed** — Do not overwrite used names in cluster_with_columns pushdown - **fixed** — Do not mark output of concat_str on multiple inputs as sorted - **fixed** — Fix CSV schema inference content line duplication bug - **fixed** — Fix InvalidOperationError using scan_delta with filter - **fixed** — Alias giving missing column after streaming GroupBy CSE - **fixed** — Ensure by_name selector selects only names - **fixed** — Restore compatibility of strings written to parquet with pyarrow filter - **fixed** — Update schema in cluster_with_columns optimization - **fixed** — Fix negative slice in groups slicing - **fixed** — Don't run CPU check on aarch64 musl - **fixed** — Fixed annotations shadowed by class methods - **fixed** — Fix selector match patterns for multiline column names ##### ✨ Enhancements - Add get() to retrieve a byte from binary data (#26454) - Remove with\_context in SQL lowering (#26416) ##### 🐞 Bug fixes - Do not overwrite used names in cluster\_with\_columns pushdown (#26467) - Do not mark output of concat\_str on multiple inputs as sorted (#26468) - Fix CSV schema inference content line duplication bug (#26452) - Fix InvalidOperationError using `scan_delta` with filter (#26448) - Alias giving missing column after streaming GroupBy CSE (#26447) - Ensure `by_name` selector selects only names (#26437) - Restore compatibility of strings written to parquet with pyarrow filter (#26436) - Update schema in cluster\_with\_columns optimization (#26430) - Fix negative slice in groups slicing (#26442) - Don't run CPU check on aarch64 musl (#26439) - Fixed annotations shadowed by class methods (#26356) - Remove the `POLARS_IDEAL_MORSEL_SIZE` monkeypatching in the parametric merge-join test (#26418) - Fix `selector` match patterns for multiline column names (#26320) ##### 📖 Documentation - Add `sink_delta` to API reference (#26446) ##### 🛠️ Other improvements - Cleanup unused attributes in optimizer (#26464) - Use `Expr::Display` as catch all for IR - DSL asymmetry (#26471) - Ignore pytz in mypy (#26441) - Remove the `POLARS_IDEAL_MORSEL_SIZE` monkeypatching in the parametric merge-join test (#26418) - Cleanup the parametric merge-join test (#26413) Thank you to all our contributors for making this release possible! @Voultapher, @alexander-beedie, @azimafroozeh, @cmdlineluser, @dependabot[bot], @dsprenkels, @hamdanal, @kdn36, @nameexhaustion, @orlp, @ritchie46 and [dependabot[bot]](https://github.com/apps/dependabot) ### 1.38.0 — Python Polars 1.38.0 - Date: 2026-02-04 - Version: 1.38.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.38.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.38.0 - **deprecated** — Deprecate retries=n in favor of storage_options={"max_retries": n} - **changed** — Enable zero-copy object_store put upload for IPC sink - **changed** — Resolve file schema's and metadata concurrently - **changed** — Run elementwise CSEE for the streaming engine - **changed** — Disable morsel splitting for fast-count on streaming engine - **changed** — Implement streaming decompression for scan_ndjson and scan_lines - **changed** — Improve string slicing performance - **changed** — Refactor scan_delta to use python dataset interface - **changed** — Add dedicated kernel for group-by arg_max/arg_min - **added** — Add streaming merge-join - **changed** — Generalize Bitmap::new_zeroed opt for Buffer::zeroed - **changed** — Reduce fs stat calls in path expansion - **changed** — Lower streaming group_by n_unique to unique().len() - **fixed** — Avoid OOM for scan_ndjson and scan_lines if input is compressed and negative slice - **added** — Support anonymous agg in-mem - **added** — Add unstable arrow_schema parameter to sink_parquet - **added** — Allow quantile to compute multiple quantiles at once - **added** — Allow empty LazyFrame in LazyFrame.group_by(...).map_groups - **added** — Add scan_lines - **added** — Support regex in str.split - **added** — Add nulls support for all rolling_by operations ##### ⚠️ Deprecations - Deprecate `retries=n` in favor of `storage_options={"max_retries": n}` (#26155) ##### 🚀 Performance improvements - Enable zero-copy object\_store `put` upload for IPC sink (#26288) - Resolve file schema's and metadata concurrently (#26325) - Run elementwise CSEE for the streaming engine (#26278) - Disable morsel splitting for fast-count on streaming engine (#26245) - Implement streaming decompression for scan\_ndjson and scan\_lines (#26200) - Improve string slicing performance (#26206) - Refactor `scan_delta` to use python dataset interface (#26190) - Add dedicated kernel for group-by `arg_max/arg_min` (#26093) - Add streaming merge-join (#25964) - Generalize Bitmap::new\_zeroed opt for Buffer::zeroed (#26142) - Reduce fs stat calls in path expansion (#26173) - Lower streaming group\_by n\_unique to unique().len() (#26109) ##### ✨ Enhancements - Avoid OOM for scan\_ndjson and scan\_lines if input is compressed and negative slice (#26396) - Support annoymous agg in-mem (#26376) - Add unstable `arrow_schema` parameter to `sink_parquet` (#26323) - Improve error message formatting for structs (#26349) - Remove parquet field overwrites (#26236) - Enable zero-copy object\_store `put` upload for IPC sink (#26288) - Improved disambiguation for qualified wildcard columns in SQL projections (#26301) - Expose `upload_concurrency` through env var (#26263) - Allow quantile to compute multiple quantiles at once (#25516) - Allow empty LazyFrame in `LazyFrame.group_by(...).map_groups` (#26275) - Use delta file statistics for batch predicate pushdown (#26242) - Add streaming UnorderedUnion (#26240) - Implement compression support for sink\_ndjson (#26212) - Add unstable record batch statistics flags to `{sink/scan}_ipc` (#26254) - Support CSE for python UDFs on the same address (#26253) - Cloud retry/backoff configuration via `storage_options` (#26204) - Use same sort order for expanded paths across local / cloud / directory / glob (#26191) - Add streaming merge-join (#25964) - Serialize optimization flags for cloud plan (#26168) - Add compression support to write\_csv and sink\_csv (#26111) - Add `scan_lines` (#26112) - Support regex in `str.split` (#26060) - Add unstable IPC Statistics read/write to `scan_ipc`/`sink_ipc` (#26079) - Add unstable `height` parameter to `DataFrame`/`LazyFrame` (#26014) - Remove old partition sink API (#26100) - Expose ArrowStreamExportable on python collect batches iterator (#26074) - Add nulls support for all rolling\_by operations (#26081) ##### 🐞 Bug fixes - Correct off-by-one in RLE row counting for nullable dictionary-encoded columns (#26411) - Support very large integers in env var limits (#26399) - Fix PlPath panic from incorrect slicing of UTF8 boundaries (#26389) - Fix Float dtype for spearman correlation (#26392) - Fix optimizer panic in right joins with type coercion (#26365) - Don't serialize retry config from local environment vars (#26289) - Fix `PartitionBy` with scalar key expressions and `diff()` (#26370) - Add {Float16, Float32} -> Float32 lossless upcast (#26373) - Fix panic using `with_columns` and `collect_all` (#26366) - Add multi-page support for writing dictionary-encoded Parquet columns (#26360) - Ensure slice advancement when skipping non-inlinable values in `is_in` with inlinable needles (#26361) - Pin `xlsx2csv` version temporarily (#26352) - Bugs in ViewArray total\_bytes\_len (#26328) - Overflow in i128::abs in Decimal fits check (#26341) - Make Expr.hash on Categorical mapping-independent (#26340) - Clone shared GroupBy node before mutation in physical plan creation (#26327) - Fixed "sheet\_name" typing for `read_ods` and `read_excel` (#26317) - Improve Polars dtype inference from Python `Union` typing (#26303) - Consider the "current location" of an item when computing `rolling_rank_by` (#26287) - Reset `is_count_star` flag between queries in collect\_all (#26256) - Fix incorrect is\_between filter on scan\_parquet (#26284) - Make polars compatibl _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.38.0]_ ### 1.37.1 — Python Polars 1.37.1 - Date: 2026-01-12 - Version: 1.37.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.37.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.37.1 - **changed** — Speed up SQL interface UNION clauses - **fixed** — Optimize slicing support on compressed IPC - **fixed** — CPU check for musl builds - **fixed** — Propagate C Stream import errors instead of panicking - **fixed** — Fix slicing on compressed IPC ##### 🚀 Performance improvements - Speed up `SQL` interface "UNION" clauses (#26039) ##### 🐞 Bug fixes - Optimize slicing support on compressed IPC (#26071) - CPU check for musl builds (#26076) - Propagate C Stream import errors instead of panicking (#26036) - Fix slicing on compressed IPC (#26066) ##### 📖 Documentation - Clarify min\_by/max\_by behavior on ties (#26077) ##### 🛠️ Other improvements - Mark top slow normal tests as slow (#26080) - Update breaking deps (#26055) - Fix for upstream url bug and update deps (#26052) - Properly pin chrono (#26051) - Don't run rust doctests (#26046) - Update deps (#26042) - Ignore very slow test (#26041) Thank you to all our contributors for making this release possible! @Voultapher, @alexander-beedie, @kdn36, @nameexhaustion, @orlp, @ritchie46 and @wtn ### 1.37.0 — Python Polars 1.37.0 - Date: 2026-01-10 - Version: 1.37.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.37.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.37.0 - **added** — Add new pl.PartitionBy API - **added** — Add lazy collect_all - **added** — Add nulls support for rolling_mean_by - **added** — Expose record batch size in {sink,write}_ipc - **added** — Add null_on_oob parameter to expr.get - **added** — Support streaming IPC scan from S3 object store - **added** — Add pl.Expr.(min|max)_by - **added** — Add Series sql method for API consistency - **added** — Support Binary and Decimal in arg_(min|max) - **added** — Add missing Series.arr.mean - **changed** — Speed up SQL interface ORDER BY clauses - **changed** — Add fast kernel for is_nan and use it for numpy NaN->null conversion - **changed** — New streaming NDJSON sink pipeline - **changed** — New streaming CSV sink pipeline - **changed** — Replace ryu with faster zmij - **changed** — Use new sink pipeline for write/sink_ipc - **changed** — Improve handling of unqualified SQL JOIN columns that are ambiguous - **changed** — Drop Python 3.9 support - **fixed** — Make struct.with_fields data model coherent - **fixed** — Ensure chunk consistency in in-memory join ##### 🚀 Performance improvements - Speed up `SQL` interface "ORDER BY" clauses (#26037) - Add fast kernel for is\_nan and use it for numpy NaN->null conversion (#26034) - Optimize ArrayFromIter implementations for ObjectArray (#25712) - New streaming NDJSON sink pipeline (#25948) - New streaming CSV sink pipeline (#25900) - Dispatch partitioned usage of `sink_*` functions to new-streaming by default (#25910) - Replace ryu with faster zmij (#25885) - Reduce memory usage for .item() count in grouped first/last (#25787) - Skip schema inference if schema provided for `scan_csv/ndjson` (#25757) - Add width-aware chunking to prevent degradation with wide data (#25764) - Use new sink pipeline for write/sink\_ipc (#25746) - Reduce memory usage when scanning multiple parquet files in streaming (#25747) - Don't call cluster\_with\_columns optimization if not needed (#25724) ##### ✨ Enhancements - Add new `pl.PartitionBy` API (#26004) - ArrowStreamExportable and sink\_delta (#25994) - Release musl builds (#25894) - Implement streaming decompression for CSV `COUNT(*)` fast path (#25988) - Add nulls support for rolling\_mean\_by (#25917) - Add lazy `collect_all` (#25991) - Add streaming decompression for NDJSON schema inference (#25992) - Improved handling of unqualified SQL `JOIN` columns that are ambiguous (#25761) - Drop Python 3.9 support (#25984) - Expose record batch size in `{sink,write}_ipc` (#25958) - Add `null_on_oob` parameter to `expr.get` (#25957) - Suggest correct timezone if timezone validation fails (#25937) - Support streaming IPC scan from S3 object store (#25868) - Implement streaming CSV schema inference (#25911) - Support hashing of meta expressions (#25916) - Improve `SQLContext` recognition of possible table objects in the Python globals (#25749) - Add pl.Expr.(min|max)\_by (#25905) - Improve MemSlice Debug impl (#25913) - Implement or fix json encode/decode for (U)Int128, Categorical, Enum, Decimal (#25896) - Expand scatter to more dtypes (#25874) - Implement streaming CSV decompression (#25842) - Add Series `sql` method for API consistency (#25792) - Mark Polars as safe for free-threading (#25677) - Support Binary and Decimal in arg\_(min|max) (#25839) - Allow Decimal parsing in str.json\_decode (#25797) - Add `shift` support for Object data type (#25769) - Add missing `Series.arr.mean` (#25774) - Allow scientific notation when parsing Decimals (#25711) ##### 🐞 Bug fixes - Release GIL on collect\_batches (#26033) - Missing buffer update in String is\_in Parquet pushdown (#26019) - Make `struct.with_fields` data model coherent (#25610) - Incorrect output order for order sensitive operations after join\_asof (#25990) - Use SeriesExport for pyo3-polars FFI (#26000) - Add pl.Schema to type signature for DataFrame.cast (#25983) - Don't write Parquet min/max statistics for i128 (#25986) - Ensure chunk consistency in in-memory join (#25979) - Fix varying block metadata length in IPC reader (#25975) - Implement collect\_batches properly in Rust (#25918) - Fix panic on arithmetic with bools in list (#25898) - Convert to index type with strict cast in some places (#25912) - Empty dataframe in streaming non-strict hconcat (#25903) - Infer large u64 in json as i128 (#25904) - Set http client timeouts to 10 minutes (#25902) - Correct lexicographic ordering for Parquet BYTE\_ARRAY statistics (#25886) - Raise error on duplicate `group_by` names in `upsample()` (#25811) - Correctly export view buffer sizes nested in Extension types (#25853) - Fix `DataFrame.estimated_size` not handling overlapping chunks correctly (#25775) - Ensure Kahan sum does not introduce NaN from infinities (#25850) - Trim excess bytes in parquet decode (#25829) - Fix panic/deadlock sinking parquet with rows larger than 64MB estimated size (#25836) - Fix quantile `midpoint` interpolation (#25824) - Don't use cast when converting from physical in list.get (#25831) - Invalid null count on int -> categorical cast (#25816) - Update groups in `list.eval` ( _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.37.0]_ ### 1.36.1 — Python Polars 1.36.1 - Date: 2025-12-10 - Version: 1.36.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.36.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.36.1 - **changed** — Tune partitioned sink_parquet cloud performance - **added** — Allow creation of Object literal - **changed** — Don't collect schema in SQL union processing - **fixed** — Don't invalidate node in cluster-with-columns - **fixed** — Add missing type stubs for bin_slice, bin_head, and bin_tail - **fixed** — Binary slice methods missing from Series and docs - **fixed** — Mix-up of variable_name/value_name in unpivot - **fixed** — Invalid usage of drop_first in to_dummies when nulls present - **changed** — Upgrade to latest version of sqlparser-rs - **fixed** — Update slab to version without RUSTSEC ##### 🚀 Performance improvements - Tune partitioned sink\_parquet cloud performance (#25687) ##### ✨ Enhancements - Allow creation of `Object` literal (#25690) - Don't collect schema in SQL union processing (#25675) ##### 🐞 Bug fixes - Don't invalidate node in cluster-with-columns (#25714) - Move `boto3` extra from s3fs in dev requirements (#25667) - Add missing type stubs for `bin_slice`, `bin_head`, and `bin_tail` (#25697) - Binary slice methods missing from Series and docs (#25683) - Mix-up of variable\_name/value\_name in unpivot (#25685) - Invalid usage of `drop_first` in `to_dummies` when nulls present (#25435) ##### 📖 Documentation - Fix typos in Excel and Pandas migration guides (#25709) - Add "right" to `how` options in `join()` docstrings (#25678) ##### 🛠️ Other improvements - Move Object `lit` fix earlier in the function (#25713) - Remove unused decimal file (#25701) - Move `boto3` extra from s3fs in dev requirements (#25667) - Upgrade to latest version of `sqlparser-rs` (#25673) - Update slab to version without RUSTSEC (#25686) - Fix typo (#25684) Thank you to all our contributors for making this release possible! @AndreaBozzo, @Kevin-Patyk, @alexander-beedie, @dsprenkels, @jamesfricker, @mcrumiller, @nameexhaustion, @orlp and @ritchie46 ### 1.36.0 — Python Polars 1.36.0 - Date: 2025-12-08 - Version: 1.36.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.36.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.36.0 - **added** — Add Extension types - **added** — Add SQL support for the QUALIFY clause - **added** — Add bin.slice(), bin.head(), and bin.tail() methods - **added** — Add SQL syntax support for CROSS JOIN UNNEST(col) - **added** — Add separate env var to log tracked metrics - **added** — Expose fields for generating physical plan visualization data - **added** — Add quantile for missing temporals - **added** — Add strict parameter to pl.concat(how='horizontal') - **added** — Support decimals in search_sorted - **added** — Expose and document pl.Categories - **added** — Extend SQL UNNEST support to handle multiple array expressions - **added** — Add SQL support for ROW_NUMBER, RANK, and DENSE_RANK functions - **added** — Add SQL support for named WINDOW references - **added** — Add leftmost option to str.replace_many / str.find_many / str.extract_many - **added** — Add maintain_order to Expr.mode - **added** — Add empty_as_null and keep_nulls to {Lazy,Data}Frame.explode - **added** — Add empty_as_null and keep_nulls flags to Expr.explode - **added** — Support additional forms of SQL CREATE TABLE statements - **added** — Add support for Float16 dtype - **added** — Add unstable Schema.to_arrow() - **changed** — Allow pl.Object in pivot value - **changed** — Temporal quantile in rolling context - **changed** — Allow elementwise Expr.over in aggregation context - **changed** — Automatically Parquet dictionary encode floats - **changed** — Support unique_counts for all datatypes - **changed** — Allow hash for all List dtypes - **changed** — Allow slice on scalar in aggregation context - **changed** — Allow implode and aggregation in aggregation context - **changed** — Move GraphMetrics into StreamingQuery - **changed** — Allow Expr.unique on List/Array with non-numeric types - **changed** — Allow Expr.rolling in aggregation contexts - **changed** — Allow bare .row() on a single-row DataFrame, equivalent to .item() on a single-element DataFrame - **changed** — Support column-positional SQL UNION operations - **changed** — Make DSL-hash skippable - **changed** — Support arbitrary expressions in SQL JOIN constraints - **changed** — Allow arbitrary expressions as the Expr.rolling index_column - **changed** — Support ewm_var/std in streaming engine - **changed** — Add ignore_nulls to first / last - **changed** — Allow arbitrary Expressions in subset parameter of unique frame method - **changed** — Streaming {Expr,LazyFrame}.rolling - **added** — Add LazyFrame.pivot - **added** — Add SQL support for LEAD and LAG functions - **added** — Add having to group_by context - **added** — Add show methods for DataFrame and LazyFrame - **fixed** — Fix streaming SchemaMismatch panic on list.drop_nulls - **fixed** — Fix panic on Boolean rolling_sum calculation for list or array eval - **fixed** — Fix panic edge-case when scanning hive partitioned data - **fixed** — Fix empty format handling - **fixed** — Improve SQL GROUP BY and ORDER BY expression resolution, handling aliasing edge-cases - **fixed** — Preserve List inner dtype during chunked take operations - **fixed** — Fix spearman panicking on nulls - **fixed** — Properly resolve HAVING clause during SQL GROUP BY operations - **fixed** — Prevent false positives in is_in for large integers - **fixed** — Differentiate between empty list and no list for unpivot - **fixed** — Bug in boolean unique_counts - **fixed** — Hang in multi-chunk DataFrame .rows() 🏆 Highlights - Add Extension types (#25322) ##### ✨ Enhancements - Add SQL support for the QUALIFY clause (#25652) - Add bin.slice(), bin.head(), and bin.tail() methods (#25647) - Add SQL syntax support for CROSS JOIN UNNEST(col) (#25623) - Add separate env var to log tracked metrics (#25586) - Expose fields for generating physical plan visualization data (#25562) - Allow pl.Object in pivot value (#25533) - Minor improvement for as_struct repr (#25529) - Temporal quantile in rolling context (#25479) - Add quantile for missing temporals (#25464) - Add strict parameter to pl.concat(how='horizontal') (#25452) - Support decimals in search_sorted (#25450) - Expose and document pl.Categories (#25443) - Use reference to Graph pipes when flushing metrics (#25442) - Extend SQL UNNEST support to handle multiple array expressions (#25418) - Add SQL support for ROW_NUMBER, RANK, and DENSE_RANK functions (#25409) - Allow elementwise Expr.over in aggregation context (#25402) - Add SQL support for named WINDOW references (#25400) - Add leftmost option to str.replace_many / str.find_many / str.extract_many (#25398) - Automatically Parquet dictionary encode floats (#25387) - Support unique_counts for all datatypes (#25379) - Add maintain_order to Expr.mode (#25377) - Allow hash for all List dtypes (#25372) - Add empty_as_null and keep_nulls to {Lazy,Data}Frame.explode (#25369) - Display function of streaming physical plan map node (#25368) - Allow slice on scalar in aggregation context (#25358) - Allow implode and aggregation in aggregation context (#25357) - Move GraphMetrics into StreamingQuery (#25310) - Documentation on Polars Cloud manifests (#25295) - Add empty_as_null and keep_nulls flags to Expr.explode (#25289) - Allow Expr.unique on List/Array with non-numeric types (#25285) - Raise suitable error on non-integer "n" value for clear (#25266) - Allow Expr.rolling in aggregation contexts (#25258) - Allow bare .row() on a single-row DataFrame, equivalent to .item() on a single-element DataFrame (#25229) - Support additional forms of SQL CREATE TABLE statements (#25191) - Add support for Float16 dtype (#25185) - Support column-positional SQL "UNION" operations (#25183) - Add unstable `Schema.to_arrow()` (#25149) - Make DSL-hash skippable (#25140) - Improve error message on unsupported SQL subquery comparisons (#25135) - Support arbitrary expressions in SQL `JOIN` constraints (#25132) - Allow arbitrary expressions as the `Expr.rolling` `index_column` (#25117) - Set polars/ user-agent (#25112) - Support `ewm_var/std` in streaming engine (#25109) - Rewrite `IR::Scan` to `IR::DataFrameScan` in `expand_datasets` when applicable (#25106) - Add ignore_nulls to first / last (#25105) - Allow arbitrary Expressions in "subset" parameter of `unique` frame method (#25099) - Add `BIT_NOT` support to the SQL interface (#25094) - Streaming `{Expr,LazyFrame}.rolling` (#25058) - Add LazyFrame.pivot (#25016) - Add SQL support for `LEAD` and `LAG` functions (#23956) - Add having to group_by context (#23550) - Add show methods for DataFrame and LazyFrame (#19634) ##### 🚀 Performance improvements - Set parallelization threshold in `take_unchecked_impl` (#25672) - New single file IO sink pipeline enabled for sink_parquet (#25670) - Correct overly eager local predicate insertion for unpivot (#25644) - New partitioned IO sink pipeline enabled for sink_parquet (#25629) - Use strong hash instead of traversal for CSPE equality (#25537) - Reduce HuggingFace API calls (#25521) - Fix panic in is_between support in streaming Parquet predicate push down (#25476) - Faster kernels for rle_lengths (#25448) - Mark output of more non-order-maintaining ops as unordered (#25419) - Enable predicate expressions on unsigned integers (#25416) - Allow detecting plan sortedness in more cases (#25408) - Add parquet prefiltering for string regexes (#25381) - Fast find start window in group_by_dynamic _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.36.0]_ ### 1.36.0-beta.2 — Python Polars 1.36.0-beta.2 - Date: 2025-12-02 - Version: 1.36.0-beta.2 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.36.0-beta.2 - Permalink: https://whatsnew.fyi/product/polars/releases/1.36.0-beta.2 - Labels: Pre-release - **added** — Add Extension types - **added** — Add SQL support for ROW_NUMBER, RANK, and DENSE_RANK functions - **added** — Add SQL support for named WINDOW references - **added** — Add BIT_NOT support to the SQL interface - **added** — Add LazyFrame.pivot - **added** — Add allow_empty flag to item - **added** — Add empty_as_null and keep_nulls flags to Expr.explode - **added** — Add empty_as_null and keep_nulls to {Lazy,Data}Frame.explode - **added** — Add having to group_by context - **added** — Add ignore_nulls to first / last - **added** — Add maintain_order to Expr.mode - **added** — Add quantile for missing temporals - **added** — Add leftmost option to str.replace_many / str.find_many / str.extract_many - **added** — Add strict parameter to pl.concat(how='horizontal') - **added** — Add support for Float16 dtype - **added** — Add unstable Schema.to_arrow - **changed** — Allow Expr.rolling in aggregation contexts - **changed** — Allow Expr.unique on List/Array with non-numeric types - **changed** — Allow glimpse to return a DataFrame - **changed** — Allow hash for all List dtypes ##### 🏆 Highlights - Add Extension types (#25322) ##### ✨ Enhancements - Add SQL support for `ROW_NUMBER`, `RANK`, and `DENSE_RANK` functions (#25409) - Add SQL support for named `WINDOW` references (#25400) - Add `BIT_NOT` support to the SQL interface (#25094) - Add `LazyFrame.pivot` (#25016) - Add `allow_empty` flag to `item` (#25048) - Add `empty_as_null` and `keep_nulls` flags to `Expr.explode` (#25289) - Add `empty_as_null` and `keep_nulls` to `{Lazy,Data}Frame.explode` (#25369) - Add `having` to `group_by` context (#23550) - Add `ignore_nulls` to `first` / `last` (#25105) - Add `maintain_order` to `Expr.mode` (#25377) - Add `quantile` for missing temporals (#25464) - Add leftmost option to `str.replace_many / str.find_many / str.extract_many` (#25398) - Add strict parameter to pl.concat(how='horizontal') (#25452) - Add support for `Float16` dtype (#25185) - Add unstable `Schema.to_arrow` (#25149) - Allow `Expr.rolling` in aggregation contexts (#25258) - Allow `Expr.unique` on `List`/`Array` with non-numeric types (#25285) - Allow `glimpse` to return a `DataFrame` (#24803) - Allow `hash` for all `List` dtypes (#25372) - Allow `implode` and aggregation in aggregation context (#25357) - Allow `slice` on scalar in aggregation context (#25358) - Allow arbitrary Expressions in "subset" parameter of `unique` frame method (#25099) - Allow arbitrary expressions as the `Expr.rolling` `index_column` (#25117) - Allow bare `.row` on a single-row DataFrame, equivalent to `.item` on a single-element DataFrame (#25229) - Allow elementwise `Expr.over` in aggregation context (#25402) - Allow pl.Object in pivot value (#25533) - Automatically Parquet dictionary encode floats (#25387) - Display function of streaming physical plan `map` node (#25368) - Documentation on Polars Cloud manifests (#25295) - Expose and document pl.Categories (#25443) - Expose fields for generating physical plan visualization data (#25562) - Extend SQL `UNNEST` support to handle multiple array expressions (#25418) - Improve SQL `UNNEST` behaviour (#22546) - Improve error message on unsupported SQL subquery comparisons (#25135) - Make DSL-hash skippable (#25140) - Minor improvement for `as_struct` repr (#25529) - Move GraphMetrics into StreamingQuery (#25310) - Raise suitable error on non-integer "n" value for `clear` (#25266) - Rewrite `IR::Scan` to `IR::DataFrameScan` in `expand_datasets` when applicable (#25106) - Set polars/ user-agent (#25112) - Streaming `{Expr,LazyFrame}.rolling` (#25058) - Support BYTE_ARRAY backed Decimals in Parquet (#25076) - Support `ewm_var/std` in streaming engine (#25109) - Support `unique_counts` for all datatypes (#25379) - Support additional forms of SQL "CREATE TABLE" statements (#25191) - Support arbitrary expressions in SQL `JOIN` constraints (#25132) - Support column-positional SQL "UNION" operations (#25183) - Support decimals in search_sorted (#25450) - Temporal `quantile` in rolling context (#25479) - Use reference to Graph pipes when flushing metrics (#25442) ##### 🚀 Performance improvements - Add parquet prefiltering for string regexes (#25381) - Add streaming native `LazyFrame.group_by_dynamic` (#25342) - Add streaming sorted Group-By (#25013) - Allow detecting plan sortedness in more cases (#25408) - Don't recompute full rolling moment window when NaNs/nulls leave the window (#25078) - Enable predicate expressions on unsigned integers (#25416) - Fast find start window in `group_by_dynamic` with large `offset` (#25376) - Faster kernels for rle_lengths (#25448) - Fuse positive `slice` into streaming `LazyFrame.rolling` (#25338) - Lazy gather for `{forward,backward}_fill` in group-by contexts (#25115) - Mark `Expr.reshape((-1,))` as row separable (#25326) - Mark output of more non-order-maintaining ops as unordered (#25419) - Optimize ipc stream read performance (#24671) - Reduce HuggingFace API calls (#25521) - Return references from `a _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.36.0-beta.2]_ ### 1.35.2 — Python Polars 1.35.2 - Date: 2025-11-09 - Version: 1.35.2 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.35.2 - Permalink: https://whatsnew.fyi/product/polars/releases/1.35.2 - **fixed** — Fix incorrect drop_nans() result when used in group_by() / over() - **fixed** — Fix handling Null dtype in ApplyExpr on group_by - **fixed** — Fix assertion panic on group_by - **fixed** — Fix wide-table join performance regression * Fix incorrect `drop_nans()` result when used in `group_by()` / `over()` (https://github.com/pola-rs/polars/pull/25146) * Fix handling `Null` dtype in `ApplyExpr` on `group_by`(https://github.com/pola-rs/polars/pull/25077) * Fix assertion panic on `group_by` (https://github.com/pola-rs/polars/pull/25179) * Fix Wide-table join performance regression (https://github.com/pola-rs/polars/pull/25222) Thank you to all our contributors for making this release possible! @coastalwhite, @kdn36, @nameexhaustion and @ritchie46 ### 1.35.1 — Python Polars 1.35.1 - Date: 2025-10-30 - Version: 1.35.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.35.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.35.1 - **changed** — Don't recompute full rolling moment window when NaNs/nulls leave the window - **changed** — Skip filtering scan IR if no paths were filtered - **changed** — Optimize ipc stream read performance - **added** — Support BYTE_ARRAY backed Decimals in Parquet - **changed** — Allow glimpse to return a DataFrame - **added** — Add allow_empty flag to item - **fixed** — The SQL interface should use logical, not bitwise, behaviour for unary NOT operator - **fixed** — Fix panic if scan predicate produces 0 length mask - **fixed** — Ensure SQL table alias resolution checks against CTE aliases on fallback - **fixed** — Fix panic in group_by_dynamic with group_by and multiple chunks - **fixed** — Fix panic when using struct field as join key - **fixed** — Allow broadcast in group_by for ApplyExpr and BinaryExpr - **fixed** — Fix field metadata for nested categorical PyCapsule export - **fixed** — Block predicate pushdown when group_by key values are changed - **fixed** — Fix group-by aggregation problems caused by AmortSeries - **fixed** — Don't push down predicates passed inserted cache nodes - **fixed** — Allow for negative time in group_by_dynamic iterator - **changed** — Change group length mismatch error to ShapeError ##### 🚀 Performance improvements - Don't recompute full rolling moment window when NaNs/nulls leave the window (#25078) - Skip filtering scan IR if no paths were filtered (#25037) - Optimize ipc stream read performance (#24671) ##### ✨ Enhancements - Support BYTE\_ARRAY backed Decimals in Parquet (#25076) - Allow `glimpse` to return a `DataFrame` (#24803) - Add `allow_empty` flag to `item` (#25048) ##### 🐞 Bug fixes - The `SQL` interface should use logical, not bitwise, behaviour for unary "NOT" operator (#25091) - Fix panic if scan predicate produces 0 length mask (#25089) - Ensure SQL table alias resolution checks against CTE aliases on fallback (#25071) - Panic in `group_by_dynamic` with `group_by` and multiple chunks (#25075) - Minor improvement to internal `is_pycapsule` utility function (#25073) - Fix panic when using struct field as join key (#25059) - Allow broadcast in `group_by` for `ApplyExpr` and `BinaryExpr` (#25053) - Fix field metadata for nested categorical PyCapsule export (#25052) - Block predicate pushdown when `group_by` key values are changed (#25032) - Group-By aggregation problems caused by `AmortSeries` (#25043) - Don't push down predicates passed inserted cache nodes (#25042) - Allow for negative time in `group_by_dynamic` iterator (#25041) ##### 📖 Documentation - Fix typo in public dataset URL (#25044) ##### 🛠️ Other improvements - Disable recursive CSPE for now (#25085) - Change group length mismatch error to `ShapeError` (#25004) - Update toolchain (#25007) Thank you to all our contributors for making this release possible! @Kevin-Patyk, @Liyixin95, @alexander-beedie, @coastalwhite, @kdn36, @nameexhaustion, @orlp, @r-brink, @ritchie46 and @stijnherfst ### 1.35.0 — Python Polars 1.35.0 - Date: 2025-10-26 - Version: 1.35.0 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.35.0 - Permalink: https://whatsnew.fyi/product/polars/releases/1.35.0 - **added** — Add Expr.item to strictly extract a single value from an expression - **added** — Add list.agg and arr.agg - **added** — Implement {Expr,Series}.rolling_rank() - **added** — Add arr.eval - **added** — Add union() function for unordered concatenation - **added** — Add name.replace to the set of column rename options - **added** — Add separator to {Data,Lazy}Frame.unnest - **added** — Add glob parameter to scan_ipc - **added** — Add environment variable to roundtrip empty struct in Parquet - **added** — Add streaming engine per-node metrics - **added** — Add support for UInt128 to pyo3-polars - **changed** — Stabilize decimal - **changed** — Support ewm_mean() in streaming engine - **changed** — Allow local scans on polars cloud (configurable) - **changed** — Support MergeSorted in CSPE - **changed** — Make Series init consistent with DataFrame init for string values declared with temporal dtype - **changed** — Improve rolling_(sum|mean) accuracy - **changed** — Allow duration strings with leading "+" - **changed** — Support np.ndarray -> AnyValue conversion - **fixed** — Fix incorrect join_asof on a casted expression ##### 🏆 Highlights - Stabilize decimal (#25020) ##### 🚀 Performance improvements - Bump foldhash to 0.2.0 and hashbrown to 0.16.0 (#25014) - Lower `unique` to native group-by and speed up `n_unique` in group-by context (#24976) - Better parallelize `take{_slice,}_unchecked` (#24980) - Implement native `skew` and `kurtosis` in group-by context (#24961) - Use native group-by aggregations for `bitwise_*` operations (#24935) - Address `group_by_dynamic` slowness in sparse data (#24916) - Push filters to PyIceberg (#24910) - Native `filter/drop_nulls/drop_nans` in group-by context (#24897) - Implement `cumulative_eval` using the group-by engine (#24889) - Prevent generation of copies of `Dataframe`s in `DslPlan` serialization (#24852) - Implement native `null_count`, `any` and `all` group-by aggregations (#24859) - Speed up `reverse` in group-by context (#24855) - Prune unused categorical values when exporting to arrow/parquet/IPC/pickle (#24829) - Don't check duplicates on streaming simple projection in release mode (#24830) - Lower approx\_n\_unique to the streaming engine (#24821) - Duration/interval string parsing optimisation (2-5x faster) (#24771) - Use native reducer for `first/last` on Decimals, Categoricals and Enums (#24786) - Implement indexed method for `BitMapIter::nth` (#24766) - Pushdown slices on plans within unions (#24735) ##### ✨ Enhancements - Stabilize decimal (#25020) - Support `ewm_mean()` in streaming engine (#25003) - Improve row-count estimates (#24996) - Remove filtered scan paths in IR when possible (#24974) - Introduce remote Polars MCP server (#24977) - Allow local scans on polars cloud (configurable) (#24962) - Add `Expr.item` to strictly extract a single value from an expression (#24888) - Add environment variable to roundtrip empty struct in Parquet (#24914) - Fast-count for `scan_iceberg().select(len())` (#24602) - Add `glob` parameter to `scan_ipc` (#24898) - Prevent generation of copies of `Dataframe`s in `DslPlan` serialization (#24852) - Add `list.agg` and `arr.agg` (#24790) - Implement `{Expr,Series}.rolling_rank()` (#24776) - Don't require PyArrow for `read_database_uri` if ADBC engine version supports PyCapsule interface (#24029) - Make `Series` init consistent with `DataFrame` init for string values declared with temporal dtype (#24785) - Support MergeSorted in CSPE (#24805) - Duration/interval string parsing optimisation (2-5x faster) (#24771) - Recursively apply CSPE (#24798) - Add streaming engine per-node metrics (#24788) - Add `arr.eval` (#24472) - Drop PyArrow requirement for non-batched usage of `read_database` with the ADBC engine and support `iter_batches` with the ADBC engine (#24180) - Improve rolling\_(sum|mean) accuracy (#24743) - Add `separator` to `{Data,Lazy}Frame.unnest` (#24716) - Add `union()` function for unordered concatenation (#24298) - Add `name.replace` to the set of column rename options (#17942) - Support `np.ndarray -> AnyValue` conversion (#24748) - Allow duration strings with leading "+" (#24737) - Drop now-unnecessary post-init "schema\_overrides" cast on `DataFrame` load from list of dicts (#24739) - Add support for UInt128 to pyo3-polars (#24731) ##### 🐞 Bug fixes - Re-enable CPU feature check before import (#25010) - Implement `read_excel` workaround for fastexcel/calamine issue loading a column subset from a named table (#25012) - Correctness `any(ignore_nulls)` and OOB in `all` (#25005) - Streaming any/all with ignore\_nulls=False (#25008) - Fix incorrect `join_asof` on a casted expression (#25006) - Optimize memory on rolling groups in `ApplyExpr` (#24709) - Fallback `Pyarrow` scan to in-memory engine (#24991) - Make `Operator::swap_operands` return correct operators for `Plus`, `Minus`, `Multiply` and `Divide` (#24997) - Capitalize letters after numbers in to\_titlecase (#24993) - Preserve null values in `pct_change` (#24952) - Raise length mismatch on `over` with sliced groups (#24887) - Check duplicate name in transpose (#24956) - Follow Kle _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.35.0]_ ### 1.35.0-beta.1 — Python Polars 1.35.0-beta.1 - Date: 2025-10-19 - Version: 1.35.0-beta.1 - Original notes: https://github.com/pola-rs/polars/releases/tag/py-1.35.0-beta.1 - Permalink: https://whatsnew.fyi/product/polars/releases/1.35.0-beta.1 - Labels: Pre-release - **changed** — Address group_by_dynamic slowness in sparse data - **changed** — Push filters to PyIceberg - **changed** — Implement native filter/drop_nulls/drop_nans in group-by context - **changed** — Implement cumulative_eval using the group-by engine - **changed** — Prevent generation of copies of Dataframes in DslPlan serialization - **changed** — Implement native null_count, any and all group-by aggregations - **changed** — Speed up reverse in group-by context - **changed** — Prune unused categorical values when exporting to arrow/parquet/IPC/pickle - **changed** — Lower approx_n_unique to the streaming engine - **changed** — Duration/interval string parsing is 2-5x faster - **changed** — Use native reducer for first/last on Decimals, Categoricals and Enums - **added** — Add environment variable to roundtrip empty struct in Parquet - **added** — Add glob parameter to scan_ipc - **added** — Add list.agg and arr.agg - **added** — Implement {Expr,Series}.rolling_rank() - **added** — Add arr.eval - **added** — Add separator to {Data,Lazy}Frame.unnest - **added** — Add union() function for unordered concatenation - **added** — Add name.replace to the set of column rename options - **fixed** — Fix repeated with_row_index() after scan() silently ignored ##### 🚀 Performance improvements - Address `group_by_dynamic` slowness in sparse data (#24916) - Push filters to PyIceberg (#24910) - Native `filter/drop_nulls/drop_nans` in group-by context (#24897) - Implement `cumulative_eval` using the group-by engine (#24889) - Prevent generation of copies of `Dataframe`s in `DslPlan` serialization (#24852) - Implement native `null_count`, `any` and `all` group-by aggregations (#24859) - Speed up `reverse` in group-by context (#24855) - Prune unused categorical values when exporting to arrow/parquet/IPC/pickle (#24829) - Don't check duplicates on streaming simple projection in release mode (#24830) - Lower approx\_n\_unique to the streaming engine (#24821) - Duration/interval string parsing optimisation (2-5x faster) (#24771) - Use native reducer for `first/last` on Decimals, Categoricals and Enums (#24786) - Implement indexed method for `BitMapIter::nth` (#24766) - Pushdown slices on plans within unions (#24735) ##### ✨ Enhancements - Add environment variable to roundtrip empty struct in Parquet (#24914) - Fast-count for `scan_iceberg().select(len())` (#24602) - Add `glob` parameter to `scan_ipc` (#24898) - Prevent generation of copies of `Dataframe`s in `DslPlan` serialization (#24852) - Add `list.agg` and `arr.agg` (#24790) - Implement `{Expr,Series}.rolling_rank()` (#24776) - Don't require PyArrow for `read_database_uri` if ADBC engine version supports PyCapsule interface (#24029) - Make `Series` init consistent with `DataFrame` init for string values declared with temporal dtype (#24785) - Support MergeSorted in CSPE (#24805) - Duration/interval string parsing optimisation (2-5x faster) (#24771) - Recursively apply CSPE (#24798) - Add streaming engine per-node metrics (#24788) - Add `arr.eval` (#24472) - Drop PyArrow requirement for non-batched usage of `read_database` with the ADBC engine and support `iter_batches` with the ADBC engine (#24180) - Improve rolling\_(sum|mean) accuracy (#24743) - Add `separator` to `{Data,Lazy}Frame.unnest` (#24716) - Add `union()` function for unordered concatenation (#24298) - Add `name.replace` to the set of column rename options (#17942) - Support `np.ndarray -> AnyValue` conversion (#24748) - Allow duration strings with leading "+" (#24737) - Drop now-unnecessary post-init "schema\_overrides" cast on `DataFrame` load from list of dicts (#24739) - Add support for UInt128 to pyo3-polars (#24731) ##### 🐞 Bug fixes - Properly release the GIL for `read_parquet_metadata` (#24922) - Broadcast `partition_by` columns in `over` expression (#24874) - Clear index cache on stacked `df.filter` expressions (#24870) - Fix 'explode' mapping strategy on scalar value (#24861) - Fix repeated `with_row_index()` after `scan()` silently ignored (#24866) - Correctly return min and max for enums in groupby aggregation (#24808) - Refactor `BinaryExpr` in `group_by` dispatch logic (#24548) - Fix aggstate for `gather` (#24857) - Keep scalars for length preserving functions in `group_by` (#24819) - Have `range` feature depend on `dtype-array` feature (#24853) - Fix duplicate select panic (#24836) - Inconsistency of list.sum() result type with None values (#24476) - Division by zero in Expr.dt.truncate (#24832) - Potential deadlock in \_\_arrow\_c\_stream\_\_ (#24831) - Allow double aggregations in group-by contexts (#24823) - Series.shrink\_dtype for i128/u128 (#24833) - Fix dtype in `EvalExpr` (#24650) - Allow aggregations on `AggState::LiteralScalar` (#24820) - Dispatch to `group_aware` for fallible expressions with masked out elements (#24815) - Fix error for `arr.sum()` on small integer Array dtypes containing nulls (#24478) - Fix regression on `write_database()` to Snowflake due to unsupported string view type (#24622) - Fix XOR did not follow kleene when one side is unit-length (#24810) - Make `Series` init consistent with `DataFrame` init for string values declared with temporal dtype (#24785) - Incorrect precision in Series.str.to\_decimal (#24804) - Use `overl _[Truncated at 4000 characters — full notes: https://github.com/pola-rs/polars/releases/tag/py-1.35.0-beta.1]_