Represent instance of different classes with the same base class in pyyaml

蓝咒 提交于 2019-12-22 18:37:45

问题


I have some set of unittests and want to store results of each test run as YAML file for further analysis. Dump data in YAML format fit my needs in several ways. But tests belongs to different suits and results have different parent class, This is example of what I have:

>>> rz # shorthand for result
[<upstream_suite.fftest.SimpleTest testMethod=test_is_fsType_not_set>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_A>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_A_a_glyph_instance>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_ended_ufo>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_folder>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_is_fsType_eq_1>,
<upstream_suite.openfolder.UfoOpenTest testMethod=test_it_exists>]
# etc.

Each test can have its own parent class.

>>> type(rz[0]) == type(rz[1])
False

I've added my own base class for all classes with __getstate__ method, but it is not working for some reason:

>>> rz[0].__getstate__()
{'targets': ['upstream'], 'methodDoc': 'Is the OS/2 table fsType set to 0?', 'methodName': 'test_is_fsType_not_set', 'tool': 'FontForge', 'name': 'upstream_suite.fftest'}
>>> yaml.safe_dump(rz[0])
*** RepresenterError: cannot represent an object: test_is_fsType_not_set (upstream_suite.fftest.SimpleTest)

Documentations say that I can make representer for each class, so I tried it and wrote this code:

import yaml
from somepath import MyTestCase

def repr_testcase(dumper, data):
    return dumper.represent_mapping(u'tag:yaml.org,2002:map', {
        'methodDoc': data._testMethodDoc,
        'tool': data.tool,
        'name': data.name,
        'methodName': data._testMethodName,
        'targets': data.targets,
        })

# Register representer 
yaml.SafeDumper.add_representer(MyTestCase, repr_testcase)

The same time:

>>> isinstance(rz[0], MyTestCase)
True

Even after that safe_dump isn't working. But if I made this trick, then it works and I can get result:

>>> yaml.SafeDumper.add_representer(type(rz[0]), repr_testcase)
>>> print(yaml.safe_dump(rz[0]))
methodDoc: Is the OS/2 table fsType set to 0?
methodName: test_is_fsType_not_set
name: checker.upstream_suite.fontforge_suite.fftest
targets: [upstream]
tool: FontForge

But that means that I need to register all possible occurrences, which is, well... at least, does not looks smart. Actually my real result is more complex dictionary, tests harvested from different places, etc.

>>> for x in rz: yaml.SafeDumper.add_representer(type(x), repr_testcase)
>>> yaml.safe_dump(rz)
... here is expected result

So, question is, what I'm doing wrong with __getstate__ or how I can make work pyyaml with all instances of particular base class with only one representer registration.


回答1:


I found the way how to make this work. Short answer is that there is another way to register representer it called add_multi_representer. So fix is:

# Change this line:
# yaml.SafeDumper.add_representer(MyTestCase, repr_testcase)

# to this line:
yaml.SafeDumper.add_multi_representer(MyTestCase, repr_testcase)

Upd. Multi representer allow to make what I was trying to achieve: register representer for base class.



来源:https://stackoverflow.com/questions/19744971/represent-instance-of-different-classes-with-the-same-base-class-in-pyyaml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!