diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py b/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py index 22113fe67567..5f2ffcc8d34c 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/__init__.py @@ -6,6 +6,7 @@ import os +from typing import Union, Iterable, AnyStr, IO, Any # pylint: disable=unused-import from .version import VERSION from .blob_client import BlobClient from .container_client import ContainerClient diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_utils.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_utils.py index 5df46b463072..fe227df1ea4e 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_utils.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_utils.py @@ -7,6 +7,7 @@ import sys from io import BytesIO, SEEK_SET, UnsupportedOperation +from typing import Optional, Union, Any, TypeVar, TYPE_CHECKING # pylint: disable=unused-import import six from azure.core.exceptions import ResourceExistsError, ResourceModifiedError @@ -39,6 +40,9 @@ ) from .models import BlobProperties, ContainerProperties +if TYPE_CHECKING: + from datetime import datetime # pylint: disable=unused-import + LeaseClient = TypeVar("LeaseClient") _LARGE_BLOB_UPLOAD_MAX_READ_BUFFER_SIZE = 4 * 1024 * 1024 _ERROR_VALUE_SHOULD_BE_SEEKABLE_STREAM = '{0} should be a seekable file-like/io.IOBase type stream object.' @@ -60,9 +64,9 @@ def _convert_mod_error(error): def get_access_conditions(lease): # type: (Optional[Union[LeaseClient, str]]) -> Union[LeaseAccessConditions, None] try: - lease_id = lease.id + lease_id = lease.id # type: ignore except AttributeError: - lease_id = lease + lease_id = lease # type: ignore return LeaseAccessConditions(lease_id=lease_id) if lease_id else None diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py index db425b424052..4a2c4532d924 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/authentication.py @@ -12,8 +12,8 @@ try: from urllib.parse import urlparse, unquote except ImportError: - from urlparse import urlparse - from urllib2 import unquote + from urlparse import urlparse # type: ignore + from urllib2 import unquote # type: ignore from azure.core.exceptions import ClientAuthenticationError from azure.core.pipeline.policies import SansIOHTTPPolicy diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/constants.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/constants.py index f8d6eb2461d1..62886ccd7a7d 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/constants.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/constants.py @@ -17,7 +17,7 @@ if sys.version_info >= (3, 5): # the timeout to connect is 20 seconds, and the read timeout is 2000 seconds # the 2000 seconds was calculated with: 100MB (max block size)/ 50KB/s (an arbitrarily chosen minimum upload speed) - DEFAULT_SOCKET_TIMEOUT = (20, 2000) + DEFAULT_SOCKET_TIMEOUT = (20, 2000) # type: ignore STORAGE_OAUTH_SCOPE = "https://storage.azure.com/.default" diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py index bb2adc334c35..9f39bcd30d0e 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/models.py @@ -423,7 +423,7 @@ def __str__(self): ('f' if self.file else '')) -Services.BLOB = Services(blob=True) -Services.QUEUE = Services(queue=True) -Services.TABLE = Services(table=True) -Services.FILE = Services(file=True) +Services.BLOB = Services(blob=True) # type: ignore +Services.QUEUE = Services(queue=True) # type: ignore +Services.TABLE = Services(table=True) # type: ignore +Services.FILE = Services(file=True) # type: ignore diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/policies.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/policies.py index e0956d8745a4..fa9770a8e131 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/policies.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/policies.py @@ -14,6 +14,7 @@ import uuid import types import platform +from typing import Any, TYPE_CHECKING from wsgiref.handlers import format_date_time try: from urllib.parse import ( @@ -23,8 +24,8 @@ urlencode, ) except ImportError: - from urllib import urlencode - from urlparse import ( + from urllib import urlencode # type: ignore + from urlparse import ( # type: ignore urlparse, parse_qsl, urlunparse, @@ -42,10 +43,13 @@ from .models import LocationMode try: - _unicode_type = unicode + _unicode_type = unicode # type: ignore except NameError: _unicode_type = str +if TYPE_CHECKING: + from azure.core.pipeline import PipelineRequest, PipelineResponse + _LOGGER = logging.getLogger(__name__) @@ -274,7 +278,7 @@ def __init__(self, **kwargs): # pylint: disable=unused-argument super(StorageRequestHook, self).__init__() def on_request(self, request, **kwargs): - # type: (PipelineRequest) -> PipelineResponse + # type: (PipelineRequest, **Any) -> PipelineResponse request_callback = request.context.options.pop('raw_request_hook', self._request_callback) if request_callback: request_callback(request) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/utils.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/utils.py index 1d7e2a6a9eb5..6d980d967891 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/utils.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/utils.py @@ -5,7 +5,7 @@ # -------------------------------------------------------------------------- from typing import ( # pylint: disable=unused-import - Union, Optional, Any, Iterable, Dict, List, Type, + Union, Optional, Any, Iterable, Dict, List, Type, Tuple, TYPE_CHECKING ) import base64 @@ -18,8 +18,8 @@ try: from urllib.parse import quote, unquote, parse_qs except ImportError: - from urlparse import parse_qs - from urllib2 import quote, unquote + from urlparse import parse_qs # type: ignore + from urllib2 import quote, unquote # type: ignore import six import isodate @@ -118,7 +118,7 @@ def to_list(): class StorageAccountHostsMixin(object): def __init__( - self, parsed_url, # type: str + self, parsed_url, # type: Any service, # type: str credential=None, # type: Optional[Any] **kwargs # type: Any @@ -485,7 +485,7 @@ def create_configuration(**kwargs): def create_pipeline(credential, **kwargs): - # type: (Configuration, Optional[HTTPPolicy], **Any) -> Tuple[Configuration, Pipeline] + # type: (Any, **Any) -> Tuple[Configuration, Pipeline] credential_policy = None if hasattr(credential, 'get_token'): credential_policy = BearerTokenCredentialPolicy(credential, STORAGE_OAUTH_SCOPE) @@ -540,7 +540,6 @@ def is_credential_sastoken(credential): def add_metadata_headers(metadata): - # type: (Dict[str, str]) -> Dict[str, str] headers = {} if metadata: for key, value in metadata.items(): diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py index d14b794f1252..6caccd84d4d9 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_client.py @@ -13,8 +13,8 @@ try: from urllib.parse import urlparse, quote, unquote except ImportError: - from urlparse import urlparse - from urllib2 import quote, unquote + from urlparse import urlparse # type: ignore + from urllib2 import quote, unquote # type: ignore import six @@ -117,20 +117,20 @@ def __init__( path_snapshot, sas_token = parse_query(parsed_url.query) try: - self.container_name = container.name + self.container_name = container.name # type: ignore except AttributeError: - self.container_name = container or unquote(path_container) + self.container_name = container or unquote(path_container) # type: ignore try: - self.snapshot = snapshot.snapshot + self.snapshot = snapshot.snapshot # type: ignore except AttributeError: try: - self.snapshot = snapshot['snapshot'] + self.snapshot = snapshot['snapshot'] # type: ignore except TypeError: self.snapshot = snapshot or path_snapshot try: - self.blob_name = blob.name + self.blob_name = blob.name # type: ignore if not snapshot: - self.snapshot = blob.snapshot + self.snapshot = blob.snapshot # type: ignore except AttributeError: self.blob_name = blob or unquote(path_blob) self._query_str, credential = self._format_query_string(sas_token, credential, self.snapshot) @@ -195,7 +195,7 @@ def generate_shared_access_signature( content_language=None, # type: Optional[str] content_type=None # type: Optional[str] ): - # type: (...) -> str + # type: (...) -> Any """ Generates a shared access signature for the blob. Use the returned signature with the credential parameter of any BlobServiceClient, @@ -273,7 +273,7 @@ def generate_shared_access_signature( content_type=content_type, ) - def get_account_information(self, **kwargs): + def get_account_information(self, **kwargs): # type: ignore # type: (Optional[int]) -> Dict[str, str] """Gets information related to the storage account in which the blob resides. The information can also be retrieved if the user has a SAS to a container or blob. @@ -282,7 +282,7 @@ def get_account_information(self, **kwargs): :rtype: dict(str, str) """ try: - return self._client.blob.get_account_info(cls=return_response_headers, **kwargs) + return self._client.blob.get_account_info(cls=return_response_headers, **kwargs) # type: ignore except StorageErrorException as error: process_storage_error(error) @@ -306,7 +306,7 @@ def upload_blob( # pylint: disable=too-many-locals encoding='UTF-8', # type: str **kwargs ): - # type: (...) -> Dict[str, Union[str, datetime]] + # type: (...) -> Any """ Creates a new blob from a data source with automatic chunking. @@ -399,7 +399,7 @@ def upload_blob( # pylint: disable=too-many-locals cek, iv, encryption_data = _generate_blob_encryption_data(self.key_encryption_key) if isinstance(data, six.text_type): - data = data.encode(encoding) + data = data.encode(encoding) # type: ignore if length is None: length = get_length(data) if isinstance(data, bytes): @@ -665,7 +665,7 @@ def delete_blob( process_storage_error(error) def undelete_blob(self, timeout=None, **kwargs): - # type: (Optional[int]) -> None + # type: (Optional[int], **Any) -> None """Restores soft-deleted blobs or snapshots. Operation will only be successful if used within the specified number of days @@ -754,7 +754,7 @@ def get_blob_properties( process_storage_error(error) blob_props.name = self.blob_name blob_props.container = self.container_name - return blob_props + return blob_props # type: ignore def set_http_headers( self, content_settings=None, # type: Optional[ContentSettings] @@ -806,16 +806,18 @@ def set_http_headers( access_conditions = get_access_conditions(lease) mod_conditions = get_modification_conditions( if_modified_since, if_unmodified_since, if_match, if_none_match) - blob_headers = BlobHTTPHeaders( - blob_cache_control=content_settings.cache_control, - blob_content_type=content_settings.content_type, - blob_content_md5=bytearray(content_settings.content_md5) if content_settings.content_md5 else None, - blob_content_encoding=content_settings.content_encoding, - blob_content_language=content_settings.content_language, - blob_content_disposition=content_settings.content_disposition - ) + blob_headers = None + if content_settings: + blob_headers = BlobHTTPHeaders( + blob_cache_control=content_settings.cache_control, + blob_content_type=content_settings.content_type, + blob_content_md5=bytearray(content_settings.content_md5) if content_settings.content_md5 else None, + blob_content_encoding=content_settings.content_encoding, + blob_content_language=content_settings.content_language, + blob_content_disposition=content_settings.content_disposition + ) try: - return self._client.blob.set_http_headers( + return self._client.blob.set_http_headers( # type: ignore timeout=timeout, blob_http_headers=blob_headers, lease_access_conditions=access_conditions, @@ -825,7 +827,7 @@ def set_http_headers( except StorageErrorException as error: process_storage_error(error) - def set_blob_metadata( + def set_blob_metadata( # type: ignore self, metadata=None, # type: Optional[Dict[str, str]] lease=None, # type: Optional[Union[LeaseClient, str]] if_modified_since=None, # type: Optional[datetime] @@ -879,7 +881,7 @@ def set_blob_metadata( mod_conditions = get_modification_conditions( if_modified_since, if_unmodified_since, if_match, if_none_match) try: - return self._client.blob.set_metadata( + return self._client.blob.set_metadata( # type: ignore timeout=timeout, lease_access_conditions=access_conditions, modified_access_conditions=mod_conditions, @@ -889,7 +891,7 @@ def set_blob_metadata( except StorageErrorException as error: process_storage_error(error) - def create_page_blob( + def create_page_blob( # type: ignore self, size, # type: int content_settings=None, # type: Optional[ContentSettings] sequence_number=None, # type: Optional[int] @@ -974,10 +976,10 @@ def create_page_blob( try: if premium_page_blob_tier: try: - headers['x-ms-access-tier'] = premium_page_blob_tier.value + headers['x-ms-access-tier'] = premium_page_blob_tier.value # type: ignore except AttributeError: - headers['x-ms-access-tier'] = premium_page_blob_tier - return self._client.page_blob.create( + headers['x-ms-access-tier'] = premium_page_blob_tier # type: ignore + return self._client.page_blob.create( # type: ignore content_length=0, blob_content_length=size, blob_sequence_number=sequence_number, @@ -992,7 +994,7 @@ def create_page_blob( except StorageErrorException as error: process_storage_error(error) - def create_append_blob( + def create_append_blob( # type: ignore self, content_settings=None, # type: Optional[ContentSettings] metadata=None, # type: Optional[Dict[str, str]] lease=None, # type: Optional[Union[LeaseClient, str]] @@ -1060,7 +1062,7 @@ def create_append_blob( blob_content_disposition=content_settings.content_disposition ) try: - return self._client.append_blob.create( + return self._client.append_blob.create( # type: ignore content_length=0, blob_http_headers=blob_headers, timeout=timeout, @@ -1073,7 +1075,7 @@ def create_append_blob( except StorageErrorException as error: process_storage_error(error) - def create_snapshot( + def create_snapshot( # type: ignore self, metadata=None, # type: Optional[Dict[str, str]] if_modified_since=None, # type: Optional[datetime] if_unmodified_since=None, # type: Optional[datetime] @@ -1141,7 +1143,7 @@ def create_snapshot( mod_conditions = get_modification_conditions( if_modified_since, if_unmodified_since, if_match, if_none_match) try: - return self._client.blob.create_snapshot( + return self._client.blob.create_snapshot( # type: ignore timeout=timeout, lease_access_conditions=access_conditions, modified_access_conditions=mod_conditions, @@ -1303,7 +1305,7 @@ def copy_blob_from_url( # pylint: disable=too-many-locals headers.update(add_metadata_headers(metadata)) if source_lease: try: - headers['x-ms-source-lease-id'] = source_lease.id + headers['x-ms-source-lease-id'] = source_lease.id # type: ignore except AttributeError: headers['x-ms-source-lease-id'] = source_lease if premium_page_blob_tier: @@ -1409,7 +1411,7 @@ def acquire_lease( :dedent: 8 :caption: Acquiring a lease on a blob. """ - lease = LeaseClient(self, lease_id=lease_id) + lease = LeaseClient(self, lease_id=lease_id) # type: ignore lease.acquire( lease_duration=lease_duration, if_modified_since=if_modified_since, @@ -1498,7 +1500,7 @@ def stage_block( raise ValueError(_ERROR_UNSUPPORTED_METHOD_FOR_ENCRYPTION) block_id = encode_base64(str(block_id)) if isinstance(data, six.text_type): - data = data.encode(encoding) + data = data.encode(encoding) # type: ignore access_conditions = get_access_conditions(lease) if length is None: length = get_length(data) @@ -1608,15 +1610,15 @@ def get_block_list( **kwargs) except StorageErrorException as error: process_storage_error(error) - committed = [] - uncommitted = [] + committed = [] # type: List + uncommitted = [] # type: List if blocks.committed_blocks: committed = [BlobBlock._from_generated(b) for b in blocks.committed_blocks] # pylint: disable=protected-access if blocks.uncommitted_blocks: uncommitted = [BlobBlock._from_generated(b) for b in blocks.uncommitted_blocks] # pylint: disable=protected-access return committed, uncommitted - def commit_block_list( + def commit_block_list( # type: ignore self, block_list, # type: List[BlobBlock] lease=None, # type: Optional[Union[LeaseClient, str]] content_settings=None, # type: Optional[ContentSettings] @@ -1706,7 +1708,7 @@ def commit_block_list( blob_content_disposition=content_settings.content_disposition ) try: - return self._client.block_blob.commit_block_list( + return self._client.block_blob.commit_block_list( # type: ignore block_lookup, blob_http_headers=blob_headers, lease_access_conditions=access_conditions, @@ -1719,7 +1721,7 @@ def commit_block_list( process_storage_error(error) def set_premium_page_blob_tier(self, premium_page_blob_tier, timeout=None, lease=None, **kwargs): - # type: (Union[str, PremiumPageBlobTier], Optional[int], Optional[Union[LeaseClient, str]]) -> None + # type: (Union[str, PremiumPageBlobTier], Optional[int], Optional[Union[LeaseClient, str]], **Any) -> None """Sets the page blob tiers on the blob. This API is only supported for page blobs on premium accounts. :param premium_page_blob_tier: @@ -1749,7 +1751,7 @@ def set_premium_page_blob_tier(self, premium_page_blob_tier, timeout=None, lease except StorageErrorException as error: process_storage_error(error) - def get_page_ranges( + def get_page_ranges( # type: ignore self, start_range=None, # type: Optional[int] end_range=None, # type: Optional[int] lease=None, # type: Optional[Union[LeaseClient, str]] @@ -1816,7 +1818,7 @@ def get_page_ranges( access_conditions = get_access_conditions(lease) mod_conditions = get_modification_conditions( if_modified_since, if_unmodified_since, if_match, if_none_match) - page_range = None + page_range = None # type: ignore if start_range is not None and end_range is None: page_range = str(start_range) elif start_range is not None and end_range is not None: @@ -1824,10 +1826,10 @@ def get_page_ranges( try: if previous_snapshot_diff: try: - prev_snapshot = previous_snapshot_diff.snapshot + prev_snapshot = previous_snapshot_diff.snapshot # type: ignore except AttributeError: try: - prev_snapshot = previous_snapshot_diff['snapshot'] + prev_snapshot = previous_snapshot_diff['snapshot'] # type: ignore except TypeError: prev_snapshot = previous_snapshot_diff ranges = self._client.page_blob.get_page_ranges_diff( @@ -1850,15 +1852,15 @@ def get_page_ranges( ) except StorageErrorException as error: process_storage_error(error) - page_range = [] - clear_range = [] + page_range = [] # type: ignore + clear_range = [] # type: List if ranges.page_range: - page_range = [{'start': b.start, 'end': b.end} for b in ranges.page_range] + page_range = [{'start': b.start, 'end': b.end} for b in ranges.page_range] # type: ignore if ranges.clear_range: clear_range = [{'start': b.start, 'end': b.end} for b in ranges.clear_range] - return page_range, clear_range + return page_range, clear_range # type: ignore - def set_sequence_number( + def set_sequence_number( # type: ignore self, sequence_number_action, # type: Union[str, SequenceNumberAction] sequence_number=None, # type: Optional[str] lease=None, # type: Optional[Union[LeaseClient, str]] @@ -1915,7 +1917,7 @@ def set_sequence_number( if sequence_number_action is None: raise ValueError("A sequence number action must be specified") try: - return self._client.page_blob.update_sequence_number( + return self._client.page_blob.update_sequence_number( # type: ignore sequence_number_action=sequence_number_action, timeout=timeout, blob_sequence_number=sequence_number, @@ -1926,7 +1928,7 @@ def set_sequence_number( except StorageErrorException as error: process_storage_error(error) - def resize_blob( + def resize_blob( # type: ignore self, size, # type: int lease=None, # type: Optional[Union[LeaseClient, str]] if_modified_since=None, # type: Optional[datetime] @@ -1979,7 +1981,7 @@ def resize_blob( if size is None: raise ValueError("A content length must be specified for a Page Blob.") try: - return self._client.page_blob.resize( + return self._client.page_blob.resize( # type: ignore blob_content_length=size, timeout=timeout, lease_access_conditions=access_conditions, @@ -1989,7 +1991,7 @@ def resize_blob( except StorageErrorException as error: process_storage_error(error) - def upload_page( + def upload_page( # type: ignore self, page, # type: bytes start_range, # type: int end_range, # type: int @@ -2085,7 +2087,7 @@ def upload_page( raise ValueError("start_range must be an integer that aligns with 512 page size") if end_range is None or end_range % 512 != 511: raise ValueError("end_range must be an integer that aligns with 512 page size") - content_range = 'bytes={0}-{1}'.format(start_range, end_range) + content_range = 'bytes={0}-{1}'.format(start_range, end_range) # type: ignore access_conditions = get_access_conditions(lease) seq_conditions = get_sequence_conditions( if_sequence_number_lte=if_sequence_number_lte, @@ -2095,7 +2097,7 @@ def upload_page( mod_conditions = get_modification_conditions( if_modified_since, if_unmodified_since, if_match, if_none_match) try: - return self._client.page_blob.upload_pages( + return self._client.page_blob.upload_pages( # type: ignore page[:length], content_length=length, transactional_content_md5=None, @@ -2110,7 +2112,7 @@ def upload_page( except StorageErrorException as error: process_storage_error(error) - def clear_page( + def clear_page( # type: ignore self, start_range, # type: int end_range, # type: int lease=None, # type: Optional[Union[LeaseClient, str]] @@ -2191,7 +2193,7 @@ def clear_page( raise ValueError("end_range must be an integer that aligns with 512 page size") content_range = 'bytes={0}-{1}'.format(start_range, end_range) try: - return self._client.page_blob.clear_pages( + return self._client.page_blob.clear_pages( # type: ignore content_length=0, timeout=timeout, range=content_range, @@ -2203,7 +2205,7 @@ def clear_page( except StorageErrorException as error: process_storage_error(error) - def append_block( + def append_block( # type: ignore self, data, # type: Union[Iterable[AnyStr], IO[AnyStr]] length=None, # type: Optional[int] validate_content=False, # type: Optional[bool] @@ -2279,7 +2281,7 @@ def append_block( raise ValueError(_ERROR_UNSUPPORTED_METHOD_FOR_ENCRYPTION) if isinstance(data, six.text_type): - data = data.encode(encoding) + data = data.encode(encoding) # type: ignore if length is None: length = get_length(data) if length is None: @@ -2296,10 +2298,10 @@ def append_block( append_position=appendpos_condition ) access_conditions = get_access_conditions(lease) - mod_conditions = get_modification_conditions( + mod_conditions = get_modification_conditions( # type: ignore if_modified_since, if_unmodified_since, if_match, if_none_match) try: - return self._client.append_blob.append_block( + return self._client.append_blob.append_block( # type: ignore data, content_length=length, timeout=timeout, diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py index c4ef9c073def..fd171cf5e814 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/blob_service_client.py @@ -12,7 +12,7 @@ try: from urllib.parse import urlparse except ImportError: - from urlparse import urlparse + from urlparse import urlparse # type: ignore from ._shared.shared_access_signature import SharedAccessSignature from ._shared.models import LocationMode, Services @@ -40,7 +40,8 @@ Metrics, RetentionPolicy, StaticWebsite, - CorsRule + CorsRule, + PublicAccess ) @@ -187,9 +188,9 @@ def generate_shared_access_signature( sas = SharedAccessSignature(self.credential.account_name, self.credential.account_key) return sas.generate_account( - Services.BLOB, resource_types, permission, expiry, start=start, ip=ip, protocol=protocol) + Services.BLOB, resource_types, permission, expiry, start=start, ip=ip, protocol=protocol) # type: ignore - def get_account_information(self, **kwargs): + def get_account_information(self, **kwargs): # type: ignore # type: (Optional[int]) -> Dict[str, str] """Gets information related to the storage account. The information can also be retrieved if the user has a SAS to a container or blob. @@ -206,11 +207,11 @@ def get_account_information(self, **kwargs): :caption: Getting account information for the blob service. """ try: - return self._client.service.get_account_info(cls=return_response_headers, **kwargs) + return self._client.service.get_account_info(cls=return_response_headers, **kwargs) # type: ignore except StorageErrorException as error: process_storage_error(error) - def get_service_stats(self, timeout=None, **kwargs): + def get_service_stats(self, timeout=None, **kwargs): # type: ignore # type: (Optional[int], **Any) -> Dict[str, Any] """Retrieves statistics related to replication for the Blob service. It is only available when read-access geo-redundant replication is enabled for @@ -243,7 +244,7 @@ def get_service_stats(self, timeout=None, **kwargs): :caption: Getting service stats for the blob service. """ try: - return self._client.service.get_statistics( + return self._client.service.get_statistics( # type: ignore timeout=timeout, use_location=LocationMode.SECONDARY, **kwargs) except StorageErrorException as error: process_storage_error(error) @@ -483,8 +484,8 @@ def delete_container( :dedent: 12 :caption: Deleting a container in the blob service. """ - container = self.get_container_client(container) - container.delete_container( + container = self.get_container_client(container) # type: ignore + container.delete_container( # type: ignore lease=lease, if_modified_since=if_modified_since, if_unmodified_since=if_unmodified_since, @@ -523,7 +524,7 @@ def get_container_client(self, container): def get_blob_client( self, container, # type: Union[ContainerProperties, str] blob, # type: Union[BlobProperties, str] - snapshot=None # type: Optional[Union[SnapshotProperties, str]] + snapshot=None # type: Optional[Union[Dict[str, Any], str]] ): # type: (...) -> BlobClient """Get a client to interact with the specified blob. @@ -550,7 +551,7 @@ def get_blob_client( :dedent: 12 :caption: Getting the blob client to interact with a specific blob. """ - return BlobClient( + return BlobClient( # type: ignore self.url, container=container, blob=blob, snapshot=snapshot, credential=self.credential, _configuration=self._config, _pipeline=self._pipeline, _location_mode=self._location_mode, _hosts=self._hosts, diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py index cc388a3034d3..bfd7c53f8539 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/container_client.py @@ -6,15 +6,15 @@ import functools from typing import ( # pylint: disable=unused-import - Union, Optional, Any, Iterable, AnyStr, Dict, List, Tuple, + Union, Optional, Any, Iterable, AnyStr, Dict, List, Tuple, IO, TYPE_CHECKING ) try: from urllib.parse import urlparse, quote, unquote except ImportError: - from urlparse import urlparse - from urllib2 import quote, unquote + from urlparse import urlparse # type: ignore + from urllib2 import quote, unquote # type: ignore import six @@ -36,7 +36,7 @@ get_access_conditions, get_modification_conditions, deserialize_container_properties) -from .models import ( +from .models import ( # pylint: disable=unused-import ContainerProperties, BlobProperties, BlobPropertiesPaged, @@ -50,6 +50,10 @@ from azure.core.pipeline.policies import HTTPPolicy from .models import ContainerPermissions, PublicAccess from datetime import datetime + from .models import ( # pylint: disable=unused-import + AccessPolicy, + ContentSettings, + PremiumPageBlobTier) class ContainerClient(StorageAccountHostsMixin): @@ -79,7 +83,7 @@ class ContainerClient(StorageAccountHostsMixin): """ def __init__( self, container_url, # type: str - container=None, # type: Union[ContainerProperties, str] + container=None, # type: Optional[Union[ContainerProperties, str]] credential=None, # type: Optional[Any] **kwargs # type: Any ): @@ -100,9 +104,9 @@ def __init__( path_container = parsed_url.path.lstrip('/').partition('/')[0] _, sas_token = parse_query(parsed_url.query) try: - self.container_name = container.name + self.container_name = container.name # type: ignore except AttributeError: - self.container_name = container or unquote(path_container) + self.container_name = container or unquote(path_container) # type: ignore self._query_str, credential = self._format_query_string(sas_token, credential) super(ContainerClient, self).__init__(parsed_url, 'blob', credential, **kwargs) self._client = AzureBlobStorage(self.url, pipeline=self._pipeline) @@ -156,7 +160,7 @@ def generate_shared_access_signature( content_language=None, # type: Optional[str] content_type=None # type: Optional[str] ): - # type: (...) -> str + # type: (...) -> Any """Generates a shared access signature for the container. Use the returned signature with the credential parameter of any BlobServiceClient, ContainerClient or BlobClient. @@ -240,7 +244,7 @@ def generate_shared_access_signature( ) def create_container(self, metadata=None, public_access=None, timeout=None, **kwargs): - # type: (Optional[Dict[str, str]], Optional[Union[PublicAccess, str]], Optional[int]) -> None + # type: (Optional[Dict[str, str]], Optional[Union[PublicAccess, str]], Optional[int], **Any) -> None """ Creates a new container under the specified account. If the container with the same name already exists, the operation fails. @@ -264,9 +268,9 @@ def create_container(self, metadata=None, public_access=None, timeout=None, **kw :caption: Creating a container to store blobs. """ headers = kwargs.pop('headers', {}) - headers.update(add_metadata_headers(metadata)) + headers.update(add_metadata_headers(metadata)) # type: ignore try: - return self._client.container.create( + return self._client.container.create( # type: ignore timeout=timeout, access=public_access, cls=return_response_headers, @@ -395,7 +399,7 @@ def acquire_lease( :dedent: 8 :caption: Acquiring a lease on the container. """ - lease = LeaseClient(self, lease_id=lease_id) + lease = LeaseClient(self, lease_id=lease_id) # type: ignore lease.acquire( lease_duration=lease_duration, if_modified_since=if_modified_since, @@ -406,8 +410,8 @@ def acquire_lease( **kwargs) return lease - def get_account_information(self, **kwargs): - # type: (Optional[int]) -> Dict[str, str] + def get_account_information(self, **kwargs): # type: ignore + # type: (**Any) -> Dict[str, str] """Gets information related to the storage account. The information can also be retrieved if the user has a SAS to a container or blob. @@ -415,7 +419,7 @@ def get_account_information(self, **kwargs): :rtype: dict(str, str) """ try: - return self._client.container.get_account_info(cls=return_response_headers, **kwargs) + return self._client.container.get_account_info(cls=return_response_headers, **kwargs) # type: ignore except StorageErrorException as error: process_storage_error(error) @@ -450,9 +454,9 @@ def get_container_properties(self, lease=None, timeout=None, **kwargs): except StorageErrorException as error: process_storage_error(error) response.name = self.container_name - return response + return response # type: ignore - def set_container_metadata( + def set_container_metadata( # type: ignore self, metadata=None, # type: Optional[Dict[str, str]] lease=None, # type: Optional[Union[str, LeaseClient]] if_modified_since=None, # type: Optional[datetime] @@ -495,7 +499,7 @@ def set_container_metadata( access_conditions = get_access_conditions(lease) mod_conditions = get_modification_conditions(if_modified_since) try: - return self._client.container.set_metadata( + return self._client.container.set_metadata( # type: ignore timeout=timeout, lease_access_conditions=access_conditions, modified_access_conditions=mod_conditions, @@ -506,7 +510,7 @@ def set_container_metadata( process_storage_error(error) def get_container_access_policy(self, lease=None, timeout=None, **kwargs): - # type: (Optional[Union[LeaseClient, str]], Optional[int]) -> Dict[str, str] + # type: (Optional[Union[LeaseClient, str]], Optional[int], **Any) -> Dict[str, Any] """Gets the permissions for the specified container. The permissions indicate whether container data may be accessed publicly. @@ -598,8 +602,8 @@ def set_container_access_policy( if value: value.start = serialize_iso(value.start) value.expiry = serialize_iso(value.expiry) - identifiers.append(SignedIdentifier(id=key, access_policy=value)) - signed_identifiers = identifiers + identifiers.append(SignedIdentifier(id=key, access_policy=value)) # type: ignore + signed_identifiers = identifiers # type: ignore mod_conditions = get_modification_conditions( if_modified_since, if_unmodified_since) @@ -617,7 +621,7 @@ def set_container_access_policy( process_storage_error(error) def list_blobs(self, name_starts_with=None, include=None, marker=None, timeout=None, **kwargs): - # type: (Optional[str], Optional[Include], Optional[int]) -> Iterable[BlobProperties] + # type: (Optional[str], Optional[Any], Optional[str], Optional[int], **Any) -> Iterable[BlobProperties] """Returns a generator to list the blobs under the specified container. The generator will lazily follow the continuation tokens returned by the service. @@ -655,8 +659,15 @@ def list_blobs(self, name_starts_with=None, include=None, marker=None, timeout=N **kwargs) return BlobPropertiesPaged(command, prefix=name_starts_with, results_per_page=results_per_page, marker=marker) - def walk_blobs(self, name_starts_with=None, include=None, delimiter="/", marker=None, timeout=None, **kwargs): - # type: (Optional[str], Optional[Include], Optional[int]) -> Iterable[BlobProperties] + def walk_blobs( + self, name_starts_with=None, # type: Optional[str] + include=None, # type: Optional[Any] + delimiter="/", # type: str + marker=None, # type: Optional[str] + timeout=None, # type: Optional[int] + **kwargs # type: Optional[Any] + ): + # type: (...) -> Iterable[BlobProperties] """ Returns a generator to list the blobs under the specified container. The generator will lazily follow the continuation tokens returned by @@ -720,7 +731,7 @@ def upload_blob( encoding='UTF-8', # type: str **kwargs ): - # type: (...) -> Dict[str, Union[str, datetime]] + # type: (...) -> BlobClient """ Creates a new blob from a data source with automatic chunking. @@ -896,8 +907,8 @@ def delete_blob( The timeout parameter is expressed in seconds. :rtype: None """ - blob = self.get_blob_client(blob) - blob.delete_blob( + blob = self.get_blob_client(blob) # type: ignore + blob.delete_blob( # type: ignore delete_snapshots=delete_snapshots, lease=lease, if_modified_since=if_modified_since, diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/lease.py b/sdk/storage/azure-storage-blob/azure/storage/blob/lease.py index bab055cef04f..3765377ece5b 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/lease.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/lease.py @@ -8,7 +8,7 @@ from typing import ( # pylint: disable=unused-import Union, Optional, Any, IO, Iterable, AnyStr, Dict, List, Tuple, - TYPE_CHECKING + TypeVar, TYPE_CHECKING ) from ._shared.utils import return_response_headers, process_storage_error @@ -19,6 +19,8 @@ from datetime import datetime from ._generated.operations import BlobOperations, ContainerOperations +BlobClient = TypeVar("BlobClient") +ContainerClient = TypeVar("ContainerClient") class LeaseClient(object): """Creates a new LeaseClient. This client provides lease operations on @@ -35,9 +37,9 @@ def __init__(self, client, lease_id=None): self.last_modified = None self.etag = None if hasattr(client, 'blob_name'): - self._client = client._client.blob # pylint: disable=protected-access + self._client = client._client.blob # type: ignore # pylint: disable=protected-access elif hasattr(client, 'container_name'): - self._client = client._client.container # pylint: disable=protected-access + self._client = client._client.container # type: ignore # pylint: disable=protected-access else: raise TypeError("Lease must use either BlobClient or ContainerClient.") @@ -324,4 +326,4 @@ def break_lease( **kwargs) except StorageErrorException as error: process_storage_error(error) - return response.get('lease_time') + return response.get('lease_time') # type: ignore diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/models.py b/sdk/storage/azure-storage-blob/azure/storage/blob/models.py index c0bf87a9a7b1..9343a6176298 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/models.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/models.py @@ -7,6 +7,7 @@ # pylint: disable=super-init-not-called, too-many-lines from enum import Enum +from typing import List, Any, TYPE_CHECKING # pylint: disable=unused-import from azure.core.paging import Paged @@ -307,7 +308,6 @@ def __init__(self, command, prefix=None, results_per_page=None, marker=None): self.location_mode = None def _advance_page(self): - # type: () -> List[Model] """Force moving the cursor to the next azure call. This method is for advanced usage, iterator protocol is prefered. @@ -336,7 +336,7 @@ def _advance_page(self): self.next_marker = self._response.next_marker or None return self.current_page - def __next__(self): + def __next__(self): # type: ignore item = super(ContainerPropertiesPaged, self).__next__() if isinstance(item, ContainerProperties): return item @@ -497,7 +497,6 @@ def __init__( self.location_mode = location_mode def _advance_page(self): - # type: () -> List[Model] """Force moving the cursor to the next azure call. This method is for advanced usage, iterator protocol is prefered. @@ -554,7 +553,6 @@ def __init__(self, *args, **kwargs): self.name = self.prefix def _advance_page(self): - # type: () -> List[Model] """Force moving the cursor to the next azure call. This method is for advanced usage, iterator protocol is prefered. diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/polling.py b/sdk/storage/azure-storage-blob/azure/storage/blob/polling.py index 421cf5ccd842..fe3aac7a55cb 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/polling.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/polling.py @@ -6,7 +6,7 @@ import logging import time - +from typing import Callable, Any # pylint: disable=unused-import from azure.core.polling import PollingMethod, LROPoller from ._shared.utils import process_storage_error @@ -60,7 +60,7 @@ def _update_status(self): self.last_modified = self.blob.last_modified def initialize(self, client, initial_status, _): # pylint: disable=arguments-differ - # type: (Any, requests.Response, Callable) -> None + # type: (Any, Any, Callable) -> None self._client = client if isinstance(initial_status, str): self.id = initial_status @@ -122,9 +122,9 @@ def status(self): :rtype: str """ try: - return self._status.value + return self._status.value # type: ignore except AttributeError: - return self._status + return self._status # type: ignore def resource(self): # type: () -> Any