source: pyson/test/ObjectMapperTest.py@ 1350

Last change on this file since 1350 was 1144, checked in by wouter, 2 months ago

#366 added test showing the issue

File size: 22.6 KB
RevLine 
[134]1
[194]2from abc import ABC
[162]3from datetime import datetime
[194]4from decimal import Decimal
[228]5import json
[194]6import re
[162]7import sys, traceback
[239]8from typing import Dict, List, Set, Any, Union, Optional
[194]9import unittest
10from uuid import uuid4, UUID
[162]11
[172]12from pyson.Deserializer import Deserializer
13from pyson.JsonDeserialize import JsonDeserialize
[162]14from pyson.JsonGetter import JsonGetter
[141]15from pyson.JsonSubTypes import JsonSubTypes
[162]16from pyson.JsonTypeInfo import Id, As
[141]17from pyson.JsonTypeInfo import JsonTypeInfo
[161]18from pyson.JsonValue import JsonValue
[162]19from pyson.ObjectMapper import ObjectMapper
[311]20from uri.uri import URI
[134]21
[162]22
[306]23def errorsEqual( e1, e2):
24 return e1==e2 or \
25 (e1.__class__==e2.__class__ and
26 e1.args == e2.args and
27 errorsEqual(e1.__cause__, e2.__cause__))
28
[134]29class Props:
30 '''
31 compound class with properties, used for testing
32 '''
33 def __init__(self, age:int, name:str):
34 if age<0:
35 raise ValueError("age must be >0, got "+str(age))
36 self._age=age
37 self._name=name;
38 def __str__(self):
39 return self._name+","+str(self._age)
40 def getage(self):
41 return self._age
42 def getname(self):
43 return self._name
44 def __eq__(self, other):
45 return isinstance(other, self.__class__) and \
46 self._name==other._name and self._age==other._age
47
48@JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
49class Simple:
50 def __init__(self, a:int):
[228]51 self._a=a
[134]52 def geta(self)->int:
53 return self._a
54 def __eq__(self, other):
55 return isinstance(other, self.__class__) and \
56 self._a==other._a
57 def __str__(self):
58 return self._name+","+str(self._a)
59
60
61class SimpleWithHash(Simple):
62 def __hash__(self):
63 return hash(self.geta())
64
65# define abstract root class
66# These need to be reachable globally for reference
67@JsonSubTypes(["test.ObjectMapperTest.Bear"])
68@JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
69class Animal:
70 pass
71
72
73class Bear(Animal):
74 def __init__(self, props:Props):
75 self._props=props
76
77 def __str__(self):
78 return "Bear["+str(self._props)+"]"
79
80 def getprops(self):
81 return self._props
82 def __eq__(self, other):
83 return isinstance(other, self.__class__) and \
84 self._props==other._props
85
86
[143]87
[154]88# A wrongly configured type, you must add
89#@JsonSubTypes(["test.ObjectMapperTest.BadSubclass"])
[143]90class BadSuperclassMissingTypeInfo:
91 pass
92
93class BadSubclass(BadSuperclassMissingTypeInfo):
94 def __init__(self, a:int):
95 self._a=a
96 def geta(self)->int:
97 return self._a
98 def __eq__(self, other):
99 return isinstance(other, self.__class__) and \
100 self._a==other._a
101 def __str__(self):
102 return self._name+","+str(self._a)
103
104#module instead of class.
105@JsonSubTypes(["test.ObjectMapperTest"])
106@JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
107class BadSuperclassModuleInstead:
108 pass
109
[144]110@JsonSubTypes(["test.ObjectMapperTest.AbstractBear"])
111@JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
112class AbstractAnimal(ABC):
113 pass
114
115class AbstractBear(AbstractAnimal):
116 def __init__(self, props:Props):
117 self._props=props
118
119 def __str__(self):
120 return "Bear["+str(self._props)+"]"
121
122 def getprops(self):
123 return self._props
124 def __eq__(self, other):
125 return isinstance(other, self.__class__) and \
126 self._props==other._props
127
[143]128
[134]129# our parser supports non-primitive keys but python dict dont.
130# therefore the following fails even before we can start testing our code...
131# we need to create a hashable dict to get around ths
132class mydict(dict):
133 def __hash__(self, *args, **kwargs):
134 return 1
135
136
[161]137# for testing @JsonValue
138class Snare:
139 def __init__(self, value:int):
140 self._a=value
141 @JsonValue()
142 def getValue(self):
143 return self._a
144 def __eq__(self, other):
145 return isinstance(other, self.__class__) and self._a==other._a
146
147class ContainsSnare:
148 def __init__(self, snare:Snare):
149 self._snare=snare
150 def getSnare(self):
151 return self._snare
152 def __eq__(self, other):
153 return isinstance(other, self.__class__) and self._snare==other._snare
154
[239]155class OptionalVal:
156 def __init__(self, value:Optional[str]):
157 self._a=value
158 def getValue(self)->Optional[str]:
159 return self._a
160 def __eq__(self, other):
161 return isinstance(other, self.__class__) and self._a==other._a
[161]162
[239]163
[571]164class MyDeserializer(Deserializer):
165 def deserialize(self, data:object, clas: object) -> "Custom":
166 if isinstance(data, float):
167 return Custom(Decimal(str(data)))
168 return Custom(data)
169
170
171@JsonDeserialize(MyDeserializer)
172class Custom:
[172]173 def __init__(self, value:Any):
174 self._a=value
175 @JsonValue()
176 def getValue(self):
177 return self._a
178 def __eq__(self, other):
179 return isinstance(other, self.__class__) and \
180 self._a==other._a
[161]181
[172]182
[176]183class DefaultOne:
184 '''
185 Has default value
186 '''
187 def __init__(self, value:int=1):
188 self._a=value
189 def getValue(self):
190 return self._a
191 def __eq__(self, other):
192 return isinstance(other, self.__class__) and \
193 self._a==other._a
[172]194
[178]195class DefaultNone(ABC):
196 '''
197 Has default value
198 '''
199 def __init__(self, value:Snare=None):
200 self._a=value
201 def getValue(self)->Snare:
202 return self._a
203 def __eq__(self, other):
204 return isinstance(other, self.__class__) and \
205 self._a==other._a
[172]206
[182]207class WithUnion(ABC):
208 '''
209 Has default value
210 '''
211 def __init__(self, value:Union[Snare,None]=None):
212 self._a=value
213 def getValue(self)->Union[Snare,None]:
214 return self._a
215 def __eq__(self, other):
216 return isinstance(other, self.__class__) and \
217 self._a==other._a
[172]218
[178]219
[306]220exception=ValueError("some error")
221exception.__cause__=ArithmeticError("div zero")
222exceptionjson = {"cause":{"cause":None, "message":"div zero", "stackTrace":[]},
223 "stackTrace":[],"message":"some error"}
[182]224
[1140]225class FrozenTest(ABC):
226 def __init__(self, value:Set[str]):
227 self._value=frozenset(value)
228 def getValue(self) -> Set[str]:
229 return self._value
[306]230
231
[1144]232class StringContainer(ABC):
233 def __init__(self, val:str):
234 self._val = val
235 @JsonValue()
236 def getValue(self) -> str:
237 return self._val
[306]238
239
240
241
242
243
244
245
246
247
248
[1144]249
250
[134]251class ObjectMapperTest(unittest.TestCase):
[162]252 '''
253 Test a lot of back-and-forth cases.
254 FIXME Can we make this a parameterized test?
255 '''
[172]256 pyson=ObjectMapper()
257
[162]258
[134]259 def testPrimitives(self):
260
[172]261 res=self.pyson.parse(3, int)
[192]262 self.assertEqual(3, res)
[134]263
264
265 # this throws correct,
[172]266 self.assertRaises(ValueError, lambda:self.pyson.parse(3, str))
[134]267
268 # this throws correct,
[172]269 self.assertRaises(ValueError, lambda:self.pyson.parse("ja", int))
[134]270
271 #DEMO with nested classes of different types.
[172]272 res=self.pyson.parse('three', str)
[134]273 print(res, type(res))
274
[172]275 self.pyson.parse(3.0, float)
276 self.pyson.parse(3.1, float)
277 self.pyson.parse(3j, complex)
278 self.pyson.parse(range(6), range)
279 self.pyson.parse(True, bool)
280 self.pyson.parse(False, bool)
281 self.pyson.parse(b"Hello", bytes)
282 self.pyson.parse(bytearray(b'\x00\x00\x00\x01'), bytearray)
[134]283
[165]284 jsonlh = "http://localhost/"
285 urilh = URI(jsonlh)
[192]286 self.assertEqual(urilh, self.pyson.parse(jsonlh, URI))
[165]287
288 #WARNING python is cheating us. equals succeeds but the type may be wrong!!
289 # python says URI("hello")=="hello"
[192]290 self.assertEqual(jsonlh, self.pyson.toJson(urilh))
291 self.assertEqual(str, type(self.pyson.toJson(urilh)))
[227]292
293 def testNone(self):
294 self.assertEqual(None, self.pyson.toJson(None))
295 self.assertEqual('null', json.dumps(None))
296 self.assertEqual(None, json.loads('null'))
297 self.assertEqual(None, self.pyson.parse(None, Any))
[193]298
299 def testDecimal(self):
[192]300 self.assertEqual(1.1, self.pyson.toJson(Decimal('1.1')))
301 self.assertEqual(Decimal('1.1'), self.pyson.parse(1.1, Decimal))
[193]302
303 self.assertEqual(Decimal('1200'), self.pyson.parse(1200, Decimal))
304 v=self.pyson.toJson(Decimal('1200'))
[194]305 self. assertEqual(1200, v)
[171]306
[194]307 # 3/40000 triggers scientific notation in python
308 v=self.pyson.toJson(Decimal(3/40000.))
309 print(str(v)) # this will print "7.5e-05"
[213]310 # this notation is allowed in json file notation too.
[194]311
[193]312 def testDecimalSerializationType(self):
313 v=self.pyson.toJson(Decimal('1200'))
[301]314 self.assertEqual(int, type(v))
[193]315
316 v=self.pyson.toJson(Decimal('1200.1'))
[301]317 self.assertEqual(float, type(v))
[193]318
319
[189]320 def testPrimitiveUUID(self):
321 id=uuid4()
[192]322 self.assertEqual(id, self.pyson.parse(str(id), UUID))
[189]323 self.assertEqual(str(id), self.pyson.toJson(id))
[134]324
325 def testProps(self):
326 propsjson={'age': 10, 'name': 'pietje'}
327 props=Props(10, "pietje")
[192]328 self.assertEqual(propsjson,self.pyson.toJson(props))
329 self.assertEqual(props, self.pyson.parse(propsjson, Props))
[134]330
331 def testParseDeepError(self):
332 propsjson={'age': 10, 'name': 12}
333 try:
[172]334 self.pyson.parse(propsjson, Props)
[134]335 raise AssertionError("parser did not throw")
336 except ValueError as e:
337 # we catch this to assure the exception contains
338 # both top error and details.
339 print("received error "+str(e))
340 self.assertTrue(str(e).find("Error parsing"))
341 self.assertTrue(str(e).find("ValueError"))
342 self.assertTrue(str(e).find("expected"))
343
344
345 def testEmpty(self):
346
347 class EmptyClass:
348 def __init__(self):
349 pass
350 def __eq__(self, other):
351 return isinstance(other, self.__class__)
352
353 obj=EmptyClass()
[172]354 print(self.pyson.toJson(obj))
355 res=self.pyson.parse({}, EmptyClass)
[134]356 self.assertEqual(obj, res)
357
358 def testSubType(self):
359
360 class Cat():
361 def __init__(self, props:Props):
362 self._props=props
363
364 def __str__(self):
365 return "Cat["+str(self._props)+"]"
366
367 def getprops(self):
368 return self._props
369
370 obj=Cat(Props(1,'bruno'))
[172]371 print(self.pyson.toJson(obj))
[134]372
373
374 bson={'props':{'age':1, 'name':'bruno'}}
[172]375 res=self.pyson.parse(bson, Cat)
[134]376 print(res, type(res))
[192]377 self.assertEqual(type(res.getprops()), Props)
[134]378
[155]379 def testDeserializeNoSuchField(self):
380 # Bear has a 'props' field, bot 'b'
[172]381 self.assertRaises(ValueError, lambda:self.pyson.parse({'b':1}, Props))
382 #self.pyson.parse({'b':1}, Props)
[155]383
[134]384 def testInheritance(self):
385 obj=Bear(Props(1,'bruno'))
[172]386 res=self.pyson.toJson(obj)
[134]387 print("result:"+str(res))
388 bson={'Bear': {'props': {'age': 1, 'name': 'bruno'}}}
[192]389 self.assertEqual(bson, res)
[134]390
[172]391 res=self.pyson.parse(bson, Animal)
[134]392 print("Deserialized an Animal! -->"+str(res))
393 self. assertEqual(obj, res)
394
[144]395 def testAbcInheritance(self):
396 obj=AbstractBear(Props(1,'bruno'))
[172]397 res=self.pyson.toJson(obj)
[144]398 print("result:"+str(res))
399 bson={'AbstractBear': {'props': {'age': 1, 'name': 'bruno'}}}
[192]400 self.assertEqual(bson, res)
[144]401
[172]402 res=self.pyson.parse(bson, AbstractAnimal)
[144]403 print("Deserialized an Animal! -->"+str(res))
404 self. assertEqual(obj, res)
405
406
407
[134]408 def testUntypedList(self):
409 class Prim:
410 def __init__(self, a:list):
411 self._a=a
412 def geta(self)->list:
413 return self._a
[164]414 def __eq__(self, other):
415 return isinstance(other, self.__class__) and self._a==other._a
[134]416
417 obj=Prim([1,2])
418 objson = {'a':[1,2]}
419
[172]420 self.assertEqual(objson, self.pyson.toJson(obj))
421 self.assertEqual(obj, self.pyson.parse(objson, Prim))
[134]422
[145]423 def testDateTime(self):
424 objson = 1000120 # 1000.12ms since 1970
425 obj=datetime.fromtimestamp(objson/1000.0);
[172]426 self.assertEqual(objson, self.pyson.toJson(obj))
427 self.assertEqual(obj, self.pyson.parse(objson, datetime))
[311]428
429 def testDateTime2(self):
[312]430 for t in range(999, 1010):
431 obj=datetime.fromtimestamp(t/1000.)
432 self.assertEqual(t, self.pyson.toJson(obj))
[145]433
434
[134]435 def testTypedList(self):
436 '''
437 deserializes typed list contained in another object
438 '''
439 class Prim:
440 def __init__(self, a:List[str]):
441 self._a=a
442 def geta(self)->List[str]:
443 return self._a
444 def __eq__(self, other):
445 return isinstance(other, self.__class__) and \
446 self._a==other._a
447
448 obj=Prim(["x","y"])
449 objson = {'a':["x","y"]}
450
[172]451 self.assertEqual(objson, self.pyson.toJson(obj))
452 self.assertEqual(obj, self.pyson.parse(objson, Prim))
[134]453
454 def testTypedListDirect(self):
455 '''
456 deserializes typed list directly
457 '''
458
459 obj=["x","y"]
460 objson = ["x","y"]
461
[172]462 self.assertEqual(objson, self.pyson.toJson(obj))
463 self.assertEqual(obj, self.pyson.parse(objson, List[str]))
[158]464
465 def testMixedDict(self):
466 obj={'a':1, 'b':'blabla'}
[134]467
[158]468 # primitive types, should not be changed
[172]469 self.assertEqual(obj, self.pyson.toJson(obj))
470 self.assertEqual(obj, self.pyson.parse(obj, Dict[Any,Any]))
[158]471
[134]472 def testTypedListOfObjMissingAnnotation(self):
473 class Prim:
474 def __init__(self, a:int):
475 self._a=a
476 def geta(self)->int:
477 return self._a
478 def __eq__(self, other):
479 return isinstance(other, self.__class__) and \
480 self._a==other._a
481 obj=[Prim(1),Prim(3)]
482 objson = [{"Prim":{'a':1}},{"Prim":{'a':3}}]
[170]483
484 # SHOULD WE CHECK THIS?
[172]485 #self.assertRaises(ValueError, lambda:self.pyson.toJson(obj))
[134]486 # object misses annotation, therefore this will try to parse
487 # Prim objects without header here.
[172]488 self.assertRaises(ValueError, lambda:self.pyson.parse(objson, List[Prim]))
[134]489
490 def testTypedListOfObj(self):
491 @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
492 class Prim:
493 def __init__(self, a:int):
494 self._a=a
495 def geta(self)->int:
496 return self._a
497 def __eq__(self, other):
498 return isinstance(other, self.__class__) and \
499 self._a==other._a
500
501 obj=[Prim(1),Prim(3)]
502 objson = [{"Prim":{'a':1}},{"Prim":{'a':3}}]
[172]503 self.assertEqual(objson, self.pyson.toJson(obj))
504 self.assertEqual(obj, self.pyson.parse(objson, List[Prim]))
[134]505
506 def testTypedSetOfObj(self):
507 @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
508 class Prim:
509 def __init__(self, a:int):
510 self._a=a
511 def geta(self)->int:
512 return self._a
513 def __eq__(self, other):
514 return isinstance(other, self.__class__) and \
515 self._a==other._a
516
517 obj=set([SimpleWithHash(1),SimpleWithHash(3)])
518 objson = [{"SimpleWithHash":{'a':1}},{"SimpleWithHash":{'a':3}}]
[172]519 self.assertEqual(objson, self.pyson.toJson(obj))
520 parsedobj=self.pyson.parse(objson, Set[SimpleWithHash])
[134]521 self.assertEqual(obj, parsedobj)
522
523
524 def testExpectListButGiveDict(self):
525 @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
526 class Prim:
527 def __init__(self, a:int):
528 self._a=a
529 def geta(self)->int:
530 return self._a
531 def __eq__(self, other):
532 return isinstance(other, self.__class__) and \
533 self._a==other._a
534
535 objson = { 'a':{"Prim":{'a':1}},'c':{"Prim":{'a':3}}}
536 # we request List but obj is a dict.
[172]537 self.assertRaises(ValueError,lambda:self.pyson.parse(objson, List[Prim]))
[134]538
539 def testSerializeDict(self):
540 obj={'a':Simple(1),'c':Simple(3)}
541 objson = { 'a':{"Simple":{'a':1}},'c':{"Simple":{'a':3}}}
[172]542 self.assertEqual(objson, self.pyson.toJson(obj))
[134]543
544
545 def testTypedDictOfObj(self):
546 obj={'a':Simple(1),'c':Simple(3)}
547 objson = { 'a':{"Simple":{'a':1}},'c':{"Simple":{'a':3}}}
[172]548 self.assertEqual(obj, self.pyson.parse(objson, Dict[str,Simple]))
[134]549 print("deserialized obj"+str(objson)+"="+str(obj))
550
551 def testTypedDictSimpleKey(self):
552 key=mydict()
553 key["Simple"]={'a':1}
554 # simple is not hashable
555 objson = { key : 'a' }
[172]556 self.assertRaises(ValueError,lambda:self.pyson.parse(objson, Dict[Simple,str]))
[134]557
558 def testTypedDictSimpleKeyHashable(self):
[570]559 # key is now an object. Pyson has special provision to handle these.
560 # the object is serialized to a string
[134]561 obj={SimpleWithHash(1):'a'}
[570]562 objson={"{\"SimpleWithHash\": {\"a\": 1}}": "a"}
563
564 print("to obj:"+json.dumps(self.pyson.toJson(obj)))
565 self.assertEqual(objson,self.pyson.toJson(obj))
566
[172]567 self.assertEqual(obj, self.pyson.parse(objson, Dict[SimpleWithHash,str]))
[134]568
[143]569 def testDeserializeBadSubclass(self):
570 objson= { 'BadSubclass':{ 'a':1}}
571 # FIXME the error message is poor in this case.
[172]572 self.assertRaises(ValueError,lambda:self.pyson.parse(objson, BadSuperclassMissingTypeInfo))
[143]573
574
575 def testModuleInsteadOfClassAsSubclasses(self):
576 objson= { 'BadSubclass':{ 'a':1}}
[1080]577 self.assertRaises(TypeError,lambda:self.pyson.parse(objson, BadSuperclassModuleInstead))
[143]578
579
580
[151]581 def testJsonGetter(self):
582 class Getter:
583 def __init__(self, a:int):
584 self._a=a
585 @JsonGetter("a")
586 def getValue(self):
587 return self._a
588 def __eq__(self, other):
589 return isinstance(other, self.__class__) and \
590 self._a==other._a
591
592 getter=Getter(17)
593 objson={'a':17}
[172]594 self.assertEqual(objson, self.pyson.toJson(getter))
595 self.assertEqual(getter, self.pyson.parse(objson, Getter))
[151]596
[154]597 def testGetterIgnoresCase(self):
598 class Getter:
599 def __init__(self, value:int):
600 self._a=value
601 def getValue(self):
602 return self._a
603 def __eq__(self, other):
604 return isinstance(other, self.__class__) and \
605 self._a==other._a
606
607 getter=Getter(17)
608 objson={'value':17}
[172]609 self.assertEqual(objson, self.pyson.toJson(getter))
610 self.assertEqual(getter, self.pyson.parse(objson, Getter))
[154]611
[161]612
613 def testJsonValue(self):
614 getter=Snare(17)
615 objson=17
[172]616 print(self.pyson.toJson(getter))
617 self.assertEqual(objson, self.pyson.toJson(getter))
[228]618 val:Snare = self.pyson.parse(objson, Snare)
619 self.assertEqual(getter, val)
[161]620
621
622 def testJsonValueAsPart(self):
623 csnare=ContainsSnare(Snare(18))
624 objson={"snare":18}
[172]625 print(self.pyson.toJson(csnare))
626 self.assertEqual(objson, self.pyson.toJson(csnare))
627 self.assertEqual(csnare, self.pyson.parse(objson, ContainsSnare))
[161]628
629
[165]630 def testUriJsonValue(self):
631 class UriJson:
632 def __init__(self, value:URI):
633 self._a=value
634 @JsonValue()
635 def getValue(self):
636 return self._a
637 def __eq__(self, other):
638 return isinstance(other, self.__class__) and \
639 self._a==other._a
640
641 objson="http://test/"
642 obj=UriJson(URI(objson))
[172]643 self.assertEqual(objson, self.pyson.toJson(obj))
644 self.assertEqual(obj, self.pyson.parse(objson, UriJson))
[170]645
646
647 def testJsonValueInList(self):
648 snare1=Snare(1)
649 snare2=Snare(2)
650 snareList = [snare1, snare2]
[172]651 self.assertEqual([1, 2],self.pyson.toJson(snareList))
652 self.assertEqual(snareList, self.pyson.parse([1,2], List[Snare]))
653
654
655
656
657 def testJsonDeserializerAnnotation(self):
658 self.assertEqual(Custom(Decimal(1)), self.pyson.parse(1.0, Custom))
659 self.assertEqual(1.0, self.pyson.toJson(Custom(Decimal(1))))
660 self.assertEqual(Custom('bla'), self.pyson.parse('bla', Custom))
661 self.assertEqual('bla', self.pyson.toJson(Custom('bla')))
[176]662
663
664 def testDeserializeMissingValue(self):
665 a=DefaultOne()
[192]666 self.assertEqual(1, a.getValue())
667 self.assertEqual(a, self.pyson.parse({}, DefaultOne))
[178]668
669
670 def testDeserializeDefaultNone(self):
671 a=DefaultNone()
[192]672 self.assertEqual(None, a.getValue())
673 self.assertEqual(a, self.pyson.parse({}, DefaultNone))
[182]674
675 def testDeserializeUnion(self):
676 a=WithUnion(None)
[192]677 self.assertEqual(None, a.getValue())
678 self.assertEqual(a, self.pyson.parse({}, WithUnion))
[183]679
680 def testDeserializeOptional(self):
681 NoneType=type(None)
682 defaultone= self.pyson.parse(None, Union[DefaultOne, NoneType])
[192]683 self.assertEqual(None, defaultone)
[239]684 self.assertEqual(OptionalVal(None), self.pyson.parse({"value":None}, OptionalVal))
685
686 def testSerializeOptional(self):
687 val=OptionalVal(None)
688 self.assertEqual({"value":None}, self.pyson.toJson(val))
[306]689
690 def testSerializeExc(self):
691 self.assertEqual(exceptionjson, self.pyson.toJson(exception))
692 self.assertEqual(exceptionjson, self.pyson.toJson(exception))
693
694 def testDeserializeExc(self):
695 self.assertTrue(errorsEqual(ValueError("err"),
696 self.pyson.parse({'message':'err'}, ValueError)))
697
698 self.assertTrue(errorsEqual(Exception("err"),
699 self.pyson.parse({'message':'err'}, Exception)))
700 self.assertEquals(None, self.pyson.parse(None, Optional[Exception]))
701
702 e=self.pyson.parse(exceptionjson, Optional[ValueError])
703 print(e)
704 expected=ValueError("some error")
705 expected.__cause__=Exception("div zero")
706
707 errorsEqual(expected, e)
[1140]708
709 def testFrozenSerializer(self):
710 data = FrozenTest(set([1,2,3]))
711 self.assertEquals({'value': [1, 2, 3]}, self.pyson.toJson(data))
712
[1144]713 def testDictWithJsonValueAsKey(self):
714 d:Dict[StringContainer, str]={StringContainer("test"):"value"}
715 self.assertEquals({"test":"value"}, self.pyson.toJson(d))
[1140]716
717
Note: See TracBrowser for help on using the repository browser.