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

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

Complete - # 22554: "Remove the ""FollowSymLinks"""
 http://team.ceda.ac.uk/trac/ceda/ticket/22554
Incomplete - # 22563: Circular reference detected in citest dataset
 http://team.ceda.ac.uk/trac/ceda/ticket/22563

RevLine 
[8088]1'''
2Created on 9 Feb 2012
3
4@author: mnagni
5'''
6from json.encoder import JSONEncoder
[8221]7import logging
[8480]8import inspect
[8599]9import datetime
10import re
11from decimal import Decimal
12from inspect import isclass
13from sqlalchemy.orm.collections import InstrumentedList
[8088]14
15class DJEncoder(JSONEncoder):
[8143]16
[8599]17    __PATTERN = re.compile('\D\D__*')
18    __PATTERN2 = re.compile('\A\w+__id\Z')
[8221]19    log = logging.getLogger('DJEncoder')
[8599]20
[8088]21    def __init__(self):
22        self.__markers = {}
[8599]23        super(DJEncoder, self).__init__() 
24
25    def default(self, obj):
26        d = {}
27
28        if isinstance(obj, datetime.datetime):
29            # wanted a simple yield str(o) in the next line,
30            # but that would mean a yield on the line with super(...),
31            # which wouldn't work (see my comment below), so...
32            return str(obj)
[8143]33       
[8599]34        if isinstance(obj, Decimal):
35            # wanted a simple yield str(o) in the next line,
36            # but that would mean a yield on the line with super(...),
37            # which wouldn't work (see my comment below), so...
38            return str(obj) 
[8143]39
[8088]40        # Convert objects to a dictionary of their representation
[8569]41        try:
42            d = { '__module__':obj.__module__,
43                 }
44        except Exception as e:
45            print e
46            return d
[8088]47        if obj.__class__.__name__ == 'EnumSymbol':
48            d['__class__'] = obj._cls.__name__
49        else:
50            d['__class__'] = obj.__class__.__name__
51           
52        if d['__module__'].startswith('sqlalchemy'):
53            return d
[8599]54 
55        for key in obj.__dict__.keys():
56            if not (key.startswith("_") \
57                    or DJEncoder.__PATTERN.match(key) \
58                    or DJEncoder.__PATTERN2.match(key)):
59                d.update({key: getattr(obj, key)})
[8088]60        getters = list(methodsWithDecorator(type(obj), "property"))
61        for name in getters:
[8599]62            if hasattr(obj, name):
63                try:
64                    d.update({name: getattr(obj, name)})
65                except Exception as e:
66                    DJEncoder.log.error(e)
[8088]67       
68        for key, value in d.items():
[8599]69            if value is not None:
70                if isinstance(value, list) or isinstance(value, InstrumentedList):
71                    for item in value:
72                        if id(item) in getattr(self, '_DJEncoder__markers'):
73                            d.pop(key)
74                            break
75                elif id(value) in getattr(self, '_DJEncoder__markers'):
76                    d.pop(key)
[8200]77        return d
[8426]78
[8599]79    def iterencode(self, o):
80        """Encode the given object and yield each string representation as
81        available.
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
[8480]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
[8426]106def encodeToJSON(toEncode):
[8433]107    return DJEncoder().encode(toEncode)   
[8200]108   
[8426]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         
Note: See TracBrowser for help on using the repository browser.