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)
