Skip to content

Commit

Permalink
[Storage][STG75]Lease on Get/Set Tags & Find Blob by Tags (#15090)
Browse files Browse the repository at this point in the history
* [Storage][STG75]Lease on Get/Set Tags & Find Blob by Tags

* pylint
  • Loading branch information
xiafu-msft authored Dec 1, 2020
1 parent 9106569 commit 2f81dfd
Show file tree
Hide file tree
Showing 12 changed files with 1,042 additions and 288 deletions.
12 changes: 12 additions & 0 deletions sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2372,10 +2372,12 @@ def set_premium_page_blob_tier(self, premium_page_blob_tier, **kwargs):
def _set_blob_tags_options(self, tags=None, **kwargs):
# type: (Optional[Dict[str, str]], **Any) -> Dict[str, Any]
tags = serialize_blob_tags(tags)
access_conditions = get_access_conditions(kwargs.pop('lease', None))
mod_conditions = get_modify_conditions(kwargs)

options = {
'tags': tags,
'lease_access_conditions': access_conditions,
'modified_access_conditions': mod_conditions,
'cls': return_response_headers}
options.update(kwargs)
Expand Down Expand Up @@ -2410,6 +2412,10 @@ def set_blob_tags(self, tags=None, **kwargs):
blob.
:keyword str if_tags_match_condition:
Specify a SQL where clause on blob tags to operate only on destination blob with a matching value.
:keyword lease:
Required if the blob has an active lease. Value can be a BlobLeaseClient object
or the lease ID as a string.
:paramtype lease: ~azure.storage.blob.BlobLeaseClient or str
:keyword int timeout:
The timeout parameter is expressed in seconds.
:returns: Blob-updated property dict (Etag and last modified)
Expand All @@ -2423,11 +2429,13 @@ def set_blob_tags(self, tags=None, **kwargs):

def _get_blob_tags_options(self, **kwargs):
# type: (**Any) -> Dict[str, str]
access_conditions = get_access_conditions(kwargs.pop('lease', None))
mod_conditions = get_modify_conditions(kwargs)

options = {
'version_id': kwargs.pop('version_id', None),
'snapshot': self.snapshot,
'lease_access_conditions': access_conditions,
'modified_access_conditions': mod_conditions,
'timeout': kwargs.pop('timeout', None),
'cls': return_headers_and_deserialized}
Expand All @@ -2446,6 +2454,10 @@ def get_blob_tags(self, **kwargs):
value that, when present, specifies the version of the blob to add tags to.
:keyword str if_tags_match_condition:
Specify a SQL where clause on blob tags to operate only on destination blob with a matching value.
:keyword lease:
Required if the blob has an active lease. Value can be a BlobLeaseClient object
or the lease ID as a string.
:paramtype lease: ~azure.storage.blob.BlobLeaseClient or str
:keyword int timeout:
The timeout parameter is expressed in seconds.
:returns: Key value pairs of blob tags.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
from ._generated.models import StorageErrorException, StorageServiceProperties, KeyInfo
from ._container_client import ContainerClient
from ._blob_client import BlobClient
from ._models import ContainerPropertiesPaged, FilteredBlobPaged
from ._models import ContainerPropertiesPaged
from ._list_blobs_helper import FilteredBlobPaged
from ._serialize import get_api_version
from ._deserialize import service_stats_deserialize, service_properties_deserialize

Expand All @@ -47,6 +48,7 @@
CorsRule,
RetentionPolicy,
StaticWebsite,
FilteredBlob
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
# --------------------------------------------------------------------------

from azure.core.paging import PageIterator, ItemPaged
from azure.storage.blob._deserialize import get_blob_properties_from_generated_code
from ._generated.models import StorageErrorException, BlobItemInternal, BlobPrefix as GenBlobPrefix
from ._models import BlobProperties
from ._deserialize import get_blob_properties_from_generated_code, parse_tags
from ._generated.models import StorageErrorException, BlobItemInternal, BlobPrefix as GenBlobPrefix, FilterBlobItem
from ._models import BlobProperties, FilteredBlob
from ._shared.models import DictMixin
from ._shared.response_handlers import return_context_and_deserialized, process_storage_error

Expand Down Expand Up @@ -164,3 +164,72 @@ def __init__(self, *args, **kwargs):
self.container = kwargs.get('container')
self.delimiter = kwargs.get('delimiter')
self.location_mode = kwargs.get('location_mode')


class FilteredBlobPaged(PageIterator):
"""An Iterable of Blob properties.
:ivar str service_endpoint: The service URL.
:ivar str prefix: A blob name prefix being used to filter the list.
:ivar str marker: The continuation token of the current page of results.
:ivar int results_per_page: The maximum number of results retrieved per API call.
:ivar str continuation_token: The continuation token to retrieve the next page of results.
:ivar str location_mode: The location mode being used to list results. The available
options include "primary" and "secondary".
:ivar current_page: The current page of listed results.
:vartype current_page: list(~azure.storage.blob.FilteredBlob)
:ivar str container: The container that the blobs are listed from.
:param callable command: Function to retrieve the next page of items.
:param str container: The name of the container.
:param int results_per_page: The maximum number of blobs to retrieve per
call.
:param str continuation_token: An opaque continuation token.
:param location_mode: Specifies the location the request should be sent to.
This mode only applies for RA-GRS accounts which allow secondary read access.
Options include 'primary' or 'secondary'.
"""
def __init__(
self, command,
container=None,
results_per_page=None,
continuation_token=None,
location_mode=None):
super(FilteredBlobPaged, self).__init__(
get_next=self._get_next_cb,
extract_data=self._extract_data_cb,
continuation_token=continuation_token or ""
)
self._command = command
self.service_endpoint = None
self.marker = continuation_token
self.results_per_page = results_per_page
self.container = container
self.current_page = None
self.location_mode = location_mode

def _get_next_cb(self, continuation_token):
try:
return self._command(
marker=continuation_token or None,
maxresults=self.results_per_page,
cls=return_context_and_deserialized,
use_location=self.location_mode)
except StorageErrorException as error:
process_storage_error(error)

def _extract_data_cb(self, get_next_return):
self.location_mode, self._response = get_next_return
self.service_endpoint = self._response.service_endpoint
self.marker = self._response.next_marker
self.current_page = [self._build_item(item) for item in self._response.blobs]

return self._response.next_marker or None, self.current_page

@staticmethod
def _build_item(item):
if isinstance(item, FilterBlobItem):
tags = parse_tags(item.tags)
blob = FilteredBlob(name=item.name, container_name=item.container_name, tags=tags)
return blob
return item
73 changes: 4 additions & 69 deletions sdk/storage/azure-storage-blob/azure/storage/blob/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from enum import Enum

from azure.core.paging import PageIterator
from azure.storage.blob._generated.models import FilterBlobItem, ArrowField
from ._generated.models import ArrowField

from ._shared import decode_base64_to_text
from ._shared.response_handlers import return_context_and_deserialized, process_storage_error
Expand Down Expand Up @@ -565,78 +565,13 @@ class FilteredBlob(DictMixin):
:type name: str
:ivar container_name: Container name.
:type container_name: str
:ivar tags: Key value pairs of blob tags.
:type tags: Dict[str, str]
"""
def __init__(self, **kwargs):
self.name = kwargs.get('name', None)
self.container_name = kwargs.get('container_name', None)


class FilteredBlobPaged(PageIterator):
"""An Iterable of Blob properties.
:ivar str service_endpoint: The service URL.
:ivar str prefix: A blob name prefix being used to filter the list.
:ivar str marker: The continuation token of the current page of results.
:ivar int results_per_page: The maximum number of results retrieved per API call.
:ivar str continuation_token: The continuation token to retrieve the next page of results.
:ivar str location_mode: The location mode being used to list results. The available
options include "primary" and "secondary".
:ivar current_page: The current page of listed results.
:vartype current_page: list(~azure.storage.blob.FilteredBlob)
:ivar str container: The container that the blobs are listed from.
:param callable command: Function to retrieve the next page of items.
:param str container: The name of the container.
:param int results_per_page: The maximum number of blobs to retrieve per
call.
:param str continuation_token: An opaque continuation token.
:param location_mode: Specifies the location the request should be sent to.
This mode only applies for RA-GRS accounts which allow secondary read access.
Options include 'primary' or 'secondary'.
"""
def __init__(
self, command,
container=None,
results_per_page=None,
continuation_token=None,
location_mode=None):
super(FilteredBlobPaged, self).__init__(
get_next=self._get_next_cb,
extract_data=self._extract_data_cb,
continuation_token=continuation_token or ""
)
self._command = command
self.service_endpoint = None
self.marker = continuation_token
self.results_per_page = results_per_page
self.container = container
self.current_page = None
self.location_mode = location_mode

def _get_next_cb(self, continuation_token):
try:
return self._command(
marker=continuation_token or None,
maxresults=self.results_per_page,
cls=return_context_and_deserialized,
use_location=self.location_mode)
except StorageErrorException as error:
process_storage_error(error)

def _extract_data_cb(self, get_next_return):
self.location_mode, self._response = get_next_return
self.service_endpoint = self._response.service_endpoint
self.marker = self._response.next_marker
self.current_page = [self._build_item(item) for item in self._response.blobs]

return self._response.next_marker or None, self.current_page

@staticmethod
def _build_item(item):
if isinstance(item, FilterBlobItem):
blob = FilteredBlob(name=item.name, container_name=item.container_name) # pylint: disable=protected-access
return blob
return item
self.tags = kwargs.get('tags', None)


class LeaseProperties(DictMixin):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,10 @@ async def set_blob_tags(self, tags=None, **kwargs):
:keyword str if_tags_match_condition:
Specify a SQL where clause on blob tags to operate only on blob with a matching value.
eg. "\"tagname\"='my tag'"
:keyword lease:
Required if the blob has an active lease. Value can be a BlobLeaseClient object
or the lease ID as a string.
:paramtype lease: ~azure.storage.blob.BlobLeaseClient or str
:keyword int timeout:
The timeout parameter is expressed in seconds.
:returns: Blob-updated property dict (Etag and last modified)
Expand All @@ -1552,6 +1556,10 @@ async def get_blob_tags(self, **kwargs):
:keyword str if_tags_match_condition:
Specify a SQL where clause on blob tags to operate only on blob with a matching value.
eg. "\"tagname\"='my tag'"
:keyword lease:
Required if the blob has an active lease. Value can be a BlobLeaseClient object
or the lease ID as a string.
:paramtype lease: ~azure.storage.blob.BlobLeaseClient or str
:keyword int timeout:
The timeout parameter is expressed in seconds.
:returns: Key value pairs of blob tags.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# pylint: disable=super-init-not-called, too-many-lines

from azure.core.async_paging import AsyncPageIterator
from .._deserialize import parse_tags

from .._models import ContainerProperties, FilteredBlob
from .._shared.response_handlers import return_context_and_deserialized, process_storage_error
Expand Down Expand Up @@ -136,6 +137,7 @@ async def _extract_data_cb(self, get_next_return):
@staticmethod
def _build_item(item):
if isinstance(item, FilterBlobItem):
blob = FilteredBlob(name=item.name, container_name=item.container_name) # pylint: disable=protected-access
tags = parse_tags(item.tags)
blob = FilteredBlob(name=item.name, container_name=item.container_name, tags=tags)
return blob
return item
Loading

0 comments on commit 2f81dfd

Please sign in to comment.