Hi again Jose,

Jeff Scudder has just drawn my attention to a pair of excellent
articles he's written about exactly this subject:
http://code.google.com/appengine/articles/gdata.html
http://code.google.com/appengine/articles/more_google_data.html

As the first article points out, you need to call the
gdata.alt.appengine.run_on_appengine function on each instance of a
gdata.service.GDataService object in order to have it work on App
Engine correctly.

-Nick Johnson

On Mon, May 18, 2009 at 12:29 PM, Nick Johnson (Google)
<[email protected]> wrote:
> Hi Jose,
>
> This is a known incompatibility in App Engine. The GData APIs send an
> absolute URL to the httplib library where it expects a relative one
> (since the host and port was specified in the constructor); the Python
> httplib handles this properly, but the App Engine replacement
> currently does not.
>
> -Nick Johnson
>
> On Fri, May 15, 2009 at 7:32 PM, Jose  Vidal <[email protected]> wrote:
>>
>> I am trying to read a spreadsheet from app engine using text_db and
>> authsub.
>>
>> I read http://code.google.com/appengine/articles/gdata.html and got it
>> to work. Then I read 
>> http://code.google.com/p/gdata-python-client/wiki/AuthSubWithTextDB
>> and I tried to merge the two in the file below (step4.py) but when I
>> run it locally I get:
>>
>> Traceback (most recent call last):
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/google/
>> appengine/ext/webapp/__init__.py", line 498, in __call__
>>    handler.get(*groups)
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/
>> glassboard/step4.py", line 56, in get
>>    session_token = client._GetDocsClient().UpgradeToSessionToken
>> (auth_token) #If I don't pass this argument I get a NonAuthSubToken
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/
>> glassboard/gdata/service.py", line 866, in UpgradeToSessionToken
>>    self.SetAuthSubToken(self.upgrade_to_session_token(token))
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/
>> glassboard/gdata/service.py", line 885, in upgrade_to_session_token
>>    headers={'Content-Type':'application/x-www-form-urlencoded'})
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/
>> glassboard/gdata/auth.py", line 678, in perform_request
>>    return http_client.request(operation, url, data=data,
>> headers=headers)
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/
>> glassboard/atom/http.py", line 163, in request
>>    return connection.getresponse()
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/google/
>> appengine/dist/httplib.py", line 200, in getresponse
>>    self._allow_truncated, self._follow_redirects)
>>  File "/home/jmvidal/share/progs/googleapps/google_appengine/google/
>> appengine/api/urlfetch.py", line 267, in fetch
>>    raise DownloadError(str(e))
>> DownloadError: ApplicationError: 2 nonnumeric port: ''
>>
>> Can anyone shed some light on this?
>>
>>
>> # step4.py
>> #
>> # Trying to read spreadsheets from app engine using text_db and
>> authsub.
>> #
>> # Merge of this code
>> # http://code.google.com/p/gdata-python-client/wiki/AuthSubWithTextDB
>> # with this one
>> # http://code.google.com/appengine/articles/gdata.html (step 3)
>>
>> import wsgiref.handlers
>> import cgi
>> from google.appengine.ext import webapp
>> from google.appengine.api import users
>> import atom.url
>> import gdata.service
>> import gdata.alt.appengine
>> import gdata.spreadsheet.text_db
>> import settings
>>
>>
>> class Fetcher(webapp.RequestHandler):
>>
>>  def get(self):
>>    # Write our pages title
>>    self.response.out.write("""<html><head><title>
>>        Google Data Feed Fetcher: read Google Data API Atom feeds</
>> title>""")
>>    self.response.out.write('</head><body>')
>>    next_url = atom.url.Url('http', settings.HOST_NAME, path='/step4')
>>    # Allow the user to sign in or sign out
>>    if users.get_current_user():
>>      self.response.out.write('<a href="%s">Sign Out</a><br>' % (
>>          users.create_logout_url(str(next_url))))
>>    else:
>>      self.response.out.write('<a href="%s">Sign In</a><br>' % (
>>          users.create_login_url(str(next_url))))
>>
>>    # Initialize a client to talk to Google Data API services.
>> #    client = gdata.service.GDataService()
>> #    auth_url =  client.GenerateAuthSubURL(
>> #      next_url,
>> #      ('http://docs.google.com/feeds/',), secure=False, session=True)
>>
>>    client = gdata.spreadsheet.text_db.DatabaseClient()
>>    auth_url = client._GetDocsClient().GenerateAuthSubURL(
>>      next_url,
>>      ('http://spreadsheets.google.com/feeds/','http://docs.google.com/
>> feeds/documents/'), secure=False, session=True)
>>
>>    gdata.alt.appengine.run_on_appengine(client)
>>
>>    feed_url = self.request.get('feed_url')
>>
>>    session_token = None
>>    # Find the AuthSub token and upgrade it to a session token.
>>    auth_token = gdata.auth.extract_auth_sub_token_from_url
>> (self.request.uri)
>>    if auth_token:
>>      # Upgrade the single-use AuthSub token to a multi-use session
>> token.
>>      client._GetDocsClient().SetAuthSubToken(auth_token)
>>      session_token = client._GetDocsClient().UpgradeToSessionToken
>> (auth_token) #If I don't pass this argument I get a NonAuthSubToken
>>      client._GetSpreadsheetsClient().SetAuthSubToken
>> (client._GetDocsClient().GetAuthSubToken())
>> #      session_token = client.upgrade_to_session_token(auth_token)
>>    if session_token and users.get_current_user():
>>      # If there is a current user, store the token in the datastore
>> and
>>      # associate it with the current user. Since we told the client
>> to
>>      # run_on_appengine, the add_token call will automatically store
>> the
>>      # session token if there is a current_user.
>>      client.token_store.add_token(session_token)
>>    elif session_token:
>>      # Since there is no current user, we will put the session token
>>      # in a property of the client. We will not store the token in
>> the
>>      # datastore, since we wouldn't know which user it belongs to.
>>      # Since a new client object is created with each get call, we
>> don't
>>      # need to worry about the anonymous token being used by other
>> users.
>>      client.current_token = session_token
>>
>>    self.response.out.write('<div id="main">')
>>    self.fetch_feed(client, feed_url)
>>    self.response.out.write('</div>')
>>    self.response.out.write(
>>        '<div id="sidebar"><div id="scopes"><h4>Request a token</
>> h4><ul>')
>>    self.response.out.write('<li><a href="%s">Google Documents</a></
>> li>' % (auth_url))
>>    self.response.out.write('</ul></div><br/><div id="tokens">')
>>
>>  def fetch_feed(self, client, feed_url):
>>    # Attempt to fetch the feed.
>>    if not feed_url:
>>      self.response.out.write(
>>          'No feed_url was specified for the app to fetch.<br/>')
>>      example_url = atom.url.Url('http', settings.HOST_NAME, path='/
>> step4',
>>          params={'feed_url':
>>              'http://docs.google.com/feeds/documents/private/full'}
>>          ).to_string()
>>      self.response.out.write('Here\'s an example query which will
>> show the'
>>          ' XML for the feed listing your Google Documents <a '
>>          'href="%s">%s</a>' % (example_url, example_url))
>>      return
>>    try:
>>      response = client.Get(feed_url, converter=str)
>>      self.response.out.write(cgi.escape(response))
>>    except gdata.service.RequestError, request_error:
>>      # If fetching fails, then tell the user that they need to login
>> to
>>      # authorize this app by logging in at the following URL.
>>      if request_error[0]['status'] == 401:
>>        # Get the URL of the current page so that our AuthSub request
>> will
>>        # send the user back to here.
>>        next = atom.url.Url('http', settings.HOST_NAME, path='/step4',
>>          params={'feed_url': feed_url})
>>        # If there is a current user, we can request a session token,
>> otherwise
>>        # we should ask for a single use token.
>>        auth_sub_url = client.GenerateAuthSubURL(next, feed_url,
>>            secure=False, session=True)
>>        self.response.out.write('<a href="%s">' % (auth_sub_url))
>>        self.response.out.write(
>>            'Click here to authorize this application to view the
>> feed</a>')
>>      else:
>>        self.response.out.write(
>>            'Something went wrong, here is the error object: %s ' % (
>>                str(request_error[0])))
>>
>>
>> def main():
>>  application = webapp.WSGIApplication([('/.*', Fetcher),],
>> debug=True)
>>  wsgiref.handlers.CGIHandler().run(application)
>>
>>
>> if __name__ == '__main__':
>>  main()
>>
>> 

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to