diff --git a/config.py b/config.py index 513d0ce..6ead621 100644 --- a/config.py +++ b/config.py @@ -6,8 +6,8 @@ ''' ''' -gae-rest needs to import the files containing your Models since it is -unable to dynamic infer what are all the available entity kinds +gae-rest needs to import the files containing your Models since it is +unable to dynamic infer what are all the available entity kinds (content types) in your application Example: models = ['my_models.py', 'my_expandos.py'] ''' @@ -15,9 +15,9 @@ ''' which attribute on each Entity can be used as atom element -Example: creator = {'Entry': 'author'} +Example: author = {'Entry': 'author'} ''' -creator = {} +author = {} ''' diff --git a/examples/entries/entries.py b/examples/entries/entries.py index b0da10f..124742c 100644 --- a/examples/entries/entries.py +++ b/examples/entries/entries.py @@ -1,10 +1,12 @@ from google.appengine.ext import db from google.appengine.ext import webapp from google.appengine.api.users import User +from datetime import datetime import wsgiref.handlers class Entry(db.Model): user = db.UserProperty() + published = db.DateTimeProperty() entries = ['jonasgalvez@gmail.com', 'fabricio@gmail.com'] @@ -12,7 +14,7 @@ class Entry(db.Model): entry.delete() for entry in entries: - e = Entry(user=User(email=entry)) + e = Entry(user=User(email=entry), published=datetime.now()) e.put() class EntriesHandler(webapp.RequestHandler): diff --git a/examples/entries/gae-rest/config.py b/examples/entries/gae-rest/config.py index 984d62b..5b9518c 100644 --- a/examples/entries/gae-rest/config.py +++ b/examples/entries/gae-rest/config.py @@ -1,4 +1,49 @@ +''' +Configuration File + +Setup this file according to your application Models as to map their +attributes to the equivalent atom elements. +''' + +''' +gae-rest needs to import the files containing your Models since it is +unable to dynamic infer what are all the available entity kinds +(content types) in your application +''' models = ['entries.py'] -creator = {'Entry': 'user'} -published = {} + +''' +which attribute on each Entity can be used as atom <author> element +Example: author = {'Entry': 'author'} +''' +author = {'Entry': 'user'} + +''' +<title> +Example: title = {'Entry': 'title'} +''' +title = {} + +''' +<content> +Example: content = {'Entry': 'body_html'} +''' +content = {} + +''' +<summary> +Example: summary = {'Entry': 'excerpt'} +''' +summary = {} + +''' +<published> +Example: published = {'Entry': 'published'} +''' +published = {'Entry': 'published'} + +''' +<updated> +Example: updated = {'Entry': 'updated'} +''' updated = {} \ No newline at end of file diff --git a/examples/entries/gae-rest/xn.py b/examples/entries/gae-rest/xn.py index e2da9a6..ae1cc57 100644 --- a/examples/entries/gae-rest/xn.py +++ b/examples/entries/gae-rest/xn.py @@ -1,4 +1,5 @@ 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 @@ -24,11 +25,7 @@ def expose(only=[]): sys.path.remove(pydir) return loadedfiles -loadedfiles = expose() - -def retrieve_model_property_list(entity): - q = db.GqlQuery("SELECT * FROM XNExposedModel WHERE name = :1", entity) - return q[0].model_properties +expose() class XNQueryHandler(webapp.RequestHandler): def get(self, format, version, query): @@ -39,32 +36,53 @@ def get(self, format, version, query): kind = xnquery.resources.content.selectors.type.rightside atom = AtomBuilder(kind, objects) self.response.out.write(str(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('<','<'), + 'summary': lambda value: value.replace('<','<'), + '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: - for property in object.properties().keys(): + properties = object.properties() + self.process_known_elements(object, properties) + for property in properties: value = getattr(object, property) - if (kind in config.creator) and property == config.creator[kind]: - with xml.author: - if type(value) == User: - xml.name(value.nickname()) - xml.email(value.email()) - else: - xml.name(value) - elif type(value) == list: - xml["xn:%s" % property](' '.join(getattr(object, property))) + if type(value) == list: + xml["xn:%s" % property](' '.join(value)) else: - xml["xn:%s" % property](getattr(object, property)) + xml["xn:%s" % property](str(value).replace('<','<')) 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): + 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)) + del properties[m_element] def __str__(self): return str(self.xml) diff --git a/xn.py b/xn.py index c8f5b07..ae1cc57 100644 --- a/xn.py +++ b/xn.py @@ -25,11 +25,7 @@ def expose(only=[]): sys.path.remove(pydir) return loadedfiles -loadedfiles = expose() - -def retrieve_model_property_list(entity): - q = db.GqlQuery("SELECT * FROM XNExposedModel WHERE name = :1", entity) - return q[0].model_properties +expose() class XNQueryHandler(webapp.RequestHandler): def get(self, format, version, query): @@ -46,36 +42,47 @@ class AtomBuilder: '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('<','<'), + 'summary': lambda value: value.replace('<','<'), + '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: - for property in object.properties().keys(): + properties = object.properties() + self.process_known_elements(object, properties) + for property in properties: value = getattr(object, property) - if (kind in config.creator) and property == config.creator[kind]: - with xml.author: - if type(value) == User: - xml.name(value.nickname()) - xml.email(value.email()) - else: - xml.name(value) - elif (kind in config.title) and property == config.title[kind]: - xml.title(value) - elif (kind in config.content) and property == config.content[kind]: - xml.content(value.replace('<','<')) - elif (kind in config.summary) and property == config.summary[kind]: - xml.summary(value.replace('<','<')) - elif (kind in config.published) and property == config.published[kind]: - xml.published('%sZ' % value.isoformat()) - elif (kind in config.updated) and property == config.updated[kind]: - xml.updated('%sZ' % value.isoformat()) - elif type(value) == list: + if type(value) == list: xml["xn:%s" % property](' '.join(value)) else: xml["xn:%s" % property](str(value).replace('<','<')) 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): + 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)) + del properties[m_element] def __str__(self): return str(self.xml)