fix: void validate arguments/properties name (#358)
This commit is contained in:
parent
e7750caed5
commit
f58f1a6466
@ -260,7 +260,11 @@ class MessageBus(BaseMessageBus):
|
||||
return await future
|
||||
|
||||
async def introspect(
|
||||
self, bus_name: str, path: str, timeout: float = 30.0
|
||||
self,
|
||||
bus_name: str,
|
||||
path: str,
|
||||
timeout: float = 30.0,
|
||||
validate_property_names: bool = True,
|
||||
) -> intr.Node:
|
||||
"""Get introspection data for the node at the given path from the given
|
||||
bus name.
|
||||
@ -274,6 +278,8 @@ class MessageBus(BaseMessageBus):
|
||||
:type path: str
|
||||
:param timeout: The timeout to introspect.
|
||||
:type timeout: float
|
||||
:param validate_property_names: Whether to validate property names or not.
|
||||
:type validate_property_names: bool
|
||||
|
||||
:returns: The introspection data for the name at the path.
|
||||
:rtype: :class:`Node <dbus_fast.introspection.Node>`
|
||||
@ -295,6 +301,7 @@ class MessageBus(BaseMessageBus):
|
||||
path,
|
||||
partial(self._reply_handler, future),
|
||||
check_callback_type=False,
|
||||
validate_property_names=validate_property_names,
|
||||
)
|
||||
|
||||
timer_handle = self._loop.call_later(
|
||||
|
||||
@ -34,9 +34,6 @@ class Arg:
|
||||
direction: Optional[list[ArgDirection]] = None,
|
||||
name: Optional[str] = None,
|
||||
):
|
||||
if name is not None:
|
||||
assert_member_name_valid(name)
|
||||
|
||||
type_ = None
|
||||
if type(signature) is SignatureType:
|
||||
type_ = signature
|
||||
@ -245,8 +242,10 @@ class Property:
|
||||
name: str,
|
||||
signature: str,
|
||||
access: PropertyAccess = PropertyAccess.READWRITE,
|
||||
validate: bool = True,
|
||||
):
|
||||
assert_member_name_valid(name)
|
||||
if validate:
|
||||
assert_member_name_valid(name)
|
||||
|
||||
tree = get_signature_tree(signature)
|
||||
if len(tree.types) != 1:
|
||||
@ -259,7 +258,7 @@ class Property:
|
||||
self.access = access
|
||||
self.type = tree.types[0]
|
||||
|
||||
def from_xml(element):
|
||||
def from_xml(element, validate: bool = True):
|
||||
"""Convert an :class:`xml.etree.ElementTree.Element` to a :class:`Property`.
|
||||
|
||||
The element must be valid DBus introspection XML for a ``property``.
|
||||
@ -279,7 +278,7 @@ class Property:
|
||||
if not signature:
|
||||
raise InvalidIntrospectionError('properties must have a "type" attribute')
|
||||
|
||||
return Property(name, signature, access)
|
||||
return Property(name, signature, access, validate=validate)
|
||||
|
||||
def to_xml(self) -> ET.Element:
|
||||
"""Convert this :class:`Property` into an :class:`xml.etree.ElementTree.Element`."""
|
||||
@ -324,7 +323,9 @@ class Interface:
|
||||
self.properties = properties if properties is not None else []
|
||||
|
||||
@staticmethod
|
||||
def from_xml(element: ET.Element) -> "Interface":
|
||||
def from_xml(
|
||||
element: ET.Element, validate_property_names: bool = True
|
||||
) -> "Interface":
|
||||
"""Convert a :class:`xml.etree.ElementTree.Element` into a
|
||||
:class:`Interface`.
|
||||
|
||||
@ -348,7 +349,9 @@ class Interface:
|
||||
elif child.tag == "signal":
|
||||
interface.signals.append(Signal.from_xml(child))
|
||||
elif child.tag == "property":
|
||||
interface.properties.append(Property.from_xml(child))
|
||||
interface.properties.append(
|
||||
Property.from_xml(child, validate=validate_property_names)
|
||||
)
|
||||
|
||||
return interface
|
||||
|
||||
@ -409,7 +412,9 @@ class Node:
|
||||
self.is_root = is_root
|
||||
|
||||
@staticmethod
|
||||
def from_xml(element: ET.Element, is_root: bool = False):
|
||||
def from_xml(
|
||||
element: ET.Element, is_root: bool = False, validate_property_names: bool = True
|
||||
) -> "Node":
|
||||
"""Convert an :class:`xml.etree.ElementTree.Element` to a :class:`Node`.
|
||||
|
||||
The element must be valid DBus introspection XML for a ``node``.
|
||||
@ -418,6 +423,8 @@ class Node:
|
||||
:type element: :class:`xml.etree.ElementTree.Element`
|
||||
:param is_root: Whether this is the root node
|
||||
:type is_root: bool
|
||||
:param validate_property_names: Whether to validate property names or not
|
||||
:type validate_property_names: bool
|
||||
|
||||
:raises:
|
||||
- :class:`InvalidIntrospectionError <dbus_fast.InvalidIntrospectionError>` - If the XML tree is not valid introspection data.
|
||||
@ -426,20 +433,30 @@ class Node:
|
||||
|
||||
for child in element:
|
||||
if child.tag == "interface":
|
||||
node.interfaces.append(Interface.from_xml(child))
|
||||
node.interfaces.append(
|
||||
Interface.from_xml(
|
||||
child, validate_property_names=validate_property_names
|
||||
)
|
||||
)
|
||||
elif child.tag == "node":
|
||||
node.nodes.append(Node.from_xml(child))
|
||||
node.nodes.append(
|
||||
Node.from_xml(
|
||||
child, validate_property_names=validate_property_names
|
||||
)
|
||||
)
|
||||
|
||||
return node
|
||||
|
||||
@staticmethod
|
||||
def parse(data: str) -> "Node":
|
||||
def parse(data: str, validate_property_names: bool = True) -> "Node":
|
||||
"""Parse XML data as a string into a :class:`Node`.
|
||||
|
||||
The string must be valid DBus introspection XML.
|
||||
|
||||
:param data: The XMl string.
|
||||
:type data: str
|
||||
:param validate_property_names: Whether to validate property names or not
|
||||
:type validate_property_names: bool
|
||||
|
||||
:raises:
|
||||
- :class:`InvalidIntrospectionError <dbus_fast.InvalidIntrospectionError>` - If the string is not valid introspection data.
|
||||
@ -450,7 +467,9 @@ class Node:
|
||||
'introspection data must have a "node" for the root element'
|
||||
)
|
||||
|
||||
return Node.from_xml(element, is_root=True)
|
||||
return Node.from_xml(
|
||||
element, is_root=True, validate_property_names=validate_property_names
|
||||
)
|
||||
|
||||
def to_xml(self) -> ET.Element:
|
||||
"""Convert this :class:`Node` into an :class:`xml.etree.ElementTree.Element`."""
|
||||
|
||||
@ -262,6 +262,7 @@ class BaseMessageBus:
|
||||
path: str,
|
||||
callback: Callable[[Optional[intr.Node], Optional[Exception]], None],
|
||||
check_callback_type: bool = True,
|
||||
validate_property_names: bool = True,
|
||||
) -> None:
|
||||
"""Get introspection data for the node at the given path from the given
|
||||
bus name.
|
||||
@ -276,6 +277,10 @@ class BaseMessageBus:
|
||||
:param callback: A callback that will be called with the introspection
|
||||
data as a :class:`Node <dbus_fast.introspection.Node>`.
|
||||
:type callback: :class:`Callable`
|
||||
:param check_callback_type: Whether to check callback type or not.
|
||||
:type check_callback_type: bool
|
||||
:param validate_property_names: Whether to validate property names or not.
|
||||
:type validate_property_names: bool
|
||||
|
||||
:raises:
|
||||
- :class:`InvalidObjectPathError <dbus_fast.InvalidObjectPathError>` - If the given object path is not valid.
|
||||
@ -287,7 +292,9 @@ class BaseMessageBus:
|
||||
def reply_notify(reply: Optional[Message], err: Optional[Exception]) -> None:
|
||||
try:
|
||||
BaseMessageBus._check_method_return(reply, err, "s")
|
||||
result = intr.Node.parse(reply.body[0]) # type: ignore[union-attr]
|
||||
result = intr.Node.parse(
|
||||
reply.body[0], validate_property_names=validate_property_names
|
||||
) # type: ignore[union-attr]
|
||||
except Exception as e:
|
||||
callback(None, e)
|
||||
return
|
||||
|
||||
10
tests/data/sloppy-introspection.xml
Normal file
10
tests/data/sloppy-introspection.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node name="/com/example/sample_object0">
|
||||
<interface name="com.example.SampleInterface0">
|
||||
<method name="Frobate">
|
||||
<arg name="0-foo-bar" type="i" direction="in"/>
|
||||
</method>
|
||||
<property name="0-baz-qux" type="y" access="write"/>
|
||||
</interface>
|
||||
</node>
|
||||
@ -5,7 +5,7 @@
|
||||
<method name="Frobate">
|
||||
<arg name="foo" type="i" direction="in"/>
|
||||
<arg name="bar" type="s" direction="out"/>
|
||||
<arg name="baz" type="a{us}" direction="out"/>
|
||||
<arg name="0-baz" type="a{us}" direction="out"/>
|
||||
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
|
||||
</method>
|
||||
<method name="Bazify">
|
||||
@ -16,11 +16,11 @@
|
||||
<arg name="bar" type="(iiav)" direction="in"/>
|
||||
</method>
|
||||
<signal name="Changed">
|
||||
<arg name="new_value" type="b"/>
|
||||
<arg name="0-new_value" type="b"/>
|
||||
</signal>
|
||||
<signal name="ChangedMulti">
|
||||
<arg name="new_value1" type="b"/>
|
||||
<arg name="new_value2" type="y"/>
|
||||
<arg name="0-new_value2" type="y"/>
|
||||
</signal>
|
||||
<property name="Bar" type="y" access="write"/>
|
||||
</interface>
|
||||
@ -1,14 +1,33 @@
|
||||
import os
|
||||
|
||||
from dbus_fast import ArgDirection, PropertyAccess, SignatureType
|
||||
from dbus_fast import (
|
||||
ArgDirection,
|
||||
PropertyAccess,
|
||||
SignatureType,
|
||||
InvalidMemberNameError,
|
||||
)
|
||||
from dbus_fast import introspection as intr
|
||||
|
||||
with open(f"{os.path.dirname(__file__)}/data/introspection.xml") as f:
|
||||
example_data = f.read()
|
||||
with open(f"{os.path.dirname(__file__)}/data/strict-introspection.xml") as f:
|
||||
strict_data = f.read()
|
||||
|
||||
with open(f"{os.path.dirname(__file__)}/data/sloppy-introspection.xml") as f:
|
||||
sloppy_data = f.read()
|
||||
|
||||
|
||||
def test_example_introspection_from_xml():
|
||||
node = intr.Node.parse(example_data)
|
||||
def test_introspection_from_xml_sloppy():
|
||||
intr.Node.parse(sloppy_data, validate_property_names=False)
|
||||
|
||||
|
||||
def test_introspection_from_xml_strict():
|
||||
try:
|
||||
node = intr.Node.parse(sloppy_data)
|
||||
except InvalidMemberNameError:
|
||||
pass
|
||||
else:
|
||||
assert False, "Expected an AssertionError"
|
||||
|
||||
node = intr.Node.parse(strict_data)
|
||||
|
||||
assert len(node.interfaces) == 1
|
||||
interface = node.interfaces[0]
|
||||
@ -61,12 +80,12 @@ def test_example_introspection_from_xml():
|
||||
assert len(changed.args) == 1
|
||||
new_value = changed.args[0]
|
||||
assert type(new_value) is intr.Arg
|
||||
assert new_value.name == "new_value"
|
||||
assert new_value.name == "0-new_value"
|
||||
assert new_value.signature == "b"
|
||||
|
||||
|
||||
def test_example_introspection_to_xml():
|
||||
node = intr.Node.parse(example_data)
|
||||
node = intr.Node.parse(strict_data)
|
||||
tree = node.to_xml()
|
||||
assert tree.tag == "node"
|
||||
assert tree.attrib.get("name") == "/com/example/sample_object0"
|
||||
@ -94,7 +113,7 @@ def test_example_introspection_to_xml():
|
||||
|
||||
arg = signal[0]
|
||||
assert arg.tag == "arg"
|
||||
assert arg.attrib.get("name") == "new_value"
|
||||
assert arg.attrib.get("name") == "0-new_value"
|
||||
assert arg.attrib.get("type") == "b"
|
||||
|
||||
signal = interface[4]
|
||||
@ -109,7 +128,7 @@ def test_example_introspection_to_xml():
|
||||
|
||||
arg = signal[1]
|
||||
assert arg.tag == "arg"
|
||||
assert arg.attrib.get("name") == "new_value2"
|
||||
assert arg.attrib.get("name") == "0-new_value2"
|
||||
assert arg.attrib.get("type") == "y"
|
||||
|
||||
prop = interface[5]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user