Skip to content

Commit b63278b

Browse files
authored
Add RemovePartitionSpecsUpdate event (#2198)
<!-- Thanks for opening a pull request! --> <!-- In the case this PR will resolve an issue, please replace ${GITHUB_ISSUE_ID} below with the actual Github issue id. --> <!-- Closes #${GITHUB_ISSUE_ID} --> # Rationale for this change This adds RemovePartitionSpecsUpdate, another missing TableMetadata update event. It also ends up testing AddPartitionSpecUpdate, which it looks like it untested. [REST API Spec Reference](https://github.com/apache/iceberg/blob/09140e52836048b112c42c9cfe721295bd57048b/open-api/rest-catalog-open-api.yaml#L3006-L3018) # Are these changes tested? Unit tests added. # Are there any user-facing changes? - Added RemovePartitionSpecsUpdate event <!-- In the case of user-facing changes, please add the changelog label. -->
1 parent da47a4a commit b63278b

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

pyiceberg/table/update/__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ class RemoveStatisticsUpdate(IcebergBaseModel):
193193
snapshot_id: int = Field(alias="snapshot-id")
194194

195195

196+
class RemovePartitionSpecsUpdate(IcebergBaseModel):
197+
action: Literal["remove-partition-specs"] = Field(default="remove-partition-specs")
198+
spec_ids: List[int] = Field(alias="spec-ids")
199+
200+
196201
class RemoveSchemasUpdate(IcebergBaseModel):
197202
action: Literal["remove-schemas"] = Field(default="remove-schemas")
198203
schema_ids: List[int] = Field(alias="schema-ids")
@@ -227,6 +232,7 @@ class RemovePartitionStatisticsUpdate(IcebergBaseModel):
227232
RemovePropertiesUpdate,
228233
SetStatisticsUpdate,
229234
RemoveStatisticsUpdate,
235+
RemovePartitionSpecsUpdate,
230236
RemoveSchemasUpdate,
231237
SetPartitionStatisticsUpdate,
232238
RemovePartitionStatisticsUpdate,
@@ -595,6 +601,21 @@ def _(update: RemoveStatisticsUpdate, base_metadata: TableMetadata, context: _Ta
595601
return base_metadata.model_copy(update={"statistics": statistics})
596602

597603

604+
@_apply_table_update.register(RemovePartitionSpecsUpdate)
605+
def _(update: RemovePartitionSpecsUpdate, base_metadata: TableMetadata, context: _TableMetadataUpdateContext) -> TableMetadata:
606+
for remove_spec_id in update.spec_ids:
607+
if not any(spec.spec_id == remove_spec_id for spec in base_metadata.partition_specs):
608+
raise ValueError(f"Partition spec with id {remove_spec_id} does not exist")
609+
610+
if base_metadata.default_spec_id in update.spec_ids:
611+
raise ValueError(f"Cannot remove default partition spec: {base_metadata.default_spec_id}")
612+
613+
partition_specs = [spec for spec in base_metadata.partition_specs if spec.spec_id not in update.spec_ids]
614+
615+
context.add_update(update)
616+
return base_metadata.model_copy(update={"partition_specs": partition_specs})
617+
618+
598619
@_apply_table_update.register(RemoveSchemasUpdate)
599620
def _(update: RemoveSchemasUpdate, base_metadata: TableMetadata, context: _TableMetadataUpdateContext) -> TableMetadata:
600621
# This method should error if any schemas do not exist.

tests/table/test_init.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
)
6767
from pyiceberg.table.statistics import BlobMetadata, PartitionStatisticsFile, StatisticsFile
6868
from pyiceberg.table.update import (
69+
AddPartitionSpecUpdate,
6970
AddSnapshotUpdate,
7071
AddSortOrderUpdate,
7172
AssertCreate,
@@ -76,6 +77,7 @@
7677
AssertLastAssignedPartitionId,
7778
AssertRefSnapshotId,
7879
AssertTableUUID,
80+
RemovePartitionSpecsUpdate,
7981
RemovePartitionStatisticsUpdate,
8082
RemovePropertiesUpdate,
8183
RemoveSchemasUpdate,
@@ -1294,6 +1296,38 @@ def test_update_metadata_log_overflow(table_v2: Table) -> None:
12941296
assert len(new_metadata.metadata_log) == 1
12951297

12961298

1299+
def test_remove_partition_spec_update(table_v2: Table) -> None:
1300+
base_metadata = table_v2.metadata
1301+
new_spec = PartitionSpec(PartitionField(source_id=2, field_id=1001, transform=IdentityTransform(), name="y"), spec_id=1)
1302+
metadata_with_new_spec = update_table_metadata(base_metadata, (AddPartitionSpecUpdate(spec=new_spec),))
1303+
1304+
assert len(metadata_with_new_spec.partition_specs) == 2
1305+
1306+
update = RemovePartitionSpecsUpdate(spec_ids=[1])
1307+
updated_metadata = update_table_metadata(
1308+
metadata_with_new_spec,
1309+
(update,),
1310+
)
1311+
1312+
assert len(updated_metadata.partition_specs) == 1
1313+
1314+
1315+
def test_remove_partition_spec_update_spec_does_not_exist(table_v2: Table) -> None:
1316+
update = RemovePartitionSpecsUpdate(
1317+
spec_ids=[123],
1318+
)
1319+
with pytest.raises(ValueError, match="Partition spec with id 123 does not exist"):
1320+
update_table_metadata(table_v2.metadata, (update,))
1321+
1322+
1323+
def test_remove_partition_spec_update_default_spec(table_v2: Table) -> None:
1324+
update = RemovePartitionSpecsUpdate(
1325+
spec_ids=[0],
1326+
)
1327+
with pytest.raises(ValueError, match="Cannot remove default partition spec: 0"):
1328+
update_table_metadata(table_v2.metadata, (update,))
1329+
1330+
12971331
def test_remove_schemas_update(table_v2: Table) -> None:
12981332
base_metadata = table_v2.metadata
12991333
assert len(base_metadata.schemas) == 2

0 commit comments

Comments
 (0)