Sunday, July 10, 2011

GSoC 2011 Integration with External APIs: Proposal Sync - W7

Approaching to midterm, i partially finished my first deliverable and sent my patches for review. I'm really For now there is one way sync from GDocs to Melange. We are still discussing to allow students "sync back" their proposals to GDocs.

I was struggled with some problems that i want to mention during this blog post. First when using GData libraries on App Engine infrastructure, exporting documents is not directly possible. The reason is that App Engine uses a distrubuted system and this does not allow to write to filesystem. To export anything, GData restricts its API to save output into a file instead of returning exported content. You need little change on gdata library to make it possible:


diff -r 84a930b76e63 -r e65b82d9ad71 app/gdata/docs/service.py
--- a/app/gdata/docs/service.py Sat Jul 09 03:58:23 2011 +0530
+++ b/app/gdata/docs/service.py Sun Jul 10 11:27:08 2011 +0300
@@ -106,6 +106,11 @@
         server=server, additional_headers=additional_headers, **kwargs)
     self.ssl = True
+    # Variables used to hack-in Export function to use it
+    # with a file handler instead of file path name.
+    self.file_handler = None
+    self.use_file_handler = False
+
   def _MakeKindCategory(self, label):
     if label is None:
       return None
@@ -183,10 +188,17 @@
       raise gdata.service.RequestError, {'status': server_response.status,
                                          'reason': server_response.reason,
                                          'body': response_body}
-    f = open(file_path, 'wb')
-    f.write(response_body)
-    f.flush()
-    f.close()
+
+    def writeResponseToFile(f, close=True):
+      f.write(response_body)
+      f.flush()
+      if close:
+        f.close()
+
+    if self.use_file_handler:
+        writeResponseToFile(self.file_handler, close=False)
+    else:
+        writeResponseToFile(open(file_path, 'wb'))
   def MoveIntoFolder(self, source_entry, folder_entry):
     """Moves a document into a folder in the Document List Feed.
@@ -346,7 +358,7 @@
     self._DownloadFile(url, file_path)
-  def Export(self, entry_or_id_or_url, file_path, gid=None, extra_params=None):
+  def Export(self, entry_or_id_or_url, file_path, gid=None, extra_params=None, file_handler=None):
     """Downloads a document from the Document List in a different format.
     Args:
@@ -361,6 +373,13 @@
     Raises:
       RequestError if the service does not respond with success
     """
+
+    if file_handler:
+      self.file_handler = file_handler
+      self.use_file_handler = True
+    else:
+      self.use_file_handler = False
+
     ext = None
     match = self.__FILE_EXT_PATTERN.match(file_path)
     if match:


With this you can use a memory file (StringIO) with Export function to write content to file handler directly instead of giving a file name to function for opening.

Second problem was about OAuth authentication page. We were willing to put OAuth page inside a frame in a jQuery dialog instead of a popup window. For strange reasons, page did not show up in the frame. I started an issue to learn the reason behind that: http://code.google.com/p/gdata-issues/issues/detail?id=2651

You can see demo of proposal sync from here with username:testmelange@gmail.com , password:melange2011 and type to find "Test Document 1" that is in GDocs account of testmelange user.

1 comment:

  1. Wow! Orcun, thats cool. I liked it :). I suggest you to write a tutorial or a set of instructions on how to use it after you are done with its development. It will definitely help the users who have had no experience with Google Docs and for those users who wouldn't want to put an effort in figuring out how it works.

    ReplyDelete