Represent instance of different classes with the s

2019-05-23 05:19发布

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条回答
ゆ 、 Hurt°
2楼-- · 2019-05-23 06:01

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.

查看更多
登录 后发表回答