Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / pyuno / source / module / pyuno.cxx
blob60bb6b3f5f929fe76e7424f38c731c40d92ca3fd
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::makeAny;
52 using com::sun::star::uno::UNO_QUERY;
53 using com::sun::star::uno::Type;
54 using com::sun::star::uno::TypeClass;
55 using com::sun::star::uno::TypeDescription;
56 using com::sun::star::uno::RuntimeException;
57 using com::sun::star::uno::Exception;
58 using com::sun::star::lang::XSingleServiceFactory;
59 using com::sun::star::lang::XServiceInfo;
60 using com::sun::star::lang::XTypeProvider;
61 using com::sun::star::lang::XUnoTunnel;
62 using com::sun::star::script::XInvocation2;
63 using com::sun::star::container::XEnumeration;
64 using com::sun::star::container::XEnumerationAccess;
65 using com::sun::star::container::XIndexAccess;
66 using com::sun::star::container::XIndexContainer;
67 using com::sun::star::container::XIndexReplace;
68 using com::sun::star::container::XNameAccess;
69 using com::sun::star::container::XNameContainer;
70 using com::sun::star::container::XNameReplace;
72 namespace pyuno
75 static PyObject *PyUNO_str( PyObject * self );
77 static void PyUNO_del (PyObject* self)
79 PyUNO* me = reinterpret_cast< PyUNO* > (self);
81 PyThreadDetach antiguard;
82 delete me->members;
84 PyObject_Del (self);
88 OUString val2str( const void * pVal, typelib_TypeDescriptionReference * pTypeRef , sal_Int32 mode )
90 assert( pVal );
91 if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
92 return "void";
94 OUStringBuffer buf( 64 );
95 buf.append( "(" + OUString::unacquired(&pTypeRef->pTypeName) + ")" );
97 switch (pTypeRef->eTypeClass)
99 case typelib_TypeClass_INTERFACE:
101 buf.append( "0x" +
102 OUString::number( reinterpret_cast< sal_IntPtr >(*static_cast<void * const *>(pVal)), 16 ));
103 if( VAL2STR_MODE_DEEP == mode )
105 buf.append( "{" ); Reference< XInterface > r = *static_cast<Reference< XInterface > const *>(pVal);
106 Reference< XServiceInfo > serviceInfo( r, UNO_QUERY);
107 Reference< XTypeProvider > typeProvider(r,UNO_QUERY);
108 if( serviceInfo.is() )
110 buf.append("implementationName=" );
111 buf.append(serviceInfo->getImplementationName() );
112 buf.append(", supportedServices={" );
113 Sequence< OUString > seq = serviceInfo->getSupportedServiceNames();
114 for( int i = 0 ; i < seq.getLength() ; i ++ )
116 buf.append( seq[i] );
117 if( i +1 != seq.getLength() )
118 buf.append( "," );
120 buf.append("}");
123 if( typeProvider.is() )
125 buf.append(", supportedInterfaces={" );
126 Sequence< Type > seq (typeProvider->getTypes());
127 for( int i = 0 ; i < seq.getLength() ; i ++ )
129 buf.append(seq[i].getTypeName());
130 if( i +1 != seq.getLength() )
131 buf.append( "," );
133 buf.append("}");
135 buf.append( "}" );
138 break;
140 case typelib_TypeClass_STRUCT:
141 case typelib_TypeClass_EXCEPTION:
143 buf.append( "{ " );
144 typelib_TypeDescription * pTypeDescr = nullptr;
145 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
146 assert( pTypeDescr );
148 typelib_CompoundTypeDescription * pCompType = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
149 sal_Int32 nDescr = pCompType->nMembers;
151 if (pCompType->pBaseTypeDescription)
153 buf.append( val2str( pVal, pCompType->pBaseTypeDescription->aBase.pWeakRef, mode ) );
154 if (nDescr)
155 buf.append( ", " );
158 typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
159 sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
160 rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
162 for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
164 buf.append( OUString::unacquired(&ppMemberNames[nPos]) + " = " );
165 typelib_TypeDescription * pMemberType = nullptr;
166 TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[nPos] );
167 buf.append( val2str( static_cast<char const *>(pVal) + pMemberOffsets[nPos], pMemberType->pWeakRef, mode ) );
168 TYPELIB_DANGER_RELEASE( pMemberType );
169 if (nPos < (nDescr -1))
170 buf.append( ", " );
173 TYPELIB_DANGER_RELEASE( pTypeDescr );
175 buf.append( " }" );
176 break;
178 case typelib_TypeClass_SEQUENCE:
180 typelib_TypeDescription * pTypeDescr = nullptr;
181 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
183 uno_Sequence * pSequence = *static_cast<uno_Sequence * const *>(pVal);
184 typelib_TypeDescription * pElementTypeDescr = nullptr;
185 TYPELIB_DANGER_GET( &pElementTypeDescr, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
187 sal_Int32 nElementSize = pElementTypeDescr->nSize;
188 sal_Int32 nElements = pSequence->nElements;
190 if (nElements)
192 buf.append( "{ " );
193 char * pElements = pSequence->elements;
194 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
196 buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef, mode ) );
197 if (nPos < (nElements -1))
198 buf.append( ", " );
200 buf.append( " }" );
202 else
204 buf.append( "{}" );
206 TYPELIB_DANGER_RELEASE( pElementTypeDescr );
207 TYPELIB_DANGER_RELEASE( pTypeDescr );
208 break;
210 case typelib_TypeClass_ANY:
211 buf.append( "{ " );
212 buf.append( val2str( static_cast<uno_Any const *>(pVal)->pData,
213 static_cast<uno_Any const *>(pVal)->pType ,
214 mode) );
215 buf.append( " }" );
216 break;
217 case typelib_TypeClass_TYPE:
218 buf.append( (*static_cast<typelib_TypeDescriptionReference * const *>(pVal))->pTypeName );
219 break;
220 case typelib_TypeClass_STRING:
221 buf.append( "\"" +
222 OUString::unacquired(&*static_cast<rtl_uString * const *>(pVal)) +
223 "\"" );
224 break;
225 case typelib_TypeClass_ENUM:
227 typelib_TypeDescription * pTypeDescr = nullptr;
228 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
230 sal_Int32 * pValues = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->pEnumValues;
231 sal_Int32 nPos = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nEnumValues;
232 while (nPos--)
234 if (pValues[nPos] == *static_cast<int const *>(pVal))
235 break;
237 if (nPos >= 0)
238 buf.append( reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->ppEnumNames[nPos] );
239 else
240 buf.append( '?' );
242 TYPELIB_DANGER_RELEASE( pTypeDescr );
243 break;
245 case typelib_TypeClass_BOOLEAN:
246 if (*static_cast<sal_Bool const *>(pVal))
247 buf.append( "true" );
248 else
249 buf.append( "false" );
250 break;
251 case typelib_TypeClass_CHAR:
252 buf.append( '\'' );
253 buf.append( *static_cast<sal_Unicode const *>(pVal) );
254 buf.append( '\'' );
255 break;
256 case typelib_TypeClass_FLOAT:
257 buf.append( *static_cast<float const *>(pVal) );
258 break;
259 case typelib_TypeClass_DOUBLE:
260 buf.append( *static_cast<double const *>(pVal) );
261 break;
262 case typelib_TypeClass_BYTE:
263 buf.append( "0x" +
264 OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int8 const *>(pVal)), 16 ));
265 break;
266 case typelib_TypeClass_SHORT:
267 buf.append( "0x" +
268 OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int16 const *>(pVal)), 16 ));
269 break;
270 case typelib_TypeClass_UNSIGNED_SHORT:
271 buf.append( "0x" +
272 OUString::number( static_cast<sal_Int32>(*static_cast<sal_uInt16 const *>(pVal)), 16 ));
273 break;
274 case typelib_TypeClass_LONG:
275 buf.append( "0x" +
276 OUString::number( *static_cast<sal_Int32 const *>(pVal), 16 ));
277 break;
278 case typelib_TypeClass_UNSIGNED_LONG:
279 buf.append( "0x" +
280 OUString::number( static_cast<sal_Int64>(*static_cast<sal_uInt32 const *>(pVal)), 16 ));
281 break;
282 case typelib_TypeClass_HYPER:
283 case typelib_TypeClass_UNSIGNED_HYPER:
284 buf.append( "0x" );
285 #if defined(__GNUC__) && defined(SPARC)
286 // I guess this really should check if there are strict alignment
287 // requirements, not just "GCC on SPARC".
289 sal_Int64 aVal;
290 *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
291 *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
292 buf.append( aVal, 16 );
294 #else
295 buf.append( *static_cast<sal_Int64 const *>(pVal), 16 );
296 #endif
297 break;
299 case typelib_TypeClass_VOID:
300 case typelib_TypeClass_UNKNOWN:
301 case typelib_TypeClass_SERVICE:
302 case typelib_TypeClass_MODULE:
303 default:
304 buf.append( '?' );
307 return buf.makeStringAndClear();
310 static sal_Int32 lcl_PyNumber_AsSal_Int32( PyObject *pObj )
312 // Check object is an index
313 PyRef rIndex( PyNumber_Index( pObj ), SAL_NO_ACQUIRE );
314 if ( !rIndex.is() )
315 return -1;
317 // Convert Python number to platform long, then check actual value against
318 // bounds of sal_Int32
319 int nOverflow;
320 long nResult = PyLong_AsLongAndOverflow( pObj, &nOverflow );
321 if ( nOverflow || nResult > SAL_MAX_INT32 || nResult < SAL_MIN_INT32) {
322 PyErr_SetString( PyExc_IndexError, "Python int too large to convert to UNO long" );
323 return -1;
326 return nResult;
329 static int lcl_PySlice_GetIndicesEx( PyObject *pObject, sal_Int32 nLen, sal_Int32 *nStart, sal_Int32 *nStop, sal_Int32 *nStep, sal_Int32 *nSliceLength )
331 Py_ssize_t nStart_ssize, nStop_ssize, nStep_ssize, nSliceLength_ssize;
333 int nResult = PySlice_GetIndicesEx(pObject,
334 nLen, &nStart_ssize, &nStop_ssize, &nStep_ssize, &nSliceLength_ssize );
335 if (nResult == -1)
336 return -1;
338 if ( nStart_ssize > SAL_MAX_INT32 || nStart_ssize < SAL_MIN_INT32
339 || nStop_ssize > SAL_MAX_INT32 || nStop_ssize < SAL_MIN_INT32
340 || nStep_ssize > SAL_MAX_INT32 || nStep_ssize < SAL_MIN_INT32
341 || nSliceLength_ssize > SAL_MAX_INT32 || nSliceLength_ssize < SAL_MIN_INT32 )
343 PyErr_SetString( PyExc_IndexError, "Python int too large to convert to UNO long" );
344 return -1;
347 *nStart = static_cast<sal_Int32>(nStart_ssize);
348 *nStop = static_cast<sal_Int32>(nStop_ssize);
349 *nStep = static_cast<sal_Int32>(nStep_ssize);
350 *nSliceLength = static_cast<sal_Int32>(nSliceLength_ssize);
351 return 0;
354 static bool lcl_hasInterfaceByName( Any const &object, OUString const & interfaceName )
356 Reference< XInterface > xInterface( object, UNO_QUERY );
357 TypeDescription typeDesc( interfaceName );
358 Any aInterface = xInterface->queryInterface( typeDesc.get()->pWeakRef );
360 return aInterface.hasValue();
363 static PyObject *PyUNO_repr( PyObject * self )
365 return PyUNO_str( self );
368 static Py_hash_t PyUNO_hash( PyObject *self )
371 PyUNO *me = reinterpret_cast<PyUNO *>(self);
373 // Py_hash_t is not necessarily the same size as a pointer, but this is not
374 // important for hashing - it just has to return the same value each time
375 return sal::static_int_cast< Py_hash_t >( reinterpret_cast< sal_IntPtr > (
376 *static_cast<void * const *>(me->members->wrappedObject.getValue()) ) );
380 PyObject *PyUNO_invoke( PyObject *object, const char *name , PyObject *args )
382 PyRef ret;
385 Runtime runtime;
387 PyRef paras,callable;
388 if( PyObject_IsInstance( object, getPyUnoClass().get() ) )
390 PyUNO* me = reinterpret_cast<PyUNO*>(object);
391 OUString attrName = OUString::createFromAscii(name);
392 if (! me->members->xInvocation->hasMethod (attrName))
394 throw RuntimeException( "Attribute " + attrName + " unknown" );
396 callable = PyUNO_callable_new (
397 me->members->xInvocation,
398 attrName,
399 ACCEPT_UNO_ANY);
400 paras = args;
402 else
404 // clean the tuple from uno.Any !
405 int size = PyTuple_Size( args );
406 { // for CC, keeping ref-count of tuple being 1
407 paras = PyRef(PyTuple_New( size ), SAL_NO_ACQUIRE);
409 for( int i = 0 ; i < size ;i ++ )
411 PyObject * element = PyTuple_GetItem( args , i );
412 if( PyObject_IsInstance( element , getAnyClass( runtime ).get() ) )
414 element = PyObject_GetAttrString(
415 element, "value" );
417 else
419 Py_XINCREF( element );
421 PyTuple_SetItem( paras.get(), i , element );
423 callable = PyRef( PyObject_GetAttrString( object , name ), SAL_NO_ACQUIRE );
424 if( !callable.is() )
425 return nullptr;
427 ret = PyRef( PyObject_CallObject( callable.get(), paras.get() ), SAL_NO_ACQUIRE );
429 catch (const css::lang::IllegalArgumentException &e)
431 raisePyExceptionWithAny( css::uno::makeAny( e ) );
433 catch (const css::script::CannotConvertException &e)
435 raisePyExceptionWithAny( css::uno::makeAny( e ) );
437 catch (const css::uno::RuntimeException &e)
439 raisePyExceptionWithAny( css::uno::makeAny( e ) );
441 catch (const css::uno::Exception &e)
443 raisePyExceptionWithAny( css::uno::makeAny( e ) );
446 return ret.getAcquired();
449 PyObject *PyUNO_str( PyObject * self )
451 PyUNO *me = reinterpret_cast<PyUNO *>(self);
453 OString buf;
456 PyThreadDetach antiguard;
458 OUString s = val2str( me->members->wrappedObject.getValue(),
459 me->members->wrappedObject.getValueType().getTypeLibType() );
460 buf = "pyuno object " + OUStringToOString(s,RTL_TEXTENCODING_ASCII_US);
463 return PyUnicode_FromString( buf.getStr() );
466 static PyObject* PyUNO_dir (PyObject* self)
468 PyUNO* me = reinterpret_cast<PyUNO*>(self);
470 PyObject* member_list = nullptr;
471 Sequence<OUString> oo_member_list;
475 oo_member_list = me->members->xInvocation->getMemberNames ();
476 member_list = PyList_New (oo_member_list.getLength ());
477 for (int i = 0; i < oo_member_list.getLength (); i++)
479 // setitem steals a reference
480 PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() );
483 catch( const RuntimeException &e )
485 raisePyExceptionWithAny( makeAny(e) );
488 return member_list;
491 static sal_Int32 lcl_detach_getLength( PyUNO const *me )
493 PyThreadDetach antiguard;
495 // If both XIndexContainer and XNameContainer are implemented, it is
496 // assumed that getCount() gives the same result as the number of names
497 // returned by getElementNames(), or the user may be surprised.
499 // For XIndexContainer
500 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
501 if ( xIndexAccess.is() )
503 return xIndexAccess->getCount();
506 // For XNameContainer
507 // Not terribly efficient - get the count of all the names
508 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
509 if ( xNameAccess.is() )
511 return xNameAccess->getElementNames().getLength();
514 return -1;
517 static int PyUNO_bool( PyObject* self )
519 PyUNO* me = reinterpret_cast<PyUNO*>(self);
523 int nLen = lcl_detach_getLength( me );
524 if (nLen >= 0)
525 return nLen == 0 ? 0 : 1;
527 // Anything which doesn't have members is a scalar object and therefore true
528 return 1;
530 catch( const css::uno::RuntimeException &e )
532 raisePyExceptionWithAny( css::uno::makeAny( e ) );
535 return -1;
538 static Py_ssize_t PyUNO_len( PyObject* self )
540 PyUNO* me = reinterpret_cast<PyUNO*>(self);
544 int nLen = lcl_detach_getLength( me );
545 if (nLen >= 0)
546 return nLen;
548 PyErr_SetString( PyExc_TypeError, "object has no len()" );
550 catch( const css::uno::RuntimeException &e )
552 raisePyExceptionWithAny( css::uno::makeAny( e ) );
555 return -1;
558 static void lcl_getRowsColumns( PyUNO const * me, sal_Int32& nRows, sal_Int32& nColumns )
560 Sequence<short> aOutParamIndex;
561 Sequence<Any> aOutParam;
562 Sequence<Any> aParams;
563 Any aRet = me->members->xInvocation->invoke ( "getRows", aParams, aOutParamIndex, aOutParam );
564 Reference< XIndexAccess > xIndexAccessRows( aRet, UNO_QUERY );
565 nRows = xIndexAccessRows->getCount();
566 aRet = me->members->xInvocation->invoke ( "getColumns", aParams, aOutParamIndex, aOutParam );
567 Reference< XIndexAccess > xIndexAccessCols( aRet, UNO_QUERY );
568 nColumns = xIndexAccessCols->getCount();
571 static PyRef lcl_indexToSlice( const PyRef& rIndex )
573 Py_ssize_t nIndex = PyNumber_AsSsize_t( rIndex.get(), PyExc_IndexError );
574 if (nIndex == -1 && PyErr_Occurred())
575 return nullptr;
576 PyRef rStart( PyLong_FromSsize_t( nIndex ), SAL_NO_ACQUIRE );
577 PyRef rStop( PyLong_FromSsize_t( nIndex+1 ), SAL_NO_ACQUIRE );
578 PyRef rStep( PyLong_FromLong( 1 ), SAL_NO_ACQUIRE );
579 PyRef rSlice( PySlice_New( rStart.get(), rStop.get(), rStep.get() ), SAL_NO_ACQUIRE );
581 return rSlice;
584 static PyObject* lcl_getitem_XCellRange( PyUNO const * me, PyObject* pKey )
586 Runtime runtime;
588 Sequence<short> aOutParamIndex;
589 Sequence<Any> aOutParam;
590 Sequence<Any> aParams;
591 Any aRet;
593 // Single string key is sugar for getCellRangeByName()
594 if ( PyUnicode_Check( pKey ) ) {
596 aParams.realloc (1);
597 aParams[0] <<= pyString2ustring( pKey );
599 PyThreadDetach antiguard;
600 aRet = me->members->xInvocation->invoke (
601 "getCellRangeByName", aParams, aOutParamIndex, aOutParam );
603 PyRef rRet = runtime.any2PyObject ( aRet );
604 return rRet.getAcquired();
608 PyRef rKey0, rKey1;
609 if ( PyIndex_Check( pKey ) )
611 // [0] is equivalent to [0,:]
612 rKey0 = pKey;
613 rKey1 = PySlice_New( nullptr, nullptr, nullptr );
615 else if ( PyTuple_Check( pKey ) && (PyTuple_Size( pKey ) == 2) )
617 rKey0 = PyTuple_GetItem( pKey, 0 );
618 rKey1 = PyTuple_GetItem( pKey, 1 );
620 else
622 PyErr_SetString( PyExc_KeyError, "invalid subscript" );
623 return nullptr;
626 // If both keys are indices, return the corresponding cell
627 if ( PyIndex_Check( rKey0.get() ) && PyIndex_Check( rKey1.get() ))
629 sal_Int32 nKey0_s = lcl_PyNumber_AsSal_Int32( rKey0.get() );
630 sal_Int32 nKey1_s = lcl_PyNumber_AsSal_Int32( rKey1.get() );
632 if ( ((nKey0_s == -1) || (nKey1_s == -1)) && PyErr_Occurred() )
633 return nullptr;
635 aParams.realloc( 2 );
636 aParams[0] <<= nKey1_s;
637 aParams[1] <<= nKey0_s;
639 PyThreadDetach antiguard;
640 aRet = me->members->xInvocation->invoke (
641 "getCellByPosition", aParams, aOutParamIndex, aOutParam );
643 PyRef rRet = runtime.any2PyObject( aRet );
644 return rRet.getAcquired();
647 // If either argument is an index, coerce it to a slice
648 if ( PyIndex_Check( rKey0.get() ) )
649 rKey0 = lcl_indexToSlice( rKey0 );
651 if ( PyIndex_Check( rKey1.get() ) )
652 rKey1 = lcl_indexToSlice( rKey1 );
654 // If both arguments are slices, return the corresponding cell range
655 if ( PySlice_Check( rKey0.get() ) && PySlice_Check( rKey1.get() ) )
657 sal_Int32 nLen0 = SAL_MAX_INT32, nLen1 = SAL_MAX_INT32;
658 sal_Int32 nStart0 = 0, nStop0 = 0, nStep0 = 0, nSliceLength0 = 0;
659 sal_Int32 nStart1 = 0, nStop1 = 0, nStep1 = 0, nSliceLength1 = 0;
662 PyThreadDetach antiguard;
664 if ( lcl_hasInterfaceByName( me->members->wrappedObject, "com.sun.star.table.XColumnRowRange" ) )
666 lcl_getRowsColumns (me, nLen0, nLen1);
670 int nSuccess1 = lcl_PySlice_GetIndicesEx( rKey0.get(), nLen0, &nStart0, &nStop0, &nStep0, &nSliceLength0 );
671 int nSuccess2 = lcl_PySlice_GetIndicesEx( rKey1.get(), nLen1, &nStart1, &nStop1, &nStep1, &nSliceLength1 );
672 if ( ((nSuccess1 == -1) || (nSuccess2 == -1)) && PyErr_Occurred() )
673 return nullptr;
675 if ( nSliceLength0 <= 0 || nSliceLength1 <= 0 )
677 PyErr_SetString( PyExc_KeyError, "invalid number of rows or columns" );
678 return nullptr;
681 if ( nStep0 == 1 && nStep1 == 1 )
683 aParams.realloc (4);
684 aParams[0] <<= nStart1;
685 aParams[1] <<= nStart0;
686 aParams[2] <<= nStop1 - 1;
687 aParams[3] <<= nStop0 - 1;
689 PyThreadDetach antiguard;
690 aRet = me->members->xInvocation->invoke (
691 "getCellRangeByPosition", aParams, aOutParamIndex, aOutParam );
693 PyRef rRet = runtime.any2PyObject( aRet );
694 return rRet.getAcquired();
697 PyErr_SetString( PyExc_KeyError, "step != 1 not supported" );
698 return nullptr;
701 PyErr_SetString( PyExc_KeyError, "invalid subscript" );
702 return nullptr;
705 static PyObject* lcl_getitem_index( PyUNO const *me, PyObject *pKey, Runtime const & runtime )
707 Any aRet;
708 sal_Int32 nIndex;
710 nIndex = lcl_PyNumber_AsSal_Int32( pKey );
711 if (nIndex == -1 && PyErr_Occurred())
712 return nullptr;
715 PyThreadDetach antiguard;
717 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
718 if ( xIndexAccess.is() )
720 if (nIndex < 0)
721 nIndex += xIndexAccess->getCount();
722 aRet = xIndexAccess->getByIndex( nIndex );
725 if ( aRet.hasValue() )
727 PyRef rRet ( runtime.any2PyObject( aRet ) );
728 return rRet.getAcquired();
731 return nullptr;
734 static PyObject* lcl_getitem_slice( PyUNO const *me, PyObject *pKey )
736 Runtime runtime;
738 Reference< XIndexAccess > xIndexAccess;
739 sal_Int32 nLen = 0;
742 PyThreadDetach antiguard;
744 xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
745 if ( xIndexAccess.is() )
746 nLen = xIndexAccess->getCount();
749 if ( xIndexAccess.is() )
751 sal_Int32 nStart = 0, nStop = 0, nStep = 0, nSliceLength = 0;
752 int nSuccess = lcl_PySlice_GetIndicesEx(pKey, nLen, &nStart, &nStop, &nStep, &nSliceLength);
753 if ( nSuccess == -1 && PyErr_Occurred() )
754 return nullptr;
756 PyRef rTuple( PyTuple_New( nSliceLength ), SAL_NO_ACQUIRE, NOT_NULL );
757 sal_Int32 nCur, i;
758 for ( nCur = nStart, i = 0; i < nSliceLength; nCur += nStep, i++ )
760 Any aRet;
763 PyThreadDetach antiguard;
765 aRet = xIndexAccess->getByIndex( nCur );
767 PyRef rRet = runtime.any2PyObject( aRet );
768 PyTuple_SetItem( rTuple.get(), i, rRet.getAcquired() );
771 return rTuple.getAcquired();
774 return nullptr;
777 static PyObject* lcl_getitem_string( PyUNO const *me, PyObject *pKey, Runtime const & runtime )
779 OUString sKey = pyString2ustring( pKey );
780 Any aRet;
783 PyThreadDetach antiguard;
785 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
786 if ( xNameAccess.is() )
788 aRet = xNameAccess->getByName( sKey );
791 if ( aRet.hasValue() )
793 PyRef rRet = runtime.any2PyObject( aRet );
794 return rRet.getAcquired();
797 return nullptr;
800 static PyObject* PyUNO_getitem( PyObject *self, PyObject *pKey )
802 PyUNO* me = reinterpret_cast<PyUNO*>(self);
803 Runtime runtime;
807 // XIndexAccess access by index
808 if ( PyIndex_Check( pKey ) )
810 PyObject* pRet = lcl_getitem_index( me, pKey, runtime );
811 if ( pRet != nullptr || PyErr_Occurred() )
812 return pRet;
815 // XIndexAccess access by slice
816 if ( PySlice_Check( pKey ) )
818 PyObject* pRet = lcl_getitem_slice( me, pKey );
819 if ( pRet != nullptr || PyErr_Occurred() )
820 return pRet;
823 // XNameAccess access by key
824 if ( PyUnicode_Check( pKey ) )
826 PyObject* pRet = lcl_getitem_string( me, pKey, runtime );
827 if ( pRet != nullptr )
828 return pRet;
831 // XCellRange/XColumnRowRange specialisation
832 // Uses reflection as we can't have a hard dependency on XCellRange here
833 bool hasXCellRange = false;
836 PyThreadDetach antiguard;
838 hasXCellRange = lcl_hasInterfaceByName( me->members->wrappedObject, "com.sun.star.table.XCellRange" );
840 if ( hasXCellRange )
842 return lcl_getitem_XCellRange( me, pKey );
846 // If the object is an XIndexAccess and/or XNameAccess, but the
847 // key passed wasn't suitable, give a TypeError which specifically
848 // describes this
849 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
850 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
851 if ( xIndexAccess.is() || xNameAccess.is() )
853 PyErr_SetString( PyExc_TypeError, "subscription with invalid type" );
854 return nullptr;
857 PyErr_SetString( PyExc_TypeError, "object is not subscriptable" );
859 catch( const css::lang::IndexOutOfBoundsException & )
861 PyErr_SetString( PyExc_IndexError, "index out of range" );
863 catch( const css::container::NoSuchElementException & )
865 PyErr_SetString( PyExc_KeyError, "key not found" );
867 catch( const css::script::CannotConvertException &e )
869 raisePyExceptionWithAny( css::uno::makeAny( e ) );
871 catch( const css::lang::IllegalArgumentException &e )
873 raisePyExceptionWithAny( css::uno::makeAny( e ) );
875 catch( const css::lang::WrappedTargetException &e )
877 raisePyExceptionWithAny( css::uno::makeAny( e ) );
879 catch( const css::uno::RuntimeException &e )
881 raisePyExceptionWithAny( css::uno::makeAny( e ) );
884 return nullptr;
887 static int lcl_setitem_index( PyUNO const *me, PyObject *pKey, PyObject *pValue )
889 Runtime runtime;
891 Reference< XIndexContainer > xIndexContainer;
892 Reference< XIndexReplace > xIndexReplace;
893 sal_Int32 nIndex = lcl_PyNumber_AsSal_Int32( pKey );
894 if ( nIndex == -1 && PyErr_Occurred() )
895 return 0;
897 bool isTuple = false;
899 Any aValue;
900 if ( pValue != nullptr )
902 isTuple = PyTuple_Check( pValue );
906 aValue = runtime.pyObject2Any( pValue );
908 catch ( const css::uno::RuntimeException & )
910 // TODO pyObject2Any can't convert e.g. dicts but only throws
911 // RuntimeException on failure. Fixing this will require an audit of
912 // all the rest of PyUNO
913 throw css::script::CannotConvertException();
918 PyThreadDetach antiguard;
920 xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
921 if ( xIndexContainer.is() )
922 xIndexReplace = xIndexContainer;
923 else
924 xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
926 if ( xIndexReplace.is() && nIndex < 0 )
927 nIndex += xIndexReplace->getCount();
929 // XIndexReplace replace by index
930 if ( (pValue != nullptr) && xIndexReplace.is() )
932 if ( isTuple )
934 // Apply type specialisation to ensure the correct kind of sequence is passed
935 Type aType = xIndexReplace->getElementType();
936 aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
939 xIndexReplace->replaceByIndex( nIndex, aValue );
940 return 0;
943 // XIndexContainer remove by index
944 if ( (pValue == nullptr) && xIndexContainer.is() )
946 xIndexContainer->removeByIndex( nIndex );
947 return 0;
951 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
952 return 1;
955 static int lcl_setitem_slice( PyUNO const *me, PyObject *pKey, PyObject *pValue )
957 // XIndexContainer insert/remove/replace by slice
958 Runtime runtime;
960 Reference< XIndexReplace > xIndexReplace;
961 Reference< XIndexContainer > xIndexContainer;
962 sal_Int32 nLen = 0;
965 PyThreadDetach antiguard;
967 xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
968 if ( xIndexContainer.is() )
969 xIndexReplace = xIndexContainer;
970 else
971 xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
973 if ( xIndexReplace.is() )
974 nLen = xIndexReplace->getCount();
977 if ( xIndexReplace.is() )
979 sal_Int32 nStart = 0, nStop = 0, nStep = 0, nSliceLength = 0;
980 int nSuccess = lcl_PySlice_GetIndicesEx( pKey, nLen, &nStart, &nStop, &nStep, &nSliceLength );
981 if ( (nSuccess == -1) && PyErr_Occurred() )
982 return 0;
984 if ( pValue == nullptr )
986 pValue = PyTuple_New( 0 );
989 if ( !PyTuple_Check (pValue) )
991 PyErr_SetString( PyExc_TypeError, "value is not a tuple" );
992 return 1;
995 Py_ssize_t nTupleLength_ssize = PyTuple_Size( pValue );
996 if ( nTupleLength_ssize > SAL_MAX_INT32 )
998 PyErr_SetString( PyExc_ValueError, "tuple too large" );
999 return 1;
1001 sal_Int32 nTupleLength = static_cast<sal_Int32>(nTupleLength_ssize);
1003 if ( (nTupleLength != nSliceLength) && (nStep != 1) )
1005 PyErr_SetString( PyExc_ValueError, "number of items assigned must be equal" );
1006 return 1;
1009 if ( (nTupleLength != nSliceLength) && !xIndexContainer.is() )
1011 PyErr_SetString( PyExc_ValueError, "cannot change length" );
1012 return 1;
1015 sal_Int32 nCur, i;
1016 sal_Int32 nMax = ::std::max( nSliceLength, nTupleLength );
1017 for ( nCur = nStart, i = 0; i < nMax; nCur += nStep, i++ )
1019 if ( i < nTupleLength )
1021 PyRef rItem = PyTuple_GetItem( pValue, i );
1022 bool isTuple = PyTuple_Check( rItem.get() );
1024 Any aItem;
1027 aItem = runtime.pyObject2Any( rItem.get() );
1029 catch ( const css::uno::RuntimeException & )
1031 // TODO pyObject2Any can't convert e.g. dicts but only throws
1032 // RuntimeException on failure. Fixing this will require an audit of
1033 // all the rest of PyUNO
1034 throw css::script::CannotConvertException();
1038 PyThreadDetach antiguard;
1040 if ( isTuple )
1042 // Apply type specialisation to ensure the correct kind of sequence is passed
1043 Type aType = xIndexReplace->getElementType();
1044 aItem = runtime.getImpl()->cargo->xTypeConverter->convertTo( aItem, aType );
1047 if ( i < nSliceLength )
1049 xIndexReplace->replaceByIndex( nCur, aItem );
1051 else
1053 xIndexContainer->insertByIndex( nCur, aItem );
1057 else
1059 PyThreadDetach antiguard;
1061 xIndexContainer->removeByIndex( nCur );
1062 nCur--;
1066 return 0;
1069 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
1070 return 1;
1073 static int lcl_setitem_string( PyUNO const *me, PyObject *pKey, PyObject *pValue )
1075 Runtime runtime;
1077 OUString sKey = pyString2ustring( pKey );
1078 bool isTuple = false;
1080 Any aValue;
1081 if ( pValue != nullptr)
1083 isTuple = PyTuple_Check( pValue );
1086 aValue = runtime.pyObject2Any( pValue );
1088 catch( const css::uno::RuntimeException & )
1090 // TODO pyObject2Any can't convert e.g. dicts but only throws
1091 // RuntimeException on failure. Fixing this will require an audit of
1092 // all the rest of PyUNO
1093 throw css::script::CannotConvertException();
1098 PyThreadDetach antiguard;
1100 Reference< XNameContainer > xNameContainer( me->members->xInvocation, UNO_QUERY );
1101 Reference< XNameReplace > xNameReplace;
1102 if ( xNameContainer.is() )
1103 xNameReplace = xNameContainer;
1104 else
1105 xNameReplace.set( me->members->xInvocation, UNO_QUERY );
1107 if ( xNameReplace.is() )
1109 if ( isTuple && aValue.hasValue() )
1111 // Apply type specialisation to ensure the correct kind of sequence is passed
1112 Type aType = xNameReplace->getElementType();
1113 aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
1116 if ( aValue.hasValue() )
1118 if ( xNameContainer.is() )
1120 try {
1121 xNameContainer->insertByName( sKey, aValue );
1122 return 0;
1124 catch( const css::container::ElementExistException & )
1126 // Fall through, try replace instead
1130 xNameReplace->replaceByName( sKey, aValue );
1131 return 0;
1133 else if ( xNameContainer.is() )
1135 xNameContainer->removeByName( sKey );
1136 return 0;
1141 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
1142 return 1;
1145 static int PyUNO_setitem( PyObject *self, PyObject *pKey, PyObject *pValue )
1147 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1151 if ( PyIndex_Check( pKey ) )
1153 return lcl_setitem_index( me, pKey, pValue );
1155 else if ( PySlice_Check( pKey ) )
1157 return lcl_setitem_slice( me, pKey, pValue );
1159 else if ( PyUnicode_Check( pKey ) )
1161 return lcl_setitem_string( me, pKey, pValue );
1164 PyErr_SetString( PyExc_TypeError, "list index has invalid type" );
1166 catch( const css::lang::IndexOutOfBoundsException & )
1168 PyErr_SetString( PyExc_IndexError, "list index out of range" );
1170 catch( const css::container::NoSuchElementException & )
1172 PyErr_SetString( PyExc_KeyError, "key not found" );
1174 catch( const css::lang::IllegalArgumentException & )
1176 PyErr_SetString( PyExc_TypeError, "value has invalid type" );
1178 catch( const css::script::CannotConvertException & )
1180 PyErr_SetString( PyExc_TypeError, "value has invalid type" );
1182 catch( const css::container::ElementExistException &e )
1184 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1186 catch( const css::lang::WrappedTargetException &e )
1188 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1190 catch( const css::uno::RuntimeException &e )
1192 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1195 return 1;
1198 static PyObject* PyUNO_iter( PyObject *self )
1200 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1204 Reference< XEnumerationAccess > xEnumerationAccess;
1205 Reference< XEnumeration > xEnumeration;
1206 Reference< XIndexAccess > xIndexAccess;
1207 Reference< XNameAccess > xNameAccess;
1210 PyThreadDetach antiguard;
1212 xEnumerationAccess.set( me->members->xInvocation, UNO_QUERY );
1213 if ( xEnumerationAccess.is() )
1214 xEnumeration = xEnumerationAccess->createEnumeration();
1215 else
1216 xEnumeration.set( me->members->wrappedObject, UNO_QUERY );
1218 if ( !xEnumeration.is() )
1219 xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
1221 if ( !xIndexAccess.is() )
1222 xNameAccess.set( me->members->xInvocation, UNO_QUERY );
1225 // XEnumerationAccess iterator
1226 // XEnumeration iterator
1227 if (xEnumeration.is())
1229 return PyUNO_iterator_new( xEnumeration );
1232 // XIndexAccess iterator
1233 if ( xIndexAccess.is() )
1235 // We'd like to be able to use PySeqIter_New() here, but we're not
1236 // allowed to because we also implement the mapping protocol
1237 return PyUNO_list_iterator_new( xIndexAccess );
1240 // XNameAccess iterator
1241 if (xNameAccess.is())
1243 // There's no generic mapping iterator, but we can cobble our own
1244 // together using PySeqIter_New()
1245 Runtime runtime;
1246 Any aRet;
1249 PyThreadDetach antiguard;
1250 aRet <<= xNameAccess->getElementNames();
1252 PyRef rNames = runtime.any2PyObject( aRet );
1253 return PySeqIter_New( rNames.getAcquired() );
1256 PyErr_SetString ( PyExc_TypeError, "object is not iterable" );
1258 catch( css::script::CannotConvertException &e )
1260 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1262 catch( css::lang::IllegalArgumentException &e )
1264 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1266 catch( const css::uno::RuntimeException &e )
1268 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1271 return nullptr;
1274 static int PyUNO_contains( PyObject *self, PyObject *pKey )
1276 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1278 Runtime runtime;
1282 Any aValue;
1285 aValue = runtime.pyObject2Any( pKey );
1287 catch( const css::uno::RuntimeException & )
1289 // TODO pyObject2Any can't convert e.g. dicts but only throws
1290 // RuntimeException on failure. Fixing this will require an audit of
1291 // all the rest of PyUNO
1292 throw css::script::CannotConvertException();
1295 // XNameAccess is tried first, because checking key presence is much more
1296 // useful for objects which implement both XIndexAccess and XNameAccess
1298 // For XNameAccess
1299 if ( PyUnicode_Check( pKey ) )
1301 OUString sKey;
1302 aValue >>= sKey;
1303 Reference< XNameAccess > xNameAccess;
1306 PyThreadDetach antiguard;
1308 xNameAccess.set( me->members->xInvocation, UNO_QUERY );
1309 if ( xNameAccess.is() )
1311 bool hasKey = xNameAccess->hasByName( sKey );
1312 return hasKey ? 1 : 0;
1317 // For any other type of PyUNO iterable: Ugly iterative search by
1318 // content (XIndexAccess, XEnumerationAccess, XEnumeration)
1319 PyRef rIterator( PyUNO_iter( self ), SAL_NO_ACQUIRE );
1320 if ( rIterator.is() )
1322 while ( PyObject* pItem = PyIter_Next( rIterator.get() ) )
1324 PyRef rItem( pItem, SAL_NO_ACQUIRE );
1325 if ( PyObject_RichCompareBool( pKey, rItem.get(), Py_EQ ) == 1 )
1327 return 1;
1330 return 0;
1333 PyErr_SetString( PyExc_TypeError, "argument is not iterable" );
1335 catch( const css::script::CannotConvertException& )
1337 PyErr_SetString( PyExc_TypeError, "invalid type passed as left argument to 'in'" );
1339 catch( const css::container::NoSuchElementException &e )
1341 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1343 catch( const css::lang::IndexOutOfBoundsException &e )
1345 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1347 catch( const css::lang::IllegalArgumentException &e )
1349 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1351 catch( const css::lang::WrappedTargetException &e )
1353 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1355 catch( const css::uno::RuntimeException &e )
1357 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1360 return -1;
1363 static PyObject* PyUNO_getattr (PyObject* self, char* name)
1368 Runtime runtime;
1370 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1371 if (strcmp (name, "__dict__") == 0)
1373 Py_INCREF (Py_TYPE(me)->tp_dict);
1374 return Py_TYPE(me)->tp_dict;
1376 if (strcmp (name, "__class__") == 0)
1378 Py_INCREF (Py_None);
1379 return Py_None;
1382 PyObject *pRet = PyObject_GenericGetAttr( self, PyUnicode_FromString( name ) );
1383 if( pRet )
1384 return pRet;
1385 PyErr_Clear();
1387 OUString attrName( OUString::createFromAscii( name ) );
1388 //We need to find out if it's a method...
1389 if (me->members->xInvocation->hasMethod (attrName))
1391 //Create a callable object to invoke this...
1392 PyRef ret = PyUNO_callable_new (
1393 me->members->xInvocation,
1394 attrName);
1395 Py_XINCREF( ret.get() );
1396 return ret.get();
1400 //or a property
1401 if (me->members->xInvocation->hasProperty ( attrName))
1403 //Return the value of the property
1404 Any anyRet;
1406 PyThreadDetach antiguard;
1407 anyRet = me->members->xInvocation->getValue (attrName);
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( makeAny(e) );
1425 catch( const css::lang::IllegalArgumentException &e )
1427 raisePyExceptionWithAny( makeAny(e) );
1429 catch( const css::script::CannotConvertException &e )
1431 raisePyExceptionWithAny( makeAny(e) );
1433 catch( const RuntimeException &e )
1435 raisePyExceptionWithAny( makeAny(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( makeAny(e) );
1469 return 1;
1471 catch( const css::script::CannotConvertException &e )
1473 raisePyExceptionWithAny( makeAny(e) );
1474 return 1;
1476 catch( const RuntimeException & e )
1478 raisePyExceptionWithAny( makeAny( 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( makeAny( e ) );
1527 result = (op == Py_EQ ? Py_False : Py_True);
1528 Py_INCREF(result);
1529 return result;
1532 static PyMethodDef PyUNOMethods[] =
1534 {"__dir__", reinterpret_cast<PyCFunction>(PyUNO_dir), METH_NOARGS, nullptr},
1535 {nullptr, nullptr, 0, nullptr}
1538 static PyNumberMethods PyUNONumberMethods[] =
1540 nullptr, /* nb_add */
1541 nullptr, /* nb_subtract */
1542 nullptr, /* nb_multiply */
1543 nullptr, /* nb_remainder */
1544 nullptr, /* nb_divmod */
1545 nullptr, /* nb_power */
1546 nullptr, /* nb_negative */
1547 nullptr, /* nb_positive */
1548 nullptr, /* nb_absolute */
1549 PyUNO_bool, /* nb_bool */
1550 nullptr, /* nb_invert */
1551 nullptr, /* nb_lshift */
1552 nullptr, /* nb_rshift */
1553 nullptr, /* nb_and */
1554 nullptr, /* nb_xor */
1555 nullptr, /* nb_or */
1556 nullptr, /* nb_int */
1557 nullptr, /* nb_reserved */
1558 nullptr, /* nb_float */
1559 nullptr, /* nb_inplace_add */
1560 nullptr, /* nb_inplace_subtract */
1561 nullptr, /* nb_inplace_multiply */
1562 nullptr, /* nb_inplace_remainder */
1563 nullptr, /* nb_inplace_power */
1564 nullptr, /* nb_inplace_lshift */
1565 nullptr, /* nb_inplace_rshift */
1566 nullptr, /* nb_inplace_and */
1567 nullptr, /* nb_inplace_xor */
1568 nullptr, /* nb_inplace_or */
1570 nullptr, /* nb_floor_divide */
1571 nullptr, /* nb_true_divide */
1572 nullptr, /* nb_inplace_floor_divide */
1573 nullptr, /* nb_inplace_true_divide */
1575 nullptr, /* nb_index */
1576 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
1577 nullptr, /* nb_matrix_multiply */
1578 nullptr, /* nb_inplace_matrix_multiply */
1579 #endif
1582 static PySequenceMethods PyUNOSequenceMethods[] =
1584 nullptr, /* sq_length */
1585 nullptr, /* sq_concat */
1586 nullptr, /* sq_repeat */
1587 nullptr, /* sq_item */
1588 nullptr, /* sq_slice */
1589 nullptr, /* sq_ass_item */
1590 nullptr, /* sq_ass_slice */
1591 PyUNO_contains, /* sq_contains */
1592 nullptr, /* sq_inplace_concat */
1593 nullptr /* sq_inplace_repeat */
1596 static PyMappingMethods PyUNOMappingMethods[] =
1598 PyUNO_len, /* mp_length */
1599 PyUNO_getitem, /* mp_subscript */
1600 PyUNO_setitem, /* mp_ass_subscript */
1603 static PyTypeObject PyUNOType =
1605 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
1606 "pyuno",
1607 sizeof (PyUNO),
1609 PyUNO_del,
1610 #if PY_VERSION_HEX >= 0x03080000
1611 0, // Py_ssize_t tp_vectorcall_offset
1612 #else
1613 nullptr, // printfunc tp_print
1614 #endif
1615 PyUNO_getattr,
1616 PyUNO_setattr,
1617 /* this type does not exist in Python 3: (cmpfunc) */ nullptr,
1618 PyUNO_repr,
1619 PyUNONumberMethods,
1620 PyUNOSequenceMethods,
1621 PyUNOMappingMethods,
1622 PyUNO_hash,
1623 nullptr,
1624 PyUNO_str,
1625 nullptr,
1626 nullptr,
1627 nullptr,
1628 Py_TPFLAGS_HAVE_ITER | Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_HAVE_SEQUENCE_IN,
1629 nullptr,
1630 nullptr,
1631 nullptr,
1632 PyUNO_cmp,
1634 PyUNO_iter,
1635 nullptr,
1636 PyUNOMethods,
1637 nullptr,
1638 nullptr,
1639 nullptr,
1640 nullptr,
1641 nullptr,
1642 nullptr,
1644 nullptr,
1645 nullptr,
1646 nullptr,
1647 nullptr,
1648 nullptr,
1649 nullptr,
1650 nullptr,
1651 nullptr,
1652 nullptr,
1653 nullptr,
1654 nullptr
1656 #if PY_VERSION_HEX >= 0x03040000
1657 , nullptr
1658 #if PY_VERSION_HEX >= 0x03080000
1659 , nullptr // vectorcallfunc tp_vectorcall
1660 #if PY_VERSION_HEX < 0x03090000
1661 #if defined __clang__
1662 #pragma clang diagnostic push
1663 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1664 #endif
1665 , nullptr // tp_print
1666 #if defined __clang__
1667 #pragma clang diagnostic pop
1668 #endif
1669 #endif
1670 #endif
1671 #endif
1674 int PyUNO_initType()
1676 return PyType_Ready(&PyUNOType);
1679 PyRef getPyUnoClass()
1681 return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) );
1684 PyRef PyUNO_new (
1685 const Any &targetInterface,
1686 const Reference<XSingleServiceFactory> &ssf )
1688 Reference<XInvocation2> xInvocation;
1691 PyThreadDetach antiguard;
1692 xInvocation.set(
1693 ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), css::uno::UNO_QUERY_THROW );
1695 auto that = comphelper::getUnoTunnelImplementation<Adapter>(
1696 xInvocation->getIntrospection()->queryAdapter(cppu::UnoType<XUnoTunnel>::get()));
1697 if( that )
1698 return that->getWrappedObject();
1700 if( !Py_IsInitialized() )
1701 throw RuntimeException();
1703 PyUNO* self = PyObject_New (PyUNO, &PyUNOType);
1704 if (self == nullptr)
1705 return PyRef(); // == error
1706 self->members = new PyUNOInternals;
1707 self->members->xInvocation = xInvocation;
1708 self->members->wrappedObject = targetInterface;
1709 return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
1715 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */