Fix hooke.util.yaml handling of assorted numpy.dtypes.
[hooke.git] / hooke / util / yaml.py
1 # Copyright
2
3 """Add representers to YAML to support Hooke.
4
5 Without introspection, YAML cannot decide how to save some
6 objects.  By refusing to save these objects, we obviously loose
7 that information, so make sure the things you drop are either
8 stored somewhere else or not important.
9
10 >>> import yaml
11 >>> a = numpy.array([1,2,3])
12 >>> print yaml.dump(a)
13 null
14 ...
15 <BLANKLINE>
16
17 The default behavior is to crash.
18
19 >>> yaml.Dumper.yaml_representers.pop(numpy.ndarray)  # doctest: +ELLIPSIS
20 <function ndarray_representer at 0x...>
21 >>> print yaml.dump(a)
22 Traceback (most recent call last):
23   ...
24     if data in [None, ()]:
25 TypeError: data type not understood
26
27 Restore the representer for future tests.
28
29 >>> yaml.add_representer(numpy.ndarray, ndarray_representer)
30 """
31
32 from __future__ import absolute_import
33 import sys
34
35 import numpy
36 import yaml #from yaml.representer import Representer
37
38 from ..curve import Data
39
40
41 if False: # YAML dump debugging code
42     """To help isolate data types etc. that give YAML problems.
43
44     This is usually caused by external C modules (e.g. numpy) that
45     define new types (e.g. numpy.ndarray) which YAML cannot inspect.
46     """
47     def ignore_aliases(data):
48         print data, repr(data), type(data), repr(type(data))
49         sys.stdout.flush()
50         if data in [None, ()]:
51             return True
52         if isinstance(data, (str, unicode, bool, int, float)):
53             return True
54     yaml.representer.SafeRepresenter.ignore_aliases = staticmethod(
55         ignore_aliases)
56 else:
57     # Avoid error with
58     #   numpy.dtype(numpy.int32) in [None, ()]
59     # See
60     #   http://projects.scipy.org/numpy/ticket/1001
61     def ignore_aliases(data):
62         try:
63             if data in [None, ()]:
64                 return True
65             if isinstance(data, (str, unicode, bool, int, float)):
66                 return True
67         except TypeError, e:
68             pass
69     yaml.representer.SafeRepresenter.ignore_aliases = staticmethod(
70         ignore_aliases)
71
72
73 def none_representer(dumper, data):
74     return dumper.represent_none(None)
75 yaml.add_representer(numpy.ndarray, none_representer)
76 yaml.add_representer(numpy.dtype, none_representer)
77
78 def bool_representer(dumper, data):
79     return dumper.represent_bool(data)
80 yaml.add_representer(numpy.bool_, bool_representer)
81
82 def int_representer(dumper, data):
83     return dumper.represent_int(data)
84 yaml.add_representer(numpy.int32, int_representer)
85 yaml.add_representer(numpy.dtype(numpy.int32), int_representer)
86
87 def long_representer(dumper, data):
88     return dumper.represent_long(data)
89 yaml.add_representer(numpy.int64, int_representer)
90
91 def float_representer(dumper, data):
92     return dumper.represent_float(data)
93 yaml.add_representer(numpy.float32, float_representer)
94 yaml.add_representer(numpy.float64, float_representer)
95
96 def data_representer(dumper, data):
97     info = dict(data.info)
98     print 'KEYS', info.keys()
99     for key in info.keys():
100         if key.startswith('raw '):# or 'peak' in key: #or key not in ['surface deflection offset (m)', 'z piezo sensitivity (m/V)', 'z piezo scan (V/bit)', 'z piezo gain', 'deflection range (V)', 'z piezo range (V)', 'spring constant (N/m)', 'z piezo scan size (V)', 'deflection sensitivity (V/bit)', 'z piezo ramp size (V/bit)', 'surface deflection offset', 'z piezo offset (V)', 'name']:
101             del(info[key])
102     print 'AAAS', info.keys()
103     return dumper.represent_mapping(u'!hooke.curve.DataInfo', info)
104 yaml.add_representer(Data, data_representer)