Source code for acdcli.api.client

import os
import time
import json
import requests
import logging

from . import oauth
from .backoff_req import BackOffRequest
from .common import *
from .account import AccountMixin
from .content import ContentMixin
from .metadata import MetadataMixin
from .trash import TrashMixin

logger = logging.getLogger(__name__)

EXP_TIME_KEY = 'exp_time'

AMZ_ENDPOINT_REQ_URL = 'https://drive.amazonaws.com/drive/v1/account/endpoint'
ENDPOINT_VAL_TIME = 259200
"""number of seconds for endpoint validity (3 days)"""


[docs]class ACDClient(AccountMixin, ContentMixin, MetadataMixin, TrashMixin): """Provides a client to the Amazon Cloud Drive RESTful interface.""" _ENDPOINT_DATA_FILE = 'endpoint_data'
[docs] def __init__(self, path=''): """Initializes OAuth and endpoints.""" self.cache_path = path logger.info('Initializing ACD with path "%s".' % path) self.handler = oauth.create_handler(path) self._endpoint_data = {} self._load_endpoints() self.BOReq = BackOffRequest(self.handler)
@property def _endpoint_data_path(self): return os.path.join(self.cache_path, ACDClient._ENDPOINT_DATA_FILE) def _load_endpoints(self): """Tries to load endpoints from file and calls :meth:`_get_endpoints` on failure or if they are outdated.""" if not os.path.isfile(self._endpoint_data_path): self._endpoint_data = self._get_endpoints() else: with open(self._endpoint_data_path) as ep: self._endpoint_data = json.load(ep) if time.time() > self._endpoint_data[EXP_TIME_KEY]: logger.info('Endpoint data expired.') self._endpoint_data = self._get_endpoints() def _get_endpoints(self) -> dict: """Retrieves Amazon endpoints and saves them on success. :raises: ValueError if requests returned invalid JSON :raises: KeyError if endpoint data does not include expected keys""" r = requests.get(AMZ_ENDPOINT_REQ_URL, auth=self.handler) if r.status_code not in OK_CODES: logger.critical('Error getting endpoint data. Response: %s' % r.text) raise Exception try: e = r.json() except ValueError as e: logger.critical('Invalid JSON: "%s"' % r.text) raise e e[EXP_TIME_KEY] = time.time() + ENDPOINT_VAL_TIME self._endpoint_data = e try: self.metadata_url self.content_url except KeyError as e: logger.critical('Received invalid endpoint data.') raise e self._save_endpoint_data() return e def _save_endpoint_data(self): f = open(self._endpoint_data_path, 'w') json.dump(self._endpoint_data, f, indent=4, sort_keys=True) f.flush() os.fsync(f.fileno()) f.close() @property def metadata_url(self): return self._endpoint_data['metadataUrl'] @property def content_url(self): return self._endpoint_data['contentUrl']