Fixed a bug in the JSON templating engine.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
Metadata-Version: 1.0
|
Metadata-Version: 1.0
|
||||||
Name: pecan
|
Name: pecan
|
||||||
Version: 0.1dev
|
Version: 0.1dev
|
||||||
Summary: A WSGI object-dispatching web framework, in the spirit of TurboGears, only much much smaller, with many fewer dependancies.
|
Summary: A WSGI object-dispatching web framework, in the spirit of TurboGears, only much much smaller, with many fewer dependencies.
|
||||||
Home-page: http://github.com/cleverdevil/pecan
|
Home-page: http://github.com/cleverdevil/pecan
|
||||||
Author: Jonathan LaCour
|
Author: Jonathan LaCour
|
||||||
Author-email: jonathan@cleverdevil.org
|
Author-email: jonathan@cleverdevil.org
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pecan/decorators.py
|
|||||||
pecan/hooks.py
|
pecan/hooks.py
|
||||||
pecan/jsonify.py
|
pecan/jsonify.py
|
||||||
pecan/pecan.py
|
pecan/pecan.py
|
||||||
|
pecan/rest.py
|
||||||
pecan/routing.py
|
pecan/routing.py
|
||||||
pecan/secure.py
|
pecan/secure.py
|
||||||
pecan/templating.py
|
pecan/templating.py
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
WebOb >= 0.9.8
|
WebOb >= 1.0.0
|
||||||
|
WebCore >= 1.0.0
|
||||||
simplegeneric >= 0.7
|
simplegeneric >= 0.7
|
||||||
Genshi >= 0.6
|
Genshi >= 0.6
|
||||||
Kajiki >= 0.2.2
|
Kajiki >= 0.2.2
|
||||||
@@ -6,4 +7,5 @@ Mako >= 0.3
|
|||||||
py >= 1.3.4
|
py >= 1.3.4
|
||||||
WebTest >= 1.2.2
|
WebTest >= 1.2.2
|
||||||
Paste >= 1.7.5.1
|
Paste >= 1.7.5.1
|
||||||
PasteScript >= 1.7.3
|
PasteScript >= 1.7.3
|
||||||
|
formencode >= 1.2.2
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
try:
|
try:
|
||||||
from json import JSONEncoder, dumps
|
from json import JSONEncoder
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from simplejson import JSONEncoder, dumps
|
from simplejson import JSONEncoder
|
||||||
|
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from webob.multidict import MultiDict
|
from webob.multidict import MultiDict
|
||||||
from simplegeneric import generic
|
from simplegeneric import generic
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# exceptions
|
# exceptions
|
||||||
#
|
#
|
||||||
@@ -21,49 +20,58 @@ class JsonEncodeError(Exception):
|
|||||||
# encoders
|
# encoders
|
||||||
#
|
#
|
||||||
|
|
||||||
class BaseEncoder(JSONEncoder):
|
def is_saobject(obj):
|
||||||
def is_saobject(self, obj):
|
return hasattr(obj, '_sa_class_manager')
|
||||||
return hasattr(obj, '_sa_class_manager')
|
|
||||||
|
|
||||||
def jsonify(self, obj):
|
class GenericJSON(JSONEncoder):
|
||||||
return dumps(self.encode(obj))
|
def default(self, obj):
|
||||||
|
import pdb; pdb.set_trace()
|
||||||
def encode(self, obj):
|
|
||||||
if hasattr(obj, '__json__') and callable(obj.__json__):
|
if hasattr(obj, '__json__') and callable(obj.__json__):
|
||||||
return obj.__json__()
|
return obj.__json__()
|
||||||
elif isinstance(obj, (date, datetime)):
|
elif isinstance(obj, (datetime.date, datetime.datetime)):
|
||||||
return obj.isoformat()
|
return str(obj)
|
||||||
elif isinstance(obj, Decimal):
|
elif isinstance(obj, decimal.Decimal):
|
||||||
return float(obj)
|
return float(obj)
|
||||||
elif self.is_saobject(obj):
|
elif is_saobject(obj):
|
||||||
props = {}
|
props = {}
|
||||||
for key in obj.__dict__:
|
for key in obj.__dict__:
|
||||||
if not key.startswith('_sa_'):
|
if not key.startswith('_sa_'):
|
||||||
props[key] = getattr(obj, key)
|
props[key] = getattr(obj, key)
|
||||||
return props
|
return props
|
||||||
|
elif isinstance(obj, ResultProxy):
|
||||||
|
return dict(rows=list(obj), count=obj.rowcount)
|
||||||
|
elif isinstance(obj, RowProxy):
|
||||||
|
return dict(rows=dict(obj), count=1)
|
||||||
elif isinstance(obj, MultiDict):
|
elif isinstance(obj, MultiDict):
|
||||||
return obj.mixed()
|
return obj.mixed()
|
||||||
else:
|
else:
|
||||||
try:
|
return JSONEncoder.default(self, obj)
|
||||||
from sqlalchemy.engine.base import ResultProxy, RowProxy
|
|
||||||
if isinstance(obj, ResultProxy):
|
|
||||||
return dict(rows=list(obj), count=obj.rowcount)
|
|
||||||
elif isinstance(obj, RowProxy):
|
|
||||||
return dict(rows=dict(obj), count=1)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# generic function support
|
|
||||||
#
|
|
||||||
|
|
||||||
encoder = BaseEncoder()
|
_default = GenericJSON()
|
||||||
|
|
||||||
@generic
|
@generic
|
||||||
def jsonify(obj):
|
def jsonify(obj):
|
||||||
return encoder.encode(obj)
|
return _default.default(obj)
|
||||||
|
|
||||||
|
class GenericFunctionJSON(GenericJSON):
|
||||||
|
def default(self, obj):
|
||||||
|
return jsonify(obj)
|
||||||
|
|
||||||
|
_instance = GenericFunctionJSON()
|
||||||
|
|
||||||
|
|
||||||
def encode(obj):
|
def encode(obj):
|
||||||
return dumps(jsonify(obj))
|
if isinstance(obj, basestring):
|
||||||
|
return _instance.encode(obj)
|
||||||
|
try:
|
||||||
|
value = obj['test']
|
||||||
|
except TypeError:
|
||||||
|
if not hasattr(obj, '__json__') and not is_saobject(obj):
|
||||||
|
raise JsonEncodeError('Your Encoded object must be dict-like.')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
"""Return a JSON string representation of a Python object."""
|
||||||
|
return _instance.encode(obj)
|
||||||
@@ -5,6 +5,7 @@ from pecan import request
|
|||||||
class RestController(object):
|
class RestController(object):
|
||||||
# TODO: implement the following:
|
# TODO: implement the following:
|
||||||
# - get, new, edit, post_delete, get_delete
|
# - get, new, edit, post_delete, get_delete
|
||||||
|
# - implement the "_method" parameter
|
||||||
# - see: http://turbogears.org/2.1/docs/modules/tgcontroller.html
|
# - see: http://turbogears.org/2.1/docs/modules/tgcontroller.html
|
||||||
|
|
||||||
@expose()
|
@expose()
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ class JsonRenderer(object):
|
|||||||
|
|
||||||
def render(self, template_path, namespace):
|
def render(self, template_path, namespace):
|
||||||
from jsonify import encode
|
from jsonify import encode
|
||||||
result = encode(namespace)
|
return encode(namespace)
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ class TestEngines(object):
|
|||||||
@expose('json')
|
@expose('json')
|
||||||
def index(self, argument=None):
|
def index(self, argument=None):
|
||||||
assert argument == 'value'
|
assert argument == 'value'
|
||||||
|
return dict()
|
||||||
|
|
||||||
# arguments should get passed appropriately
|
# arguments should get passed appropriately
|
||||||
app = TestApp(Pecan(RootController()))
|
app = TestApp(Pecan(RootController()))
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class TestRestController(object):
|
|||||||
|
|
||||||
@expose('json')
|
@expose('json')
|
||||||
def get_all(self):
|
def get_all(self):
|
||||||
return self.data
|
return dict(items=self.data)
|
||||||
|
|
||||||
@expose('json')
|
@expose('json')
|
||||||
def post(self, value):
|
def post(self, value):
|
||||||
@@ -45,7 +45,7 @@ class TestRestController(object):
|
|||||||
# test get_all
|
# test get_all
|
||||||
r = app.get('/things')
|
r = app.get('/things')
|
||||||
assert r.status_int == 200
|
assert r.status_int == 200
|
||||||
assert r.body == dumps(ThingsController.data)
|
assert r.body == dumps(dict(items=ThingsController.data))
|
||||||
|
|
||||||
# test get_one
|
# test get_one
|
||||||
for i, value in enumerate(ThingsController.data):
|
for i, value in enumerate(ThingsController.data):
|
||||||
@@ -81,4 +81,4 @@ class TestRestController(object):
|
|||||||
# make sure it works
|
# make sure it works
|
||||||
r = app.get('/things')
|
r = app.get('/things')
|
||||||
assert r.status_int == 200
|
assert r.status_int == 200
|
||||||
assert len(loads(r.body)) == 4
|
assert len(loads(r.body)['items']) == 4
|
||||||
Reference in New Issue
Block a user