Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ tower = "tower.cli:main"

[project.optional-dependencies]
ai = ["huggingface-hub>=0.34.3", "ollama>=0.5.3"]
iceberg = ["polars==1.27.1", "pyarrow==19.0.1", "pyiceberg==0.9.1"]
iceberg = ["polars>=1.39.3", "pyarrow>=23.0.1", "pyiceberg>=0.11.1"]
dbt = ["dbt-core>=1.9,<1.10"] # Can not use dbt 1.10+ due to dependency conflicts
all = ["tower[ai,iceberg,dbt]"]

Expand Down Expand Up @@ -102,5 +102,5 @@ dev = [
"mypy==1.13.0",
"openapi-python-client==0.28.1",
"pre-commit==4.0.1",
"pyiceberg[sql-sqlite]==0.9.1",
"pyiceberg[sql-sqlite]>=0.11.1",
]
8 changes: 6 additions & 2 deletions src/tower/_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ def read(self) -> pl.DataFrame:
"""
# We call `collect` here to force the execution of the query and get
# the result as a DataFrame.
return pl.scan_iceberg(self._table).collect()
# Note: reader_override="pyiceberg" ensures AWS S3 vended credentials are passed through
# properly. The native rust reader is faster but doesn't pass credentials from pyiceberg.
return pl.scan_iceberg(self._table, reader_override="pyiceberg").collect()

def to_polars(self) -> pl.LazyFrame:
"""
Expand Down Expand Up @@ -121,7 +123,9 @@ def to_polars(self) -> pl.LazyFrame:
>>> # Execute the plan
>>> final_df = result.collect()
"""
return pl.scan_iceberg(self._table)
# Note: reader_override="pyiceberg" ensures AWS S3 vended credentials are passed through
# properly. The native rust reader is faster but doesn't pass credentials from pyiceberg.
return pl.scan_iceberg(self._table, reader_override="pyiceberg")

def rows_affected(self) -> RowsAffectedInformation:
"""
Expand Down
11 changes: 8 additions & 3 deletions tests/tower/test_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,10 +491,11 @@ def test_nested_structs(in_memory_catalog):
"""Tests writing and reading a table with nested structs."""
table_name = "test_nested_structs_table"
# Define a pyarrow schema with nested structs
# config: struct<name: string, settings: struct<retries: int8, timeout: int32, active: bool>>
# config: struct<name: string, settings: struct<retries: int32, timeout: int32, active: bool>>
# Note: Using int32 instead of int8 because Iceberg stores all integers as int32
settings_struct_type = pa.struct(
[
pa.field("retries", pa.int8(), nullable=False),
pa.field("retries", pa.int32(), nullable=False),
pa.field("timeout", pa.int32(), nullable=True),
pa.field("active", pa.bool_(), nullable=False),
]
Expand Down Expand Up @@ -714,7 +715,11 @@ def test_map_type_simple(in_memory_catalog):

# Row 4 (null map)
props4_series = df_read.filter(pl.col("id") == 4).select("properties").to_series()
assert props4_series[0] is None
# In newer versions, null maps are represented as empty lists rather than None
props4_value = props4_series[0]
assert props4_value is None or (
hasattr(props4_value, "to_list") and props4_value.to_list() == []
)


def test_drop_existing_table(in_memory_catalog):
Expand Down
Loading
Loading