public
Description: Atom REST API for Google App Engine
Homepage:
Clone URL: git://github.com/fczuardi/gae-rest.git
gae-rest / xn.py
100644 104 lines (98 sloc) 3.722 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from __future__ import with_statement
from datetime import datetime
import os, re, sys, types
sys.path += [os.path.split(os.path.abspath(__file__))[0]]
import glob, urllib2
import urllib
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.api.users import User
from xnquery import *
from xmlbuilder import *
import config
 
def expose(only=[]):
  rootdir = os.path.join(os.path.abspath(os.path.split(os.path.dirname(__file__))[0]))
  loadedfiles = []
  for model in config.models:
    pydir, pyfile = os.path.split(model)
    pydir = os.path.abspath(os.path.join(rootdir, pydir))
    sys.path += [pydir]
    pyfile = os.path.splitext(pyfile)[0]
    loadedfiles.append(pyfile)
    __import__(pyfile)
    sys.path.remove(pydir)
  return loadedfiles
 
expose()
 
class XNQueryHandler(webapp.RequestHandler):
  def get(self, format, version, query):
    xnquery = XNQueryParser(query, os.environ['QUERY_STRING'])
    # if the query is content(id='...'), do not use GQLQueryBuilder
    if 'id' in xnquery.resources.content.selectors:
      entity_ref = db.Key(xnquery.resources.content.selectors.id.rightside)
      objects = [db.get(entity_ref)]
      if len(objects) > 0: kind = entity_ref.kind()
    else:
      gqlquery = GQLQueryBuilder(xnquery)
      objects = db.GqlQuery(str(gqlquery))
      kind = xnquery.resources.content.selectors.type.rightside
    self.response.headers['Content-Type'] = 'application/atom+xml'
    atom = AtomBuilder(kind, objects)
    self.response.out.write(unicode(atom))
 
class AtomBuilder:
  FEED_NS = {
    'xmlns': 'http://www.w3.org/2005/Atom',
    'xmlns:xn': 'http://www.ning.com/atom/1.0'
  }
  HANDLERS = {
    'title': lambda value: value,
    'content': lambda value: value.replace('<','&lt;'),
    'summary': lambda value: value.replace('<','&lt;'),
    'published': lambda value: '%sZ' % value.isoformat(),
    'updated': lambda value: '%sZ' % value.isoformat(),
    'author': 'process_author'
  }
  def __init__(self, kind, objects):
    xml = builder(version='1.0', encoding='utf-8')
    self.xml = xml
    self.kind = kind
    with xml.feed(**self.FEED_NS):
      xml.title("GAE-REST Test Atom Feed")
      for object in objects:
        with xml.entry:
          xml.id(object.key())
          properties = object.properties()
          self.process_known_elements(object, properties)
          for property in properties:
            value = getattr(object, property)
            if type(value) == list:
              xml["xn:%s" % property](' '.join(value))
            else:
              xml["xn:%s" % property](unicode(value).replace('<','&lt;'))
    self.xml = xml
  def process_author(self, value):
    with self.xml.author:
      if type(value) == User:
        self.xml.name(value.nickname())
        self.xml.email(value.email())
      else:
        self.xml.name(value)
  def process_known_elements(self, object, properties):
    used_properties = {}
    for element in AtomBuilder.HANDLERS.keys():
      m_element = getattr(config, element).get(self.kind, None)
      if m_element != None:
        if type(AtomBuilder.HANDLERS[element]) != str:
          self.xml[element](AtomBuilder.HANDLERS[element](getattr(object, m_element)))
        else:
          getattr(self, AtomBuilder.HANDLERS[element])(getattr(object, m_element))
        used_properties[m_element] = True
    for property_name in used_properties.keys():
      del properties[property_name]
  def __str__(self):
    return unicode(self.xml)
 
def main():
  application = webapp.WSGIApplication([('/xn/(.*)/(.*)/(.*)', XNQueryHandler)], debug=True)
  wsgiref.handlers.CGIHandler().run(application)
 
if __name__ == "__main__":
  main()