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

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

djencoder fix for Windows machines

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