1# pylint: disable=too-many-lines
2# -------------------------------------------------------------------------
3# Copyright (c) Microsoft Corporation. All rights reserved.
4# Licensed under the MIT License. See License.txt in the project root for
5# license information.
6# --------------------------------------------------------------------------
7# pylint: disable=invalid-overridden-method
8import functools
9from typing import (  # pylint: disable=unused-import
10    Union, Optional, Any, Iterable, AnyStr, Dict, List, IO, AsyncIterator,
11    TYPE_CHECKING
12)
13
14from azure.core.tracing.decorator import distributed_trace
15from azure.core.tracing.decorator_async import distributed_trace_async
16from azure.core.async_paging import AsyncItemPaged
17from azure.core.pipeline import AsyncPipeline
18from azure.core.pipeline.transport import AsyncHttpResponse
19
20from .._shared.base_client_async import AsyncStorageAccountHostsMixin, AsyncTransportWrapper
21from .._shared.policies_async import ExponentialRetry
22from .._shared.request_handlers import add_metadata_headers, serialize_iso
23from .._shared.response_handlers import (
24    process_storage_error,
25    return_response_headers,
26    return_headers_and_deserialized)
27from .._generated import VERSION
28from .._generated.aio import AzureBlobStorage
29from .._generated.models import (
30    StorageErrorException,
31    SignedIdentifier)
32from .._deserialize import deserialize_container_properties
33from .._serialize import get_modify_conditions, get_container_cpk_scope_info, get_api_version
34from .._container_client import ContainerClient as ContainerClientBase, _get_blob_name
35from .._lease import get_access_conditions
36from .._models import ContainerProperties, BlobType, BlobProperties  # pylint: disable=unused-import
37from ._list_blobs_helper import BlobPropertiesPaged, BlobPrefix
38from ._lease_async import BlobLeaseClient
39from ._blob_client_async import BlobClient
40
41if TYPE_CHECKING:
42    from .._models import PublicAccess
43    from ._download_async import StorageStreamDownloader
44    from datetime import datetime
45    from .._models import ( # pylint: disable=unused-import
46        AccessPolicy,
47        StandardBlobTier,
48        PremiumPageBlobTier)
49
50
51class ContainerClient(AsyncStorageAccountHostsMixin, ContainerClientBase):
52    """A client to interact with a specific container, although that container
53    may not yet exist.
54
55    For operations relating to a specific blob within this container, a blob client can be
56    retrieved using the :func:`~get_blob_client` function.
57
58    :param str account_url:
59        The URI to the storage account. In order to create a client given the full URI to the container,
60        use the :func:`from_container_url` classmethod.
61    :param container_name:
62        The name of the container for the blob.
63    :type container_name: str
64    :param credential:
65        The credentials with which to authenticate. This is optional if the
66        account URL already has a SAS token. The value can be a SAS token string, an account
67        shared access key, or an instance of a TokenCredentials class from azure.identity.
68        If the URL already has a SAS token, specifying an explicit credential will take priority.
69    :keyword str api_version:
70        The Storage API version to use for requests. Default value is '2019-07-07'.
71        Setting to an older version may result in reduced feature compatibility.
72
73        .. versionadded:: 12.2.0
74
75    :keyword str secondary_hostname:
76        The hostname of the secondary endpoint.
77    :keyword int max_block_size: The maximum chunk size for uploading a block blob in chunks.
78        Defaults to 4*1024*1024, or 4MB.
79    :keyword int max_single_put_size: If the blob size is less than or equal max_single_put_size, then the blob will be
80        uploaded with only one http PUT request. If the blob size is larger than max_single_put_size,
81        the blob will be uploaded in chunks. Defaults to 64*1024*1024, or 64MB.
82    :keyword int min_large_block_upload_threshold: The minimum chunk size required to use the memory efficient
83        algorithm when uploading a block blob. Defaults to 4*1024*1024+1.
84    :keyword bool use_byte_buffer: Use a byte buffer for block blob uploads. Defaults to False.
85    :keyword int max_page_size: The maximum chunk size for uploading a page blob. Defaults to 4*1024*1024, or 4MB.
86    :keyword int max_single_get_size: The maximum size for a blob to be downloaded in a single call,
87        the exceeded part will be downloaded in chunks (could be parallel). Defaults to 32*1024*1024, or 32MB.
88    :keyword int max_chunk_get_size: The maximum chunk size used for downloading a blob. Defaults to 4*1024*1024,
89        or 4MB.
90
91    .. admonition:: Example:
92
93        .. literalinclude:: ../samples/blob_samples_containers_async.py
94            :start-after: [START create_container_client_from_service]
95            :end-before: [END create_container_client_from_service]
96            :language: python
97            :dedent: 8
98            :caption: Get a ContainerClient from an existing BlobServiceClient.
99
100        .. literalinclude:: ../samples/blob_samples_containers_async.py
101            :start-after: [START create_container_client_sasurl]
102            :end-before: [END create_container_client_sasurl]
103            :language: python
104            :dedent: 12
105            :caption: Creating the container client directly.
106    """
107    def __init__(
108            self, account_url,  # type: str
109            container_name,  # type: str
110            credential=None,  # type: Optional[Any]
111            **kwargs  # type: Any
112        ):
113        # type: (...) -> None
114        kwargs['retry_policy'] = kwargs.get('retry_policy') or ExponentialRetry(**kwargs)
115        super(ContainerClient, self).__init__(
116            account_url,
117            container_name=container_name,
118            credential=credential,
119            **kwargs)
120        self._client = AzureBlobStorage(url=self.url, pipeline=self._pipeline)
121        self._client._config.version = get_api_version(kwargs, VERSION)  # pylint: disable=protected-access
122        self._loop = kwargs.get('loop', None)
123
124    @distributed_trace_async
125    async def create_container(self, metadata=None, public_access=None, **kwargs):
126        # type: (Optional[Dict[str, str]], Optional[Union[PublicAccess, str]], **Any) -> None
127        """
128        Creates a new container under the specified account. If the container
129        with the same name already exists, the operation fails.
130
131        :param metadata:
132            A dict with name_value pairs to associate with the
133            container as metadata. Example:{'Category':'test'}
134        :type metadata: dict[str, str]
135        :param ~azure.storage.blob.PublicAccess public_access:
136            Possible values include: 'container', 'blob'.
137        :keyword container_encryption_scope:
138            Specifies the default encryption scope to set on the container and use for
139            all future writes.
140
141            .. versionadded:: 12.2.0
142
143        :paramtype container_encryption_scope: dict or ~azure.storage.blob.ContainerEncryptionScope
144        :keyword int timeout:
145            The timeout parameter is expressed in seconds.
146        :rtype: None
147
148        .. admonition:: Example:
149
150            .. literalinclude:: ../samples/blob_samples_containers_async.py
151                :start-after: [START create_container]
152                :end-before: [END create_container]
153                :language: python
154                :dedent: 16
155                :caption: Creating a container to store blobs.
156        """
157        headers = kwargs.pop('headers', {})
158        headers.update(add_metadata_headers(metadata)) # type: ignore
159        timeout = kwargs.pop('timeout', None)
160        container_cpk_scope_info = get_container_cpk_scope_info(kwargs)
161        try:
162            return await self._client.container.create( # type: ignore
163                timeout=timeout,
164                access=public_access,
165                container_cpk_scope_info=container_cpk_scope_info,
166                cls=return_response_headers,
167                headers=headers,
168                **kwargs)
169        except StorageErrorException as error:
170            process_storage_error(error)
171
172    @distributed_trace_async
173    async def delete_container(
174            self, **kwargs):
175        # type: (Any) -> None
176        """
177        Marks the specified container for deletion. The container and any blobs
178        contained within it are later deleted during garbage collection.
179
180        :keyword lease:
181            If specified, delete_container only succeeds if the
182            container's lease is active and matches this ID.
183            Required if the container has an active lease.
184        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
185        :keyword ~datetime.datetime if_modified_since:
186            A DateTime value. Azure expects the date value passed in to be UTC.
187            If timezone is included, any non-UTC datetimes will be converted to UTC.
188            If a date is passed in without timezone info, it is assumed to be UTC.
189            Specify this header to perform the operation only
190            if the resource has been modified since the specified time.
191        :keyword ~datetime.datetime if_unmodified_since:
192            A DateTime value. Azure expects the date value passed in to be UTC.
193            If timezone is included, any non-UTC datetimes will be converted to UTC.
194            If a date is passed in without timezone info, it is assumed to be UTC.
195            Specify this header to perform the operation only if
196            the resource has not been modified since the specified date/time.
197        :keyword str etag:
198            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
199            and act according to the condition specified by the `match_condition` parameter.
200        :keyword ~azure.core.MatchConditions match_condition:
201            The match condition to use upon the etag.
202        :keyword int timeout:
203            The timeout parameter is expressed in seconds.
204        :rtype: None
205
206        .. admonition:: Example:
207
208            .. literalinclude:: ../samples/blob_samples_containers_async.py
209                :start-after: [START delete_container]
210                :end-before: [END delete_container]
211                :language: python
212                :dedent: 16
213                :caption: Delete a container.
214        """
215        lease = kwargs.pop('lease', None)
216        access_conditions = get_access_conditions(lease)
217        mod_conditions = get_modify_conditions(kwargs)
218        timeout = kwargs.pop('timeout', None)
219        try:
220            await self._client.container.delete(
221                timeout=timeout,
222                lease_access_conditions=access_conditions,
223                modified_access_conditions=mod_conditions,
224                **kwargs)
225        except StorageErrorException as error:
226            process_storage_error(error)
227
228    @distributed_trace_async
229    async def acquire_lease(
230            self, lease_duration=-1,  # type: int
231            lease_id=None,  # type: Optional[str]
232            **kwargs):
233        # type: (...) -> BlobLeaseClient
234        """
235        Requests a new lease. If the container does not have an active lease,
236        the Blob service creates a lease on the container and returns a new
237        lease ID.
238
239        :param int lease_duration:
240            Specifies the duration of the lease, in seconds, or negative one
241            (-1) for a lease that never expires. A non-infinite lease can be
242            between 15 and 60 seconds. A lease duration cannot be changed
243            using renew or change. Default is -1 (infinite lease).
244        :param str lease_id:
245            Proposed lease ID, in a GUID string format. The Blob service returns
246            400 (Invalid request) if the proposed lease ID is not in the correct format.
247        :keyword ~datetime.datetime if_modified_since:
248            A DateTime value. Azure expects the date value passed in to be UTC.
249            If timezone is included, any non-UTC datetimes will be converted to UTC.
250            If a date is passed in without timezone info, it is assumed to be UTC.
251            Specify this header to perform the operation only
252            if the resource has been modified since the specified time.
253        :keyword ~datetime.datetime if_unmodified_since:
254            A DateTime value. Azure expects the date value passed in to be UTC.
255            If timezone is included, any non-UTC datetimes will be converted to UTC.
256            If a date is passed in without timezone info, it is assumed to be UTC.
257            Specify this header to perform the operation only if
258            the resource has not been modified since the specified date/time.
259        :keyword str etag:
260            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
261            and act according to the condition specified by the `match_condition` parameter.
262        :keyword ~azure.core.MatchConditions match_condition:
263            The match condition to use upon the etag.
264        :keyword int timeout:
265            The timeout parameter is expressed in seconds.
266        :returns: A BlobLeaseClient object, that can be run in a context manager.
267        :rtype: ~azure.storage.blob.aio.BlobLeaseClient
268
269        .. admonition:: Example:
270
271            .. literalinclude:: ../samples/blob_samples_containers_async.py
272                :start-after: [START acquire_lease_on_container]
273                :end-before: [END acquire_lease_on_container]
274                :language: python
275                :dedent: 12
276                :caption: Acquiring a lease on the container.
277        """
278        lease = BlobLeaseClient(self, lease_id=lease_id) # type: ignore
279        kwargs.setdefault('merge_span', True)
280        timeout = kwargs.pop('timeout', None)
281        await lease.acquire(lease_duration=lease_duration, timeout=timeout, **kwargs)
282        return lease
283
284    @distributed_trace_async
285    async def get_account_information(self, **kwargs):
286        # type: (**Any) -> Dict[str, str]
287        """Gets information related to the storage account.
288
289        The information can also be retrieved if the user has a SAS to a container or blob.
290        The keys in the returned dictionary include 'sku_name' and 'account_kind'.
291
292        :returns: A dict of account information (SKU and account type).
293        :rtype: dict(str, str)
294        """
295        try:
296            return await self._client.container.get_account_info(cls=return_response_headers, **kwargs) # type: ignore
297        except StorageErrorException as error:
298            process_storage_error(error)
299
300    @distributed_trace_async
301    async def get_container_properties(self, **kwargs):
302        # type: (**Any) -> ContainerProperties
303        """Returns all user-defined metadata and system properties for the specified
304        container. The data returned does not include the container's list of blobs.
305
306        :keyword lease:
307            If specified, get_container_properties only succeeds if the
308            container's lease is active and matches this ID.
309        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
310        :keyword int timeout:
311            The timeout parameter is expressed in seconds.
312        :return: Properties for the specified container within a container object.
313        :rtype: ~azure.storage.blob.ContainerProperties
314
315        .. admonition:: Example:
316
317            .. literalinclude:: ../samples/blob_samples_containers_async.py
318                :start-after: [START get_container_properties]
319                :end-before: [END get_container_properties]
320                :language: python
321                :dedent: 16
322                :caption: Getting properties on the container.
323        """
324        lease = kwargs.pop('lease', None)
325        access_conditions = get_access_conditions(lease)
326        timeout = kwargs.pop('timeout', None)
327        try:
328            response = await self._client.container.get_properties(
329                timeout=timeout,
330                lease_access_conditions=access_conditions,
331                cls=deserialize_container_properties,
332                **kwargs)
333        except StorageErrorException as error:
334            process_storage_error(error)
335        response.name = self.container_name
336        return response # type: ignore
337
338    @distributed_trace_async
339    async def set_container_metadata( # type: ignore
340            self, metadata=None,  # type: Optional[Dict[str, str]]
341            **kwargs
342        ):
343        # type: (...) -> Dict[str, Union[str, datetime]]
344        """Sets one or more user-defined name-value pairs for the specified
345        container. Each call to this operation replaces all existing metadata
346        attached to the container. To remove all metadata from the container,
347        call this operation with no metadata dict.
348
349        :param metadata:
350            A dict containing name-value pairs to associate with the container as
351            metadata. Example: {'category':'test'}
352        :type metadata: dict[str, str]
353        :keyword lease:
354            If specified, set_container_metadata only succeeds if the
355            container's lease is active and matches this ID.
356        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
357        :keyword ~datetime.datetime if_modified_since:
358            A DateTime value. Azure expects the date value passed in to be UTC.
359            If timezone is included, any non-UTC datetimes will be converted to UTC.
360            If a date is passed in without timezone info, it is assumed to be UTC.
361            Specify this header to perform the operation only
362            if the resource has been modified since the specified time.
363        :keyword int timeout:
364            The timeout parameter is expressed in seconds.
365        :returns: Container-updated property dict (Etag and last modified).
366
367        .. admonition:: Example:
368
369            .. literalinclude:: ../samples/blob_samples_containers_async.py
370                :start-after: [START set_container_metadata]
371                :end-before: [END set_container_metadata]
372                :language: python
373                :dedent: 16
374                :caption: Setting metadata on the container.
375        """
376        headers = kwargs.pop('headers', {})
377        headers.update(add_metadata_headers(metadata))
378        lease = kwargs.pop('lease', None)
379        access_conditions = get_access_conditions(lease)
380        mod_conditions = get_modify_conditions(kwargs)
381        timeout = kwargs.pop('timeout', None)
382        try:
383            return await self._client.container.set_metadata( # type: ignore
384                timeout=timeout,
385                lease_access_conditions=access_conditions,
386                modified_access_conditions=mod_conditions,
387                cls=return_response_headers,
388                headers=headers,
389                **kwargs)
390        except StorageErrorException as error:
391            process_storage_error(error)
392
393    @distributed_trace_async
394    async def get_container_access_policy(self, **kwargs):
395        # type: (Any) -> Dict[str, Any]
396        """Gets the permissions for the specified container.
397        The permissions indicate whether container data may be accessed publicly.
398
399        :keyword lease:
400            If specified, get_container_access_policy only succeeds if the
401            container's lease is active and matches this ID.
402        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
403        :keyword int timeout:
404            The timeout parameter is expressed in seconds.
405        :returns: Access policy information in a dict.
406        :rtype: dict[str, Any]
407
408        .. admonition:: Example:
409
410            .. literalinclude:: ../samples/blob_samples_containers_async.py
411                :start-after: [START get_container_access_policy]
412                :end-before: [END get_container_access_policy]
413                :language: python
414                :dedent: 16
415                :caption: Getting the access policy on the container.
416        """
417        lease = kwargs.pop('lease', None)
418        access_conditions = get_access_conditions(lease)
419        timeout = kwargs.pop('timeout', None)
420        try:
421            response, identifiers = await self._client.container.get_access_policy(
422                timeout=timeout,
423                lease_access_conditions=access_conditions,
424                cls=return_headers_and_deserialized,
425                **kwargs)
426        except StorageErrorException as error:
427            process_storage_error(error)
428        return {
429            'public_access': response.get('blob_public_access'),
430            'signed_identifiers': identifiers or []
431        }
432
433    @distributed_trace_async
434    async def set_container_access_policy(
435            self, signed_identifiers,  # type: Dict[str, AccessPolicy]
436            public_access=None,  # type: Optional[Union[str, PublicAccess]]
437            **kwargs  # type: Any
438        ):  # type: (...) -> Dict[str, Union[str, datetime]]
439        """Sets the permissions for the specified container or stored access
440        policies that may be used with Shared Access Signatures. The permissions
441        indicate whether blobs in a container may be accessed publicly.
442
443        :param signed_identifiers:
444            A dictionary of access policies to associate with the container. The
445            dictionary may contain up to 5 elements. An empty dictionary
446            will clear the access policies set on the service.
447        :type signed_identifiers: dict[str, ~azure.storage.blob.AccessPolicy]
448        :param ~azure.storage.blob.PublicAccess public_access:
449            Possible values include: 'container', 'blob'.
450        :keyword lease:
451            Required if the container has an active lease. Value can be a BlobLeaseClient object
452            or the lease ID as a string.
453        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
454        :keyword ~datetime.datetime if_modified_since:
455            A datetime value. Azure expects the date value passed in to be UTC.
456            If timezone is included, any non-UTC datetimes will be converted to UTC.
457            If a date is passed in without timezone info, it is assumed to be UTC.
458            Specify this header to perform the operation only
459            if the resource has been modified since the specified date/time.
460        :keyword ~datetime.datetime if_unmodified_since:
461            A datetime value. Azure expects the date value passed in to be UTC.
462            If timezone is included, any non-UTC datetimes will be converted to UTC.
463            If a date is passed in without timezone info, it is assumed to be UTC.
464            Specify this header to perform the operation only if
465            the resource has not been modified since the specified date/time.
466        :keyword int timeout:
467            The timeout parameter is expressed in seconds.
468        :returns: Container-updated property dict (Etag and last modified).
469        :rtype: dict[str, str or ~datetime.datetime]
470
471        .. admonition:: Example:
472
473            .. literalinclude:: ../samples/blob_samples_containers_async.py
474                :start-after: [START set_container_access_policy]
475                :end-before: [END set_container_access_policy]
476                :language: python
477                :dedent: 16
478                :caption: Setting access policy on the container.
479        """
480        timeout = kwargs.pop('timeout', None)
481        lease = kwargs.pop('lease', None)
482        if len(signed_identifiers) > 5:
483            raise ValueError(
484                'Too many access policies provided. The server does not support setting '
485                'more than 5 access policies on a single resource.')
486        identifiers = []
487        for key, value in signed_identifiers.items():
488            if value:
489                value.start = serialize_iso(value.start)
490                value.expiry = serialize_iso(value.expiry)
491            identifiers.append(SignedIdentifier(id=key, access_policy=value)) # type: ignore
492        signed_identifiers = identifiers # type: ignore
493
494        mod_conditions = get_modify_conditions(kwargs)
495        access_conditions = get_access_conditions(lease)
496        try:
497            return await self._client.container.set_access_policy(
498                container_acl=signed_identifiers or None,
499                timeout=timeout,
500                access=public_access,
501                lease_access_conditions=access_conditions,
502                modified_access_conditions=mod_conditions,
503                cls=return_response_headers,
504                **kwargs)
505        except StorageErrorException as error:
506            process_storage_error(error)
507
508    @distributed_trace
509    def list_blobs(self, name_starts_with=None, include=None, **kwargs):
510        # type: (Optional[str], Optional[Union[str, List[str]]], **Any) -> AsyncItemPaged[BlobProperties]
511        """Returns a generator to list the blobs under the specified container.
512        The generator will lazily follow the continuation tokens returned by
513        the service.
514
515        :param str name_starts_with:
516            Filters the results to return only blobs whose names
517            begin with the specified prefix.
518        :param list[str] or str include:
519            Specifies one or more additional datasets to include in the response.
520            Options include: 'snapshots', 'metadata', 'uncommittedblobs', 'copy', 'deleted', 'tags'.
521        :keyword int timeout:
522            The timeout parameter is expressed in seconds.
523        :returns: An iterable (auto-paging) response of BlobProperties.
524        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.storage.blob.BlobProperties]
525
526        .. admonition:: Example:
527
528            .. literalinclude:: ../samples/blob_samples_containers_async.py
529                :start-after: [START list_blobs_in_container]
530                :end-before: [END list_blobs_in_container]
531                :language: python
532                :dedent: 12
533                :caption: List the blobs in the container.
534        """
535        if include and not isinstance(include, list):
536            include = [include]
537
538        results_per_page = kwargs.pop('results_per_page', None)
539        timeout = kwargs.pop('timeout', None)
540        command = functools.partial(
541            self._client.container.list_blob_flat_segment,
542            include=include,
543            timeout=timeout,
544            **kwargs)
545        return AsyncItemPaged(
546            command,
547            prefix=name_starts_with,
548            results_per_page=results_per_page,
549            page_iterator_class=BlobPropertiesPaged
550        )
551
552    @distributed_trace
553    def walk_blobs(
554            self, name_starts_with=None, # type: Optional[str]
555            include=None, # type: Optional[Any]
556            delimiter="/", # type: str
557            **kwargs # type: Optional[Any]
558        ):
559        # type: (...) -> AsyncItemPaged[BlobProperties]
560        """Returns a generator to list the blobs under the specified container.
561        The generator will lazily follow the continuation tokens returned by
562        the service. This operation will list blobs in accordance with a hierarchy,
563        as delimited by the specified delimiter character.
564
565        :param str name_starts_with:
566            Filters the results to return only blobs whose names
567            begin with the specified prefix.
568        :param list[str] include:
569            Specifies one or more additional datasets to include in the response.
570            Options include: 'snapshots', 'metadata', 'uncommittedblobs', 'copy', 'deleted'.
571        :param str delimiter:
572            When the request includes this parameter, the operation returns a BlobPrefix
573            element in the response body that acts as a placeholder for all blobs whose
574            names begin with the same substring up to the appearance of the delimiter
575            character. The delimiter may be a single character or a string.
576        :keyword int timeout:
577            The timeout parameter is expressed in seconds.
578        :returns: An iterable (auto-paging) response of BlobProperties.
579        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.storage.blob.BlobProperties]
580        """
581        if include and not isinstance(include, list):
582            include = [include]
583
584        results_per_page = kwargs.pop('results_per_page', None)
585        timeout = kwargs.pop('timeout', None)
586        command = functools.partial(
587            self._client.container.list_blob_hierarchy_segment,
588            delimiter=delimiter,
589            include=include,
590            timeout=timeout,
591            **kwargs)
592        return BlobPrefix(
593            command,
594            prefix=name_starts_with,
595            results_per_page=results_per_page,
596            delimiter=delimiter)
597
598    @distributed_trace_async
599    async def upload_blob(
600            self, name,  # type: Union[str, BlobProperties]
601            data,  # type: Union[Iterable[AnyStr], IO[AnyStr]]
602            blob_type=BlobType.BlockBlob,  # type: Union[str, BlobType]
603            length=None,  # type: Optional[int]
604            metadata=None,  # type: Optional[Dict[str, str]]
605            **kwargs
606        ):
607        # type: (...) -> BlobClient
608        """Creates a new blob from a data source with automatic chunking.
609
610        :param name: The blob with which to interact. If specified, this value will override
611            a blob value specified in the blob URL.
612        :type name: str or ~azure.storage.blob.BlobProperties
613        :param data: The blob data to upload.
614        :param ~azure.storage.blob.BlobType blob_type: The type of the blob. This can be
615            either BlockBlob, PageBlob or AppendBlob. The default value is BlockBlob.
616        :param int length:
617            Number of bytes to read from the stream. This is optional, but
618            should be supplied for optimal performance.
619        :param metadata:
620            Name-value pairs associated with the blob as metadata.
621        :type metadata: dict(str, str)
622        :keyword bool overwrite: Whether the blob to be uploaded should overwrite the current data.
623            If True, upload_blob will overwrite the existing data. If set to False, the
624            operation will fail with ResourceExistsError. The exception to the above is with Append
625            blob types: if set to False and the data already exists, an error will not be raised
626            and the data will be appended to the existing blob. If set overwrite=True, then the existing
627            append blob will be deleted, and a new one created. Defaults to False.
628        :keyword ~azure.storage.blob.ContentSettings content_settings:
629            ContentSettings object used to set blob properties. Used to set content type, encoding,
630            language, disposition, md5, and cache control.
631        :keyword bool validate_content:
632            If true, calculates an MD5 hash for each chunk of the blob. The storage
633            service checks the hash of the content that has arrived with the hash
634            that was sent. This is primarily valuable for detecting bitflips on
635            the wire if using http instead of https, as https (the default), will
636            already validate. Note that this MD5 hash is not stored with the
637            blob. Also note that if enabled, the memory-efficient upload algorithm
638            will not be used, because computing the MD5 hash requires buffering
639            entire blocks, and doing so defeats the purpose of the memory-efficient algorithm.
640        :keyword lease:
641            Required if the container has an active lease. Value can be a BlobLeaseClient object
642            or the lease ID as a string.
643        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
644        :keyword ~datetime.datetime if_modified_since:
645            A DateTime value. Azure expects the date value passed in to be UTC.
646            If timezone is included, any non-UTC datetimes will be converted to UTC.
647            If a date is passed in without timezone info, it is assumed to be UTC.
648            Specify this header to perform the operation only
649            if the resource has been modified since the specified time.
650        :keyword ~datetime.datetime if_unmodified_since:
651            A DateTime value. Azure expects the date value passed in to be UTC.
652            If timezone is included, any non-UTC datetimes will be converted to UTC.
653            If a date is passed in without timezone info, it is assumed to be UTC.
654            Specify this header to perform the operation only if
655            the resource has not been modified since the specified date/time.
656        :keyword str etag:
657            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
658            and act according to the condition specified by the `match_condition` parameter.
659        :keyword ~azure.core.MatchConditions match_condition:
660            The match condition to use upon the etag.
661        :keyword str if_tags_match_condition
662            Specify a SQL where clause on blob tags to operate only on blob with a matching value.
663            eg. "\"tagname\"='my tag'"
664
665            .. versionadded:: 12.4.0
666
667        :keyword int timeout:
668            The timeout parameter is expressed in seconds. This method may make
669            multiple calls to the Azure service and the timeout will apply to
670            each call individually.
671        :keyword ~azure.storage.blob.PremiumPageBlobTier premium_page_blob_tier:
672            A page blob tier value to set the blob to. The tier correlates to the size of the
673            blob and number of allowed IOPS. This is only applicable to page blobs on
674            premium storage accounts.
675        :keyword ~azure.storage.blob.StandardBlobTier standard_blob_tier:
676            A standard blob tier value to set the blob to. For this version of the library,
677            this is only applicable to block blobs on standard storage accounts.
678        :keyword int maxsize_condition:
679            Optional conditional header. The max length in bytes permitted for
680            the append blob. If the Append Block operation would cause the blob
681            to exceed that limit or if the blob size is already greater than the
682            value specified in this header, the request will fail with
683            MaxBlobSizeConditionNotMet error (HTTP status code 412 - Precondition Failed).
684        :keyword int max_concurrency:
685            Maximum number of parallel connections to use when the blob size exceeds
686            64MB.
687        :keyword ~azure.storage.blob.CustomerProvidedEncryptionKey cpk:
688            Encrypts the data on the service-side with the given key.
689            Use of customer-provided keys must be done over HTTPS.
690            As the encryption key itself is provided in the request,
691            a secure connection must be established to transfer the key.
692        :keyword str encryption_scope:
693            A predefined encryption scope used to encrypt the data on the service. An encryption
694            scope can be created using the Management API and referenced here by name. If a default
695            encryption scope has been defined at the container, this value will override it if the
696            container-level scope is configured to allow overrides. Otherwise an error will be raised.
697
698            .. versionadded:: 12.2.0
699
700        :keyword str encoding:
701            Defaults to UTF-8.
702        :returns: A BlobClient to interact with the newly uploaded blob.
703        :rtype: ~azure.storage.blob.aio.BlobClient
704
705        .. admonition:: Example:
706
707            .. literalinclude:: ../samples/blob_samples_containers_async.py
708                :start-after: [START upload_blob_to_container]
709                :end-before: [END upload_blob_to_container]
710                :language: python
711                :dedent: 12
712                :caption: Upload blob to the container.
713        """
714        blob = self.get_blob_client(name)
715        kwargs.setdefault('merge_span', True)
716        timeout = kwargs.pop('timeout', None)
717        encoding = kwargs.pop('encoding', 'UTF-8')
718        await blob.upload_blob(
719            data,
720            blob_type=blob_type,
721            length=length,
722            metadata=metadata,
723            timeout=timeout,
724            encoding=encoding,
725            **kwargs
726        )
727        return blob
728
729    @distributed_trace_async
730    async def delete_blob(
731            self, blob,  # type: Union[str, BlobProperties]
732            delete_snapshots=None,  # type: Optional[str]
733            **kwargs
734        ):
735        # type: (...) -> None
736        """Marks the specified blob or snapshot for deletion.
737
738        The blob is later deleted during garbage collection.
739        Note that in order to delete a blob, you must delete all of its
740        snapshots. You can delete both at the same time with the delete_blob
741        operation.
742
743        If a delete retention policy is enabled for the service, then this operation soft deletes the blob or snapshot
744        and retains the blob or snapshot for specified number of days.
745        After specified number of days, blob's data is removed from the service during garbage collection.
746        Soft deleted blob or snapshot is accessible through :func:`list_blobs()` specifying `include=["deleted"]`
747        option. Soft-deleted blob or snapshot can be restored using :func:`~BlobClient.undelete()`
748
749        :param blob: The blob with which to interact. If specified, this value will override
750            a blob value specified in the blob URL.
751        :type blob: str or ~azure.storage.blob.BlobProperties
752        :param str delete_snapshots:
753            Required if the blob has associated snapshots. Values include:
754             - "only": Deletes only the blobs snapshots.
755             - "include": Deletes the blob along with all snapshots.
756        :keyword lease:
757            Required if the blob has an active lease. Value can be a Lease object
758            or the lease ID as a string.
759        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
760        :keyword ~datetime.datetime if_modified_since:
761            A DateTime value. Azure expects the date value passed in to be UTC.
762            If timezone is included, any non-UTC datetimes will be converted to UTC.
763            If a date is passed in without timezone info, it is assumed to be UTC.
764            Specify this header to perform the operation only
765            if the resource has been modified since the specified time.
766        :keyword ~datetime.datetime if_unmodified_since:
767            A DateTime value. Azure expects the date value passed in to be UTC.
768            If timezone is included, any non-UTC datetimes will be converted to UTC.
769            If a date is passed in without timezone info, it is assumed to be UTC.
770            Specify this header to perform the operation only if
771            the resource has not been modified since the specified date/time.
772        :keyword str etag:
773            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
774            and act according to the condition specified by the `match_condition` parameter.
775        :keyword ~azure.core.MatchConditions match_condition:
776            The match condition to use upon the etag.
777        :keyword str if_tags_match_condition
778            Specify a SQL where clause on blob tags to operate only on blob with a matching value.
779            eg. "\"tagname\"='my tag'"
780
781            .. versionadded:: 12.4.0
782
783        :keyword int timeout:
784            The timeout parameter is expressed in seconds.
785        :rtype: None
786        """
787        blob = self.get_blob_client(blob) # type: ignore
788        kwargs.setdefault('merge_span', True)
789        timeout = kwargs.pop('timeout', None)
790        await blob.delete_blob( # type: ignore
791            delete_snapshots=delete_snapshots,
792            timeout=timeout,
793            **kwargs)
794
795    @distributed_trace_async
796    async def download_blob(self, blob, offset=None, length=None, **kwargs):
797        # type: (Union[str, BlobProperties], Optional[int], Optional[int], Any) -> StorageStreamDownloader
798        """Downloads a blob to the StorageStreamDownloader. The readall() method must
799        be used to read all the content or readinto() must be used to download the blob into
800        a stream.
801
802        :param blob: The blob with which to interact. If specified, this value will override
803            a blob value specified in the blob URL.
804        :type blob: str or ~azure.storage.blob.BlobProperties
805        :param int offset:
806            Start of byte range to use for downloading a section of the blob.
807            Must be set if length is provided.
808        :param int length:
809            Number of bytes to read from the stream. This is optional, but
810            should be supplied for optimal performance.
811        :keyword bool validate_content:
812            If true, calculates an MD5 hash for each chunk of the blob. The storage
813            service checks the hash of the content that has arrived with the hash
814            that was sent. This is primarily valuable for detecting bitflips on
815            the wire if using http instead of https, as https (the default), will
816            already validate. Note that this MD5 hash is not stored with the
817            blob. Also note that if enabled, the memory-efficient upload algorithm
818            will not be used because computing the MD5 hash requires buffering
819            entire blocks, and doing so defeats the purpose of the memory-efficient algorithm.
820        :keyword lease:
821            Required if the blob has an active lease. If specified, download_blob only
822            succeeds if the blob's lease is active and matches this ID. Value can be a
823            BlobLeaseClient object or the lease ID as a string.
824        :paramtype lease: ~azure.storage.blob.aio.BlobLeaseClient or str
825        :keyword ~datetime.datetime if_modified_since:
826            A DateTime value. Azure expects the date value passed in to be UTC.
827            If timezone is included, any non-UTC datetimes will be converted to UTC.
828            If a date is passed in without timezone info, it is assumed to be UTC.
829            Specify this header to perform the operation only
830            if the resource has been modified since the specified time.
831        :keyword ~datetime.datetime if_unmodified_since:
832            A DateTime value. Azure expects the date value passed in to be UTC.
833            If timezone is included, any non-UTC datetimes will be converted to UTC.
834            If a date is passed in without timezone info, it is assumed to be UTC.
835            Specify this header to perform the operation only if
836            the resource has not been modified since the specified date/time.
837        :keyword str etag:
838            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
839            and act according to the condition specified by the `match_condition` parameter.
840        :keyword ~azure.core.MatchConditions match_condition:
841            The match condition to use upon the etag.
842        :keyword str if_tags_match_condition
843            Specify a SQL where clause on blob tags to operate only on blob with a matching value.
844            eg. "\"tagname\"='my tag'"
845
846            .. versionadded:: 12.4.0
847
848        :keyword ~azure.storage.blob.CustomerProvidedEncryptionKey cpk:
849            Encrypts the data on the service-side with the given key.
850            Use of customer-provided keys must be done over HTTPS.
851            As the encryption key itself is provided in the request,
852            a secure connection must be established to transfer the key.
853        :keyword int max_concurrency:
854            The number of parallel connections with which to download.
855        :keyword str encoding:
856            Encoding to decode the downloaded bytes. Default is None, i.e. no decoding.
857        :keyword int timeout:
858            The timeout parameter is expressed in seconds. This method may make
859            multiple calls to the Azure service and the timeout will apply to
860            each call individually.
861        :returns: A streaming object. (StorageStreamDownloader)
862        :rtype: ~azure.storage.blob.aio.StorageStreamDownloader
863        """
864        blob_client = self.get_blob_client(blob) # type: ignore
865        kwargs.setdefault('merge_span', True)
866        return await blob_client.download_blob(
867            offset=offset,
868            length=length,
869            **kwargs)
870
871    @distributed_trace_async
872    async def delete_blobs(  # pylint: disable=arguments-differ
873            self, *blobs: List[Union[str, BlobProperties, dict]],
874            **kwargs
875    ) -> AsyncIterator[AsyncHttpResponse]:
876        """Marks the specified blobs or snapshots for deletion.
877
878        The blobs are later deleted during garbage collection.
879        Note that in order to delete blobs, you must delete all of their
880        snapshots. You can delete both at the same time with the delete_blobs operation.
881
882        If a delete retention policy is enabled for the service, then this operation soft deletes the blobs or snapshots
883        and retains the blobs or snapshots for specified number of days.
884        After specified number of days, blobs' data is removed from the service during garbage collection.
885        Soft deleted blobs or snapshots are accessible through :func:`list_blobs()` specifying `include=["deleted"]`
886        Soft-deleted blobs or snapshots can be restored using :func:`~BlobClient.undelete()`
887
888        :param blobs:
889            The blobs to delete. This can be a single blob, or multiple values can
890            be supplied, where each value is either the name of the blob (str) or BlobProperties.
891
892            .. note::
893                When the blob type is dict, here's a list of keys, value rules.
894
895                blob name:
896                    key: 'name', value type: str
897                snapshot you want to delete:
898                    key: 'snapshot', value type: str
899                whether to delete snapthots when deleting blob:
900                    key: 'delete_snapshots', value: 'include' or 'only'
901                if the blob modified or not:
902                    key: 'if_modified_since', 'if_unmodified_since', value type: datetime
903                etag:
904                    key: 'etag', value type: str
905                match the etag or not:
906                    key: 'match_condition', value type: MatchConditions
907                tags match condition:
908                    key: 'if_tags_match_condition', value type: str
909                lease:
910                    key: 'lease_id', value type: Union[str, LeaseClient]
911                timeout for subrequest:
912                    key: 'timeout', value type: int
913
914        :type blobs: list[str], list[dict], or list[~azure.storage.blob.BlobProperties]
915        :keyword str delete_snapshots:
916            Required if a blob has associated snapshots. Values include:
917             - "only": Deletes only the blobs snapshots.
918             - "include": Deletes the blob along with all snapshots.
919        :keyword ~datetime.datetime if_modified_since:
920            A DateTime value. Azure expects the date value passed in to be UTC.
921            If timezone is included, any non-UTC datetimes will be converted to UTC.
922            If a date is passed in without timezone info, it is assumed to be UTC.
923            Specify this header to perform the operation only
924            if the resource has been modified since the specified time.
925        :keyword ~datetime.datetime if_unmodified_since:
926            A DateTime value. Azure expects the date value passed in to be UTC.
927            If timezone is included, any non-UTC datetimes will be converted to UTC.
928            If a date is passed in without timezone info, it is assumed to be UTC.
929            Specify this header to perform the operation only if
930            the resource has not been modified since the specified date/time.
931        :keyword str if_tags_match_condition
932            Specify a SQL where clause on blob tags to operate only on blob with a matching value.
933            eg. "\"tagname\"='my tag'"
934
935            .. versionadded:: 12.4.0
936
937        :keyword bool raise_on_any_failure:
938            This is a boolean param which defaults to True. When this is set, an exception
939            is raised even if there is a single operation failure. For optimal performance,
940            this should be set to False
941        :keyword int timeout:
942            The timeout parameter is expressed in seconds.
943        :return: An async iterator of responses, one for each blob in order
944        :rtype: asynciterator[~azure.core.pipeline.transport.AsyncHttpResponse]
945
946        .. admonition:: Example:
947
948            .. literalinclude:: ../samples/blob_samples_common_async.py
949                :start-after: [START delete_multiple_blobs]
950                :end-before: [END delete_multiple_blobs]
951                :language: python
952                :dedent: 12
953                :caption: Deleting multiple blobs.
954        """
955        if len(blobs) == 0:
956            return iter(list())
957
958        reqs, options = self._generate_delete_blobs_options(*blobs, **kwargs)
959
960        return await self._batch_send(*reqs, **options)
961
962    @distributed_trace
963    async def set_standard_blob_tier_blobs(
964        self,
965        standard_blob_tier: Union[str, 'StandardBlobTier'],
966        *blobs: List[Union[str, BlobProperties, dict]],
967        **kwargs
968    ) -> AsyncIterator[AsyncHttpResponse]:
969        """This operation sets the tier on block blobs.
970
971        A block blob's tier determines Hot/Cool/Archive storage type.
972        This operation does not update the blob's ETag.
973
974        :param standard_blob_tier:
975            Indicates the tier to be set on all blobs. Options include 'Hot', 'Cool',
976            'Archive'. The hot tier is optimized for storing data that is accessed
977            frequently. The cool storage tier is optimized for storing data that
978            is infrequently accessed and stored for at least a month. The archive
979            tier is optimized for storing data that is rarely accessed and stored
980            for at least six months with flexible latency requirements.
981
982            .. note::
983                If you want to set different tier on different blobs please set this positional parameter to None.
984                Then the blob tier on every BlobProperties will be taken.
985
986        :type standard_blob_tier: str or ~azure.storage.blob.StandardBlobTier
987        :param blobs:
988            The blobs with which to interact. This can be a single blob, or multiple values can
989            be supplied, where each value is either the name of the blob (str) or BlobProperties.
990
991            .. note::
992                When the blob type is dict, here's a list of keys, value rules.
993                blob name:
994                    key: 'name', value type: str
995                standard blob tier:
996                    key: 'blob_tier', value type: StandardBlobTier
997                rehydrate priority:
998                    key: 'rehydrate_priority', value type: RehydratePriority
999                lease:
1000                    key: 'lease_id', value type: Union[str, LeaseClient]
1001                tags match condition:
1002                    key: 'if_tags_match_condition', value type: str
1003                timeout for subrequest:
1004                    key: 'timeout', value type: int
1005
1006        :type blobs: list[str], list[dict], or list[~azure.storage.blob.BlobProperties]
1007        :keyword ~azure.storage.blob.RehydratePriority rehydrate_priority:
1008            Indicates the priority with which to rehydrate an archived blob
1009        :keyword str if_tags_match_condition
1010            Specify a SQL where clause on blob tags to operate only on blob with a matching value.
1011            eg. "\"tagname\"='my tag'"
1012
1013            .. versionadded:: 12.4.0
1014
1015        :keyword int timeout:
1016            The timeout parameter is expressed in seconds.
1017        :keyword bool raise_on_any_failure:
1018            This is a boolean param which defaults to True. When this is set, an exception
1019            is raised even if there is a single operation failure. For optimal performance,
1020            this should be set to False.
1021        :return: An async iterator of responses, one for each blob in order
1022        :rtype: asynciterator[~azure.core.pipeline.transport.AsyncHttpResponse]
1023        """
1024        reqs, options = self._generate_set_tiers_options(standard_blob_tier, *blobs, **kwargs)
1025
1026        return await self._batch_send(*reqs, **options)
1027
1028    @distributed_trace
1029    async def set_premium_page_blob_tier_blobs(
1030        self,
1031        premium_page_blob_tier: Union[str, 'PremiumPageBlobTier'],
1032        *blobs: List[Union[str, BlobProperties, dict]],
1033        **kwargs
1034    ) -> AsyncIterator[AsyncHttpResponse]:
1035        """Sets the page blob tiers on the blobs. This API is only supported for page blobs on premium accounts.
1036
1037        :param premium_page_blob_tier:
1038            A page blob tier value to set on all blobs to. The tier correlates to the size of the
1039            blob and number of allowed IOPS. This is only applicable to page blobs on
1040            premium storage accounts.
1041
1042            .. note::
1043                If you want to set different tier on different blobs please set this positional parameter to None.
1044                Then the blob tier on every BlobProperties will be taken.
1045
1046        :type premium_page_blob_tier: ~azure.storage.blob.PremiumPageBlobTier
1047        :param blobs: The blobs with which to interact. This can be a single blob, or multiple values can
1048            be supplied, where each value is either the name of the blob (str) or BlobProperties.
1049
1050            .. note::
1051                When the blob type is dict, here's a list of keys, value rules.
1052
1053                blob name:
1054                    key: 'name', value type: str
1055                premium blob tier:
1056                    key: 'blob_tier', value type: PremiumPageBlobTier
1057                lease:
1058                    key: 'lease_id', value type: Union[str, LeaseClient]
1059                timeout for subrequest:
1060                    key: 'timeout', value type: int
1061
1062        :type blobs: list[str], list[dict], or list[~azure.storage.blob.BlobProperties]
1063        :keyword int timeout:
1064            The timeout parameter is expressed in seconds. This method may make
1065            multiple calls to the Azure service and the timeout will apply to
1066            each call individually.
1067        :keyword bool raise_on_any_failure:
1068            This is a boolean param which defaults to True. When this is set, an exception
1069            is raised even if there is a single operation failure. For optimal performance,
1070            this should be set to False.
1071        :return: An async iterator of responses, one for each blob in order
1072        :rtype: asynciterator[~azure.core.pipeline.transport.AsyncHttpResponse]
1073        """
1074        reqs, options = self._generate_set_tiers_options(premium_page_blob_tier, *blobs, **kwargs)
1075
1076        return await self._batch_send(*reqs, **options)
1077
1078    def get_blob_client(
1079            self, blob,  # type: Union[BlobProperties, str]
1080            snapshot=None  # type: str
1081        ):
1082        # type: (...) -> BlobClient
1083        """Get a client to interact with the specified blob.
1084
1085        The blob need not already exist.
1086
1087        :param blob:
1088            The blob with which to interact.
1089        :type blob: str or ~azure.storage.blob.BlobProperties
1090        :param str snapshot:
1091            The optional blob snapshot on which to operate. This can be the snapshot ID string
1092            or the response returned from :func:`~BlobClient.create_snapshot()`.
1093        :returns: A BlobClient.
1094        :rtype: ~azure.storage.blob.aio.BlobClient
1095
1096        .. admonition:: Example:
1097
1098            .. literalinclude:: ../samples/blob_samples_containers_async.py
1099                :start-after: [START get_blob_client]
1100                :end-before: [END get_blob_client]
1101                :language: python
1102                :dedent: 12
1103                :caption: Get the blob client.
1104        """
1105        blob_name = _get_blob_name(blob)
1106        _pipeline = AsyncPipeline(
1107            transport=AsyncTransportWrapper(self._pipeline._transport), # pylint: disable = protected-access
1108            policies=self._pipeline._impl_policies # pylint: disable = protected-access
1109        )
1110        return BlobClient(
1111            self.url, container_name=self.container_name, blob_name=blob_name, snapshot=snapshot,
1112            credential=self.credential, api_version=self.api_version, _configuration=self._config,
1113            _pipeline=_pipeline, _location_mode=self._location_mode, _hosts=self._hosts,
1114            require_encryption=self.require_encryption, key_encryption_key=self.key_encryption_key,
1115            key_resolver_function=self.key_resolver_function, loop=self._loop)
1116