From e13b8f70e427476deeb7f12f3b5e43aa734b40a7 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 7 Jun 2021 19:57:05 -0700 Subject: [PATCH 1/4] Fix merge issues --- frameioclient/__init__.py | 6 ------ frameioclient/client.py | 5 +---- frameioclient/lib/transport.py | 2 +- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/frameioclient/__init__.py b/frameioclient/__init__.py index d4de075e..04bcc1e2 100644 --- a/frameioclient/__init__.py +++ b/frameioclient/__init__.py @@ -1,9 +1,3 @@ from .lib import * from .services import * from .client import FrameioClient -<<<<<<< - -======= -from .service import * -from .lib import * ->>>>>>> \ No newline at end of file diff --git a/frameioclient/client.py b/frameioclient/client.py index f6e42017..dd9a107a 100644 --- a/frameioclient/client.py +++ b/frameioclient/client.py @@ -1,7 +1,5 @@ from .lib import ( - Utils, APIClient, - AWSClient, Telemetry, ClientVersion, ClientVersion, @@ -9,7 +7,7 @@ ) class FrameioClient(APIClient, object): - def __init__(self, token, host): + def __init__(self, token, host='https://api.frame.io'): super().__init__(token, host) @property @@ -41,7 +39,6 @@ def users(self): def assets(self): from .services import Asset return Asset(self) - total=3, @property def comments(self): diff --git a/frameioclient/lib/transport.py b/frameioclient/lib/transport.py index f17178d3..3442d9dc 100644 --- a/frameioclient/lib/transport.py +++ b/frameioclient/lib/transport.py @@ -46,7 +46,7 @@ def _get_session(self, auth=True): class APIClient(HTTPClient, object): - def __init__(self, token, host='https://api.frame.io'): + def __init__(self, token, host): super().__init__() self.host = host self.token = token From 75deee8c9d32061f2c63e4fd0c4feaebc4a1e27e Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Mon, 7 Jun 2021 20:16:12 -0700 Subject: [PATCH 2/4] Fix issue with (auth=True) in _get_session() --- frameioclient/lib/download.py | 4 ++-- frameioclient/lib/transport.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frameioclient/lib/download.py b/frameioclient/lib/download.py index b7220a16..71977a71 100644 --- a/frameioclient/lib/download.py +++ b/frameioclient/lib/download.py @@ -42,7 +42,7 @@ def __init__(self, asset, download_folder, prefix, multi_part=False, concurrency self.in_progress = 0 self.filename = Utils.normalize_filename(asset["name"]) self.request_logs = list() - self.session = AWSClient()._get_session(auth=None) + self.session = AWSClient()._get_session() self._evaluate_asset() @@ -135,7 +135,7 @@ def single_part_download(self, url): print("Beginning download -- {} -- {}".format(self.asset["name"], Utils.format_bytes(self.file_size, type="size"))) # Downloading - r = requests.get(url) + r = self.session.get(url) open(self.destination, "wb").write(r.content) download_time = time.time() - start_time diff --git a/frameioclient/lib/transport.py b/frameioclient/lib/transport.py index 3442d9dc..4e1929f9 100644 --- a/frameioclient/lib/transport.py +++ b/frameioclient/lib/transport.py @@ -34,7 +34,7 @@ def __init__(self): def _initialize_thread(self): self.thread_local = threading.local() - def _get_session(self, auth=True): + def _get_session(self): if not hasattr(self.thread_local, "session"): http = requests.Session() adapter = HTTPAdapter(max_retries=self.retry_strategy) @@ -51,7 +51,7 @@ def __init__(self, token, host): self.host = host self.token = token self._initialize_thread() - self.session = self._get_session(auth=token) + self.session = self._get_session() self.auth_header = { 'Authorization': 'Bearer {}'.format(self.token), } From 5d18beb5bc6eca00cec19295776e989c5411d30a Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Tue, 8 Jun 2021 01:28:46 -0700 Subject: [PATCH 3/4] Abstract API call formatter --- frameioclient/lib/transport.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/frameioclient/lib/transport.py b/frameioclient/lib/transport.py index 4e1929f9..8ec433f8 100644 --- a/frameioclient/lib/transport.py +++ b/frameioclient/lib/transport.py @@ -55,15 +55,14 @@ def __init__(self, token, host): self.auth_header = { 'Authorization': 'Bearer {}'.format(self.token), } + + def _format_api_call(self, endpoint): + return '{}/v2{}'.format(self.host, endpoint) def _api_call(self, method, endpoint, payload={}, limit=None): - url = '{}/v2{}'.format(self.host, endpoint) - - headers = {**self.shared_headers, **self.auth_header} - r = self.session.request( method, - url, + url=self._format_api_call(endpoint), headers=self.auth_header, json=payload ) @@ -97,14 +96,14 @@ def get_specific_page(self, method, endpoint, payload, page): Gets a specific page for that endpoint, used by Pagination Class :Args: - method (string): 'get', 'post' - endpoint (string): endpoint ('/accounts//teams') - payload (dict): Request payload - page (int): What page to get + method (string): 'get', 'post' + endpoint (string): endpoint ('/accounts//teams') + payload (dict): Request payload + page (int): What page to get """ if method == 'get': endpoint = '{}?page={}'.format(endpoint, page) - return self._api_call(method, endpoint) + return self._api_call(method, endpoint) if method == 'post': payload['page'] = page From b6ecdb847d9cb52454c289dece435c8ba59251b9 Mon Sep 17 00:00:00 2001 From: Jeff Hodges Date: Wed, 9 Jun 2021 11:06:11 -0700 Subject: [PATCH 4/4] Remove duplicate code --- frameioclient/lib/transport.py | 2 - frameioclient/service/assets.py | 13 +- frameioclient/services/__init__.py | 7 - frameioclient/services/assets.py | 233 ----------------------------- frameioclient/services/comments.py | 89 ----------- frameioclient/services/links.py | 121 --------------- frameioclient/services/logs.py | 17 --- frameioclient/services/projects.py | 51 ------- frameioclient/services/teams.py | 74 --------- frameioclient/services/users.py | 8 - 10 files changed, 11 insertions(+), 604 deletions(-) delete mode 100644 frameioclient/services/__init__.py delete mode 100644 frameioclient/services/assets.py delete mode 100644 frameioclient/services/comments.py delete mode 100644 frameioclient/services/links.py delete mode 100644 frameioclient/services/logs.py delete mode 100644 frameioclient/services/projects.py delete mode 100644 frameioclient/services/teams.py delete mode 100644 frameioclient/services/users.py diff --git a/frameioclient/lib/transport.py b/frameioclient/lib/transport.py index 8ec433f8..6fa672a8 100644 --- a/frameioclient/lib/transport.py +++ b/frameioclient/lib/transport.py @@ -1,9 +1,7 @@ -import os import logging import enlighten import requests import threading -import concurrent.futures from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry diff --git a/frameioclient/service/assets.py b/frameioclient/service/assets.py index b64d56d7..eb52cf43 100644 --- a/frameioclient/service/assets.py +++ b/frameioclient/service/assets.py @@ -229,7 +229,7 @@ def upload(self, destination_id, filepath, asset=None): return asset - def download(self, asset, download_folder, prefix=None, multi_part=False, concurrency=5): + def download(self, asset, download_folder, prefix=None, multi_part=False, concurrency=5, stats=False): """ Download an asset. The method will exit once the file is downloaded. @@ -241,5 +241,14 @@ def download(self, asset, download_folder, prefix=None, multi_part=False, concur client.assets.download(asset, "~./Downloads") """ - downloader = FrameioDownloader(asset, download_folder, prefix, multi_part, concurrency) + downloader = FrameioDownloader( + asset, + download_folder, + prefix, + multi_part, + concurrency, + user_id=self.client.me['id'], + stats=stats + ) + return downloader.download_handler() \ No newline at end of file diff --git a/frameioclient/services/__init__.py b/frameioclient/services/__init__.py deleted file mode 100644 index 0cd634d5..00000000 --- a/frameioclient/services/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .teams import Team -from .users import User -from .assets import Asset -from .logs import AuditLogs -from .comments import Comment -from .projects import Project -from .links import ReviewLink, PresentationLink \ No newline at end of file diff --git a/frameioclient/services/assets.py b/frameioclient/services/assets.py deleted file mode 100644 index 5c8fa82c..00000000 --- a/frameioclient/services/assets.py +++ /dev/null @@ -1,233 +0,0 @@ -import os -import mimetypes - -from .projects import Project - -from ..lib.service import Service -from ..lib import FrameioUploader, FrameioDownloader - -class Asset(Service): - def get(self, asset_id): - """ - Get an asset by id. - - :Args: - asset_id (string): The asset id. - """ - endpoint = '/assets/{}'.format(asset_id) - return self.client._api_call('get', endpoint) - - def get_children(self, asset_id, **kwargs): - """ - Get a folder. - - :Args: - asset_id (string): The asset id. - """ - endpoint = '/assets/{}/children'.format(asset_id) - return self.client._api_call('get', endpoint, kwargs) - - def create(self, parent_asset_id, **kwargs): - """ - Create an asset. - - :Args: - parent_asset_id (string): The parent asset id. - :Kwargs: - (optional) kwargs: additional request parameters. - - Example:: - - client.assets.create( - parent_asset_id="123abc", - name="ExampleFile.mp4", - type="file", - filetype="video/mp4", - filesize=123456 - ) - """ - endpoint = '/assets/{}/children'.format(parent_asset_id) - return self.client._api_call('post', endpoint, payload=kwargs) - - def from_url(self, parent_asset_id, name, url): - """ - Create an asset from a URL. - - :Args: - parent_asset_id (string): The parent asset id. - name (string): The filename. - url (string): The remote URL. - - Example:: - - client.assets.from_url( - parent_asset_id="123abc", - name="ExampleFile.mp4", - type="file", - url="https://" - ) - """ - - payload = { - "name": name, - "type": "file", - "source": { - "url": url - } - } - - endpoint = '/assets/{}/children'.format(parent_asset_id) - return self.client._api_call('post', endpoint, payload=payload) - - def update(self, asset_id, **kwargs): - """ - Updates an asset - - :Args: - asset_id (string): the asset's id - :Kwargs: - the fields to update - - Example:: - client.assets.update("adeffee123342", name="updated_filename.mp4") - """ - endpoint = '/assets/{}'.format(asset_id) - return self.client._api_call('put', endpoint, kwargs) - - def copy(self, destination_folder_id, **kwargs): - """ - Copy an asset - - :Args: - destination_folder_id (string): The id of the folder you want to copy into. - :Kwargs: - id (string): The id of the asset you want to copy. - - Example:: - client.assets.copy("adeffee123342", id="7ee008c5-49a2-f8b5-997d-8b64de153c30") - """ - endpoint = '/assets/{}/copy'.format(destination_folder_id) - return self.client._api_call('post', endpoint, kwargs) - - def bulk_copy(self, destination_folder_id, asset_list=[], copy_comments=False): - """Bulk copy assets - - :Args: - destination_folder_id (string): The id of the folder you want to copy into. - :Kwargs: - asset_list (list): A list of the asset IDs you want to copy. - copy_comments (boolean): Whether or not to copy comments: True or False. - - Example:: - client.assets.bulk_copy("adeffee123342", asset_list=["7ee008c5-49a2-f8b5-997d-8b64de153c30", \ - "7ee008c5-49a2-f8b5-997d-8b64de153c30"], copy_comments=True) - """ - - payload = {"batch": []} - new_list = list() - - if copy_comments: - payload['copy_comments'] = "all" - - for asset in asset_list: - payload['batch'].append({"id": asset}) - - endpoint = '/batch/assets/{}/copy'.format(destination_folder_id) - return self.client._api_call('post', endpoint, payload) - - def delete(self, asset_id): - """ - Delete an asset - - :Args: - asset_id (string): the asset's id - """ - endpoint = '/assets/{}'.format(asset_id) - return self.client._api_call('delete', endpoint) - - def _upload(self, asset, file): - """ - Upload an asset. The method will exit once the file is uploaded. - - :Args: - asset (object): The asset object. - file (file): The file to upload. - - Example:: - client.upload(asset, open('example.mp4')) - """ - - uploader = FrameioUploader(asset, file) - uploader.upload() - - # def upload_folder(self, destination_id, folderpath): - # try: - # if os.path.isdir(folderpath): - # # Good it's a directory, we can keep going - - # except OSError: - # if not os.path.exists(folderpath): - # sys.exit("Folder doesn't exist, exiting...") - - def build_asset_info(self, filepath): - full_path = os.path.abspath(filepath) - - file_info = { - "filepath": full_path, - "filename": os.path.basename(full_path), - "filesize": os.path.getsize(full_path), - "mimetype": mimetypes.guess_type(full_path)[0] - } - - return file_info - - def upload(self, destination_id, filepath): - # Check if destination is a project or folder - # If it's a project, well then we look up its root asset ID, otherwise we use the folder id provided - # Then we start our upload - - try: - # First try to grab it as a folder - folder_id = self.get(destination_id)['id'] - except Exception as e: - # Then try to grab it as a project - folder_id = Project(self.client).get_project(destination_id)['root_asset_id'] - finally: - file_info = self.build_asset_info(filepath) - try: - asset = self.create(folder_id, - type="file", - name=file_info['filename'], - filetype=file_info['mimetype'], - filesize=file_info['filesize'] - ) - - with open(file_info['filepath'], "rb") as fp: - self._upload(asset, fp) - - except Exception as e: - print(e) - - def download(self, asset, download_folder, prefix=None, multi_part=False, concurrency=5, stats=False): - """ - Download an asset. The method will exit once the file is downloaded. - - :Args: - asset (object): The asset object. - download_folder (path): The location to download the file to. - - Example:: - - client.download(asset, "~./Downloads") - """ - downloader = FrameioDownloader( - asset, - download_folder, - prefix, - multi_part, - concurrency, - user_id=self.client.me['id'], - stats=stats - ) - - return downloader.download_handler() \ No newline at end of file diff --git a/frameioclient/services/comments.py b/frameioclient/services/comments.py deleted file mode 100644 index a3fde975..00000000 --- a/frameioclient/services/comments.py +++ /dev/null @@ -1,89 +0,0 @@ -from ..lib.service import Service - -class Comment(Service): - def create(self, asset_id, **kwargs): - """ - Create a comment. - - :Args: - asset_id (string): The asset id. - :Kwargs: - (optional) kwargs: additional request parameters. - - Example:: - - client.comments.create( - asset_id="123abc", - text="Hello world" - ) - """ - endpoint = '/assets/{}/comments'.format(asset_id) - return self.client._api_call('post', endpoint, payload=kwargs) - - def get(self, comment_id, **kwargs): - """ - Get a comment. - - :Args: - comment_id (string): The comment id. - """ - endpoint = '/comments/{}'.format(comment_id) - return self.client._api_call('get', endpoint, **kwargs) - - def list(self, asset_id, **kwargs): - """ - Get an asset's comments. - - :Args: - asset_id (string): The asset id. - """ - endpoint = '/assets/{}/comments'.format(asset_id) - return self.client._api_call('get', endpoint, **kwargs) - - def update(self, comment_id, **kwargs): - """ - Update a comment. - - :Args: - comment_id (string): The comment id. - :Kwargs: - (optional) kwargs: additional request parameters. - - Example:: - - client.comments.update( - comment_id="123abc", - text="Hello world" - ) - """ - endpoint = '/comments/{}'.format(comment_id) - return self.client._api_call('post', endpoint, payload=kwargs) - - def delete(self, comment_id): - """ - Delete a comment. - - :Args: - comment_id (string): The comment id. - """ - endpoint = '/comments/{}'.format(comment_id) - return self.client._api_call('delete', endpoint) - - def reply(self, comment_id, **kwargs): - """ - Reply to an existing comment. - - :Args: - comment_id (string): The comment id. - :Kwargs: - (optional) kwargs: additional request parameters. - - Example:: - - client.comments.reply( - comment_id="123abc", - text="Hello world" - ) - """ - endpoint = '/comments/{}/replies'.format(comment_id) - return self.client._api_call('post', endpoint, payload=kwargs) diff --git a/frameioclient/services/links.py b/frameioclient/services/links.py deleted file mode 100644 index b617a36d..00000000 --- a/frameioclient/services/links.py +++ /dev/null @@ -1,121 +0,0 @@ -from ..lib.service import Service - -class ReviewLink(Service): - def create(self, project_id, **kwargs): - """ - Create a review link. - - :Args: - project_id (string): The project id. - :Kwargs: - kwargs: additional request parameters. - - Example:: - - client.review_links.create( - project_id="123", - name="My Review Link", - password="abc123" - ) - """ - endpoint = '/projects/{}/review_links'.format(project_id) - return self.client._api_call('post', endpoint, payload=kwargs) - - def list(self, project_id): - """ - Get the review links of a project - - :Args: - asset_id (string): The asset id. - """ - endpoint = '/projects/{}/review_links'.format(project_id) - return self.client._api_call('get', endpoint) - - def get(self, link_id, **kwargs): - """ - Get a single review link - - :Args: - link_id (string): The review link id. - """ - endpoint = '/review_links/{}'.format(link_id) - return self.client._api_call('get', endpoint, payload=kwargs) - - def get_assets(self, link_id): - """ - Get items from a single review link. - - :Args: - link_id (string): The review link id. - - Example:: - - client.review_links.get_assets( - link_id="123" - ) - """ - endpoint = '/review_links/{}/items'.format(link_id) - return self.client._api_call('get', endpoint) - - def update_assets(self, link_id, **kwargs): - """ - Add or update assets for a review link. - - :Args: - link_id (string): The review link id. - :Kwargs: - kwargs: additional request parameters. - - Example:: - - client.review_links.update_assets( - link_id="123", - asset_ids=["abc","def"] - ) - """ - endpoint = '/review_links/{}/assets'.format(link_id) - return self.client._api_call('post', endpoint, payload=kwargs) - - def update_settings(self, link_id, **kwargs): - """ - Updates review link settings. - - :Args: - link_id (string): The review link id. - :Kwargs: - kwargs: additional request parameters. - - Example:: - - client.review_links.update_settings( - link_id, - expires_at="2020-04-08T12:00:00+00:00", - is_active=False, - name="Review Link 123", - password="my_fun_password", - ) - """ - endpoint = '/review_links/{}'.format(link_id) - return self.client._api_call('put', endpoint, payload=kwargs) - - -class PresentationLink(Service): - def create(self, asset_id, **kwargs): - """ - Create a presentation link. - - :Args: - asset_id (string): The asset id. - :Kwargs: - kwargs: additional request parameters. - - Example:: - - client.presentation_links.create( - asset_id="9cee7966-4066-b326-7db1-f9e6f5e929e4", - title="My fresh presentation", - password="abc123" - ) - """ - endpoint = '/assets/{}/presentations'.format(asset_id) - return self.client._api_call('post', endpoint, payload=kwargs) diff --git a/frameioclient/services/logs.py b/frameioclient/services/logs.py deleted file mode 100644 index 3dba9af9..00000000 --- a/frameioclient/services/logs.py +++ /dev/null @@ -1,17 +0,0 @@ -from ..lib.service import Service - -class AuditLogs(Service): - def list(self, account_id): - """ - Get audit logs for the currently authenticated account. - - :Args: - - Example:: - - client.logs.list( - account_id="6bdcb4d9-9a2e-a765-4548-ae6b27a6c024" - ) - """ - endpoint = '/accounts/{}/audit_logs'.format(account_id) - return self.client._api_call('get', endpoint) diff --git a/frameioclient/services/projects.py b/frameioclient/services/projects.py deleted file mode 100644 index 960ca245..00000000 --- a/frameioclient/services/projects.py +++ /dev/null @@ -1,51 +0,0 @@ -from ..lib.service import Service - -class Project(Service): - def create(self, team_id, **kwargs): - """ - Create a project. - - :Args: - team_id (string): The team id. - :Kwargs: - (optional) kwargs: additional request parameters. - - Example:: - - client.projects.create_project( - team_id="123", - name="My Awesome Project", - ) - """ - endpoint = '/teams/{}/projects'.format(team_id) - return self.client._api_call('post', endpoint, payload=kwargs) - - def get_project(self, project_id): - """ - Get an individual project - - :Args: - project_id (string): the project's id - """ - endpoint = '/projects/{}'.format(project_id) - return self.client._api_call('get', endpoint) - - def get_collaborators(self, project_id, **kwargs): - """ - Get collaborators for a project - - :Args: - project_id (string): the project's id - """ - endpoint = "/projects/{}/collaborators?include=project_role".format(project_id) - return self.client._api_call('get', endpoint, kwargs) - - def get_pending_collaborators(self, project_id, **kwargs): - """ - Get pending collaborators for a project - - :Args: - project_id (string): the project's id - """ - endpoint = "/projects/{}/pending_collaborators".format(project_id) - return self.client._api_call('get', endpoint, kwargs) diff --git a/frameioclient/services/teams.py b/frameioclient/services/teams.py deleted file mode 100644 index 7030aae4..00000000 --- a/frameioclient/services/teams.py +++ /dev/null @@ -1,74 +0,0 @@ -import warnings -from ..lib.service import Service - -class Team(Service): - def create(self, account_id, **kwargs): - """ - Create a Team - - :Args: - account_id (string): The account id you want to create this Team under. - :Kwargs: - (optional) kwargs: additional request parameters. - - Example:: - - client.teams.create( - account_id="6bdcb4d9-4548-4548-4548-27a6c024ae6b", - name="My Awesome Project", - ) - """ - warnings.warn('Note: Your token must support team.create scopes') - endpoint = '/accounts/{}/teams'.format(account_id) - return self.client._api_call('post', endpoint, payload=kwargs) - - def list(self, account_id, **kwargs): - """ - Get teams owned by the specified account. - (To return all teams, use list_all()) - - :Args: - account_id (string): The account id. - """ - endpoint = '/accounts/{}/teams'.format(account_id) - return self.client._api_call('get', endpoint, kwargs) - - def list_all(self, **kwargs): - """ - Get all teams for the authenticated user. - - :Args: - account_id (string): The account id. - """ - endpoint = '/teams' - return self.client._api_call('get', endpoint, kwargs) - - def get(self, team_id): - """ - Get team by id - - :Args: - team_id (string): the Team's id - """ - endpoint = '/teams/{}'.format(team_id) - return self.client._api_call('get', endpoint) - - def get_members(self, team_id): - """ - Get the member list for a given Team. - - :Args: - team_id (string): The Team id. - """ - endpoint = '/teams/{}/members'.format(team_id) - return self.client._api_call('get', endpoint) - - def list_projects(self, team_id, **kwargs): - """ - Get projects owned by the Team. - - :Args: - team_id (string): The Team id. - """ - endpoint = '/teams/{}/projects'.format(team_id) - return self.client._api_call('get', endpoint, kwargs) diff --git a/frameioclient/services/users.py b/frameioclient/services/users.py deleted file mode 100644 index 61c0fb26..00000000 --- a/frameioclient/services/users.py +++ /dev/null @@ -1,8 +0,0 @@ -from ..lib.service import Service - -class User(Service): - def get_me(self): - """ - Get the current user. - """ - return self.client._api_call('get', '/me') \ No newline at end of file