Release the hounds: Support for App Engine and Contacts API

Tuesday, April 08, 2008 at 12:09 PM



The 1.0.12.1 release of the gdata-python-client has a couple of nifty new features which I thought are worth mentioning. First, is a new module which allows the Python library to be used on Google App Engine. Since the App Engine runs a sandboxed Python interpreter, HTTP calls must be made using one of the App Engine's APIs: urlfetch. After some refactoring of the library's code, I was able to write a drop-in replacement for making HTTP requests, so that the gdata.service module can be used on Google App Engine. To use urlfetch instead of the library's default (httplib), you would use the following:

import gdata.service
import gdata.urlfetch
# Use urlfetch instead of httplib
gdata.service.http_request_handler = gdata.urlfetch
This refactoring has the added benefit of making it easier to swap out the HTTP transport layer from under the gdata.service module. I'm planning to take advantage of this for a new mock_service module to use in unit tests, and the door is open if people want to help with that or other ideas (I've been meaning to support httplib2, and will one of these days).

Second, I'd like to extend a big thank you to Dag Brattli , who wrote modules for the Google Contacts API. Now you can access and manage your Gmail contacts using the same Python library you've come to know. (and maybe, dare I say, love?) Dag is the latest in a long line of contributors to whom I owe a debt of gratitude. This library wouldn't have support for Contacts and other services and use cases without the hard work of Dag, Takashi, Håvard, Benoit, and others who have submitted patches or reported issues (apologies if I've forgotten anyone).

Updated (April 10th, 2008) to reference release 1.0.12.1 instead of 1.0.12. The new release fixes an issue with importing ElementTree.

17 comments:

Patate said...
This post has been removed by the author.
Venkatesh said...

Jeff,

I can't get it to work. Here is my handler.py code. I am unable to import the packages in PROD. Everything works fine in my DEV M/C(XP).

import sys
import cgi
import wsgiref.handlers
import string
from google.appengine.ext import webapp
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext.webapp import template
#As soon as i add these import in PROD it fails with a 500 Error
import gdata.service
import gdata.urlfetch
# Use urlfetch instead of httplib
gdata.service.http_request_handler = gdata.urlfetch


class Blog(webapp.RequestHandler):
def get(self):
try:
self.response.out.write('Hello')
except:
self.response.out.write(sys.exc_info())

class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('Hello')

def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/blog', Blog),
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
main()

Venkatesh said...

import sys
import cgi
import wsgiref.handlers
import string
from google.appengine.ext import webapp
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext.webapp import template
#As soon as i add these import in PROD it fails with a 500 Error
import gdata.service
import gdata.urlfetch
# Use urlfetch instead of httplib
gdata.service.http_request_handler = gdata.urlfetch


class Blog(webapp.RequestHandler):
def get(self):
try:
self.response.out.write('Hello')
except:
self.response.out.write(sys.exc_info())

class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('Hello')

def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/blog', Blog),
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
main()

Jeff Scudder said...

Hi Venkatesh, my first guess would be that the gdata and atom packages might not have been uploaded to your server. It should work if you copy the src/atom and src/gdata directories into your App Engine app's directory. The sample would work on your machine, because it can import from the modules you've installed locally, however, App Engine doesn't have these modules by default. Was that the issue?

Venkatesh said...

Thanks Jeff. IT worked.

The mistake I did was this.

gdata and atom where under root directory and not the project directory.

Once I move those two folders to my current project directory it worked.

Thanks a lot for your quick response.

Venkatesh said...

Ah, yes ..i saw 37 files getting upload (Guess they were Gdata/atom src)

Venkatesh said...

Jeff,
Can't get it to work with AutSub authentication. I get
"(, DownloadError(), )"

Here is my handler code.

def GetAuthSubUrl(req):
next = 'http://' + req.environ['HTTP_HOST'] + '/blog'
scope = 'http://www.blogger.com/feeds'
secure = True
session = True
blogger_service = service.GDataService()
return blogger_service.GenerateAuthSubURL(next, scope, secure, session);


class Document(db.Model):
author = db.UserProperty()
content = db.TextProperty()
date = db.DateTimeProperty(auto_now_add=True)

class Blog(webapp.RequestHandler):
def get(self):
try:
authsub_token = self.request.get('token')
blogger_service = service.GDataService()
blogger_service.auth_token = authsub_token
blogger_service.UpgradeToSessionToken()
blogger_service.http_request_handler = gdata.urlfetch
# Get the blog ID for the first blog.
feed = blogger_service.Get('/feeds/default/blogs')
self.response.out.write(authsub_token)
self_link = feed.entry[0].GetSelfLink()
if self_link:
self.blog_id = self_link.href.split('/')[-1]
for entry in feed.entry:
self.response.out.write("\t" + entry.title.text)
except:
self.response.out.write(sys.exc_info())

class MainPage(webapp.RequestHandler):
def get(self):
authSubUrl = GetAuthSubUrl(self.request);
self.response.out.write(self.request.environ['HTTP_HOST'])
self.response.out.write('Login to your Google account' % authSubUrl)

def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/blog', Blog),
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
main()

Sebastian Aviña said...

GData doesn't work on my development server, I need to upload the application to debug it..

I'm using Windows Vista, Python 2.5.2, gdata.py-1.0.12.1.tar

And, GData-py, works fine under Python IDE, the only problem is on the development server...

This is a sample error on localhost:8080

Traceback (most recent call last):
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 484, in __call__
handler.get(*groups)
File "E:\appeng\picasa-gallery\sample.py", line 26, in get
albums = pws.GetUserFeed().entry
File "E:\appeng\fotogaytan\gdata\photos\service.py", line 239, in GetUserFeed
return self.GetFeed(uri, limit=limit)
File "E:\appeng\fotogaytan\gdata\photos\service.py", line 182, in GetFeed
return self.Get(uri, converter=gdata.photos.AnyFeedFromString)
File "E:\appeng\fotogaytan\gdata\service.py", line 484, in Get
return converter(result_body)
File "E:\appeng\fotogaytan\gdata\photos\__init__.py", line 1072, in AnyFeedFromString
File "C:\Python25\lib\xml\etree\ElementTree.py", line 962, in XML
parser = XMLTreeBuilder()
File "C:\Python25\lib\xml\etree\ElementTree.py", line 1118, in __init__
"No module named expat; use SimpleXMLTreeBuilder instead"
ImportError: No module named expat; use SimpleXMLTreeBuilder instead

m_Zoqui said...

I was not able to run a veru simple test to list my documents. I can get it running under command line, but not under the dev server. The expat module is not imported, and it crashes on line "documents_feed = client.GetDocumentListFeed()"

Is there any way to solve this issue?

import wsgiref.handlers
import gdata.docs.service
import gdata.service
import gdata.urlfetch
from google.appengine.ext import webapp

gdata.service.http_request_handler = gdata.urlfetch

class MyHandler(webapp.RequestHandler):
def get(self):
client = gdata.docs.service.DocsService()
client.ClientLogin('mazoqui@gmail.com', '?????????')
documents_feed = client.GetDocumentListFeed()
#for document_entry in documents_feed.entry:
# self.response.out.write(document_entry.title.text)

def main():
app = webapp.WSGIApplication([
(r'.*',MyHandler)], debug=True)
wsgiref.handlers.CGIHandler().run(app)

if __name__ == "__main__":
main()

Jeff Scudder said...

@ Venkatesh, Sebastian Aviña, and m_Zoqui: Glad to hear this is generating interest! I'm more than happy to help you get started with this new environment, and I think this might be easier handled in a discussion group (the formatting in the comments can make it difficult to see your code). How about we meet in the gdata-python client contributor's group?

Peter Kehl said...
This post has been removed by the author.
Peter Kehl said...

Hi Jeff,

thank you for this article. But how do I get GData work with Google App Engine Launcher/local server? I'm on Mac OS. It fails when I run my service via dev_appserver.py or GoogleAppEngineLauncher (version 1.0.2 from 15 May):

import gdata.service
ImportError: No module named gdata.service

If I have to add GData python library, then where should I put it? Thank you.

Peter Kehl said...

I see from up comments above and from G. App engine group: I had to copy folders gdata and atom from GData python src in the top level of my project (same level as app.yml).

uiyui said...

I would gold für wow cultivate courage.buy wow gold “Nothing is so mild wow gold cheap and gentle as courage, nothing so cruel and pitiless as cowardice,” syas a wise author. We too often borrow trouble, and anticipate that may never appear.”wow gold kaufen The fear of ill exceeds the ill we fear.” Dangers will arise in any career, but presence of mind will often conquer the worst of them. Be prepared for any fate, and there is no harm to be freared. If I were a boy again, I would look on the cheerful side. life is very much like a mirror:sell wow gold if you smile upon it,maple mesos I smiles back upon you; but if you frown and look doubtful on it,cheap maplestory mesos you will get a similar look in return. Inner sunshine warms not only the heart of the owner,world of warcraft power leveling but of all that come in contact with it. “ who shuts love out ,in turn shall be shut out from love.” If I were a boy again, I would school myself to say no more often.billig wow gold I might cheap mesos write pages maple meso on the importance of learning very early in life to gain that point where a young boy can stand erect, and decline doing an unworthy act because it is unworthy.wow powerleveling If I were a boy again, I would demand of myself more courtesy towards my companions and friends,wow leveling and indeed towards strangers as well.Maple Story Account The smallest courtesies along the rough roads of life are wow powerleveln like the little birds that sing to us all winter long, and make that season of ice and snow more endurable. Finally,maple story powerleveling instead of trying hard to be happy

wow gold said...

If you wow gold were in wow gold any doubt buy wow gold that the buy wow gold God Wars cheap wow gold Dungeon was cheap wow gold challenge enough wow power leveling for you, wow power leveling look no further power leveling than the giant power leveling demon, K’ril wow gold Tsutsaroth. Once buy wow gold thought of as cheap wow gold nothing more world of warcraft gold confirm his existence.

xuqunren said...

We offer WoW Gold, World of Warcraft Gold and WoW Power Leveling on all WoW servers, and start to sell Warhammer Gold (Warhammer Online Gold) at lowest price, we can deliver WoW Gold and WoW Power Leveling at a moment's notice. We promise you the lowest price of World of Warcraft Gold everyday. GameVive is the one for you to buy Cheap WoW Gold!www.gamevive.com , Cheap WoW Gold
Airnk.com always update lots of air jordans photos, pictures and news here! Come on, join us for the wonderful basketball shoes and air jordan shoes revel now! Full your collection of jordan shoes from grabbing the right one at airnk.com. We have very fashionable basketball shoes basketball shoes and Air Jordan Shoes that will go well with any of you clothes.Tiffany & Co Silver Jewelry | Tiffany Jewelry | Tiffany Rings | Tiffany Earrings | Ttiffany Necklaces | Tiffany Bracelet | tiffany | cheap wow gold

Admin said...

sinema izle
film izle
film
online sinema
porno izle