Skip to content

Commit 4908192

Browse files
committed
Update Readme
Updated docstrings Prevent pre-allocation for download resources Improve doc strings and add arbitrary range request Parameterize the download directory for integration test Adds speedtest.net powered bandwidth check Adds download benchmark script Adds download progress UI Auto stash before rebase of "jh/speed-test" Refactor transport layer and add telemetry and logging WIP Dockerfile Update python version matrix for CI WIP add telemetry Dockerfile for CDN perf testing add missing dep in setup.py Missing comma :face-palm: Fix name of the segment python package Add additional missing packages Add missing comma Adjust status bar position Continued telemetry work
1 parent 07a28d0 commit 4908192

31 files changed

+651
-274
lines changed

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.formatting.provider": "black"
3+
}

Dockerfile

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
FROM python:3.8.6-slim-buster as deps
2+
# Set work directory
3+
WORKDIR /home/speedtest
4+
5+
# Copy files
6+
COPY Pipfile .
7+
COPY Pipfile.lock .
8+
9+
# Install pipenv
10+
RUN pip install pipenv
11+
12+
FROM deps as installer
13+
# Set work directory
14+
WORKDIR /home/speedtest
15+
16+
# Install deps
17+
RUN pipenv install --system --deploy --ignore-pipfile
18+
19+
# Copy over the other pieces
20+
COPY frameioclient frameioclient
21+
COPY setup.py .
22+
COPY README.md .
23+
24+
# Install the local frameioclient
25+
RUN pipenv install -e . --skip-lock
26+
27+
# Copy over scripts and tests
28+
COPY scripts scripts
29+
COPY tests tests
30+
31+
ENV SEGMENT_WRITE_KEY=
32+
33+
FROM installer as runtime
34+
ENTRYPOINT [ "pipenv", "run", "python", "scripts/benchmark/download.py" ]

Makefile

+13-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,16 @@ clean:
1717
find . -name "*.pyc" -exec rm -f {} \;
1818

1919
test:
20-
cd tests && pipenv run python integration.py
20+
cd tests && pipenv run python integration.py
21+
22+
package:
23+
pipenv run python3 setup.py sdist bdist_wheel
24+
25+
build-docker:
26+
docker build . -t benchmark
27+
28+
run-benchmark:
29+
docker run -it -e $1 benchmark
30+
31+
format:
32+
black frameioclient

examples/download_asset.py

-15
This file was deleted.

frameioclient/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
from .client import FrameioClient
1+
from .lib import *
2+
from .services import *
3+
from .client import FrameioClient

frameioclient/client.py

+19-74
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,25 @@
1-
import sys
2-
import requests
3-
from requests.adapters import HTTPAdapter
4-
from requests.packages.urllib3.util.retry import Retry
5-
61
from .lib import (
2+
Utils,
73
APIClient,
4+
AWSClient,
85
Telemetry,
96
ClientVersion,
10-
PaginatedResponse,
11-
Utils,
127
ClientVersion,
13-
FrameioDownloader,
14-
PresentationException
8+
FrameioDownloader
159
)
1610

1711
class FrameioClient(APIClient, object):
18-
def __init__(self, token, host='https://api.frame.io'):
12+
def __init__(self, token, host):
1913
super().__init__(token, host)
2014

21-
self.adapter = HTTPAdapter(max_retries=self.retry_strategy)
22-
self.session = requests.Session()
23-
self.session.mount("https://", self.adapter)
24-
25-
def _api_call(self, method, endpoint, payload={}, limit=None):
26-
url = '{}/v2{}'.format(self.host, endpoint)
27-
28-
r = self.session.request(
29-
method,
30-
url,
31-
json=payload,
32-
headers=self.headers,
33-
)
34-
35-
if r.ok:
36-
if r.headers.get('page-number'):
37-
if int(r.headers.get('total-pages')) > 1:
38-
return PaginatedResponse(
39-
results=r.json(),
40-
limit=limit,
41-
page_size=r.headers['per-page'],
42-
total_pages=r.headers['total-pages'],
43-
total=r.headers['total'],
44-
endpoint=endpoint,
45-
method=method,
46-
payload=payload,
47-
client=self
48-
)
49-
if isinstance(r.json(), list):
50-
return r.json()[:limit]
51-
return r.json()
52-
53-
if r.status_code == 422 and "presentation" in endpoint:
54-
raise PresentationException
55-
56-
return r.raise_for_status()
57-
58-
def get_specific_page(self, method, endpoint, payload, page):
59-
"""
60-
Gets a specific page for that endpoint, used by Pagination Class
61-
62-
:Args:
63-
method (string): 'get', 'post'
64-
endpoint (string): endpoint ('/accounts/<ACCOUNT_ID>/teams')
65-
payload (dict): Request payload
66-
page (int): What page to get
67-
"""
68-
if method == 'get':
69-
endpoint = '{}?page={}'.format(endpoint, page)
70-
return self._api_call(method, endpoint)
71-
72-
if method == 'post':
73-
payload['page'] = page
74-
return self._api_call(method, endpoint, payload=payload)
15+
@property
16+
def me(self):
17+
return self.users.get_me()
7518

19+
@property
20+
def telemetry(self):
21+
return Telemetry(self)
7622

77-
class FrameioClient(FrameioConnection):
7823
@property
7924
def _auth(self):
8025
return self.token
@@ -85,46 +30,46 @@ def _version(self):
8530

8631
@property
8732
def _download(self):
88-
return FrameioDownloader
33+
return FrameioDownloader(self)
8934

9035
@property
9136
def users(self):
92-
from .service import User
37+
from .services import User
9338
return User(self)
9439

9540
@property
9641
def assets(self):
97-
from .service import Asset
42+
from .services import Asset
9843
return Asset(self)
9944

10045
@property
10146
def comments(self):
102-
from .service import Comment
47+
from .services import Comment
10348
return Comment(self)
10449

10550
@property
10651
def logs(self):
107-
from .service import AuditLogs
52+
from .services import AuditLogs
10853
return AuditLogs(self)
10954

11055
@property
11156
def review_links(self):
112-
from .service import ReviewLink
57+
from .services import ReviewLink
11358
return ReviewLink(self)
11459

11560
@property
11661
def presentation_links(self):
117-
from .service import PresentationLink
62+
from .services import PresentationLink
11863
return PresentationLink(self)
11964

12065
@property
12166
def projects(self):
122-
from .service import Project
67+
from .services import Project
12368
return Project(self)
12469

12570
@property
12671
def teams(self):
127-
from .service import Team
72+
from .services import Team
12873
return Team(self)
12974

13075
@property

frameioclient/lib/__init__.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
from .download import FrameioDownloader
2-
from .upload import FrameioUploader
3-
from .utils import Utils, PaginatedResponse, KB, MB
41
from .exceptions import *
2+
from .logger import SDKLogger
3+
from .telemetry import Telemetry
54
from .version import ClientVersion
5+
from .upload import FrameioUploader
6+
from .download import FrameioDownloader
7+
from .transport import AWSClient, APIClient
8+
from .utils import Utils, PaginatedResponse, KB, MB

frameioclient/lib/bandwidth.py

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import speedtest
2+
3+
class NetworkBandwidth:
4+
# Test the network bandwidth any time we have a new IP address
5+
# Persist this information to a config.json file
6+
7+
def __init__(self):
8+
self.results = dict()
9+
10+
def load_stats(self):
11+
# Force an update on these stats before starting download/upload
12+
pass
13+
14+
def persist_stats(self):
15+
pass
16+
17+
def run(self):
18+
self.results = self.speed_test()
19+
20+
@staticmethod
21+
def speedtest():
22+
"""
23+
Run a speedtest using Speedtest.net in order to get a 'control' for \
24+
bandwidth optimization.
25+
26+
Example::
27+
NetworkBandwidth.speedtest()
28+
"""
29+
30+
st = speedtest.Speedtest()
31+
download_speed = round(st.download(threads=10) * (1.192 * 10 ** -7), 2)
32+
upload_speed = round(st.upload(threads=10) * (1.192 * 10 ** -7), 2)
33+
servernames = []
34+
server_names = st.get_servers(servernames)
35+
ping = st.results.ping
36+
37+
return {
38+
"ping": ping,
39+
"download_speed": download_speed,
40+
"upload_speed": upload_speed,
41+
}
42+
43+
def __repr__(self):
44+
self.results
45+
46+
class DiskBandwidth:
47+
# Test the disk speed and write to a config.json file for re-use
48+
# Worth re-checking the disk every time a new one is detected (base route)
49+
50+
def __init__(self, volume):
51+
self.volume = volume
52+
self.results = dict()
53+
54+
def __repr__(self):
55+
self.results
56+

0 commit comments

Comments
 (0)