Source

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

Full commit
Guillermo Szelig… cf1fe10 

Guillermo Szelig… daf20da 
Guillermo Szelig… 00abda6 
Guillermo Szelig… e79fb15 
Guillermo Szelig… d74d6b5 
Guillermo Szelig… 64b0fae 
Guillermo Szelig… f0edac1 
Guillermo Szelig… 64b0fae 



Guillermo Szelig… 00abda6 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… cfd7b98 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… cfd7b98 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… cfd7b98 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 82edb12 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 



Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… d74d6b5 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… d74d6b5 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… d74d6b5 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… d74d6b5 
Guillermo Szelig… cf1fe10 



Guillermo Szelig… d74d6b5 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… d74d6b5 

Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 




Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 

Guillermo Szelig… cf1fe10 

Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 18b6082 
Guillermo Szelig… cf1fe10 



Guillermo Szelig… 18b6082 

Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 6250b35 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… e79fb15 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… e79fb15 
Guillermo Szelig… cf1fe10 





















Guillermo Szelig… e79fb15 
Guillermo Szelig… 81adde9 
Guillermo Szelig… 00abda6 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 00abda6 
Guillermo Szelig… cf1fe10 
Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 


Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 



Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 



Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 


Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 


Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 


Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 


Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… f0edac1 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 


Guillermo Szelig… 81adde9 
Guillermo Szelig… cf1fe10 

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()})