Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/syck/dumpers.py

    r20 r25  
     1""" 
     2syck.dumpers is a high-level wrapper for the Syck YAML emitter. 
     3Do not use it directly, use the module 'syck' instead. 
     4""" 
    15 
    26import _syck 
     
    1014    'emit', 'dump', 'emit_documents', 'dump_documents'] 
    1115 
    12 INF = 1e300000 
    13 NEGINF = -INF 
    14 NAN = INF/INF 
    15  
    16  
    1716class GenericDumper(_syck.Emitter): 
     17    """ 
     18    GenericDumper dumps native Python objects into YAML documents. 
     19    """ 
    1820 
    1921    def dump(self, object): 
     22        """Dumps the given Python object as a YAML document.""" 
    2023        self.emit(self._convert(object, {})) 
    2124 
    2225    def _convert(self, object, object_to_node): 
    2326        if id(object) in object_to_node and self.allow_aliases(object): 
    24             return object_to_node[id(object)] 
     27            return object_to_node[id(object)][1] 
    2528        node = self.represent(object) 
    26         object_to_node[id(object)] = node 
     29        object_to_node[id(object)] = object, node 
    2730        if node.kind == 'seq': 
    28             for index, item in enumerate(node.value): 
     31            for index in range(len(node.value)): 
     32                item = node.value[index] 
    2933                node.value[index] = self._convert(item, object_to_node) 
    3034        elif node.kind == 'map': 
    31             for key in node.value.keys(): 
    32                 value = node.value[key] 
    33                 del node.value[key] 
    34                 node.value[self._convert(key, object_to_node)] =    \ 
    35                         self._convert(value, object_to_node) 
     35            if isinstance(node.value, dict): 
     36                for key in node.value.keys(): 
     37                    value = node.value[key] 
     38                    del node.value[key] 
     39                    node.value[self._convert(key, object_to_node)] =    \ 
     40                            self._convert(value, object_to_node) 
     41            elif isinstance(node.value, list): 
     42                for index in range(len(node.value)): 
     43                    key, value = node.value[index] 
     44                    node.value[index] = (self._convert(key, object_to_node), 
     45                            self._convert(value, object_to_node)) 
    3646#        # Workaround against a Syck bug: 
    3747#        if node.kind == 'scalar' and node.style not in ['1quote', '2quote'] \ 
     
    4151 
    4252    def represent(self, object): 
     53        """Represents the given Python object as a 'Node'.""" 
    4354        if isinstance(object, dict): 
    4455            return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map") 
     
    4960 
    5061    def allow_aliases(self, object): 
     62        """Checks whether the given object can be aliased.""" 
    5163        return True 
    5264 
    5365class Dumper(GenericDumper): 
    54  
    55     def __init__(self, *args, **kwds): 
    56         super(Dumper, self).__init__(*args, **kwds) 
    57  
    58     def represent(self, object): 
     66    """ 
     67    Dumper dumps native Python objects into YAML documents. 
     68    """ 
     69 
     70    INF = 1e300000 
     71    inf_value = repr(INF) 
     72    neginf_value = repr(-INF) 
     73    nan_value = repr(INF/INF) 
     74 
     75    def find_representer(self, object): 
     76        """ 
     77        For the given object, find a method that can represent it as a 'Node' 
     78        object. 
     79 
     80        If the type of the object has the form 'package.module.type', 
     81        find_representer() returns the method 'represent_package_module_type'. 
     82        If this method does not exist, it checks the base types. 
     83        """ 
    5984        for object_type in type(object).__mro__: 
    6085            if object_type.__module__ == '__builtin__': 
     
    6287            else: 
    6388                name = '%s.%s' % (object_type.__module__, object_type.__name__) 
    64             method = 'represent_%s' % name.replace('.', '_') 
     89            method = 'represent_' + name.replace('.', '_') 
    6590            if hasattr(self, method): 
    66                 return getattr(self, method)(object) 
    67         return super(Dumper, self).represent(object) 
     91                return getattr(self, method) 
     92 
     93    def represent(self, object): 
     94        """Represents the given Python object as a 'Node'.""" 
     95        representer = self.find_representer(object) 
     96        if representer: 
     97            return representer(object) 
     98        else: 
     99            return super(Dumper, self).represent(object) 
    68100 
    69101    def represent_object(self, object): 
     
    88120        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int") 
    89121 
    90     def represent_int(self, object): 
    91         return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int") 
    92  
    93122    def represent_float(self, object): 
    94123        value = repr(object) 
    95         if value == repr(INF): 
     124        if value == self.inf_value: 
    96125            value = '.inf' 
    97         elif value == repr(NEGINF): 
     126        elif value == self.neginf_value: 
    98127            value = '-.inf' 
    99         elif value == repr(NAN): 
     128        elif value == self.nan_value: 
    100129            value = '.nan' 
    101130        return _syck.Scalar(value, tag="tag:yaml.org,2002:float") 
     
    103132    def represent_sets_Set(self, object): 
    104133        return _syck.Seq(list(object), tag="tag:yaml.org,2002:set") 
     134    represent_set = represent_sets_Set 
    105135 
    106136    def represent_datetime_datetime(self, object): 
    107137        return _syck.Scalar(object.isoformat(), tag="tag:yaml.org,2002:timestamp") 
    108138 
     139    def represent_long(self, object): 
     140        return _syck.Scalar(repr(object), tag="tag:python.yaml.org,2002:long") 
     141 
     142    def represent_unicode(self, object): 
     143        return _syck.Scalar(object.encode('utf-8'), tag="tag:python.yaml.org,2002:unicode") 
     144 
     145    def represent_tuple(self, object): 
     146        return _syck.Seq(list(object), tag="tag:python.yaml.org,2002:tuple") 
     147 
     148    def represent_type(self, object): 
     149        name = '%s.%s' % (object.__module__, object.__name__) 
     150        return _syck.Scalar('', tag="tag:python.yaml.org,2002:name:"+name) 
     151    represent_classobj = represent_type 
     152    represent_class = represent_type 
     153    # TODO: Python 2.2 does not provide the module name of a function 
     154    represent_function = represent_type 
     155    represent_builtin_function_or_method = represent_type 
     156 
     157    def represent_instance(self, object): 
     158        cls = object.__class__ 
     159        class_name = '%s.%s' % (cls.__module__, cls.__name__) 
     160        args = () 
     161        state = {} 
     162        if hasattr(object, '__getinitargs__'): 
     163            args = object.__getinitargs__() 
     164        if hasattr(object, '__getstate__'): 
     165            state = object.__getstate__() 
     166        elif not hasattr(object, '__getinitargs__'): 
     167            state = object.__dict__.copy() 
     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        value = {} 
     172        if args: 
     173            value['args'] = list(args) 
     174        if state or not isinstance(state, dict): 
     175            value['state'] = state 
     176        return _syck.Map(value, 
     177                tag="tag:python.yaml.org,2002:new:"+class_name) 
     178 
     179    def represent_object(self, object): # Do you understand this? I don't. 
     180        cls = type(object) 
     181        class_name = '%s.%s' % (cls.__module__, cls.__name__) 
     182        args = () 
     183        state = {} 
     184        if cls.__reduce__ is type.__reduce__: 
     185            if hasattr(object, '__reduce_ex__'): 
     186                reduce = object.__reduce_ex__(2) 
     187                args = reduce[1][1:] 
     188            else: 
     189                reduce = object.__reduce__() 
     190            if len(reduce) > 2: 
     191                state = reduce[2] 
     192            if state is None: 
     193                state = {} 
     194            if not args and isinstance(state, dict): 
     195                return _syck.Map(state.copy(), 
     196                        tag="tag:python.yaml.org,2002:object:"+class_name) 
     197            if not state and isinstance(state, dict): 
     198                return _syck.Seq(list(args), 
     199                        tag="tag:python.yaml.org,2002:new:"+class_name) 
     200            value = {} 
     201            if args: 
     202                value['args'] = list(args) 
     203            if state or not isinstance(state, dict): 
     204                value['state'] = state 
     205            return _syck.Map(value, 
     206                    tag="tag:python.yaml.org,2002:new:"+class_name) 
     207        else: 
     208            reduce = object.__reduce__() 
     209            cls = reduce[0] 
     210            class_name = '%s.%s' % (cls.__module__, cls.__name__) 
     211            args = reduce[1] 
     212            state = None 
     213            if len(reduce) > 2: 
     214                state = reduce[2] 
     215            if state is None: 
     216                state = {} 
     217            if not state and isinstance(state, dict): 
     218                return _syck.Seq(list(args), 
     219                        tag="tag:python.yaml.org,2002:apply:"+class_name) 
     220            value = {} 
     221            if args: 
     222                value['args'] = list(args) 
     223            if state or not isinstance(state, dict): 
     224                value['state'] = state 
     225            return _syck.Map(value, 
     226                    tag="tag:python.yaml.org,2002:apply:"+class_name) 
     227 
     228    def represent__syck_Node(self, object): 
     229        object_type = type(object) 
     230        type_name = '%s.%s' % (object_type.__module__, object_type.__name__) 
     231        state = [] 
     232        if hasattr(object_type, '__slotnames__'): 
     233            for name in object_type.__slotnames__: 
     234                value = getattr(object, name) 
     235                if value: 
     236                    state.append((name, value)) 
     237        return _syck.Map(state, 
     238                tag="tag:python.yaml.org,2002:object:"+type_name) 
     239 
    109240    def allow_aliases(self, object): 
     241        """Checks whether the given object can be aliased.""" 
    110242        if object is None or type(object) in [int, bool, float]: 
    111243            return False 
    112244        if type(object) is str and (not object or object.isalnum()): 
    113245            return False 
     246        if type(object) is tuple and not object: 
     247            return False 
    114248        return True 
    115249 
    116 def emit(node, output=None, **parameters): 
     250def emit(node, output=None, Dumper=Dumper, **parameters): 
     251    """ 
     252    Emits the given node to the output. 
     253 
     254    If output is None, returns the produced YAML document. 
     255    """ 
    117256    if output is None: 
    118257        dumper = Dumper(StringIO.StringIO(), **parameters) 
     
    123262        return dumper.output.getvalue() 
    124263 
    125 def dump(object, output=None, **parameters): 
     264def dump(object, output=None, Dumper=Dumper, **parameters): 
     265    """ 
     266    Dumps the given object to the output. 
     267 
     268    If output is None, returns the produced YAML document. 
     269    """ 
    126270    if output is None: 
    127271        dumper = Dumper(StringIO.StringIO(), **parameters) 
     
    132276        return dumper.output.getvalue() 
    133277 
    134 def emit_documents(nodes, output=None, **parameters): 
     278def emit_documents(nodes, output=None, Dumper=Dumper, **parameters): 
     279    """ 
     280    Emits the list of nodes to the output. 
     281     
     282    If output is None, returns the produced YAML document. 
     283    """ 
    135284    if output is None: 
    136285        dumper = Dumper(StringIO.StringIO(), **parameters) 
     
    142291        return dumper.output.getvalue() 
    143292 
    144 def dump_documents(objects, output=None, **parameters): 
     293def dump_documents(objects, output=None, Dumper=Dumper, **parameters): 
     294    """ 
     295    Dumps the list of objects to the output. 
     296     
     297    If output is None, returns the produced YAML document. 
     298    """ 
    145299    if output is None: 
    146300        dumper = Dumper(StringIO.StringIO(), **parameters) 
Note: See TracChangeset for help on using the changeset viewer.