Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / pyuno / source / module / pyuno_struct.cxx
blob50b74126bee93cddc949333af671f7ace991d61f
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 <rtl/strbuf.hxx>
24 #include <com/sun/star/beans/UnknownPropertyException.hpp>
25 #include <com/sun/star/beans/XMaterialHolder.hpp>
26 #include <com/sun/star/script/CannotConvertException.hpp>
27 #include <com/sun/star/script/XInvocation2.hpp>
28 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
30 #include "pyuno_impl.hxx"
32 using com::sun::star::uno::Sequence;
33 using com::sun::star::uno::Reference;
34 using com::sun::star::uno::Any;
35 using com::sun::star::uno::makeAny;
36 using com::sun::star::uno::UNO_QUERY;
37 using com::sun::star::uno::TypeClass;
38 using com::sun::star::uno::RuntimeException;
39 using com::sun::star::uno::Exception;
40 using com::sun::star::lang::XSingleServiceFactory;
41 using com::sun::star::script::XInvocation2;
42 using com::sun::star::beans::XMaterialHolder;
44 namespace pyuno
47 static void PyUNOStruct_del( PyObject* self )
49 PyUNO *me = reinterpret_cast<PyUNO*>( self );
51 PyThreadDetach antiguard;
52 delete me->members;
54 PyObject_Del( self );
57 static PyObject *PyUNOStruct_str( PyObject *self )
59 PyUNO *me = reinterpret_cast<PyUNO*>( self );
60 OString buf;
62 Reference<XMaterialHolder> rHolder( me->members->xInvocation,UNO_QUERY );
63 if( rHolder.is() )
65 PyThreadDetach antiguard;
66 Any a = rHolder->getMaterial();
67 OUString s = val2str( a.getValue(), a.getValueType().getTypeLibType() );
68 buf = OUStringToOString( s, RTL_TEXTENCODING_ASCII_US );
71 return PyStr_FromString( buf.getStr());
74 static PyObject *PyUNOStruct_repr( PyObject *self )
76 PyUNO *me = reinterpret_cast<PyUNO*>( self );
77 PyObject *ret = nullptr;
79 if( me->members->wrappedObject.getValueType().getTypeClass()
80 == css::uno::TypeClass_EXCEPTION )
82 Reference< XMaterialHolder > rHolder(me->members->xInvocation,UNO_QUERY);
83 if( rHolder.is() )
85 Any a = rHolder->getMaterial();
86 Exception e;
87 a >>= e;
88 ret = ustring2PyUnicode(e.Message ).getAcquired();
91 else
93 ret = PyUNOStruct_str( self );
96 return ret;
99 static PyObject* PyUNOStruct_dir( PyObject *self )
101 PyUNO *me = reinterpret_cast<PyUNO*>( self );
103 PyObject* member_list = nullptr;
107 member_list = PyList_New( 0 );
108 const css::uno::Sequence<OUString> aMemberNames = me->members->xInvocation->getMemberNames();
109 for( const auto& aMember : aMemberNames )
111 // setitem steals a reference
112 PyList_Append( member_list, ustring2PyString( aMember ).getAcquired() );
115 catch( const RuntimeException &e )
117 raisePyExceptionWithAny( makeAny(e) );
120 return member_list;
123 static PyObject* PyUNOStruct_getattr( PyObject* self, char* name )
125 PyUNO *me = reinterpret_cast<PyUNO*>( self );
129 Runtime runtime;
131 me = reinterpret_cast<PyUNO*>(self);
132 if (strcmp (name, "__dict__") == 0)
134 Py_INCREF (Py_TYPE(me)->tp_dict);
135 return Py_TYPE(me)->tp_dict;
137 if( strcmp( name, "__class__" ) == 0 )
139 return getClass(
140 me->members->wrappedObject.getValueType().getTypeName(), runtime ).getAcquired();
143 PyObject *pRet = PyObject_GenericGetAttr( self, PyUnicode_FromString( name ) );
144 if( pRet )
145 return pRet;
146 PyErr_Clear();
148 OUString attrName( OUString::createFromAscii( name ) );
149 if( me->members->xInvocation->hasProperty( attrName ) )
151 //Return the value of the property
152 Any anyRet;
154 PyThreadDetach antiguard;
155 anyRet = me->members->xInvocation->getValue( attrName );
157 PyRef ret = runtime.any2PyObject( anyRet );
158 Py_XINCREF( ret.get() );
159 return ret.get();
162 //or else...
163 PyErr_SetString (PyExc_AttributeError, name);
165 catch( const css::reflection::InvocationTargetException & e )
167 raisePyExceptionWithAny( e.TargetException );
169 catch( const css::beans::UnknownPropertyException & e )
171 raisePyExceptionWithAny( makeAny(e) );
173 catch( const css::lang::IllegalArgumentException &e )
175 raisePyExceptionWithAny( makeAny(e) );
177 catch( const css::script::CannotConvertException &e )
179 raisePyExceptionWithAny( makeAny(e) );
181 catch( const RuntimeException &e )
183 raisePyExceptionWithAny( makeAny(e) );
186 return nullptr;
189 static int PyUNOStruct_setattr (PyObject* self, char* name, PyObject* value)
191 PyUNO* me;
193 me = reinterpret_cast<PyUNO*>(self);
196 Runtime runtime;
197 Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
199 OUString attrName( OUString::createFromAscii( name ) );
201 PyThreadDetach antiguard;
202 if (me->members->xInvocation->hasProperty (attrName))
204 me->members->xInvocation->setValue (attrName, val);
205 return 0; //Keep with Python's boolean system
209 catch( const css::reflection::InvocationTargetException & e )
211 raisePyExceptionWithAny( e.TargetException );
212 return 1;
214 catch( const css::beans::UnknownPropertyException & e )
216 raisePyExceptionWithAny( makeAny(e) );
217 return 1;
219 catch( const css::script::CannotConvertException &e )
221 raisePyExceptionWithAny( makeAny(e) );
222 return 1;
224 catch( const RuntimeException & e )
226 raisePyExceptionWithAny( makeAny( e ) );
227 return 1;
229 PyErr_SetString (PyExc_AttributeError, name);
230 return 1; //as above.
234 static PyObject* PyUNOStruct_cmp( PyObject *self, PyObject *that, int op )
236 PyObject *result;
238 if(op != Py_EQ && op != Py_NE)
240 PyErr_SetString( PyExc_TypeError, "only '==' and '!=' comparisons are defined" );
241 return nullptr;
243 if( self == that )
245 result = (op == Py_EQ ? Py_True : Py_False);
246 Py_INCREF( result );
247 return result;
251 Runtime runtime;
252 if( PyObject_IsInstance( that, getPyUnoStructClass().get() ) )
255 PyUNO *me = reinterpret_cast< PyUNO * > ( self );
256 PyUNO *other = reinterpret_cast< PyUNO * > ( that );
257 css::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
258 css::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
260 if( tcMe == tcOther )
262 if( tcMe == css::uno::TypeClass_STRUCT ||
263 tcMe == css::uno::TypeClass_EXCEPTION )
265 Reference< XMaterialHolder > xMe( me->members->xInvocation,UNO_QUERY );
266 Reference< XMaterialHolder > xOther( other->members->xInvocation,UNO_QUERY );
267 if( xMe->getMaterial() == xOther->getMaterial() )
269 result = (op == Py_EQ ? Py_True : Py_False);
270 Py_INCREF( result );
271 return result;
277 catch( const css::uno::RuntimeException & e)
279 raisePyExceptionWithAny( makeAny( e ) );
282 result = (op == Py_EQ ? Py_False : Py_True);
283 Py_INCREF(result);
284 return result;
287 static PyMethodDef PyUNOStructMethods[] =
289 {"__dir__", reinterpret_cast<PyCFunction>(PyUNOStruct_dir), METH_NOARGS, nullptr},
290 {nullptr, nullptr, 0, nullptr}
293 static PyTypeObject PyUNOStructType =
295 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
296 "pyuno.struct",
297 sizeof (PyUNO),
299 PyUNOStruct_del,
300 #if PY_VERSION_HEX >= 0x03080000
301 0, // Py_ssize_t tp_vectorcall_offset
302 #else
303 nullptr, // printfunc tp_print
304 #endif
305 PyUNOStruct_getattr,
306 PyUNOStruct_setattr,
307 /* this type does not exist in Python 3: (cmpfunc) */ nullptr,
308 PyUNOStruct_repr,
309 nullptr,
310 nullptr,
311 nullptr,
312 nullptr,
313 nullptr,
314 PyUNOStruct_str,
315 nullptr,
316 nullptr,
317 nullptr,
318 Py_TPFLAGS_HAVE_RICHCOMPARE,
319 nullptr,
320 nullptr,
321 nullptr,
322 PyUNOStruct_cmp,
324 nullptr,
325 nullptr,
326 PyUNOStructMethods,
327 nullptr,
328 nullptr,
329 nullptr,
330 nullptr,
331 nullptr,
332 nullptr,
334 nullptr,
335 nullptr,
336 nullptr,
337 nullptr,
338 nullptr,
339 nullptr,
340 nullptr,
341 nullptr,
342 nullptr,
343 nullptr,
344 nullptr
346 #if PY_VERSION_HEX >= 0x03040000
347 , nullptr
348 #if PY_VERSION_HEX >= 0x03080000
349 , nullptr // vectorcallfunc tp_vectorcall
350 #endif
351 #endif
354 int PyUNOStruct_initType()
356 return PyType_Ready( &PyUNOStructType );
359 PyRef getPyUnoStructClass()
361 return PyRef( reinterpret_cast< PyObject * > ( &PyUNOStructType ) );
364 PyRef PyUNOStruct_new (
365 const Any &targetInterface,
366 const Reference<XSingleServiceFactory> &ssf )
368 Reference<XInvocation2> xInvocation;
371 PyThreadDetach antiguard;
372 xInvocation.set(
373 ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), css::uno::UNO_QUERY_THROW );
375 if( !Py_IsInitialized() )
376 throw RuntimeException();
378 PyUNO* self = PyObject_New (PyUNO, &PyUNOStructType);
379 if (self == nullptr)
380 return PyRef(); // == error
381 self->members = new PyUNOInternals;
382 self->members->xInvocation = xInvocation;
383 self->members->wrappedObject = targetInterface;
384 return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */