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
11 changes: 8 additions & 3 deletions sdk/storage/azure-storage-file/HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@ To use a directory_url, the method `from_directory_url` must be used.
- `file_permission_key` parameter has been renamed to `permission_key`
- `set_share_access_policy` has required parameter `signed_identifiers`.
- NoRetry policy has been removed. Use keyword argument `retry_total=0` for no retries.
- Removed types that were accidentally exposed from two modules. Only `FileServiceClient`, `ShareClient`,
`DirectoryClient` and `FileClient` should be imported from azure.storage.file.aio
- Removed types that were accidentally exposed from two modules. Only `FileServiceClient`, `ShareClient`, `DirectoryClient` and `FileClient` should be imported from azure.storage.file.aio
- NoRetry policy has been removed. Use keyword argument `retry_total=0` for no retries.
- Some parameters have become keyword only, rather than positional. Some examples include:
- `loop`
- `max_concurrency`
- `validate_content`
- `timeout` etc.

- `start_range` and `end_range` params are now renamed to and behave like`offset` and `length` in
the following APIs:
- download_file
- upload_range
- upload_range_from_url
- clear_range
- get_ranges

**New features**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,12 @@ def _upload_chunk(self, chunk_offset, chunk_data):
class FileChunkUploader(_ChunkUploader): # pylint: disable=abstract-method

def _upload_chunk(self, chunk_offset, chunk_data):
chunk_end = chunk_offset + len(chunk_data) - 1
length = len(chunk_data)
chunk_end = chunk_offset + length - 1
response = self.service.upload_range(
chunk_data,
chunk_offset,
chunk_end,
length,
Comment thread
annatisch marked this conversation as resolved.
data_stream_total=self.total_size,
upload_stream_current=self.progress_total,
**self.request_options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,12 @@ async def _upload_chunk(self, chunk_offset, chunk_data):
class FileChunkUploader(_ChunkUploader): # pylint: disable=abstract-method

async def _upload_chunk(self, chunk_offset, chunk_data):
chunk_end = chunk_offset + len(chunk_data) - 1
length = len(chunk_data)
chunk_end = chunk_offset + length - 1
response = await self.service.upload_range(
chunk_data,
chunk_offset,
chunk_end,
length,
Comment thread
annatisch marked this conversation as resolved.
data_stream_total=self.total_size,
upload_stream_current=self.progress_total,
**self.request_options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,12 +469,14 @@ async def download_file(
raise ValueError("Encryption not supported.")
if length is not None and offset is None:
raise ValueError("Offset value must not be None if length is set.")

range_end = None
if length is not None:
range_end = offset + length - 1 # Service actually uses an end-range inclusive index
downloader = StorageStreamDownloader(
client=self._client.file,
config=self._config,
offset=offset,
length=length,
length=range_end,
validate_content=validate_content,
encryption_options=None,
cls=deserialize_file_stream,
Expand Down Expand Up @@ -635,25 +637,21 @@ async def set_file_metadata(self, metadata=None, **kwargs): # type: ignore
async def upload_range( # type: ignore
self,
data, # type: bytes
start_range, # type: int
end_range, # type: int
offset, # type: int
length, # type: int
**kwargs
):
# type: (...) -> Dict[str, Any]
"""Upload a range of bytes to a file.

:param bytes data:
The data to upload.
:param int start_range:
:param int offset:
Start of byte range to use for uploading a section of the file.
The range can be up to 4 MB in size.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will upload first 512 bytes of file.
:param int end_range:
End of byte range to use for uploading a section of the file.
:param int length:
Number of bytes to use for uploading a section of the file.
The range can be up to 4 MB in size.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will upload first 512 bytes of file.
:keyword bool validate_content:
If true, calculates an MD5 hash of the page content. The storage
service checks the hash of the content that has arrived
Expand All @@ -675,13 +673,12 @@ async def upload_range( # type: ignore
raise ValueError("Encryption not supported.")
if isinstance(data, six.text_type):
data = data.encode(encoding)

content_range = "bytes={0}-{1}".format(start_range, end_range)
content_length = end_range - start_range + 1
end_range = offset + length - 1 # Reformat to an inclusive range index
content_range = 'bytes={0}-{1}'.format(offset, end_range)
try:
return await self._client.file.upload_range( # type: ignore
range=content_range,
content_length=content_length,
content_length=length,
optionalbody=data,
timeout=timeout,
validate_content=validate_content,
Expand All @@ -693,25 +690,21 @@ async def upload_range( # type: ignore

@distributed_trace_async
async def upload_range_from_url(self, source_url, # type: str
range_start, # type: int
range_end, # type: int
source_range_start, # type: int
offset, # type: int
length, # type: int
source_offset, # type: int
**kwargs # type: Any
):
# type: (str, int, int, int, **Any) -> Dict[str, Any]
'''
Writes the bytes from one Azure File endpoint into the specified range of another Azure File endpoint.

:param int range_start:
:param int offset:
Start of byte range to use for updating a section of the file.
The range can be up to 4 MB in size.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will download first 512 bytes of file.
:param int range_end:
End of byte range to use for updating a section of the file.
:param int length:
Number of bytes to use for updating a section of the file.
The range can be up to 4 MB in size.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will download first 512 bytes of file.
:param str source_url:
A URL of up to 2 KB in length that specifies an Azure file or blob.
The value should be URL-encoded as it would appear in a request URI.
Expand All @@ -721,20 +714,18 @@ async def upload_range_from_url(self, source_url, # type: str
Examples:
https://myaccount.file.core.windows.net/myshare/mydir/myfile
https://otheraccount.file.core.windows.net/myshare/mydir/myfile?sastoken
:param int source_range_start:
Start of byte range to use for updating a section of the file.
The range can be up to 4 MB in size.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will download first 512 bytes of file.
:param int source_offset:
This indicates the start of the range of bytes(inclusive) that has to be taken from the copy source.
The service will read the same number of bytes as the destination range (length-offset).
:keyword int timeout:
The timeout parameter is expressed in seconds.
'''

options = self._upload_range_from_url_options(
source_url=source_url,
range_start=range_start,
range_end=range_end,
source_range_start=source_range_start,
offset=offset,
length=length,
source_offset=source_offset,
**kwargs
)
try:
Expand All @@ -745,21 +736,17 @@ async def upload_range_from_url(self, source_url, # type: str
@distributed_trace_async
async def get_ranges( # type: ignore
self,
start_range=None, # type: Optional[int]
end_range=None, # type: Optional[int]
offset=None, # type: Optional[int]
length=None, # type: Optional[int]
**kwargs
):
# type: (...) -> List[dict[str, int]]
"""Returns the list of valid ranges of a file.

:param int start_range:
:param int offset:
Specifies the start offset of bytes over which to get ranges.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will download first 512 bytes of file.
:param int end_range:
Specifies the end offset of bytes over which to get ranges.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will download first 512 bytes of file.
:param int length:
Number of bytes to use over which to get ranges.
:keyword int timeout:
The timeout parameter is expressed in seconds.
:returns: A list of valid ranges.
Expand All @@ -770,11 +757,12 @@ async def get_ranges( # type: ignore
raise ValueError("Unsupported method for encryption.")

content_range = None
if start_range is not None:
if end_range is not None:
content_range = "bytes={0}-{1}".format(start_range, end_range)
if offset is not None:
if length is not None:
length = offset + length - 1 # Reformat to an inclusive range index

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we reuse length here? can we make it offset_end = offset + length - 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one hasn't been addressed 😀

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @xiafu-msft - I'm merging these changes into the Stream PR now - will add this
FYI @rakshith91

content_range = "bytes={0}-{1}".format(offset, length)
else:
content_range = "bytes={0}-".format(start_range)
content_range = "bytes={0}-".format(offset)
try:
ranges = await self._client.file.get_range_list(
sharesnapshot=self.snapshot, timeout=timeout, range=content_range, **kwargs
Expand All @@ -786,24 +774,20 @@ async def get_ranges( # type: ignore
@distributed_trace_async
async def clear_range( # type: ignore
self,
start_range, # type: int
end_range, # type: int
offset, # type: int
length, # type: int
**kwargs
):
# type: (...) -> Dict[str, Any]
"""Clears the specified range and releases the space used in storage for
that range.

:param int start_range:
:param int offset:
Start of byte range to use for clearing a section of the file.
The range can be up to 4 MB in size.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will download first 512 bytes of file.
:param int end_range:
End of byte range to use for clearing a section of the file.
:param int length:
Number of bytes to use for clearing a section of the file.
The range can be up to 4 MB in size.
The start_range and end_range params are inclusive.
Ex: start_range=0, end_range=511 will download first 512 bytes of file.
:keyword int timeout:
The timeout parameter is expressed in seconds.
:returns: File-updated property dict (Etag and last modified).
Expand All @@ -813,11 +797,12 @@ async def clear_range( # type: ignore
if self.require_encryption or (self.key_encryption_key is not None):
raise ValueError("Unsupported method for encryption.")

if start_range is None or start_range % 512 != 0:
raise ValueError("start_range must be an integer that aligns with 512 file size")
if end_range is None or end_range % 512 != 511:
raise ValueError("end_range must be an integer that aligns with 512 file size")
content_range = "bytes={0}-{1}".format(start_range, end_range)
if offset is None or offset % 512 != 0:
raise ValueError("offset must be an integer that aligns with 512 bytes file size")
if length is None or length % 512 != 0:
raise ValueError("length must be an integer that aligns with 512 bytes file size")
end_range = length + offset - 1 # Reformat to an inclusive range index
content_range = "bytes={0}-{1}".format(offset, end_range)
try:
return await self._client.file.upload_range( # type: ignore
timeout=timeout,
Expand Down
Loading