Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add property for maxStaleness in table definitions #2087

Merged
merged 2 commits into from
Dec 6, 2024
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
35 changes: 35 additions & 0 deletions google/cloud/bigquery/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ class Table(_TableBase):
"view_query": "view",
"require_partition_filter": "requirePartitionFilter",
"table_constraints": "tableConstraints",
"max_staleness": "maxStaleness",
}

def __init__(self, table_ref, schema=None) -> None:
Expand Down Expand Up @@ -1115,6 +1116,40 @@ def __repr__(self):
def __str__(self):
return f"{self.project}.{self.dataset_id}.{self.table_id}"

@property
def max_staleness(self):
"""Union[str, None]: The maximum staleness of data that could be returned when the table is queried.

Staleness encoded as a string encoding of sql IntervalValue type.
This property is optional and defaults to None.

According to the BigQuery API documentation, maxStaleness specifies the maximum time
interval for which stale data can be returned when querying the table.
It helps control data freshness in scenarios like metadata-cached external tables.

Returns:
Optional[str]: A string representing the maximum staleness interval
(e.g., '1h', '30m', '15s' for hours, minutes, seconds respectively).
"""
return self._properties.get(self._PROPERTY_TO_API_FIELD["max_staleness"])

@max_staleness.setter
def max_staleness(self, value):
"""Set the maximum staleness for the table.

Args:
value (Optional[str]): A string representing the maximum staleness interval.
Must be a valid time interval string.
Examples include '1h' (1 hour), '30m' (30 minutes), '15s' (15 seconds).

Raises:
ValueError: If the value is not None and not a string.
"""
if value is not None and not isinstance(value, str):
raise ValueError("max_staleness must be a string or None")

self._properties[self._PROPERTY_TO_API_FIELD["max_staleness"]] = value


class TableListItem(_TableBase):
"""A read-only table resource from a list operation.
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,49 @@ def test___str__(self):
table1 = self._make_one(TableReference(dataset, "table1"))
self.assertEqual(str(table1), "project1.dataset1.table1")

def test_max_staleness_getter(self):
"""Test getting max_staleness property."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Initially None
self.assertIsNone(table.max_staleness)
# Set max_staleness using setter
table.max_staleness = "1h"
self.assertEqual(table.max_staleness, "1h")

def test_max_staleness_setter(self):
"""Test setting max_staleness property."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Set valid max_staleness
table.max_staleness = "30m"
self.assertEqual(table.max_staleness, "30m")
# Set to None
table.max_staleness = None
self.assertIsNone(table.max_staleness)

def test_max_staleness_setter_invalid_type(self):
"""Test setting max_staleness with an invalid type raises ValueError."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Try setting invalid type
with self.assertRaises(ValueError):
table.max_staleness = 123 # Not a string

def test_max_staleness_to_api_repr(self):
"""Test max_staleness is correctly represented in API representation."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Set max_staleness
table.max_staleness = "1h"
# Convert to API representation
resource = table.to_api_repr()
self.assertEqual(resource.get("maxStaleness"), "1h")


class Test_row_from_mapping(unittest.TestCase, _SchemaBase):
PROJECT = "prahj-ekt"
Expand Down