Skip to content

Commit 8b9851a

Browse files
[Storage] [STG 98] Merge STG 98 Base Branch into Main (Azure#40381)
1 parent f32da5e commit 8b9851a

File tree

116 files changed

+4155
-1220
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+4155
-1220
lines changed

.vscode/cspell.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,7 +1182,9 @@
11821182
"racwdlmeop",
11831183
"newfs",
11841184
"adlsstorage",
1185-
"adlskey"
1185+
"adlskey",
1186+
"skdutid",
1187+
"sduoid"
11861188
]
11871189
},
11881190
{
@@ -1497,7 +1499,9 @@
14971499
"Fsubdir",
14981500
"Fdir",
14991501
"adal",
1500-
"mytestshare"
1502+
"mytestshare",
1503+
"skdutid",
1504+
"sduoid"
15011505
]
15021506
},
15031507
{

sdk/storage/azure-storage-blob/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
## 12.26.0b1 (Unreleased)
44

55
### Features Added
6+
- Added support for service version 2025-07-05.
7+
- Added support for OAuth authentication in `ContainerClient`'s `get_container_access_policy`
8+
and `set_container_access_policy` APIs.
9+
- Added support for the keyword `source_token_intent` when copying from file share to blob and
10+
authenticated via `TokenCredential` for the following `BlobClient` APIs: `upload_blob_from_url`,
11+
`start_copy_from_url`, `stage_block_from_url`, `upload_pages_from_url`, and `append_block_from_url`.
12+
- Added support for `query_blob` in the asynchronous `BlobClient`.
613

714
## 12.25.1 (2025-03-27)
815

sdk/storage/azure-storage-blob/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/storage/azure-storage-blob",
5-
"Tag": "python/storage/azure-storage-blob_b11831f46e"
5+
"Tag": "python/storage/azure-storage-blob_56ef3e2a11"
66
}

sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,15 @@ def upload_blob_from_url(
422422
:keyword str source_authorization:
423423
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
424424
the prefix of the source_authorization string.
425+
:keyword source_token_intent:
426+
Required when source is Azure Storage Files and using `TokenCredential` for authentication.
427+
This is ignored for other forms of authentication.
428+
Specifies the intent for all requests when using `TokenCredential` authentication. Possible values are:
429+
430+
backup - Specifies requests are intended for backup/admin type operations, meaning that all file/directory
431+
ACLs are bypassed and full permissions are granted. User must also have required RBAC permission.
432+
433+
:paramtype source_token_intent: Literal['backup']
425434
:returns: Blob-updated property Dict (Etag and last modified)
426435
:rtype: Dict[str, Any]
427436
"""
@@ -430,7 +439,8 @@ def upload_blob_from_url(
430439
options = _upload_blob_from_url_options(
431440
source_url=source_url,
432441
metadata=metadata,
433-
**kwargs)
442+
**kwargs
443+
)
434444
try:
435445
return cast(Dict[str, Any], self._client.block_blob.put_blob_from_url(**options))
436446
except HttpResponseError as error:
@@ -1746,6 +1756,15 @@ def start_copy_from_url(
17461756
17471757
.. versionadded:: 12.9.0
17481758
1759+
:keyword source_token_intent:
1760+
Required when source is Azure Storage Files and using `TokenCredential` for authentication.
1761+
This is ignored for other forms of authentication.
1762+
Specifies the intent for all requests when using `TokenCredential` authentication. Possible values are:
1763+
1764+
backup - Specifies requests are intended for backup/admin type operations, meaning that all file/directory
1765+
ACLs are bypassed and full permissions are granted. User must also have required RBAC permission.
1766+
1767+
:paramtype source_token_intent: Literal['backup']
17491768
:keyword str encryption_scope:
17501769
A predefined encryption scope used to encrypt the data on the sync copied blob. An encryption
17511770
scope can be created using the Management API and referenced here by name. If a default
@@ -1770,7 +1789,8 @@ def start_copy_from_url(
17701789
source_url=source_url,
17711790
metadata=metadata,
17721791
incremental_copy=incremental_copy,
1773-
**kwargs)
1792+
**kwargs
1793+
)
17741794
try:
17751795
if incremental_copy:
17761796
return cast(Dict[str, Union[str, datetime]], self._client.page_blob.copy_incremental(**options))
@@ -2046,6 +2066,15 @@ def stage_block_from_url(
20462066
:keyword str source_authorization:
20472067
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
20482068
the prefix of the source_authorization string.
2069+
:keyword source_token_intent:
2070+
Required when source is Azure Storage Files and using `TokenCredential` for authentication.
2071+
This is ignored for other forms of authentication.
2072+
Specifies the intent for all requests when using `TokenCredential` authentication. Possible values are:
2073+
2074+
backup - Specifies requests are intended for backup/admin type operations, meaning that all file/directory
2075+
ACLs are bypassed and full permissions are granted. User must also have required RBAC permission.
2076+
2077+
:paramtype source_token_intent: Literal['backup']
20492078
:returns: Blob property dict.
20502079
:rtype: dict[str, Any]
20512080
"""
@@ -2057,7 +2086,8 @@ def stage_block_from_url(
20572086
source_offset=source_offset,
20582087
source_length=source_length,
20592088
source_content_md5=source_content_md5,
2060-
**kwargs)
2089+
**kwargs
2090+
)
20612091
try:
20622092
return cast(Dict[str, Any], self._client.block_blob.stage_block_from_url(**options))
20632093
except HttpResponseError as error:
@@ -2919,6 +2949,15 @@ def upload_pages_from_url(
29192949
:keyword str source_authorization:
29202950
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
29212951
the prefix of the source_authorization string.
2952+
:keyword source_token_intent:
2953+
Required when source is Azure Storage Files and using `TokenCredential` for authentication.
2954+
This is ignored for other forms of authentication.
2955+
Specifies the intent for all requests when using `TokenCredential` authentication. Possible values are:
2956+
2957+
backup - Specifies requests are intended for backup/admin type operations, meaning that all file/directory
2958+
ACLs are bypassed and full permissions are granted. User must also have required RBAC permission.
2959+
2960+
:paramtype source_token_intent: Literal['backup']
29222961
:returns: Response after uploading pages from specified URL.
29232962
:rtype: Dict[str, Any]
29242963
"""
@@ -3211,6 +3250,15 @@ def append_block_from_url(
32113250
:keyword str source_authorization:
32123251
Authenticate as a service principal using a client secret to access a source blob. Ensure "bearer " is
32133252
the prefix of the source_authorization string.
3253+
:keyword source_token_intent:
3254+
Required when source is Azure Storage Files and using `TokenCredential` for authentication.
3255+
This is ignored for other forms of authentication.
3256+
Specifies the intent for all requests when using `TokenCredential` authentication. Possible values are:
3257+
3258+
backup - Specifies requests are intended for backup/admin type operations, meaning that all file/directory
3259+
ACLs are bypassed and full permissions are granted. User must also have required RBAC permission.
3260+
3261+
:paramtype source_token_intent: Literal['backup']
32143262
:returns: Result after appending a new block.
32153263
:rtype: Dict[str, Union[str, datetime, int]]
32163264
"""

sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client_helpers.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ def _upload_blob_from_url_options(source_url: str, **kwargs: Any) -> Dict[str, A
197197
overwrite = kwargs.pop('overwrite', False)
198198
content_settings = kwargs.pop('content_settings', None)
199199
source_authorization = kwargs.pop('source_authorization', None)
200+
source_token_intent = kwargs.pop('source_token_intent', None)
200201
if content_settings:
201202
kwargs['blob_http_headers'] = BlobHTTPHeaders(
202203
blob_cache_control=content_settings.cache_control,
@@ -214,6 +215,7 @@ def _upload_blob_from_url_options(source_url: str, **kwargs: Any) -> Dict[str, A
214215

215216
options = {
216217
'copy_source_authorization': source_authorization,
218+
'file_request_intent': source_token_intent,
217219
'content_length': 0,
218220
'copy_source_blob_properties': kwargs.pop('include_source_blob_properties', True),
219221
'source_content_md5': kwargs.pop('source_content_md5', None),
@@ -376,7 +378,7 @@ def _quick_query_options(snapshot: Optional[str], query_expression: str, **kwarg
376378
'timeout': kwargs.pop('timeout', None),
377379
'cls': return_headers_and_deserialized,
378380
}
379-
options.update(kwargs)
381+
options.update({k: v for k, v in kwargs.items() if v is not None})
380382
return options, delimiter
381383

382384
def _generic_delete_blob_options(delete_snapshots: Optional[str] = None, **kwargs: Any) -> Dict[str, Any]:
@@ -607,6 +609,7 @@ def _start_copy_from_url_options( # pylint:disable=too-many-statements
607609
requires_sync = kwargs.pop('requires_sync', None)
608610
encryption_scope_str = kwargs.pop('encryption_scope', None)
609611
source_authorization = kwargs.pop('source_authorization', None)
612+
source_token_intent = kwargs.pop('source_token_intent', None)
610613
# If tags is a str, interpret that as copy_source_tags
611614
copy_source_tags = isinstance(tags, str)
612615

@@ -626,6 +629,8 @@ def _start_copy_from_url_options( # pylint:disable=too-many-statements
626629
headers['x-ms-encryption-scope'] = encryption_scope_str
627630
if source_authorization:
628631
headers['x-ms-copy-source-authorization'] = source_authorization
632+
if source_token_intent:
633+
headers['x-ms-file-request-intent'] = source_token_intent
629634
if copy_source_tags:
630635
headers['x-ms-copy-source-tag-option'] = tags
631636
else:
@@ -635,6 +640,9 @@ def _start_copy_from_url_options( # pylint:disable=too-many-statements
635640
if source_authorization:
636641
raise ValueError(
637642
"Source authorization tokens are only supported for sync copy, please specify requires_sync=True")
643+
if source_token_intent:
644+
raise ValueError(
645+
"Source token intent is only supported for sync copy, please specify requires_sync=True")
638646
if copy_source_tags:
639647
raise ValueError(
640648
"Copying source tags is only supported for sync copy, please specify requires_sync=True")
@@ -729,6 +737,7 @@ def _stage_block_from_url_options(
729737
) -> Dict[str, Any]:
730738
source_url = _encode_source_url(source_url=source_url)
731739
source_authorization = kwargs.pop('source_authorization', None)
740+
source_token_intent = kwargs.pop('source_token_intent', None)
732741
if source_length is not None and source_offset is None:
733742
raise ValueError("Source offset value must not be None if length is set.")
734743
if source_length is not None and source_offset is not None:
@@ -747,6 +756,7 @@ def _stage_block_from_url_options(
747756
encryption_algorithm=cpk.algorithm)
748757
options = {
749758
'copy_source_authorization': source_authorization,
759+
'file_request_intent': source_token_intent,
750760
'block_id': block_id,
751761
'content_length': 0,
752762
'source_url': source_url,
@@ -1010,6 +1020,7 @@ def _upload_pages_from_url_options(
10101020
if_sequence_number_equal_to=kwargs.pop('if_sequence_number_eq', None)
10111021
)
10121022
source_authorization = kwargs.pop('source_authorization', None)
1023+
source_token_intent = kwargs.pop('source_token_intent', None)
10131024
access_conditions = get_access_conditions(kwargs.pop('lease', None))
10141025
mod_conditions = get_modify_conditions(kwargs)
10151026
source_mod_conditions = get_source_conditions(kwargs)
@@ -1023,6 +1034,7 @@ def _upload_pages_from_url_options(
10231034

10241035
options = {
10251036
'copy_source_authorization': source_authorization,
1037+
'file_request_intent': source_token_intent,
10261038
'source_url': source_url,
10271039
'content_length': 0,
10281040
'source_range': source_range,
@@ -1152,6 +1164,7 @@ def _append_block_from_url_options(
11521164
append_position=appendpos_condition
11531165
)
11541166
source_authorization = kwargs.pop('source_authorization', None)
1167+
source_token_intent = kwargs.pop('source_token_intent', None)
11551168
access_conditions = get_access_conditions(kwargs.pop('lease', None))
11561169
mod_conditions = get_modify_conditions(kwargs)
11571170
source_mod_conditions = get_source_conditions(kwargs)
@@ -1164,6 +1177,7 @@ def _append_block_from_url_options(
11641177

11651178
options = {
11661179
'copy_source_authorization': source_authorization,
1180+
'file_request_intent': source_token_intent,
11671181
'source_url': copy_source_url,
11681182
'content_length': 0,
11691183
'source_range': source_range,

sdk/storage/azure-storage-blob/azure/storage/blob/_generated/_azure_blob_storage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class AzureBlobStorage: # pylint: disable=client-accepts-api-version-keyword
4848
:param base_url: Service URL. Required. Default value is "".
4949
:type base_url: str
5050
:keyword version: Specifies the version of the operation to use for this request. Default value
51-
is "2025-01-05". Note that overriding this default value may result in unsupported behavior.
51+
is "2025-07-05". Note that overriding this default value may result in unsupported behavior.
5252
:paramtype version: str
5353
"""
5454

sdk/storage/azure-storage-blob/azure/storage/blob/_generated/_configuration.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ class AzureBlobStorageConfiguration: # pylint: disable=too-many-instance-attrib
2323
desired operation. Required.
2424
:type url: str
2525
:keyword version: Specifies the version of the operation to use for this request. Default value
26-
is "2025-01-05". Note that overriding this default value may result in unsupported behavior.
26+
is "2025-07-05". Note that overriding this default value may result in unsupported behavior.
2727
:paramtype version: str
2828
"""
2929

3030
def __init__(self, url: str, **kwargs: Any) -> None:
31-
version: Literal["2025-01-05"] = kwargs.pop("version", "2025-01-05")
31+
version: Literal["2025-07-05"] = kwargs.pop("version", "2025-07-05")
3232

3333
if url is None:
3434
raise ValueError("Parameter 'url' must not be None.")

sdk/storage/azure-storage-blob/azure/storage/blob/_generated/_serialization.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# pylint: disable=too-many-lines
1+
# pylint: disable=line-too-long,useless-suppression,too-many-lines
22
# --------------------------------------------------------------------------
33
#
44
# Copyright (c) Microsoft Corporation. All rights reserved.
@@ -411,7 +411,7 @@ def from_dict(
411411
:param function key_extractors: A key extractor function.
412412
:param str content_type: JSON by default, set application/xml if XML.
413413
:returns: An instance of this model
414-
:raises: DeserializationError if something went wrong
414+
:raises DeserializationError: if something went wrong
415415
:rtype: Self
416416
"""
417417
deserializer = Deserializer(cls._infer_class_models())
@@ -1361,7 +1361,7 @@ def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument
13611361
# Iter and wrapped, should have found one node only (the wrap one)
13621362
if len(children) != 1:
13631363
raise DeserializationError(
1364-
"Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format( # pylint: disable=line-too-long
1364+
"Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format(
13651365
xml_name
13661366
)
13671367
)

sdk/storage/azure-storage-blob/azure/storage/blob/_generated/aio/_azure_blob_storage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class AzureBlobStorage: # pylint: disable=client-accepts-api-version-keyword
4848
:param base_url: Service URL. Required. Default value is "".
4949
:type base_url: str
5050
:keyword version: Specifies the version of the operation to use for this request. Default value
51-
is "2025-01-05". Note that overriding this default value may result in unsupported behavior.
51+
is "2025-07-05". Note that overriding this default value may result in unsupported behavior.
5252
:paramtype version: str
5353
"""
5454

sdk/storage/azure-storage-blob/azure/storage/blob/_generated/aio/_configuration.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ class AzureBlobStorageConfiguration: # pylint: disable=too-many-instance-attrib
2323
desired operation. Required.
2424
:type url: str
2525
:keyword version: Specifies the version of the operation to use for this request. Default value
26-
is "2025-01-05". Note that overriding this default value may result in unsupported behavior.
26+
is "2025-07-05". Note that overriding this default value may result in unsupported behavior.
2727
:paramtype version: str
2828
"""
2929

3030
def __init__(self, url: str, **kwargs: Any) -> None:
31-
version: Literal["2025-01-05"] = kwargs.pop("version", "2025-01-05")
31+
version: Literal["2025-07-05"] = kwargs.pop("version", "2025-07-05")
3232

3333
if url is None:
3434
raise ValueError("Parameter 'url' must not be None.")

0 commit comments

Comments
 (0)