一个支持属性、类变量和继承的Python字典实现,满足您的复杂模板需求。
项目描述
一个支持属性、类变量和继承的Python字典实现,满足您的复杂模板需求。
对Python 2.6、2.7和3.3进行了测试
动机
覆盖类的一个特定行为很简单:创建一个子类(或者甚至只是一个实例),只需实现您感兴趣的部分即可。但是,对于模板来说并非如此。如果您想更改它的一部分,您需要覆盖整个模板,这在本质上就是重新做模板作者的工。
“propdict”通过允许模板作者将逻辑和行为放入进入模板的数据中,而不是模板本身,来对此进行反击。
然后,模板的消费者可以简单地从基于“propdict”的数据派生子类,覆盖特定的方面,并保持模板不变。
基本功能
“propdict”实例的行为几乎与常规字典完全相同,只是您可以使用字典表示法或属性表示法访问值
>>> server_foo.ip_addr '10.0.0.1' >>> server_foo['ip_addr'] '10.0.0.1'>>> print server_foo['ifconfig'] ifconfig_em0="inet 10.0.0.1 netmask 255.255.255.0">>> print server_foo.ifconfig ifconfig_em0="inet 10.0.0.1 netmask 255.255.255.0"
同样的方法也适用于赋值
>>> server_foo.ip_addr = '192.168.1.1' >>> print server_foo.ip_addr 192.168.1.1>>> server_foo['ip_addr'] = '127.0.0.1' >>> print server_foo.ip_addr 127.0.0.1
当然,赋值也可以用于更改属性,正如您在示例中所看到的
>>> server_foo.ifconfig = u'foo mask' >>> print server_foo.ifconfig foo mask
值得注意的是,您不能删除属性。但是,您 可以 删除属性的 自定义 值,但这只会重新暴露它们的原始值
>>> del server_foo['ifconfig'] >>> print server_foo.ifconfig ifconfig_em0="inet 127.0.0.1 netmask 255.255.255.0">>> del server_foo['ifconfig'] Traceback (most recent call last): ... KeyError: 'ifconfig'
示例
假设您是一组用于配置*NIX风格系统的模板的作者。当然,这些模板中的许多都会使用相同的值,例如正在配置的机器的IP地址。现在,一些 其他 值反过来又依赖于IP地址的值。让我们说有一个这样的文件包含一行配置网络接口使用子网掩码,因此您最终得到一个包含以下片段的模板
>>> template = '''ifconfig_%(iface)s="inet %(ip_addr)s netmask %(netmask)s"'''
给定一个包含必要数据的字典,这将评估为以下内容
>>> print template % dict(ip_addr='192.168.1.1', iface='em0', netmask='255.255.255.0') ifconfig_em0="inet 192.168.1.1 netmask 255.255.255.0"
这在大多数情况下都工作得很好,但如果部署的某个主机位于NAT后面并且需要一个完全不同的配置(不遵循上述格式),那该怎么办呢?现在你可能需要创建一个自定义的模板版本(与上面的基本示例不同,它可能具有非平凡的长度和复杂性),仅在这一行上有所不同,或者模板的作者需要处理(另一个)特殊边缘情况,这不会影响99%的用户。
第三种解决方案是将模板的这一行尽可能保持简单
>>> template = "%(ifconfig)s"
并将逻辑放入字典中。如下所示
>>> from propdict import propdict >>> class Host(propdict): ... ip_addr = None ... iface = 'em0' ... netmask = '255.255.255.0' ... @property ... def ifconfig(self): ... return '''ifconfig_%(iface)s="inet %(ip_addr)s netmask %(netmask)s"''' % self>>> server_foo = Host(ip_addr='10.0.0.1') >>> print template % server_foo ifconfig_em0="inet 10.0.0.1 netmask 255.255.255.0"
到目前为止一切顺利,我们得到了与上面相同的结果。但让我们考虑另一个服务器
>>> server_bar = Host(ip_addr='10.0.0.2', ifconfig='ifconfig_em1="inet 10.0.0.2 netmask 255.255.0.0"') >>> print template % server_bar ifconfig_em1="inet 10.0.0.2 netmask 255.255.0.0"
请注意,新的ifconfig定义包含一个新接口值(也许这个主机有两个内置),但仍然引用ip_addr。在这种情况下,可能最好不仅提供一个新的、静态的值,而是提出一个更好的属性实现
>>> class HostBar(Host): ... iface_2 = 'em1' ... @property ... def ifconfig(self): ... return '''ifconfig_%(iface_2)s="inet %(ip_addr)s netmask %(netmask)s"''' % self >>> server_bar = HostBar(ip_addr='10.0.0.2', netmask='255.255.0.0') >>> print template % server_bar ifconfig_em1="inet 10.0.0.2 netmask 255.255.0.0"
因此,我们能够通过仅更改这一行并提供一个任意的新值来为ifconfig键提供,同时不触及模板,同时仍然保持默认行为(它自动从接口和IP地址为您计算)。
安装
propdict没有依赖项,可以使用您喜欢的工具(如pip、easy_install、buildout、setuptools)简单地作为egg安装。您知道该怎么做。
运行测试
为了确保propdict适合您的设置,请运行其测试。您需要从github获取一个副本和py.test,可能如下所示
git clone git@github.com:tomster/propdict cd propdict virtualenv . source bin/activate pip install pytest-cov
然后,运行所有测试(包括这个README)
bin/py.test
如果您进行了某些更改并想知道是否破坏了覆盖率
bin/py.test --cov propdict --cov-report html --cov-report term test_propdict.py
变更日志
1.1 - 201310-18
打包修复[fschulze]
在构造函数中支持字典[fschulze]
1.0 - 2013-10-17
在生产环境中经过数月,发布了相同代码的稳定版本。
0.1a1 - 2013-03-17
初始公共发布
项目详情
propdict-1.1.zip的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 8b2a3c1de90ca836926023e57739f22f1b8d82c0a47368b14ccaab84de561b76 |
|
MD5 | 077bc643eba3b9f2fe9dc1e121dac3da |
|
BLAKE2b-256 | db2e13ea4855514ec6221d2a400a616ecfb0dbf8411fa36b665f0b5edd8e00f9 |