Skip to content

Commit 8d35972

Browse files
authored
Merge pull request #427 from zezha-msft/1.1.0
Version 1.1.0: July 2017 service release
2 parents 6cf217b + f8d05a1 commit 8d35972

File tree

575 files changed

+32839
-29924
lines changed

Some content is hidden

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

575 files changed

+32839
-29924
lines changed

azure-storage-blob/ChangeLog.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
> See [BreakingChanges](BreakingChanges.md) for a detailed list of API breaks.
44
5+
## Version 1.1.0:
6+
7+
- Support for 2017-07-29 REST version. Please see our REST API documentation and blogs for information about the related added features.
8+
- Added support for soft delete feature. If a delete retention policy is enabled through the set service properties API, then blobs or snapshots could be deleted softly and retained for a specified number of days, before being permanently removed by garbage collection.
9+
- Error message now contains the ErrorCode from the x-ms-error-code header value.
10+
511
## Version 1.0.0:
612

713
- The package has switched from Apache 2.0 to the MIT license.
@@ -14,4 +20,4 @@
1420

1521
- Enabling MD5 validation no longer uses the memory-efficient algorithm for large block blobs, since computing the MD5 hash requires reading the entire block into memory.
1622
- Fixed a bug in the _SubStream class which was at risk of causing data corruption when using the memory-efficient algorithm for large block blobs.
17-
- Support for AccessTierChangeTime to get the last time a tier was modified on an individual blob.
23+
- Support for AccessTierChangeTime to get the last time a tier was modified on an individual blob.

azure-storage-blob/azure/storage/blob/_constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
# --------------------------------------------------------------------------
66

77
__author__ = 'Microsoft Corp. <[email protected]>'
8-
__version__ = '1.0.0'
8+
__version__ = '1.1.0'
99

1010
# x-ms-version for storage service.
11-
X_MS_VERSION = '2017-04-17'
11+
X_MS_VERSION = '2017-07-29'
1212

1313
# internal configurations, should not be changed
1414
_LARGE_BLOB_UPLOAD_MAX_READ_BUFFER_SIZE = 4 * 1024 * 1024

azure-storage-blob/azure/storage/blob/_deserialization.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
)
1818
from azure.storage.common._deserialization import (
1919
_parse_properties,
20-
_int_to_str,
20+
_to_int,
2121
_parse_metadata,
2222
_convert_xml_to_signed_identifiers,
2323
_bool,
@@ -62,7 +62,7 @@ def _parse_page_properties(response):
6262
put_page = PageBlobProperties()
6363
put_page.last_modified = parser.parse(response.headers.get('last-modified'))
6464
put_page.etag = response.headers.get('etag')
65-
put_page.sequence_number = _int_to_str(response.headers.get('x-ms-blob-sequence-number'))
65+
put_page.sequence_number = _to_int(response.headers.get('x-ms-blob-sequence-number'))
6666

6767
return put_page
6868

@@ -74,8 +74,8 @@ def _parse_append_block(response):
7474
append_block = AppendBlockProperties()
7575
append_block.last_modified = parser.parse(response.headers.get('last-modified'))
7676
append_block.etag = response.headers.get('etag')
77-
append_block.append_offset = _int_to_str(response.headers.get('x-ms-blob-append-offset'))
78-
append_block.committed_block_count = _int_to_str(response.headers.get('x-ms-blob-committed-block-count'))
77+
append_block.append_offset = _to_int(response.headers.get('x-ms-blob-append-offset'))
78+
append_block.committed_block_count = _to_int(response.headers.get('x-ms-blob-committed-block-count'))
7979

8080
return append_block
8181

@@ -95,7 +95,7 @@ def _parse_lease(response):
9595
'''
9696
lease = {'time': response.headers.get('x-ms-lease-time')}
9797
if lease['time']:
98-
lease['time'] = _int_to_str(lease['time'])
98+
lease['time'] = _to_int(lease['time'])
9999

100100
lease['id'] = response.headers.get('x-ms-lease-id')
101101

@@ -215,9 +215,9 @@ def _convert_xml_to_containers(response):
215215
LIST_BLOBS_ATTRIBUTE_MAP = {
216216
'Last-Modified': (None, 'last_modified', parser.parse),
217217
'Etag': (None, 'etag', _to_str),
218-
'x-ms-blob-sequence-number': (None, 'sequence_number', _int_to_str),
218+
'x-ms-blob-sequence-number': (None, 'sequence_number', _to_int),
219219
'BlobType': (None, 'blob_type', _to_str),
220-
'Content-Length': (None, 'content_length', _int_to_str),
220+
'Content-Length': (None, 'content_length', _to_int),
221221
'ServerEncrypted': (None, 'server_encrypted', _bool),
222222
'Content-Type': ('content_settings', 'content_type', _to_str),
223223
'Content-Encoding': ('content_settings', 'content_encoding', _to_str),
@@ -238,6 +238,8 @@ def _convert_xml_to_containers(response):
238238
'AccessTierChangeTime': (None, 'blob_tier_change_time', parser.parse),
239239
'AccessTierInferred': (None, 'blob_tier_inferred', _bool),
240240
'ArchiveStatus': (None, 'rehydration_status', _to_str),
241+
'DeletedTime': (None, 'deleted_time', parser.parse),
242+
'RemainingRetentionDays': (None, 'remaining_retention_days', _to_int),
241243
}
242244

243245

@@ -252,6 +254,7 @@ def _convert_xml_to_blob_list(response):
252254
<Blobs>
253255
<Blob>
254256
<Name>blob-name</name>
257+
<Deleted>true</Deleted>
255258
<Snapshot>date-time-value</Snapshot>
256259
<Properties>
257260
<Last-Modified>date-time-value</Last-Modified>
@@ -276,6 +279,8 @@ def _convert_xml_to_blob_list(response):
276279
<AccessTier>P4 | P6 | P10 | P20 | P30 | P40 | P50 | P60 | Archive | Cool | Hot</AccessTier>
277280
<AccessTierChangeTime>date-time-value</AccessTierChangeTime>
278281
<AccessTierInferred>true</AccessTierInferred>
282+
<DeletedTime>datetime</DeletedTime>
283+
<RemainingRetentionDays>int</RemainingRetentionDays>
279284
</Properties>
280285
<Metadata>
281286
<Name>value</Name>
@@ -309,6 +314,10 @@ def _convert_xml_to_blob_list(response):
309314
blob.name = blob_element.findtext('Name')
310315
blob.snapshot = blob_element.findtext('Snapshot')
311316

317+
deleted = blob_element.findtext('Deleted')
318+
if deleted:
319+
blob.deleted = _bool(deleted)
320+
312321
# Properties
313322
properties_element = blob_element.find('Properties')
314323
if properties_element is not None:

azure-storage-blob/azure/storage/blob/appendblobservice.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def create_blob(self, container_name, blob_name, content_settings=None,
120120
if_modified_since=None, if_unmodified_since=None,
121121
if_match=None, if_none_match=None, timeout=None):
122122
'''
123-
Creates a blob or overrides an existing blob. Use if_match=* to
123+
Creates a blob or overrides an existing blob. Use if_none_match=* to
124124
prevent overriding an existing blob.
125125
126126
See create_blob_from_* for high level

azure-storage-blob/azure/storage/blob/baseblobservice.py

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,10 @@ def _list_blobs(self, container_name, prefix=None, marker=None,
12781278
Version 2012-02-12 and newer. Specifies that metadata
12791279
related to any current or previous Copy Blob operation
12801280
should be included in the response.
1281+
deleted:
1282+
Version 2017-07-29 and newer. Specifies that soft deleted blobs
1283+
which are retained by the service should be included
1284+
in the response.
12811285
:param str delimiter:
12821286
When the request includes this parameter, the operation
12831287
returns a :class:`~azure.storage.blob.models.BlobPrefix` element in the response body that acts as a
@@ -1343,30 +1347,41 @@ def get_blob_service_stats(self, timeout=None):
13431347

13441348
def set_blob_service_properties(
13451349
self, logging=None, hour_metrics=None, minute_metrics=None,
1346-
cors=None, target_version=None, timeout=None):
1350+
cors=None, target_version=None, timeout=None, delete_retention_policy=None):
13471351
'''
13481352
Sets the properties of a storage account's Blob service, including
13491353
Azure Storage Analytics. If an element (ex Logging) is left as None, the
13501354
existing settings on the service for that functionality are preserved.
13511355
1352-
:param Logging logging:
1356+
:param logging:
13531357
Groups the Azure Analytics Logging settings.
1354-
:param Metrics hour_metrics:
1358+
:type logging:
1359+
:class:`~azure.storage.common.models.Logging`
1360+
:param hour_metrics:
13551361
The hour metrics settings provide a summary of request
13561362
statistics grouped by API in hourly aggregates for blobs.
1357-
:param Metrics minute_metrics:
1363+
:type hour_metrics:
1364+
:class:`~azure.storage.common.models.Metrics`
1365+
:param minute_metrics:
13581366
The minute metrics settings provide request statistics
13591367
for each minute for blobs.
1368+
:type minute_metrics:
1369+
:class:`~azure.storage.common.models.Metrics`
13601370
:param cors:
13611371
You can include up to five CorsRule elements in the
13621372
list. If an empty list is specified, all CORS rules will be deleted,
13631373
and CORS will be disabled for the service.
13641374
:type cors: list(:class:`~azure.storage.common.models.CorsRule`)
1365-
:param string target_version:
1375+
:param str target_version:
13661376
Indicates the default version to use for requests if an incoming
13671377
request's version is not specified.
13681378
:param int timeout:
13691379
The timeout parameter is expressed in seconds.
1380+
:param delete_retention_policy:
1381+
The delete retention policy specifies whether to retain deleted blobs.
1382+
It also specifies the number of days and versions of blob to keep.
1383+
:type delete_retention_policy:
1384+
:class:`~azure.storage.common.models.DeleteRetentionPolicy`
13701385
'''
13711386
request = HTTPRequest()
13721387
request.method = 'PUT'
@@ -1378,7 +1393,8 @@ def set_blob_service_properties(
13781393
'timeout': _int_to_str(timeout),
13791394
}
13801395
request.body = _get_request_body(
1381-
_convert_service_properties_to_xml(logging, hour_metrics, minute_metrics, cors, target_version))
1396+
_convert_service_properties_to_xml(logging, hour_metrics, minute_metrics,
1397+
cors, target_version, delete_retention_policy))
13821398

13831399
self._perform_request(request)
13841400

@@ -1389,10 +1405,8 @@ def get_blob_service_properties(self, timeout=None):
13891405
13901406
:param int timeout:
13911407
The timeout parameter is expressed in seconds.
1392-
:return: The blob service properties.
1393-
:rtype:
1394-
:class:`~azure.storage.common.models.ServiceProperties` with an attached
1395-
target_version property
1408+
:return: The blob :class:`~azure.storage.common.models.ServiceProperties` with an attached
1409+
target_version property.
13961410
'''
13971411
request = HTTPRequest()
13981412
request.method = 'GET'
@@ -3136,6 +3150,12 @@ def delete_blob(self, container_name, blob_name, snapshot=None,
31363150
snapshots. You can delete both at the same time with the Delete
31373151
Blob operation.
31383152
3153+
If a delete retention policy is enabled for the service, then this operation soft deletes the blob or snapshot
3154+
and retains the blob or snapshot for specified number of days.
3155+
After specified number of days, blob's data is removed from the service during garbage collection.
3156+
Soft deleted blob or snapshot is accessible through List Blobs API specifying include=Include.Deleted option.
3157+
Soft-deleted blob or snapshot can be restored using Undelete API.
3158+
31393159
:param str container_name:
31403160
Name of existing container.
31413161
:param str blob_name:
@@ -3191,3 +3211,28 @@ def delete_blob(self, container_name, blob_name, snapshot=None,
31913211
}
31923212

31933213
self._perform_request(request)
3214+
3215+
def undelete_blob(self, container_name, blob_name, timeout=None):
3216+
'''
3217+
The undelete Blob operation restores the contents and metadata of soft deleted blob or snapshot.
3218+
Attempting to undelete a blob or snapshot that is not soft deleted will succeed without any changes.
3219+
3220+
:param str container_name:
3221+
Name of existing container.
3222+
:param str blob_name:
3223+
Name of existing blob.
3224+
:param int timeout:
3225+
The timeout parameter is expressed in seconds.
3226+
'''
3227+
_validate_not_none('container_name', container_name)
3228+
_validate_not_none('blob_name', blob_name)
3229+
request = HTTPRequest()
3230+
request.method = 'PUT'
3231+
request.host_locations = self._get_host_locations()
3232+
request.path = _get_path(container_name, blob_name)
3233+
request.query = {
3234+
'comp': 'undelete',
3235+
'timeout': _int_to_str(timeout)
3236+
}
3237+
3238+
self._perform_request(request)

azure-storage-blob/azure/storage/blob/models.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,20 @@ class Blob(object):
6565
Stores all the system properties for the blob.
6666
:ivar metadata:
6767
Name-value pairs associated with the blob as metadata.
68+
:ivar bool deleted:
69+
Specify whether the blob was soft deleted.
70+
In other words, if the blob is being retained by the delete retention policy,
71+
this field would be True. The blob could be undeleted or it will be garbage collected after the specified
72+
time period.
6873
'''
6974

70-
def __init__(self, name=None, snapshot=None, content=None, props=None, metadata=None):
75+
def __init__(self, name=None, snapshot=None, content=None, props=None, metadata=None, deleted=False):
7176
self.name = name
7277
self.snapshot = snapshot
7378
self.content = content
7479
self.properties = props or BlobProperties()
7580
self.metadata = metadata
81+
self.deleted = deleted
7682

7783

7884
class BlobProperties(object):
@@ -118,6 +124,10 @@ class BlobProperties(object):
118124
:ivar bool blob_tier_inferred:
119125
Indicates whether the access tier was inferred by the service.
120126
If false, it indicates that the tier was set explicitly.
127+
:ivar datetime deleted_time:
128+
A datetime object representing the time at which the blob was deleted.
129+
:ivar int remaining_retention_days:
130+
The number of days that the blob will be retained before being permanently deleted by the service.
121131
'''
122132

123133
def __init__(self):
@@ -135,6 +145,8 @@ def __init__(self):
135145
self.blob_tier = None
136146
self.blob_tier_change_time = None
137147
self.blob_tier_inferred = False
148+
self.deleted_time = None
149+
self.remaining_retention_days = None
138150

139151

140152
class ContentSettings(object):
@@ -506,10 +518,12 @@ class Include(object):
506518
:ivar ~azure.storage.blob.models.Include Include.UNCOMMITTED_BLOBS:
507519
Specifies that blobs for which blocks have been uploaded, but which have not
508520
been committed using Put Block List, be included in the response.
521+
:ivar ~azure.storage.blob.models.Include Include.DELETED:
522+
Specifies that deleted blobs should be returned in the response.
509523
'''
510524

511525
def __init__(self, snapshots=False, metadata=False, uncommitted_blobs=False,
512-
copy=False, _str=None):
526+
copy=False, deleted=False, _str=None):
513527
'''
514528
:param bool snapshots:
515529
Specifies that snapshots should be included in the enumeration.
@@ -520,7 +534,9 @@ def __init__(self, snapshots=False, metadata=False, uncommitted_blobs=False,
520534
not been committed using Put Block List, be included in the response.
521535
:param bool copy:
522536
Specifies that metadata related to any current or previous Copy Blob
523-
operation should be included in the response.
537+
operation should be included in the response.
538+
:param bool deleted:
539+
Specifies that deleted blobs should be returned in the response.
524540
:param str _str:
525541
A string representing the includes.
526542
'''
@@ -531,6 +547,7 @@ def __init__(self, snapshots=False, metadata=False, uncommitted_blobs=False,
531547
self.metadata = metadata or ('metadata' in components)
532548
self.uncommitted_blobs = uncommitted_blobs or ('uncommittedblobs' in components)
533549
self.copy = copy or ('copy' in components)
550+
self.deleted = deleted or ('deleted' in components)
534551

535552
def __or__(self, other):
536553
return Include(_str=str(self) + str(other))
@@ -542,14 +559,16 @@ def __str__(self):
542559
include = (('snapshots,' if self.snapshots else '') +
543560
('metadata,' if self.metadata else '') +
544561
('uncommittedblobs,' if self.uncommitted_blobs else '') +
545-
('copy,' if self.copy else ''))
562+
('copy,' if self.copy else '') +
563+
('deleted,' if self.deleted else ''))
546564
return include.rstrip(',')
547565

548566

549567
Include.COPY = Include(copy=True)
550568
Include.METADATA = Include(metadata=True)
551569
Include.SNAPSHOTS = Include(snapshots=True)
552570
Include.UNCOMMITTED_BLOBS = Include(uncommitted_blobs=True)
571+
Include.DELETED = Include(deleted=True)
553572

554573

555574
class BlobPermissions(object):

azure-storage-blob/setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
setup(
5353
name='azure-storage-blob',
54-
version='1.0.0',
54+
version='1.1.0',
5555
description='Microsoft Azure Storage Blob Client Library for Python',
5656
long_description=open('README.rst', 'r').read(),
5757
license='MIT License',
@@ -74,7 +74,7 @@
7474
packages=find_packages(),
7575
install_requires=[
7676
'azure-common>=1.1.5',
77-
'azure-storage-common>=1.0.0,<1.1.0'
77+
'azure-storage-common>=1.1.0,<1.2.0'
7878
],
7979
extras_require={
8080
":python_version<'3.0'": ['futures'],

azure-storage-common/BreakingChanges.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
> See the [Change Log](ChangeLog.md) for a summary of storage library changes.
44
5+
## Version 1.1.0:
6+
7+
- Error message now contains the ErrorCode from the x-ms-error-code header value.
8+
59
## Version 1.0.0:
610

711
- Renamed the confusing argument name increment_power to increment_base on ExponentialRetry.

azure-storage-common/ChangeLog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
> See [BreakingChanges](BreakingChanges.md) for a detailed list of API breaks.
44
5+
## Version 1.1.0:
6+
7+
- Support for 2017-07-29 REST version. Please see our REST API documentation and blogs for information about the related added features.
8+
- Error message now contains the ErrorCode from the x-ms-error-code header value.
9+
510
## Version 1.0.0:
611

712
- The package has switched from Apache 2.0 to the MIT license.

azure-storage-common/azure/storage/common/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Logging,
1515
Metrics,
1616
CorsRule,
17+
DeleteRetentionPolicy,
1718
ServiceProperties,
1819
AccessPolicy,
1920
ResourceTypes,

0 commit comments

Comments
 (0)