SimplyKnownAsG / yamlize

Python YAML serializing library
Apache License 2.0
11 stars 5 forks source link

Duplicate mapping keys not detected/allow_duplicate_keys not honored #11

Open youngmit opened 2 years ago

youngmit commented 2 years ago

ruamel.yaml purports to disallow duplicate keys by default (https://yaml.readthedocs.io/en/latest/api.html#duplicate-keys), however yamlize is somehow side-steps this. The duplicate check is happening in constructor.py in ruamel.yaml. I am trying to figure out how to get that functionality back, but it is unclear where the interface is between ruamel.yaml and yamlize. Perhaps the cause/solution would be more immediately obvious to the author? Any guidance would be most appreciated, thanks!

SimplyKnownAsG commented 2 years ago

hmmmm. Can you provide a MWE (or failing in this instance?). I tried the below and it failed as expected. Notably, I distinctly remember thinking that YAML allowed duplicate keys and JSON didn't (which is backwards, evidently). I vividly recall having this backwards in my mind.

In [1]: from yamlize import Object ; from yamlize import Attribute

In [2]: class Animal(Object):
   ...:     name = Attribute(type=str)
   ...:     age = Attribute(type=int)
   ...: 
   ...:     def __init__(self, name, age):
   ...:         Object.__init__(self)
   ...:         self.name = name
   ...:         self.age = age
   ...: 

In [3]: Animal.load('{name: Lucy, age: 11}')
Out[3]: <__main__.Animal at 0x7ff474073780>

In [4]: Animal.load('{name: Lucy, name: Lucy, age: 11}')
---------------------------------------------------------------------------
YamlizingError                            Traceback (most recent call last)
<ipython-input-4-9ab4c76cb578> in <module>
----> 1 Animal.load('{name: Lucy, name: Lucy, age: 11}')

~/Documents/yamlize/yamlize/yamlizable.py in load(cls, stream, Loader)
     51         try:
     52             node = loader.get_single_node()
---> 53             return cls.from_yaml(loader, node, None)
     54         finally:
     55             loader.dispose()

~/Documents/yamlize/yamlize/objects.py in from_yaml(cls, loader, node, _rtd)
    138         self.__round_trip_data = RoundTripData(node)
    139         loader.constructed_objects[node] = self
--> 140         self.__from_node(loader, node)
    141 
    142         return self

~/Documents/yamlize/yamlize/objects.py in __from_node(self, loader, node)
    194 
    195             if attribute in previous_attrs:
--> 196                 raise YamlizingError('Error parsing {}, found duplicate entry '
    197                                      'for key `{}`'
    198                                      .format(type(self), attribute.key),

YamlizingError: Error parsing <class '__main__.Animal'>, found duplicate entry for key `name`
start:   in "<unicode string>", line 1, column 14:
    {name: Lucy, name: Lucy, age: 11}
                 ^ (line: 1)
end:   in "<unicode string>", line 1, column 18:
    {name: Lucy, name: Lucy, age: 11}
                     ^ (line: 1)
youngmit commented 2 years ago

Good to know that it should pitch a fit. I'll try to get a MWE together sometime this week; our use case is a comfortable hop-skip-jump away from simple, so I might discover where this is happening in the process of simplifying.