pyuno/inc/pyuno.hxx                                 |    6 +-----
 pyuno/qa/pytests/testcollections_XIndexContainer.py |    2 +-
 pyuno/qa/pytests/testcollections_XIndexReplace.py   |    2 +-
 pyuno/source/module/pyuno.cxx                       |    7 ++-----
 pyuno/source/module/pyuno_adapter.cxx               |    2 +-
 pyuno/source/module/pyuno_callable.cxx              |    7 ++-----
 pyuno/source/module/pyuno_impl.hxx                  |    3 +--
 pyuno/source/module/pyuno_module.cxx                |    4 ++--
 pyuno/source/module/pyuno_runtime.cxx               |   13 +++----------
 pyuno/source/module/pyuno_struct.cxx                |    2 +-
 pyuno/source/module/uno.py                          |   11 +++++++++--
 sw/qa/python/check_indexed_property_values.py       |   16 ++++++++--------
 sw/qa/python/check_named_property_values.py         |   12 ++++++------
 13 files changed, 38 insertions(+), 49 deletions(-)

New commits:
commit 68f8ddc15323bd67dff022766800cbcf11fdf370
Author:     Neil Roberts <[email protected]>
AuthorDate: Thu Dec 11 13:39:17 2025 +0100
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Thu Dec 18 10:05:47 2025 +0100

    Replace calls to uno.invoke with direct method call when just for Any
    
    Now that the restriction on passing on Any as an argument to a method
    has been lifted we can simplify some of the PythonTests that were
    calling uno.invoke in order to pass an Any and just call the method
    directly.
    
    Change-Id: I14af4e3f50236e46f6108f8fea0284f696b59e44
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195464
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>

diff --git a/pyuno/qa/pytests/testcollections_XIndexContainer.py 
b/pyuno/qa/pytests/testcollections_XIndexContainer.py
index 45cf509889a4..379d5328fdeb 100644
--- a/pyuno/qa/pytests/testcollections_XIndexContainer.py
+++ b/pyuno/qa/pytests/testcollections_XIndexContainer.py
@@ -30,7 +30,7 @@ class TestXIndexContainer(CollectionsTestBase):
         values = 
sm.createInstanceWithContext("com.sun.star.document.IndexedPropertyValues", 
self.context)
         for i in range(count):
             properties = (PropertyValue(Name='n'+str(i), Value='v'+str(i)),)
-            uno.invoke(values, "insertByIndex", (i, 
uno.Any("[]com.sun.star.beans.PropertyValue", properties)))
+            values.insertByIndex(i, 
uno.Any("[]com.sun.star.beans.PropertyValue", properties))
         return values
 
     def generateTestTuple(self, values):
diff --git a/pyuno/qa/pytests/testcollections_XIndexReplace.py 
b/pyuno/qa/pytests/testcollections_XIndexReplace.py
index 0075883543d3..ddc93095c559 100644
--- a/pyuno/qa/pytests/testcollections_XIndexReplace.py
+++ b/pyuno/qa/pytests/testcollections_XIndexReplace.py
@@ -28,7 +28,7 @@ class TestXIndexReplace(CollectionsTestBase):
         index = getContentIndexInstance(doc)
         for i in range(10):
             styles = ('n'+str(i),)
-            uno.invoke(index.LevelParagraphStyles, "replaceByIndex", (i, 
uno.Any("[]string", styles)))
+            index.LevelParagraphStyles.replaceByIndex(i, uno.Any("[]string", 
styles))
         return index
 
     def generateTestTuple(self, values):
diff --git a/sw/qa/python/check_indexed_property_values.py 
b/sw/qa/python/check_indexed_property_values.py
index d6d314adc894..300c41c1a52a 100644
--- a/sw/qa/python/check_indexed_property_values.py
+++ b/sw/qa/python/check_indexed_property_values.py
@@ -51,34 +51,34 @@ class CheckIndexedPropertyValues(unittest.TestCase):
         prop3 = uno.Any("[]com.sun.star.beans.PropertyValue", (p3,))
 
         self.assertEqual(0, len(xCont), "Initial container is not empty")
-        uno.invoke(xCont, "insertByIndex", (0, prop1))
+        xCont.insertByIndex(0, prop1)
 
         ret = xCont[0]
         self.assertEqual(p1.Name, ret[0].Name)
         self.assertEqual(p1.Value, ret[0].Value)
 
-        uno.invoke(xCont, "replaceByIndex", (0, prop2))
+        xCont.replaceByIndex(0, prop2)
         ret = xCont[0]
         self.assertEqual(p2.Name, ret[0].Name)
         self.assertEqual(p2.Value, ret[0].Value)
 
         xCont.removeByIndex(0)
         self.assertTrue(not(xCont.hasElements()) and len(xCont) == 0, "Could 
not remove PropertyValue")
-        uno.invoke(xCont, "insertByIndex", (0, prop1))
-        uno.invoke(xCont, "insertByIndex", (1, prop2))
+        xCont.insertByIndex(0, prop1)
+        xCont.insertByIndex(1, prop2)
         self.assertTrue(xCont.hasElements() and len(xCont) == 2, "Did not 
insert PropertyValue")
 
-        uno.invoke(xCont, "insertByIndex", (1, prop2))
-        uno.invoke(xCont, "insertByIndex", (1, prop3))
+        xCont.insertByIndex(1, prop2)
+        xCont.insertByIndex(1, prop3)
         ret = xCont[1]
         self.assertEqual(p3.Name, ret[0].Name)
         self.assertEqual(p3.Value, ret[0].Value)
 
         with self.assertRaises(IndexOutOfBoundsException):
-            uno.invoke(xCont, "insertByIndex", (25, prop2))
+            xCont.insertByIndex(25, prop2)
 
         with self.assertRaises(IndexOutOfBoundsException):
             xCont.removeByIndex(25)
 
         with self.assertRaises(IllegalArgumentException):
-            uno.invoke(xCont, "insertByIndex", (3, "Example String"))
+            xCont.insertByIndex(3, "Example String")
diff --git a/sw/qa/python/check_named_property_values.py 
b/sw/qa/python/check_named_property_values.py
index 39d4b33cacc9..ef72c6e44fe1 100644
--- a/sw/qa/python/check_named_property_values.py
+++ b/sw/qa/python/check_named_property_values.py
@@ -51,20 +51,20 @@ class CheckNamedPropertyValues(unittest.TestCase):
 
         self.assertFalse(xCont.hasElements(),  "Initial container is not 
empty")
 
-        uno.invoke(xCont, "insertByName", ("prop1", prop1))
+        xCont.insertByName("prop1", prop1)
         ret = xCont["prop1"]
         self.assertEqual(p1.Name, ret[0].Name)
         self.assertEqual(p1.Value, ret[0].Value)
 
-        uno.invoke(xCont, "replaceByName", ("prop1", prop2))
+        xCont.replaceByName("prop1", prop2)
         ret = xCont["prop1"]
         self.assertEqual(p2.Name, ret[0].Name)
         self.assertEqual(p2.Value, ret[0].Value)
 
         xCont.removeByName("prop1")
         self.assertFalse(xCont.hasElements(), "Could not remove 
PropertyValue.")
-        uno.invoke(xCont, "insertByName", ("prop1", prop1))
-        uno.invoke(xCont, "insertByName", ("prop2", prop2))
+        xCont.insertByName("prop1", prop1)
+        xCont.insertByName("prop2", prop2)
         self.assertTrue(xCont.hasElements(), "Did not insert PropertyValue")
         names = xCont.getElementNames()
         self.assertEqual(2, len(names), "Not all element names were returned")
@@ -73,10 +73,10 @@ class CheckNamedPropertyValues(unittest.TestCase):
             self.assertIn(names[i], ["prop1", "prop2"], "Got a wrong element 
name")
 
         with self.assertRaises(ElementExistException):
-            uno.invoke(xCont, "insertByName", ("prop2", prop1))
+            xCont.insertByName("prop2", prop1)
 
         with self.assertRaises(IllegalArgumentException):
-            uno.invoke(xCont, "insertByName", ("prop3", "Example String"))
+            xCont.insertByName("prop3", "Example String")
 
         with self.assertRaises(NoSuchElementException):
             xCont.removeByName("prop3")
commit 507b6c2b907c54d37eea186ff07e340db6eed84a
Author:     Neil Roberts <[email protected]>
AuthorDate: Thu Dec 11 11:20:34 2025 +0100
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Thu Dec 18 10:05:39 2025 +0100

    tdf#169229: pyuno: Allow Any when calling a method
    
    Previously when creating a callable object for an attribute on an
    object (ie, a method), it would mark it with a special mode to disallow
    passing a pyuno.Any as an argument. There doesn’t seem to be a good
    reason to do this and it makes it difficult to use an explicit type when
    calling a method that can take an Any. This patch instead just removes
    the mode parameter from pyobject2Any entirely.
    
    The example in the bug report is trying to call
    createInstanceWithArgumentsAndContext which takes a Sequence of Anys as
    an argument. Without this patch it is difficult to pass a null interface
    as one of the arguments.
    
    Change-Id: I8756bdc2821ebf247ff67a66f071263ac00e3890
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195452
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>

diff --git a/pyuno/inc/pyuno.hxx b/pyuno/inc/pyuno.hxx
index f7cab36c7327..0a3b2796a577 100644
--- a/pyuno/inc/pyuno.hxx
+++ b/pyuno/inc/pyuno.hxx
@@ -150,9 +150,6 @@ public:
 //struct stRuntimeImpl;
 typedef struct stRuntimeImpl RuntimeImpl;
 
-enum ConversionMode { ACCEPT_UNO_ANY, REJECT_UNO_ANY };
-
-
 /** The pyuno::Runtime class keeps the internal state of the python UNO bridge
     for the currently in use python interpreter.
 
@@ -229,8 +226,7 @@ public:
 
         @throws css::uno::RuntimeException
     */
-    css::uno::Any pyObject2Any (
-        const PyRef & source , enum ConversionMode mode = REJECT_UNO_ANY ) 
const;
+    css::uno::Any pyObject2Any ( const PyRef & source ) const;
 
     /** extracts a proper uno exception from a given python exception
      */
diff --git a/pyuno/source/module/pyuno.cxx b/pyuno/source/module/pyuno.cxx
index abac37eecf08..76f06d289304 100644
--- a/pyuno/source/module/pyuno.cxx
+++ b/pyuno/source/module/pyuno.cxx
@@ -392,10 +392,7 @@ PyObject *PyUNO_invoke( PyObject *object, const char *name 
, PyObject *args )
             {
                 throw RuntimeException( "Attribute " + attrName + " unknown" );
             }
-            callable = PyUNO_callable_new (
-                me->members->xInvocation,
-                attrName,
-                ACCEPT_UNO_ANY);
+            callable = PyUNO_callable_new ( me->members->xInvocation, attrName 
);
             paras = args;
         }
         else
@@ -1446,7 +1443,7 @@ static int PyUNO_setattr (PyObject* self, char* name, 
PyObject* value)
     try
     {
         Runtime runtime;
-        Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
+        Any val= runtime.pyObject2Any(value);
 
         OUString attrName( OUString::createFromAscii( name ) );
         {
diff --git a/pyuno/source/module/pyuno_adapter.cxx 
b/pyuno/source/module/pyuno_adapter.cxx
index 72693f1cac17..a9502d34abd9 100644
--- a/pyuno/source/module/pyuno_adapter.cxx
+++ b/pyuno/source/module/pyuno_adapter.cxx
@@ -235,7 +235,7 @@ Any Adapter::invoke( const OUString &aFunctionName,
         raiseInvocationTargetExceptionWhenNeeded( runtime);
         if( pyRet.is() )
         {
-            ret = runtime.pyObject2Any( pyRet, ACCEPT_UNO_ANY );
+            ret = runtime.pyObject2Any( pyRet );
 
             if( ret.hasValue() &&
                 ret.getValueTypeClass() == css::uno::TypeClass_SEQUENCE &&
diff --git a/pyuno/source/module/pyuno_callable.cxx 
b/pyuno/source/module/pyuno_callable.cxx
index 3599fffb7cda..2c802aa70ef8 100644
--- a/pyuno/source/module/pyuno_callable.cxx
+++ b/pyuno/source/module/pyuno_callable.cxx
@@ -37,7 +37,6 @@ struct PyUNO_callable_Internals
 {
     Reference<XInvocation2> xInvocation;
     OUString methodName;
-    ConversionMode mode;
 };
 
 struct PyUNO_callable
@@ -75,7 +74,7 @@ static PyObject* PyUNO_callable_call(
     {
         Runtime runtime;
         cargo = runtime.getImpl()->cargo;
-        any_params = runtime.pyObject2Any (args, me->members->mode);
+        any_params = runtime.pyObject2Any (args);
 
         if (any_params.getValueTypeClass () == css::uno::TypeClass_SEQUENCE)
         {
@@ -256,8 +255,7 @@ static PyTypeObject PyUNO_callable_Type =
 
 PyRef PyUNO_callable_new (
     const Reference<XInvocation2> &my_inv,
-    const OUString & methodName,
-    enum ConversionMode mode )
+    const OUString & methodName )
 {
     PyUNO_callable* self;
 
@@ -270,7 +268,6 @@ PyRef PyUNO_callable_new (
     self->members = new PyUNO_callable_Internals;
     self->members->xInvocation = my_inv;
     self->members->methodName = methodName;
-    self->members->mode = mode;
 
     return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
 }
diff --git a/pyuno/source/module/pyuno_impl.hxx 
b/pyuno/source/module/pyuno_impl.hxx
index 878367d3764a..9dab16285ef3 100644
--- a/pyuno/source/module/pyuno_impl.hxx
+++ b/pyuno/source/module/pyuno_impl.hxx
@@ -177,8 +177,7 @@ void raiseInvocationTargetExceptionWhenNeeded( const 
Runtime &runtime );
 
 PyRef PyUNO_callable_new (
     const css::uno::Reference<css::script::XInvocation2> &xInv,
-    const OUString &methodName,
-    ConversionMode mode = REJECT_UNO_ANY );
+    const OUString &methodName );
 
 PyObject* PyUNO_Type_new (const char *typeName , css::uno::TypeClass t , const 
Runtime &r );
 PyObject* PyUNO_Enum_new( const char *enumBase, const char *enumValue, const 
Runtime &r );
diff --git a/pyuno/source/module/pyuno_module.cxx 
b/pyuno/source/module/pyuno_module.cxx
index e2edfeb601cd..b1eb13ec659c 100644
--- a/pyuno/source/module/pyuno_module.cxx
+++ b/pyuno/source/module/pyuno_module.cxx
@@ -161,7 +161,7 @@ void fillStruct(
             {
                 state.setInitialised(OUMemberName);
                 state.setUsed(pyMemberName);
-                Any a = runtime.pyObject2Any( element, ACCEPT_UNO_ANY );
+                Any a = runtime.pyObject2Any( element );
                 inv->setValue( OUMemberName, a );
             }
         }
@@ -174,7 +174,7 @@ void fillStruct(
             const OUString aMemberName (pCompType->ppMemberNames[i]);
             state.setInitialised(aMemberName, tupleIndex);
             PyObject *element = PyTuple_GetItem( initializer, tupleIndex );
-            Any a = runtime.pyObject2Any( element, ACCEPT_UNO_ANY );
+            Any a = runtime.pyObject2Any( element );
             inv->setValue( aMemberName, a );
         }
     }
diff --git a/pyuno/source/module/pyuno_runtime.cxx 
b/pyuno/source/module/pyuno_runtime.cxx
index 5840b249618f..48121acc6aff 100644
--- a/pyuno/source/module/pyuno_runtime.cxx
+++ b/pyuno/source/module/pyuno_runtime.cxx
@@ -662,7 +662,7 @@ bool Runtime::pyIterUnpack( PyObject *const pObj, Any &a ) 
const
     return true;
 }
 
-Any Runtime::pyObject2Any(const PyRef & source, enum ConversionMode mode) const
+Any Runtime::pyObject2Any(const PyRef & source) const
 {
     if (!impl || !impl->cargo->valid)
     {
@@ -726,7 +726,7 @@ Any Runtime::pyObject2Any(const PyRef & source, enum 
ConversionMode mode) const
         auto sRange = asNonConstRange(s);
         for (Py_ssize_t i = 0; i < PyTuple_Size (o); i++)
         {
-            sRange[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
+            sRange[i] = pyObject2Any (PyTuple_GetItem (o, i) );
         }
         a <<= s;
     }
@@ -737,7 +737,7 @@ Any Runtime::pyObject2Any(const PyRef & source, enum 
ConversionMode mode) const
         auto sRange = asNonConstRange(s);
         for (Py_ssize_t i = 0; i < l; i++)
         {
-            sRange[i] = pyObject2Any (PyList_GetItem (o, i), mode );
+            sRange[i] = pyObject2Any (PyList_GetItem (o, i) );
         }
         a <<= s;
     }
@@ -797,13 +797,6 @@ Any Runtime::pyObject2Any(const PyRef & source, enum 
ConversionMode mode) const
         }
         else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
         {
-            if( ACCEPT_UNO_ANY != mode )
-            {
-                throw RuntimeException(
-                    u"uno.Any instance not accepted during method call, "
-                    "use uno.invoke instead"_ustr );
-            }
-
             a = pyObject2Any( PyRef( PyObject_GetAttrString( o , "value" ), 
SAL_NO_ACQUIRE) );
             Type t;
             pyObject2Any( PyRef( PyObject_GetAttrString( o, "type" ), 
SAL_NO_ACQUIRE ) ) >>= t;
diff --git a/pyuno/source/module/pyuno_struct.cxx 
b/pyuno/source/module/pyuno_struct.cxx
index 6cba8664bb0a..2e94fbe5f98e 100644
--- a/pyuno/source/module/pyuno_struct.cxx
+++ b/pyuno/source/module/pyuno_struct.cxx
@@ -188,7 +188,7 @@ static int PyUNOStruct_setattr (PyObject* self, char* name, 
PyObject* value)
     try
     {
         Runtime runtime;
-        Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
+        Any val= runtime.pyObject2Any(value);
 
         OUString attrName( OUString::createFromAscii( name ) );
         {
diff --git a/pyuno/source/module/uno.py b/pyuno/source/module/uno.py
index b2a75bd03982..c5b5b25fa3ad 100644
--- a/pyuno/source/module/uno.py
+++ b/pyuno/source/module/uno.py
@@ -315,7 +315,9 @@ class ByteSequence:
 class Any:
     """Represents a UNO Any value.
 
-    Use only in connection with uno.invoke() to pass an explicit typed Any.
+    Use to pass an explicit typed Any. Note that before LibreOffice 26.8 it 
was not possible to pass
+    an Any as an argument to a method call and you had to use uno.invoke 
instead.
+
     """
 
     def __init__(self, type, value):
@@ -328,7 +330,12 @@ class Any:
 
 
 def invoke(object, methodname, argTuple):
-    """Use this function to pass exactly typed Anys to the callee (using 
uno.Any)."""
+    """Use this function to call an interface method named by a string.
+
+    Note that before LibreOffice 26.8 this function was needed in order to 
pass an Any as an
+    argument to a method call, but now it is possible to just directly call 
the method instead.
+
+    """
 
     return pyuno.invoke(object, methodname, argTuple)
 

Reply via email to