Source

cloudster / api / storages / adapters / dropbox / adapter.py

Full commit
import webbrowser

from api.shelf.registry.metadata import ClientRegistryMetadata
from api.storages.adapters import skeleton
from api.storages.adapters.dropbox import events
from api.storages.adapters import elements

from api.storages.clients.dropbox import client, session

ACCESS_TYPE_FOLDER = 'app_folder'  # should be 'dropbox' or 'app_folder' as configured for your app
ACCESS_TYPE_FULL = 'dropbox'

class DropboxClient(skeleton.StorageAdapter):

    @staticmethod
    def registry_metadata():

        metadata = ClientRegistryMetadata('dropbox', DropboxAccountData)

        return metadata

    def __init__(self, account_data):

        skeleton.StorageAdapter.__init__(self)
        self._account_data = account_data

    def move(self):
        pass

    def obtain_access_token(self, session_handler):

        request_token =  session_handler.obtain_request_token()

        auth_page = session_handler.build_authorize_url(request_token)

        print 'You should redirect user to ' + auth_page

        webbrowser.open_new_tab(auth_page)

        raw_input()

        return session_handler.obtain_access_token(request_token)

    def __create_session_handler(self):
        return session.DropboxSession(self._account_data.appKey(), self._account_data.appSecret(), self._account_data.accessType())

    def grant_client_access(self, session_handler=None):

        if session_handler is None:
            handler = self.__create_session_handler()
        else:
            handler = session_handler

        access_token = self.obtain_access_token(handler)

        self._account_data.assignAccessToken(access_token)

        return access_token

    #Mirar el metodo session.obtain_request_token(self) para mas informacion de como hacerlo en el futuro
    def connect(self):

        sess = self.__create_session_handler()

        if not self._account_data.isAccessGranted():
            self.grant_client_access(sess)
        else:
            sess.set_token(self._account_data.oauthToken(), self._account_data.oauthTokenSecret())

        self._client = client.DropboxClient(sess)


    #TODO We need to check if we actually have an active session opened

    def list(self, path):

        #This is not a recursive call, only returns those elements that belong to the specified path
        remote_info = self._client.metadata(path)

        content = []

        for remote_element in remote_info['contents']:
            if remote_element['is_dir']:
                content.append(self._toStorageFolder(remote_element))
            else:
                content.append(self._toStorageFile(remote_element))

        return content


    def _toStorageFile(self,source):
        return elements.StorageFile(source['path'],source['modified'],source['rev'])

    def _toStorageFolder(self, source):
        return elements.StorageFolder(source['path'],source['modified'],source['rev'])

    def about(self):return self._client.account_info()

    def write(self, target_full_path, source_file, overwrite=True):
        self._client.put_file(target_full_path, source_file, overwrite)

    def read(self, full_remote_path, target_file_path=None):

        remote_file = self._client.get_file(full_remote_path)

        if target_file_path is not None:

            f = open(target_file_path,'wb')

            file_size = 0

            for header_name, header_value in [(header_content.split(":")[0],header_content.split(":")[1]) for header_content in remote_file.msg.headers]:
                if header_name.lower() == 'content-length':
                    file_size = int(header_value)
                    break


            print "Downloading: %s Bytes: %s" % (target_file_path, file_size)

            file_size_dl = 0
            block_sz = 1024*1024

            while True:
                buffer = remote_file.read(block_sz)

                if not buffer:
                    break

                file_size_dl += len(buffer)
                f.write(buffer)

                status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
                status += chr(8)*(len(status)+1)

                print status

            f.close()
        else:
            return remote_file


    def remove(self, full_path):
        self._client.file_delete(full_path)

    def events(self, history_pointer = None):

        iterator = events.DropboxEventsIterator(self._client, history_pointer)
        translator = events.DropboxEventTranslator()

        return events.DropboxEventsBrowser(iterator, translator)


class DropboxAccountData(skeleton.StorageAccountData):

    def __init__(self, account_data):

        parsed_data = skeleton.StorageAccountData.parse(self, account_data)

        skeleton.StorageAccountData.__init__(self, parsed_data)

        self._appKey = parsed_data["appKey"]
        self._appSecret = parsed_data["appSecret"]
        self._accessType = parsed_data["accessType"]

        if "OAuthToken" in parsed_data:
            self._oauth_token = parsed_data["OAuthToken"]
        else:
            self._oauth_token=None

        if "OAuthTokenSecret" in parsed_data:
            self._oauth_token_secret = parsed_data["OAuthTokenSecret"]
        else:
            self._oauth_token_secret = None

    def assignAccessToken(self, access_token):
        self._oauth_token = access_token.key
        self._oauth_token_secret = access_token.secret

    @skeleton.account_field('dropbox','appKey', 'Application key', skeleton.AccountFieldDescriptor.FIELD_TYPE_STRING)
    def appKey(self):
        return self._appKey

    @skeleton.account_field('dropbox','appSecret', 'Application secret', skeleton.AccountFieldDescriptor.FIELD_TYPE_STRING)
    def appSecret(self):
        return self._appSecret

    @skeleton.account_field('dropbox','accessType', 'Access type', skeleton.AccountFieldDescriptor.FIELD_TYPE_STRING)    
    def accessType(self):
        return self._accessType

    def oauthToken(self):
        return self._oauth_token

    def oauthTokenSecret(self):
        return self._oauth_token_secret

    def isAccessGranted(self):
        return self._oauth_token_secret is not None and self._oauth_token is not None

    @staticmethod
    def get_configuration_fields():
        return skeleton.StorageAccountData._list_account_field('dropbox')

    def jsonize(self):
        return dict({'appKey': self._appKey, 'appSecret': self._appSecret, 'accessType': self._accessType, 'OAuthToken' : self._oauth_token, 'OAuthTokenSecret': self._oauth_token_secret, 'unique_id': self.unique_id()})