1 | import sys
|
---|
2 | from types import MethodType
|
---|
3 |
|
---|
4 |
|
---|
5 | def JsonSubTypes(subclassnames:list):
|
---|
6 | '''
|
---|
7 | A bit complex mechanism that just sets
|
---|
8 | attribute __jsonsubtypes__ of the annotated class to the tuple
|
---|
9 | (annotatedclass, subclassnames).
|
---|
10 | We store annotatedclass itself also here because derived
|
---|
11 | classes inherit this annotation, while they are NOT having
|
---|
12 | these derived classes. We can check the annotated class to
|
---|
13 | check if this attribute holds.
|
---|
14 |
|
---|
15 | NOTE this annotation must be used only if the referred
|
---|
16 | classes actually extend the annotated class.
|
---|
17 | Failure to do this will lead to runtime errors.
|
---|
18 | We follow the behaviour of jackson here:
|
---|
19 | such classes may still serialize but will fail to deserialize.
|
---|
20 |
|
---|
21 | NOTE2 in jackson the parent-child relations are stored
|
---|
22 | in a separate object. Here we store these in the
|
---|
23 | class object itself. The major advantage is that
|
---|
24 | we can leave inheritance to python inheritance mechanisms.
|
---|
25 | Disadvantage is that this modifies the class,
|
---|
26 | and that this can not handle multiple inheritance situations.
|
---|
27 | Now I have no idea how these should be handled anyway,
|
---|
28 | neither do I think jackson would support that as multiple
|
---|
29 | inheritance is not part of java,
|
---|
30 | so probably not much is currently lost here.
|
---|
31 |
|
---|
32 | @param subclassnames a list of full class names of subclasses.
|
---|
33 | '''
|
---|
34 | if not isinstance(subclassnames, list):
|
---|
35 | raise ValueError("JSonSubTypes requires list of classes")
|
---|
36 | # we can't check class existence here, as subclasses
|
---|
37 | # will not yet exist as they extend superclass.
|
---|
38 |
|
---|
39 |
|
---|
40 | def doAnnotate(annotatedclass):
|
---|
41 | '''
|
---|
42 | This function is applied to the annotated class.
|
---|
43 | It just adds an attribute __jsonsubtypes__ to the class
|
---|
44 | with the annotation data
|
---|
45 | '''
|
---|
46 | setattr(annotatedclass,'__jsonsubtypes__', (annotatedclass, subclassnames))
|
---|
47 | return annotatedclass
|
---|
48 |
|
---|
49 | # we return doAnnotate as result of the function.
|
---|
50 | # that way we can apply that function to the next argument
|
---|
51 | # which is the annotatedclass
|
---|
52 | return doAnnotate
|
---|
53 |
|
---|
54 |
|
---|
55 | def getSubTypes(clas) -> tuple:
|
---|
56 | '''
|
---|
57 | @return (annotatedclass, [subclassId])
|
---|
58 | tuple with the full annotated class object, and the list of ClassIds
|
---|
59 | of the registered subclasses of the annotated class.
|
---|
60 | returns None if the class has no subtypes registered.
|
---|
61 | Note that this annotation is inherited - all derived classes
|
---|
62 | inherit the same annotation.
|
---|
63 | '''
|
---|
64 | return getattr(clas, '__jsonsubtypes__',None)
|
---|