From 816b025087705fe500db1cc0ef354b4899fb5074 Mon Sep 17 00:00:00 2001 From: Sean Kane <68240067+seankane-msft@users.noreply.github.com> Date: Wed, 2 Jun 2021 13:48:40 -0700 Subject: [PATCH] [Tables] mypy (#19001) * type hints * mypy fixes * adding small fix * fixed more async issues * adding pylint changes * more lint fixes * caught another one * fixes for py3.7 * removal --- eng/tox/mypy_hard_failure_packages.py | 1 + .../azure/data/tables/_authentication.py | 12 ++--- .../azure/data/tables/_base_client.py | 23 ++++---- .../azure/data/tables/_deserialize.py | 16 +++--- .../azure/data/tables/_entity.py | 4 +- .../azure/data/tables/_models.py | 29 +++++----- .../azure/data/tables/_policies.py | 4 +- .../azure/data/tables/_serialize.py | 6 +-- .../data/tables/_shared_access_signature.py | 28 ++++++---- .../azure/data/tables/_table_batch.py | 28 +++++----- .../azure/data/tables/_table_client.py | 54 ++++++++++--------- .../data/tables/_table_service_client.py | 10 ++-- .../tables/_table_shared_access_signature.py | 20 ++++--- .../data/tables/aio/_base_client_async.py | 10 ++-- .../data/tables/aio/_table_batch_async.py | 22 ++++---- .../data/tables/aio/_table_client_async.py | 47 ++++++++-------- .../tables/aio/_table_service_client_async.py | 10 ++-- sdk/tables/azure-data-tables/mypy.ini | 5 +- 18 files changed, 171 insertions(+), 158 deletions(-) diff --git a/eng/tox/mypy_hard_failure_packages.py b/eng/tox/mypy_hard_failure_packages.py index 8b5f6c93ac31..dfc43744fc6d 100644 --- a/eng/tox/mypy_hard_failure_packages.py +++ b/eng/tox/mypy_hard_failure_packages.py @@ -14,4 +14,5 @@ "azure-ai-formrecognizer", "azure-ai-metricsadvisor", "azure-eventgrid", + "azure-data-tables", ] diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_authentication.py b/sdk/tables/azure-data-tables/azure/data/tables/_authentication.py index e6aafa709cc4..95d80dfd0844 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_authentication.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_authentication.py @@ -5,8 +5,7 @@ # -------------------------------------------------------------------------- import logging -import sys -from typing import Union +from typing import TYPE_CHECKING try: from urllib.parse import urlparse @@ -19,7 +18,7 @@ try: from azure.core.pipeline.transport import AsyncHttpTransport except ImportError: - AsyncHttpTransport = None + AsyncHttpTransport = None # type: ignore try: from yarl import URL @@ -34,8 +33,9 @@ _wrap_exception, ) -if sys.version_info > (3, 5): - from typing import Awaitable # pylint: disable=ungrouped-imports +if TYPE_CHECKING: + from azure.core.pipeline import PipelineRequest # pylint: disable=ungrouped-imports + logger = logging.getLogger(__name__) @@ -112,7 +112,7 @@ def _add_authorization_header(self, request, string_to_sign): raise _wrap_exception(ex, AzureSigningError) def on_request(self, request): - # type: (PipelineRequest) -> Union[None, Awaitable[None]] + # type: (PipelineRequest) -> None self.sign_request(request) def sign_request(self, request): diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_base_client.py b/sdk/tables/azure-data-tables/azure/data/tables/_base_client.py index 8505b59a69a9..eaf893289380 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_base_client.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_base_client.py @@ -4,7 +4,7 @@ # license information. # -------------------------------------------------------------------------- -from typing import Dict, Optional, Any, List, Mapping +from typing import Dict, Optional, Any, List, Mapping, Union from uuid import uuid4 try: from urllib.parse import parse_qs, quote, urlparse @@ -51,6 +51,7 @@ ) from ._sdk_moniker import SDK_MONIKER + _SUPPORTED_API_VERSIONS = ["2019-02-02", "2019-07-07"] @@ -133,9 +134,9 @@ def __init__( LocationMode.PRIMARY: primary_hostname, LocationMode.SECONDARY: secondary_hostname, } - self._credential_policy = None - self._configure_credential(self.credential) - self._policies = self._configure_policies(hosts=self._hosts, **kwargs) + self._credential_policy = None # type: ignore + self._configure_credential(self.credential) # type: ignore + self._policies = self._configure_policies(hosts=self._hosts, **kwargs) # type: ignore if self._cosmos_endpoint: self._policies.insert(0, CosmosPatchTransformPolicy()) @@ -203,7 +204,7 @@ class TablesBaseClient(AccountHostsMixin): def __init__( self, endpoint, # type: str - credential=None, # type: str + credential=None, # type: Union[AzureNamedKeyCredential, AzureSasCredential] **kwargs # type: Any ): # type: (...) -> None @@ -242,15 +243,15 @@ def _configure_policies(self, **kwargs): def _configure_credential(self, credential): # type: (Any) -> None if hasattr(credential, "get_token"): - self._credential_policy = BearerTokenCredentialPolicy( + self._credential_policy = BearerTokenCredentialPolicy( # type: ignore credential, STORAGE_OAUTH_SCOPE ) elif isinstance(credential, SharedKeyCredentialPolicy): - self._credential_policy = credential + self._credential_policy = credential # type: ignore elif isinstance(credential, AzureSasCredential): - self._credential_policy = AzureSasCredentialPolicy(credential) + self._credential_policy = AzureSasCredentialPolicy(credential) # type: ignore elif isinstance(credential, AzureNamedKeyCredential): - self._credential_policy = SharedKeyCredentialPolicy(credential) + self._credential_policy = SharedKeyCredentialPolicy(credential) # type: ignore elif credential is not None: raise TypeError("Unsupported credential: {}".format(credential)) @@ -260,9 +261,9 @@ def _batch_send(self, *reqs, **kwargs): # Pop it here, so requests doesn't feel bad about additional kwarg policies = [StorageHeadersPolicy()] - changeset = HttpRequest("POST", None) + changeset = HttpRequest("POST", None) # type: ignore changeset.set_multipart_mixed( - *reqs, policies=policies, boundary="changeset_{}".format(uuid4()) + *reqs, policies=policies, boundary="changeset_{}".format(uuid4()) # type: ignore ) request = self._client._client.post( # pylint: disable=protected-access url="https://{}/$batch".format(self._primary_hostname), diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_deserialize.py b/sdk/tables/azure-data-tables/azure/data/tables/_deserialize.py index 107b74f853e8..103443e23f8e 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_deserialize.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_deserialize.py @@ -3,7 +3,8 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -from typing import Dict, Optional, Any +from typing import Union, Dict, Any, Optional + from uuid import UUID import logging import datetime @@ -51,7 +52,7 @@ def _from_entity_binary(value): def _from_entity_int32(value): - # type: (str) -> EntityProperty + # type: (str) -> int return int(value) @@ -96,11 +97,12 @@ def _from_entity_guid(value): def _from_entity_str(value): - # type: (str) -> EntityProperty - if isinstance(six.binary_type): + # type: (Union[str, bytes]) -> str + if isinstance(value, six.binary_type): return value.decode('utf-8') return value + _EDM_TYPES = [ EdmType.BINARY, EdmType.INT64, @@ -180,7 +182,7 @@ def _convert_to_entity(entry_element): # Add type for String try: - if isinstance(value, unicode) and mtype is None: + if isinstance(value, unicode) and mtype is None: # type: ignore mtype = EdmType.STRING except NameError: if isinstance(value, str) and mtype is None: @@ -256,7 +258,7 @@ def _return_context_and_deserialized( def _trim_service_metadata(metadata, content=None): - # type: (Dict[str,str], Optional[Dict[str, Any]]) -> None + # type: (Dict[str, str], Optional[Dict[str, Any]]) -> Dict[str, Any] result = { "date": metadata.pop("date", None), "etag": metadata.pop("etag", None), @@ -265,5 +267,5 @@ def _trim_service_metadata(metadata, content=None): preference = metadata.pop('preference_applied', None) if preference: result["preference_applied"] = preference - result["content"] = content + result["content"] = content # type: ignore return result diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_entity.py b/sdk/tables/azure-data-tables/azure/data/tables/_entity.py index 824fa35d10b9..90a8febdbbb8 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_entity.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_entity.py @@ -12,14 +12,14 @@ class TableEntity(dict): An Entity dictionary with additional metadata """ - _metadata = None + _metadata = {} # type: Dict[str, Any] @property def metadata(self): # type: () -> Dict[str, Any] """Resets metadata to be a part of the entity :return Dict of entity metadata - :rtype Dict[str, Any] + :rtype: Dict[str, Any] """ return self._metadata diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_models.py b/sdk/tables/azure-data-tables/azure/data/tables/_models.py index 18802ec9bf0e..d001747c21d2 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_models.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_models.py @@ -4,7 +4,7 @@ # license information. # -------------------------------------------------------------------------- from enum import Enum -from typing import TYPE_CHECKING, Any, Dict +from typing import TYPE_CHECKING, Any, Dict, List from azure.core.exceptions import HttpResponseError from azure.core.paging import PageIterator @@ -28,6 +28,7 @@ if TYPE_CHECKING: from ._generated.models import TableQueryResponse + from ._generated.models import TableServiceProperties as GenTableServiceProperties class TableServiceStats(GenTableServiceStats): @@ -250,8 +251,8 @@ class CorsRule(GeneratedCorsRule): def __init__( # pylint: disable=super-init-not-called self, - allowed_origins, # type: list[str] - allowed_methods, # type: list[str] + allowed_origins, # type: List[str] + allowed_methods, # type: List[str] **kwargs # type: Any ): # type: (...)-> None @@ -407,7 +408,7 @@ def __add__(self, other): return TableSasPermissions(_str=str(self) + str(other)) def __str__(self): - # type: () -> TableSasPermissions + # type: () -> str return ( ("r" if self.read else "") + ("a" if self.add else "") @@ -446,23 +447,19 @@ def from_string( return parsed -TableSasPermissions.READ = TableSasPermissions(**dict(read=True)) -TableSasPermissions.ADD = TableSasPermissions(**dict(add=True)) -TableSasPermissions.UPDATE = TableSasPermissions(**dict(update=True)) -TableSasPermissions.DELETE = TableSasPermissions(**dict(delete=True)) - - def service_stats_deserialize(generated): + # type: (GenTableServiceStats) -> Dict[str, Any] """Deserialize a ServiceStats objects into a dict.""" return { "geo_replication": { - "status": generated.geo_replication.status, - "last_sync_time": generated.geo_replication.last_sync_time, + "status": generated.geo_replication.status, # type: ignore + "last_sync_time": generated.geo_replication.last_sync_time, # type: ignore } } def service_properties_deserialize(generated): + # type: (GenTableServiceProperties) -> Dict[str, Any] """Deserialize a ServiceProperties objects into a dict.""" return { "analytics_logging": TableAnalyticsLogging._from_generated(generated.logging), # pylint: disable=protected-access @@ -473,7 +470,8 @@ def service_properties_deserialize(generated): generated.minute_metrics ), "cors": [ - CorsRule._from_generated(cors) for cors in generated.cors # pylint: disable=protected-access + CorsRule._from_generated(cors) # pylint: disable=protected-access + for cors in generated.cors # type: ignore ], } @@ -493,10 +491,11 @@ def __init__(self, name, **kwargs): # pylint: disable=unused-argument """ self.name = name + # TODO: TableQueryResponse is not the correct type @classmethod def _from_generated(cls, generated, **kwargs): # type: (TableQueryResponse, Dict[str, Any]) -> TableItem - return cls(generated.table_name, **kwargs) + return cls(generated.table_name, **kwargs) # type: ignore class TablePayloadFormat(object): @@ -643,7 +642,7 @@ def __str__(self): @classmethod def from_string(cls, permission, **kwargs): - # type: (str, Dict[str]) -> AccountSasPermissions + # type: (str, Dict[str, Any]) -> AccountSasPermissions """Create AccountSasPermissions from a string. To specify read, write, delete, etc. permissions you need only to diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_policies.py b/sdk/tables/azure-data-tables/azure/data/tables/_policies.py index e0623c4f5d96..ad5045703369 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_policies.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_policies.py @@ -50,7 +50,7 @@ def set_next_host_location(settings, request): class StorageHeadersPolicy(HeadersPolicy): def on_request(self, request): - # type: (PipelineRequest, Any) -> None + # type: (PipelineRequest) -> None super(StorageHeadersPolicy, self).on_request(request) # Add required date headers @@ -236,6 +236,6 @@ class CosmosPatchTransformPolicy(SansIOHTTPPolicy): """Policy to transform PATCH requests into POST requests with the "X-HTTP-Method":"MERGE" header set.""" def on_request(self, request): - # type: (PipelineRequest) -> Union[None, Awaitable[None]] + # type: (PipelineRequest) -> None if request.http_request.method == "PATCH": _transform_patch_to_cosmos_post(request.http_request) diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_serialize.py b/sdk/tables/azure-data-tables/azure/data/tables/_serialize.py index 1a42bee0faa1..b7c71952d08f 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_serialize.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_serialize.py @@ -141,9 +141,9 @@ def _to_entity_none(value): # pylint: disable=unused-argument try: _PYTHON_TO_ENTITY_CONVERSIONS.update( { - unicode: _to_entity_str, + unicode: _to_entity_str, # type: ignore str: _to_entity_binary, - long: _to_entity_int32, + long: _to_entity_int32, # type: ignore } ) except NameError: @@ -198,7 +198,7 @@ def _add_entity_properties(source): if isinstance(value, Enum): try: - conv = _PYTHON_TO_ENTITY_CONVERSIONS.get(unicode) + conv = _PYTHON_TO_ENTITY_CONVERSIONS.get(unicode) # type: ignore except NameError: conv = _PYTHON_TO_ENTITY_CONVERSIONS.get(str) mtype, value = conv(value) diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_shared_access_signature.py b/sdk/tables/azure-data-tables/azure/data/tables/_shared_access_signature.py index c3d1607a5f66..e80c725156d0 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_shared_access_signature.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_shared_access_signature.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- from datetime import date +from typing import Optional, Union, TYPE_CHECKING from ._deserialize import url_quote @@ -14,6 +15,10 @@ ) from ._constants import DEFAULT_X_MS_VERSION +if TYPE_CHECKING: + from datetime import datetime # pylint: disable=ungrouped-imports + from ._models import AccountSasPermissions, ResourceTypes, SASProtocol + def _to_utc_datetime(value): # This is for SAS where milliseconds are not supported @@ -41,27 +46,28 @@ def __init__(self, credential, x_ms_version=DEFAULT_X_MS_VERSION): def generate_account( self, - services, - resource_types, - permission, - expiry, - start=None, - ip_address_or_range=None, - protocol=None, + services, # type: str + resource_types, # type: ResourceTypes + permission, # type: Union[AccountSasPermissions, str] + expiry, # type: Union[datetime, str] + start=None, # type: Optional[Union[datetime, str]] + ip_address_or_range=None, # type: Optional[str] + protocol=None, # type: Optional[Union[str, SASProtocol]] ): + # type: (...) -> str """ Generates a shared access signature for the account. Use the returned signature with the sas_token parameter of the service or to create a new account object. - :param Services services: - Specifies the services accessible with the account SAS. You can + :param str services: + Specifies the services as a bitmap accessible with the account SAS. You can combine values to provide access to more than one service. :param ResourceTypes resource_types: Specifies the resource types that are accessible with the account SAS. You can combine values to provide access to more than one resource type. - :param AccountPermissions permission: + :param AccountSasPermissions permission: The permissions associated with the shared access signature. The user is restricted to operations allowed by the permissions. Required unless an id is given referencing a stored access policy @@ -243,6 +249,7 @@ def get_value_to_append(query): ) def add_account_signature(self, account_name, account_key): + # type: (str, str) -> None def get_value_to_append(query): return_value = self.query_dict.get(query) or "" return return_value + "\n" @@ -266,6 +273,7 @@ def get_value_to_append(query): ) def get_token(self): + # type: () -> str return "&".join( [ "{0}={1}".format(n, url_quote(v)) diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_table_batch.py b/sdk/tables/azure-data-tables/azure/data/tables/_table_batch.py index 1342fa8533b1..89fe84b1117a 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_table_batch.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_table_batch.py @@ -9,7 +9,8 @@ Any, Dict, Mapping, - Optional + Optional, + List ) from azure.core import MatchConditions @@ -20,7 +21,10 @@ from ._entity import TableEntity if TYPE_CHECKING: - from ._generated import models + from azure.core.pipeline.transport import HttpRequest + import msrest + from ._generated import models, AzureTable + from ._generated._configuration import AzureTableConfiguration EntityType = Union[TableEntity, Mapping[str, Any]] @@ -73,7 +77,7 @@ def __init__( self.table_name = table_name self._partition_key = kwargs.pop("partition_key", None) - self.requests = [] + self.requests = [] # type: List[HttpRequest] def __len__(self): return len(self.requests) @@ -111,7 +115,7 @@ def create( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore if "PartitionKey" in temp and "RowKey" in temp: temp = _add_entity_properties(temp) @@ -240,13 +244,13 @@ def update( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore match_condition = kwargs.pop("match_condition", None) etag = kwargs.pop("etag", None) if match_condition and not etag: try: - etag = entity.metadata.get("etag", None) + etag = entity.metadata.get("etag", None) # type: ignore except (AttributeError, TypeError): pass if_match = _get_match_headers( @@ -379,7 +383,7 @@ def _batch_update_entity( ) self.requests.append(request) - _batch_update_entity.metadata = { + _batch_update_entity.metadata = { # type: ignore "url": "/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')" } # type: ignore @@ -487,7 +491,7 @@ def _batch_merge_entity( _transform_patch_to_cosmos_post(request) self.requests.append(request) - _batch_merge_entity.metadata = { + _batch_merge_entity.metadata = { # type: ignore "url": "/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')" } @@ -518,7 +522,7 @@ def delete( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore partition_key = temp["PartitionKey"] row_key = temp["RowKey"] @@ -526,7 +530,7 @@ def delete( etag = kwargs.pop("etag", None) if match_condition and not etag: try: - etag = entity.metadata.get("etag", None) + etag = entity.metadata.get("etag", None) # type: ignore except (AttributeError, TypeError): pass if_match = _get_match_headers( @@ -629,7 +633,7 @@ def _batch_delete_entity( ) self.requests.append(request) - _batch_delete_entity.metadata = { + _batch_delete_entity.metadata = { # type: ignore "url": "/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')" } @@ -658,7 +662,7 @@ def upsert( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore partition_key = temp["PartitionKey"] row_key = temp["RowKey"] 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 26f464aafc3e..5619471db2e5 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 @@ -5,7 +5,7 @@ # -------------------------------------------------------------------------- import functools -from typing import Optional, Any, Union, List, Tuple, Dict, Mapping, Iterable, overload +from typing import Optional, Any, TYPE_CHECKING, Union, List, Tuple, Dict, Mapping, Iterable, overload try: from urllib.parse import urlparse, unquote except ImportError: @@ -47,6 +47,9 @@ OperationType = Union[TransactionOperation, str] TransactionOperationType = Union[Tuple[OperationType, EntityType], Tuple[OperationType, EntityType, Mapping[str, Any]]] +if TYPE_CHECKING: + from azure.core.credentials import AzureNamedKeyCredential, AzureSasCredential + class TableClient(TablesBaseClient): """A client to interact with a specific Table in an Azure Tables account. @@ -184,7 +187,7 @@ def get_table_access_policy( ) except HttpResponseError as error: _process_table_error(error) - return {s.id: s.access_policy or AccessPolicy() for s in identifiers} + return {s.id: s.access_policy or AccessPolicy() for s in identifiers} # type: ignore @distributed_trace def set_table_access_policy( @@ -210,13 +213,13 @@ def set_table_access_policy( signed_identifiers = identifiers # type: ignore try: self._client.table.set_access_policy( - table=self.table_name, table_acl=signed_identifiers or None, **kwargs + table=self.table_name, table_acl=signed_identifiers or None, **kwargs # type: ignore ) except HttpResponseError as error: try: _process_table_error(error) except HttpResponseError as table_error: - if (table_error.error_code == 'InvalidXmlDocument' + 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 ' @@ -228,7 +231,7 @@ def set_table_access_policy( def create_table( self, **kwargs # type: Any ): - # type: (...) -> Dict[str,str] + # type: (...) -> TableItem """Creates a new table under the current account. :return: A TableItem representing the created table. @@ -247,9 +250,9 @@ def create_table( table_properties = TableProperties(table_name=self.table_name) try: result = self._client.table.create(table_properties, **kwargs) - return TableItem(name=result.table_name) except HttpResponseError as error: _process_table_error(error) + return TableItem(name=result.table_name) # type: ignore @distributed_trace def delete_table( @@ -382,13 +385,12 @@ def create_entity( """ entity = _add_entity_properties(entity) try: - metadata, content = self._client.table.insert_entity( + metadata, content = self._client.table.insert_entity( # type: ignore table=self.table_name, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) - return _trim_service_metadata(metadata, content=content) except HttpResponseError as error: decoded = _decode_error(error.response, error.message) if decoded.error_code == "PropertiesNeedValue": @@ -397,6 +399,7 @@ def create_entity( if entity.get("RowKey") is None: raise ValueError("RowKey must be present in an entity") _reraise_error(error) + return _trim_service_metadata(metadata, content=content) # type: ignore @distributed_trace def update_entity( @@ -434,7 +437,7 @@ def update_entity( etag = kwargs.pop("etag", None) if match_condition and not etag: try: - etag = entity.metadata.get("etag", None) + etag = entity.metadata.get("etag", None) # type: ignore except (AttributeError, TypeError): pass if_match = _get_match_headers( @@ -449,30 +452,30 @@ def update_entity( metadata = None content = None if mode is UpdateMode.REPLACE: - metadata, content = self._client.table.update_entity( + metadata, content = self._client.table.update_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore if_match=if_match, cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) elif mode is UpdateMode.MERGE: - metadata, content = self._client.table.merge_entity( + metadata, content = self._client.table.merge_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, if_match=if_match, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) else: raise ValueError("Mode type is not supported") - return _trim_service_metadata(metadata, content=content) except HttpResponseError as error: _process_table_error(error) + return _trim_service_metadata(metadata, content=content) # type: ignore @distributed_trace def list_entities( @@ -541,12 +544,12 @@ def query_entities( """ parameters = kwargs.pop("parameters", None) query_filter = _parameter_filter_substitution( - parameters, query_filter + parameters, query_filter # type: ignore ) top = kwargs.pop("results_per_page", None) user_select = kwargs.pop("select", None) if user_select and not isinstance(user_select, str): - user_select = ",".join(user_select) + user_select = ",".join(user_select) # type: ignore command = functools.partial(self._client.table.query_entities, **kwargs) return ItemPaged( @@ -598,10 +601,9 @@ def get_entity( query_options=QueryOptions(select=user_select), **kwargs ) - properties = _convert_to_entity(entity) - return properties except HttpResponseError as error: _process_table_error(error) + return _convert_to_entity(entity) @distributed_trace def upsert_entity( @@ -638,20 +640,20 @@ def upsert_entity( metadata = None content = None if mode is UpdateMode.MERGE: - metadata, content = self._client.table.merge_entity( + metadata, content = self._client.table.merge_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) elif mode is UpdateMode.REPLACE: - metadata, content = self._client.table.update_entity( + metadata, content = self._client.table.update_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) @@ -662,9 +664,9 @@ def upsert_entity( mode ) ) - return _trim_service_metadata(metadata, content=content) except HttpResponseError as error: _process_table_error(error) + return _trim_service_metadata(metadata, content=content) # type: ignore def submit_transaction( self, @@ -704,11 +706,11 @@ def submit_transaction( ) for operation in operations: try: - operation_kwargs = operation[2] + operation_kwargs = operation[2] # type: ignore except IndexError: operation_kwargs = {} try: getattr(batched_requests, operation[0].lower())(operation[1], **operation_kwargs) except AttributeError: raise ValueError("Unrecognized operation: {}".format(operation[0])) - return self._batch_send(*batched_requests.requests, **kwargs) + return self._batch_send(*batched_requests.requests, **kwargs) # type: ignore 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 5bd6eaa9d8ac..0a0b279314fd 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 @@ -115,9 +115,9 @@ def get_service_stats(self, **kwargs): stats = self._client.service.get_statistics( # type: ignore timeout=timeout, use_location=LocationMode.SECONDARY, **kwargs ) - return service_stats_deserialize(stats) except HttpResponseError as error: _process_table_error(error) + return service_stats_deserialize(stats) @distributed_trace def get_service_properties(self, **kwargs): @@ -132,9 +132,9 @@ def get_service_properties(self, **kwargs): timeout = kwargs.pop("timeout", None) try: service_props = self._client.service.get_properties(timeout=timeout, **kwargs) # type: ignore - return service_properties_deserialize(service_props) except HttpResponseError as error: _process_table_error(error) + return service_properties_deserialize(service_props) @distributed_trace def set_service_properties( @@ -165,10 +165,10 @@ def set_service_properties( logging=analytics_logging, hour_metrics=hour_metrics, minute_metrics=minute_metrics, - cors=cors, + cors=cors, # type: ignore ) try: - return self._client.service.set_properties(props, **kwargs) # type: ignore + self._client.service.set_properties(props, **kwargs) except HttpResponseError as error: _process_table_error(error) @@ -324,7 +324,7 @@ def get_table_client(self, table_name, **kwargs): :rtype: :class:`~azure.data.tables.TableClient` """ - pipeline = Pipeline( + pipeline = Pipeline( # type: ignore transport=TransportWrapper(self._client._client._pipeline._transport), # pylint: disable = protected-access policies=self._policies ) diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_table_shared_access_signature.py b/sdk/tables/azure-data-tables/azure/data/tables/_table_shared_access_signature.py index 789aa935456c..d31f71b2d7e8 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_table_shared_access_signature.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_table_shared_access_signature.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -from typing import TYPE_CHECKING +from typing import Union, Any, TYPE_CHECKING from ._models import AccountSasPermissions from ._common_conversion import _sign_string @@ -16,13 +16,15 @@ ) if TYPE_CHECKING: - from typing import Any, Union + from datetime import datetime + from azure.core.credentials import AzureNamedKeyCredential + from ._models import ResourceTypes def generate_account_sas( credential, # type: AzureNamedKeyCredential resource_types, # type: ResourceTypes - permission, # type: Union[str,AccountSasPermissions] - expiry, # type: Union[datetime,str] + permission, # type: Union[str, AccountSasPermissions] + expiry, # type: Union[datetime, str] **kwargs # type: Any ): # type: (...) -> str @@ -72,7 +74,7 @@ def generate_account_sas( _validate_not_none("account_name", credential.named_key.name) _validate_not_none("account_key", credential.named_key.key) if permission is str: - permission = AccountSasPermissions.from_string(permission=permission) + permission = AccountSasPermissions.from_string(permission=permission) # type: ignore sas = TableSharedAccessSignature(credential) return sas.generate_account( "t", @@ -85,12 +87,8 @@ def generate_account_sas( ) -def generate_table_sas( - credential, # type: AzureNamedKeyCredential - table_name, # type: str - **kwargs # type: Any -): # type: (...) -> str - +def generate_table_sas(credential, table_name, **kwargs): + # type: (AzureNamedKeyCredential, str, **Any) -> str """ Generates a shared access signature for the table service. Use the returned signature with the sas_token parameter of TableService. diff --git a/sdk/tables/azure-data-tables/azure/data/tables/aio/_base_client_async.py b/sdk/tables/azure-data-tables/azure/data/tables/aio/_base_client_async.py index a82e774481be..736c00956a58 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/aio/_base_client_async.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/aio/_base_client_async.py @@ -69,15 +69,15 @@ async def close(self) -> None: def _configure_credential(self, credential): # type: (Any) -> None if hasattr(credential, "get_token"): - self._credential_policy = AsyncBearerTokenCredentialPolicy( + self._credential_policy = AsyncBearerTokenCredentialPolicy( # type: ignore credential, STORAGE_OAUTH_SCOPE ) elif isinstance(credential, SharedKeyCredentialPolicy): - self._credential_policy = credential + self._credential_policy = credential # type: ignore elif isinstance(credential, AzureSasCredential): - self._credential_policy = AzureSasCredentialPolicy(credential) + self._credential_policy = AzureSasCredentialPolicy(credential) # type: ignore elif isinstance(credential, AzureNamedKeyCredential): - self._credential_policy = SharedKeyCredentialPolicy(credential) + self._credential_policy = SharedKeyCredentialPolicy(credential) # type: ignore elif credential is not None: raise TypeError("Unsupported credential: {}".format(credential)) @@ -103,7 +103,7 @@ async def _batch_send(self, *reqs: "HttpRequest", **kwargs) -> List[Mapping[str, # Pop it here, so requests doesn't feel bad about additional kwarg policies = [StorageHeadersPolicy()] - changeset = HttpRequest("POST", None) + changeset = HttpRequest("POST", None) # type: ignore changeset.set_multipart_mixed( *reqs, policies=policies, boundary="changeset_{}".format(uuid4()) ) diff --git a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_batch_async.py b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_batch_async.py index 2a972bfe01dd..4c8e590cdafa 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_batch_async.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_batch_async.py @@ -54,7 +54,7 @@ def __init__( self.table_name = table_name self._partition_key = kwargs.pop("partition_key", None) - self.requests = [] + self.requests = [] # type: ignore def __len__(self): return len(self.requests) @@ -90,7 +90,7 @@ def create( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore if "PartitionKey" in temp and "RowKey" in temp: temp = _add_entity_properties(temp) @@ -216,13 +216,13 @@ def update( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore match_condition = kwargs.pop("match_condition", None) etag = kwargs.pop("etag", None) if match_condition and not etag: try: - etag = entity.metadata.get("etag", None) + etag = entity.metadata.get("etag", None) # type: ignore except (AttributeError, TypeError): pass if_match = _get_match_headers( @@ -352,9 +352,9 @@ def _batch_update_entity( ) self.requests.append(request) - _batch_update_entity.metadata = { + _batch_update_entity.metadata = { # type: ignore "url": "/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')" - } # type: ignore + } def _batch_merge_entity( self, @@ -458,7 +458,7 @@ def _batch_merge_entity( _transform_patch_to_cosmos_post(request) self.requests.append(request) - _batch_merge_entity.metadata = { + _batch_merge_entity.metadata = { # type: ignore "url": "/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')" } @@ -487,7 +487,7 @@ def delete( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore partition_key = temp["PartitionKey"] row_key = temp["RowKey"] @@ -495,7 +495,7 @@ def delete( etag = kwargs.pop("etag", None) if match_condition and not etag: try: - etag = entity.metadata.get("etag", None) + etag = entity.metadata.get("etag", None) # type: ignore except (AttributeError, TypeError): pass if_match = _get_match_headers( @@ -595,7 +595,7 @@ def _batch_delete_entity( ) self.requests.append(request) - _batch_delete_entity.metadata = { + _batch_delete_entity.metadata = { # type: ignore "url": "/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')" } @@ -625,7 +625,7 @@ def upsert( :caption: Creating and adding an entity to a Table """ self._verify_partition_key(entity) - temp = entity.copy() + temp = entity.copy() # type: ignore partition_key = temp["PartitionKey"] row_key = temp["RowKey"] 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 98c0dfffd695..6891f16db8cf 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 @@ -181,7 +181,7 @@ async def get_table_access_policy(self, **kwargs) -> Mapping[str, AccessPolicy]: return { s.id: s.access_policy or AccessPolicy(start=None, expiry=None, permission=None) - for s in identifiers + for s in identifiers # type: ignore } @distributed_trace_async @@ -204,17 +204,16 @@ async def set_table_access_policy( value.start = serialize_iso(value.start) value.expiry = serialize_iso(value.expiry) identifiers.append(SignedIdentifier(id=key, access_policy=value)) - signed_identifiers = identifiers # type: ignore try: await self._client.table.set_access_policy( - table=self.table_name, table_acl=signed_identifiers or None, **kwargs + table=self.table_name, table_acl=identifiers or None, **kwargs # type: ignore ) except HttpResponseError as error: try: _process_table_error(error) except HttpResponseError as table_error: - if (table_error.error_code == 'InvalidXmlDocument' - and len(signed_identifiers) > 5): + 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.' @@ -222,7 +221,7 @@ async def set_table_access_policy( raise @distributed_trace_async - async def create_table(self, **kwargs) -> None: + async def create_table(self, **kwargs) -> TableItem: """Creates a new table under the given account. :return: A TableItem representing the created table. @@ -241,9 +240,9 @@ async def create_table(self, **kwargs) -> None: table_properties = TableProperties(table_name=self.table_name) try: result = await self._client.table.create(table_properties, **kwargs) - return TableItem(name=result.table_name) except HttpResponseError as error: _process_table_error(error) + return TableItem(name=result.table_name) # type: ignore @distributed_trace_async async def delete_table(self, **kwargs) -> None: @@ -323,7 +322,7 @@ async def delete_entity(self, *args: Union[TableEntity, str], **kwargs: Any) -> etag = kwargs.pop("etag", None) if match_condition and entity and not etag: try: - etag = entity.metadata.get("etag", None) + etag = entity.metadata.get("etag", None) # type: ignore except (AttributeError, TypeError): pass if_match = _get_match_headers( @@ -370,13 +369,12 @@ async def create_entity( """ entity = _add_entity_properties(entity) try: - metadata, content = await self._client.table.insert_entity( + metadata, content = await self._client.table.insert_entity( # type: ignore table=self.table_name, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) - return _trim_service_metadata(metadata, content=content) except HttpResponseError as error: decoded = _decode_error(error.response, error.message) if decoded.error_code == "PropertiesNeedValue": @@ -385,6 +383,7 @@ async def create_entity( if entity.get("RowKey") is None: raise ValueError("RowKey must be present in an entity") _reraise_error(error) + return _trim_service_metadata(metadata, content=content) # type: ignore @distributed_trace_async @@ -422,7 +421,7 @@ async def update_entity( etag = kwargs.pop("etag", None) if match_condition and entity and not etag: try: - etag = entity.metadata.get("etag", None) + etag = entity.metadata.get("etag", None) # type: ignore except (AttributeError, TypeError): pass if_match = _get_match_headers( @@ -437,30 +436,30 @@ async def update_entity( metadata = None content = None if mode is UpdateMode.REPLACE: - metadata, content = await self._client.table.update_entity( + metadata, content = await self._client.table.update_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore if_match=if_match, cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) elif mode is UpdateMode.MERGE: - metadata, content = await self._client.table.merge_entity( + metadata, content = await self._client.table.merge_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, if_match=if_match, cls=kwargs.pop("cls", _return_headers_and_deserialized), - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore **kwargs ) else: raise ValueError("Mode type is not supported") - return _trim_service_metadata(metadata, content=content) except HttpResponseError as error: _process_table_error(error) + return _trim_service_metadata(metadata, content=content) # type: ignore @distributed_trace def list_entities(self, **kwargs) -> AsyncItemPaged[TableEntity]: @@ -582,9 +581,9 @@ async def get_entity( **kwargs ) properties = _convert_to_entity(entity) - return properties except HttpResponseError as error: _process_table_error(error) + return properties @distributed_trace_async async def upsert_entity( @@ -621,20 +620,20 @@ async def upsert_entity( metadata = None content = None if mode is UpdateMode.MERGE: - metadata, content = await self._client.table.merge_entity( + metadata, content = await self._client.table.merge_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) elif mode is UpdateMode.REPLACE: - metadata, content = await self._client.table.update_entity( + metadata, content = await self._client.table.update_entity( # type: ignore table=self.table_name, partition_key=partition_key, row_key=row_key, - table_entity_properties=entity, + table_entity_properties=entity, # type: ignore cls=kwargs.pop("cls", _return_headers_and_deserialized), **kwargs ) @@ -645,9 +644,9 @@ async def upsert_entity( mode ) ) - return _trim_service_metadata(metadata, content=content) except HttpResponseError as error: _process_table_error(error) + return _trim_service_metadata(metadata, content=content) # type: ignore @distributed_trace_async async def submit_transaction( @@ -687,7 +686,7 @@ async def submit_transaction( ) for operation in operations: try: - operation_kwargs = operation[2] + operation_kwargs = operation[2] # type: ignore except IndexError: operation_kwargs = {} try: 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 0ef872977c48..6c02387b0958 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 @@ -114,9 +114,9 @@ async def get_service_stats(self, **kwargs) -> Dict[str, Any]: stats = await self._client.service.get_statistics( # type: ignore timeout=timeout, use_location=LocationMode.SECONDARY, **kwargs ) - return service_stats_deserialize(stats) except HttpResponseError as error: _process_table_error(error) + return service_stats_deserialize(stats) @distributed_trace_async async def get_service_properties(self, **kwargs) -> Dict[str, object]: @@ -131,9 +131,9 @@ async def get_service_properties(self, **kwargs) -> Dict[str, object]: timeout = kwargs.pop("timeout", None) try: service_props = await self._client.service.get_properties(timeout=timeout, **kwargs) # type: ignore - return service_properties_deserialize(service_props) except HttpResponseError as error: _process_table_error(error) + return service_properties_deserialize(service_props) @distributed_trace_async async def set_service_properties( @@ -163,10 +163,10 @@ async def set_service_properties( logging=analytics_logging, hour_metrics=hour_metrics, minute_metrics=minute_metrics, - cors=cors, + cors=cors, # type: ignore ) try: - return await self._client.service.set_properties(props, **kwargs) # type: ignore + await self._client.service.set_properties(props, **kwargs) # type: ignore except HttpResponseError as error: _process_table_error(error) @@ -313,7 +313,7 @@ def get_table_client(self, table_name: str, **kwargs) -> TableClient: :rtype: :class:`~azure.data.tables.aio.TableClient` """ - pipeline = AsyncPipeline( + pipeline = AsyncPipeline( # type: ignore transport=AsyncTransportWrapper(self._client._client._pipeline._transport), # pylint:disable=protected-access policies=self._policies, ) diff --git a/sdk/tables/azure-data-tables/mypy.ini b/sdk/tables/azure-data-tables/mypy.ini index 46246be1772d..4e9d56b6a058 100644 --- a/sdk/tables/azure-data-tables/mypy.ini +++ b/sdk/tables/azure-data-tables/mypy.ini @@ -1,12 +1,11 @@ [mypy] -python_version = 3.8 -warn_return_any = True +python_version = 3.6 warn_unused_configs = True ignore_missing_imports = True # Per-module options: -[mypy-azure-table.azure.data.tables._generated.*] +[mypy-azure.data.tables._generated.*] ignore_errors = True [mypy-azure.core.*]