tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / pyuno / source / module / pyuno.cxx
blob0266afb200a72b9df933bda8b2fae9a29bf67aa8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <algorithm>
23 #include <cassert>
25 #include <rtl/ustrbuf.hxx>
27 #include <typelib/typedescription.hxx>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/lang/XTypeProvider.hpp>
31 #include <com/sun/star/beans/UnknownPropertyException.hpp>
32 #include <com/sun/star/container/XEnumerationAccess.hpp>
33 #include <com/sun/star/container/XIndexAccess.hpp>
34 #include <com/sun/star/container/XIndexContainer.hpp>
35 #include <com/sun/star/container/XIndexReplace.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
37 #include <com/sun/star/container/XNameContainer.hpp>
38 #include <com/sun/star/container/XNameReplace.hpp>
39 #include <com/sun/star/script/CannotConvertException.hpp>
40 #include <com/sun/star/script/XInvocation2.hpp>
41 #include <com/sun/star/script/XTypeConverter.hpp>
42 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
43 #include <comphelper/servicehelper.hxx>
45 #include "pyuno_impl.hxx"
47 using com::sun::star::uno::Sequence;
48 using com::sun::star::uno::Reference;
49 using com::sun::star::uno::XInterface;
50 using com::sun::star::uno::Any;
51 using com::sun::star::uno::UNO_QUERY;
52 using com::sun::star::uno::Type;
53 using com::sun::star::uno::TypeClass;
54 using com::sun::star::uno::TypeDescription;
55 using com::sun::star::uno::RuntimeException;
56 using com::sun::star::uno::Exception;
57 using com::sun::star::lang::XSingleServiceFactory;
58 using com::sun::star::lang::XServiceInfo;
59 using com::sun::star::lang::XTypeProvider;
60 using com::sun::star::lang::XUnoTunnel;
61 using com::sun::star::script::XInvocation2;
62 using com::sun::star::container::XEnumeration;
63 using com::sun::star::container::XEnumerationAccess;
64 using com::sun::star::container::XIndexAccess;
65 using com::sun::star::container::XIndexContainer;
66 using com::sun::star::container::XIndexReplace;
67 using com::sun::star::container::XNameAccess;
68 using com::sun::star::container::XNameContainer;
69 using com::sun::star::container::XNameReplace;
71 namespace pyuno
74 static PyObject *PyUNO_str( PyObject * self );
76 static void PyUNO_del (PyObject* self)
78 PyUNO* me = reinterpret_cast< PyUNO* > (self);
80 PyThreadDetach antiguard;
81 delete me->members;
83 PyObject_Del (self);
87 OUString val2str( const void * pVal, typelib_TypeDescriptionReference * pTypeRef , sal_Int32 mode )
89 assert( pVal );
90 if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
91 return u"void"_ustr;
93 OUStringBuffer buf( 64 );
94 buf.append( "(" + OUString::unacquired(&pTypeRef->pTypeName) + ")" );
96 switch (pTypeRef->eTypeClass)
98 case typelib_TypeClass_INTERFACE:
100 buf.append( "0x" +
101 OUString::number( reinterpret_cast< sal_IntPtr >(*static_cast<void * const *>(pVal)), 16 ));
102 if( VAL2STR_MODE_DEEP == mode )
104 buf.append( "{" ); Reference< XInterface > r = *static_cast<Reference< XInterface > const *>(pVal);
105 Reference< XServiceInfo > serviceInfo( r, UNO_QUERY);
106 Reference< XTypeProvider > typeProvider(r,UNO_QUERY);
107 if( serviceInfo.is() )
109 buf.append("implementationName="
110 + serviceInfo->getImplementationName()
111 + ", supportedServices={" );
112 Sequence< OUString > seq = serviceInfo->getSupportedServiceNames();
113 for( int i = 0 ; i < seq.getLength() ; i ++ )
115 buf.append( seq[i] );
116 if( i +1 != seq.getLength() )
117 buf.append( "," );
119 buf.append("}");
122 if( typeProvider.is() )
124 buf.append(", supportedInterfaces={" );
125 Sequence< Type > seq (typeProvider->getTypes());
126 for( int i = 0 ; i < seq.getLength() ; i ++ )
128 buf.append(seq[i].getTypeName());
129 if( i +1 != seq.getLength() )
130 buf.append( "," );
132 buf.append("}");
134 buf.append( "}" );
137 break;
139 case typelib_TypeClass_STRUCT:
140 case typelib_TypeClass_EXCEPTION:
142 buf.append( "{ " );
143 typelib_TypeDescription * pTypeDescr = nullptr;
144 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
145 assert( pTypeDescr );
147 typelib_CompoundTypeDescription * pCompType = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
148 sal_Int32 nDescr = pCompType->nMembers;
150 if (pCompType->pBaseTypeDescription)
152 buf.append( val2str( pVal, pCompType->pBaseTypeDescription->aBase.pWeakRef, mode ) );
153 if (nDescr)
154 buf.append( ", " );
157 typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
158 sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
159 rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
161 for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
163 buf.append( OUString::unacquired(&ppMemberNames[nPos]) + " = " );
164 typelib_TypeDescription * pMemberType = nullptr;
165 TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[nPos] );
166 buf.append( val2str( static_cast<char const *>(pVal) + pMemberOffsets[nPos], pMemberType->pWeakRef, mode ) );
167 TYPELIB_DANGER_RELEASE( pMemberType );
168 if (nPos < (nDescr -1))
169 buf.append( ", " );
172 TYPELIB_DANGER_RELEASE( pTypeDescr );
174 buf.append( " }" );
175 break;
177 case typelib_TypeClass_SEQUENCE:
179 typelib_TypeDescription * pTypeDescr = nullptr;
180 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
182 uno_Sequence * pSequence = *static_cast<uno_Sequence * const *>(pVal);
183 typelib_TypeDescription * pElementTypeDescr = nullptr;
184 TYPELIB_DANGER_GET( &pElementTypeDescr, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
186 sal_Int32 nElementSize = pElementTypeDescr->nSize;
187 sal_Int32 nElements = pSequence->nElements;
189 if (nElements)
191 buf.append( "{ " );
192 char * pElements = pSequence->elements;
193 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
195 buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef, mode ) );
196 if (nPos < (nElements -1))
197 buf.append( ", " );
199 buf.append( " }" );
201 else
203 buf.append( "{}" );
205 TYPELIB_DANGER_RELEASE( pElementTypeDescr );
206 TYPELIB_DANGER_RELEASE( pTypeDescr );
207 break;
209 case typelib_TypeClass_ANY:
210 buf.append( "{ "
211 + val2str( static_cast<uno_Any const *>(pVal)->pData,
212 static_cast<uno_Any const *>(pVal)->pType ,
213 mode)
214 + " }" );
215 break;
216 case typelib_TypeClass_TYPE:
217 buf.append( (*static_cast<typelib_TypeDescriptionReference * const *>(pVal))->pTypeName );
218 break;
219 case typelib_TypeClass_STRING:
220 buf.append( "\"" +
221 OUString::unacquired(&*static_cast<rtl_uString * const *>(pVal)) +
222 "\"" );
223 break;
224 case typelib_TypeClass_ENUM:
226 typelib_TypeDescription * pTypeDescr = nullptr;
227 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
229 sal_Int32 * pValues = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->pEnumValues;
230 sal_Int32 nPos = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nEnumValues;
231 while (nPos--)
233 if (pValues[nPos] == *static_cast<int const *>(pVal))
234 break;
236 if (nPos >= 0)
237 buf.append( reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->ppEnumNames[nPos] );
238 else
239 buf.append( '?' );
241 TYPELIB_DANGER_RELEASE( pTypeDescr );
242 break;
244 case typelib_TypeClass_BOOLEAN:
245 if (*static_cast<sal_Bool const *>(pVal))
246 buf.append( "true" );
247 else
248 buf.append( "false" );
249 break;
250 case typelib_TypeClass_CHAR:
251 buf.append( "\'"
252 + OUStringChar(*static_cast<sal_Unicode const *>(pVal) )
253 + "\'" );
254 break;
255 case typelib_TypeClass_FLOAT:
256 buf.append( *static_cast<float const *>(pVal) );
257 break;
258 case typelib_TypeClass_DOUBLE:
259 buf.append( *static_cast<double const *>(pVal) );
260 break;
261 case typelib_TypeClass_BYTE:
262 buf.append( "0x" +
263 OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int8 const *>(pVal)), 16 ));
264 break;
265 case typelib_TypeClass_SHORT:
266 buf.append( "0x" +
267 OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int16 const *>(pVal)), 16 ));
268 break;
269 case typelib_TypeClass_UNSIGNED_SHORT:
270 buf.append( "0x" +
271 OUString::number( static_cast<sal_Int32>(*static_cast<sal_uInt16 const *>(pVal)), 16 ));
272 break;
273 case typelib_TypeClass_LONG:
274 buf.append( "0x" +
275 OUString::number( *static_cast<sal_Int32 const *>(pVal), 16 ));
276 break;
277 case typelib_TypeClass_UNSIGNED_LONG:
278 buf.append( "0x" +
279 OUString::number( static_cast<sal_Int64>(*static_cast<sal_uInt32 const *>(pVal)), 16 ));
280 break;
281 case typelib_TypeClass_HYPER:
282 case typelib_TypeClass_UNSIGNED_HYPER:
283 buf.append( "0x" );
284 #if defined(__GNUC__) && defined(SPARC)
285 // I guess this really should check if there are strict alignment
286 // requirements, not just "GCC on SPARC".
288 sal_Int64 aVal;
289 *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
290 *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
291 buf.append( aVal, 16 );
293 #else
294 buf.append( *static_cast<sal_Int64 const *>(pVal), 16 );
295 #endif
296 break;
298 case typelib_TypeClass_VOID:
299 case typelib_TypeClass_UNKNOWN:
300 case typelib_TypeClass_SERVICE:
301 case typelib_TypeClass_MODULE:
302 default:
303 buf.append( '?' );
306 return buf.makeStringAndClear();
309 static sal_Int32 lcl_PyNumber_AsSal_Int32( PyObject *pObj )
311 // Check object is an index
312 PyRef rIndex( PyNumber_Index( pObj ), SAL_NO_ACQUIRE );
313 if ( !rIndex.is() )
314 return -1;
316 // Convert Python number to platform long, then check actual value against
317 // bounds of sal_Int32
318 int nOverflow;
319 long nResult = PyLong_AsLongAndOverflow( pObj, &nOverflow );
320 if ( nOverflow || nResult > SAL_MAX_INT32 || nResult < SAL_MIN_INT32) {
321 PyErr_SetString( PyExc_IndexError, "Python int too large to convert to UNO long" );
322 return -1;
325 return nResult;
328 static int lcl_PySlice_GetIndicesEx( PyObject *pObject, sal_Int32 nLen, sal_Int32 *nStart, sal_Int32 *nStop, sal_Int32 *nStep, sal_Int32 *nSliceLength )
330 Py_ssize_t nStart_ssize, nStop_ssize, nStep_ssize, nSliceLength_ssize;
332 int nResult = PySlice_GetIndicesEx(pObject,
333 nLen, &nStart_ssize, &nStop_ssize, &nStep_ssize, &nSliceLength_ssize );
334 if (nResult == -1)
335 return -1;
337 if ( nStart_ssize > SAL_MAX_INT32 || nStart_ssize < SAL_MIN_INT32
338 || nStop_ssize > SAL_MAX_INT32 || nStop_ssize < SAL_MIN_INT32
339 || nStep_ssize > SAL_MAX_INT32 || nStep_ssize < SAL_MIN_INT32
340 || nSliceLength_ssize > SAL_MAX_INT32 || nSliceLength_ssize < SAL_MIN_INT32 )
342 PyErr_SetString( PyExc_IndexError, "Python int too large to convert to UNO long" );
343 return -1;
346 *nStart = static_cast<sal_Int32>(nStart_ssize);
347 *nStop = static_cast<sal_Int32>(nStop_ssize);
348 *nStep = static_cast<sal_Int32>(nStep_ssize);
349 *nSliceLength = static_cast<sal_Int32>(nSliceLength_ssize);
350 return 0;
353 static bool lcl_hasInterfaceByName( Any const &object, OUString const & interfaceName )
355 Reference< XInterface > xInterface( object, UNO_QUERY );
356 TypeDescription typeDesc( interfaceName );
357 Any aInterface = xInterface->queryInterface( typeDesc.get()->pWeakRef );
359 return aInterface.hasValue();
362 static PyObject *PyUNO_repr( PyObject * self )
364 return PyUNO_str( self );
367 static Py_hash_t PyUNO_hash( PyObject *self )
370 PyUNO *me = reinterpret_cast<PyUNO *>(self);
372 // Py_hash_t is not necessarily the same size as a pointer, but this is not
373 // important for hashing - it just has to return the same value each time
374 return sal::static_int_cast< Py_hash_t >( reinterpret_cast< sal_IntPtr > (
375 *static_cast<void * const *>(me->members->wrappedObject.getValue()) ) );
379 PyObject *PyUNO_invoke( PyObject *object, const char *name , PyObject *args )
381 PyRef ret;
384 Runtime runtime;
386 PyRef paras,callable;
387 if( PyObject_IsInstance( object, getPyUnoClass().get() ) )
389 PyUNO* me = reinterpret_cast<PyUNO*>(object);
390 OUString attrName = OUString::createFromAscii(name);
391 if (! me->members->xInvocation->hasMethod (attrName))
393 throw RuntimeException( "Attribute " + attrName + " unknown" );
395 callable = PyUNO_callable_new (
396 me->members->xInvocation,
397 attrName,
398 ACCEPT_UNO_ANY);
399 paras = args;
401 else
403 // clean the tuple from uno.Any !
404 int size = PyTuple_Size( args );
405 { // for CC, keeping ref-count of tuple being 1
406 paras = PyRef(PyTuple_New( size ), SAL_NO_ACQUIRE);
408 for( int i = 0 ; i < size ;i ++ )
410 PyObject * element = PyTuple_GetItem( args , i );
411 if( PyObject_IsInstance( element , getAnyClass( runtime ).get() ) )
413 element = PyObject_GetAttrString(
414 element, "value" );
416 else
418 Py_XINCREF( element );
420 PyTuple_SetItem( paras.get(), i , element );
422 callable = PyRef( PyObject_GetAttrString( object , name ), SAL_NO_ACQUIRE );
423 if( !callable.is() )
424 return nullptr;
426 ret = PyRef( PyObject_CallObject( callable.get(), paras.get() ), SAL_NO_ACQUIRE );
428 catch (const css::lang::IllegalArgumentException &e)
430 raisePyExceptionWithAny( css::uno::Any( e ) );
432 catch (const css::script::CannotConvertException &e)
434 raisePyExceptionWithAny( css::uno::Any( e ) );
436 catch (const css::uno::RuntimeException &e)
438 raisePyExceptionWithAny( css::uno::Any( e ) );
440 catch (const css::uno::Exception &e)
442 raisePyExceptionWithAny( css::uno::Any( e ) );
445 return ret.getAcquired();
448 PyObject *PyUNO_str( PyObject * self )
450 PyUNO *me = reinterpret_cast<PyUNO *>(self);
452 OString buf;
455 PyThreadDetach antiguard;
457 OUString s = val2str( me->members->wrappedObject.getValue(),
458 me->members->wrappedObject.getValueType().getTypeLibType() );
459 buf = "pyuno object " + OUStringToOString(s,RTL_TEXTENCODING_ASCII_US);
462 return PyUnicode_FromString( buf.getStr() );
465 static PyObject* PyUNO_dir (PyObject* self)
467 PyUNO* me = reinterpret_cast<PyUNO*>(self);
469 PyObject* member_list = nullptr;
470 Sequence<OUString> oo_member_list;
474 oo_member_list = me->members->xInvocation->getMemberNames ();
475 member_list = PyList_New (oo_member_list.getLength ());
476 for (int i = 0; i < oo_member_list.getLength (); i++)
478 // setitem steals a reference
479 PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() );
482 catch( const RuntimeException &e )
484 raisePyExceptionWithAny( Any(e) );
487 return member_list;
490 static sal_Int32 lcl_detach_getLength( PyUNO const *me )
492 PyThreadDetach antiguard;
494 // If both XIndexContainer and XNameContainer are implemented, it is
495 // assumed that getCount() gives the same result as the number of names
496 // returned by getElementNames(), or the user may be surprised.
498 // For XIndexContainer
499 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
500 if ( xIndexAccess.is() )
502 return xIndexAccess->getCount();
505 // For XNameContainer
506 // Not terribly efficient - get the count of all the names
507 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
508 if ( xNameAccess.is() )
510 return xNameAccess->getElementNames().getLength();
513 return -1;
516 static int PyUNO_bool( PyObject* self )
518 PyUNO* me = reinterpret_cast<PyUNO*>(self);
522 int nLen = lcl_detach_getLength( me );
523 if (nLen >= 0)
524 return nLen == 0 ? 0 : 1;
526 // Anything which doesn't have members is a scalar object and therefore true
527 return 1;
529 catch( const css::uno::RuntimeException &e )
531 raisePyExceptionWithAny( css::uno::Any( e ) );
534 return -1;
537 static Py_ssize_t PyUNO_len( PyObject* self )
539 PyUNO* me = reinterpret_cast<PyUNO*>(self);
543 int nLen = lcl_detach_getLength( me );
544 if (nLen >= 0)
545 return nLen;
547 PyErr_SetString( PyExc_TypeError, "object has no len()" );
549 catch( const css::uno::RuntimeException &e )
551 raisePyExceptionWithAny( css::uno::Any( e ) );
554 return -1;
557 static void lcl_getRowsColumns( PyUNO const * me, sal_Int32& nRows, sal_Int32& nColumns )
559 Sequence<short> aOutParamIndex;
560 Sequence<Any> aOutParam;
561 Sequence<Any> aParams;
562 Any aRet = me->members->xInvocation->invoke ( u"getRows"_ustr, aParams, aOutParamIndex, aOutParam );
563 Reference< XIndexAccess > xIndexAccessRows( aRet, UNO_QUERY );
564 nRows = xIndexAccessRows->getCount();
565 aRet = me->members->xInvocation->invoke ( u"getColumns"_ustr, aParams, aOutParamIndex, aOutParam );
566 Reference< XIndexAccess > xIndexAccessCols( aRet, UNO_QUERY );
567 nColumns = xIndexAccessCols->getCount();
570 static PyRef lcl_indexToSlice( const PyRef& rIndex )
572 Py_ssize_t nIndex = PyNumber_AsSsize_t( rIndex.get(), PyExc_IndexError );
573 if (nIndex == -1 && PyErr_Occurred())
574 return nullptr;
575 PyRef rStart( PyLong_FromSsize_t( nIndex ), SAL_NO_ACQUIRE );
576 PyRef rStop( PyLong_FromSsize_t( nIndex+1 ), SAL_NO_ACQUIRE );
577 PyRef rStep( PyLong_FromLong( 1 ), SAL_NO_ACQUIRE );
578 PyRef rSlice( PySlice_New( rStart.get(), rStop.get(), rStep.get() ), SAL_NO_ACQUIRE );
580 return rSlice;
583 static PyObject* lcl_getitem_XCellRange( PyUNO const * me, PyObject* pKey )
585 Runtime runtime;
587 Sequence<short> aOutParamIndex;
588 Sequence<Any> aOutParam;
589 Sequence<Any> aParams;
590 Any aRet;
592 // Single string key is sugar for getCellRangeByName()
593 if ( PyUnicode_Check( pKey ) ) {
595 aParams = { Any(pyString2ustring( pKey )) };
597 PyThreadDetach antiguard;
598 aRet = me->members->xInvocation->invoke (
599 u"getCellRangeByName"_ustr, aParams, aOutParamIndex, aOutParam );
601 PyRef rRet = runtime.any2PyObject ( aRet );
602 return rRet.getAcquired();
606 PyRef rKey0, rKey1;
607 if ( PyIndex_Check( pKey ) )
609 // [0] is equivalent to [0,:]
610 rKey0 = pKey;
611 rKey1 = PySlice_New( nullptr, nullptr, nullptr );
613 else if ( PyTuple_Check( pKey ) && (PyTuple_Size( pKey ) == 2) )
615 rKey0 = PyTuple_GetItem( pKey, 0 );
616 rKey1 = PyTuple_GetItem( pKey, 1 );
618 else
620 PyErr_SetString( PyExc_KeyError, "invalid subscript" );
621 return nullptr;
624 // If both keys are indices, return the corresponding cell
625 if ( PyIndex_Check( rKey0.get() ) && PyIndex_Check( rKey1.get() ))
627 sal_Int32 nKey0_s = lcl_PyNumber_AsSal_Int32( rKey0.get() );
628 sal_Int32 nKey1_s = lcl_PyNumber_AsSal_Int32( rKey1.get() );
630 if ( ((nKey0_s == -1) || (nKey1_s == -1)) && PyErr_Occurred() )
631 return nullptr;
633 aParams = { Any(nKey1_s), Any(nKey0_s) };
635 PyThreadDetach antiguard;
636 aRet = me->members->xInvocation->invoke (
637 u"getCellByPosition"_ustr, aParams, aOutParamIndex, aOutParam );
639 PyRef rRet = runtime.any2PyObject( aRet );
640 return rRet.getAcquired();
643 // If either argument is an index, coerce it to a slice
644 if ( PyIndex_Check( rKey0.get() ) )
645 rKey0 = lcl_indexToSlice( rKey0 );
647 if ( PyIndex_Check( rKey1.get() ) )
648 rKey1 = lcl_indexToSlice( rKey1 );
650 // If both arguments are slices, return the corresponding cell range
651 if ( PySlice_Check( rKey0.get() ) && PySlice_Check( rKey1.get() ) )
653 sal_Int32 nLen0 = SAL_MAX_INT32, nLen1 = SAL_MAX_INT32;
654 sal_Int32 nStart0 = 0, nStop0 = 0, nStep0 = 0, nSliceLength0 = 0;
655 sal_Int32 nStart1 = 0, nStop1 = 0, nStep1 = 0, nSliceLength1 = 0;
658 PyThreadDetach antiguard;
660 if ( lcl_hasInterfaceByName( me->members->wrappedObject, u"com.sun.star.table.XColumnRowRange"_ustr ) )
662 lcl_getRowsColumns (me, nLen0, nLen1);
666 int nSuccess1 = lcl_PySlice_GetIndicesEx( rKey0.get(), nLen0, &nStart0, &nStop0, &nStep0, &nSliceLength0 );
667 int nSuccess2 = lcl_PySlice_GetIndicesEx( rKey1.get(), nLen1, &nStart1, &nStop1, &nStep1, &nSliceLength1 );
668 if ( ((nSuccess1 == -1) || (nSuccess2 == -1)) && PyErr_Occurred() )
669 return nullptr;
671 if ( nSliceLength0 <= 0 || nSliceLength1 <= 0 )
673 PyErr_SetString( PyExc_KeyError, "invalid number of rows or columns" );
674 return nullptr;
677 if ( nStep0 == 1 && nStep1 == 1 )
679 aParams = { Any(nStart1), Any(nStart0), Any(nStop1 - 1), Any(nStop0 - 1) };
681 PyThreadDetach antiguard;
682 aRet = me->members->xInvocation->invoke (
683 u"getCellRangeByPosition"_ustr, aParams, aOutParamIndex, aOutParam );
685 PyRef rRet = runtime.any2PyObject( aRet );
686 return rRet.getAcquired();
689 PyErr_SetString( PyExc_KeyError, "step != 1 not supported" );
690 return nullptr;
693 PyErr_SetString( PyExc_KeyError, "invalid subscript" );
694 return nullptr;
697 static PyObject* lcl_getitem_index( PyUNO const *me, PyObject *pKey, Runtime const & runtime )
699 Any aRet;
700 sal_Int32 nIndex;
702 nIndex = lcl_PyNumber_AsSal_Int32( pKey );
703 if (nIndex == -1 && PyErr_Occurred())
704 return nullptr;
707 PyThreadDetach antiguard;
709 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
710 if ( xIndexAccess.is() )
712 if (nIndex < 0)
713 nIndex += xIndexAccess->getCount();
714 aRet = xIndexAccess->getByIndex( nIndex );
717 if ( aRet.hasValue() )
719 PyRef rRet ( runtime.any2PyObject( aRet ) );
720 return rRet.getAcquired();
723 return nullptr;
726 static PyObject* lcl_getitem_slice( PyUNO const *me, PyObject *pKey )
728 Runtime runtime;
730 Reference< XIndexAccess > xIndexAccess;
731 sal_Int32 nLen = 0;
734 PyThreadDetach antiguard;
736 xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
737 if ( xIndexAccess.is() )
738 nLen = xIndexAccess->getCount();
741 if ( !xIndexAccess )
742 return nullptr;
744 sal_Int32 nStart = 0, nStop = 0, nStep = 0, nSliceLength = 0;
745 int nSuccess = lcl_PySlice_GetIndicesEx(pKey, nLen, &nStart, &nStop, &nStep, &nSliceLength);
746 if ( nSuccess == -1 && PyErr_Occurred() )
747 return nullptr;
749 PyRef rTuple( PyTuple_New( nSliceLength ), SAL_NO_ACQUIRE, NOT_NULL );
750 sal_Int32 nCur, i;
751 for ( nCur = nStart, i = 0; i < nSliceLength; nCur += nStep, i++ )
753 Any aRet;
756 PyThreadDetach antiguard;
758 aRet = xIndexAccess->getByIndex( nCur );
760 PyRef rRet = runtime.any2PyObject( aRet );
761 PyTuple_SetItem( rTuple.get(), i, rRet.getAcquired() );
764 return rTuple.getAcquired();
767 static PyObject* lcl_getitem_string( PyUNO const *me, PyObject *pKey, Runtime const & runtime )
769 OUString sKey = pyString2ustring( pKey );
770 Any aRet;
773 PyThreadDetach antiguard;
775 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
776 if ( xNameAccess.is() )
778 aRet = xNameAccess->getByName( sKey );
781 if ( aRet.hasValue() )
783 PyRef rRet = runtime.any2PyObject( aRet );
784 return rRet.getAcquired();
787 return nullptr;
790 static PyObject* PyUNO_getitem( PyObject *self, PyObject *pKey )
792 PyUNO* me = reinterpret_cast<PyUNO*>(self);
793 Runtime runtime;
797 // XIndexAccess access by index
798 if ( PyIndex_Check( pKey ) )
800 PyObject* pRet = lcl_getitem_index( me, pKey, runtime );
801 if ( pRet != nullptr || PyErr_Occurred() )
802 return pRet;
805 // XIndexAccess access by slice
806 if ( PySlice_Check( pKey ) )
808 PyObject* pRet = lcl_getitem_slice( me, pKey );
809 if ( pRet != nullptr || PyErr_Occurred() )
810 return pRet;
813 // XNameAccess access by key
814 if ( PyUnicode_Check( pKey ) )
816 PyObject* pRet = lcl_getitem_string( me, pKey, runtime );
817 if ( pRet != nullptr )
818 return pRet;
821 // XCellRange/XColumnRowRange specialisation
822 // Uses reflection as we can't have a hard dependency on XCellRange here
823 bool hasXCellRange = false;
826 PyThreadDetach antiguard;
828 hasXCellRange = lcl_hasInterfaceByName( me->members->wrappedObject, u"com.sun.star.table.XCellRange"_ustr );
830 if ( hasXCellRange )
832 return lcl_getitem_XCellRange( me, pKey );
836 // If the object is an XIndexAccess and/or XNameAccess, but the
837 // key passed wasn't suitable, give a TypeError which specifically
838 // describes this
839 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
840 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
841 if ( xIndexAccess.is() || xNameAccess.is() )
843 PyErr_SetString( PyExc_TypeError, "subscription with invalid type" );
844 return nullptr;
847 PyErr_SetString( PyExc_TypeError, "object is not subscriptable" );
849 catch( const css::lang::IndexOutOfBoundsException & )
851 PyErr_SetString( PyExc_IndexError, "index out of range" );
853 catch( const css::container::NoSuchElementException & )
855 PyErr_SetString( PyExc_KeyError, "key not found" );
857 catch( const css::script::CannotConvertException &e )
859 raisePyExceptionWithAny( css::uno::Any( e ) );
861 catch( const css::lang::IllegalArgumentException &e )
863 raisePyExceptionWithAny( css::uno::Any( e ) );
865 catch( const css::lang::WrappedTargetException &e )
867 raisePyExceptionWithAny( css::uno::Any( e ) );
869 catch( const css::uno::RuntimeException &e )
871 raisePyExceptionWithAny( css::uno::Any( e ) );
874 return nullptr;
877 static int lcl_setitem_index( PyUNO const *me, PyObject *pKey, PyObject *pValue )
879 Runtime runtime;
881 Reference< XIndexContainer > xIndexContainer;
882 Reference< XIndexReplace > xIndexReplace;
883 sal_Int32 nIndex = lcl_PyNumber_AsSal_Int32( pKey );
884 if ( nIndex == -1 && PyErr_Occurred() )
885 return 0;
887 bool isTuple = false;
889 Any aValue;
890 if ( pValue != nullptr )
892 isTuple = PyTuple_Check( pValue );
896 aValue = runtime.pyObject2Any( pValue );
898 catch ( const css::uno::RuntimeException & )
900 // TODO pyObject2Any can't convert e.g. dicts but only throws
901 // RuntimeException on failure. Fixing this will require an audit of
902 // all the rest of PyUNO
903 throw css::script::CannotConvertException();
908 PyThreadDetach antiguard;
910 xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
911 if ( xIndexContainer.is() )
912 xIndexReplace = xIndexContainer;
913 else
914 xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
916 if ( xIndexReplace.is() && nIndex < 0 )
917 nIndex += xIndexReplace->getCount();
919 // XIndexReplace replace by index
920 if ( (pValue != nullptr) && xIndexReplace.is() )
922 if ( isTuple )
924 // Apply type specialisation to ensure the correct kind of sequence is passed
925 Type aType = xIndexReplace->getElementType();
926 aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
929 xIndexReplace->replaceByIndex( nIndex, aValue );
930 return 0;
933 // XIndexContainer remove by index
934 if ( (pValue == nullptr) && xIndexContainer.is() )
936 xIndexContainer->removeByIndex( nIndex );
937 return 0;
941 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
942 return -1;
945 static int lcl_setitem_slice( PyUNO const *me, PyObject *pKey, PyObject *pValue )
947 // XIndexContainer insert/remove/replace by slice
948 Runtime runtime;
950 Reference< XIndexReplace > xIndexReplace;
951 Reference< XIndexContainer > xIndexContainer;
952 sal_Int32 nLen = 0;
955 PyThreadDetach antiguard;
957 xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
958 if ( xIndexContainer.is() )
959 xIndexReplace = xIndexContainer;
960 else
961 xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
963 if ( xIndexReplace.is() )
964 nLen = xIndexReplace->getCount();
967 if ( xIndexReplace.is() )
969 sal_Int32 nStart = 0, nStop = 0, nStep = 0, nSliceLength = 0;
970 int nSuccess = lcl_PySlice_GetIndicesEx( pKey, nLen, &nStart, &nStop, &nStep, &nSliceLength );
971 if ( (nSuccess == -1) && PyErr_Occurred() )
972 return 0;
974 if ( pValue == nullptr )
976 pValue = PyTuple_New( 0 );
979 if ( !PyTuple_Check (pValue) )
981 PyErr_SetString( PyExc_TypeError, "value is not a tuple" );
982 return -1;
985 Py_ssize_t nTupleLength_ssize = PyTuple_Size( pValue );
986 if ( nTupleLength_ssize > SAL_MAX_INT32 )
988 PyErr_SetString( PyExc_ValueError, "tuple too large" );
989 return -1;
991 sal_Int32 nTupleLength = static_cast<sal_Int32>(nTupleLength_ssize);
993 if ( (nTupleLength != nSliceLength) && (nStep != 1) )
995 PyErr_SetString( PyExc_ValueError, "number of items assigned must be equal" );
996 return -1;
999 if ( (nTupleLength != nSliceLength) && !xIndexContainer.is() )
1001 PyErr_SetString( PyExc_ValueError, "cannot change length" );
1002 return -1;
1005 sal_Int32 nCur, i;
1006 sal_Int32 nMax = ::std::max( nSliceLength, nTupleLength );
1007 for ( nCur = nStart, i = 0; i < nMax; nCur += nStep, i++ )
1009 if ( i < nTupleLength )
1011 PyRef rItem = PyTuple_GetItem( pValue, i );
1012 bool isTuple = PyTuple_Check( rItem.get() );
1014 Any aItem;
1017 aItem = runtime.pyObject2Any( rItem.get() );
1019 catch ( const css::uno::RuntimeException & )
1021 // TODO pyObject2Any can't convert e.g. dicts but only throws
1022 // RuntimeException on failure. Fixing this will require an audit of
1023 // all the rest of PyUNO
1024 throw css::script::CannotConvertException();
1028 PyThreadDetach antiguard;
1030 if ( isTuple )
1032 // Apply type specialisation to ensure the correct kind of sequence is passed
1033 Type aType = xIndexReplace->getElementType();
1034 aItem = runtime.getImpl()->cargo->xTypeConverter->convertTo( aItem, aType );
1037 if ( i < nSliceLength )
1039 xIndexReplace->replaceByIndex( nCur, aItem );
1041 else
1043 xIndexContainer->insertByIndex( nCur, aItem );
1047 else
1049 PyThreadDetach antiguard;
1051 xIndexContainer->removeByIndex( nCur );
1052 nCur--;
1056 return 0;
1059 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
1060 return -1;
1063 static int lcl_setitem_string( PyUNO const *me, PyObject *pKey, PyObject *pValue )
1065 Runtime runtime;
1067 OUString sKey = pyString2ustring( pKey );
1068 bool isTuple = false;
1070 Any aValue;
1071 if ( pValue != nullptr)
1073 isTuple = PyTuple_Check( pValue );
1076 aValue = runtime.pyObject2Any( pValue );
1078 catch( const css::uno::RuntimeException & )
1080 // TODO pyObject2Any can't convert e.g. dicts but only throws
1081 // RuntimeException on failure. Fixing this will require an audit of
1082 // all the rest of PyUNO
1083 throw css::script::CannotConvertException();
1088 PyThreadDetach antiguard;
1090 Reference< XNameContainer > xNameContainer( me->members->xInvocation, UNO_QUERY );
1091 Reference< XNameReplace > xNameReplace;
1092 if ( xNameContainer.is() )
1093 xNameReplace = xNameContainer;
1094 else
1095 xNameReplace.set( me->members->xInvocation, UNO_QUERY );
1097 if ( xNameReplace.is() )
1099 if ( isTuple && aValue.hasValue() )
1101 // Apply type specialisation to ensure the correct kind of sequence is passed
1102 Type aType = xNameReplace->getElementType();
1103 aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
1106 if ( aValue.hasValue() )
1108 if ( xNameContainer.is() )
1110 try {
1111 xNameContainer->insertByName( sKey, aValue );
1112 return 0;
1114 catch( const css::container::ElementExistException & )
1116 // Fall through, try replace instead
1120 xNameReplace->replaceByName( sKey, aValue );
1121 return 0;
1123 else if ( xNameContainer.is() )
1125 xNameContainer->removeByName( sKey );
1126 return 0;
1131 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
1132 return -1;
1135 static int PyUNO_setitem( PyObject *self, PyObject *pKey, PyObject *pValue )
1137 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1141 if ( PyIndex_Check( pKey ) )
1143 return lcl_setitem_index( me, pKey, pValue );
1145 else if ( PySlice_Check( pKey ) )
1147 return lcl_setitem_slice( me, pKey, pValue );
1149 else if ( PyUnicode_Check( pKey ) )
1151 return lcl_setitem_string( me, pKey, pValue );
1154 PyErr_SetString( PyExc_TypeError, "list index has invalid type" );
1156 catch( const css::lang::IndexOutOfBoundsException & )
1158 PyErr_SetString( PyExc_IndexError, "list index out of range" );
1160 catch( const css::container::NoSuchElementException & )
1162 PyErr_SetString( PyExc_KeyError, "key not found" );
1164 catch( const css::lang::IllegalArgumentException & )
1166 PyErr_SetString( PyExc_TypeError, "value has invalid type" );
1168 catch( const css::script::CannotConvertException & )
1170 PyErr_SetString( PyExc_TypeError, "value has invalid type" );
1172 catch( const css::container::ElementExistException &e )
1174 raisePyExceptionWithAny( css::uno::Any( e ) );
1176 catch( const css::lang::WrappedTargetException &e )
1178 raisePyExceptionWithAny( css::uno::Any( e ) );
1180 catch( const css::uno::RuntimeException &e )
1182 raisePyExceptionWithAny( css::uno::Any( e ) );
1185 return -1;
1188 static PyObject* PyUNO_iter( PyObject *self )
1190 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1194 Reference< XEnumerationAccess > xEnumerationAccess;
1195 Reference< XEnumeration > xEnumeration;
1196 Reference< XIndexAccess > xIndexAccess;
1197 Reference< XNameAccess > xNameAccess;
1200 PyThreadDetach antiguard;
1202 xEnumerationAccess.set( me->members->xInvocation, UNO_QUERY );
1203 if ( xEnumerationAccess.is() )
1204 xEnumeration = xEnumerationAccess->createEnumeration();
1205 else
1206 xEnumeration.set( me->members->wrappedObject, UNO_QUERY );
1208 if ( !xEnumeration.is() )
1209 xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
1211 if ( !xIndexAccess.is() )
1212 xNameAccess.set( me->members->xInvocation, UNO_QUERY );
1215 // XEnumerationAccess iterator
1216 // XEnumeration iterator
1217 if (xEnumeration.is())
1219 return PyUNO_iterator_new( xEnumeration );
1222 // XIndexAccess iterator
1223 if ( xIndexAccess.is() )
1225 // We'd like to be able to use PySeqIter_New() here, but we're not
1226 // allowed to because we also implement the mapping protocol
1227 return PyUNO_list_iterator_new( xIndexAccess );
1230 // XNameAccess iterator
1231 if (xNameAccess.is())
1233 // There's no generic mapping iterator, but we can cobble our own
1234 // together using PySeqIter_New()
1235 Runtime runtime;
1236 Any aRet;
1239 PyThreadDetach antiguard;
1240 aRet <<= xNameAccess->getElementNames();
1242 PyRef rNames = runtime.any2PyObject( aRet );
1243 return PySeqIter_New( rNames.getAcquired() );
1246 PyErr_SetString ( PyExc_TypeError, "object is not iterable" );
1248 catch( css::script::CannotConvertException &e )
1250 raisePyExceptionWithAny( css::uno::Any( e ) );
1252 catch( css::lang::IllegalArgumentException &e )
1254 raisePyExceptionWithAny( css::uno::Any( e ) );
1256 catch( const css::uno::RuntimeException &e )
1258 raisePyExceptionWithAny( css::uno::Any( e ) );
1261 return nullptr;
1264 static int PyUNO_contains( PyObject *self, PyObject *pKey )
1266 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1268 Runtime runtime;
1272 Any aValue;
1275 aValue = runtime.pyObject2Any( pKey );
1277 catch( const css::uno::RuntimeException & )
1279 // TODO pyObject2Any can't convert e.g. dicts but only throws
1280 // RuntimeException on failure. Fixing this will require an audit of
1281 // all the rest of PyUNO
1282 throw css::script::CannotConvertException();
1285 // XNameAccess is tried first, because checking key presence is much more
1286 // useful for objects which implement both XIndexAccess and XNameAccess
1288 // For XNameAccess
1289 if ( PyUnicode_Check( pKey ) )
1291 OUString sKey;
1292 aValue >>= sKey;
1293 Reference< XNameAccess > xNameAccess;
1296 PyThreadDetach antiguard;
1298 xNameAccess.set( me->members->xInvocation, UNO_QUERY );
1299 if ( xNameAccess.is() )
1301 bool hasKey = xNameAccess->hasByName( sKey );
1302 return hasKey ? 1 : 0;
1307 // For any other type of PyUNO iterable: Ugly iterative search by
1308 // content (XIndexAccess, XEnumerationAccess, XEnumeration)
1309 PyRef rIterator( PyUNO_iter( self ), SAL_NO_ACQUIRE );
1310 if ( rIterator.is() )
1312 while ( PyObject* pItem = PyIter_Next( rIterator.get() ) )
1314 PyRef rItem( pItem, SAL_NO_ACQUIRE );
1315 if ( PyObject_RichCompareBool( pKey, rItem.get(), Py_EQ ) == 1 )
1317 return 1;
1320 return 0;
1323 PyErr_SetString( PyExc_TypeError, "argument is not iterable" );
1325 catch( const css::script::CannotConvertException& )
1327 PyErr_SetString( PyExc_TypeError, "invalid type passed as left argument to 'in'" );
1329 catch( const css::container::NoSuchElementException &e )
1331 raisePyExceptionWithAny( css::uno::Any( e ) );
1333 catch( const css::lang::IndexOutOfBoundsException &e )
1335 raisePyExceptionWithAny( css::uno::Any( e ) );
1337 catch( const css::lang::IllegalArgumentException &e )
1339 raisePyExceptionWithAny( css::uno::Any( e ) );
1341 catch( const css::lang::WrappedTargetException &e )
1343 raisePyExceptionWithAny( css::uno::Any( e ) );
1345 catch( const css::uno::RuntimeException &e )
1347 raisePyExceptionWithAny( css::uno::Any( e ) );
1350 return -1;
1353 static PyObject* PyUNO_getattr (PyObject* self, char* name)
1358 Runtime runtime;
1360 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1361 if (strcmp (name, "__dict__") == 0)
1363 Py_INCREF (Py_TYPE(me)->tp_dict);
1364 return Py_TYPE(me)->tp_dict;
1366 if (strcmp (name, "__class__") == 0)
1368 Py_INCREF (Py_None);
1369 return Py_None;
1372 PyObject *pRet = PyObject_GenericGetAttr( self, PyUnicode_FromString( name ) );
1373 if( pRet )
1374 return pRet;
1375 PyErr_Clear();
1377 OUString attrName( OUString::createFromAscii( name ) );
1378 //We need to find out if it's a method...
1379 bool isMethod;
1381 PyThreadDetach antiguard;
1382 isMethod = me->members->xInvocation->hasMethod (attrName);
1384 if (isMethod)
1386 //Create a callable object to invoke this...
1387 PyRef ret = PyUNO_callable_new (
1388 me->members->xInvocation,
1389 attrName);
1390 Py_XINCREF( ret.get() );
1391 return ret.get();
1395 //or a property
1396 bool isProperty;
1397 Any anyRet;
1399 PyThreadDetach antiguard;
1400 isProperty = me->members->xInvocation->hasProperty ( attrName);
1401 if (isProperty)
1403 //Return the value of the property
1404 anyRet = me->members->xInvocation->getValue (attrName);
1407 if (isProperty)
1409 PyRef ret = runtime.any2PyObject(anyRet);
1410 Py_XINCREF( ret.get() );
1411 return ret.get();
1414 //or else...
1415 PyErr_SetString (PyExc_AttributeError, name);
1417 catch( const css::reflection::InvocationTargetException & e )
1419 raisePyExceptionWithAny( e.TargetException );
1421 catch( const css::beans::UnknownPropertyException & e )
1423 raisePyExceptionWithAny( Any(e) );
1425 catch( const css::lang::IllegalArgumentException &e )
1427 raisePyExceptionWithAny( Any(e) );
1429 catch( const css::script::CannotConvertException &e )
1431 raisePyExceptionWithAny( Any(e) );
1433 catch( const RuntimeException &e )
1435 raisePyExceptionWithAny( Any(e) );
1438 return nullptr;
1441 static int PyUNO_setattr (PyObject* self, char* name, PyObject* value)
1443 PyUNO* me;
1445 me = reinterpret_cast<PyUNO*>(self);
1448 Runtime runtime;
1449 Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
1451 OUString attrName( OUString::createFromAscii( name ) );
1453 PyThreadDetach antiguard;
1454 if (me->members->xInvocation->hasProperty (attrName))
1456 me->members->xInvocation->setValue (attrName, val);
1457 return 0; //Keep with Python's boolean system
1461 catch( const css::reflection::InvocationTargetException & e )
1463 raisePyExceptionWithAny( e.TargetException );
1464 return -1;
1466 catch( const css::beans::UnknownPropertyException & e )
1468 raisePyExceptionWithAny( Any(e) );
1469 return -1;
1471 catch( const css::script::CannotConvertException &e )
1473 raisePyExceptionWithAny( Any(e) );
1474 return -1;
1476 catch( const RuntimeException & e )
1478 raisePyExceptionWithAny( Any( e ) );
1479 return -1;
1481 PyErr_SetString (PyExc_AttributeError, name);
1482 return -1; //as above.
1485 static PyObject* PyUNO_cmp( PyObject *self, PyObject *that, int op )
1487 PyObject *result;
1489 if(op != Py_EQ && op != Py_NE)
1491 PyErr_SetString(PyExc_TypeError, "only '==' and '!=' comparisons are defined");
1492 return nullptr;
1494 if( self == that )
1496 result = (op == Py_EQ ? Py_True : Py_False);
1497 Py_INCREF(result);
1498 return result;
1502 Runtime runtime;
1503 if( PyObject_IsInstance( that, getPyUnoClass().get() ) )
1506 PyUNO *me = reinterpret_cast< PyUNO*> ( self );
1507 PyUNO *other = reinterpret_cast< PyUNO *> (that );
1508 css::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
1509 css::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
1511 if( tcMe == tcOther )
1513 if( me->members->wrappedObject == other->members->wrappedObject )
1515 result = (op == Py_EQ ? Py_True : Py_False);
1516 Py_INCREF(result);
1517 return result;
1522 catch( const css::uno::RuntimeException & e)
1524 raisePyExceptionWithAny( Any( e ) );
1527 result = (op == Py_EQ ? Py_False : Py_True);
1528 Py_INCREF(result);
1529 return result;
1532 #if defined __GNUC__ && !defined __clang__
1533 #pragma GCC diagnostic push
1534 #pragma GCC diagnostic ignored "-Wcast-function-type"
1535 #endif
1536 static PyMethodDef PyUNOMethods[] =
1538 #if defined __clang__
1539 #if __has_warning("-Wcast-function-type-mismatch")
1540 #pragma clang diagnostic push
1541 #pragma clang diagnostic ignored "-Wcast-function-type-mismatch"
1542 #endif
1543 #endif
1544 {"__dir__", reinterpret_cast<PyCFunction>(PyUNO_dir), METH_NOARGS, nullptr},
1545 #if defined __clang__
1546 #if __has_warning("-Wcast-function-type-mismatch")
1547 #pragma clang diagnostic pop
1548 #endif
1549 #endif
1550 {nullptr, nullptr, 0, nullptr}
1552 #if defined __GNUC__ && !defined __clang__
1553 #pragma GCC diagnostic pop
1554 #endif
1556 static PyNumberMethods PyUNONumberMethods[] =
1558 nullptr, /* nb_add */
1559 nullptr, /* nb_subtract */
1560 nullptr, /* nb_multiply */
1561 nullptr, /* nb_remainder */
1562 nullptr, /* nb_divmod */
1563 nullptr, /* nb_power */
1564 nullptr, /* nb_negative */
1565 nullptr, /* nb_positive */
1566 nullptr, /* nb_absolute */
1567 PyUNO_bool, /* nb_bool */
1568 nullptr, /* nb_invert */
1569 nullptr, /* nb_lshift */
1570 nullptr, /* nb_rshift */
1571 nullptr, /* nb_and */
1572 nullptr, /* nb_xor */
1573 nullptr, /* nb_or */
1574 nullptr, /* nb_int */
1575 nullptr, /* nb_reserved */
1576 nullptr, /* nb_float */
1577 nullptr, /* nb_inplace_add */
1578 nullptr, /* nb_inplace_subtract */
1579 nullptr, /* nb_inplace_multiply */
1580 nullptr, /* nb_inplace_remainder */
1581 nullptr, /* nb_inplace_power */
1582 nullptr, /* nb_inplace_lshift */
1583 nullptr, /* nb_inplace_rshift */
1584 nullptr, /* nb_inplace_and */
1585 nullptr, /* nb_inplace_xor */
1586 nullptr, /* nb_inplace_or */
1588 nullptr, /* nb_floor_divide */
1589 nullptr, /* nb_true_divide */
1590 nullptr, /* nb_inplace_floor_divide */
1591 nullptr, /* nb_inplace_true_divide */
1593 nullptr, /* nb_index */
1594 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
1595 nullptr, /* nb_matrix_multiply */
1596 nullptr, /* nb_inplace_matrix_multiply */
1597 #endif
1600 static PySequenceMethods PyUNOSequenceMethods[] =
1602 nullptr, /* sq_length */
1603 nullptr, /* sq_concat */
1604 nullptr, /* sq_repeat */
1605 nullptr, /* sq_item */
1606 nullptr, /* sq_slice */
1607 nullptr, /* sq_ass_item */
1608 nullptr, /* sq_ass_slice */
1609 PyUNO_contains, /* sq_contains */
1610 nullptr, /* sq_inplace_concat */
1611 nullptr /* sq_inplace_repeat */
1614 static PyMappingMethods PyUNOMappingMethods[] =
1616 PyUNO_len, /* mp_length */
1617 PyUNO_getitem, /* mp_subscript */
1618 PyUNO_setitem, /* mp_ass_subscript */
1621 static PyTypeObject PyUNOType =
1623 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
1624 "pyuno",
1625 sizeof (PyUNO),
1627 PyUNO_del,
1628 #if PY_VERSION_HEX >= 0x03080000
1629 0, // Py_ssize_t tp_vectorcall_offset
1630 #else
1631 nullptr, // printfunc tp_print
1632 #endif
1633 PyUNO_getattr,
1634 PyUNO_setattr,
1635 /* this type does not exist in Python 3: (cmpfunc) */ nullptr,
1636 PyUNO_repr,
1637 PyUNONumberMethods,
1638 PyUNOSequenceMethods,
1639 PyUNOMappingMethods,
1640 PyUNO_hash,
1641 nullptr,
1642 PyUNO_str,
1643 nullptr,
1644 nullptr,
1645 nullptr,
1646 Py_TPFLAGS_HAVE_ITER | Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_HAVE_SEQUENCE_IN,
1647 nullptr,
1648 nullptr,
1649 nullptr,
1650 PyUNO_cmp,
1652 PyUNO_iter,
1653 nullptr,
1654 PyUNOMethods,
1655 nullptr,
1656 nullptr,
1657 nullptr,
1658 nullptr,
1659 nullptr,
1660 nullptr,
1662 nullptr,
1663 nullptr,
1664 nullptr,
1665 nullptr,
1666 nullptr,
1667 nullptr,
1668 nullptr,
1669 nullptr,
1670 nullptr,
1671 nullptr,
1672 nullptr
1674 #if PY_VERSION_HEX >= 0x03040000
1675 , nullptr
1676 #if PY_VERSION_HEX >= 0x03080000
1677 , nullptr // vectorcallfunc tp_vectorcall
1678 #if PY_VERSION_HEX < 0x03090000
1679 #if defined __clang__
1680 #pragma clang diagnostic push
1681 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1682 #endif
1683 , nullptr // tp_print
1684 #if defined __clang__
1685 #pragma clang diagnostic pop
1686 #endif
1687 #endif
1688 #if PY_VERSION_HEX >= 0x030C00A1
1689 , 0 // tp_watched
1690 #endif
1691 #endif
1692 #endif
1695 int PyUNO_initType()
1697 return PyType_Ready(&PyUNOType);
1700 PyRef getPyUnoClass()
1702 return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) );
1705 PyRef PyUNO_new (
1706 const Any &targetInterface,
1707 const Reference<XSingleServiceFactory> &ssf )
1709 Reference<XInvocation2> xInvocation;
1712 PyThreadDetach antiguard;
1713 xInvocation.set(
1714 ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), css::uno::UNO_QUERY_THROW );
1716 auto that = comphelper::getFromUnoTunnel<Adapter>(
1717 xInvocation->getIntrospection()->queryAdapter(cppu::UnoType<XUnoTunnel>::get()));
1718 if( that )
1719 return that->getWrappedObject();
1721 if( !Py_IsInitialized() )
1722 throw RuntimeException();
1724 PyUNO* self = PyObject_New (PyUNO, &PyUNOType);
1725 if (self == nullptr)
1726 return PyRef(); // == error
1727 self->members = new PyUNOInternals;
1728 self->members->xInvocation = std::move(xInvocation);
1729 self->members->wrappedObject = targetInterface;
1730 return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
1736 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */