跳转到主要内容

"将值转换为正确包装的dbus-python对象"

项目描述

将存在于核心Python类型(例如,列表、整数、字典)中的对象转换为基于指定dbus签名的存在于dbus-python类型(例如,dbus.Array、dbus.UInt32、dbus.Dictionary)中的对象的工具。

动机

dbus-python库是libdbus的Python绑定库。它不提供确保客户端代码放置在D-Bus上的值类型符合所需签名的功能。客户端代码可能是一个D-Bus服务,因此它放置在D-Bus上的值应符合它指定的签名,或者在某些情况下,是服务的客户端,它必须符合服务的规范。

如果一个服务在其对象上实现了Introspectable接口,dbus-python将使用签名信息将客户端消息转换成正确的dbus类型。如果Introspectable接口不可用,dbus-python将通过递归检查参数的值来猜测签名,然后继续之前的操作。如果签名包含一个‘v’,表示变体类型,dbus-python必须猜测相应值的类型。可以通过将适当方法中的introspect参数设置为false来指示dbus-python不使用dbus introspection。

此库提供了一种确保放置在D-Bus上的值符合给定签名的机制,通过将这些值封装在相应签名的构造函数中来实现的。它为任何有效的签名生成正确的函数。

使用和实现提示

库的使用相当简单

>>> from into_dbus_python import xformers
>>> funcs = xformers("adq")
>>> len(funcs)
2

请注意,函数列表的长度与签名中完整类型的数量相同。函数列表中的每个元素都是一个元组。

>>> funcs[0]
(<function ToDbusXformer._handleArray.<locals>.the_func at 0x7f4542f2d730>, 'ad')

第一个元素是该函数本身,第二个是一个字符串,与函数产生的正确类型签名相匹配。应用此函数会产生实际值

>>> funcs[0][0]([2.3, 37.5])
(dbus.Array([dbus.Double(2.3), dbus.Double(37.5)], signature=dbus.Signature('d')), 0)

在这个例子中,签名是“ad”,所以产生的值是dbus.Double对象的dbus.Array。签名参数具有适当的值;它只是“d”,表示数组中元素类型的符号,即double。请注意,该函数还产生一个元组,转换的值和一个int,表示变体级别。由于签名中没有“v”,变体级别为0。

如果传递了无效的参数,生成的函数将失败并抛出IntoDPError。

>>> try:
...     funcs[0][0](True)
... except IntoDPError as err:
...     print("bad arg")
...
bad arg

如果任何函数抛出的异常不是IntoDPError的子类型,则这构成一个bug,并且不是公共API的一部分。

便利性

解析器本身返回一个元组列表,其中通常只有元组中的第一个元素对客户端感兴趣。第二个元素,匹配的字符串,是递归实现的必要结果,但通常对客户端没有太大用处。生成的函数每个都返回一个包含转换值和变体级别的元组,通常只有转换值对客户端感兴趣。

因此,库提供了一个便利函数xformer(),它接受一个签名并返回一个函数,该函数接受一个对象列表,并返回一个列表,将其转换为适当的dbus类型。它可以如下使用

>>> from into_dbus_python import xformer
>>> func = xformer("adq")
>>> func([[2.3, 34.0], 3])
[dbus.Array([dbus.Double(2.3), dbus.Double(34.0)], signature=dbus.Signature('d')), dbus.UInt16(3)]

请注意,该函数必须接受一个值列表,每个值对应于签名中的每个完整类型。这里,有两个完整类型“ad”和“q”,有两个结果值。

如果签名包含一个“v”,表示变体类型,则值必须是一个签名和值的对,该值存在于该类型中。例如,

>>> func = xformer("v")
>>> func([("aq", [0, 1])])
[dbus.Array([dbus.UInt16(0), dbus.UInt16(1)], signature=dbus.Signature('q'), variant_level=1)]

请注意,构造的Array对象的变体级别为1。在dbus对象中,非零的变体级别表示该对象是一个变体。在这个例子中,变体级别只是1。变体的进一步嵌套是允许的,变体级别在每个级别上增加1。

>>> func([("av", [("q", 0)])])
[dbus.Array([dbus.UInt16(0, variant_level=1)], signature=dbus.Signature('v'), variant_level=2)]

这里,数组中变体元素的变体级别为0,但整个数组的变体级别为2,因为数组包含一个变体元素,并且居住在一个变体类型中。

核心类型的限制

生成的函数对要转换的值的类型施加尽可能少的限制。一般来说,元组与列表一样好,因为两者都是可迭代的。

>>> func = xformer("adq")
>>> func([(2.3, 34.0), 3])
[dbus.Array([dbus.Double(2.3), dbus.Double(34.0)], signature=dbus.Signature('d')), dbus.UInt16(3)]

但是,dbus.Dictionary类型的居住者必须是一个具有items()方法的对象,该方法产生键和值的对,例如字典。

签名()函数

这个库还公开了一个函数,signature(),它接受一个dbus-python类型中的值,计算其签名。它与xformer()函数有以下关系。

令S为一个签名。令C为Python核心类型中的值列表。令V = xformer(S)(C)。那么" "".join(signature(v) for v in V) 等于S。

技术说明

此软件包通过使用setParseAction()方法向各个解析器添加动作,扩展了在dbus-signature-pyparsing软件包中实现的dbus签名解析器(https://github.com/stratis-storage/dbus-signature-pyparsing)。

该软件包已使用Hypothesis测试库(http://hypothesis.works/)和hs-dbus-signature软件包中实现的外部Hypothesis策略进行了大量测试(https://github.com/stratis-storage/hs-dbus-signature)。

对于下游打包者,如果将测试纳入其打包,建议只使用test_deterministic.py模块中的测试,以避免由于Hypothesis测试的非确定性行为而可能出现的测试失败。

项目详情


下载文件

下载适合您平台的应用程序。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

into-dbus-python-0.8.2.tar.gz (17.9 kB 查看哈希值)

上传时间

构建分布

into_dbus_python-0.8.2-py3-none-any.whl (15.0 kB 查看哈希值)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面