diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_error.py b/sdk/tables/azure-data-tables/azure/data/tables/_error.py index 72e97d1b0587..58bc2dfe51cd 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_error.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_error.py @@ -17,19 +17,9 @@ ) from azure.core.pipeline.policies import ContentDecodePolicy -if sys.version_info < (3,): - - def _str(value): - if isinstance(value, unicode): # pylint: disable=undefined-variable - return value.encode("utf-8") - - return str(value) -else: - _str = str - def _to_str(value): - return _str(value) if value is not None else None + return str(value) if value is not None else None _ERROR_TYPE_NOT_SUPPORTED = "Type not supported when sending data to the service: {0}." @@ -220,6 +210,34 @@ def _process_table_error(storage_error, table_name=None): _reraise_error(decoded_error) +def _reprocess_error(decoded_error, identifiers=None): + error_code = decoded_error.error_code + message = decoded_error.message + authentication_failed = "Server failed to authenticate the request" + invalid_input = "The number of keys specified in the URI does not match number of key properties for the resource" + invalid_query_parameter_value = "Value for one of the query parameters specified in the request URI is invalid" + invalid_url = "Request url is invalid" + properties_need_value = "The values are not specified for all properties in the entity" + table_does_not_exist = "The table specified does not exist" + if (error_code == "AuthenticationFailed" and authentication_failed in message or # pylint: disable=too-many-boolean-expressions + error_code == "InvalidInput" and invalid_input in message or + error_code == "InvalidInput" and invalid_url in message or + error_code == "InvalidQueryParameterValue" and invalid_query_parameter_value in message or + error_code == "PropertiesNeedValue" and properties_need_value in message or + error_code =="TableNotFound" and table_does_not_exist in message + ): + args_list = list(decoded_error.args) + args_list[0] += "\nA possible cause of this error could be that the account URL used to"\ + "create the Client includes an invalid path, for example the table name. Please check your account URL." + decoded_error.args = tuple(args_list) + + if (identifiers is not None and error_code == "InvalidXmlDocument" and len(identifiers) > 5): + raise ValueError( + "Too many access policies provided. The server does not support setting more than 5 access policies"\ + "on a single resource." + ) + + class TableTransactionError(HttpResponseError): """There is a failure in the transaction operations. diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py b/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py index b09db8d9e0f7..3e81829644a3 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py @@ -20,9 +20,10 @@ from ._deserialize import _convert_to_entity, _trim_service_metadata from ._entity import TableEntity from ._error import ( + _decode_error, _process_table_error, + _reprocess_error, _reraise_error, - _decode_error, _validate_tablename_error ) from ._generated.models import ( @@ -219,21 +220,15 @@ def set_table_access_policy( permission=value.permission ) identifiers.append(SignedIdentifier(id=key, access_policy=payload)) - signed_identifiers = identifiers # type: ignore try: self._client.table.set_access_policy( - table=self.table_name, table_acl=signed_identifiers or None, **kwargs # type: ignore + table=self.table_name, table_acl=identifiers or None, **kwargs # type: ignore ) except HttpResponseError as error: try: _process_table_error(error, table_name=self.table_name) except HttpResponseError as table_error: - if (table_error.error_code == 'InvalidXmlDocument' # type: ignore - and len(signed_identifiers) > 5): - raise ValueError( - 'Too many access policies provided. The server does not support setting ' - 'more than 5 access policies on a single resource.' - ) + _reprocess_error(table_error, identifiers=identifiers) raise @distributed_trace @@ -260,7 +255,11 @@ def create_table( try: result = self._client.table.create(table_properties, **kwargs) except HttpResponseError as error: - _process_table_error(error, table_name=self.table_name) + try: + _process_table_error(error, table_name=self.table_name) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise return TableItem(name=result.table_name) # type: ignore @distributed_trace @@ -289,7 +288,11 @@ def delete_table( except HttpResponseError as error: if error.status_code == 404: return - _process_table_error(error, table_name=self.table_name) + try: + _process_table_error(error, table_name=self.table_name) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise @overload def delete_entity(self, partition_key, row_key, **kwargs): diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_table_service_client.py b/sdk/tables/azure-data-tables/azure/data/tables/_table_service_client.py index d370e43196b5..29c1ad5bc108 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_table_service_client.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_table_service_client.py @@ -20,7 +20,7 @@ ) from ._base_client import parse_connection_str, TablesBaseClient, TransportWrapper from ._models import LocationMode -from ._error import _process_table_error +from ._error import _process_table_error, _reprocess_error from ._table_client import TableClient from ._serialize import _parameter_filter_substitution @@ -134,7 +134,11 @@ def get_service_properties(self, **kwargs): try: service_props = self._client.service.get_properties(timeout=timeout, **kwargs) # type: ignore except HttpResponseError as error: - _process_table_error(error) + try: + _process_table_error(error) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise return service_properties_deserialize(service_props) @distributed_trace @@ -167,7 +171,11 @@ def set_service_properties(self, **kwargs): try: self._client.service.set_properties(props, **kwargs) except HttpResponseError as error: - _process_table_error(error) + try: + _process_table_error(error) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise @distributed_trace def create_table(self, table_name, **kwargs): diff --git a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py index de408b999fb1..218cb4908856 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py @@ -25,8 +25,9 @@ from .._serialize import serialize_iso, _parameter_filter_substitution, _prepare_key from .._deserialize import deserialize_iso, _return_headers_and_deserialized from .._error import ( - _process_table_error, _decode_error, + _process_table_error, + _reprocess_error, _reraise_error, _validate_tablename_error ) @@ -224,12 +225,7 @@ async def set_table_access_policy( try: _process_table_error(error, table_name=self.table_name) except HttpResponseError as table_error: - if (table_error.error_code == 'InvalidXmlDocument' # type: ignore - and len(identifiers) > 5): - raise ValueError( - 'Too many access policies provided. The server does not support setting ' - 'more than 5 access policies on a single resource.' - ) + _reprocess_error(table_error, identifiers=identifiers) raise @distributed_trace_async @@ -253,7 +249,11 @@ async def create_table(self, **kwargs) -> TableItem: try: result = await self._client.table.create(table_properties, **kwargs) except HttpResponseError as error: - _process_table_error(error, table_name=self.table_name) + try: + _process_table_error(error, table_name=self.table_name) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise return TableItem(name=result.table_name) # type: ignore @distributed_trace_async @@ -279,7 +279,11 @@ async def delete_table(self, **kwargs) -> None: except HttpResponseError as error: if error.status_code == 404: return - _process_table_error(error, table_name=self.table_name) + try: + _process_table_error(error, table_name=self.table_name) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise @overload async def delete_entity(self, partition_key: str, row_key: str, **kwargs: Any) -> None: diff --git a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_service_client_async.py b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_service_client_async.py index 14c02b23b0c7..77c12d0f4789 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_service_client_async.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_service_client_async.py @@ -20,7 +20,7 @@ from .._base_client import parse_connection_str from .._generated.models import TableServiceProperties from .._models import service_stats_deserialize, service_properties_deserialize -from .._error import _process_table_error +from .._error import _process_table_error, _reprocess_error from .._models import TableItem, LocationMode from .._serialize import _parameter_filter_substitution from ._table_client_async import TableClient @@ -135,7 +135,11 @@ async def get_service_properties(self, **kwargs) -> Dict[str, object]: try: service_props = await self._client.service.get_properties(timeout=timeout, **kwargs) # type: ignore except HttpResponseError as error: - _process_table_error(error) + try: + _process_table_error(error) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise return service_properties_deserialize(service_props) @distributed_trace_async @@ -174,7 +178,11 @@ async def set_service_properties( try: await self._client.service.set_properties(props, **kwargs) # type: ignore except HttpResponseError as error: - _process_table_error(error) + try: + _process_table_error(error) + except HttpResponseError as decoded_error: + _reprocess_error(decoded_error) + raise @distributed_trace_async async def create_table(self, table_name: str, **kwargs) -> TableClient: diff --git a/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py b/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py index 0df8d40645f3..7af03ffed787 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py @@ -20,7 +20,7 @@ from devtools_testutils import is_live -from .testcase import TableTestCase, SLEEP_DELAY +from .testcase import TableTestCase TEST_TABLE_PREFIX = "pytableasync" diff --git a/sdk/tables/azure-data-tables/tests/_shared/testcase.py b/sdk/tables/azure-data-tables/tests/_shared/testcase.py index 7f12ccc8491e..281f1cf3ca9f 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/testcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/testcase.py @@ -30,8 +30,6 @@ from devtools_testutils import is_live -SLEEP_DELAY = 30 - TEST_TABLE_PREFIX = "pytablesync" SERVICE_UNAVAILABLE_RESP_BODY = '