Fixed a bug in the JSON templating engine.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: pecan
|
||||
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
|
||||
Author: Jonathan LaCour
|
||||
Author-email: jonathan@cleverdevil.org
|
||||
|
||||
@@ -6,6 +6,7 @@ pecan/decorators.py
|
||||
pecan/hooks.py
|
||||
pecan/jsonify.py
|
||||
pecan/pecan.py
|
||||
pecan/rest.py
|
||||
pecan/routing.py
|
||||
pecan/secure.py
|
||||
pecan/templating.py
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
WebOb >= 0.9.8
|
||||
WebOb >= 1.0.0
|
||||
WebCore >= 1.0.0
|
||||
simplegeneric >= 0.7
|
||||
Genshi >= 0.6
|
||||
Kajiki >= 0.2.2
|
||||
@@ -6,4 +7,5 @@ Mako >= 0.3
|
||||
py >= 1.3.4
|
||||
WebTest >= 1.2.2
|
||||
Paste >= 1.7.5.1
|
||||
PasteScript >= 1.7.3
|
||||
PasteScript >= 1.7.3
|
||||
formencode >= 1.2.2
|
||||
@@ -1,14 +1,13 @@
|
||||
try:
|
||||
from json import JSONEncoder, dumps
|
||||
from json import JSONEncoder
|
||||
except ImportError:
|
||||
from simplejson import JSONEncoder, dumps
|
||||
from simplejson import JSONEncoder
|
||||
|
||||
from datetime import datetime, date
|
||||
from decimal import Decimal
|
||||
from webob.multidict import MultiDict
|
||||
from simplegeneric import generic
|
||||
|
||||
|
||||
#
|
||||
# exceptions
|
||||
#
|
||||
@@ -21,49 +20,58 @@ class JsonEncodeError(Exception):
|
||||
# encoders
|
||||
#
|
||||
|
||||
class BaseEncoder(JSONEncoder):
|
||||
def is_saobject(self, obj):
|
||||
return hasattr(obj, '_sa_class_manager')
|
||||
|
||||
def jsonify(self, obj):
|
||||
return dumps(self.encode(obj))
|
||||
|
||||
def encode(self, obj):
|
||||
def is_saobject(obj):
|
||||
return hasattr(obj, '_sa_class_manager')
|
||||
|
||||
|
||||
class GenericJSON(JSONEncoder):
|
||||
def default(self, obj):
|
||||
import pdb; pdb.set_trace()
|
||||
|
||||
if hasattr(obj, '__json__') and callable(obj.__json__):
|
||||
return obj.__json__()
|
||||
elif isinstance(obj, (date, datetime)):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, Decimal):
|
||||
elif isinstance(obj, (datetime.date, datetime.datetime)):
|
||||
return str(obj)
|
||||
elif isinstance(obj, decimal.Decimal):
|
||||
return float(obj)
|
||||
elif self.is_saobject(obj):
|
||||
elif is_saobject(obj):
|
||||
props = {}
|
||||
for key in obj.__dict__:
|
||||
if not key.startswith('_sa_'):
|
||||
props[key] = getattr(obj, key)
|
||||
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):
|
||||
return obj.mixed()
|
||||
else:
|
||||
try:
|
||||
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
|
||||
|
||||
return JSONEncoder.default(self, obj)
|
||||
|
||||
#
|
||||
# generic function support
|
||||
#
|
||||
|
||||
encoder = BaseEncoder()
|
||||
_default = GenericJSON()
|
||||
|
||||
@generic
|
||||
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):
|
||||
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):
|
||||
# TODO: implement the following:
|
||||
# - get, new, edit, post_delete, get_delete
|
||||
# - implement the "_method" parameter
|
||||
# - see: http://turbogears.org/2.1/docs/modules/tgcontroller.html
|
||||
|
||||
@expose()
|
||||
|
||||
@@ -34,8 +34,7 @@ class JsonRenderer(object):
|
||||
|
||||
def render(self, template_path, namespace):
|
||||
from jsonify import encode
|
||||
result = encode(namespace)
|
||||
return result
|
||||
return encode(namespace)
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -169,6 +169,7 @@ class TestEngines(object):
|
||||
@expose('json')
|
||||
def index(self, argument=None):
|
||||
assert argument == 'value'
|
||||
return dict()
|
||||
|
||||
# arguments should get passed appropriately
|
||||
app = TestApp(Pecan(RootController()))
|
||||
|
||||
@@ -18,7 +18,7 @@ class TestRestController(object):
|
||||
|
||||
@expose('json')
|
||||
def get_all(self):
|
||||
return self.data
|
||||
return dict(items=self.data)
|
||||
|
||||
@expose('json')
|
||||
def post(self, value):
|
||||
@@ -45,7 +45,7 @@ class TestRestController(object):
|
||||
# test get_all
|
||||
r = app.get('/things')
|
||||
assert r.status_int == 200
|
||||
assert r.body == dumps(ThingsController.data)
|
||||
assert r.body == dumps(dict(items=ThingsController.data))
|
||||
|
||||
# test get_one
|
||||
for i, value in enumerate(ThingsController.data):
|
||||
@@ -81,4 +81,4 @@ class TestRestController(object):
|
||||
# make sure it works
|
||||
r = app.get('/things')
|
||||
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