1. Guillermo Szeliga
  2. cloudster

Commits

Guillermo Szeliga  committed 00abda6 Draft

- Accounts management: ask accounts descriptor for their configuration fields

  • Participants
  • Parent commits 6af9684
  • Branches default

Comments (0)

Files changed (6)

File api/patterns/annotations.py

View file
+__author__ = 'guillermo'
+
+#http://stackoverflow.com/questions/5707589/calling-functions-by-array-index-in-python/5707605#5707605
+#http://stackoverflow.com/questions/5910703/howto-get-all-methods-of-a-python-class-with-given-decorator
+
+#sample: account_field=annotations.create()
+def create():
+    registry = {}
+    def register(func):
+        registry[func.__name__] = func
+        return func  # normally a decorator returns a wrapped function,
+                     # but here we return func unmodified, after registering it
+    register.all = registry
+    return register
+
+
+def makeRegisteringDecorator(foreignDecorator):
+    """
+        Returns a copy of foreignDecorator, which is identical in every
+        way(*), except also appends a .decorator property to the callable it
+        spits out.
+    """
+    def newDecorator(func):
+        # Call to newDecorator(method)
+        # Exactly like old decorator, but output keeps track of what decorated it
+        R = foreignDecorator(func) # apply foreignDecorator, like call to foreignDecorator(method) would have done
+        R.decorator = newDecorator # keep track of decorator
+        #R.original = func         # might as well keep track of everything!
+        return R
+
+    newDecorator.__name__ = foreignDecorator.__name__
+    newDecorator.__doc__ = foreignDecorator.__doc__
+    # (*)We can be somewhat "hygienic", but newDecorator still isn't signature-preserving, i.e. you will not be able to get a runtime list of parameters. For that, you need hackish libraries...but in this case, the only argument is func, so it's not a big issue
+
+    return newDecorator
+
+#sample: list(methodsWithDecorator(xxx,decorator))
+def methodsWithDecorator(cls, decorator):
+    """
+        Returns all methods in CLS with DECORATOR as the
+        outermost decorator.
+
+        DECORATOR must be a "registering decorator"; one
+        can make any decorator "registering" via the
+        makeRegisteringDecorator function.
+    """
+    for maybeDecorated in cls.__dict__.values():
+        if hasattr(maybeDecorated, 'decorator'):
+            if maybeDecorated.decorator == decorator:
+                print(maybeDecorated)
+                yield maybeDecorated

File api/shelf/configuration/accounts.py

View file
         self.__client_class = client_class
         self.__account_type_class = self.__client_class.registry_metadata().account_type_class()
 
-    def get_descriptor(self):
-        return self.__account_type_class.get_descriptor()
+    def get_configuration_descriptor(self):
+        return self.__account_type_class.get_configuration_fields()
 
     def create(self, account_config_values):
         print 'Instantiates a new account data object'

File api/shelf/console/shell.py

View file
 		operation_parts = operation.rsplit(" ")
 
 		if operation_parts[0] == 'create':
-			descriptor = account_manager.get_descriptor()
+			descriptor = account_manager.get_configuration_descriptor()
+
+			print 'descriptor: ' + descriptor
 
 			#1- Asks for all values
 			values = {}

File api/storages/adapters/box/adapter.py

View file
 
 from api.storages.adapters.box import events
 from api.storages.clients.box import session, client
-from api.storages.adapters.skeleton import StorageAdapter
-from api.storages.adapters.skeleton import StorageAccountData
+from api.storages.adapters import skeleton
 from api.shelf.registry.metadata import ClientRegistryMetadata
 
 from api.storages.adapters import elements
 
-class BoxClient(StorageAdapter):
+class BoxClient(skeleton.StorageAdapter):
 
-    @staticmethod
-    def registry_metadata():
+	@staticmethod
+	def registry_metadata():
 
-        metadata = ClientRegistryMetadata('box', BoxAccountData)
+		metadata = ClientRegistryMetadata('box', BoxAccountData)
 
-        return metadata
+		return metadata
 
-    def __init__(self, account_data):
+	def __init__(self, account_data):
 
-        StorageAdapter.__init__(self)
+		skeleton.StorageAdapter.__init__(self)
 
-        self.__account_data = account_data
+		self.__account_data = account_data
 
-    def obtainAccessToken(self, sess):
+	def obtainAccessToken(self, sess):
 
-        auth_page = sess.get_authorization_page()
+		auth_page = sess.get_authorization_page()
 
-        print 'You should redirect user to ' + auth_page
+		print 'You should redirect user to ' + auth_page
 
-        raw_input()
+		raw_input()
 
-        return sess.get_auth_token()
+		return sess.get_auth_token()
 
-    def connect(self):
+	def connect(self):
 
-        boxSession = session.BoxSession(self.__account_data.appKey())
+		boxSession = session.BoxSession(self.__account_data.appKey())
 
-        if not self.__account_data.isAccessGranted():
-            self.__account_data.assignAccessToken(self.obtainAccessToken(boxSession))
-        else:
-            boxSession.set_auth_token(self.__account_data.oauthTokenSecret())
+		if not self.__account_data.isAccessGranted():
+			self.__account_data.assignAccessToken(self.obtainAccessToken(boxSession))
+		else:
+			boxSession.set_auth_token(self.__account_data.oauthTokenSecret())
 
-        self._client = client.BoxClient(boxSession)
+		self._client = client.BoxClient(boxSession)
 
-    def write(self, target_full_path, source_file, overwrite=True):
-        self._client.upload(target_full_path, source_file)
+	def write(self, target_full_path, source_file, overwrite=True):
+		self._client.upload(target_full_path, source_file)
 
-    def read(self, full_remote_path, target_file_path=None):
+	def read(self, full_remote_path, target_file_path=None):
 
-        remote_file = self._client.download(full_remote_path)
+		remote_file = self._client.download(full_remote_path)
 
-        if target_file_path is not None:
+		if target_file_path is not None:
 
-            f = open(target_file_path,'wb')
+			f = open(target_file_path,'wb')
 
-            meta = remote_file.info()
-            file_size = int(meta.getheaders("Content-Length")[0])
+			meta = remote_file.info()
+			file_size = int(meta.getheaders("Content-Length")[0])
 
-            print "Downloading: %s Bytes: %s" % (target_file_path, file_size)
+			print "Downloading: %s Bytes: %s" % (target_file_path, file_size)
 
-            file_size_dl = 0
-            block_sz = 1024*1024
+			file_size_dl = 0
+			block_sz = 1024*1024
 
-            while True:
-                buffer = remote_file.read(block_sz)
+			while True:
+				buffer = remote_file.read(block_sz)
 
-                if not buffer:
-                    break
+				if not buffer:
+					break
 
-                file_size_dl += len(buffer)
-                f.write(buffer)
+				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)
+				status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
+				status += chr(8)*(len(status)+1)
 
-                print status
+				print status
 
-            f.close()
-        else:
-            return remote_file
+			f.close()
+		else:
+			return remote_file
 
-    def list(self, full_element_path):
-        remote_info = self._client.get_metadata(full_element_path)
+	def list(self, full_element_path):
+		remote_info = self._client.get_metadata(full_element_path)
 
-        content = []
+		content = []
 
-        if remote_info['type'] == client.BoxClient.ELEMENT_TYPE_FOLDER:
-            for item in remote_info['item_collection']['entries']:
-                if item['type'] == client.BoxClient.ELEMENT_TYPE_FOLDER:
-                    content.append(elements.StorageFolder(remote_info['name'], None, remote_info['id']))
-                elif item['type'] == client.BoxClient.ELEMENT_TYPE_FILE:
-                    content.append(elements.StorageFile(remote_info['name'],None,remote_info['id']))
-        else:
-            content.append(elements.StorageFile(remote_info['path'],remote_info['modified_at'],remote_info['id']))
+		if remote_info['type'] == client.BoxClient.ELEMENT_TYPE_FOLDER:
+			for item in remote_info['item_collection']['entries']:
+				if item['type'] == client.BoxClient.ELEMENT_TYPE_FOLDER:
+					content.append(elements.StorageFolder(remote_info['name'], None, remote_info['id']))
+				elif item['type'] == client.BoxClient.ELEMENT_TYPE_FILE:
+					content.append(elements.StorageFile(remote_info['name'],None,remote_info['id']))
+		else:
+			content.append(elements.StorageFile(remote_info['path'],remote_info['modified_at'],remote_info['id']))
 
-        return content
+		return content
 
-    def remove(self, full_path):
-        self._client.delete(full_path)
+	def remove(self, full_path):
+		self._client.delete(full_path)
 
-    def events(self, history_pointer=client.BoxClient.DEFAULT_STREAM_POSITION):
-        iterator = events.BoxEventsIterator(self._client, history_pointer)
-        translator = events.BoxEventTranslator()
+	def events(self, history_pointer=client.BoxClient.DEFAULT_STREAM_POSITION):
+		iterator = events.BoxEventsIterator(self._client, history_pointer)
+		translator = events.BoxEventTranslator()
 
-        return events.BoxEventsBrowser(iterator, translator)
+		return events.BoxEventsBrowser(iterator, translator)
 
 
-class BoxAccountData(StorageAccountData):
+class BoxAccountData(skeleton.StorageAccountData):
 
-    def __init__(self, account_data):
+	def __init__(self, account_data):
 
-        parsed_data = StorageAccountData.parse(self, account_data)
+		skeleton.StorageAccountData.__init__(self)
 
-        self._appKey = parsed_data["appKey"]
-        self._oauth_token = None
-        self._oauth_token_secret = None
+		parsed_data = skeleton.StorageAccountData.parse(self, account_data)
 
-        if "OAuthToken" in parsed_data:
-            self._oauth_token = parsed_data["OAuthToken"]
+		self._appKey = parsed_data["appKey"]
+		self._oauth_token = None
+		self._oauth_token_secret = None
 
-        if "OAuthTokenSecret" in parsed_data:
-            self._oauth_token_secret = parsed_data["OAuthTokenSecret"]
+		if "OAuthToken" in parsed_data:
+			self._oauth_token = parsed_data["OAuthToken"]
 
+		if "OAuthTokenSecret" in parsed_data:
+			self._oauth_token_secret = parsed_data["OAuthTokenSecret"]
 
-    def appKey(self):
-        return self._appKey
+	@skeleton.account_field('box','appKey')
+	def appKey(self):
+		return self._appKey
 
-    def assignAccessToken(self, access_token):
-        self._oauth_token = access_token.key
-        self._oauth_token_secret = access_token.secret
+	def assignAccessToken(self, access_token):
+		self._oauth_token = access_token.key
+		self._oauth_token_secret = access_token.secret
 
-    def oauthToken(self):
-        return self._oauth_token
+	@skeleton.account_field('box','OAuthToken')
+	def oauthToken(self):
+		return self._oauth_token
 
-    def oauthTokenSecret(self):
-        return self._oauth_token_secret
+	def oauthTokenSecret(self):
+		return self._oauth_token_secret
 
-    def isAccessGranted(self):
-        return (self._oauth_token_secret != None and self._oauth_token != None)
+	def isAccessGranted(self):
+		return (self._oauth_token_secret != None and self._oauth_token != None)
 
-    @staticmethod
-    def get_descriptor():
-        print 'Return account description fields, needs_authorization, etc'
+	@staticmethod
+	def get_configuration_fields():
+		return skeleton.StorageAccountData._list_account_field('box')
 
-    @staticmethod
-    def create_descriptor(properties=None,interactiveMode=False):
-        print 'Interactive creation ....'
+	@staticmethod
+	def create_descriptor(properties=None,interactiveMode=False):
+		print 'Interactive creation ....'
 
-    def jsonize(self):
-        return dict({'appKey': self._appKey, 'OAuthToken' : self._oauth_token, 'OAuthTokenSecret': self._oauth_token_secret})
+	def jsonize(self):
+		return dict({'appKey': self._appKey, 'OAuthToken' : self._oauth_token, 'OAuthTokenSecret': self._oauth_token_secret})

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

View file
 from api.shelf.registry.metadata import ClientRegistryMetadata
-from api.storages.adapters.skeleton import StorageAdapter
-from api.storages.adapters.skeleton import StorageAccountData
+from api.storages.adapters import skeleton
 from api.storages.adapters.dropbox import events
 from api.storages.adapters import elements
 
 ACCESS_TYPE_FOLDER = 'app_folder'  # should be 'dropbox' or 'app_folder' as configured for your app
 ACCESS_TYPE_FULL = 'dropbox'
 
-class DropboxClient(StorageAdapter):
+class DropboxClient(skeleton.StorageAdapter):
 
 	@staticmethod
 	def registry_metadata():
 
 	def __init__(self, account_data):
 
-		StorageAdapter.__init__(self)
+		skeleton.StorageAdapter.__init__(self)
 		self._account_data = account_data
 
 	def obtainAccessToken(self, sess):
 		return events.DropboxEventsBrowser(iterator, translator)
 
 
-class DropboxAccountData(StorageAccountData):
+class DropboxAccountData(skeleton.StorageAccountData):
 
 	def __init__(self, account_data):
 
-		parsed_data = StorageAccountData.parse(self, account_data)
+		skeleton.StorageAccountData.__init__(self)
+
+		parsed_data = skeleton.StorageAccountData.parse(self, account_data)
 
 		self._appKey = parsed_data["appKey"]
 		self._appSecret = parsed_data["appSecret"]
 		self._oauth_token = access_token.key
 		self._oauth_token_secret = access_token.secret
 
+	@skeleton.account_field('dropbox','appKey')
 	def appKey(self):
 		return self._appKey
 

File api/storages/adapters/skeleton.py

View file
 import abc
 from api.serializers import json_types
+from functools import wraps
+
+__accounts_field_registry__ = {}
+
+def account_field(cls,name):
+
+	def inner(f):
+
+		__accounts_field_registry__[cls]=name
+
+		def wrapped(*args, **kwargs):
+			return f(*args, **kwargs)
+		return wraps(f)(wrapped)
+
+	return inner
 
 class StorageAdapter(object):
 
 		pass
 
 
+
 class StorageAccountData(json_types.JSonizable):
 
+	def __init__(self):
+		pass
+
 	def parse(self,account_data):
 		return json_types.JSonizable.fromJSON(self,account_data)
 
 		pass
 
 	@staticmethod
-	def get_descriptor():
+	@abc.abstractmethod
+	def get_configuration_fields():
 		pass
 
 	@staticmethod
+	def _list_account_field(account_id):
+		return __accounts_field_registry__[account_id]
+
+	@staticmethod
 	@abc.abstractmethod
 	def create_descriptor(properties=None,interactive=False):
 		pass