This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch branch-0.6
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-0.6 by this push:
     new fd8c7755d [#4228] improvement(client-python): Add Schema Error Handler 
and related exceptions, test cases in client-python (#4381)
fd8c7755d is described below

commit fd8c7755d8d6e743ec9bba124d88c8730ab72cdb
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Aug 6 09:25:03 2024 +0800

    [#4228] improvement(client-python): Add Schema Error Handler and related 
exceptions, test cases in client-python (#4381)
    
    ### What changes were proposed in this pull request?
    
    Add Schema Error Handler and related exceptions, test cases in
    `client-python` based on `client-java`
    
    ### Why are the changes needed?
    
    Fix: #4228
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    UTs and ITs are added and test with `./gradlew
    client:client-python:test`
    
    Co-authored-by: Jing-Jia Hung <[email protected]>
---
 .../gravitino/catalog/base_schema_catalog.py       | 10 ++++-
 clients/client-python/gravitino/exceptions/base.py |  9 ++++
 .../exceptions/handlers/schema_error_handler.py    | 49 ++++++++++++++++++++++
 .../client-python/tests/integration/test_schema.py | 14 +++++++
 .../tests/unittests/test_error_handler.py          | 48 +++++++++++++++++++++
 5 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/clients/client-python/gravitino/catalog/base_schema_catalog.py 
b/clients/client-python/gravitino/catalog/base_schema_catalog.py
index 83d4ea229..2b146b27e 100644
--- a/clients/client-python/gravitino/catalog/base_schema_catalog.py
+++ b/clients/client-python/gravitino/catalog/base_schema_catalog.py
@@ -32,6 +32,7 @@ from gravitino.dto.requests.schema_updates_request import 
SchemaUpdatesRequest
 from gravitino.dto.responses.drop_response import DropResponse
 from gravitino.dto.responses.entity_list_response import EntityListResponse
 from gravitino.dto.responses.schema_response import SchemaResponse
+from gravitino.exceptions.handlers.schema_error_handler import 
SCHEMA_ERROR_HANDLER
 from gravitino.namespace import Namespace
 from gravitino.utils import HTTPClient
 from gravitino.rest.rest_utils import encode_string
@@ -89,7 +90,8 @@ class BaseSchemaCatalog(CatalogDTO, SupportsSchemas):
              A list of schema names under the given catalog namespace.
         """
         resp = self.rest_client.get(
-            
BaseSchemaCatalog.format_schema_request_path(self._schema_namespace())
+            
BaseSchemaCatalog.format_schema_request_path(self._schema_namespace()),
+            error_handler=SCHEMA_ERROR_HANDLER,
         )
         entity_list_response = EntityListResponse.from_json(
             resp.body, infer_missing=True
@@ -124,6 +126,7 @@ class BaseSchemaCatalog(CatalogDTO, SupportsSchemas):
         resp = self.rest_client.post(
             
BaseSchemaCatalog.format_schema_request_path(self._schema_namespace()),
             json=req,
+            error_handler=SCHEMA_ERROR_HANDLER,
         )
         schema_response = SchemaResponse.from_json(resp.body, 
infer_missing=True)
         schema_response.validate()
@@ -145,7 +148,8 @@ class BaseSchemaCatalog(CatalogDTO, SupportsSchemas):
         resp = self.rest_client.get(
             
BaseSchemaCatalog.format_schema_request_path(self._schema_namespace())
             + "/"
-            + encode_string(schema_name)
+            + encode_string(schema_name),
+            error_handler=SCHEMA_ERROR_HANDLER,
         )
         schema_response = SchemaResponse.from_json(resp.body, 
infer_missing=True)
         schema_response.validate()
@@ -175,6 +179,7 @@ class BaseSchemaCatalog(CatalogDTO, SupportsSchemas):
             + "/"
             + encode_string(schema_name),
             updates_request,
+            error_handler=SCHEMA_ERROR_HANDLER,
         )
         schema_response = SchemaResponse.from_json(resp.body, 
infer_missing=True)
         schema_response.validate()
@@ -200,6 +205,7 @@ class BaseSchemaCatalog(CatalogDTO, SupportsSchemas):
                 + "/"
                 + encode_string(schema_name),
                 params=params,
+                error_handler=SCHEMA_ERROR_HANDLER,
             )
             drop_resp = DropResponse.from_json(resp.body, infer_missing=True)
             drop_resp.validate()
diff --git a/clients/client-python/gravitino/exceptions/base.py 
b/clients/client-python/gravitino/exceptions/base.py
index 7700e151a..59b2e05a4 100644
--- a/clients/client-python/gravitino/exceptions/base.py
+++ b/clients/client-python/gravitino/exceptions/base.py
@@ -67,6 +67,10 @@ class NoSuchMetalakeException(NotFoundException):
     """An exception thrown when a metalake is not found."""
 
 
+class NoSuchCatalogException(NotFoundException):
+    """An exception thrown when a catalog is not found."""
+
+
 class AlreadyExistsException(GravitinoRuntimeException):
     """Base exception thrown when an entity or resource already exists."""
 
@@ -75,6 +79,10 @@ class MetalakeAlreadyExistsException(AlreadyExistsException):
     """An exception thrown when a metalake already exists."""
 
 
+class SchemaAlreadyExistsException(AlreadyExistsException):
+    """An exception thrown when a schema already exists."""
+
+
 class NotEmptyException(GravitinoRuntimeException):
     """Base class for all exceptions thrown when a resource is not empty."""
 
@@ -93,3 +101,4 @@ class UnauthorizedException(GravitinoRuntimeException):
 
 class BadRequestException(GravitinoRuntimeException):
     """An exception thrown when the request is invalid."""
+
diff --git 
a/clients/client-python/gravitino/exceptions/handlers/schema_error_handler.py 
b/clients/client-python/gravitino/exceptions/handlers/schema_error_handler.py
new file mode 100644
index 000000000..647466873
--- /dev/null
+++ 
b/clients/client-python/gravitino/exceptions/handlers/schema_error_handler.py
@@ -0,0 +1,49 @@
+"""
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+"""
+
+from gravitino.constants.error import ErrorConstants
+from gravitino.dto.responses.error_response import ErrorResponse
+from gravitino.exceptions.handlers.rest_error_handler import RestErrorHandler
+from gravitino.exceptions.base import (
+    NoSuchCatalogException,
+    NoSuchSchemaException,
+    SchemaAlreadyExistsException,
+)
+
+
+class SchemaErrorHandler(RestErrorHandler):
+
+    def handle(self, error_response: ErrorResponse):
+
+        error_message = error_response.format_error_message()
+        code = error_response.code()
+        exception_type = error_response.type()
+
+        if code == ErrorConstants.NOT_FOUND_CODE:
+            if exception_type == NoSuchCatalogException.__name__:
+                raise NoSuchCatalogException(error_message)
+            if exception_type == NoSuchSchemaException.__name__:
+                raise NoSuchSchemaException(error_message)
+        if code == ErrorConstants.ALREADY_EXISTS_CODE:
+            raise SchemaAlreadyExistsException(error_message)
+
+        super().handle(error_response)
+
+
+SCHEMA_ERROR_HANDLER = SchemaErrorHandler()
diff --git a/clients/client-python/tests/integration/test_schema.py 
b/clients/client-python/tests/integration/test_schema.py
index eb250f64a..7be2406fd 100644
--- a/clients/client-python/tests/integration/test_schema.py
+++ b/clients/client-python/tests/integration/test_schema.py
@@ -29,6 +29,10 @@ from gravitino import (
     SchemaChange,
     Schema,
 )
+from gravitino.exceptions.base import (
+    NoSuchSchemaException,
+    SchemaAlreadyExistsException,
+)
 
 from tests.integration.integration_test_env import IntegrationTestEnv
 
@@ -133,6 +137,11 @@ class TestSchema(IntegrationTestEnv):
         self.assertEqual(schema.properties(), self.schema_properties)
         self.assertEqual(schema.audit_info().creator(), "anonymous")
 
+    def test_failed_create_schema(self):
+        self.create_schema()
+        with self.assertRaises(SchemaAlreadyExistsException):
+            _ = self.create_schema()
+
     def test_drop_schema(self):
         self.create_schema()
         catalog = self.gravitino_client.load_catalog(name=self.catalog_name)
@@ -158,6 +167,11 @@ class TestSchema(IntegrationTestEnv):
         self.assertEqual(schema.properties(), self.schema_properties)
         self.assertEqual(schema.audit_info().creator(), "anonymous")
 
+    def test_failed_load_schema(self):
+        catalog = self.gravitino_client.load_catalog(name=self.catalog_name)
+        with self.assertRaises(NoSuchSchemaException):
+            _ = catalog.as_schemas().load_schema(schema_name=self.schema_name)
+
     def test_alter_schema(self):
         self.create_schema()
         schema_properties_new_value = self.schema_properties_value2 + "_new"
diff --git a/clients/client-python/tests/unittests/test_error_handler.py 
b/clients/client-python/tests/unittests/test_error_handler.py
index e5547493c..fd92af495 100644
--- a/clients/client-python/tests/unittests/test_error_handler.py
+++ b/clients/client-python/tests/unittests/test_error_handler.py
@@ -21,6 +21,7 @@ import unittest
 
 from gravitino.dto.responses.error_response import ErrorResponse
 from gravitino.exceptions.base import (
+    NoSuchCatalogException,
     NoSuchSchemaException,
     NoSuchFilesetException,
     NoSuchMetalakeException,
@@ -31,12 +32,14 @@ from gravitino.exceptions.base import (
     IllegalArgumentException,
     AlreadyExistsException,
     NotEmptyException,
+    SchemaAlreadyExistsException,
     UnsupportedOperationException,
 )
 
 from gravitino.exceptions.handlers.rest_error_handler import REST_ERROR_HANDLER
 from gravitino.exceptions.handlers.fileset_error_handler import 
FILESET_ERROR_HANDLER
 from gravitino.exceptions.handlers.metalake_error_handler import 
METALAKE_ERROR_HANDLER
+from gravitino.exceptions.handlers.schema_error_handler import 
SCHEMA_ERROR_HANDLER
 
 
 class TestErrorHandler(unittest.TestCase):
@@ -147,3 +150,48 @@ class TestErrorHandler(unittest.TestCase):
             METALAKE_ERROR_HANDLER.handle(
                 ErrorResponse.generate_error_response(Exception, "mock error")
             )
+
+    def test_schema_error_handler(self):
+
+        with self.assertRaises(NoSuchCatalogException):
+            SCHEMA_ERROR_HANDLER.handle(
+                ErrorResponse.generate_error_response(
+                    NoSuchCatalogException, "mock error"
+                )
+            )
+
+        with self.assertRaises(NoSuchSchemaException):
+            SCHEMA_ERROR_HANDLER.handle(
+                ErrorResponse.generate_error_response(
+                    NoSuchSchemaException, "mock error"
+                )
+            )
+
+        with self.assertRaises(SchemaAlreadyExistsException):
+            SCHEMA_ERROR_HANDLER.handle(
+                ErrorResponse.generate_error_response(
+                    SchemaAlreadyExistsException, "mock error"
+                )
+            )
+
+        with self.assertRaises(NotEmptyException):
+            SCHEMA_ERROR_HANDLER.handle(
+                ErrorResponse.generate_error_response(NotEmptyException, "mock 
error")
+            )
+
+        with self.assertRaises(UnsupportedOperationException):
+            SCHEMA_ERROR_HANDLER.handle(
+                ErrorResponse.generate_error_response(
+                    UnsupportedOperationException, "mock error"
+                )
+            )
+
+        with self.assertRaises(InternalError):
+            SCHEMA_ERROR_HANDLER.handle(
+                ErrorResponse.generate_error_response(InternalError, "mock 
error")
+            )
+
+        with self.assertRaises(RESTException):
+            SCHEMA_ERROR_HANDLER.handle(
+                ErrorResponse.generate_error_response(Exception, "mock error")
+            )

Reply via email to