Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / pyuno / source / module / pyuno.cxx
blobd554f5ca769c2d10bfd90ea309ec3c51b8f5fe5f
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/strbuf.hxx>
26 #include <rtl/ustrbuf.hxx>
28 #include <typelib/typedescription.hxx>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/lang/XTypeProvider.hpp>
32 #include <com/sun/star/beans/UnknownPropertyException.hpp>
33 #include <com/sun/star/container/XEnumerationAccess.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/container/XIndexContainer.hpp>
36 #include <com/sun/star/container/XIndexReplace.hpp>
37 #include <com/sun/star/container/XNameAccess.hpp>
38 #include <com/sun/star/container/XNameContainer.hpp>
39 #include <com/sun/star/container/XNameReplace.hpp>
40 #include <com/sun/star/script/CannotConvertException.hpp>
41 #include <com/sun/star/script/XInvocation2.hpp>
42 #include <com/sun/star/script/XTypeConverter.hpp>
43 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
44 #include <comphelper/servicehelper.hxx>
46 #include "pyuno_impl.hxx"
48 using com::sun::star::uno::Sequence;
49 using com::sun::star::uno::Reference;
50 using com::sun::star::uno::XInterface;
51 using com::sun::star::uno::Any;
52 using com::sun::star::uno::makeAny;
53 using com::sun::star::uno::UNO_QUERY;
54 using com::sun::star::uno::Type;
55 using com::sun::star::uno::TypeClass;
56 using com::sun::star::uno::TypeDescription;
57 using com::sun::star::uno::RuntimeException;
58 using com::sun::star::uno::Exception;
59 using com::sun::star::lang::XSingleServiceFactory;
60 using com::sun::star::lang::XServiceInfo;
61 using com::sun::star::lang::XTypeProvider;
62 using com::sun::star::lang::XUnoTunnel;
63 using com::sun::star::script::XInvocation2;
64 using com::sun::star::container::XEnumeration;
65 using com::sun::star::container::XEnumerationAccess;
66 using com::sun::star::container::XIndexAccess;
67 using com::sun::star::container::XIndexContainer;
68 using com::sun::star::container::XIndexReplace;
69 using com::sun::star::container::XNameAccess;
70 using com::sun::star::container::XNameContainer;
71 using com::sun::star::container::XNameReplace;
73 namespace pyuno
76 static PyObject *PyUNO_str( PyObject * self );
78 static void PyUNO_del (PyObject* self)
80 PyUNO* me = reinterpret_cast< PyUNO* > (self);
82 PyThreadDetach antiguard;
83 delete me->members;
85 PyObject_Del (self);
89 OUString val2str( const void * pVal, typelib_TypeDescriptionReference * pTypeRef , sal_Int32 mode )
91 assert( pVal );
92 if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
93 return "void";
95 OUStringBuffer buf( 64 );
96 buf.append( "(" + OUString::unacquired(&pTypeRef->pTypeName) + ")" );
98 switch (pTypeRef->eTypeClass)
100 case typelib_TypeClass_INTERFACE:
102 buf.append( "0x" +
103 OUString::number( reinterpret_cast< sal_IntPtr >(*static_cast<void * const *>(pVal)), 16 ));
104 if( VAL2STR_MODE_DEEP == mode )
106 buf.append( "{" ); Reference< XInterface > r = *static_cast<Reference< XInterface > const *>(pVal);
107 Reference< XServiceInfo > serviceInfo( r, UNO_QUERY);
108 Reference< XTypeProvider > typeProvider(r,UNO_QUERY);
109 if( serviceInfo.is() )
111 buf.append("implementationName=" );
112 buf.append(serviceInfo->getImplementationName() );
113 buf.append(", supportedServices={" );
114 Sequence< OUString > seq = serviceInfo->getSupportedServiceNames();
115 for( int i = 0 ; i < seq.getLength() ; i ++ )
117 buf.append( seq[i] );
118 if( i +1 != seq.getLength() )
119 buf.append( "," );
121 buf.append("}");
124 if( typeProvider.is() )
126 buf.append(", supportedInterfaces={" );
127 Sequence< Type > seq (typeProvider->getTypes());
128 for( int i = 0 ; i < seq.getLength() ; i ++ )
130 buf.append(seq[i].getTypeName());
131 if( i +1 != seq.getLength() )
132 buf.append( "," );
134 buf.append("}");
136 buf.append( "}" );
139 break;
141 case typelib_TypeClass_STRUCT:
142 case typelib_TypeClass_EXCEPTION:
144 buf.append( "{ " );
145 typelib_TypeDescription * pTypeDescr = nullptr;
146 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
147 assert( pTypeDescr );
149 typelib_CompoundTypeDescription * pCompType = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
150 sal_Int32 nDescr = pCompType->nMembers;
152 if (pCompType->pBaseTypeDescription)
154 buf.append( val2str( pVal, pCompType->pBaseTypeDescription->aBase.pWeakRef, mode ) );
155 if (nDescr)
156 buf.append( ", " );
159 typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
160 sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
161 rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
163 for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
165 buf.append( OUString::unacquired(&ppMemberNames[nPos]) + " = " );
166 typelib_TypeDescription * pMemberType = nullptr;
167 TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[nPos] );
168 buf.append( val2str( static_cast<char const *>(pVal) + pMemberOffsets[nPos], pMemberType->pWeakRef, mode ) );
169 TYPELIB_DANGER_RELEASE( pMemberType );
170 if (nPos < (nDescr -1))
171 buf.append( ", " );
174 TYPELIB_DANGER_RELEASE( pTypeDescr );
176 buf.append( " }" );
177 break;
179 case typelib_TypeClass_SEQUENCE:
181 typelib_TypeDescription * pTypeDescr = nullptr;
182 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
184 uno_Sequence * pSequence = *static_cast<uno_Sequence * const *>(pVal);
185 typelib_TypeDescription * pElementTypeDescr = nullptr;
186 TYPELIB_DANGER_GET( &pElementTypeDescr, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
188 sal_Int32 nElementSize = pElementTypeDescr->nSize;
189 sal_Int32 nElements = pSequence->nElements;
191 if (nElements)
193 buf.append( "{ " );
194 char * pElements = pSequence->elements;
195 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
197 buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef, mode ) );
198 if (nPos < (nElements -1))
199 buf.append( ", " );
201 buf.append( " }" );
203 else
205 buf.append( "{}" );
207 TYPELIB_DANGER_RELEASE( pElementTypeDescr );
208 TYPELIB_DANGER_RELEASE( pTypeDescr );
209 break;
211 case typelib_TypeClass_ANY:
212 buf.append( "{ " );
213 buf.append( val2str( static_cast<uno_Any const *>(pVal)->pData,
214 static_cast<uno_Any const *>(pVal)->pType ,
215 mode) );
216 buf.append( " }" );
217 break;
218 case typelib_TypeClass_TYPE:
219 buf.append( (*static_cast<typelib_TypeDescriptionReference * const *>(pVal))->pTypeName );
220 break;
221 case typelib_TypeClass_STRING:
222 buf.append( "\"" +
223 OUString::unacquired(&*static_cast<rtl_uString * const *>(pVal)) +
224 "\"" );
225 break;
226 case typelib_TypeClass_ENUM:
228 typelib_TypeDescription * pTypeDescr = nullptr;
229 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
231 sal_Int32 * pValues = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->pEnumValues;
232 sal_Int32 nPos = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nEnumValues;
233 while (nPos--)
235 if (pValues[nPos] == *static_cast<int const *>(pVal))
236 break;
238 if (nPos >= 0)
239 buf.append( reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->ppEnumNames[nPos] );
240 else
241 buf.append( '?' );
243 TYPELIB_DANGER_RELEASE( pTypeDescr );
244 break;
246 case typelib_TypeClass_BOOLEAN:
247 if (*static_cast<sal_Bool const *>(pVal))
248 buf.append( "true" );
249 else
250 buf.append( "false" );
251 break;
252 case typelib_TypeClass_CHAR:
253 buf.append( '\'' );
254 buf.append( *static_cast<sal_Unicode const *>(pVal) );
255 buf.append( '\'' );
256 break;
257 case typelib_TypeClass_FLOAT:
258 buf.append( *static_cast<float const *>(pVal) );
259 break;
260 case typelib_TypeClass_DOUBLE:
261 buf.append( *static_cast<double const *>(pVal) );
262 break;
263 case typelib_TypeClass_BYTE:
264 buf.append( "0x" +
265 OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int8 const *>(pVal)), 16 ));
266 break;
267 case typelib_TypeClass_SHORT:
268 buf.append( "0x" +
269 OUString::number( static_cast<sal_Int32>(*static_cast<sal_Int16 const *>(pVal)), 16 ));
270 break;
271 case typelib_TypeClass_UNSIGNED_SHORT:
272 buf.append( "0x" +
273 OUString::number( static_cast<sal_Int32>(*static_cast<sal_uInt16 const *>(pVal)), 16 ));
274 break;
275 case typelib_TypeClass_LONG:
276 buf.append( "0x" +
277 OUString::number( *static_cast<sal_Int32 const *>(pVal), 16 ));
278 break;
279 case typelib_TypeClass_UNSIGNED_LONG:
280 buf.append( "0x" +
281 OUString::number( static_cast<sal_Int64>(*static_cast<sal_uInt32 const *>(pVal)), 16 ));
282 break;
283 case typelib_TypeClass_HYPER:
284 case typelib_TypeClass_UNSIGNED_HYPER:
285 buf.append( "0x" );
286 #if defined(__GNUC__) && defined(SPARC)
287 // I guess this really should check if there are strict alignment
288 // requirements, not just "GCC on SPARC".
290 sal_Int64 aVal;
291 *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
292 *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
293 buf.append( aVal, 16 );
295 #else
296 buf.append( *static_cast<sal_Int64 const *>(pVal), 16 );
297 #endif
298 break;
300 case typelib_TypeClass_VOID:
301 case typelib_TypeClass_UNKNOWN:
302 case typelib_TypeClass_SERVICE:
303 case typelib_TypeClass_MODULE:
304 default:
305 buf.append( '?' );
308 return buf.makeStringAndClear();
311 static sal_Int32 lcl_PyNumber_AsSal_Int32( PyObject *pObj )
313 // Check object is an index
314 PyRef rIndex( PyNumber_Index( pObj ), SAL_NO_ACQUIRE );
315 if ( !rIndex.is() )
316 return -1;
318 // Convert Python number to platform long, then check actual value against
319 // bounds of sal_Int32
320 #if PY_VERSION_HEX >= 0x03020000
321 int nOverflow;
322 long nResult = PyLong_AsLongAndOverflow( pObj, &nOverflow );
323 if ( nOverflow || nResult > SAL_MAX_INT32 || nResult < SAL_MIN_INT32) {
324 #else
325 long nResult = PyLong_AsLong( pObj );
326 if ( nResult > SAL_MAX_INT32 || nResult < SAL_MIN_INT32) {
327 #endif
328 PyErr_SetString( PyExc_IndexError, "Python int too large to convert to UNO long" );
329 return -1;
332 return nResult;
335 static int lcl_PySlice_GetIndicesEx( PyObject *pObject, sal_Int32 nLen, sal_Int32 *nStart, sal_Int32 *nStop, sal_Int32 *nStep, sal_Int32 *nSliceLength )
337 Py_ssize_t nStart_ssize, nStop_ssize, nStep_ssize, nSliceLength_ssize;
339 int nResult = PySlice_GetIndicesEx(
340 #if PY_VERSION_HEX >= 0x030200f0
341 pObject,
342 #else
343 reinterpret_cast<PySliceObject*>(pObject),
344 #endif
345 nLen, &nStart_ssize, &nStop_ssize, &nStep_ssize, &nSliceLength_ssize );
346 if (nResult == -1)
347 return -1;
349 if ( nStart_ssize > SAL_MAX_INT32 || nStart_ssize < SAL_MIN_INT32
350 || nStop_ssize > SAL_MAX_INT32 || nStop_ssize < SAL_MIN_INT32
351 || nStep_ssize > SAL_MAX_INT32 || nStep_ssize < SAL_MIN_INT32
352 || nSliceLength_ssize > SAL_MAX_INT32 || nSliceLength_ssize < SAL_MIN_INT32 )
354 PyErr_SetString( PyExc_IndexError, "Python int too large to convert to UNO long" );
355 return -1;
358 *nStart = static_cast<sal_Int32>(nStart_ssize);
359 *nStop = static_cast<sal_Int32>(nStop_ssize);
360 *nStep = static_cast<sal_Int32>(nStep_ssize);
361 *nSliceLength = static_cast<sal_Int32>(nSliceLength_ssize);
362 return 0;
365 static bool lcl_hasInterfaceByName( Any const &object, OUString const & interfaceName )
367 Reference< XInterface > xInterface( object, UNO_QUERY );
368 TypeDescription typeDesc( interfaceName );
369 Any aInterface = xInterface->queryInterface( typeDesc.get()->pWeakRef );
371 return aInterface.hasValue();
374 static PyObject *PyUNO_repr( PyObject * self )
376 return PyUNO_str( self );
379 static Py_hash_t PyUNO_hash( PyObject *self )
382 PyUNO *me = reinterpret_cast<PyUNO *>(self);
384 // Py_hash_t is not necessarily the same size as a pointer, but this is not
385 // important for hashing - it just has to return the same value each time
386 return sal::static_int_cast< Py_hash_t >( reinterpret_cast< sal_IntPtr > (
387 *static_cast<void * const *>(me->members->wrappedObject.getValue()) ) );
391 PyObject *PyUNO_invoke( PyObject *object, const char *name , PyObject *args )
393 PyRef ret;
396 Runtime runtime;
398 PyRef paras,callable;
399 if( PyObject_IsInstance( object, getPyUnoClass().get() ) )
401 PyUNO* me = reinterpret_cast<PyUNO*>(object);
402 OUString attrName = OUString::createFromAscii(name);
403 if (! me->members->xInvocation->hasMethod (attrName))
405 throw RuntimeException( "Attribute " + attrName + " unknown" );
407 callable = PyUNO_callable_new (
408 me->members->xInvocation,
409 attrName,
410 ACCEPT_UNO_ANY);
411 paras = args;
413 else
415 // clean the tuple from uno.Any !
416 int size = PyTuple_Size( args );
417 { // for CC, keeping ref-count of tuple being 1
418 paras = PyRef(PyTuple_New( size ), SAL_NO_ACQUIRE);
420 for( int i = 0 ; i < size ;i ++ )
422 PyObject * element = PyTuple_GetItem( args , i );
423 if( PyObject_IsInstance( element , getAnyClass( runtime ).get() ) )
425 element = PyObject_GetAttrString(
426 element, "value" );
428 else
430 Py_XINCREF( element );
432 PyTuple_SetItem( paras.get(), i , element );
434 callable = PyRef( PyObject_GetAttrString( object , name ), SAL_NO_ACQUIRE );
435 if( !callable.is() )
436 return nullptr;
438 ret = PyRef( PyObject_CallObject( callable.get(), paras.get() ), SAL_NO_ACQUIRE );
440 catch (const css::lang::IllegalArgumentException &e)
442 raisePyExceptionWithAny( css::uno::makeAny( e ) );
444 catch (const css::script::CannotConvertException &e)
446 raisePyExceptionWithAny( css::uno::makeAny( e ) );
448 catch (const css::uno::RuntimeException &e)
450 raisePyExceptionWithAny( css::uno::makeAny( e ) );
452 catch (const css::uno::Exception &e)
454 raisePyExceptionWithAny( css::uno::makeAny( e ) );
457 return ret.getAcquired();
460 PyObject *PyUNO_str( PyObject * self )
462 PyUNO *me = reinterpret_cast<PyUNO *>(self);
464 OString buf;
467 PyThreadDetach antiguard;
469 OUString s = val2str( me->members->wrappedObject.getValue(),
470 me->members->wrappedObject.getValueType().getTypeLibType() );
471 buf = "pyuno object " + OUStringToOString(s,RTL_TEXTENCODING_ASCII_US);
474 return PyStr_FromString( buf.getStr() );
477 static PyObject* PyUNO_dir (PyObject* self)
479 PyUNO* me = reinterpret_cast<PyUNO*>(self);
481 PyObject* member_list = nullptr;
482 Sequence<OUString> oo_member_list;
486 oo_member_list = me->members->xInvocation->getMemberNames ();
487 member_list = PyList_New (oo_member_list.getLength ());
488 for (int i = 0; i < oo_member_list.getLength (); i++)
490 // setitem steals a reference
491 PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() );
494 catch( const RuntimeException &e )
496 raisePyExceptionWithAny( makeAny(e) );
499 return member_list;
502 static sal_Int32 lcl_detach_getLength( PyUNO const *me )
504 PyThreadDetach antiguard;
506 // If both XIndexContainer and XNameContainer are implemented, it is
507 // assumed that getCount() gives the same result as the number of names
508 // returned by getElementNames(), or the user may be surprised.
510 // For XIndexContainer
511 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
512 if ( xIndexAccess.is() )
514 return xIndexAccess->getCount();
517 // For XNameContainer
518 // Not terribly efficient - get the count of all the names
519 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
520 if ( xNameAccess.is() )
522 return xNameAccess->getElementNames().getLength();
525 return -1;
528 static int PyUNO_bool( PyObject* self )
530 PyUNO* me = reinterpret_cast<PyUNO*>(self);
534 int nLen = lcl_detach_getLength( me );
535 if (nLen >= 0)
536 return nLen == 0 ? 0 : 1;
538 // Anything which doesn't have members is a scalar object and therefore true
539 return 1;
541 catch( const css::uno::RuntimeException &e )
543 raisePyExceptionWithAny( css::uno::makeAny( e ) );
546 return -1;
549 static Py_ssize_t PyUNO_len( PyObject* self )
551 PyUNO* me = reinterpret_cast<PyUNO*>(self);
555 int nLen = lcl_detach_getLength( me );
556 if (nLen >= 0)
557 return nLen;
559 PyErr_SetString( PyExc_TypeError, "object has no len()" );
561 catch( const css::uno::RuntimeException &e )
563 raisePyExceptionWithAny( css::uno::makeAny( e ) );
566 return -1;
569 static void lcl_getRowsColumns( PyUNO const * me, sal_Int32& nRows, sal_Int32& nColumns )
571 Sequence<short> aOutParamIndex;
572 Sequence<Any> aOutParam;
573 Sequence<Any> aParams;
574 Any aRet = me->members->xInvocation->invoke ( "getRows", aParams, aOutParamIndex, aOutParam );
575 Reference< XIndexAccess > xIndexAccessRows( aRet, UNO_QUERY );
576 nRows = xIndexAccessRows->getCount();
577 aRet = me->members->xInvocation->invoke ( "getColumns", aParams, aOutParamIndex, aOutParam );
578 Reference< XIndexAccess > xIndexAccessCols( aRet, UNO_QUERY );
579 nColumns = xIndexAccessCols->getCount();
582 static PyRef lcl_indexToSlice( const PyRef& rIndex )
584 Py_ssize_t nIndex = PyNumber_AsSsize_t( rIndex.get(), PyExc_IndexError );
585 if (nIndex == -1 && PyErr_Occurred())
586 return nullptr;
587 PyRef rStart( PyLong_FromSsize_t( nIndex ), SAL_NO_ACQUIRE );
588 PyRef rStop( PyLong_FromSsize_t( nIndex+1 ), SAL_NO_ACQUIRE );
589 PyRef rStep( PyLong_FromLong( 1 ), SAL_NO_ACQUIRE );
590 PyRef rSlice( PySlice_New( rStart.get(), rStop.get(), rStep.get() ), SAL_NO_ACQUIRE );
592 return rSlice;
595 static PyObject* lcl_getitem_XCellRange( PyUNO const * me, PyObject* pKey )
597 Runtime runtime;
599 Sequence<short> aOutParamIndex;
600 Sequence<Any> aOutParam;
601 Sequence<Any> aParams;
602 Any aRet;
604 // Single string key is sugar for getCellRangeByName()
605 if ( PyStr_Check( pKey ) ) {
607 aParams.realloc (1);
608 aParams[0] <<= pyString2ustring( pKey );
610 PyThreadDetach antiguard;
611 aRet = me->members->xInvocation->invoke (
612 "getCellRangeByName", aParams, aOutParamIndex, aOutParam );
614 PyRef rRet = runtime.any2PyObject ( aRet );
615 return rRet.getAcquired();
619 PyRef rKey0, rKey1;
620 if ( PyIndex_Check( pKey ) )
622 // [0] is equivalent to [0,:]
623 rKey0 = pKey;
624 rKey1 = PySlice_New( nullptr, nullptr, nullptr );
626 else if ( PyTuple_Check( pKey ) && (PyTuple_Size( pKey ) == 2) )
628 rKey0 = PyTuple_GetItem( pKey, 0 );
629 rKey1 = PyTuple_GetItem( pKey, 1 );
631 else
633 PyErr_SetString( PyExc_KeyError, "invalid subscript" );
634 return nullptr;
637 // If both keys are indices, return the corresponding cell
638 if ( PyIndex_Check( rKey0.get() ) && PyIndex_Check( rKey1.get() ))
640 sal_Int32 nKey0_s = lcl_PyNumber_AsSal_Int32( rKey0.get() );
641 sal_Int32 nKey1_s = lcl_PyNumber_AsSal_Int32( rKey1.get() );
643 if ( ((nKey0_s == -1) || (nKey1_s == -1)) && PyErr_Occurred() )
644 return nullptr;
646 aParams.realloc( 2 );
647 aParams[0] <<= nKey1_s;
648 aParams[1] <<= nKey0_s;
650 PyThreadDetach antiguard;
651 aRet = me->members->xInvocation->invoke (
652 "getCellByPosition", aParams, aOutParamIndex, aOutParam );
654 PyRef rRet = runtime.any2PyObject( aRet );
655 return rRet.getAcquired();
658 // If either argument is an index, coerce it to a slice
659 if ( PyIndex_Check( rKey0.get() ) )
660 rKey0 = lcl_indexToSlice( rKey0 );
662 if ( PyIndex_Check( rKey1.get() ) )
663 rKey1 = lcl_indexToSlice( rKey1 );
665 // If both arguments are slices, return the corresponding cell range
666 if ( PySlice_Check( rKey0.get() ) && PySlice_Check( rKey1.get() ) )
668 sal_Int32 nLen0 = SAL_MAX_INT32, nLen1 = SAL_MAX_INT32;
669 sal_Int32 nStart0 = 0, nStop0 = 0, nStep0 = 0, nSliceLength0 = 0;
670 sal_Int32 nStart1 = 0, nStop1 = 0, nStep1 = 0, nSliceLength1 = 0;
673 PyThreadDetach antiguard;
675 if ( lcl_hasInterfaceByName( me->members->wrappedObject, "com.sun.star.table.XColumnRowRange" ) )
677 lcl_getRowsColumns (me, nLen0, nLen1);
681 int nSuccess1 = lcl_PySlice_GetIndicesEx( rKey0.get(), nLen0, &nStart0, &nStop0, &nStep0, &nSliceLength0 );
682 int nSuccess2 = lcl_PySlice_GetIndicesEx( rKey1.get(), nLen1, &nStart1, &nStop1, &nStep1, &nSliceLength1 );
683 if ( ((nSuccess1 == -1) || (nSuccess2 == -1)) && PyErr_Occurred() )
684 return nullptr;
686 if ( nSliceLength0 <= 0 || nSliceLength1 <= 0 )
688 PyErr_SetString( PyExc_KeyError, "invalid number of rows or columns" );
689 return nullptr;
692 if ( nStep0 == 1 && nStep1 == 1 )
694 aParams.realloc (4);
695 aParams[0] <<= nStart1;
696 aParams[1] <<= nStart0;
697 aParams[2] <<= nStop1 - 1;
698 aParams[3] <<= nStop0 - 1;
700 PyThreadDetach antiguard;
701 aRet = me->members->xInvocation->invoke (
702 "getCellRangeByPosition", aParams, aOutParamIndex, aOutParam );
704 PyRef rRet = runtime.any2PyObject( aRet );
705 return rRet.getAcquired();
708 PyErr_SetString( PyExc_KeyError, "step != 1 not supported" );
709 return nullptr;
712 PyErr_SetString( PyExc_KeyError, "invalid subscript" );
713 return nullptr;
716 static PyObject* lcl_getitem_index( PyUNO const *me, PyObject *pKey, Runtime const & runtime )
718 Any aRet;
719 sal_Int32 nIndex;
721 nIndex = lcl_PyNumber_AsSal_Int32( pKey );
722 if (nIndex == -1 && PyErr_Occurred())
723 return nullptr;
726 PyThreadDetach antiguard;
728 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
729 if ( xIndexAccess.is() )
731 if (nIndex < 0)
732 nIndex += xIndexAccess->getCount();
733 aRet = xIndexAccess->getByIndex( nIndex );
736 if ( aRet.hasValue() )
738 PyRef rRet ( runtime.any2PyObject( aRet ) );
739 return rRet.getAcquired();
742 return nullptr;
745 static PyObject* lcl_getitem_slice( PyUNO const *me, PyObject *pKey )
747 Runtime runtime;
749 Reference< XIndexAccess > xIndexAccess;
750 sal_Int32 nLen = 0;
753 PyThreadDetach antiguard;
755 xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
756 if ( xIndexAccess.is() )
757 nLen = xIndexAccess->getCount();
760 if ( xIndexAccess.is() )
762 sal_Int32 nStart = 0, nStop = 0, nStep = 0, nSliceLength = 0;
763 int nSuccess = lcl_PySlice_GetIndicesEx(pKey, nLen, &nStart, &nStop, &nStep, &nSliceLength);
764 if ( nSuccess == -1 && PyErr_Occurred() )
765 return nullptr;
767 PyRef rTuple( PyTuple_New( nSliceLength ), SAL_NO_ACQUIRE, NOT_NULL );
768 sal_Int32 nCur, i;
769 for ( nCur = nStart, i = 0; i < nSliceLength; nCur += nStep, i++ )
771 Any aRet;
774 PyThreadDetach antiguard;
776 aRet = xIndexAccess->getByIndex( nCur );
778 PyRef rRet = runtime.any2PyObject( aRet );
779 PyTuple_SetItem( rTuple.get(), i, rRet.getAcquired() );
782 return rTuple.getAcquired();
785 return nullptr;
788 static PyObject* lcl_getitem_string( PyUNO const *me, PyObject *pKey, Runtime const & runtime )
790 OUString sKey = pyString2ustring( pKey );
791 Any aRet;
794 PyThreadDetach antiguard;
796 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
797 if ( xNameAccess.is() )
799 aRet = xNameAccess->getByName( sKey );
802 if ( aRet.hasValue() )
804 PyRef rRet = runtime.any2PyObject( aRet );
805 return rRet.getAcquired();
808 return nullptr;
811 static PyObject* PyUNO_getitem( PyObject *self, PyObject *pKey )
813 PyUNO* me = reinterpret_cast<PyUNO*>(self);
814 Runtime runtime;
818 // XIndexAccess access by index
819 if ( PyIndex_Check( pKey ) )
821 PyObject* pRet = lcl_getitem_index( me, pKey, runtime );
822 if ( pRet != nullptr || PyErr_Occurred() )
823 return pRet;
826 // XIndexAccess access by slice
827 if ( PySlice_Check( pKey ) )
829 PyObject* pRet = lcl_getitem_slice( me, pKey );
830 if ( pRet != nullptr || PyErr_Occurred() )
831 return pRet;
834 // XNameAccess access by key
835 if ( PyStr_Check( pKey ) )
837 PyObject* pRet = lcl_getitem_string( me, pKey, runtime );
838 if ( pRet != nullptr )
839 return pRet;
842 // XCellRange/XColumnRowRange specialisation
843 // Uses reflection as we can't have a hard dependency on XCellRange here
844 bool hasXCellRange = false;
847 PyThreadDetach antiguard;
849 hasXCellRange = lcl_hasInterfaceByName( me->members->wrappedObject, "com.sun.star.table.XCellRange" );
851 if ( hasXCellRange )
853 return lcl_getitem_XCellRange( me, pKey );
857 // If the object is an XIndexAccess and/or XNameAccess, but the
858 // key passed wasn't suitable, give a TypeError which specifically
859 // describes this
860 Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
861 Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
862 if ( xIndexAccess.is() || xNameAccess.is() )
864 PyErr_SetString( PyExc_TypeError, "subscription with invalid type" );
865 return nullptr;
868 PyErr_SetString( PyExc_TypeError, "object is not subscriptable" );
870 catch( const css::lang::IndexOutOfBoundsException & )
872 PyErr_SetString( PyExc_IndexError, "index out of range" );
874 catch( const css::container::NoSuchElementException & )
876 PyErr_SetString( PyExc_KeyError, "key not found" );
878 catch( const css::script::CannotConvertException &e )
880 raisePyExceptionWithAny( css::uno::makeAny( e ) );
882 catch( const css::lang::IllegalArgumentException &e )
884 raisePyExceptionWithAny( css::uno::makeAny( e ) );
886 catch( const css::lang::WrappedTargetException &e )
888 raisePyExceptionWithAny( css::uno::makeAny( e ) );
890 catch( const css::uno::RuntimeException &e )
892 raisePyExceptionWithAny( css::uno::makeAny( e ) );
895 return nullptr;
898 static int lcl_setitem_index( PyUNO const *me, PyObject *pKey, PyObject *pValue )
900 Runtime runtime;
902 Reference< XIndexContainer > xIndexContainer;
903 Reference< XIndexReplace > xIndexReplace;
904 sal_Int32 nIndex = lcl_PyNumber_AsSal_Int32( pKey );
905 if ( nIndex == -1 && PyErr_Occurred() )
906 return 0;
908 bool isTuple = false;
910 Any aValue;
911 if ( pValue != nullptr )
913 isTuple = PyTuple_Check( pValue );
917 aValue = runtime.pyObject2Any( pValue );
919 catch ( const css::uno::RuntimeException & )
921 // TODO pyObject2Any can't convert e.g. dicts but only throws
922 // RuntimeException on failure. Fixing this will require an audit of
923 // all the rest of PyUNO
924 throw css::script::CannotConvertException();
929 PyThreadDetach antiguard;
931 xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
932 if ( xIndexContainer.is() )
933 xIndexReplace = xIndexContainer;
934 else
935 xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
937 if ( xIndexReplace.is() && nIndex < 0 )
938 nIndex += xIndexReplace->getCount();
940 // XIndexReplace replace by index
941 if ( (pValue != nullptr) && xIndexReplace.is() )
943 if ( isTuple )
945 // Apply type specialisation to ensure the correct kind of sequence is passed
946 Type aType = xIndexReplace->getElementType();
947 aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
950 xIndexReplace->replaceByIndex( nIndex, aValue );
951 return 0;
954 // XIndexContainer remove by index
955 if ( (pValue == nullptr) && xIndexContainer.is() )
957 xIndexContainer->removeByIndex( nIndex );
958 return 0;
962 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
963 return 1;
966 static int lcl_setitem_slice( PyUNO const *me, PyObject *pKey, PyObject *pValue )
968 // XIndexContainer insert/remove/replace by slice
969 Runtime runtime;
971 Reference< XIndexReplace > xIndexReplace;
972 Reference< XIndexContainer > xIndexContainer;
973 sal_Int32 nLen = 0;
976 PyThreadDetach antiguard;
978 xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
979 if ( xIndexContainer.is() )
980 xIndexReplace = xIndexContainer;
981 else
982 xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
984 if ( xIndexReplace.is() )
985 nLen = xIndexReplace->getCount();
988 if ( xIndexReplace.is() )
990 sal_Int32 nStart = 0, nStop = 0, nStep = 0, nSliceLength = 0;
991 int nSuccess = lcl_PySlice_GetIndicesEx( pKey, nLen, &nStart, &nStop, &nStep, &nSliceLength );
992 if ( (nSuccess == -1) && PyErr_Occurred() )
993 return 0;
995 if ( pValue == nullptr )
997 pValue = PyTuple_New( 0 );
1000 if ( !PyTuple_Check (pValue) )
1002 PyErr_SetString( PyExc_TypeError, "value is not a tuple" );
1003 return 1;
1006 Py_ssize_t nTupleLength_ssize = PyTuple_Size( pValue );
1007 if ( nTupleLength_ssize > SAL_MAX_INT32 )
1009 PyErr_SetString( PyExc_ValueError, "tuple too large" );
1010 return 1;
1012 sal_Int32 nTupleLength = static_cast<sal_Int32>(nTupleLength_ssize);
1014 if ( (nTupleLength != nSliceLength) && (nStep != 1) )
1016 PyErr_SetString( PyExc_ValueError, "number of items assigned must be equal" );
1017 return 1;
1020 if ( (nTupleLength != nSliceLength) && !xIndexContainer.is() )
1022 PyErr_SetString( PyExc_ValueError, "cannot change length" );
1023 return 1;
1026 sal_Int32 nCur, i;
1027 sal_Int32 nMax = ::std::max( nSliceLength, nTupleLength );
1028 for ( nCur = nStart, i = 0; i < nMax; nCur += nStep, i++ )
1030 if ( i < nTupleLength )
1032 PyRef rItem = PyTuple_GetItem( pValue, i );
1033 bool isTuple = PyTuple_Check( rItem.get() );
1035 Any aItem;
1038 aItem = runtime.pyObject2Any( rItem.get() );
1040 catch ( const css::uno::RuntimeException & )
1042 // TODO pyObject2Any can't convert e.g. dicts but only throws
1043 // RuntimeException on failure. Fixing this will require an audit of
1044 // all the rest of PyUNO
1045 throw css::script::CannotConvertException();
1049 PyThreadDetach antiguard;
1051 if ( isTuple )
1053 // Apply type specialisation to ensure the correct kind of sequence is passed
1054 Type aType = xIndexReplace->getElementType();
1055 aItem = runtime.getImpl()->cargo->xTypeConverter->convertTo( aItem, aType );
1058 if ( i < nSliceLength )
1060 xIndexReplace->replaceByIndex( nCur, aItem );
1062 else
1064 xIndexContainer->insertByIndex( nCur, aItem );
1068 else
1070 PyThreadDetach antiguard;
1072 xIndexContainer->removeByIndex( nCur );
1073 nCur--;
1077 return 0;
1080 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
1081 return 1;
1084 static int lcl_setitem_string( PyUNO const *me, PyObject *pKey, PyObject *pValue )
1086 Runtime runtime;
1088 OUString sKey = pyString2ustring( pKey );
1089 bool isTuple = false;
1091 Any aValue;
1092 if ( pValue != nullptr)
1094 isTuple = PyTuple_Check( pValue );
1097 aValue = runtime.pyObject2Any( pValue );
1099 catch( const css::uno::RuntimeException & )
1101 // TODO pyObject2Any can't convert e.g. dicts but only throws
1102 // RuntimeException on failure. Fixing this will require an audit of
1103 // all the rest of PyUNO
1104 throw css::script::CannotConvertException();
1109 PyThreadDetach antiguard;
1111 Reference< XNameContainer > xNameContainer( me->members->xInvocation, UNO_QUERY );
1112 Reference< XNameReplace > xNameReplace;
1113 if ( xNameContainer.is() )
1114 xNameReplace = xNameContainer;
1115 else
1116 xNameReplace.set( me->members->xInvocation, UNO_QUERY );
1118 if ( xNameReplace.is() )
1120 if ( isTuple && aValue.hasValue() )
1122 // Apply type specialisation to ensure the correct kind of sequence is passed
1123 Type aType = xNameReplace->getElementType();
1124 aValue = runtime.getImpl()->cargo->xTypeConverter->convertTo( aValue, aType );
1127 if ( aValue.hasValue() )
1129 if ( xNameContainer.is() )
1131 try {
1132 xNameContainer->insertByName( sKey, aValue );
1133 return 0;
1135 catch( const css::container::ElementExistException & )
1137 // Fall through, try replace instead
1141 xNameReplace->replaceByName( sKey, aValue );
1142 return 0;
1144 else if ( xNameContainer.is() )
1146 xNameContainer->removeByName( sKey );
1147 return 0;
1152 PyErr_SetString( PyExc_TypeError, "cannot assign to object" );
1153 return 1;
1156 static int PyUNO_setitem( PyObject *self, PyObject *pKey, PyObject *pValue )
1158 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1162 if ( PyIndex_Check( pKey ) )
1164 return lcl_setitem_index( me, pKey, pValue );
1166 else if ( PySlice_Check( pKey ) )
1168 return lcl_setitem_slice( me, pKey, pValue );
1170 else if ( PyStr_Check( pKey ) )
1172 return lcl_setitem_string( me, pKey, pValue );
1175 PyErr_SetString( PyExc_TypeError, "list index has invalid type" );
1177 catch( const css::lang::IndexOutOfBoundsException & )
1179 PyErr_SetString( PyExc_IndexError, "list index out of range" );
1181 catch( const css::container::NoSuchElementException & )
1183 PyErr_SetString( PyExc_KeyError, "key not found" );
1185 catch( const css::lang::IllegalArgumentException & )
1187 PyErr_SetString( PyExc_TypeError, "value has invalid type" );
1189 catch( const css::script::CannotConvertException & )
1191 PyErr_SetString( PyExc_TypeError, "value has invalid type" );
1193 catch( const css::container::ElementExistException &e )
1195 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1197 catch( const css::lang::WrappedTargetException &e )
1199 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1201 catch( const css::uno::RuntimeException &e )
1203 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1206 return 1;
1209 static PyObject* PyUNO_iter( PyObject *self )
1211 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1215 Reference< XEnumerationAccess > xEnumerationAccess;
1216 Reference< XEnumeration > xEnumeration;
1217 Reference< XIndexAccess > xIndexAccess;
1218 Reference< XNameAccess > xNameAccess;
1221 PyThreadDetach antiguard;
1223 xEnumerationAccess.set( me->members->xInvocation, UNO_QUERY );
1224 if ( xEnumerationAccess.is() )
1225 xEnumeration = xEnumerationAccess->createEnumeration();
1226 else
1227 xEnumeration.set( me->members->wrappedObject, UNO_QUERY );
1229 if ( !xEnumeration.is() )
1230 xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
1232 if ( !xIndexAccess.is() )
1233 xNameAccess.set( me->members->xInvocation, UNO_QUERY );
1236 // XEnumerationAccess iterator
1237 // XEnumeration iterator
1238 if (xEnumeration.is())
1240 return PyUNO_iterator_new( xEnumeration );
1243 // XIndexAccess iterator
1244 if ( xIndexAccess.is() )
1246 // We'd like to be able to use PySeqIter_New() here, but we're not
1247 // allowed to because we also implement the mapping protocol
1248 return PyUNO_list_iterator_new( xIndexAccess );
1251 // XNameAccess iterator
1252 if (xNameAccess.is())
1254 // There's no generic mapping iterator, but we can cobble our own
1255 // together using PySeqIter_New()
1256 Runtime runtime;
1257 Any aRet;
1260 PyThreadDetach antiguard;
1261 aRet <<= xNameAccess->getElementNames();
1263 PyRef rNames = runtime.any2PyObject( aRet );
1264 return PySeqIter_New( rNames.getAcquired() );
1267 PyErr_SetString ( PyExc_TypeError, "object is not iterable" );
1269 catch( css::script::CannotConvertException &e )
1271 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1273 catch( css::lang::IllegalArgumentException &e )
1275 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1277 catch( const css::uno::RuntimeException &e )
1279 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1282 return nullptr;
1285 static int PyUNO_contains( PyObject *self, PyObject *pKey )
1287 PyUNO* me = reinterpret_cast<PyUNO*>(self);
1289 Runtime runtime;
1293 Any aValue;
1296 aValue = runtime.pyObject2Any( pKey );
1298 catch( const css::uno::RuntimeException & )
1300 // TODO pyObject2Any can't convert e.g. dicts but only throws
1301 // RuntimeException on failure. Fixing this will require an audit of
1302 // all the rest of PyUNO
1303 throw css::script::CannotConvertException();
1306 // XNameAccess is tried first, because checking key presence is much more
1307 // useful for objects which implement both XIndexAccess and XNameAccess
1309 // For XNameAccess
1310 if ( PyStr_Check( pKey ) )
1312 OUString sKey;
1313 aValue >>= sKey;
1314 Reference< XNameAccess > xNameAccess;
1317 PyThreadDetach antiguard;
1319 xNameAccess.set( me->members->xInvocation, UNO_QUERY );
1320 if ( xNameAccess.is() )
1322 bool hasKey = xNameAccess->hasByName( sKey );
1323 return hasKey ? 1 : 0;
1328 // For any other type of PyUNO iterable: Ugly iterative search by
1329 // content (XIndexAccess, XEnumerationAccess, XEnumeration)
1330 PyRef rIterator( PyUNO_iter( self ), SAL_NO_ACQUIRE );
1331 if ( rIterator.is() )
1333 while ( PyObject* pItem = PyIter_Next( rIterator.get() ) )
1335 PyRef rItem( pItem, SAL_NO_ACQUIRE );
1336 if ( PyObject_RichCompareBool( pKey, rItem.get(), Py_EQ ) == 1 )
1338 return 1;
1341 return 0;
1344 PyErr_SetString( PyExc_TypeError, "argument is not iterable" );
1346 catch( const css::script::CannotConvertException& )
1348 PyErr_SetString( PyExc_TypeError, "invalid type passed as left argument to 'in'" );
1350 catch( const css::container::NoSuchElementException &e )
1352 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1354 catch( const css::lang::IndexOutOfBoundsException &e )
1356 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1358 catch( const css::lang::IllegalArgumentException &e )
1360 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1362 catch( const css::lang::WrappedTargetException &e )
1364 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1366 catch( const css::uno::RuntimeException &e )
1368 raisePyExceptionWithAny( css::uno::makeAny( e ) );
1371 return -1;
1374 static PyObject* PyUNO_getattr (PyObject* self, char* name)
1376 PyUNO* me;
1381 Runtime runtime;
1383 me = reinterpret_cast<PyUNO*>(self);
1384 if (strcmp (name, "__dict__") == 0)
1386 Py_INCREF (Py_TYPE(me)->tp_dict);
1387 return Py_TYPE(me)->tp_dict;
1389 if (strcmp (name, "__class__") == 0)
1391 Py_INCREF (Py_None);
1392 return Py_None;
1395 PyObject *pRet = PyObject_GenericGetAttr( self, PyUnicode_FromString( name ) );
1396 if( pRet )
1397 return pRet;
1398 PyErr_Clear();
1400 OUString attrName( OUString::createFromAscii( name ) );
1401 //We need to find out if it's a method...
1402 if (me->members->xInvocation->hasMethod (attrName))
1404 //Create a callable object to invoke this...
1405 PyRef ret = PyUNO_callable_new (
1406 me->members->xInvocation,
1407 attrName);
1408 Py_XINCREF( ret.get() );
1409 return ret.get();
1413 //or a property
1414 if (me->members->xInvocation->hasProperty ( attrName))
1416 //Return the value of the property
1417 Any anyRet;
1419 PyThreadDetach antiguard;
1420 anyRet = me->members->xInvocation->getValue (attrName);
1422 PyRef ret = runtime.any2PyObject(anyRet);
1423 Py_XINCREF( ret.get() );
1424 return ret.get();
1427 //or else...
1428 PyErr_SetString (PyExc_AttributeError, name);
1430 catch( const css::reflection::InvocationTargetException & e )
1432 raisePyExceptionWithAny( e.TargetException );
1434 catch( const css::beans::UnknownPropertyException & e )
1436 raisePyExceptionWithAny( makeAny(e) );
1438 catch( const css::lang::IllegalArgumentException &e )
1440 raisePyExceptionWithAny( makeAny(e) );
1442 catch( const css::script::CannotConvertException &e )
1444 raisePyExceptionWithAny( makeAny(e) );
1446 catch( const RuntimeException &e )
1448 raisePyExceptionWithAny( makeAny(e) );
1451 return nullptr;
1454 static int PyUNO_setattr (PyObject* self, char* name, PyObject* value)
1456 PyUNO* me;
1458 me = reinterpret_cast<PyUNO*>(self);
1461 Runtime runtime;
1462 Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
1464 OUString attrName( OUString::createFromAscii( name ) );
1466 PyThreadDetach antiguard;
1467 if (me->members->xInvocation->hasProperty (attrName))
1469 me->members->xInvocation->setValue (attrName, val);
1470 return 0; //Keep with Python's boolean system
1474 catch( const css::reflection::InvocationTargetException & e )
1476 raisePyExceptionWithAny( e.TargetException );
1477 return 1;
1479 catch( const css::beans::UnknownPropertyException & e )
1481 raisePyExceptionWithAny( makeAny(e) );
1482 return 1;
1484 catch( const css::script::CannotConvertException &e )
1486 raisePyExceptionWithAny( makeAny(e) );
1487 return 1;
1489 catch( const RuntimeException & e )
1491 raisePyExceptionWithAny( makeAny( e ) );
1492 return 1;
1494 PyErr_SetString (PyExc_AttributeError, name);
1495 return 1; //as above.
1498 static PyObject* PyUNO_cmp( PyObject *self, PyObject *that, int op )
1500 PyObject *result;
1502 if(op != Py_EQ && op != Py_NE)
1504 PyErr_SetString(PyExc_TypeError, "only '==' and '!=' comparisons are defined");
1505 return nullptr;
1507 if( self == that )
1509 result = (op == Py_EQ ? Py_True : Py_False);
1510 Py_INCREF(result);
1511 return result;
1515 Runtime runtime;
1516 if( PyObject_IsInstance( that, getPyUnoClass().get() ) )
1519 PyUNO *me = reinterpret_cast< PyUNO*> ( self );
1520 PyUNO *other = reinterpret_cast< PyUNO *> (that );
1521 css::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
1522 css::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
1524 if( tcMe == tcOther )
1526 if( me->members->wrappedObject == other->members->wrappedObject )
1528 result = (op == Py_EQ ? Py_True : Py_False);
1529 Py_INCREF(result);
1530 return result;
1535 catch( const css::uno::RuntimeException & e)
1537 raisePyExceptionWithAny( makeAny( e ) );
1540 result = (op == Py_EQ ? Py_False : Py_True);
1541 Py_INCREF(result);
1542 return result;
1545 static PyMethodDef PyUNOMethods[] =
1547 {"__dir__", reinterpret_cast<PyCFunction>(PyUNO_dir), METH_NOARGS, nullptr},
1548 {nullptr, nullptr, 0, nullptr}
1551 static PyNumberMethods PyUNONumberMethods[] =
1553 nullptr, /* nb_add */
1554 nullptr, /* nb_subtract */
1555 nullptr, /* nb_multiply */
1556 #if PY_MAJOR_VERSION < 3
1557 nullptr, /* nb_divide */
1558 #endif
1559 nullptr, /* nb_remainder */
1560 nullptr, /* nb_divmod */
1561 nullptr, /* nb_power */
1562 nullptr, /* nb_negative */
1563 nullptr, /* nb_positive */
1564 nullptr, /* nb_absolute */
1565 PyUNO_bool, /* nb_bool */
1566 nullptr, /* nb_invert */
1567 nullptr, /* nb_lshift */
1568 nullptr, /* nb_rshift */
1569 nullptr, /* nb_and */
1570 nullptr, /* nb_xor */
1571 nullptr, /* nb_or */
1572 #if PY_MAJOR_VERSION < 3
1573 nullptr, /* nb_coerce */
1574 #endif
1575 nullptr, /* nb_int */
1576 nullptr, /* nb_reserved */
1577 nullptr, /* nb_float */
1578 #if PY_MAJOR_VERSION < 3
1579 nullptr, /* nb_oct */
1580 nullptr, /* nb_hex */
1581 #endif
1582 nullptr, /* nb_inplace_add */
1583 nullptr, /* nb_inplace_subtract */
1584 nullptr, /* nb_inplace_multiply */
1585 #if PY_MAJOR_VERSION < 3
1586 nullptr, /* nb_inplace_divide */
1587 #endif
1588 nullptr, /* nb_inplace_remainder */
1589 nullptr, /* nb_inplace_power */
1590 nullptr, /* nb_inplace_lshift */
1591 nullptr, /* nb_inplace_rshift */
1592 nullptr, /* nb_inplace_and */
1593 nullptr, /* nb_inplace_xor */
1594 nullptr, /* nb_inplace_or */
1596 nullptr, /* nb_floor_divide */
1597 nullptr, /* nb_true_divide */
1598 nullptr, /* nb_inplace_floor_divide */
1599 nullptr, /* nb_inplace_true_divide */
1601 nullptr, /* nb_index */
1602 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5
1603 nullptr, /* nb_matrix_multiply */
1604 nullptr, /* nb_inplace_matrix_multiply */
1605 #endif
1608 static PySequenceMethods PyUNOSequenceMethods[] =
1610 nullptr, /* sq_length */
1611 nullptr, /* sq_concat */
1612 nullptr, /* sq_repeat */
1613 nullptr, /* sq_item */
1614 nullptr, /* sq_slice */
1615 nullptr, /* sq_ass_item */
1616 nullptr, /* sq_ass_slice */
1617 PyUNO_contains, /* sq_contains */
1618 nullptr, /* sq_inplace_concat */
1619 nullptr /* sq_inplace_repeat */
1622 static PyMappingMethods PyUNOMappingMethods[] =
1624 PyUNO_len, /* mp_length */
1625 PyUNO_getitem, /* mp_subscript */
1626 PyUNO_setitem, /* mp_ass_subscript */
1629 static PyTypeObject PyUNOType =
1631 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
1632 "pyuno",
1633 sizeof (PyUNO),
1635 PyUNO_del,
1636 #if PY_VERSION_HEX >= 0x03080000
1637 0, // Py_ssize_t tp_vectorcall_offset
1638 #else
1639 nullptr, // printfunc tp_print
1640 #endif
1641 PyUNO_getattr,
1642 PyUNO_setattr,
1643 /* this type does not exist in Python 3: (cmpfunc) */ nullptr,
1644 PyUNO_repr,
1645 PyUNONumberMethods,
1646 PyUNOSequenceMethods,
1647 PyUNOMappingMethods,
1648 PyUNO_hash,
1649 nullptr,
1650 PyUNO_str,
1651 nullptr,
1652 nullptr,
1653 nullptr,
1654 Py_TPFLAGS_HAVE_ITER | Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_HAVE_SEQUENCE_IN,
1655 nullptr,
1656 nullptr,
1657 nullptr,
1658 PyUNO_cmp,
1660 PyUNO_iter,
1661 nullptr,
1662 PyUNOMethods,
1663 nullptr,
1664 nullptr,
1665 nullptr,
1666 nullptr,
1667 nullptr,
1668 nullptr,
1670 nullptr,
1671 nullptr,
1672 nullptr,
1673 nullptr,
1674 nullptr,
1675 nullptr,
1676 nullptr,
1677 nullptr,
1678 nullptr,
1679 nullptr,
1680 nullptr
1682 #if PY_VERSION_HEX >= 0x03040000
1683 , nullptr
1684 #if PY_VERSION_HEX >= 0x03080000
1685 , nullptr // vectorcallfunc tp_vectorcall
1686 #endif
1687 #endif
1690 int PyUNO_initType()
1692 return PyType_Ready(&PyUNOType);
1695 PyRef getPyUnoClass()
1697 return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) );
1700 PyRef PyUNO_new (
1701 const Any &targetInterface,
1702 const Reference<XSingleServiceFactory> &ssf )
1704 Reference<XInvocation2> xInvocation;
1707 PyThreadDetach antiguard;
1708 xInvocation.set(
1709 ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), css::uno::UNO_QUERY_THROW );
1711 auto that = comphelper::getUnoTunnelImplementation<Adapter>(
1712 xInvocation->getIntrospection()->queryAdapter(cppu::UnoType<XUnoTunnel>::get()));
1713 if( that )
1714 return that->getWrappedObject();
1716 if( !Py_IsInitialized() )
1717 throw RuntimeException();
1719 PyUNO* self = PyObject_New (PyUNO, &PyUNOType);
1720 if (self == nullptr)
1721 return PyRef(); // == error
1722 self->members = new PyUNOInternals;
1723 self->members->xInvocation = xInvocation;
1724 self->members->wrappedObject = targetInterface;
1725 return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
1731 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */