Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,7 @@ src/build
.cache/

# virtual environments for testing generated by validate_packages.py
py*test-*/*
py*test-*/*

# pytest cache
.pytest_cache/*
6 changes: 1 addition & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ matrix:
include:
- os: linux
python: "2.7"
- os: linux
python: "3.3"
- os: linux
python: "3.4"
- os: linux
python: "3.5"
- os: linux
python: "3.6"
- os: linux
python: "nightly"
- os: linux
python: "pypy3.5-5.8.0"
- os: osx
Expand All @@ -31,7 +27,7 @@ matrix:
before_install:
- if [[ -n "$TRAVIS_TAG" && "$TRAVIS_PYTHON_VERSION" != "3.6" ]]; then travis_terminate 0; fi; # Deploy on 3.6
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python3; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade python; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then python3 -m venv venv; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source venv/bin/activate; fi
install:
Expand Down
6 changes: 6 additions & 0 deletions azure-storage-blob/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

> See [BreakingChanges](BreakingChanges.md) for a detailed list of API breaks.

## Version 1.2.0rc1:

- Support for 2017-11-09 REST version. Please see our REST API documentation and blog for information about the related added features.
- Support for write-once read-many containers.
- Added support for OAuth authentication for HTTPS requests(Please note that this feature is available in preview).

## Version 1.1.0:

- Support for 2017-07-29 REST version. Please see our REST API documentation and blogs for information about the related added features.
Expand Down
4 changes: 2 additions & 2 deletions azure-storage-blob/azure/storage/blob/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
# --------------------------------------------------------------------------

__author__ = 'Microsoft Corp. <ptvshelp@microsoft.com>'
__version__ = '1.1.0'
__version__ = '1.2.0rc1'

# x-ms-version for storage service.
X_MS_VERSION = '2017-07-29'
X_MS_VERSION = '2017-11-09'

# internal configurations, should not be changed
_LARGE_BLOB_UPLOAD_MAX_READ_BUFFER_SIZE = 4 * 1024 * 1024
6 changes: 6 additions & 0 deletions azure-storage-blob/azure/storage/blob/_deserialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ def _convert_xml_to_containers(response):
<LeaseState>available | leased | expired | breaking | broken</LeaseState>
<LeaseDuration>infinite | fixed</LeaseDuration>
<PublicAccess>blob | container</PublicAccess>
<HasImmutabilityPolicy>true | false</HasImmutabilityPolicy>
<HasLegalHold>true | false</HasLegalHold>
</Properties>
<Metadata>
<metadata-name>value</metadata-name>
Expand Down Expand Up @@ -205,6 +207,8 @@ def _convert_xml_to_containers(response):
container.properties.lease_state = properties_element.findtext('LeaseState')
container.properties.lease_duration = properties_element.findtext('LeaseDuration')
container.properties.public_access = properties_element.findtext('PublicAccess')
container.properties.has_immutability_policy = properties_element.findtext('HasImmutabilityPolicy')
container.properties.has_legal_hold = properties_element.findtext('HasLegalHold')

# Add container to list
containers.append(container)
Expand Down Expand Up @@ -240,6 +244,7 @@ def _convert_xml_to_containers(response):
'ArchiveStatus': (None, 'rehydration_status', _to_str),
'DeletedTime': (None, 'deleted_time', parser.parse),
'RemainingRetentionDays': (None, 'remaining_retention_days', _to_int),
'Creation-Time': (None, 'creation_time', parser.parse),
}


Expand Down Expand Up @@ -281,6 +286,7 @@ def _convert_xml_to_blob_list(response):
<AccessTierInferred>true</AccessTierInferred>
<DeletedTime>datetime</DeletedTime>
<RemainingRetentionDays>int</RemainingRetentionDays>
<Creation-Time>date-time-value</Creation-Time>
</Properties>
<Metadata>
<Name>value</Name>
Expand Down
2 changes: 1 addition & 1 deletion azure-storage-blob/azure/storage/blob/_upload_chunking.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ def _is_chunk_empty(self, chunk_data):
# read until non-zero byte is encountered
# if reached the end without returning, then chunk_data is all 0's
for each_byte in chunk_data:
if each_byte != 0:
if each_byte != 0 and each_byte != b'\x00':
return False
return True

Expand Down
12 changes: 8 additions & 4 deletions azure-storage-blob/azure/storage/blob/appendblobservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ class AppendBlobService(BaseBlobService):
'''
MAX_BLOCK_SIZE = 4 * 1024 * 1024

def __init__(self, account_name=None, account_key=None, sas_token=None,
is_emulated=False, protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE,
custom_domain=None, request_session=None, connection_string=None, socket_timeout=None):
def __init__(self, account_name=None, account_key=None, sas_token=None, is_emulated=False,
protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE, custom_domain=None, request_session=None,
connection_string=None, socket_timeout=None, token_credential=None):
'''
:param str account_name:
The storage account name. This is used to authenticate requests
Expand Down Expand Up @@ -109,11 +109,15 @@ def __init__(self, account_name=None, account_key=None, sas_token=None,
:param int socket_timeout:
If specified, this will override the default socket timeout. The timeout specified is in seconds.
See DEFAULT_SOCKET_TIMEOUT in _constants.py for the default value.
:param token_credential:
A token credential used to authenticate HTTPS requests. The token value
should be updated before its expiration.
:type `~azure.storage.common.TokenCredential`
'''
self.blob_type = _BlobTypes.AppendBlob
super(AppendBlobService, self).__init__(
account_name, account_key, sas_token, is_emulated, protocol, endpoint_suffix,
custom_domain, request_session, connection_string, socket_timeout)
custom_domain, request_session, connection_string, socket_timeout, token_credential)

def create_blob(self, container_name, blob_name, content_settings=None,
metadata=None, lease_id=None,
Expand Down
13 changes: 10 additions & 3 deletions azure-storage-blob/azure/storage/blob/baseblobservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ class BaseBlobService(StorageClient):
MAX_SINGLE_GET_SIZE = 32 * 1024 * 1024
MAX_CHUNK_GET_SIZE = 4 * 1024 * 1024

def __init__(self, account_name=None, account_key=None, sas_token=None,
is_emulated=False, protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE,
custom_domain=None, request_session=None, connection_string=None, socket_timeout=None):
def __init__(self, account_name=None, account_key=None, sas_token=None, is_emulated=False,
protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE, custom_domain=None, request_session=None,
connection_string=None, socket_timeout=None, token_credential=None):
'''
:param str account_name:
The storage account name. This is used to authenticate requests
Expand Down Expand Up @@ -180,12 +180,17 @@ def __init__(self, account_name=None, account_key=None, sas_token=None,
:param int socket_timeout:
If specified, this will override the default socket timeout. The timeout specified is in seconds.
See DEFAULT_SOCKET_TIMEOUT in _constants.py for the default value.
:param token_credential:
A token credential used to authenticate HTTPS requests. The token value
should be updated before its expiration.
:type `~azure.storage.common.TokenCredential`
'''
service_params = _ServiceParameters.get_service_parameters(
'blob',
account_name=account_name,
account_key=account_key,
sas_token=sas_token,
token_credential=token_credential,
is_emulated=is_emulated,
protocol=protocol,
endpoint_suffix=endpoint_suffix,
Expand All @@ -204,6 +209,8 @@ def __init__(self, account_name=None, account_key=None, sas_token=None,
)
elif self.sas_token:
self.authentication = _StorageSASAuthentication(self.sas_token)
elif self.token_credential:
self.authentication = self.token_credential
else:
self.authentication = _StorageNoAuthentication()

Expand Down
12 changes: 8 additions & 4 deletions azure-storage-blob/azure/storage/blob/blockblobservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ class BlockBlobService(BaseBlobService):
MAX_BLOCK_SIZE = 4 * 1024 * 1024
MIN_LARGE_BLOCK_UPLOAD_THRESHOLD = 4 * 1024 * 1024 + 1

def __init__(self, account_name=None, account_key=None, sas_token=None,
is_emulated=False, protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE,
custom_domain=None, request_session=None, connection_string=None, socket_timeout=None):
def __init__(self, account_name=None, account_key=None, sas_token=None, is_emulated=False,
protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE, custom_domain=None,
request_session=None, connection_string=None, socket_timeout=None, token_credential=None):
'''
:param str account_name:
The storage account name. This is used to authenticate requests
Expand Down Expand Up @@ -134,11 +134,15 @@ def __init__(self, account_name=None, account_key=None, sas_token=None,
:param int socket_timeout:
If specified, this will override the default socket timeout. The timeout specified is in seconds.
See DEFAULT_SOCKET_TIMEOUT in _constants.py for the default value.
:param token_credential:
A token credential used to authenticate HTTPS requests. The token value
should be updated before its expiration.
:type `~azure.storage.common.TokenCredential`
'''
self.blob_type = _BlobTypes.BlockBlob
super(BlockBlobService, self).__init__(
account_name, account_key, sas_token, is_emulated, protocol, endpoint_suffix,
custom_domain, request_session, connection_string, socket_timeout)
custom_domain, request_session, connection_string, socket_timeout, token_credential)

def put_block(self, container_name, blob_name, block, block_id,
validate_content=False, lease_id=None, timeout=None):
Expand Down
9 changes: 9 additions & 0 deletions azure-storage-blob/azure/storage/blob/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@ class ContainerProperties(object):
conditionally.
:ivar LeaseProperties lease:
Stores all the lease information for the container.
:ivar bool has_immutability_policy:
Represents whether the container has an immutability policy.
:ivar bool has_legal_hold:
Represents whether the container has a legal hold.
'''

def __init__(self):
self.last_modified = None
self.etag = None
self.lease = LeaseProperties()
self.public_access = None
self.has_immutability_policy = None
self.has_legal_hold = None


class Blob(object):
Expand Down Expand Up @@ -128,6 +134,8 @@ class BlobProperties(object):
A datetime object representing the time at which the blob was deleted.
:ivar int remaining_retention_days:
The number of days that the blob will be retained before being permanently deleted by the service.
:ivar datetime creation_time:
Indicates when the blob was created, in UTC.
'''

def __init__(self):
Expand All @@ -147,6 +155,7 @@ def __init__(self):
self.blob_tier_inferred = False
self.deleted_time = None
self.remaining_retention_days = None
self.creation_time = None


class ContentSettings(object):
Expand Down
12 changes: 8 additions & 4 deletions azure-storage-blob/azure/storage/blob/pageblobservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ class PageBlobService(BaseBlobService):

MAX_PAGE_SIZE = 4 * 1024 * 1024

def __init__(self, account_name=None, account_key=None, sas_token=None,
is_emulated=False, protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE,
custom_domain=None, request_session=None, connection_string=None, socket_timeout=None):
def __init__(self, account_name=None, account_key=None, sas_token=None, is_emulated=False,
protocol=DEFAULT_PROTOCOL, endpoint_suffix=SERVICE_HOST_BASE, custom_domain=None,
request_session=None, connection_string=None, socket_timeout=None, token_credential=None):
'''
:param str account_name:
The storage account name. This is used to authenticate requests
Expand Down Expand Up @@ -119,11 +119,15 @@ def __init__(self, account_name=None, account_key=None, sas_token=None,
:param int socket_timeout:
If specified, this will override the default socket timeout. The timeout specified is in seconds.
See DEFAULT_SOCKET_TIMEOUT in _constants.py for the default value.
:param token_credential:
A token credential used to authenticate HTTPS requests. The token value
should be updated before its expiration.
:type `~azure.storage.common.TokenCredential`
'''
self.blob_type = _BlobTypes.PageBlob
super(PageBlobService, self).__init__(
account_name, account_key, sas_token, is_emulated, protocol, endpoint_suffix,
custom_domain, request_session, connection_string, socket_timeout)
custom_domain, request_session, connection_string, socket_timeout, token_credential)

def create_blob(
self, container_name, blob_name, content_length, content_settings=None,
Expand Down
Loading