source: trunk/lib/syck/dumpers.py @ 24

Revision 24, 8.8 KB checked in by xi, 9 years ago (diff)

Fixed more compatibility issues for Python 2.2.

Not fixed (and probably never will be):

  • datetime.datetime
  • object.getnewargs
  • function.module
Line 
1
2import _syck
3
4try:
5    import cStringIO as StringIO
6except ImportError:
7    import StringIO
8
9__all__ = ['GenericDumper', 'Dumper',
10    'emit', 'dump', 'emit_documents', 'dump_documents']
11
12INF = 1e300000
13NEGINF = -INF
14NAN = INF/INF
15
16
17class GenericDumper(_syck.Emitter):
18
19    def dump(self, object):
20        self.emit(self._convert(object, {}))
21
22    def _convert(self, object, object_to_node):
23        if id(object) in object_to_node and self.allow_aliases(object):
24            return object_to_node[id(object)][1]
25        node = self.represent(object)
26        object_to_node[id(object)] = object, node
27        if node.kind == 'seq':
28            for index in range(len(node.value)):
29                item = node.value[index]
30                node.value[index] = self._convert(item, object_to_node)
31        elif node.kind == 'map':
32            for key in node.value.keys():
33                value = node.value[key]
34                del node.value[key]
35                node.value[self._convert(key, object_to_node)] =    \
36                        self._convert(value, object_to_node)
37#        # Workaround against a Syck bug:
38#        if node.kind == 'scalar' and node.style not in ['1quote', '2quote'] \
39#                and node.value and node.value[-1] in [' ', '\t']:
40#            node.style = '2quote'
41        return node
42
43    def represent(self, object):
44        if isinstance(object, dict):
45            return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map")
46        elif isinstance(object, list):
47            return _syck.Seq(object[:], tag="tag:yaml.org,2002:seq")
48        else:
49            return _syck.Scalar(str(object), tag="tag:yaml.org,2002:str")
50
51    def allow_aliases(self, object):
52        return True
53
54class Dumper(GenericDumper):
55
56    def __init__(self, *args, **kwds):
57        super(Dumper, self).__init__(*args, **kwds)
58
59    def find_representer(self, object):
60        for object_type in type(object).__mro__:
61            if object_type.__module__ == '__builtin__':
62                name = object_type.__name__
63            else:
64                name = '%s.%s' % (object_type.__module__, object_type.__name__)
65            method = 'represent_' + name.replace('.', '_')
66            if hasattr(self, method):
67                return getattr(self, method)
68
69    def represent(self, object):
70        representer = self.find_representer(object)
71        if representer:
72            return representer(object)
73        else:
74            return super(Dumper, self).represent(object)
75
76    def represent_object(self, object):
77        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:str")
78
79    def represent_NoneType(self, object):
80        return _syck.Scalar('~', tag="tag:yaml.org,2002:null")
81
82    def represent_bool(self, object):
83        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:bool")
84
85    def represent_str(self, object):
86        return _syck.Scalar(str(object), tag="tag:yaml.org,2002:str")
87
88    def represent_list(self, object):
89        return _syck.Seq(object[:], tag="tag:yaml.org,2002:seq")
90
91    def represent_dict(self, object):
92        return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map")
93
94    def represent_int(self, object):
95        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int")
96
97    def represent_float(self, object):
98        value = repr(object)
99        if value == repr(INF):
100            value = '.inf'
101        elif value == repr(NEGINF):
102            value = '-.inf'
103        elif value == repr(NAN):
104            value = '.nan'
105        return _syck.Scalar(value, tag="tag:yaml.org,2002:float")
106
107    def represent_sets_Set(self, object):
108        return _syck.Seq(list(object), tag="tag:yaml.org,2002:set")
109
110    def represent_datetime_datetime(self, object):
111        return _syck.Scalar(object.isoformat(), tag="tag:yaml.org,2002:timestamp")
112
113    def represent_long(self, object):
114        return _syck.Scalar(repr(object), tag="tag:python.yaml.org,2002:long")
115
116    def represent_unicode(self, object):
117        return _syck.Scalar(object.encode('utf-8'), tag="tag:python.yaml.org,2002:unicode")
118
119    def represent_tuple(self, object):
120        return _syck.Seq(list(object), tag="tag:python.yaml.org,2002:tuple")
121
122    def represent_type(self, object):
123        # TODO: Python 2.2 does not provide the module name of a function
124        name = '%s.%s' % (object.__module__, object.__name__)
125        return _syck.Scalar('', tag="tag:python.yaml.org,2002:name:"+name)
126    represent_classobj = represent_type
127    represent_class = represent_type
128    represent_function = represent_type
129    represent_builtin_function_or_method = represent_type
130
131    def represent_instance(self, object):
132        cls = object.__class__
133        class_name = '%s.%s' % (cls.__module__, cls.__name__)
134        args = ()
135        state = {}
136        if hasattr(object, '__getinitargs__'):
137            args = object.__getinitargs__()
138        if hasattr(object, '__getstate__'):
139            state = object.__getstate__()
140        elif not hasattr(object, '__getinitargs__'):
141            state = object.__dict__.copy()
142        if not args and isinstance(state, dict):
143            return _syck.Map(state.copy(),
144                    tag="tag:python.yaml.org,2002:object:"+class_name)
145        value = {}
146        if args:
147            value['args'] = list(args)
148        if state or not isinstance(state, dict):
149            value['state'] = state
150        return _syck.Map(value,
151                tag="tag:python.yaml.org,2002:new:"+class_name)
152
153    def represent_object(self, object): # Do you understand this? I don't.
154        cls = type(object)
155        class_name = '%s.%s' % (cls.__module__, cls.__name__)
156        args = ()
157        state = {}
158        if cls.__reduce__ is type.__reduce__:
159            if hasattr(object, '__reduce_ex__'):
160                reduce = object.__reduce_ex__(2)
161                args = reduce[1][1:]
162            else:
163                reduce = object.__reduce__()
164            if len(reduce) > 2:
165                state = reduce[2]
166            if state is None:
167                state = {}
168            if not args and isinstance(state, dict):
169                return _syck.Map(state.copy(),
170                        tag="tag:python.yaml.org,2002:object:"+class_name)
171            if not state and isinstance(state, dict):
172                return _syck.Seq(list(args),
173                        tag="tag:python.yaml.org,2002:new:"+class_name)
174            value = {}
175            if args:
176                value['args'] = list(args)
177            if state or not isinstance(state, dict):
178                value['state'] = state
179            return _syck.Map(value,
180                    tag="tag:python.yaml.org,2002:new:"+class_name)
181        else:
182            reduce = object.__reduce__()
183            cls = reduce[0]
184            class_name = '%s.%s' % (cls.__module__, cls.__name__)
185            args = reduce[1]
186            state = None
187            if len(reduce) > 2:
188                state = reduce[2]
189            if state is None:
190                state = {}
191            if not state and isinstance(state, dict):
192                return _syck.Seq(list(args),
193                        tag="tag:python.yaml.org,2002:apply:"+class_name)
194            value = {}
195            if args:
196                value['args'] = list(args)
197            if state or not isinstance(state, dict):
198                value['state'] = state
199            return _syck.Map(value,
200                    tag="tag:python.yaml.org,2002:apply:"+class_name)
201
202    def allow_aliases(self, object):
203        if object is None or type(object) in [int, bool, float]:
204            return False
205        if type(object) is str and (not object or object.isalnum()):
206            return False
207        if type(object) is tuple and not object:
208            return False
209        return True
210
211def emit(node, output=None, Dumper=Dumper, **parameters):
212    if output is None:
213        dumper = Dumper(StringIO.StringIO(), **parameters)
214    else:
215        dumper = Dumper(output, **parameters)
216    dumper.emit(node)
217    if output is None:
218        return dumper.output.getvalue()
219
220def dump(object, output=None, Dumper=Dumper, **parameters):
221    if output is None:
222        dumper = Dumper(StringIO.StringIO(), **parameters)
223    else:
224        dumper = Dumper(output, **parameters)
225    dumper.dump(object)
226    if output is None:
227        return dumper.output.getvalue()
228
229def emit_documents(nodes, output=None, Dumper=Dumper, **parameters):
230    if output is None:
231        dumper = Dumper(StringIO.StringIO(), **parameters)
232    else:
233        dumper = Dumper(output, **parameters)
234    for node in nodes:
235        dumper.emit(node)
236    if output is None:
237        return dumper.output.getvalue()
238
239def dump_documents(objects, output=None, Dumper=Dumper, **parameters):
240    if output is None:
241        dumper = Dumper(StringIO.StringIO(), **parameters)
242    else:
243        dumper = Dumper(output, **parameters)
244    for object in objects:
245        dumper.dump(object)
246    if output is None:
247        return dumper.output.getvalue()
248
249
Note: See TracBrowser for help on using the repository browser.