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
2 changes: 1 addition & 1 deletion .codegen.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "engineHash": "04310d4", "specHash": "88cd5aa", "version": "4.14.0" }
{ "engineHash": "bcfc85f", "specHash": "88cd5aa", "version": "4.14.0" }
5 changes: 4 additions & 1 deletion box_sdk_gen/internal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,20 @@ def to_string(value: Any) -> Optional[str]:

class HashName(str, Enum):
SHA1 = 'sha1'
SHA512 = 'sha512'


class Hash:
def __init__(self, algorithm: HashName):
self.algorithm = algorithm
self.hash = hashlib.sha1()
self.hash = hashlib.new(algorithm.value)

def update_hash(self, data: Buffer):
self.hash.update(data)

def digest_hash(self, encoding):
if encoding == 'hex':
return self.hash.hexdigest()
return base64.b64encode(self.hash.digest()).decode("utf-8")


Expand Down
14 changes: 11 additions & 3 deletions docs/box_sdk_gen/chunked_uploads.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ This operation is performed by calling function `create_file_upload_session_for_
See the endpoint docs at
[API Reference](https://developer.box.com/reference/post-files-id-upload-sessions/).

_Currently we don't have an example for calling `create_file_upload_session_for_existing_file` in integration tests_
<!-- sample post_files_id_upload_sessions -->

```python
client.chunked_uploads.create_file_upload_session_for_existing_file(uploaded_file.id, file_size)
```

### Arguments

Expand Down Expand Up @@ -364,7 +368,11 @@ This operation is performed by calling function `create_file_upload_session_plan
See the endpoint docs at
[API Reference](https://developer.box.com/reference/post-files-upload-sessions-id-plan/).

_Currently we don't have an example for calling `create_file_upload_session_plan_by_url` in integration tests_
<!-- sample post_files_upload_sessions_id_plan -->

```python
client.chunked_uploads.create_file_upload_session_plan_by_url(plan_url, parts)
```

### Arguments

Expand Down Expand Up @@ -507,7 +515,7 @@ Starts the process of chunk uploading a big file. Should return a File object re
This operation is performed by calling function `upload_big_file`.

```python
client.chunked_uploads.upload_big_file(file_byte_stream, file_name, file_size, parent_folder_id)
client.chunked_uploads.upload_big_file(generate_byte_stream_from_buffer(file_buffer), file_name, file_size, parent_folder_id)
```

### Arguments
Expand Down
82 changes: 82 additions & 0 deletions test/box_sdk_gen/test/chunked_uploads.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

from box_sdk_gen.internal.utils import Iterator

from box_sdk_gen.schemas.upload_part_plan_hit import UploadPartPlanHit

from box_sdk_gen.internal.utils import generate_byte_stream_from_buffer

from box_sdk_gen.internal.utils import hex_to_base_64
Expand All @@ -30,6 +32,8 @@

from box_sdk_gen.internal.utils import ByteStream

from box_sdk_gen.internal.utils import delay_in_seconds

from test.box_sdk_gen.test.commons import get_default_client

from box_sdk_gen.schemas.file import File
Expand All @@ -38,10 +42,14 @@

from box_sdk_gen.schemas.upload_part import UploadPart

from box_sdk_gen.schemas.upload_part_plan import UploadPartPlan

from box_sdk_gen.schemas.upload_parts import UploadParts

from box_sdk_gen.schemas.uploaded_part import UploadedPart

from box_sdk_gen.schemas.upload_session_plan_response import UploadSessionPlanResponse

from box_sdk_gen.schemas.files import Files

from box_sdk_gen.client import BoxClient
Expand Down Expand Up @@ -253,6 +261,80 @@ def testChunkedManualProcessByUrl():
client.chunked_uploads.delete_file_upload_session_by_url(abort_url)


class _TestPartPlanAccumulator:
def __init__(self, last_index: int, parts: List[UploadPartPlan], file_size: int):
self.last_index = last_index
self.parts = parts
self.file_size = file_size


def _reducer_for_upload_session_plan(
acc: _TestPartPlanAccumulator, chunk: ByteStream
) -> _TestPartPlanAccumulator:
last_index: int = acc.last_index
parts: List[UploadPartPlan] = acc.parts
chunk_buffer: Buffer = read_byte_stream(chunk)
hash: Hash = Hash(algorithm=HashName.SHA512)
hash.update_hash(chunk_buffer)
sha_512: str = hash.digest_hash('hex')
chunk_size: int = buffer_length(chunk_buffer)
bytes_start: int = last_index + 1
bytes_end: int = last_index + chunk_size
part: UploadPartPlan = UploadPartPlan(
offset=bytes_start, size=chunk_size, sha_512=sha_512
)
return _TestPartPlanAccumulator(
last_index=bytes_end, parts=parts + [part], file_size=acc.file_size
)


def testUploadSessionPlan():
file_size: int = (20 * 1024) * 1024
file_name: str = get_uuid()
parent_folder_id: str = '0'
file_content_stream: ByteStream = generate_byte_stream(file_size)
file_buffer: Buffer = read_byte_stream(file_content_stream)
uploaded_file: File = client.chunked_uploads.upload_big_file(
generate_byte_stream_from_buffer(file_buffer),
file_name,
file_size,
parent_folder_id,
)
delay_in_seconds(5)
upload_session: UploadSession = (
client.chunked_uploads.create_file_upload_session_for_existing_file(
uploaded_file.id, file_size
)
)
upload_session_id: str = upload_session.id
plan_url: str = upload_session.session_endpoints.plan
part_size: int = upload_session.part_size
total_parts: int = upload_session.total_parts
chunks_iterator: Iterator = iterate_chunks(
generate_byte_stream_from_buffer(file_buffer), part_size, file_size
)
results: _TestPartPlanAccumulator = reduce_iterator(
chunks_iterator,
_reducer_for_upload_session_plan,
_TestPartPlanAccumulator(last_index=-1, parts=[], file_size=file_size),
)
parts: List[UploadPartPlan] = results.parts
plan: UploadSessionPlanResponse = (
client.chunked_uploads.create_file_upload_session_plan_by_url(plan_url, parts)
)
assert plan.upload_session_id == upload_session_id
assert len(plan.hits) == total_parts
assert len(plan.misses) == 0
first_part: UploadPartPlan = parts[0]
first_hit: UploadPartPlanHit = plan.hits[0]
assert first_hit.offset == first_part.offset
assert first_hit.size == first_part.size
assert first_hit.sha_512 == first_part.sha_512
assert not first_hit.part_id == ''
client.chunked_uploads.delete_file_upload_session_by_id(upload_session_id)
client.files.delete_file_by_id(uploaded_file.id)


def testChunkedUploadConvenienceMethod():
file_size: int = (20 * 1024) * 1024
file_byte_stream: ByteStream = generate_byte_stream(file_size)
Expand Down
Loading