Skip to content
Open
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
2 changes: 2 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,8 @@

### Features Added
- Added support for service version 2026-04-06.
- Added support for the keywords `access_tier_if_modified_since` and `access_tier_if_unmodified_since` to
conditionally perform `BlobClient.delete_blob` operation.

## 12.28.0b1 (Unreleased)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,18 @@ def delete_blob(self, delete_snapshots: Optional[str] = None, **kwargs: Any) ->

.. versionadded:: 12.4.0

:keyword ~datetime.datetime access_tier_if_modified_since:
A DateTime value. Azure expects the date value passed in to be UTC.
If timezone is included, any non-UTC datetimes will be converted to UTC.
If a date is passed in without timezone info, it is assumed to be UTC.
Specify this header to perform the operation only if
the access-tier has been modified since the specified date/time.
:keyword ~datetime.datetime access_tier_if_unmodified_since:
A DateTime value. Azure expects the date value passed in to be UTC.
If timezone is included, any non-UTC datetimes will be converted to UTC.
If a date is passed in without timezone info, it is assumed to be UTC.
Specify this header to perform the operation only if
the access-tier has been modified since the specified date/time.
: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 @@ -954,7 +966,8 @@ def delete_blob(self, delete_snapshots: Optional[str] = None, **kwargs: Any) ->
snapshot=self.snapshot,
version_id=get_version_id(self.version_id, kwargs),
delete_snapshots=delete_snapshots,
**kwargs)
**kwargs
)
try:
self._client.blob.delete(**options)
except HttpResponseError as error:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ class BlobClient(StorageAccountHostsMixin, StorageEncryptionMixin):
etag: Optional[str] = None,
match_condition: Optional[MatchConditions] = None,
if_tags_match_condition: Optional[str] = None,
access_tier_if_modified_since: Optional[datetime] = None,
access_tier_if_unmodified_since: Optional[datetime] = None,
timeout: Optional[int] = None,
**kwargs: Any
) -> None: ...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ def _generic_delete_blob_options(delete_snapshots: Optional[str] = None, **kwarg
'snapshot': kwargs.pop('snapshot', None), # this is added for delete_blobs
'delete_snapshots': delete_snapshots or None,
'lease_access_conditions': access_conditions,
'modified_access_conditions': mod_conditions}
'modified_access_conditions': mod_conditions
}
options.update(kwargs)
return options

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class AzureBlobStorage: # pylint: disable=client-accepts-api-version-keyword
:param base_url: Service URL. Required. Default value is "".
:type base_url: str
:keyword version: Specifies the version of the operation to use for this request. Default value
is "2026-02-06". Note that overriding this default value may result in unsupported behavior.
is "2026-04-06". Note that overriding this default value may result in unsupported behavior.
:paramtype version: str
"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ class AzureBlobStorageConfiguration: # pylint: disable=too-many-instance-attrib
desired operation. Required.
:type url: str
:keyword version: Specifies the version of the operation to use for this request. Default value
is "2026-02-06". Note that overriding this default value may result in unsupported behavior.
is "2026-04-06". Note that overriding this default value may result in unsupported behavior.
:paramtype version: str
"""

def __init__(self, url: str, **kwargs: Any) -> None:
version: Literal["2026-02-06"] = kwargs.pop("version", "2026-02-06")
version: Literal["2026-04-06"] = kwargs.pop("version", "2026-04-06")

if url is None:
raise ValueError("Parameter 'url' must not be None.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import sys
import codecs
from typing import (
Dict,
Any,
cast,
Optional,
Expand All @@ -31,7 +30,6 @@
Mapping,
Callable,
MutableMapping,
List,
)

try:
Expand Down Expand Up @@ -229,12 +227,12 @@ class Model:
serialization and deserialization.
"""

_subtype_map: Dict[str, Dict[str, Any]] = {}
_attribute_map: Dict[str, Dict[str, Any]] = {}
_validation: Dict[str, Dict[str, Any]] = {}
_subtype_map: dict[str, dict[str, Any]] = {}
_attribute_map: dict[str, dict[str, Any]] = {}
_validation: dict[str, dict[str, Any]] = {}

def __init__(self, **kwargs: Any) -> None:
self.additional_properties: Optional[Dict[str, Any]] = {}
self.additional_properties: Optional[dict[str, Any]] = {}
for k in kwargs: # pylint: disable=consider-using-dict-items
if k not in self._attribute_map:
_LOGGER.warning("%s is not a known attribute of class %s and will be ignored", k, self.__class__)
Expand Down Expand Up @@ -311,7 +309,7 @@ def serialize(self, keep_readonly: bool = False, **kwargs: Any) -> JSON:
def as_dict(
self,
keep_readonly: bool = True,
key_transformer: Callable[[str, Dict[str, Any], Any], Any] = attribute_transformer,
key_transformer: Callable[[str, dict[str, Any], Any], Any] = attribute_transformer,
**kwargs: Any
) -> JSON:
"""Return a dict that can be serialized using json.dump.
Expand Down Expand Up @@ -380,7 +378,7 @@ def deserialize(cls, data: Any, content_type: Optional[str] = None) -> Self:
def from_dict(
cls,
data: Any,
key_extractors: Optional[Callable[[str, Dict[str, Any], Any], Any]] = None,
key_extractors: Optional[Callable[[str, dict[str, Any], Any], Any]] = None,
content_type: Optional[str] = None,
) -> Self:
"""Parse a dict using given key extractor return a model.
Expand Down Expand Up @@ -414,7 +412,7 @@ def _flatten_subtype(cls, key, objects):
return {}
result = dict(cls._subtype_map[key])
for valuetype in cls._subtype_map[key].values():
result.update(objects[valuetype]._flatten_subtype(key, objects)) # pylint: disable=protected-access
result |= objects[valuetype]._flatten_subtype(key, objects) # pylint: disable=protected-access
return result

@classmethod
Expand Down Expand Up @@ -528,7 +526,7 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
"[]": self.serialize_iter,
"{}": self.serialize_dict,
}
self.dependencies: Dict[str, type] = dict(classes) if classes else {}
self.dependencies: dict[str, type] = dict(classes) if classes else {}
self.key_transformer = full_restapi_key_transformer
self.client_side_validation = True

Expand Down Expand Up @@ -579,7 +577,7 @@ def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, to

if attr_name == "additional_properties" and attr_desc["key"] == "":
if target_obj.additional_properties is not None:
serialized.update(target_obj.additional_properties)
serialized |= target_obj.additional_properties
continue
try:

Expand Down Expand Up @@ -789,7 +787,7 @@ def serialize_data(self, data, data_type, **kwargs):

# If dependencies is empty, try with current data class
# It has to be a subclass of Enum anyway
enum_type = self.dependencies.get(data_type, data.__class__)
enum_type = self.dependencies.get(data_type, cast(type, data.__class__))
if issubclass(enum_type, Enum):
return Serializer.serialize_enum(data, enum_obj=enum_type)

Expand Down Expand Up @@ -1184,7 +1182,7 @@ def rest_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argumen

while "." in key:
# Need the cast, as for some reasons "split" is typed as list[str | Any]
dict_keys = cast(List[str], _FLATTEN.split(key))
dict_keys = cast(list[str], _FLATTEN.split(key))
if len(dict_keys) == 1:
key = _decode_attribute_map_key(dict_keys[0])
break
Expand Down Expand Up @@ -1386,7 +1384,7 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
"duration": (isodate.Duration, datetime.timedelta),
"iso-8601": (datetime.datetime),
}
self.dependencies: Dict[str, type] = dict(classes) if classes else {}
self.dependencies: dict[str, type] = dict(classes) if classes else {}
self.key_extractors = [rest_key_extractor, xml_key_extractor]
# Additional properties only works if the "rest_key_extractor" is used to
# extract the keys. Making it to work whatever the key extractor is too much
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class AzureBlobStorage: # pylint: disable=client-accepts-api-version-keyword
:param base_url: Service URL. Required. Default value is "".
:type base_url: str
:keyword version: Specifies the version of the operation to use for this request. Default value
is "2026-02-06". Note that overriding this default value may result in unsupported behavior.
is "2026-04-06". Note that overriding this default value may result in unsupported behavior.
:paramtype version: str
"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ class AzureBlobStorageConfiguration: # pylint: disable=too-many-instance-attrib
desired operation. Required.
:type url: str
:keyword version: Specifies the version of the operation to use for this request. Default value
is "2026-02-06". Note that overriding this default value may result in unsupported behavior.
is "2026-04-06". Note that overriding this default value may result in unsupported behavior.
:paramtype version: str
"""

def __init__(self, url: str, **kwargs: Any) -> None:
version: Literal["2026-02-06"] = kwargs.pop("version", "2026-02-06")
version: Literal["2026-04-06"] = kwargs.pop("version", "2026-04-06")

if url is None:
raise ValueError("Parameter 'url' must not be None.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# --------------------------------------------------------------------------
from collections.abc import MutableMapping
import datetime
from typing import Any, Callable, Dict, IO, Literal, Optional, TypeVar, Union
from typing import Any, Callable, IO, Literal, Optional, TypeVar, Union

from azure.core import AsyncPipelineClient
from azure.core.exceptions import (
Expand All @@ -35,7 +35,7 @@
from .._configuration import AzureBlobStorageConfiguration

T = TypeVar("T")
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, dict[str, Any]], Any]]


class AppendBlobOperations:
Expand All @@ -62,7 +62,7 @@ async def create(
self,
content_length: int,
timeout: Optional[int] = None,
metadata: Optional[Dict[str, str]] = None,
metadata: Optional[dict[str, str]] = None,
request_id_parameter: Optional[str] = None,
blob_tags_string: Optional[str] = None,
immutability_policy_expiry: Optional[datetime.datetime] = None,
Expand Down Expand Up @@ -215,7 +215,10 @@ async def create(

if response.status_code not in [201]:
map_error(status_code=response.status_code, response=response, error_map=error_map)
error = self._deserialize.failsafe_deserialize(_models.StorageError, pipeline_response)
error = self._deserialize.failsafe_deserialize(
_models.StorageError,
pipeline_response,
)
raise HttpResponseError(response=response, model=error)

response_headers = {}
Expand Down Expand Up @@ -390,7 +393,10 @@ async def append_block(

if response.status_code not in [201]:
map_error(status_code=response.status_code, response=response, error_map=error_map)
error = self._deserialize.failsafe_deserialize(_models.StorageError, pipeline_response)
error = self._deserialize.failsafe_deserialize(
_models.StorageError,
pipeline_response,
)
raise HttpResponseError(response=response, model=error)

response_headers = {}
Expand Down Expand Up @@ -598,7 +604,10 @@ async def append_block_from_url(

if response.status_code not in [201]:
map_error(status_code=response.status_code, response=response, error_map=error_map)
error = self._deserialize.failsafe_deserialize(_models.StorageError, pipeline_response)
error = self._deserialize.failsafe_deserialize(
_models.StorageError,
pipeline_response,
)
raise HttpResponseError(response=response, model=error)

response_headers = {}
Expand Down Expand Up @@ -719,7 +728,10 @@ async def seal(

if response.status_code not in [200]:
map_error(status_code=response.status_code, response=response, error_map=error_map)
error = self._deserialize.failsafe_deserialize(_models.StorageError, pipeline_response)
error = self._deserialize.failsafe_deserialize(
_models.StorageError,
pipeline_response,
)
raise HttpResponseError(response=response, model=error)

response_headers = {}
Expand Down
Loading
Loading