Skip to content

Nested classes can't be deserialized #131

Open
@MoritzMaxeiner

Description

@MoritzMaxeiner

Trying to serialize and then deserialize a nested class like

import yaml

class A:
    class B:
        def __init__(self, i):
            self.i = i
    def __init__(self, i):
        self.b = A.B(i)

yaml.load(yaml.dump(A(0)))

with pyyaml 3.12 (python 3.6) yields an exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/__init__.py", line 72, in load
    return loader.get_single_data()
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 37, in get_single_data
    return self.construct_document(node)
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 46, in construct_document
    for dummy in generator:
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 578, in construct_python_object
    state = self.construct_mapping(node, deep=deep)
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 204, in construct_mapping
    return super().construct_mapping(node, deep=deep)
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 129, in construct_mapping
    value = self.construct_object(value_node, deep=deep)
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 91, in construct_object
    data = next(generator)
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 575, in construct_python_object
    instance = self.make_python_instance(suffix, node, newobj=True)
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 552, in make_python_instance
    cls = self.find_python_name(suffix, node.start_mark)
  File "/home/calrama/.local/lib64/python3.6/site-packages/yaml/constructor.py", line 529, in find_python_name
    % (object_name, module.__name__), mark)
yaml.constructor.ConstructorError: while constructing a Python object
cannot find 'B' in the module '__main__'
  in "<unicode string>", line 2, column 4:
    b: !!python/object:__main__.B {i: 0}
       ^

Without nesting B in A it works as expected:

import yaml

class B:
    def __init__(self, i):
       self.i = i

class A:
    def __init__(self, i):
        self.b = B(i)

yaml.load(yaml.dump(A(0)))

The obvious workaround of just not using nesting is not always easily applicable when e.g. working with classes exposed from C/C++ (especially with C/C++ enumerations exposed as nested classes).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions