Skip to content

Commit

Permalink
chore: Build java on Travis and add README (box/box-codegen#573)
Browse files Browse the repository at this point in the history
  • Loading branch information
box-sdk-build committed Sep 27, 2024
1 parent d1dd404 commit 05deaa9
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .codegen.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "engineHash": "5a78cc2", "specHash": "6b64d06", "version": "1.5.1" }
{ "engineHash": "1a0f05b", "specHash": "6b64d06", "version": "1.5.1" }
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
blank_issues_enabled: false
contact_links:
- name: SDK documentation
url: https://github.com/box/box-python-sdk-generated/tree/main/docs
url: https://github.com/box/box-python-sdk-gen/tree/main/docs
about: Before creating an issue, I have checked that the SDK documentation doesn't solve my issue.
- name: API documentation
url: https://developer.box.com/docs
Expand All @@ -10,5 +10,5 @@ contact_links:
url: https://community.box.com/t5/Platform-and-Development-Forum/bd-p/DeveloperForum
about: Before creating an issue, I have searched the Box Developer Forums and my issue isn't already reported there.
- name: Issues in this repo
url: https://github.com/box/box-python-sdk-generated/search?type=Issues
url: https://github.com/box/box-python-sdk-gen/search?type=Issues
about: Before creating an issue, I have searched Issues in this repo and my issue isn't already reported.
4 changes: 2 additions & 2 deletions .github/workflows/autoupdate-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.DISPATCH_ACCESS_TOKEN }}
token: $

- name: Set up Git
run: |
Expand All @@ -24,7 +24,7 @@ jobs:

- name: Auto update pull requests
run: |
PR_LIST=$(curl -s -H "Authorization: Bearer ${{ secrets.DISPATCH_ACCESS_TOKEN }}" "https://api.github.com/repos/$GITHUB_REPOSITORY/pulls?state=open" | jq -r '.[] | .head.ref')
PR_LIST=$(curl -s -H "Authorization: Bearer $" "https://api.github.com/repos/$GITHUB_REPOSITORY/pulls?state=open" | jq -r '.[] | .head.ref')
for pr_branch in $PR_LIST; do
git checkout "$pr_branch"
if git merge origin/main; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/spell-check-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
with:
ref: refs/heads/main
repository: box/box-sdk-spellchecker
token: ${{ secrets.DISPATCH_ACCESS_TOKEN }}
token: $
path: spellchecker
- name: Execute spellchecker
uses: ./spellchecker
23 changes: 22 additions & 1 deletion box_sdk_gen/internal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
import datetime
import hashlib
import os
import shutil
import uuid
import time
from enum import Enum
from io import SEEK_CUR, SEEK_END, SEEK_SET, BufferedIOBase, BytesIO
from typing import Any, Callable, Dict, Iterable, Optional, TypeVar
from typing import Any, Callable, Dict, Iterable, Optional, TypeVar, BinaryIO

try:
import jwt
Expand All @@ -21,6 +22,7 @@
from .null_value import null

ByteStream = BufferedIOBase
OutputStream = BinaryIO
Buffer = bytes


Expand Down Expand Up @@ -139,6 +141,25 @@ def read_byte_stream(byte_stream: ByteStream) -> Buffer:
return Buffer(byte_stream.read())


def write_input_stream_to_output_stream(
input_stream: ByteStream, output_stream: OutputStream
):
shutil.copyfileobj(input_stream, output_stream)


def get_file_output_stream(file_path: str) -> OutputStream:
return open(file_path, 'wb')


def close_file_output_stream(file_output_stream: OutputStream):
file_output_stream.close()


def read_buffer_from_file(path: str) -> bytes:
with open(path, 'rb') as file:
return file.read()


def prepare_params(map: Dict[str, Optional[str]]) -> Dict[str, str]:
return {k: v for k, v in map.items() if v is not None}

Expand Down
63 changes: 63 additions & 0 deletions box_sdk_gen/managers/downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

from box_sdk_gen.networking.fetch import fetch

from box_sdk_gen.internal.utils import write_input_stream_to_output_stream

from box_sdk_gen.internal.utils import OutputStream


class DownloadsManager:
def __init__(
Expand Down Expand Up @@ -109,3 +113,62 @@ def download_file(
)
)
return response.content

def download_file_to_output_stream(
self,
file_id: str,
output_stream: OutputStream,
*,
version: Optional[str] = None,
access_token: Optional[str] = None,
range: Optional[str] = None,
boxapi: Optional[str] = None,
extra_headers: Optional[Dict[str, Optional[str]]] = None
) -> None:
"""
:param file_id: The unique identifier that represents a file.
The ID for any file can be determined
by visiting a file in the web application
and copying the ID from the URL. For example,
for the URL `https://*.app.box.com/files/123`
the `file_id` is `123`.
Example: "12345"
:type file_id: str
:param output_stream: Download file to a given output stream
:type output_stream: OutputStream
:param version: The file version to download, defaults to None
:type version: Optional[str], optional
:param access_token: An optional access token that can be used to pre-authenticate this request, which means that a download link can be shared with a browser or a third party service without them needing to know how to handle the authentication.
When using this parameter, please make sure that the access token is sufficiently scoped down to only allow read access to that file and no other files or folders., defaults to None
:type access_token: Optional[str], optional
:param range: The byte range of the content to download.
The format `bytes={start_byte}-{end_byte}` can be used to specify
what section of the file to download., defaults to None
:type range: Optional[str], optional
:param boxapi: The URL, and optional password, for the shared link of this item.
This header can be used to access items that have not been
explicitly shared with a user.
Use the format `shared_link=[link]` or if a password is required then
use `shared_link=[link]&shared_link_password=[password]`.
This header can be used on the file or folder shared, as well as on any files
or folders nested within the item., defaults to None
:type boxapi: Optional[str], optional
:param extra_headers: Extra headers that will be included in the HTTP request., defaults to None
:type extra_headers: Optional[Dict[str, Optional[str]]], optional
"""
if extra_headers is None:
extra_headers = {}
download_stream: ByteStream = self.download_file(
file_id,
version=version,
access_token=access_token,
range=range,
boxapi=boxapi,
extra_headers=extra_headers,
)
write_input_stream_to_output_stream(download_stream, output_stream)
97 changes: 67 additions & 30 deletions docs/downloads.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,81 @@
# Downloads
# DownloadsManager

Downloads module is used to download files from Box.
- [Download file](#download-file)
- [Download file](#download-file)

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
## Download file

- [Download a File](#download-a-file)
Returns the contents of a file in binary format.

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
This operation is performed by calling function `download_file`.

## Download a File
See the endpoint docs at
[API Reference](https://developer.box.com/reference/get-files-id-content/).

To get the entire contents of the file as stream of bytes, call `download_file` method.
This method returns a `ByteStream` object, which is an implementation of `io.BufferedIOBase`, what allows
reading downloaded file as a stream. Thanks to that, the file parts will be downloaded just when needed and
it won;t be necessary to store the entire file content in-memory.

To get the full content of the file in `bytes` format just call `read()` method on returned object.
<!-- sample get_files_id_content -->

```python
from io import BufferedIOBase

file_content_stream: BufferedIOBase = client.downloads.download_file(
file_id="123456789"
)
print("File content: ", file_content_stream.read())
client.downloads.download_file(uploaded_file.id)
```

To save downloaded file to your local disk you can use e.g. `shutil.copyfileobj()` method:
### Arguments

<!-- sample get_files_id_content -->
- file_id `str`
- The unique identifier that represents a file. The ID for any file can be determined by visiting a file in the web application and copying the ID from the URL. For example, for the URL `https://*.app.box.com/files/123` the `file_id` is `123`. Example: "12345"
- version `Optional[str]`
- The file version to download
- access_token `Optional[str]`
- An optional access token that can be used to pre-authenticate this request, which means that a download link can be shared with a browser or a third party service without them needing to know how to handle the authentication. When using this parameter, please make sure that the access token is sufficiently scoped down to only allow read access to that file and no other files or folders.
- range `Optional[str]`
- The byte range of the content to download. The format `bytes={start_byte}-{end_byte}` can be used to specify what section of the file to download.
- boxapi `Optional[str]`
- The URL, and optional password, for the shared link of this item. This header can be used to access items that have not been explicitly shared with a user. Use the format `shared_link=[link]` or if a password is required then use `shared_link=[link]&shared_link_password=[password]`. This header can be used on the file or folder shared, as well as on any files or folders nested within the item.
- extra_headers `Optional[Dict[str, Optional[str]]]`
- Extra headers that will be included in the HTTP request.

### Returns

This function returns a value of type `ByteStream`.

Returns the requested file if the client has the **follow
redirects** setting enabled to automatically
follow HTTP `3xx` responses as redirects. If not, the request
will return `302` instead.
For details, see
the [download file guide](g://downloads/file#download-url).If the file is not ready to be downloaded yet `Retry-After` header will
be returned indicating the time in seconds after which the file will
be available for the client to download.

This response can occur when the file was uploaded immediately before the
download request.

## Download file

Download file to a given output stream

This operation is performed by calling function `download_file_to_output_stream`.

```python
import shutil
from io import BufferedIOBase

file_content_stream: BufferedIOBase = client.downloads.download_file(
file_id="123456789"
)
with open("file.pdf", "wb") as f:
shutil.copyfileobj(file_content_stream, f)
print('File was successfully downloaded as "file.pdf"')
client.downloads.download_file_to_output_stream(uploaded_file.id, file_output_stream)
```

### Arguments

- file_id `str`
- The unique identifier that represents a file. The ID for any file can be determined by visiting a file in the web application and copying the ID from the URL. For example, for the URL `https://*.app.box.com/files/123` the `file_id` is `123`. Example: "12345"
- output_stream `OutputStream`
- Download file to a given output stream
- version `Optional[str]`
- The file version to download
- access_token `Optional[str]`
- An optional access token that can be used to pre-authenticate this request, which means that a download link can be shared with a browser or a third party service without them needing to know how to handle the authentication. When using this parameter, please make sure that the access token is sufficiently scoped down to only allow read access to that file and no other files or folders.
- range `Optional[str]`
- The byte range of the content to download. The format `bytes={start_byte}-{end_byte}` can be used to specify what section of the file to download.
- boxapi `Optional[str]`
- The URL, and optional password, for the shared link of this item. This header can be used to access items that have not been explicitly shared with a user. Use the format `shared_link=[link]` or if a password is required then use `shared_link=[link]&shared_link_password=[password]`. This header can be used on the file or folder shared, as well as on any files or folders nested within the item.
- extra_headers `Optional[Dict[str, Optional[str]]]`
- Extra headers that will be included in the HTTP request.

### Returns

This function returns a value of type `None`.
29 changes: 29 additions & 0 deletions test/downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

from box_sdk_gen.schemas.file_full import FileFull

from box_sdk_gen.internal.utils import OutputStream

from box_sdk_gen.internal.utils import get_uuid

from box_sdk_gen.internal.utils import generate_byte_buffer
Expand All @@ -22,6 +24,12 @@

from box_sdk_gen.internal.utils import read_byte_stream

from box_sdk_gen.internal.utils import get_file_output_stream

from box_sdk_gen.internal.utils import close_file_output_stream

from box_sdk_gen.internal.utils import read_buffer_from_file

from test.commons import get_default_client

from box_sdk_gen.networking.fetch import FetchOptions
Expand All @@ -47,3 +55,24 @@ def test_download_file():
)
assert buffer_equals(read_byte_stream(downloaded_file_content), file_buffer)
client.files.delete_file_by_id(uploaded_file.id)


def test_download_file_to_output_stream():
new_file_name: str = get_uuid()
file_buffer: Buffer = generate_byte_buffer(1024 * 1024)
file_content_stream: ByteStream = generate_byte_stream_from_buffer(file_buffer)
uploaded_files: Files = client.uploads.upload_file(
UploadFileAttributes(
name=new_file_name, parent=UploadFileAttributesParentField(id='0')
),
file_content_stream,
)
uploaded_file: FileFull = uploaded_files.entries[0]
file_output_stream: OutputStream = get_file_output_stream(new_file_name)
client.downloads.download_file_to_output_stream(
uploaded_file.id, file_output_stream
)
close_file_output_stream(file_output_stream)
downloaded_file_content: Buffer = read_buffer_from_file(new_file_name)
assert buffer_equals(downloaded_file_content, file_buffer)
client.files.delete_file_by_id(uploaded_file.id)

0 comments on commit 05deaa9

Please sign in to comment.