2 __all__
= ['BaseRepresenter', 'SafeRepresenter', 'Representer',
10 datetime_available
= True
12 datetime_available
= False
17 from sets
import Set
as set
21 class RepresenterError(YAMLError
):
24 class BaseRepresenter
:
26 yaml_representers
= {}
27 yaml_multi_representers
= {}
29 def __init__(self
, default_style
=None, default_flow_style
=None):
30 self
.default_style
= default_style
31 self
.default_flow_style
= default_flow_style
32 self
.represented_objects
= {}
34 def represent(self
, data
):
35 node
= self
.represent_data(data
)
37 self
.represented_objects
= {}
42 classobj_type
= type(C
)
43 instance_type
= type(c
)
44 function_type
= type(f
)
45 builtin_function_type
= type(abs)
46 module_type
= type(sys
)
49 def get_classobj_bases(self
, cls
):
51 for base
in cls
.__bases
__:
52 bases
.extend(self
.get_classobj_bases(base
))
55 def represent_data(self
, data
):
56 if self
.ignore_aliases(data
):
60 if alias_key
is not None:
61 if alias_key
in self
.represented_objects
:
62 node
= self
.represented_objects
[alias_key
]
64 raise RepresenterError("recursive objects are not allowed: %r" % data
)
66 self
.represented_objects
[alias_key
] = None
67 data_types
= type(data
).__mro
__
68 if type(data
) is self
.instance_type
:
69 data_types
= self
.get_classobj_bases(data
.__class
__)+list(data_types
)
70 if data_types
[0] in self
.yaml_representers
:
71 node
= self
.yaml_representers
[data_types
[0]](self
, data
)
73 for data_type
in data_types
:
74 if data_type
in self
.yaml_multi_representers
:
75 node
= self
.yaml_multi_representers
[data_type
](self
, data
)
78 if None in self
.yaml_multi_representers
:
79 node
= self
.yaml_multi_representers
[None](self
, data
)
80 elif None in self
.yaml_representers
:
81 node
= self
.yaml_representers
[None](self
, data
)
83 node
= ScalarNode(None, unicode(data
))
84 if alias_key
is not None:
85 self
.represented_objects
[alias_key
] = node
88 def add_representer(cls
, data_type
, representer
):
89 if not 'yaml_representers' in cls
.__dict
__:
90 cls
.yaml_representers
= cls
.yaml_representers
.copy()
91 cls
.yaml_representers
[data_type
] = representer
92 add_representer
= classmethod(add_representer
)
94 def add_multi_representer(cls
, data_type
, representer
):
95 if not 'yaml_multi_representers' in cls
.__dict
__:
96 cls
.yaml_multi_representers
= cls
.yaml_multi_representers
.copy()
97 cls
.yaml_multi_representers
[data_type
] = representer
98 add_multi_representer
= classmethod(add_multi_representer
)
100 def represent_scalar(self
, tag
, value
, style
=None):
102 style
= self
.default_style
103 return ScalarNode(tag
, value
, style
=style
)
105 def represent_sequence(self
, tag
, sequence
, flow_style
=None):
108 for item
in sequence
:
109 node_item
= self
.represent_data(item
)
110 if not (isinstance(node_item
, ScalarNode
) and not node_item
.style
):
112 value
.append(self
.represent_data(item
))
113 if flow_style
is None:
114 flow_style
= self
.default_flow_style
115 if flow_style
is None:
116 flow_style
= best_style
117 return SequenceNode(tag
, value
, flow_style
=flow_style
)
119 def represent_mapping(self
, tag
, mapping
, flow_style
=None):
121 if hasattr(mapping
, 'keys'):
123 for item_key
in mapping
.keys():
124 item_value
= mapping
[item_key
]
125 node_key
= self
.represent_data(item_key
)
126 node_value
= self
.represent_data(item_value
)
127 if not (isinstance(node_key
, ScalarNode
) and not node_key
.style
):
129 if not (isinstance(node_value
, ScalarNode
) and not node_value
.style
):
131 value
[node_key
] = node_value
134 for item_key
, item_value
in mapping
:
135 node_key
= self
.represent_data(item_key
)
136 node_value
= self
.represent_data(item_value
)
137 if not (isinstance(node_key
, ScalarNode
) and not node_key
.style
):
139 if not (isinstance(node_value
, ScalarNode
) and not node_value
.style
):
141 value
.append((node_key
, node_value
))
142 if flow_style
is None:
143 flow_style
= self
.default_flow_style
144 if flow_style
is None:
145 flow_style
= best_style
146 return MappingNode(tag
, value
, flow_style
=flow_style
)
148 def ignore_aliases(self
, data
):
151 class SafeRepresenter(BaseRepresenter
):
153 def ignore_aliases(self
, data
):
154 if data
in [None, ()]:
156 if isinstance(data
, (str, unicode, bool, int, float)):
159 def represent_none(self
, data
):
160 return self
.represent_scalar(u
'tag:yaml.org,2002:null',
163 def represent_str(self
, data
):
167 data
= unicode(data
, 'ascii')
168 tag
= u
'tag:yaml.org,2002:str'
169 except UnicodeDecodeError:
171 data
= unicode(data
, 'utf-8')
172 tag
= u
'tag:yaml.org,2002:str'
173 except UnicodeDecodeError:
174 data
= data
.encode('base64')
175 tag
= u
'tag:yaml.org,2002:binary'
177 return self
.represent_scalar(tag
, data
, style
=style
)
179 def represent_unicode(self
, data
):
180 return self
.represent_scalar(u
'tag:yaml.org,2002:str', data
)
182 def represent_bool(self
, data
):
187 return self
.represent_scalar(u
'tag:yaml.org,2002:bool', value
)
189 def represent_int(self
, data
):
190 return self
.represent_scalar(u
'tag:yaml.org,2002:int', unicode(data
))
192 def represent_long(self
, data
):
193 return self
.represent_scalar(u
'tag:yaml.org,2002:int', unicode(data
))
195 repr_pos_inf
= repr(1e300000
)
196 repr_neg_inf
= repr(-1e300000
)
197 repr_nan
= repr(1e300000
/1e300000
)
199 def represent_float(self
, data
):
200 repr_data
= repr(data
)
201 if repr_data
== self
.repr_pos_inf
:
203 elif repr_data
== self
.repr_neg_inf
:
205 elif repr_data
== self
.repr_nan
:
208 value
= unicode(repr_data
)
209 return self
.represent_scalar(u
'tag:yaml.org,2002:float', value
)
211 def represent_list(self
, data
):
212 pairs
= (len(data
) > 0 and isinstance(data
, list))
215 if not isinstance(item
, tuple) or len(item
) != 2:
219 return self
.represent_sequence(u
'tag:yaml.org,2002:seq', data
)
221 for item_key
, item_value
in data
:
222 value
.append(self
.represent_mapping(u
'tag:yaml.org,2002:map',
223 [(item_key
, item_value
)]))
224 return SequenceNode(u
'tag:yaml.org,2002:pairs', value
)
226 def represent_dict(self
, data
):
227 return self
.represent_mapping(u
'tag:yaml.org,2002:map', data
)
229 def represent_set(self
, data
):
233 return self
.represent_mapping(u
'tag:yaml.org,2002:set', value
)
235 def represent_date(self
, data
):
236 value
= u
'%04d-%02d-%02d' % (data
.year
, data
.month
, data
.day
)
237 return self
.represent_scalar(u
'tag:yaml.org,2002:timestamp', value
)
239 def represent_datetime(self
, data
):
240 value
= u
'%04d-%02d-%02d %02d:%02d:%02d' \
241 % (data
.year
, data
.month
, data
.day
,
242 data
.hour
, data
.minute
, data
.second
)
244 value
+= u
'.' + unicode(data
.microsecond
/1000000.0).split(u
'.')[1]
246 value
+= unicode(data
.utcoffset())
247 return self
.represent_scalar(u
'tag:yaml.org,2002:timestamp', value
)
249 def represent_yaml_object(self
, tag
, data
, cls
, flow_style
=None):
250 if hasattr(data
, '__getstate__'):
251 state
= data
.__getstate
__()
253 state
= data
.__dict
__.copy()
254 if isinstance(state
, dict):
255 state
= state
.items()
257 return self
.represent_mapping(tag
, state
, flow_style
=flow_style
)
259 def represent_undefined(self
, data
):
260 raise RepresenterError("cannot represent an object: %s" % data
)
262 SafeRepresenter
.add_representer(type(None),
263 SafeRepresenter
.represent_none
)
265 SafeRepresenter
.add_representer(str,
266 SafeRepresenter
.represent_str
)
268 SafeRepresenter
.add_representer(unicode,
269 SafeRepresenter
.represent_unicode
)
271 SafeRepresenter
.add_representer(bool,
272 SafeRepresenter
.represent_bool
)
274 SafeRepresenter
.add_representer(int,
275 SafeRepresenter
.represent_int
)
277 SafeRepresenter
.add_representer(long,
278 SafeRepresenter
.represent_long
)
280 SafeRepresenter
.add_representer(float,
281 SafeRepresenter
.represent_float
)
283 SafeRepresenter
.add_representer(list,
284 SafeRepresenter
.represent_list
)
286 SafeRepresenter
.add_representer(tuple,
287 SafeRepresenter
.represent_list
)
289 SafeRepresenter
.add_representer(dict,
290 SafeRepresenter
.represent_dict
)
292 SafeRepresenter
.add_representer(set,
293 SafeRepresenter
.represent_set
)
295 if datetime_available
:
296 SafeRepresenter
.add_representer(datetime
.date
,
297 SafeRepresenter
.represent_date
)
298 SafeRepresenter
.add_representer(datetime
.datetime
,
299 SafeRepresenter
.represent_datetime
)
301 SafeRepresenter
.add_representer(None,
302 SafeRepresenter
.represent_undefined
)
304 class Representer(SafeRepresenter
):
306 def represent_str(self
, data
):
310 data
= unicode(data
, 'ascii')
311 tag
= u
'tag:yaml.org,2002:str'
312 except UnicodeDecodeError:
314 data
= unicode(data
, 'utf-8')
315 tag
= u
'tag:yaml.org,2002:python/str'
316 except UnicodeDecodeError:
317 data
= data
.encode('base64')
318 tag
= u
'tag:yaml.org,2002:binary'
320 return self
.represent_scalar(tag
, data
, style
=style
)
322 def represent_unicode(self
, data
):
326 tag
= u
'tag:yaml.org,2002:python/unicode'
327 except UnicodeEncodeError:
328 tag
= u
'tag:yaml.org,2002:str'
329 return self
.represent_scalar(tag
, data
)
331 def represent_long(self
, data
):
332 tag
= u
'tag:yaml.org,2002:int'
333 if int(data
) is not data
:
334 tag
= u
'tag:yaml.org,2002:python/long'
335 return self
.represent_scalar(tag
, unicode(data
))
337 def represent_complex(self
, data
):
339 data
= u
'%r' % data
.real
340 elif data
.real
== 0.0:
341 data
= u
'%rj' % data
.imag
343 data
= u
'%r+%rj' % (data
.real
, data
.imag
)
345 data
= u
'%r%rj' % (data
.real
, data
.imag
)
346 return self
.represent_scalar(u
'tag:yaml.org,2002:python/complex', data
)
348 def represent_tuple(self
, data
):
349 return self
.represent_sequence(u
'tag:yaml.org,2002:python/tuple', data
)
351 def represent_name(self
, data
):
352 name
= u
'%s.%s' % (data
.__module
__, data
.__name
__)
353 return self
.represent_scalar(u
'tag:yaml.org,2002:python/name:'+name
, u
'')
355 def represent_module(self
, data
):
356 return self
.represent_scalar(
357 u
'tag:yaml.org,2002:python/module:'+data
.__name
__, u
'')
359 def represent_instance(self
, data
):
360 # For instances of classic classes, we use __getinitargs__ and
361 # __getstate__ to serialize the data.
363 # If data.__getinitargs__ exists, the object must be reconstructed by
364 # calling cls(**args), where args is a tuple returned by
365 # __getinitargs__. Otherwise, the cls.__init__ method should never be
366 # called and the class instance is created by instantiating a trivial
367 # class and assigning to the instance's __class__ variable.
369 # If data.__getstate__ exists, it returns the state of the object.
370 # Otherwise, the state of the object is data.__dict__.
372 # We produce either a !!python/object or !!python/object/new node.
373 # If data.__getinitargs__ does not exist and state is a dictionary, we
374 # produce a !!python/object node . Otherwise we produce a
375 # !!python/object/new node.
378 class_name
= u
'%s.%s' % (cls
.__module
__, cls
.__name
__)
381 if hasattr(data
, '__getinitargs__'):
382 args
= list(data
.__getinitargs
__())
383 if hasattr(data
, '__getstate__'):
384 state
= data
.__getstate
__()
386 state
= data
.__dict
__
387 if args
is None and isinstance(state
, dict):
388 state
= state
.items()
390 return self
.represent_mapping(
391 u
'tag:yaml.org,2002:python/object:'+class_name
, state
)
392 if isinstance(state
, dict) and not state
:
393 return self
.represent_sequence(
394 u
'tag:yaml.org,2002:python/object/new:'+class_name
, args
)
398 value
['state'] = state
399 return self
.represent_mapping(
400 u
'tag:yaml.org,2002:python/object/new:'+class_name
, value
)
402 def represent_object(self
, data
):
403 # We use __reduce__ API to save the data. data.__reduce__ returns
404 # a tuple of length 2-5:
405 # (function, args, state, listitems, dictitems)
407 # For reconstructing, we calls function(*args), then set its state,
408 # listitems, and dictitems if they are not None.
410 # A special case is when function.__name__ == '__newobj__'. In this
411 # case we create the object with args[0].__new__(*args).
413 # Another special case is when __reduce__ returns a string - we don't
416 # We produce a !!python/object, !!python/object/new or
417 # !!python/object/apply node.
420 if cls
in copy_reg
.dispatch_table
:
421 reduce = copy_reg
.dispatch_table
[cls
]
422 elif hasattr(data
, '__reduce_ex__'):
423 reduce = data
.__reduce
_ex
__(2)
424 elif hasattr(data
, '__reduce__'):
425 reduce = data
.__reduce
__()
427 raise RepresenterError("cannot represent object: %r" % data
)
428 reduce = (list(reduce)+[None]*5)[:5]
429 function
, args
, state
, listitems
, dictitems
= reduce
433 if listitems
is not None:
434 listitems
= list(listitems
)
435 if dictitems
is not None:
436 dictitems
= dict(dictitems
)
437 if function
.__name
__ == '__newobj__':
440 tag
= u
'tag:yaml.org,2002:python/object/new:'
443 tag
= u
'tag:yaml.org,2002:python/object/apply:'
445 function_name
= u
'%s.%s' % (function
.__module
__, function
.__name
__)
446 if not args
and not listitems
and not dictitems \
447 and isinstance(state
, dict) and newobj
:
448 state
= state
.items()
450 return self
.represent_mapping(
451 u
'tag:yaml.org,2002:python/object:'+function_name
, state
)
452 if not listitems
and not dictitems \
453 and isinstance(state
, dict) and not state
:
454 return self
.represent_sequence(tag
+function_name
, args
)
458 if state
or not isinstance(state
, dict):
459 value
['state'] = state
461 value
['listitems'] = listitems
463 value
['dictitems'] = dictitems
464 return self
.represent_mapping(tag
+function_name
, value
)
466 Representer
.add_representer(str,
467 Representer
.represent_str
)
469 Representer
.add_representer(unicode,
470 Representer
.represent_unicode
)
472 Representer
.add_representer(long,
473 Representer
.represent_long
)
475 Representer
.add_representer(complex,
476 Representer
.represent_complex
)
478 Representer
.add_representer(tuple,
479 Representer
.represent_tuple
)
481 Representer
.add_representer(type,
482 Representer
.represent_name
)
484 Representer
.add_representer(Representer
.classobj_type
,
485 Representer
.represent_name
)
487 Representer
.add_representer(Representer
.function_type
,
488 Representer
.represent_name
)
490 Representer
.add_representer(Representer
.builtin_function_type
,
491 Representer
.represent_name
)
493 Representer
.add_representer(Representer
.module_type
,
494 Representer
.represent_module
)
496 Representer
.add_multi_representer(Representer
.instance_type
,
497 Representer
.represent_instance
)
499 Representer
.add_multi_representer(object,
500 Representer
.represent_object
)