Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / pyuno / source / module / pyuno_struct.cxx
blobdf160b473b849b34ed47b9d509241950f0d8a046
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>
27 #include <osl/diagnose.h>
29 #include <typelib/typedescription.hxx>
31 #include <com/sun/star/beans/XMaterialHolder.hpp>
33 #include "pyuno_impl.hxx"
35 using com::sun::star::uno::Sequence;
36 using com::sun::star::uno::Reference;
37 using com::sun::star::uno::Any;
38 using com::sun::star::uno::makeAny;
39 using com::sun::star::uno::UNO_QUERY;
40 using com::sun::star::uno::TypeClass;
41 using com::sun::star::uno::RuntimeException;
42 using com::sun::star::uno::Exception;
43 using com::sun::star::lang::XSingleServiceFactory;
44 using com::sun::star::script::XInvocation2;
45 using com::sun::star::beans::XMaterialHolder;
47 namespace pyuno
50 void PyUNOStruct_del( PyObject* self )
52 PyUNO *me = reinterpret_cast<PyUNO*>( self );
54 PyThreadDetach antiguard;
55 delete me->members;
57 PyObject_Del( self );
60 PyObject *PyUNOStruct_str( PyObject *self )
62 PyUNO *me = reinterpret_cast<PyUNO*>( self );
63 OStringBuffer buf;
65 Reference<XMaterialHolder> rHolder( me->members->xInvocation,UNO_QUERY );
66 if( rHolder.is() )
68 PyThreadDetach antiguard;
69 Any a = rHolder->getMaterial();
70 OUString s = val2str( a.getValue(), a.getValueType().getTypeLibType() );
71 buf.append( OUStringToOString( s, RTL_TEXTENCODING_ASCII_US ) );
74 return PyStr_FromString( buf.getStr());
77 PyObject *PyUNOStruct_repr( PyObject *self )
79 PyUNO *me = reinterpret_cast<PyUNO*>( self );
80 PyObject *ret = nullptr;
82 if( me->members->wrappedObject.getValueType().getTypeClass()
83 == css::uno::TypeClass_EXCEPTION )
85 Reference< XMaterialHolder > rHolder(me->members->xInvocation,UNO_QUERY);
86 if( rHolder.is() )
88 Any a = rHolder->getMaterial();
89 Exception e;
90 a >>= e;
91 ret = ustring2PyUnicode(e.Message ).getAcquired();
94 else
96 ret = PyUNOStruct_str( self );
99 return ret;
102 PyObject* PyUNOStruct_dir( PyObject *self )
104 PyUNO *me = reinterpret_cast<PyUNO*>( self );
106 PyObject* member_list = nullptr;
110 member_list = PyList_New( 0 );
111 for( const auto& aMember : me->members->xInvocation->getMemberNames() )
113 // setitem steals a reference
114 PyList_Append( member_list, ustring2PyString( aMember ).getAcquired() );
117 catch( const RuntimeException &e )
119 raisePyExceptionWithAny( makeAny(e) );
122 return member_list;
125 PyObject* PyUNOStruct_getattr( PyObject* self, char* name )
127 PyUNO *me = reinterpret_cast<PyUNO*>( self );
131 Runtime runtime;
133 me = reinterpret_cast<PyUNO*>(self);
134 if (strcmp (name, "__dict__") == 0)
136 Py_INCREF (Py_TYPE(me)->tp_dict);
137 return Py_TYPE(me)->tp_dict;
139 if( strcmp( name, "__class__" ) == 0 )
141 return getClass(
142 me->members->wrappedObject.getValueType().getTypeName(), runtime ).getAcquired();
145 PyObject *pRet = PyObject_GenericGetAttr( self, PyUnicode_FromString( name ) );
146 if( pRet )
147 return pRet;
148 PyErr_Clear();
150 OUString attrName( OUString::createFromAscii( name ) );
151 if( me->members->xInvocation->hasProperty( attrName ) )
153 //Return the value of the property
154 Any anyRet;
156 PyThreadDetach antiguard;
157 anyRet = me->members->xInvocation->getValue( attrName );
159 PyRef ret = runtime.any2PyObject( anyRet );
160 Py_XINCREF( ret.get() );
161 return ret.get();
164 //or else...
165 PyErr_SetString (PyExc_AttributeError, name);
167 catch( const css::reflection::InvocationTargetException & e )
169 raisePyExceptionWithAny( e.TargetException );
171 catch( const css::beans::UnknownPropertyException & e )
173 raisePyExceptionWithAny( makeAny(e) );
175 catch( const css::lang::IllegalArgumentException &e )
177 raisePyExceptionWithAny( makeAny(e) );
179 catch( const css::script::CannotConvertException &e )
181 raisePyExceptionWithAny( makeAny(e) );
183 catch( const RuntimeException &e )
185 raisePyExceptionWithAny( makeAny(e) );
188 return nullptr;
191 int PyUNOStruct_setattr (PyObject* self, char* name, PyObject* value)
193 PyUNO* me;
195 me = reinterpret_cast<PyUNO*>(self);
198 Runtime runtime;
199 Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
201 OUString attrName( OUString::createFromAscii( name ) );
203 PyThreadDetach antiguard;
204 if (me->members->xInvocation->hasProperty (attrName))
206 me->members->xInvocation->setValue (attrName, val);
207 return 0; //Keep with Python's boolean system
211 catch( const css::reflection::InvocationTargetException & e )
213 raisePyExceptionWithAny( e.TargetException );
214 return 1;
216 catch( const css::beans::UnknownPropertyException & e )
218 raisePyExceptionWithAny( makeAny(e) );
219 return 1;
221 catch( const css::script::CannotConvertException &e )
223 raisePyExceptionWithAny( makeAny(e) );
224 return 1;
226 catch( const RuntimeException & e )
228 raisePyExceptionWithAny( makeAny( e ) );
229 return 1;
231 PyErr_SetString (PyExc_AttributeError, name);
232 return 1; //as above.
236 static PyObject* PyUNOStruct_cmp( PyObject *self, PyObject *that, int op )
238 PyObject *result;
240 if(op != Py_EQ && op != Py_NE)
242 PyErr_SetString( PyExc_TypeError, "only '==' and '!=' comparisons are defined" );
243 return nullptr;
245 if( self == that )
247 result = (op == Py_EQ ? Py_True : Py_False);
248 Py_INCREF( result );
249 return result;
253 Runtime runtime;
254 if( PyObject_IsInstance( that, getPyUnoStructClass().get() ) )
257 PyUNO *me = reinterpret_cast< PyUNO * > ( self );
258 PyUNO *other = reinterpret_cast< PyUNO * > ( that );
259 css::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
260 css::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
262 if( tcMe == tcOther )
264 if( tcMe == css::uno::TypeClass_STRUCT ||
265 tcMe == css::uno::TypeClass_EXCEPTION )
267 Reference< XMaterialHolder > xMe( me->members->xInvocation,UNO_QUERY );
268 Reference< XMaterialHolder > xOther( other->members->xInvocation,UNO_QUERY );
269 if( xMe->getMaterial() == xOther->getMaterial() )
271 result = (op == Py_EQ ? Py_True : Py_False);
272 Py_INCREF( result );
273 return result;
279 catch( const css::uno::RuntimeException & e)
281 raisePyExceptionWithAny( makeAny( e ) );
284 result = (op == Py_EQ ? Py_False : Py_True);
285 Py_INCREF(result);
286 return result;
289 static PyMethodDef PyUNOStructMethods[] =
291 {"__dir__", reinterpret_cast<PyCFunction>(PyUNOStruct_dir), METH_NOARGS, nullptr},
292 {nullptr, nullptr, 0, nullptr}
295 static PyTypeObject PyUNOStructType =
297 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
298 "pyuno.struct",
299 sizeof (PyUNO),
301 PyUNOStruct_del,
302 nullptr,
303 PyUNOStruct_getattr,
304 PyUNOStruct_setattr,
305 /* this type does not exist in Python 3: (cmpfunc) */ nullptr,
306 PyUNOStruct_repr,
307 nullptr,
308 nullptr,
309 nullptr,
310 nullptr,
311 nullptr,
312 PyUNOStruct_str,
313 nullptr,
314 nullptr,
315 nullptr,
316 Py_TPFLAGS_HAVE_RICHCOMPARE,
317 nullptr,
318 nullptr,
319 nullptr,
320 PyUNOStruct_cmp,
322 nullptr,
323 nullptr,
324 PyUNOStructMethods,
325 nullptr,
326 nullptr,
327 nullptr,
328 nullptr,
329 nullptr,
330 nullptr,
332 nullptr,
333 nullptr,
334 nullptr,
335 nullptr,
336 nullptr,
337 nullptr,
338 nullptr,
339 nullptr,
340 nullptr,
341 nullptr,
342 nullptr
343 #if PY_VERSION_HEX >= 0x02060000
345 #endif
346 #if PY_VERSION_HEX >= 0x03040000
347 , nullptr
348 #endif
351 int PyUNOStruct_initType()
353 return PyType_Ready( &PyUNOStructType );
356 PyRef getPyUnoStructClass()
358 return PyRef( reinterpret_cast< PyObject * > ( &PyUNOStructType ) );
361 PyRef PyUNOStruct_new (
362 const Any &targetInterface,
363 const Reference<XSingleServiceFactory> &ssf )
365 Reference<XInvocation2> xInvocation;
368 PyThreadDetach antiguard;
369 xInvocation.set(
370 ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), UNO_QUERY );
371 OSL_ASSERT( xInvocation.is() );
372 if( !xInvocation.is() )
373 throw RuntimeException("XInvocation2 not implemented, cannot interact with object");
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: */