jerryshao commented on code in PR #9132:
URL: https://github.com/apache/gravitino/pull/9132#discussion_r2575969169


##########
clients/client-python/gravitino/client/relational_table.py:
##########
@@ -15,65 +15,201 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from typing import Optional
+from typing import Optional, cast
 
 from gravitino.api.audit import Audit
 from gravitino.api.rel.column import Column
 from gravitino.api.rel.expressions.distributions.distribution import 
Distribution
 from gravitino.api.rel.expressions.sorts.sort_order import SortOrder
 from gravitino.api.rel.expressions.transforms.transform import Transform
 from gravitino.api.rel.indexes.index import Index
+from gravitino.api.rel.partitions.partition import Partition
 from gravitino.api.rel.table import Table
+from gravitino.client.generic_column import GenericColumn
+from gravitino.dto.rel.partitions.partition_dto import PartitionDTO
+from gravitino.dto.rel.table_dto import TableDTO
+from gravitino.dto.requests.add_partitions_request import AddPartitionsRequest
+from gravitino.dto.responses.drop_response import DropResponse
+from gravitino.dto.responses.partition_list_response import 
PartitionListResponse
+from gravitino.dto.responses.partition_name_list_response import (
+    PartitionNameListResponse,
+)
+from gravitino.dto.responses.partition_response import PartitionResponse
+from gravitino.dto.util.dto_converters import DTOConverters
+from gravitino.exceptions.handlers.partition_error_handler import (
+    PARTITION_ERROR_HANDLER,
+)
+from gravitino.namespace import Namespace
+from gravitino.rest.rest_utils import encode_string
+from gravitino.utils import HTTPClient
 
 
-class RelationalTable(Table):  # pylint: disable=too-many-instance-attributes
-    """A generic table implementation."""
+class RelationalTable(Table):
+    """Represents a relational table."""
 
     def __init__(
-        self,
-        name: str,
-        columns: list[Column],
-        partitioning: list[Transform],
-        sort_order: list[SortOrder],
-        distribution: Distribution,
-        index: list[Index],
-        comment: Optional[str],
-        properties: dict[str, str],
-        audit_info: Audit,
+        self, namespace: Namespace, table_dto: TableDTO, rest_client: 
HTTPClient
     ):
-        self._name = name
-        self._columns = columns
-        self._partitioning = partitioning
-        self._sort_order = sort_order
-        self._distribution = distribution
-        self._index = index
-        self._comment = comment
-        self._properties = properties
-        self._audit_info = audit_info
+        self._namespace = namespace
+        self._table = cast(Table, DTOConverters.from_dto(table_dto))
+        self._rest_client = rest_client
 
     def name(self) -> str:
-        return self._name
+        return self._table.name()
 
     def columns(self) -> list[Column]:
-        return self._columns
+        metalake, catalog, schema = self._namespace.levels()
+        return [
+            cast(
+                Column,
+                GenericColumn(
+                    c, self._rest_client, metalake, catalog, schema, 
self._table.name()
+                ),
+            )
+            for c in self._table.columns()
+        ]
 
     def partitioning(self) -> list[Transform]:
-        return self._partitioning
+        return self._table.partitioning()
 
     def sort_order(self) -> list[SortOrder]:
-        return self._sort_order
+        return self._table.sort_order()
 
     def distribution(self) -> Distribution:
-        return self._distribution
+        return self._table.distribution()
 
     def index(self) -> list[Index]:
-        return self._index
+        return self._table.index()
 
     def comment(self) -> Optional[str]:
-        return self._comment
+        return self._table.comment()
 
     def properties(self) -> dict[str, str]:
-        return self._properties
+        return self._table.properties()
 
     def audit_info(self) -> Audit:
-        return self._audit_info
+        return self._table.audit_info()
+
+    def get_partition_request_path(self) -> str:
+        """Get the partition request path.
+
+        Returns:
+            str: The partition request path.
+        """
+
+        return (
+            f"api/metalakes/{encode_string(self._namespace.level(0))}"
+            f"/catalogs/{encode_string(self._namespace.level(1))}"
+            f"/schemas/{encode_string(self._namespace.level(2))}"
+            f"/tables/{encode_string(self._table.name())}"
+            "/partitions"
+        )
+
+    def list_partition_names(self) -> list[str]:
+        """Get the partition names of the table.
+
+        Returns:
+            list[str]: The partition names of the table.
+        """
+
+        resp = self._rest_client.get(
+            endpoint=self.get_partition_request_path(),
+            error_handler=PARTITION_ERROR_HANDLER,
+        )
+        partition_name_list_resp = PartitionNameListResponse.from_json(
+            resp.body, infer_missing=True
+        )
+        partition_name_list_resp.validate()
+
+        return partition_name_list_resp.partition_names()
+
+    def list_partitions(self) -> list[Partition]:
+        """Get the partitions of the table.
+
+        Returns:
+            list[Partition]: The partitions of the table.
+        """
+
+        params = {"details": "true"}
+        resp = self._rest_client.get(
+            endpoint=self.get_partition_request_path(),
+            params=params,
+            error_handler=PARTITION_ERROR_HANDLER,
+        )
+        partition_list_resp = PartitionListResponse.from_json(
+            resp.body, infer_missing=True
+        )
+        partition_list_resp.validate()
+
+        return partition_list_resp.get_partitions()
+
+    def get_partition(self, partition_name: str) -> Partition:
+        """Returns the partition with the given name.
+
+        Args:
+            partition_name (str): the name of the partition
+
+        Returns:
+            Partition: the partition with the given name
+
+        Raises:
+            NoSuchPartitionException:
+                if the partition does not exist, throws this exception.
+        """
+
+        resp = self._rest_client.get(
+            endpoint=f"{self.get_partition_request_path()}/{partition_name}",
+            error_handler=PARTITION_ERROR_HANDLER,
+        )
+        partition_resp = PartitionResponse.from_json(resp.body, 
infer_missing=True)
+        partition_resp.validate()
+
+        return partition_resp.get_partition()
+
+    def drop_partition(self, partition_name: str) -> bool:
+        """Drops the partition with the given name.
+
+        Args:
+            partition_name (str): The name of the partition.
+
+        Returns:
+            bool: `True` if the partition is dropped, `False` if the partition 
does not exist.
+        """
+        resp = self._rest_client.delete(
+            endpoint=f"{self.get_partition_request_path()}/{partition_name}",

Review Comment:
   We need to encode the `partition_name` in the URL.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to