from datetime import datetime, date from decimal import Decimal from json import loads from unittest import TestCase from pecan.jsonify import jsonify, encode from pecan import Pecan, expose, request from webtest import TestApp from webob.multidict import MultiDict, UnicodeMultiDict def make_person(): class Person(object): def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name @property def name(self): return '%s %s' % (self.first_name, self.last_name) return Person def test_simple_rule(): Person = make_person() # create a Person instance p = Person('Jonathan', 'LaCour') # register a generic JSON rule @jsonify.when_type(Person) def jsonify_person(obj): return dict( name=obj.name ) # encode the object using our new rule result = loads(encode(p)) assert result['name'] == 'Jonathan LaCour' assert len(result) == 1 class TestJsonify(object): def test_simple_jsonify(self): Person = make_person() # register a generic JSON rule @jsonify.when_type(Person) def jsonify_person(obj): return dict( name=obj.name ) class RootController(object): @expose('json') def index(self): # create a Person instance p = Person('Jonathan', 'LaCour') return p app = TestApp(Pecan(RootController())) r = app.get('/') assert r.status_int == 200 assert loads(r.body) == {'name':'Jonathan LaCour'} class TestJsonifyGenericEncoder(TestCase): def test_json_callable(self): class JsonCallable(object): def __init__(self, arg): self.arg = arg def __json__(self): return {"arg":self.arg} result = encode(JsonCallable('foo')) assert loads(result) == {'arg':'foo'} def test_datetime(self): today = date.today() now = datetime.now() result = encode(today) assert loads(result) == str(today) result = encode(now) assert loads(result) == str(now) def test_decimal(self): # XXX Testing for float match which is inexact d = Decimal('1.1') result = encode(d) assert loads(result) == float(d) def test_multidict(self): md = MultiDict() md.add('arg', 'foo') md.add('arg', 'bar') result = encode(md) assert loads(result) == {'arg': ['foo', 'bar']} def test_fallback_to_builtin_encoder(self): class Foo(object): pass self.assertRaises(TypeError, encode, Foo())