python 3.x - YAML - Serializing attributes which are types -


i having trouble yaml-serializing classes have type references members. using safe loader of ruamel.yaml.

i ran following repl prompt (to multiple errors).

initialization:

import sys ruamel.yaml import yaml, yaml_object  y = yaml(typ="safe",pure=true)  # ==============  @yaml_object(y) class a(object):     """object want serialize"""     yaml_tag = "!aclass"     def __init__(self, type):         self.type = type     def f(self):         return self.type()     pass  class t1(object):     """this referenced."""     pass  @yaml_object(y) class t2(object):     """another referenced object"""     pass  class t3(object):     """yet try"""     pass y.register_class(t3.__class__) 

code causes failure:

y.dump(a(t1), sys.stdout) y.dump(a(t2), sys.stdout) y.dump(a(t3), sys.stdout) y.dump(a(int), sys.stdout) 

this outputs (only last lines of tracebacks):

ruamel.yaml.representer.representererror: cannot represent object: <attribute '__dict__' of 't1' objects> ruamel.yaml.representer.representererror: cannot represent object: <attribute '__dict__' of 't2' objects> ruamel.yaml.representer.representererror: cannot represent object: <attribute '__dict__' of 't3' objects> ruamel.yaml.representer.representererror: cannot represent object: <slot wrapper '__abs__' of 'int' objects> 

any solution lets me (safely) uniquely save type (i need generate objects of type , check whether incoming object of type) appreciated. function or class generates required type have same problem of not being serializable, either.


p.s. possibly found bug, parser will, reason, have different behavior depending on whether same effective argument (attempted) serialized.

y.dump(a(str), sys.stdout) y.dump(a(str), sys.stdout) y.dump(a(str), sys.stdout) y.dump(a(str), sys.stdout) 

outputs:

>>> y.dump(a(str), sys.stdout) traceback (most recent call last):   file "<stdin>", line 1, in <module>   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\main.py", line 352, in dump     return self.dump_all([data], stream, _kw, transform=transform)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\main.py", line 383, in dump_all     self.representer.represent(data)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 73, in represent     node = self.represent_data(data)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 101, in represent_data     node = self.yaml_representers[data_types[0]](self, data)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\main.py", line 552, in t_y     tag, data, cls, flow_style=representer.default_flow_style)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 371, in represent_yaml_object     return self.represent_mapping(tag, state, flow_style=flow_style)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 206, in represent_mapping     node_value = self.represent_data(item_value)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 101, in represent_data     node = self.yaml_representers[data_types[0]](self, data)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\main.py", line 492, in t_y     tag, data, cls, flow_style=representer.default_flow_style)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 371, in represent_yaml_object     return self.represent_mapping(tag, state, flow_style=flow_style)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 206, in represent_mapping     node_value = self.represent_data(item_value)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 111, in represent_data     node = self.yaml_representers[none](self, data)   file "c:\program files\anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 375, in represent_undefined     raise representererror("cannot represent object: %s" % data) ruamel.yaml.representer.representererror: cannot represent object: <slot wrapper '__add__' of 'str' objects> >>> y.dump(a(str), sys.stdout) !aclass type: !type {} >>> y.dump(a(str), sys.stdout) traceback (most recent call last): # same traceback here ruamel.yaml.representer.representererror: cannot represent object: <slot wrapper '__add__' of 'str' objects> >>> y.dump(a(str), sys.stdout) !aclass type: !type {} >>>  

yaml expects dump objects, , writing out scalar strings. t1 not object (nor t2 or t3), , problem comes from. can try make each class reference object , uses tags on those, imo merely complicates things.

eventually boils down getting scalar representation, i.e. string representation of class file, might adapt a() directly dump string representation , read back:

import sys ruamel.yaml import yaml, yaml_object ruamel.yaml.compat import stringio ruamel.yaml.scalarstring import doublequotedscalarstring   y = yaml(typ="safe", pure=true)  # ==============  @yaml_object(y) class a(object):     """object want serialize"""     yaml_tag = "!aclass"     def __init__(self, type):         self.type = type  #.__class__.__name__      @classmethod     def to_yaml(cls, representer, node):         return representer.represent_scalar(             cls.yaml_tag, u'{}'.format(node.type.__name__)         )      @classmethod     def from_yaml(cls, constructor, node):         if '.' in node.value:  # in other module             m, n = node.value.rsplit('.', 1)             return cls(getattr(sys.modules[m], n))         else:             return cls(globals()[node.value])   class t1(object):     """this referenced."""     pass   @yaml_object(y) class t2(object):     """another referenced object"""     pass   class t3(object):     """yet try"""     pass y.register_class(t3)   t in t1, t2, t3, doublequotedscalarstring:     print('----------------------')     x = stringio()     s = a(t)     print('s', s.type)     y.dump(s, x)     print(x.getvalue())      d = y.load(x.getvalue())     print('d', d.type) 

which gives:

---------------------- s <class '__main__.t1'> !aclass t1 ...  d <class '__main__.t1'> ---------------------- s <class '__main__.t2'> !aclass t2 ...  d <class '__main__.t2'> ---------------------- s <class '__main__.t3'> !aclass t3 ...  d <class '__main__.t3'> ---------------------- s <class 'ruamel.yaml.scalarstring.doublequotedscalarstring'> !aclass doublequotedscalarstring ...  d <class 'ruamel.yaml.scalarstring.doublequotedscalarstring'> 

if there other attributes on a() needs dumped/loaded, should create dictionary (with string converted .type) , dump/load that.

i don't think found real bug, experience side effect continuing after error: y object (and components) left in undefined state. should not reuse yaml() instance after catching errors. should more clear in documentation. if want try/except in loop , should move y = yaml(typ='safe', pure=true) within try part.


Comments

Popular posts from this blog

Is there a better way to structure post methods in Class Based Views -

performance - Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures? -

jquery - Responsive Navbar with Sub Navbar -