Improve XPCOM to dict conversion

We will need this in the future when listing machines and requesting attributes that don't exist (yet)

Related to saltstack/salt#27089 Saltcloud virtualbox provider
This commit is contained in:
LoveIsGrief 2016-01-02 17:51:35 +01:00
parent 43fff23cae
commit 2439d61b02
2 changed files with 49 additions and 12 deletions

View File

@ -56,11 +56,11 @@ def vb_get_box():
return vbox
def vb_list_machines():
def vb_list_machines(**kwargs):
manager = vb_get_manager()
machines = manager.getArray(vb_get_box(), "machines")
return [
vb_xpcom_to_attribute_dict(machine, "IMachine")
vb_xpcom_to_attribute_dict(machine, "IMachine", **kwargs)
for machine in machines
]
@ -149,10 +149,11 @@ def vb_xpcom_to_attribute_dict(xpcom
, interface_name=None
, attributes=None
, excluded_attributes=None
, extra_attributes=None
):
"""
Attempts to build a dict from an XPCOM object.
Attributes that don't exist in the object aren't included.
Attributes that don't exist in the object return an empty string.
@param xpcom:
@type xpcom:
@ -161,10 +162,13 @@ def vb_xpcom_to_attribute_dict(xpcom
@type interface_name: str
@param attributes: Overrides the attributes used from XPCOM_ATTRIBUTES
@type attributes: list
@param excluded_attributes: Which should be excluded in the returned dict
@param excluded_attributes: Which should be excluded in the returned dict.
!!These take precedence over extra_attributes!!
@type excluded_attributes: list
@param extra_attributes: Which should be retrieved in addition those already being retrieved
@type extra_attributes: list
@return:
@rtype:
@rtype: dict
"""
# Check the interface
if interface_name:
@ -174,13 +178,15 @@ def vb_xpcom_to_attribute_dict(xpcom
log.warn("Interface %s is unknown and cannot be converted to dict" % interface_name)
return dict()
interface_attributes = attributes or XPCOM_ATTRIBUTES.get(interface_name, [])
excluded_attributes = excluded_attributes or []
interface_attributes = set(attributes or XPCOM_ATTRIBUTES.get(interface_name, []))
if extra_attributes:
interface_attributes = interface_attributes.union(extra_attributes)
if excluded_attributes:
interface_attributes = interface_attributes.difference(excluded_attributes)
attribute_tuples = [
(attribute, getattr(xpcom, attribute))
(attribute, getattr(xpcom, attribute, ""))
for attribute in interface_attributes
if hasattr(xpcom, attribute) and attribute not in excluded_attributes
]
return dict(attribute_tuples)

View File

@ -236,7 +236,7 @@ class XpcomConversionTests(unittest.TestCase):
interface = "IMachine"
imachine = XpcomConversionTests._mock_xpcom_object(interface)
ret = vb_xpcom_to_attribute_dict(imachine)
ret = vb_xpcom_to_attribute_dict(imachine, interface_name=interface)
expected_attributes = XPCOM_ATTRIBUTES[interface]
self.assertIsNotNone(expected_attributes, "%s is unknown")
@ -252,11 +252,42 @@ class XpcomConversionTests(unittest.TestCase):
"something": 12345
}
imachine = XpcomConversionTests._mock_xpcom_object(attributes=expected_dict)
xpc = XpcomConversionTests._mock_xpcom_object(attributes=expected_dict)
ret = vb_xpcom_to_attribute_dict(imachine, attributes=expected_dict.keys())
ret = vb_xpcom_to_attribute_dict(xpc, attributes=expected_dict.keys())
self.assertDictEqual(ret, expected_dict)
def test_extra_attributes(self):
interface = "IMachine"
expected_extras = {
"extra": "extra",
}
expected_machine = dict([(attribute, attribute) for attribute in XPCOM_ATTRIBUTES[interface]])
expected_machine.update(expected_extras)
imachine = XpcomConversionTests._mock_xpcom_object(interface, attributes=expected_machine)
ret = vb_xpcom_to_attribute_dict(
imachine,
interface_name=interface,
extra_attributes=expected_extras.keys()
)
self.assertDictEqual(ret, expected_machine)
ret_keys = ret.keys()
for key in expected_extras.keys():
self.assertIn(key, ret_keys)
def test_extra_nonexistant_attributes(self):
expected_extra_dict = {
"nonexistant": ""
}
xpcom = XpcomConversionTests._mock_xpcom_object()
ret = vb_xpcom_to_attribute_dict(xpcom, extra_attributes=expected_extra_dict.keys())
self.assertDictEqual(ret, expected_extra_dict)
if __name__ == '__main__':
from integration import run_tests # pylint: disable=import-error