source: mauRepo/MolesManager/trunk/cedaMoles/MolesManager/djencoder.py @ 8608

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/mauRepo/MolesManager/trunk/cedaMoles/MolesManager/djencoder.py@8608
Revision 8608, 4.3 KB checked in by mnagni, 7 years ago (diff)

Fixes

  • a djencoder Windows/linux compatibility
  • a javascript error in case ceda_observation.result.source is null or empty
Line 
1'''
2Created on 9 Feb 2012
3
4@author: mnagni
5'''
6from json.encoder import JSONEncoder
7import logging
8import inspect
9import datetime
10import re
11from decimal import Decimal
12from sqlalchemy.orm.collections import InstrumentedList
13
14class DJEncoder(JSONEncoder):
15    __PATTERN = re.compile('\D\D__*')
16    __PATTERN2 = re.compile('\A\w+__id\Z')
17    log = logging.getLogger('DJEncoder')
18
19    def __init__(self):
20        self.__markers = {}
21        super(DJEncoder, self).__init__() 
22
23    def default(self, obj):
24        mydict = {}
25
26        if isinstance(obj, datetime.datetime):
27            # wanted a simple yield str(o) in the next line,
28            # but that would mean a yield on the line with super(...),
29            # which wouldn't work (see my comment below), so...
30            return str(obj)
31       
32        if isinstance(obj, Decimal):
33            # wanted a simple yield str(o) in the next line,
34            # but that would mean a yield on the line with super(...),
35            # which wouldn't work (see my comment below), so...
36            return str(obj) 
37
38        # Convert objects to a dictionary of their representation
39        try:
40            mydict = { '__module__':obj.__module__,
41                 }
42        except Exception as e:
43            return mydict
44        if obj.__class__.__name__ == 'EnumSymbol':
45            mydict['__class__'] = obj._cls.__name__
46        else:
47            mydict['__class__'] = obj.__class__.__name__
48           
49        if mydict['__module__'].startswith('sqlalchemy'):
50            return mydict
51 
52        for key in obj.__dict__.keys():
53            if not (key.startswith("_") \
54                    or DJEncoder.__PATTERN.match(key) \
55                    or DJEncoder.__PATTERN2.match(key)):
56                mydict.update({key: getattr(obj, key)})
57        getters = list(methodsWithDecorator(type(obj), "property"))
58        for name in getters:
59            if hasattr(obj, name):
60                try:
61                    mydict.update({name: getattr(obj, name)})
62                except Exception as e:
63                    DJEncoder.log.error(e)
64       
65        for key, value in mydict.items():   
66            if value is not None:
67                if (isinstance(value, list) \
68                    or isinstance(value, InstrumentedList)) \
69                        and not isPrimitive(value):
70                    for item in value:
71                        if id(item) in getattr(self, '_DJEncoder__markers'):
72                            mydict.pop(key)
73                            break
74                elif id(value) in getattr(self, '_DJEncoder__markers'):
75                    mydict.pop(key)
76        return mydict
77
78    def iterencode(self, o, _one_shot=True):
79        """Encode the given object and yield each string representation as
80        available. The third parameter, '_one_shot' is required for compatibility with
81        the the windows JSONEncoder implementation.
82
83        For example::
84
85            for chunk in JSONEncoder().iterencode(bigobject):
86                mysocket.write(chunk)
87
88        """
89        if self.check_circular and hasattr(self, '_DJEncoder__markers'):
90            markers = getattr(self, '_DJEncoder__markers')
91        else:
92            markers = None
93        return self._iterencode(o, markers)
94
95def methodsWithDecorator(cls, decoratorName):
96    #if type(cls).__name__ == 'type' or type(cls).__name__ == 'instancemetho':
97    #    return
98    sourcelines = inspect.getsourcelines(cls)[0]
99    for i,line in enumerate(sourcelines):
100        line = line.strip()
101        if line.split('(')[0].strip() == '@'+decoratorName: # leaving a bit out
102            nextLine = sourcelines[i+1]
103            name = nextLine.split('def')[1].split('(')[0].strip()
104            yield(name)
105
106def encodeToJSON(toEncode):
107    return DJEncoder().encode(toEncode)   
108   
109def escapeForJSON(toEscape):
110    res = toEscape.replace('"', '"')
111    res = res.replace("'", "'")       
112    #res = res.replace("'", "'")
113    res = res.replace('\\', '\\')
114    #res = res.replace('(', '(')       
115    #res = res.replace(')', ')')               
116    return res     
117
118def isPrimitive(obj):
119    # Is a simple primitive?
120    return obj is None \
121            or isinstance(obj, str) \
122            or isinstance(obj, int) \
123            or isinstance(obj, unicode) \
124            or isinstance(obj, Decimal)   
Note: See TracBrowser for help on using the repository browser.