From ddd1b0ed15fd6274d8b55d8cfc647a4751f89829 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 15:19:05 +0000 Subject: [PATCH] Refactor Session.col to standalone leanframe.col Moved `col` method from `Session` to `leanframe/core/expression.py` as a standalone function. Exposed `col` as an alias in `leanframe/__init__.py` and `Session.col` as a static method for backward compatibility. Added unit tests to verify standalone, static, and instance usage. Co-authored-by: tswast <247555+tswast@users.noreply.github.com> --- leanframe/__init__.py | 2 ++ leanframe/core/expression.py | 6 +++++ leanframe/core/session.py | 7 ++--- tests/unit/test_expression_col.py | 44 +++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/unit/test_expression_col.py diff --git a/leanframe/__init__.py b/leanframe/__init__.py index ec66097..6ccc15b 100644 --- a/leanframe/__init__.py +++ b/leanframe/__init__.py @@ -15,6 +15,7 @@ """LeanFrame provides a DataFrame API for BigQuery.""" from leanframe.core.session import Session +from leanframe.core.expression import col from leanframe.core.frame import DataFrameHandler from leanframe.core.nested_handler import NestedHandler from leanframe.version import __version__ @@ -22,6 +23,7 @@ __all__ = [ "__version__", "Session", + "col", "DataFrameHandler", "NestedHandler", ] diff --git a/leanframe/core/expression.py b/leanframe/core/expression.py index 0192255..a80c284 100644 --- a/leanframe/core/expression.py +++ b/leanframe/core/expression.py @@ -16,9 +16,15 @@ from __future__ import annotations +import ibis import ibis.expr.types as ibis_types +def col(name: str) -> Expression: + """Return a new expression object which is a deferred series.""" + return Expression(ibis.deferred[name]) + + class Expression: """A wrapper around an Ibis expression for deferred computation.""" diff --git a/leanframe/core/session.py b/leanframe/core/session.py index 5dee5c6..2f323de 100644 --- a/leanframe/core/session.py +++ b/leanframe/core/session.py @@ -22,6 +22,7 @@ import ibis.expr.types as ibis_types import pandas +from leanframe.core.expression import col _ALPHABET = "abcdefghijklmnopqrstufwxyz" @@ -67,8 +68,4 @@ def DataFrame(self, data: ibis_types.Table | pandas.DataFrame): f"DataFrame constructor doesn't support {type(data)} data yet." ) - def col(self, name: str): - """Return a new expression object which is a deferred series.""" - import leanframe.core.expression - - return leanframe.core.expression.Expression(ibis.deferred[name]) + col = staticmethod(col) diff --git a/tests/unit/test_expression_col.py b/tests/unit/test_expression_col.py new file mode 100644 index 0000000..81759fa --- /dev/null +++ b/tests/unit/test_expression_col.py @@ -0,0 +1,44 @@ +# Copyright 2025 Google LLC, LeanFrame Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for standalone col and aliases.""" + +import ibis +import leanframe +from leanframe.core.session import Session +from leanframe.core.expression import Expression, col + +def test_col_standalone(): + """Verify col() works as a standalone function.""" + expr = col('a') + assert isinstance(expr, Expression) + +def test_col_session_static(): + """Verify Session.col() works as a static method.""" + expr = Session.col('a') + assert isinstance(expr, Expression) + +def test_col_session_instance(): + """Verify session.col() works as an instance method (compatibility).""" + # Use sqlite backend as dummy + backend = ibis.sqlite.connect() + session = Session(backend) + + expr = session.col('a') + assert isinstance(expr, Expression) + +def test_col_package_alias(): + """Verify leanframe.col is available.""" + expr = leanframe.col('a') + assert isinstance(expr, Expression)