Skip to content

Commit 078ae2c

Browse files
authored
Merge pull request #60 from Frameio/jh/watermark-id-downloads
[DEVREL-484] Add support for Watermark ID downloads
2 parents f751dc6 + e0585a4 commit 078ae2c

10 files changed

Lines changed: 140 additions & 18 deletions

File tree

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.8.1
2+
current_version = 0.8.2
33
commit = True
44
tag = True
55

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
# Order is important; the last matching pattern takes the most
88
# precedence. When someone opens a pull request that only
99
# modifies Python files.
10-
*.py jmeggesto@frame.io billy@frame.io zach@frame.io jay@frame.io
10+
*.py @devrel

examples/download_asset.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import os
2+
3+
from frameioclient import FrameioClient
4+
5+
def download_file(asset_id):
6+
token = os.getenv("FRAMEIO_TOKEN")
7+
client = FrameioClient(token)
8+
asset_info = client.get_asset(asset_id)
9+
client.download(asset_info, "downloads")
10+
11+
if __name__ == "__main__":
12+
download_file("6cc9a45f-64a7-456e-a95f-98687220bf6e")

frameioclient/client.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,7 @@ def copy_asset(self, destination_folder_id, **kwargs):
351351
return self._api_call('post', endpoint, kwargs)
352352

353353
def bulk_copy_assets(self, destination_folder_id, asset_list=[], copy_comments=False):
354-
"""
355-
Bulk copy assets
354+
"""Bulk copy assets
356355
357356
:Args:
358357
destination_folder_id (string): The id of the folder you want to copy into.

frameioclient/download.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,51 @@
1-
import requests
2-
import math
31
import os
2+
import math
3+
import requests
4+
5+
from .exceptions import DownloadException
46

57
class FrameioDownloader(object):
68
def __init__(self, asset, download_folder):
79
self.asset = asset
810
self.download_folder = download_folder
911

12+
def get_download_key(self):
13+
try:
14+
url = self.asset['original']
15+
except KeyError as e:
16+
if self.asset['is_session_watermarked'] == True:
17+
resolution_list = list()
18+
try:
19+
for resolution_key, download_url in sorted(self.asset['downloads'].items()):
20+
resolution = resolution_key.split("_")[1] # Grab the item at index 1 (resolution)
21+
try:
22+
resolution = int(resolution)
23+
except ValueError:
24+
continue
25+
26+
if download_url is not None:
27+
resolution_list.append(download_url)
28+
29+
# Grab the highest resolution (first item) now
30+
url = resolution_list[0]
31+
except KeyError:
32+
raise DownloadException
33+
else:
34+
raise DownloadException
35+
36+
return url
37+
1038
def download(self):
1139
original_filename = self.asset['name']
1240
final_destination = os.path.join(self.download_folder, original_filename)
13-
14-
url = self.asset['original']
15-
r = requests.get(url)
16-
17-
open(final_destination, 'wb').write(r.content)
41+
42+
print("Final destiation: {}".format(final_destination))
43+
44+
if os.path.isfile(final_destination):
45+
return final_destination
46+
else:
47+
url = self.get_download_key()
48+
r = requests.get(url)
49+
open(final_destination, 'wb').write(r.content)
50+
return final_destination
1851

frameioclient/exceptions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,14 @@ def __init__(
1010
):
1111
self.message = message
1212
super().__init__(self.message)
13+
14+
class DownloadException(Exception):
15+
"""Exception raised when trying to download a file where there is no available
16+
download URL.
17+
"""
18+
def __init__(
19+
self,
20+
message="This file is unavailable for download due to security and permission settings."
21+
):
22+
self.message = message
23+
super().__init__(self.message)

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from setuptools.command.install import install
66

7-
version='0.8.1'
7+
version='0.8.2'
88

99
with open("README.md", "r") as f:
1010
long_description = f.read()
@@ -47,9 +47,11 @@ def run(self):
4747
'Programming Language :: Python :: 2',
4848
'Programming Language :: Python :: 2.7',
4949
'Programming Language :: Python :: 3',
50+
'Programming Language :: Python :: 3.5',
5051
'Programming Language :: Python :: 3.6',
5152
'Programming Language :: Python :: 3.7',
5253
'Programming Language :: Python :: 3.8',
54+
'Programming Language :: Python :: 3.9',
5355
],
5456
description='Client library for the Frame.io API',
5557
long_description=long_description,

tests/conftest.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1+
import os
12
import pytest
23
from frameioclient import FrameioClient
34

4-
@pytest.fixture
5-
def frameioclient(token):
6-
return FrameioClient("aaaabbbbccccddddeeee")
5+
token = os.getenv('FRAME_IO_TOKEN')
6+
7+
# @pytest.fixture
8+
# def frameioclient(token):
9+
# return FrameioClient("aaaabbbbccccddddeeee")
10+
11+
12+
@pytest.fixture()
13+
def setup_client():
14+
client = FrameioClient(token)
15+
return client

tests/test_frameioclient.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import pytest
21
from frameioclient import FrameioClient
32

4-
def test_FrameioClient(frameioclient):
5-
assert type(frameioclient) == FrameioClient
3+
def test_FrameioClient(setup_client):
4+
client = setup_client
5+
assert type(client) == FrameioClient

tests/test_frameiodownloader.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import pytest
2+
from frameioclient.download import FrameioDownloader
3+
from frameioclient.exceptions import DownloadException
4+
5+
6+
regular_asset = {
7+
"is_hls_required": False,
8+
"is_session_watermarked": False,
9+
"downloads": {
10+
"h264_720": "some-720-url",
11+
"h264_1080_best": "some-1080-url"
12+
},
13+
"h264_720": "some-720-url",
14+
"h264_1080_best": "some-1080-url",
15+
"original": "some-original-url",
16+
"hls_manifest": "some-hls-url"
17+
}
18+
19+
watermarked_asset_download_allowed = {
20+
"is_hls_required": True,
21+
"is_session_watermarked": True,
22+
"downloads": {
23+
"h264_720": "download-stream-service-url",
24+
"h264_1080_best": "download-stream-service-url"
25+
},
26+
"hls_manifest": "hls-url"
27+
}
28+
29+
watermarked_asset_no_download = {
30+
"is_hls_required": True,
31+
"is_session_watermarked": True,
32+
"hls_manifest": "hls-url"
33+
}
34+
35+
no_download_allowed = {
36+
"is_hls_required": True,
37+
"is_session_watermarked": False,
38+
"hls_manifest": "hls-url"
39+
}
40+
41+
def test_get_download_key_returns_original():
42+
url = FrameioDownloader(regular_asset, './').get_download_key()
43+
assert url == regular_asset['original']
44+
45+
def test_get_download_key_returns_watermarked_download():
46+
url = FrameioDownloader(watermarked_asset_download_allowed, './').get_download_key()
47+
assert url == watermarked_asset_download_allowed['downloads']['h264_1080_best']
48+
49+
def test_get_download_key_fails_gracefully_on_watermarked_asset():
50+
with pytest.raises(DownloadException):
51+
FrameioDownloader(watermarked_asset_no_download, './').get_download_key()
52+
53+
def test_get_download_key_fails_gracefully_when_downloads_disallowed():
54+
with pytest.raises(DownloadException):
55+
FrameioDownloader(no_download_allowed, './').get_download_key()
56+

0 commit comments

Comments
 (0)