Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-dasbus for openSUSE:Factory 
checked in at 2021-06-09 21:52:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-dasbus (Old)
 and      /work/SRC/openSUSE:Factory/.python-dasbus.new.32437 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-dasbus"

Wed Jun  9 21:52:59 2021 rev:2 rq:898671 version:1.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-dasbus/python-dasbus.changes      
2021-05-20 19:25:25.249853786 +0200
+++ /work/SRC/openSUSE:Factory/.python-dasbus.new.32437/python-dasbus.changes   
2021-06-09 21:53:21.314587371 +0200
@@ -1,0 +2,10 @@
+Tue Jun  8 13:13:14 UTC 2021 - Predrag Ivanovi?? <predi...@mts.rs>
+
+- Update to dasbus-1.6
+ * Allow to generate multiple output arguments (vponcova)
+ * Support multiple output arguments (vponcova)
+ * Add the is_tuple_of_one function (vponcova)
+- Package changes:
+ * Switch from PyPI to Github download.
+
+-------------------------------------------------------------------

Old:
----
  dasbus-1.5.tar.gz

New:
----
  dasbus-1.6.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-dasbus.spec ++++++
--- /var/tmp/diff_new_pack.jBStIn/_old  2021-06-09 21:53:21.770588184 +0200
+++ /var/tmp/diff_new_pack.jBStIn/_new  2021-06-09 21:53:21.774588191 +0200
@@ -19,17 +19,17 @@
 %define skip_python2 1
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-dasbus
-Version:        1.5
+Version:        1.6
 Release:        0
 Summary:        DBus library in Python 3
 License:        LGPL-2.0-or-later
 Group:          Development/Libraries/Python
 URL:            https://github.com/rhinstaller/dasbus
-Source:         
https://files.pythonhosted.org/packages/source/d/dasbus/dasbus-%{version}.tar.gz
+Source:         
https://github.com/rhinstaller/dasbus/releases/download/v%{version}/dasbus-%{version}.tar.gz
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module setuptools}
-BuildRequires:  gobject-introspection
 BuildRequires:  fdupes
+BuildRequires:  gobject-introspection
 Requires:       python-gobject
 BuildArch:      noarch
 %python_subpackages

++++++ dasbus-1.5.tar.gz -> dasbus-1.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/PKG-INFO new/dasbus-1.6/PKG-INFO
--- old/dasbus-1.5/PKG-INFO     2021-05-03 16:38:39.873418000 +0200
+++ new/dasbus-1.6/PKG-INFO     2021-05-31 17:16:53.949654300 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: dasbus
-Version: 1.5
+Version: 1.6
 Summary: DBus library in Python 3
 Home-page: https://github.com/rhinstaller/dasbus
 Author: Vendula Poncova
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/dasbus/server/handler.py 
new/dasbus-1.6/dasbus/server/handler.py
--- old/dasbus-1.5/dasbus/server/handler.py     2021-05-03 16:35:50.000000000 
+0200
+++ new/dasbus-1.6/dasbus/server/handler.py     2021-05-31 17:14:31.000000000 
+0200
@@ -26,7 +26,7 @@
 from dasbus.signal import Signal
 from dasbus.server.interface import get_xml, are_additional_arguments_supported
 from dasbus.specification import DBusSpecification, DBusSpecificationError
-from dasbus.typing import get_variant, unwrap_variant
+from dasbus.typing import get_variant, unwrap_variant, is_tuple_of_one
 
 import gi
 gi.require_version("Gio", "2.0")
@@ -147,12 +147,19 @@
         :param out_type: a type of the reply
         :param out_value: a value of the reply
         """
-        reply_value = None
+        reply_value = cls._get_reply_value(out_type, out_value)
+        invocation.return_value(reply_value)
+
+    @classmethod
+    def _get_reply_value(cls, out_type, out_value):
+        """Get the reply value of the DBus call."""
+        if out_type is None:
+            return None
 
-        if out_type is not None:
-            reply_value = get_variant(out_type, (out_value, ))
+        if is_tuple_of_one(out_type):
+            out_value = (out_value, )
 
-        invocation.return_value(reply_value)
+        return get_variant(out_type, out_value)
 
 
 class AbstractServerObjectHandler(metaclass=ABCMeta):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/dasbus/server/interface.py 
new/dasbus-1.6/dasbus/server/interface.py
--- old/dasbus-1.5/dasbus/server/interface.py   2021-05-03 16:35:50.000000000 
+0200
+++ new/dasbus-1.6/dasbus/server/interface.py   2021-05-31 17:14:31.000000000 
+0200
@@ -30,7 +30,8 @@
 from dasbus.namespace import get_dbus_name
 from dasbus.signal import Signal
 from dasbus.specification import DBusSpecificationError, DBusSpecification
-from dasbus.typing import get_dbus_type
+from dasbus.typing import get_dbus_type, is_base_type, get_type_arguments, \
+    Tuple
 from dasbus.xml import XMLGenerator
 
 __all__ = [
@@ -45,11 +46,49 @@
 # Class attribute for the XML specification.
 DBUS_XML_ATTRIBUTE = "__dbus_xml__"
 
+# Method attribute for the @returns_multiple_arguments decorator.
+RETURNS_MULTIPLE_ARGUMENTS_ATTRIBUTE = \
+    "__dbus_method_returns_multiple_arguments__"
+
 # Method attribute for the @accepts_additional_arguments decorator.
 ACCEPTS_ADDITIONAL_ARGUMENTS_ATTRIBUTE = \
     "__dbus_handler_accepts_additional_arguments__"
 
 
+def returns_multiple_arguments(method):
+    """Decorator for returning multiple arguments from a DBus method.
+
+    The decorator allows to generate multiple output arguments in the
+    XML specification of the decorated DBus method. Otherwise, there
+    will be only one output argument in the specification.
+
+    Define a DBus method with multiple output arguments:
+
+    .. code-block:: python
+
+        @returns_multiple_arguments
+        def Method(self) -> Tuple[Int, Bool]:
+            return 0, False
+
+    The generated XML specification of the example:
+
+    .. code-block:: xml
+
+        <method name="Method">
+            <arg direction="out" name="return_0" type="i"/>
+            <arg direction="out" name="return_1" type="b"/>
+        </method>
+
+    If the XML specification is not generated by the dbus_interface
+    decorator, the returns_multiple_arguments decorator has no effect.
+
+    :param method: a DBus method
+    :return: a DBus method with a flag
+    """
+    setattr(method, RETURNS_MULTIPLE_ARGUMENTS_ATTRIBUTE, True)
+    return method
+
+
 def accepts_additional_arguments(method):
     """Decorator for accepting extra arguments in a DBus method.
 
@@ -455,12 +494,17 @@
 
         raises DBusSpecificationError: if parameters are invalid
         """
+        signature = inspect.signature(member)
+        yield from cls._iterate_in_parameters(member, signature)
+        yield from cls._iterate_out_parameters(member, signature)
+
+    @classmethod
+    def _iterate_in_parameters(cls, member, signature):
+        """Iterate over input parameters."""
         # Get type hints for parameters.
+        direction = DBusSpecification.DIRECTION_IN
         type_hints = get_type_hints(member)
 
-        # Get method signature.
-        signature = inspect.signature(member)
-
         # Iterate over method parameters, skip cls.
         for name in list(signature.parameters)[1:]:
             # Check the kind of the parameter
@@ -483,21 +527,47 @@
                     "Undefined type of parameter '{}'.".format(name)
                 )
 
-            yield name, type_hints[name], DBusSpecification.DIRECTION_IN
+            yield name, type_hints[name], direction
+
+    @classmethod
+    def _iterate_out_parameters(cls, member, signature):
+        """Iterate over output parameters."""
+        name = DBusSpecification.RETURN_PARAMETER
+        direction = DBusSpecification.DIRECTION_OUT
+        type_hint = signature.return_annotation
 
         # Is the return type defined?
-        if signature.return_annotation is signature.empty:
+        if type_hint is signature.empty:
             return
 
         # Is the return type other than None?
-        if signature.return_annotation is None:
+        if type_hint is None:
             return
 
-        yield (
-            DBusSpecification.RETURN_PARAMETER,
-            signature.return_annotation,
-            DBusSpecification.DIRECTION_OUT
-        )
+        # Generate multiple output arguments if requested.
+        if getattr(member, RETURNS_MULTIPLE_ARGUMENTS_ATTRIBUTE, False):
+            # The return type has to be a tuple.
+            if not is_base_type(type_hint, Tuple):
+                raise DBusSpecificationError(
+                    "Expected a tuple of multiple arguments."
+                )
+
+            # The return type has to contain multiple arguments.
+            type_args = get_type_arguments(type_hint)
+
+            if len(type_args) < 2:
+                raise DBusSpecificationError(
+                    "Expected a tuple of more than one argument."
+                )
+
+            # Iterate over types in the tuple
+            for i, type_arg in enumerate(type_args):
+                yield "{}_{}".format(name, i), type_arg, direction
+
+            return
+
+        # Otherwise, return only one output argument.
+        yield name, type_hint, direction
 
     @classmethod
     def _is_property(cls, member):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/dasbus/typing.py 
new/dasbus-1.6/dasbus/typing.py
--- old/dasbus-1.5/dasbus/typing.py     2021-05-03 16:35:50.000000000 +0200
+++ new/dasbus-1.6/dasbus/typing.py     2021-05-31 17:14:31.000000000 +0200
@@ -51,6 +51,7 @@
     "get_native",
     "get_variant",
     "get_variant_type",
+    "is_tuple_of_one",
     "unwrap_variant",
     "is_base_type",
     "get_type_arguments",
@@ -138,6 +139,16 @@
     return VariantType.new(type_string)
 
 
+def is_tuple_of_one(type_hint):
+    """Is the type hint a tuple of one item?
+
+    :param type_hint: a type hint or a type string
+    :return: True or False
+    """
+    variant_type = get_variant_type(type_hint)
+    return variant_type.is_tuple() and variant_type.n_items() == 1
+
+
 def get_native(value):
     """Decompose a DBus value into a native Python object.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/dasbus.egg-info/PKG-INFO 
new/dasbus-1.6/dasbus.egg-info/PKG-INFO
--- old/dasbus-1.5/dasbus.egg-info/PKG-INFO     2021-05-03 16:38:39.000000000 
+0200
+++ new/dasbus-1.6/dasbus.egg-info/PKG-INFO     2021-05-31 17:16:53.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: dasbus
-Version: 1.5
+Version: 1.6
 Summary: DBus library in Python 3
 Home-page: https://github.com/rhinstaller/dasbus
 Author: Vendula Poncova
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/setup.py new/dasbus-1.6/setup.py
--- old/dasbus-1.5/setup.py     2021-05-03 16:37:01.000000000 +0200
+++ new/dasbus-1.6/setup.py     2021-05-31 17:14:51.000000000 +0200
@@ -22,7 +22,7 @@
 
 setup(
     name="dasbus",
-    version="1.5",
+    version="1.6",
     author="Vendula Poncova",
     author_email="vponc...@redhat.com",
     description="DBus library in Python 3",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/tests/test_dbus.py 
new/dasbus-1.6/tests/test_dbus.py
--- old/dasbus-1.5/tests/test_dbus.py   2021-05-03 16:35:50.000000000 +0200
+++ new/dasbus-1.6/tests/test_dbus.py   2021-05-31 17:14:31.000000000 +0200
@@ -26,8 +26,10 @@
 from dasbus.error import ErrorMapper, get_error_decorator
 from dasbus.loop import EventLoop
 from dasbus.server.interface import dbus_interface, dbus_signal, \
-    accepts_additional_arguments
-from dasbus.typing import get_variant, Str, Int, Dict, Variant, List
+    accepts_additional_arguments, returns_multiple_arguments
+from dasbus.typing import get_variant, Str, Int, Dict, Variant, List, \
+    Tuple, Bool
+from dasbus.xml import XMLGenerator
 
 import gi
 gi.require_version("Gio", "2.0")
@@ -136,6 +138,10 @@
     def GetInfo(self, arg: Str, *, call_info) -> Str:
         return "{}: {}".format(arg, call_info)
 
+    @returns_multiple_arguments
+    def ReturnArgs(self) -> Tuple[Int, Bool, Str]:
+        return 0, False, "zero"
+
 
 class DBusTestCase(unittest.TestCase):
     """Test DBus support with a real DBus connection."""
@@ -152,6 +158,7 @@
 
         self.service = None
         self.clients = []
+        self.maxDiff = None
 
     def tearDown(self):
         self.message_bus.disconnect()
@@ -166,6 +173,49 @@
     def _set_service(self, service):
         self.service = service
 
+    def test_xml_specification(self):
+        """Test the generated specification."""
+        self._set_service(ExampleInterface())
+
+        expected_xml = '''
+        <node>
+          <!--Specifies ExampleInterface-->
+          <interface name="my.testing.Example">
+            <method name="GetInfo">
+              <arg direction="in" name="arg" type="s"></arg>
+              <arg direction="out" name="return" type="s"></arg>
+            </method>
+            <method name="Hello">
+              <arg direction="in" name="name" type="s"></arg>
+              <arg direction="out" name="return" type="s"></arg>
+            </method>
+            <method name="Knock"></method>
+            <signal name="Knocked"></signal>
+            <property access="read" name="Name" type="s"></property>
+            <method name="Raise">
+              <arg direction="in" name="message" type="s"></arg>
+            </method>
+            <method name="ReturnArgs">
+              <arg direction="out" name="return_0" type="i"></arg>
+              <arg direction="out" name="return_1" type="b"></arg>
+              <arg direction="out" name="return_2" type="s"></arg>
+            </method>
+            <property access="write" name="Secret" type="s"></property>
+            <property access="readwrite" name="Value" type="i"></property>
+            <signal name="Visited">
+              <arg direction="out" name="name" type="s"></arg>
+            </signal>
+          </interface>
+        </node>
+        '''
+
+        generated_xml = self.service.__dbus_xml__
+
+        self.assertEqual(
+            XMLGenerator.prettify_xml(expected_xml),
+            XMLGenerator.prettify_xml(generated_xml)
+        )
+
     def _add_client(self, client_test):
         thread = Thread(None, client_test)
         thread.daemon = True
@@ -548,3 +598,17 @@
         self._add_client(test1)
         self._add_client(test2)
         self._run_test()
+
+    def test_multiple_output_arguments(self):
+        """Call a DBus method with multiple output arguments."""
+        self._set_service(ExampleInterface())
+
+        def test1():
+            proxy = self._get_proxy()
+            self.assertEqual(
+                proxy.ReturnArgs(),
+                (0, False, "zero")
+            )
+
+        self._add_client(test1)
+        self._run_test()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/tests/test_interface.py 
new/dasbus-1.6/tests/test_interface.py
--- old/dasbus-1.5/tests/test_interface.py      2021-05-03 16:35:50.000000000 
+0200
+++ new/dasbus-1.6/tests/test_interface.py      2021-05-31 17:14:31.000000000 
+0200
@@ -18,10 +18,10 @@
 #
 import unittest
 
-from dasbus.typing import Int, Str, List, Double, File, Tuple, Bool
+from dasbus.typing import Int, Str, List, Double, File, Tuple, Bool, Dict
 from dasbus.server.interface import dbus_interface, dbus_class, dbus_signal, \
     get_xml, DBusSpecificationGenerator, DBusSpecificationError, \
-    accepts_additional_arguments
+    accepts_additional_arguments, returns_multiple_arguments
 from dasbus.xml import XMLGenerator
 
 
@@ -762,3 +762,87 @@
         '''
 
         self._compare(AdditionalArgumentsClass, expected_xml)
+
+    def test_multiple_output_arguments(self):
+        """Test interface methods with multiple output arguments."""
+
+        @dbus_interface("my.example.Interface")
+        class MultipleOutputArgumentsClass(object):
+
+            @returns_multiple_arguments
+            def Method1(self):
+                pass
+
+            @returns_multiple_arguments
+            def Method2(self) -> None:
+                pass
+
+            @returns_multiple_arguments
+            def Method3(self) -> Tuple[Int, Bool, Str]:
+                pass
+
+            @returns_multiple_arguments
+            def Method4(self) -> Tuple[Tuple[Int], List[Str]]:
+                pass
+
+        expected_xml = '''
+        <node>
+            <!--Specifies MultipleOutputArgumentsClass-->
+            <interface name="my.example.Interface">
+                <method name="Method1"/>
+                <method name="Method2"/>
+                <method name="Method3">
+                    <arg direction="out" name="return_0" type="i"/>
+                    <arg direction="out" name="return_1" type="b"/>
+                    <arg direction="out" name="return_2" type="s"/>
+                </method>
+                <method name="Method4">
+                    <arg direction="out" name="return_0" type="(i)"/>
+                    <arg direction="out" name="return_1" type="as"/>
+                </method>
+            </interface>
+        </node>
+        '''
+
+        self._compare(MultipleOutputArgumentsClass, expected_xml)
+
+    def test_invalid_multiple_output_arguments(self):
+        """Test interface methods with invalid output arguments."""
+
+        class InvalidOutputArgumentsClass(object):
+
+            @returns_multiple_arguments
+            def Method1(self) -> Int:
+                pass
+
+            @returns_multiple_arguments
+            def Method2(self) -> List[Bool]:
+                pass
+
+            @returns_multiple_arguments
+            def Method3(self) -> Dict[Str, Bool]:
+                pass
+
+            @returns_multiple_arguments
+            def Method4(self) -> Tuple[Int]:
+                pass
+
+        self._check_invalid_method(
+            InvalidOutputArgumentsClass.Method1,
+            "Expected a tuple of multiple arguments."
+        )
+
+        self._check_invalid_method(
+            InvalidOutputArgumentsClass.Method2,
+            "Expected a tuple of multiple arguments."
+        )
+
+        self._check_invalid_method(
+            InvalidOutputArgumentsClass.Method3,
+            "Expected a tuple of multiple arguments."
+        )
+
+        self._check_invalid_method(
+            InvalidOutputArgumentsClass.Method4,
+            "Expected a tuple of more than one argument."
+        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/tests/test_server.py 
new/dasbus-1.6/tests/test_server.py
--- old/dasbus-1.5/tests/test_server.py 2021-05-03 16:35:50.000000000 +0200
+++ new/dasbus-1.6/tests/test_server.py 2021-05-31 17:14:31.000000000 +0200
@@ -145,6 +145,10 @@
                     <arg direction="in" name="y" type="o"/>
                     <arg direction="out" name="return" type="(ib)"/>
                 </method>
+                <method name="Method5">
+                    <arg direction="out" name="return" type="i"/>
+                    <arg direction="out" name="return" type="b"/>
+                </method>
             </interface>
         </node>
         """)
@@ -178,6 +182,14 @@
         )
         self.object.Method4.assert_called_once_with([1.2, 2.3], "/my/path")
 
+        self.object.Method5.return_value = (1, True)
+        self._call_method(
+            "Interface",
+            "Method5",
+            reply=get_variant("(ib)", (1, True))
+        )
+        self.object.Method5.assert_called_once_with()
+
         self._call_method_with_error(
             "Interface",
             "MethodInvalid",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dasbus-1.5/tests/test_typing.py 
new/dasbus-1.6/tests/test_typing.py
--- old/dasbus-1.5/tests/test_typing.py 2021-05-03 16:35:50.000000000 +0200
+++ new/dasbus-1.6/tests/test_typing.py 2021-05-31 17:14:31.000000000 +0200
@@ -24,7 +24,7 @@
 from dasbus.typing import get_dbus_type, is_base_type, get_native, \
     get_variant, get_variant_type, Int, Int16, Int32, Int64, UInt16, UInt32, \
     UInt64, Bool, Byte, Str, Dict, List, Tuple, Variant, Double, ObjPath, \
-    File, unwrap_variant, get_type_name
+    File, unwrap_variant, get_type_name, is_tuple_of_one, get_type_arguments
 
 import gi
 gi.require_version("GLib", "2.0")
@@ -53,6 +53,16 @@
         self.assertIsInstance(variant_type, GLib.VariantType)
         self.assertTrue(expected_type.equal(variant_type))
 
+        # Test the is_tuple_of_one function.
+        expected_value = is_base_type(type_hint, Tuple) \
+            and len(get_type_arguments(type_hint)) == 1
+
+        self.assertEqual(is_tuple_of_one(type_hint), expected_value)
+        self.assertEqual(is_tuple_of_one(expected_string), expected_value)
+
+        self.assertTrue(is_tuple_of_one(Tuple[type_hint]))
+        self.assertTrue(is_tuple_of_one("({})".format(expected_string)))
+
     def test_unknown(self):
         """Test the unknown type."""
 

Reply via email to