Mercurial > piecrust2
comparison piecrust/fastpickle.py @ 459:2ef04e16f0b9
internal: Add support for fake pickling of date/time structures.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 11 Jul 2015 00:44:58 -0700 |
parents | 298f8f46432a |
children | b015e38d4ee1 |
comparison
equal
deleted
inserted
replaced
458:612ed0526afd | 459:2ef04e16f0b9 |
---|---|
9 | 9 |
10 def unpickle(data): | 10 def unpickle(data): |
11 return _unpickle_object(data) | 11 return _unpickle_object(data) |
12 | 12 |
13 | 13 |
14 def _tuple_dispatch(obj, func): | 14 _PICKLING = 0 |
15 _UNPICKLING = 1 | |
16 | |
17 | |
18 def _tuple_dispatch(obj, func, op): | |
15 res = [None] * len(obj) | 19 res = [None] * len(obj) |
16 for i, c in enumerate(obj): | 20 for i, c in enumerate(obj): |
17 res[i] = func(c) | 21 res[i] = func(c) |
18 return tuple(res) | 22 return tuple(res) |
19 | 23 |
20 | 24 |
21 def _list_dispatch(obj, func): | 25 def _list_dispatch(obj, func, op): |
22 res = [None] * len(obj) | 26 res = [None] * len(obj) |
23 for i, c in enumerate(obj): | 27 for i, c in enumerate(obj): |
24 res[i] = func(c) | 28 res[i] = func(c) |
25 return res | 29 return res |
26 | 30 |
27 | 31 |
28 def _dict_dispatch(obj, func): | 32 def _dict_dispatch(obj, func, op): |
29 res = {} | 33 res = {} |
30 for k, v in obj.items(): | 34 for k, v in obj.items(): |
31 res[k] = func(v) | 35 res[k] = func(v) |
32 return res | 36 return res |
33 | 37 |
34 | 38 |
35 def _set_dispatch(obj, func): | 39 def _set_dispatch(obj, func, op): |
36 res = set() | 40 res = set() |
37 for v in obj: | 41 for v in obj: |
38 res.add(func(v)) | 42 res.add(func(v)) |
39 return res | 43 return res |
44 | |
45 | |
46 def _date_convert(obj, op): | |
47 if op == _PICKLING: | |
48 return {'__class__': 'date', | |
49 'year': obj.year, | |
50 'month': obj.month, | |
51 'day': obj.day} | |
52 elif op == _UNPICKLING: | |
53 return datetime.date( | |
54 obj['year'], obj['month'], obj['day']) | |
55 | |
56 | |
57 def _datetime_convert(obj, op): | |
58 if op == _PICKLING: | |
59 return {'__class__': 'datetime', | |
60 'year': obj.year, | |
61 'month': obj.month, | |
62 'day': obj.day, | |
63 'hour': obj.hour, | |
64 'minute': obj.minute, | |
65 'second': obj.second, | |
66 'microsecond': obj.microsecond} | |
67 elif op == _UNPICKLING: | |
68 return datetime.datetime( | |
69 obj['year'], obj['month'], obj['day'], | |
70 obj['hour'], obj['minute'], obj['second'], obj['microsecond']) | |
71 | |
72 | |
73 def _time_convert(obj, op): | |
74 if op == _PICKLING: | |
75 return {'__class__': 'time', | |
76 'hour': obj.hour, | |
77 'minute': obj.minute, | |
78 'second': obj.second, | |
79 'microsecond': obj.microsecond} | |
80 elif op == _UNPICKLING: | |
81 return datetime.time( | |
82 obj['hour'], obj['minute'], obj['second'], obj['microsecond']) | |
40 | 83 |
41 | 84 |
42 _identity_dispatch = object() | 85 _identity_dispatch = object() |
43 | 86 |
44 _type_dispatch = { | 87 _type_dispatch = { |
45 type(None): _identity_dispatch, | 88 type(None): _identity_dispatch, |
46 bool: _identity_dispatch, | 89 bool: _identity_dispatch, |
47 int: _identity_dispatch, | 90 int: _identity_dispatch, |
48 float: _identity_dispatch, | 91 float: _identity_dispatch, |
49 str: _identity_dispatch, | 92 str: _identity_dispatch, |
50 datetime.date: _identity_dispatch, | |
51 datetime.datetime: _identity_dispatch, | |
52 datetime.time: _identity_dispatch, | |
53 tuple: _tuple_dispatch, | 93 tuple: _tuple_dispatch, |
54 list: _list_dispatch, | 94 list: _list_dispatch, |
55 dict: _dict_dispatch, | 95 dict: _dict_dispatch, |
56 collections.OrderedDict: _dict_dispatch, | 96 collections.OrderedDict: _dict_dispatch, |
57 set: _set_dispatch | 97 set: _set_dispatch |
98 } | |
99 | |
100 | |
101 _type_convert = { | |
102 datetime.date: _date_convert, | |
103 datetime.datetime: _datetime_convert, | |
104 datetime.time: _time_convert | |
105 } | |
106 | |
107 | |
108 _type_unconvert = { | |
109 'date': _date_convert, | |
110 'datetime': _datetime_convert, | |
111 'time': _time_convert | |
58 } | 112 } |
59 | 113 |
60 | 114 |
61 def _pickle_object(obj): | 115 def _pickle_object(obj): |
62 t = type(obj) | 116 t = type(obj) |
63 disp = _type_dispatch.get(t) | 117 disp = _type_dispatch.get(t) |
64 if disp is _identity_dispatch: | 118 if disp is _identity_dispatch: |
65 return obj | 119 return obj |
66 | 120 |
67 if disp is not None: | 121 if disp is not None: |
68 return disp(obj, _pickle_object) | 122 return disp(obj, _pickle_object, _PICKLING) |
69 | 123 |
70 if isinstance(obj, Exception): | 124 conv = _type_convert.get(t) |
71 return obj | 125 if conv is not None: |
126 return conv(obj, _PICKLING) | |
72 | 127 |
73 getter = getattr(obj, '__getstate__', None) | 128 getter = getattr(obj, '__getstate__', None) |
74 if getter is not None: | 129 if getter is not None: |
75 state = getter() | 130 state = getter() |
76 else: | 131 else: |
77 state = obj.__dict__ | 132 state = obj.__dict__ |
78 | 133 |
79 state = _dict_dispatch(state, _pickle_object) | 134 state = _dict_dispatch(state, _pickle_object, _PICKLING) |
80 state['__class__'] = obj.__class__.__name__ | 135 state['__class__'] = obj.__class__.__name__ |
81 state['__module__'] = obj.__class__.__module__ | 136 state['__module__'] = obj.__class__.__module__ |
82 | 137 |
83 return state | 138 return state |
84 | 139 |
88 disp = _type_dispatch.get(t) | 143 disp = _type_dispatch.get(t) |
89 if disp is _identity_dispatch: | 144 if disp is _identity_dispatch: |
90 return state | 145 return state |
91 | 146 |
92 if (disp is not None and | 147 if (disp is not None and |
93 (t != dict or '__module__' not in state)): | 148 (t != dict or '__class__' not in state)): |
94 return disp(state, _unpickle_object) | 149 return disp(state, _unpickle_object, _UNPICKLING) |
95 | 150 |
96 if isinstance(state, Exception): | 151 class_name = state['__class__'] |
97 return state | 152 conv = _type_unconvert.get(class_name) |
153 if conv is not None: | |
154 return conv(state, _UNPICKLING) | |
98 | 155 |
99 mod_name = state['__module__'] | 156 mod_name = state['__module__'] |
100 mod = sys.modules[mod_name] | 157 mod = sys.modules[mod_name] |
101 class_name = state['__class__'] | |
102 class_def = getattr(mod, class_name) | 158 class_def = getattr(mod, class_name) |
103 obj = class_def.__new__(class_def) | 159 obj = class_def.__new__(class_def) |
104 | 160 |
105 del state['__class__'] | 161 del state['__class__'] |
106 del state['__module__'] | 162 del state['__module__'] |