This is an automated email from the ASF dual-hosted git repository.
kevinjqliu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-python.git
The following commit(s) were added to refs/heads/main by this push:
new 045dd10a feat: add support for setting and removing table properties
on console (#2153)
045dd10a is described below
commit 045dd10a45cbf0b82b095b5bde47f4731a3bf88b
Author: Sébastien Brochet <[email protected]>
AuthorDate: Mon Jul 7 00:42:41 2025 +0200
feat: add support for setting and removing table properties on console
(#2153)
<!--
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
Hello!
Setting or removing table properties on console currently raise a
`Writing is WIP` error. This PR adds the code to set and remove table
properties.
# Are these changes tested?
Yes
# Are there any user-facing changes?
Yes, setting and removing table properties on console now works.
<!-- In the case of user-facing changes, please add the changelog label.
-->
---
mkdocs/docs/cli.md | 16 ++++++++++++++++
pyiceberg/cli/console.py | 12 +++++++-----
tests/cli/test_console.py | 16 ++++++++--------
3 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/mkdocs/docs/cli.md b/mkdocs/docs/cli.md
index 28e44955..984e0df4 100644
--- a/mkdocs/docs/cli.md
+++ b/mkdocs/docs/cli.md
@@ -219,3 +219,19 @@ Or output in JSON for automation:
}
}
```
+
+You can also add, update or remove properties on tables or namespaces:
+
+```sh
+➜ pyiceberg properties set table nyc.taxis
write.metadata.delete-after-commit.enabled true
+Set write.metadata.delete-after-commit.enabled=true on nyc.taxis
+
+➜ pyiceberg properties get table nyc.taxis
+write.metadata.delete-after-commit.enabled true
+
+➜ pyiceberg properties remove table nyc.taxis
write.metadata.delete-after-commit.enabled
+Property write.metadata.delete-after-commit.enabled removed from nyc.taxis
+
+➜ pyiceberg properties get table nyc.taxis
write.metadata.delete-after-commit.enabled
+Could not find property write.metadata.delete-after-commit.enabled on nyc.taxis
+```
diff --git a/pyiceberg/cli/console.py b/pyiceberg/cli/console.py
index 3fbd9c9f..d918f879 100644
--- a/pyiceberg/cli/console.py
+++ b/pyiceberg/cli/console.py
@@ -361,9 +361,10 @@ def table(ctx: Context, identifier: str, property_name:
str, property_value: str
catalog, output = _catalog_and_output(ctx)
identifier_tuple = Catalog.identifier_to_tuple(identifier)
- _ = catalog.load_table(identifier_tuple)
- output.text(f"Setting {property_name}={property_value} on {identifier}")
- raise NotImplementedError("Writing is WIP")
+ table = catalog.load_table(identifier_tuple)
+ with table.transaction() as tx:
+ tx.set_properties({property_name: property_value})
+ output.text(f"Set {property_name}={property_value} on {identifier}")
@properties.group()
@@ -398,8 +399,9 @@ def table(ctx: Context, identifier: str, property_name:
str) -> None: # noqa: F
catalog, output = _catalog_and_output(ctx)
table = catalog.load_table(identifier)
if property_name in table.metadata.properties:
- output.exception(NotImplementedError("Writing is WIP"))
- ctx.exit(1)
+ with table.transaction() as tx:
+ tx.remove_properties(property_name)
+ output.text(f"Property {property_name} removed from {identifier}")
else:
raise NoSuchPropertyException(f"Property {property_name} does not
exist on {identifier}")
diff --git a/tests/cli/test_console.py b/tests/cli/test_console.py
index fe375eb2..a0e95522 100644
--- a/tests/cli/test_console.py
+++ b/tests/cli/test_console.py
@@ -476,8 +476,8 @@ def test_properties_set_table(catalog: InMemoryCatalog) ->
None:
runner = CliRunner()
result = runner.invoke(run, ["properties", "set", "table",
"default.my_table", "location", "s3://new_location"])
- assert result.exit_code == 1
- assert "Writing is WIP" in result.output
+ assert result.exit_code == 0
+ assert result.output == "Set location=s3://new_location on
default.my_table\n"
def test_properties_set_table_does_not_exist(catalog: InMemoryCatalog) -> None:
@@ -518,8 +518,8 @@ def test_properties_remove_table(catalog: InMemoryCatalog)
-> None:
runner = CliRunner()
result = runner.invoke(run, ["properties", "remove", "table",
"default.my_table", "read.split.target.size"])
- assert result.exit_code == 1
- assert "Writing is WIP" in result.output
+ assert result.exit_code == 0
+ assert result.output == "Property read.split.target.size removed from
default.my_table\n"
def test_properties_remove_table_property_does_not_exists(catalog:
InMemoryCatalog) -> None:
@@ -894,8 +894,8 @@ def test_json_properties_set_table(catalog:
InMemoryCatalog) -> None:
result = runner.invoke(
run, ["--output=json", "properties", "set", "table",
"default.my_table", "location", "s3://new_location"]
)
- assert result.exit_code == 1
- assert "Writing is WIP" in result.output
+ assert result.exit_code == 0
+ assert result.output == """"Set location=s3://new_location on
default.my_table"\n"""
def test_json_properties_set_table_does_not_exist(catalog: InMemoryCatalog) ->
None:
@@ -938,8 +938,8 @@ def test_json_properties_remove_table(catalog:
InMemoryCatalog) -> None:
runner = CliRunner()
result = runner.invoke(run, ["--output=json", "properties", "remove",
"table", "default.my_table", "read.split.target.size"])
- assert result.exit_code == 1
- assert "Writing is WIP" in result.output
+ assert result.exit_code == 0
+ assert result.output == """"Property read.split.target.size removed from
default.my_table"\n"""
def test_json_properties_remove_table_property_does_not_exists(catalog:
InMemoryCatalog) -> None: