Skip to content

Commit 64d3415

Browse files
committed
Rename Window to WindowExpr so we can define Window to mean a window definition to be reused
1 parent d50aacf commit 64d3415

File tree

6 files changed

+56
-37
lines changed

6 files changed

+56
-37
lines changed

python/datafusion/expr.py

+34-16
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
Union = expr_internal.Union
9393
Unnest = expr_internal.Unnest
9494
UnnestExpr = expr_internal.UnnestExpr
95-
Window = expr_internal.Window
95+
WindowExpr = expr_internal.WindowExpr
9696

9797
__all__ = [
9898
"Expr",
@@ -154,6 +154,7 @@
154154
"Partitioning",
155155
"Repartition",
156156
"Window",
157+
"WindowExpr",
157158
"WindowFrame",
158159
"WindowFrameBound",
159160
]
@@ -542,32 +543,25 @@ def window_frame(self, window_frame: WindowFrame) -> ExprFuncBuilder:
542543
"""
543544
return ExprFuncBuilder(self.expr.window_frame(window_frame.window_frame))
544545

545-
def over(
546-
self,
547-
partition_by: Optional[list[Expr]] = None,
548-
window_frame: Optional[WindowFrame] = None,
549-
order_by: Optional[list[SortExpr | Expr]] = None,
550-
null_treatment: Optional[NullTreatment] = None,
551-
) -> Expr:
546+
def over(self, window: Window) -> Expr:
552547
"""Turn an aggregate function into a window function.
553548
554549
This function turns any aggregate function into a window function. With the
555550
exception of ``partition_by``, how each of the parameters is used is determined
556551
by the underlying aggregate function.
557552
558553
Args:
559-
partition_by: Expressions to partition the window frame on
560-
window_frame: Specify the window frame parameters
561-
order_by: Set ordering within the window frame
562-
null_treatment: Set how to handle null values
554+
window: Window definition
563555
"""
564-
partition_by_raw = expr_list_to_raw_expr_list(partition_by)
565-
order_by_raw = sort_list_to_raw_sort_list(order_by)
556+
partition_by_raw = expr_list_to_raw_expr_list(window._partition_by)
557+
order_by_raw = sort_list_to_raw_sort_list(window._order_by)
566558
window_frame_raw = (
567-
window_frame.window_frame if window_frame is not None else None
559+
window._window_frame.window_frame
560+
if window._window_frame is not None
561+
else None
568562
)
569563
null_treatment_raw = (
570-
null_treatment.value if null_treatment is not None else None
564+
window._null_treatment.value if window._null_treatment is not None else None
571565
)
572566

573567
return Expr(
@@ -621,6 +615,30 @@ def build(self) -> Expr:
621615
return Expr(self.builder.build())
622616

623617

618+
class Window:
619+
"""Define reusable window parameters."""
620+
621+
def __init__(
622+
self,
623+
partition_by: Optional[list[Expr]] = None,
624+
window_frame: Optional[WindowFrame] = None,
625+
order_by: Optional[list[SortExpr | Expr]] = None,
626+
null_treatment: Optional[NullTreatment] = None,
627+
) -> None:
628+
"""Construct a window definition.
629+
630+
Args:
631+
partition_by: Partitions for window operation
632+
window_frame: Define the start and end bounds of the window frame
633+
order_by: Set ordering
634+
null_treatment: Indicate how nulls are to be treated
635+
"""
636+
self._partition_by = partition_by
637+
self._window_frame = window_frame
638+
self._order_by = order_by
639+
self._null_treatment = null_treatment
640+
641+
624642
class WindowFrame:
625643
"""Defines a window frame for performing window operations."""
626644

python/datafusion/tests/test_dataframe.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
literal,
3232
udf,
3333
)
34+
from datafusion.expr import Window
3435

3536

3637
@pytest.fixture
@@ -389,27 +390,29 @@ def test_distinct():
389390
(
390391
"first_value",
391392
f.first_value(column("a")).over(
392-
partition_by=[column("c")], order_by=[column("b")]
393+
Window(partition_by=[column("c")], order_by=[column("b")])
393394
),
394395
[1, 1, 1, 1, 5, 5, 5],
395396
),
396397
(
397398
"last_value",
398399
f.last_value(column("a")).over(
399-
partition_by=[column("c")],
400-
order_by=[column("b")],
401-
window_frame=WindowFrame("rows", None, None),
400+
Window(
401+
partition_by=[column("c")],
402+
order_by=[column("b")],
403+
window_frame=WindowFrame("rows", None, None),
404+
)
402405
),
403406
[3, 3, 3, 3, 6, 6, 6],
404407
),
405408
(
406409
"3rd_value",
407-
f.nth_value(column("b"), 3).over(order_by=[column("a")]),
410+
f.nth_value(column("b"), 3).over(Window(order_by=[column("a")])),
408411
[None, None, 7, 7, 7, 7, 7],
409412
),
410413
(
411414
"avg",
412-
f.round(f.avg(column("b")).over(order_by=[column("a")]), literal(3)),
415+
f.round(f.avg(column("b")).over(Window(order_by=[column("a")])), literal(3)),
413416
[7.0, 7.0, 7.0, 7.333, 7.75, 7.75, 8.0],
414417
),
415418
]

src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ pub(crate) fn init_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
791791
m.add_class::<drop_table::PyDropTable>()?;
792792
m.add_class::<repartition::PyPartitioning>()?;
793793
m.add_class::<repartition::PyRepartition>()?;
794-
m.add_class::<window::PyWindow>()?;
794+
m.add_class::<window::PyWindowExpr>()?;
795795
m.add_class::<window::PyWindowFrame>()?;
796796
m.add_class::<window::PyWindowFrameBound>()?;
797797
Ok(())

src/expr/window.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ use super::py_expr_list;
3232

3333
use crate::errors::py_datafusion_err;
3434

35-
#[pyclass(name = "Window", module = "datafusion.expr", subclass)]
35+
#[pyclass(name = "WindowExpr", module = "datafusion.expr", subclass)]
3636
#[derive(Clone)]
37-
pub struct PyWindow {
37+
pub struct PyWindowExpr {
3838
window: Window,
3939
}
4040

@@ -62,15 +62,15 @@ pub struct PyWindowFrameBound {
6262
frame_bound: WindowFrameBound,
6363
}
6464

65-
impl From<PyWindow> for Window {
66-
fn from(window: PyWindow) -> Window {
65+
impl From<PyWindowExpr> for Window {
66+
fn from(window: PyWindowExpr) -> Window {
6767
window.window
6868
}
6969
}
7070

71-
impl From<Window> for PyWindow {
72-
fn from(window: Window) -> PyWindow {
73-
PyWindow { window }
71+
impl From<Window> for PyWindowExpr {
72+
fn from(window: Window) -> PyWindowExpr {
73+
PyWindowExpr { window }
7474
}
7575
}
7676

@@ -80,7 +80,7 @@ impl From<WindowFrameBound> for PyWindowFrameBound {
8080
}
8181
}
8282

83-
impl Display for PyWindow {
83+
impl Display for PyWindowExpr {
8484
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
8585
write!(
8686
f,
@@ -103,7 +103,7 @@ impl Display for PyWindowFrame {
103103
}
104104

105105
#[pymethods]
106-
impl PyWindow {
106+
impl PyWindowExpr {
107107
/// Returns the schema of the Window
108108
pub fn schema(&self) -> PyResult<PyDFSchema> {
109109
Ok(self.window.schema.as_ref().clone().into())
@@ -283,7 +283,7 @@ impl PyWindowFrameBound {
283283
}
284284
}
285285

286-
impl LogicalNode for PyWindow {
286+
impl LogicalNode for PyWindowExpr {
287287
fn inputs(&self) -> Vec<PyLogicalPlan> {
288288
vec![self.window.input.as_ref().clone().into()]
289289
}

src/functions.rs

-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use std::ptr::null;
19-
2018
use datafusion::functions_aggregate::all_default_aggregate_functions;
2119
use datafusion::logical_expr::window_function;
2220
use datafusion::logical_expr::ExprFunctionExt;

src/sql/logical.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::expr::subquery::PySubquery;
3434
use crate::expr::subquery_alias::PySubqueryAlias;
3535
use crate::expr::table_scan::PyTableScan;
3636
use crate::expr::unnest::PyUnnest;
37-
use crate::expr::window::PyWindow;
37+
use crate::expr::window::PyWindowExpr;
3838
use datafusion::logical_expr::LogicalPlan;
3939
use pyo3::prelude::*;
4040

@@ -80,7 +80,7 @@ impl PyLogicalPlan {
8080
LogicalPlan::Subquery(plan) => PySubquery::from(plan.clone()).to_variant(py),
8181
LogicalPlan::SubqueryAlias(plan) => PySubqueryAlias::from(plan.clone()).to_variant(py),
8282
LogicalPlan::Unnest(plan) => PyUnnest::from(plan.clone()).to_variant(py),
83-
LogicalPlan::Window(plan) => PyWindow::from(plan.clone()).to_variant(py),
83+
LogicalPlan::Window(plan) => PyWindowExpr::from(plan.clone()).to_variant(py),
8484
LogicalPlan::Repartition(_)
8585
| LogicalPlan::Union(_)
8686
| LogicalPlan::Statement(_)

0 commit comments

Comments
 (0)