Skip to content

Commit

Permalink
Make EmitsChangedSignal introspection more accurate
Browse files Browse the repository at this point in the history
Now has 5 values: None, True, False, 'const', 'invalidates'
  • Loading branch information
igo95862 committed Sep 14, 2022
1 parent 4e69458 commit 3f70eaf
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 14 deletions.
43 changes: 30 additions & 13 deletions src/sdbus/interface_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@
from __future__ import annotations

from pathlib import Path
from typing import Dict, Iterable, Iterator, List, Optional, Tuple, Union
from typing import (
Dict,
Iterable,
Iterator,
List,
Literal,
Optional,
Tuple,
Union,
)
from xml.etree.ElementTree import Element
from xml.etree.ElementTree import fromstring as etree_from_str
from xml.etree.ElementTree import parse as etree_from_file
Expand Down Expand Up @@ -402,20 +411,21 @@ def __repr__(self) -> str:


class DbusPropertyIntrospection(DbusMemberAbstract):
_EMITS_CHANGED_MAP: Dict[str, Optional[str]] = {
'true': 'DbusPropertyEmitsChangeFlag',
'false': None,
'invalidates': 'DbusPropertyEmitsInvalidationFlag',
'const': 'DbusPropertyConstFlag',
}
_EMITS_CHANGED_MAP: \
Dict[Union[bool, None, Literal['const', 'invalidates']], str] = {
True: 'DbusPropertyEmitsChangeFlag',
'invalidates': 'DbusPropertyEmitsInvalidationFlag',
'const': 'DbusPropertyConstFlag',
}

def __init__(self, element: Element):
if element.tag != 'property':
raise ValueError(f"Expected property tag, got {element.tag}")

self.dbus_signature = element.attrib['type']

self.emits_changed: Optional[str] = None
self.emits_changed: \
Union[bool, Literal['const', 'invalidates'], None] = None
self.is_explicit = False

access_type = element.attrib['access']
Expand All @@ -429,8 +439,9 @@ def __init__(self, element: Element):
super().__init__(element)

def _flags_iter(self) -> Iterator[str]:
if self.emits_changed is not None:
yield self.emits_changed
emits_changed_str = self._EMITS_CHANGED_MAP.get(self.emits_changed)
if emits_changed_str is not None:
yield emits_changed_str

yield from super()._flags_iter()

Expand All @@ -440,11 +451,17 @@ def _parse_annotation_data(self,

if annotation_name == ('org.freedesktop.DBus.Property'
'.EmitsChangedSignal'):
if annotation_value not in self._EMITS_CHANGED_MAP:
if annotation_value == 'true':
self.emits_changed = True
elif annotation_value == 'false':
self.emits_changed = False
elif annotation_value == 'const':
self.emits_changed = 'const'
elif annotation_value == 'invalidates':
self.emits_changed = 'invalidates'
else:
raise ValueError('Unknown EmitsChanged value',
annotation_value)

self.emits_changed = self._EMITS_CHANGED_MAP[annotation_value]
elif annotation_name == 'org.freedesktop.systemd1.Explicit':
self.is_explicit = parse_str_bool(annotation_value)

Expand Down
43 changes: 42 additions & 1 deletion test/test_interface_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@
<arg name="new_value" type="b"/>
</signal>
<property name="Bar" type="y" access="readwrite"/>
<property name="FooFoo" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal"
value="false"/>
</property>
<property name="BoundBy" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal"
value="const"/>
</property>
<property name="FooInvalidates" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal"
value="invalidates"/>
</property>
</interface>
<node name="child_of_sample_object"/>
<node name="another_child_of_sample_object"/>
Expand Down Expand Up @@ -141,7 +153,36 @@ def test_parsing(self) -> None:
if find_spec('jinja2') is None:
raise SkipTest('Jinja2 not installed')

generate_async_py_file(interfaces_from_str(test_xml))
interfaces_intro = interfaces_from_str(test_xml)

with self.subTest('Test introspection details'):
test_interface = interfaces_intro[0]

for test_property in test_interface.properties:
if test_property.method_name == 'BoundBy':
self.assertEqual(
test_property.emits_changed,
'const',
)
elif test_property.method_name == 'Bar':
self.assertEqual(
test_property.emits_changed,
None,
)
elif test_property.method_name == 'FooInvalidates':
self.assertEqual(
test_property.emits_changed,
'invalidates',
)
elif test_property.method_name == 'FooFoo':
self.assertEqual(
test_property.emits_changed,
False,
)

generated = generate_async_py_file(interfaces_intro)
self.assertIn('flags=DbusPropertyEmitsInvalidationFlag', generated)
self.assertIn('flags=DbusPropertyConstFlag', generated)


if __name__ == "__main__":
Expand Down

0 comments on commit 3f70eaf

Please sign in to comment.