From 4f1d4bf83031b3cb1134bc50a74c39f328b7c6c8 Mon Sep 17 00:00:00 2001 From: zhangj98 Date: Wed, 11 Feb 2026 16:16:20 +0800 Subject: [PATCH 1/2] feat(python): add list tag for TagManager --- .../pypaimon/filesystem/local_file_io.py | 1 + .../pypaimon/table/file_store_table.py | 10 ++++++++++ paimon-python/pypaimon/tag/tag_manager.py | 8 ++++++++ .../pypaimon/tests/table/simple_table_test.py | 19 +++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/paimon-python/pypaimon/filesystem/local_file_io.py b/paimon-python/pypaimon/filesystem/local_file_io.py index 183eb0ea130d..e5197334f3fe 100644 --- a/paimon-python/pypaimon/filesystem/local_file_io.py +++ b/paimon-python/pypaimon/filesystem/local_file_io.py @@ -117,6 +117,7 @@ def __init__(self, file_path: Path, original_path: str): stat_info = file_path.stat() self.path = str(file_path.absolute()) self.original_path = original_path + self.base_name = os.path.basename(original_path) self.size = stat_info.st_size if file_path.is_file() else None self.type = ( pyarrow.fs.FileType.Directory if file_path.is_dir() diff --git a/paimon-python/pypaimon/table/file_store_table.py b/paimon-python/pypaimon/table/file_store_table.py index e23d9cec7515..64423e12dc7e 100644 --- a/paimon-python/pypaimon/table/file_store_table.py +++ b/paimon-python/pypaimon/table/file_store_table.py @@ -139,6 +139,16 @@ def delete_tag(self, tag_name: str) -> bool: tag_mgr = self.tag_manager() return tag_mgr.delete_tag(tag_name) + def list_tag(self): + """ + List all tags. + + Returns: + List of name of tag + """ + tag_mgr = self.tag_manager() + return tag_mgr.list_tag() + def path_factory(self) -> 'FileStorePathFactory': from pypaimon.utils.file_store_path_factory import FileStorePathFactory diff --git a/paimon-python/pypaimon/tag/tag_manager.py b/paimon-python/pypaimon/tag/tag_manager.py index 7f63f4ac062f..80f028200b29 100644 --- a/paimon-python/pypaimon/tag/tag_manager.py +++ b/paimon-python/pypaimon/tag/tag_manager.py @@ -140,6 +140,14 @@ def create_tag( self._create_or_replace_tag(snapshot, tag_name) + def list_tag(self): + """List all tags.""" + result = [] + for tag_file in self.file_io.list_status(self.tag_directory()): + _, tag = tag_file.base_name.split("-", 1) + result.append(tag) + return result + def _create_or_replace_tag( self, snapshot: Snapshot, diff --git a/paimon-python/pypaimon/tests/table/simple_table_test.py b/paimon-python/pypaimon/tests/table/simple_table_test.py index 4a4d024f3976..bf4458d9addb 100644 --- a/paimon-python/pypaimon/tests/table/simple_table_test.py +++ b/paimon-python/pypaimon/tests/table/simple_table_test.py @@ -191,10 +191,29 @@ def test_tag_create_and_delete(self): self.assertIsNotNone(tag) self.assertEqual(tag.id, 1) + table_write = write_builder.new_write() + table_commit = write_builder.new_commit() + data = pa.Table.from_pydict({ + 'pt': [1, 1], + 'k': [10, 20], + 'v': [100, 200] + }, schema=self.pa_schema) + table_write.write_arrow(data) + table_commit.commit(table_write.prepare_commit()) + table_write.close() + table_commit.close() + + table.create_tag("test_tag_2") + all_tags = set(table.list_tag()) + self.assertEqual(all_tags, {"test_tag", "test_tag_2"}) + # Delete the tag result = table.delete_tag("test_tag") self.assertTrue(result) + all_tags = table.list_tag() + self.assertEqual(all_tags, ["test_tag_2"]) + # Verify tag no longer exists self.assertFalse(tag_manager.tag_exists("test_tag")) From 5f257aed0f37a43a683bca58f1d8b51416de4161 Mon Sep 17 00:00:00 2001 From: zhangj98 Date: Thu, 12 Feb 2026 10:26:06 +0800 Subject: [PATCH 2/2] fix commet --- paimon-python/pypaimon/tag/tag_manager.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/paimon-python/pypaimon/tag/tag_manager.py b/paimon-python/pypaimon/tag/tag_manager.py index 80f028200b29..19e98129a3dd 100644 --- a/paimon-python/pypaimon/tag/tag_manager.py +++ b/paimon-python/pypaimon/tag/tag_manager.py @@ -16,6 +16,7 @@ # under the License. import logging +import os from typing import Optional from pypaimon.common.file_io import FileIO @@ -144,8 +145,17 @@ def list_tag(self): """List all tags.""" result = [] for tag_file in self.file_io.list_status(self.tag_directory()): - _, tag = tag_file.base_name.split("-", 1) - result.append(tag) + tag_file_name = None + if hasattr(tag_file, 'base_name'): + tag_file_name = tag_file.base_name + else: + try: + tag_file_name = os.path.basename(tag_file) + except TypeError: + tag_file_name = None + if tag_file_name is not None: + _, tag = tag_file_name.split("-", 1) + result.append(tag) return result def _create_or_replace_tag(