Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions sdk/storage/azure-storage-blob/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

### Features Added
- Added support for service version 2026-10-06.
- Added support for parsing List Blobs responses in Apache Arrow format by passing
`response_format="arrow"` keyword to `ContainerClient`'s `list_blobs` and `walk_blobs` APIs
(`response_format` defaults to `"auto"`, and `"auto"` currently means `"xml"`).
The use of `"response_format=arrow"` requires `nanoarrow` to be installed.
This change also enables the new `end_before` keyword for range-based listing.
- Added access tier information to the response of `BlobClient`'s `download_blob` API.
The `blob_tier`, `blob_tier_inferred`, `blob_tier_change_time`, and `smart_access_tier`
properties are now populated on the downloaded blob's `properties`.
Expand Down
8 changes: 8 additions & 0 deletions sdk/storage/azure-storage-blob/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1792,6 +1792,8 @@ namespace azure.storage.blob
name_starts_with: Optional[str] = None,
include: Optional[Union[str, List[str]]] = None,
*,
end_before: Optional[str] = ...,
response_format: Literal[auto, xml, arrow] = ...,
results_per_page: Optional[int] = ...,
start_from: Optional[str] = ...,
timeout: Optional[int] = ...,
Expand Down Expand Up @@ -1883,6 +1885,8 @@ namespace azure.storage.blob
include: Optional[Union[List[str], str]] = None,
delimiter: str = "/",
*,
end_before: Optional[str] = ...,
response_format: Literal[auto, xml, arrow] = ...,
start_from: Optional[str] = ...,
timeout: Optional[int] = ...,
**kwargs: Any
Expand Down Expand Up @@ -4438,6 +4442,8 @@ namespace azure.storage.blob.aio
name_starts_with: Optional[str] = None,
include: Optional[Union[str, List[str]]] = None,
*,
end_before: Optional[str] = ...,
response_format: Literal[auto, xml, arrow] = ...,
results_per_page: Optional[int] = ...,
start_from: Optional[str] = ...,
timeout: Optional[int] = ...,
Expand Down Expand Up @@ -4529,6 +4535,8 @@ namespace azure.storage.blob.aio
include: Optional[Union[List[str], str]] = None,
delimiter: str = "/",
*,
end_before: Optional[str] = ...,
response_format: Literal[auto, xml, arrow] = ...,
start_from: Optional[str] = ...,
timeout: Optional[int] = ...,
**kwargs: Any
Expand Down
2 changes: 1 addition & 1 deletion sdk/storage/azure-storage-blob/api.metadata.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
apiMdSha256: 38a660f5d55527fe389aaf9017736875f51f1f564acd4ea8aaaa547552b820b2
apiMdSha256: f8f6db831d73daab6cbc18c90924b1c164055d92775d0accc82a1e3ae0a364ff
parserVersion: 0.3.28
pythonVersion: 3.13.14
2 changes: 1 addition & 1 deletion sdk/storage/azure-storage-blob/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/storage/azure-storage-blob",
"Tag": "python/storage/azure-storage-blob_cd3cfd448d"
"Tag": "python/storage/azure-storage-blob_42c2d90038"
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,12 @@
"azure.storage.blob.aio.operations.ContainerOperations.change_lease": null,
"azure.storage.blob.operations.ContainerOperations.list_blob_flat_segment": null,
"azure.storage.blob.aio.operations.ContainerOperations.list_blob_flat_segment": null,
"azure.storage.blob.operations.ContainerOperations.list_blob_flat_segment_apache_arrow": null,
"azure.storage.blob.aio.operations.ContainerOperations.list_blob_flat_segment_apache_arrow": null,
"azure.storage.blob.operations.ContainerOperations.list_blob_hierarchy_segment": null,
"azure.storage.blob.aio.operations.ContainerOperations.list_blob_hierarchy_segment": null,
"azure.storage.blob.operations.ContainerOperations.list_blob_hierarchy_segment_apache_arrow": null,
"azure.storage.blob.aio.operations.ContainerOperations.list_blob_hierarchy_segment_apache_arrow": null,
"azure.storage.blob.operations.ContainerOperations.get_account_info": null,
"azure.storage.blob.aio.operations.ContainerOperations.get_account_info": null,
"azure.storage.blob.operations.BlobOperations.download": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
from ._generated.models import SignedIdentifier
from ._lease import BlobLeaseClient
from ._list_blobs_helper import (
ArrowBlobPropertiesPaged,
ArrowBlobPrefixPaged,
BlobNamesPaged,
BlobPrefix,
BlobPropertiesPaged,
Expand Down Expand Up @@ -803,9 +805,20 @@ def list_blobs(
:keyword int results_per_page:
Controls the maximum number of Blobs that will be included in each page of results if using
`ItemPaged.by_page()`.
:keyword response_format:
Comment thread
weirongw23-msft marked this conversation as resolved.
The format used to return and parse the List Blobs response.
Possible values are "auto", "xml", and "arrow".
Choose "auto" to let the SDK choose the best algorithm, currently "xml". The default value is "auto".

.. note::
The use of "arrow" requires `nanoarrow` to be installed.
:paramtype response_format: Literal["auto", "xml", "arrow"]
:keyword str start_from:
Specifies the full path (inclusive) to list paths from.
Only one entity level is supported.
:keyword str end_before:
Specifies the relative path (exclusive) to end before list paths.
This may be used if response_format is set to "arrow".
:keyword int timeout:
Sets the server-side timeout for the operation in seconds. For more details see
https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations.
Expand Down Expand Up @@ -834,15 +847,35 @@ def list_blobs(

results_per_page = kwargs.pop("results_per_page", None)
timeout = kwargs.pop("timeout", None)
response_format = kwargs.pop("response_format", "xml")
use_arrow = response_format == "arrow"
if use_arrow:
try:
import nanoarrow # pylint: disable=import-outside-toplevel,unused-import
except ImportError as e:
raise ValueError(
"The use of Apache Arrow deserialization requires nanoarrow to be installed. "
"Please install nanoarrow and try again."
) from e

command = functools.partial(
self._client.container.list_blob_flat_segment, include=include, timeout=timeout, **kwargs
(
self._client.container.list_blob_flat_segment_apache_arrow
if use_arrow
else self._client.container.list_blob_flat_segment
),
include=include,
timeout=timeout,
**kwargs,
)
return ItemPaged(
command,
prefix=name_starts_with,
results_per_page=results_per_page,
container=self.container_name,
page_iterator_class=BlobPropertiesPaged,
page_iterator_class=ArrowBlobPropertiesPaged if use_arrow else BlobPropertiesPaged,
# pylint: disable-next=protected-access
**({"deserializer": self._client.container._deserialize} if use_arrow else {}),
)

@distributed_trace
Expand Down Expand Up @@ -922,8 +955,19 @@ def walk_blobs(
element in the response body that acts as a placeholder for all blobs whose
names begin with the same substring up to the appearance of the delimiter
character. The delimiter may be a single character or a string.
:keyword response_format:
The format used to return and parse the List Blobs response.
Possible values are "auto", "xml", and "arrow".
Choose "auto" to let the SDK choose the best algorithm, currently "xml". The default value is "auto".

.. note::
The use of "arrow" requires `nanoarrow` to be installed.
:paramtype response_format: Literal["auto", "xml", "arrow"]
:keyword str start_from:
Specifies the full path (inclusive) to list paths from.
:keyword str end_before:
Specifies the relative path (exclusive) to end before list paths.
This may be used if response_format is set to "arrow".
:keyword int timeout:
Sets the server-side timeout for the operation in seconds. For more details see
https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations.
Expand All @@ -943,6 +987,33 @@ def walk_blobs(

results_per_page = kwargs.pop("results_per_page", None)
timeout = kwargs.pop("timeout", None)
response_format = kwargs.pop("response_format", "xml")
use_arrow = response_format == "arrow"
if use_arrow:
try:
import nanoarrow # pylint: disable=import-outside-toplevel,unused-import
except ImportError as e:
raise ValueError(
"The use of Apache Arrow deserialization requires nanoarrow to be installed. "
"Please install nanoarrow and try again."
) from e
command = functools.partial(
self._client.container.list_blob_hierarchy_segment_apache_arrow,
delimiter=delimiter,
include=include,
timeout=timeout,
**kwargs,
)
return ItemPaged(
command,
prefix=name_starts_with,
results_per_page=results_per_page,
container=self.container_name,
delimiter=delimiter,
deserializer=self._client.container._deserialize, # pylint: disable=protected-access
page_iterator_class=ArrowBlobPrefixPaged,
)

command = functools.partial(
self._client.container.list_blob_hierarchy_segment,
delimiter=delimiter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,9 @@ class ContainerClient(StorageAccountHostsMixin, StorageEncryptionMixin):
include: Optional[Union[str, List[str]]] = None,
*,
results_per_page: Optional[int] = None,
response_format: Literal["auto", "xml", "arrow"] = "auto",
start_from: Optional[str] = None,
end_before: Optional[str] = None,
timeout: Optional[int] = None,
**kwargs: Any,
) -> ItemPaged[BlobProperties]: ...
Expand All @@ -223,7 +225,9 @@ class ContainerClient(StorageAccountHostsMixin, StorageEncryptionMixin):
include: Optional[Union[List[str], str]] = None,
delimiter: str = "/",
*,
response_format: Literal["auto", "xml", "arrow"] = "auto",
start_from: Optional[str] = None,
end_before: Optional[str] = None,
timeout: Optional[int] = None,
**kwargs: Any,
) -> ItemPaged[Union[BlobProperties, BlobPrefix]]: ...
Expand Down
Loading