在pyyaml中表示具有相同基类的不同类的实例 [英] Represent instance of different classes with the same base class in pyyaml

查看:30
本文介绍了在pyyaml中表示具有相同基类的不同类的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些单元测试集,并希望将每个测试运行的结果存储为 YAML 文件以供进一步分析.YAML 格式的转储数据以多种方式满足我的需求.但是测试属于不同的套装,结果有不同的父类,这是我的例子:

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

我已经使用 __getstate__ 方法为所有类添加了我自己的基类,但由于某种原因它不起作用:

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)

同时:

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

即使在那之后 safe_dump 也不起作用.但是如果我做了这个技巧,那么它就会起作用并且我可以得到结果:

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

但这意味着我需要记录所有可能出现的情况,也就是说……至少,看起来并不聪明.其实我真正的result是更复杂的字典,不同地方的测试等等.

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

所以,问题是,我在使用 __getstate__ 时做错了什么,或者我如何让 pyyaml 与特定基类的所有实例一起工作,并且只有一个代表注册.

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.

推荐答案

我找到了如何使这项工作发挥作用的方法.简短的回答是,还有另一种注册代表的方法,它称为 add_multi_representer.所以修复是:

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.

这篇关于在pyyaml中表示具有相同基类的不同类的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆