Skip to content

Commit 77e4728

Browse files
authored
Feature/14 download method (#17)
* adds download method to ToshiFile class; * toshiFile download tests work; * adds download usage; * update changelog;
1 parent faa9161 commit 77e4728

File tree

5 files changed

+121
-3
lines changed

5 files changed

+121
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## Unreleased
8-
## [0.6.2] - 2022-05-10
8+
## [1.0.0] - 2022-05-13
99
### Added
10+
- ToshiFile.download_file function
1011
- doco for env variables
12+
### Changes
13+
- update usage.md with download_file instruction usage
14+
- File.file_size from Int to BigInt
1115

1216
## [0.6.1] - 2022-05-05
1317
### Changes

docs/usage.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,27 @@ Example response
5555
'meta': {'mykey': 'myvalue', 'mykey2': 'myothervalue'},
5656
'file_url': 'https://s3.amazonaws.com/toshi-files/NZSHM22_InversionSolution-QXV0b21hdGlvblRhc2s6MTAwMTA4_nrml.zip'
5757
}
58-
```
58+
```
59+
60+
To use ToshiClient.download_file in a project
61+
62+
```
63+
from nshm_toshi_client import ToshiFile, API_URL, API_KEY, S3_URL
64+
headers={"x-api-key":API_KEY}
65+
api = ToshiFile(API_URL, None, None, headers=headers)
66+
67+
example_file_path = 'usr/tmp'
68+
api.download_file('{example_id}', example_file_path)
69+
```
70+
71+
If successful, prints:
72+
73+
```
74+
saving to usr/tmp/{example_id}
75+
````
76+
77+
If failure, prints:
78+
79+
```
80+
Download failed: status code {status_code} (eg. 404)
81+
```

nshm_toshi_client/toshi_file.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import base64
33
import json
44
import logging
5+
import os
56
from hashlib import md5
67

78
import requests
@@ -123,7 +124,41 @@ def get_file(self, id, with_file_url: bool = False):
123124
if with_file_url:
124125
qry = qry.replace("#FILE_URL", "file_url")
125126

126-
print(qry)
127+
# print(qry)
127128
input_variables = dict(id=id)
128129
executed = self.run_query(qry, input_variables)
129130
return executed['node']
131+
132+
def download_file(self, id, target_dir, target_name=None):
133+
qry = '''
134+
query file ($id:ID!) {
135+
node(id: $id) {
136+
__typename
137+
... on Node {
138+
id
139+
}
140+
... on FileInterface {
141+
file_name
142+
file_url
143+
}
144+
}
145+
}'''
146+
147+
# print(qry)
148+
input_variables = dict(id=id)
149+
executed = self.run_query(qry, input_variables)
150+
url = executed['node']['file_url']
151+
filename = target_name if target_name else executed['node']['file_name']
152+
153+
if not os.path.exists(target_dir):
154+
os.mkdir(target_dir)
155+
156+
file_path = os.path.join(target_dir, filename)
157+
158+
r = requests.get(url, stream=True)
159+
if r.ok:
160+
with open(file_path, 'wb') as f:
161+
f.write(r.content)
162+
return file_path
163+
else:
164+
raise (RuntimeError(f'Error downloading file {filename}: Status code {r.status_code}'))

tests/test_data/sample.zip

743 Bytes
Binary file not shown.

tests/test_toshi_file.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from io import BytesIO
77
from unittest import mock
88
from pathlib import Path
9+
import os
10+
import shutil
911

1012
import unittest
1113

@@ -117,3 +119,57 @@ def test_get_file_dowload_url_ok(self):
117119
file_detail["file_url"]
118120
== "https://s3.amazonaws.com/toshi-files/NZSHM22_InversionSolution-QXV0b21hdGlvblRhc2s6MTAwMTA4_nrml.zip"
119121
)
122+
123+
def mocked_requests_get(*args, **kwargs):
124+
with open(Path(__file__).parent / "test_data" / "sample.zip", "rb") as f:
125+
mock_zip = BytesIO(f.read())
126+
mock_zip.seek(0)
127+
128+
class MockResponse:
129+
def __init__(self, json_data, status_code, ok):
130+
self.json = json_data
131+
self.status_code = status_code
132+
self.ok = ok
133+
self.content = mock_zip.read()
134+
135+
if (
136+
args[0]
137+
== 'https://s3.amazonaws.com/toshi-files/NZSHM22_InversionSolution-QXV0b21hdGlvblRhc2s6MTAwMTA4_nrml.zip'
138+
):
139+
return MockResponse({"key1": "value1"}, 200, True)
140+
else:
141+
return MockResponse(None, 404, False)
142+
143+
@mock.patch('nshm_toshi_client.toshi_file.requests.get', side_effect=mocked_requests_get)
144+
def test_download_file_ok(self, mock_get):
145+
with requests_mock.Mocker() as m:
146+
147+
query1_server_answer = '''{
148+
"data": {
149+
"node": {
150+
"__typename": "InversionSolutionNrml",
151+
"id": "SW52ZXJzaW9uU29sdXRpb25Ocm1sOjEwMDM0Mw==",
152+
"file_name": "NZSHM22_InversionSolution-QXV0b21hdGlvblRhc2s6MTAwMTA4_nrml.zip",
153+
"file_url": "https://s3.amazonaws.com/toshi-files/NZSHM22_InversionSolution-QXV0b21hdGlvblRhc2s6MTAwMTA4_nrml.zip"
154+
}
155+
}
156+
}'''
157+
158+
m.post(API_URL, text=query1_server_answer)
159+
headers = {"x-api-key": "THE_API_KEY"}
160+
myapi = ToshiFile(API_URL, S3_URL, None, with_schema_validation=False, headers=headers)
161+
162+
dir_path = os.path.abspath(os.getcwd())
163+
file_path = os.path.join(dir_path, "tmp")
164+
165+
myapi.download_file(
166+
"https://s3.amazonaws.com/toshi-files/NZSHM22_InversionSolution-QXV0b21hdGlvblRhc2s6MTAwMTA4_nrml.zip",
167+
file_path,
168+
)
169+
170+
assert os.path.exists(f"{file_path}/NZSHM22_InversionSolution-QXV0b21hdGlvblRhc2s6MTAwMTA4_nrml.zip")
171+
172+
def tearDown(self) -> None:
173+
tmp_dir = os.path.join(os.path.abspath(os.getcwd()), "tmp")
174+
if os.path.exists(tmp_dir):
175+
shutil.rmtree(tmp_dir)

0 commit comments

Comments
 (0)