2011-08-20 17:14:24 +02:00
|
|
|
/* -*- Mode: C++; eval:(c-set-style "bsd"); tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-07-02 14:56:57 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
2006-06-20 04:04:22 +00:00
|
|
|
|
2013-08-16 11:08:32 +03:00
|
|
|
#include <config_features.h>
|
|
|
|
#include <config_folders.h>
|
|
|
|
|
2006-06-20 04:04:22 +00:00
|
|
|
#include "pyuno_impl.hxx"
|
|
|
|
|
2016-06-21 12:46:45 +02:00
|
|
|
#include <o3tl/any.hxx>
|
2014-11-14 22:52:35 +01:00
|
|
|
#include <osl/diagnose.h>
|
2003-03-23 11:12:59 +00:00
|
|
|
#include <osl/thread.h>
|
2006-03-22 09:51:22 +00:00
|
|
|
#include <osl/module.h>
|
|
|
|
#include <osl/process.h>
|
2003-03-23 11:12:59 +00:00
|
|
|
#include <rtl/strbuf.hxx>
|
|
|
|
#include <rtl/ustrbuf.hxx>
|
2006-03-22 09:51:22 +00:00
|
|
|
#include <rtl/bootstrap.hxx>
|
2003-03-23 11:12:59 +00:00
|
|
|
|
Make PyUNO provide more Pythonic behaviour
- Simplifies working with UNO objects by giving the behaviour of
Python lists, dicts and iterators to objects which implement UNO
container interfaces
- Applies a custom behaviour to allow objects which implement
com::sun::star::table::XCellRange to yield cells and cell ranges by
subscript
- When UNO container objects are addressed in the new style,
eliminates the requirement to manually construct Any objects for
contained elements which are typed sequences
- Allows lists and iterators to be passed wherever a UNO method
accepts a sequence
- Relaxes the requirements for initialising UNO structs to allow
some members to be skipped when all initialisers are passed by name
1. Collection interfaces
========================
Objects which implement core UNO collection interfaces are made to
behave in a way that is more natural for Python code.
com::sun::star::container::XIndexAccess
com::sun::star::container::XIndexReplace
com::sun::star::container::XIndexContainer
- Objects provide Python list access semantics
num = len(obj) # Number of elements
val = obj[0] # Access by index
val1,val2 = obj[2:4] # Access by slice
val1,val2 = obj[0:3:2] # Access by extended slice
if val in obj: ... # Test value presence
for val in obj: ... # Implicit iterator (values)
itr = iter(obj) # Named iterator (values)
obj[0] = val # Replace by index
obj[2:4] = val1,val2 # Replace by slice
obj[0:3:2] = val1,val2 # Replace by extended slice
obj[2:3] = val1,val2 # Insert/replace by slice
obj[2:2] = (val,) # Insert by slice
obj[2:4] = (val,) # Replace/delete by slice
obj[2:3] = () # Delete by slice (implicit)
del obj[0] # Delete by index
del obj[2:4] # Delete by slice
com::sun::star::container::XNameAccess
com::sun::star::container::XNameReplace
com::sun::star::container::XNameContainer
- Objects provide Python dict access semantics
num = len(obj) # Number of keys
val = obj[key] # Access by key
if key in obj: ... # Test key presence
for key in obj: ... # Implicit iterator (keys)
itr = iter(obj) # Named iterator (keys)
obj[key] = val # Replace by key
obj[key] = val # Insert by key
del obj[key] # Delete by key
com::sun::star::container::XEnumerationAccess
- Objects provide Python iterable semantics
for val in obj: ... # Implicit iterator
itr = iter(obj) # Named iterator
com::sun::star::container::XEnumeration
- Objects provide Python iterator semantics
for val in itr: ... # Iteration of named iterator
if val in itr: ... # Test value presence
Objects which implement both XIndex* and XName* are supported, and
respond to both integer and string keys. However, iterating over
such an object will return the keys (like a Python dict) rather than
the values (like a Python list).
2. Cell ranges
==============
A custom behaviour is applied to objects which implement
com::sun::star::table::XCellRange to allow their cells and cell
ranges to be addressed by subscript, in the style of a Python list
or dict (read-only). This is applicable to Calc spreadsheet sheets,
Writer text tables and cell ranges created upon these.
cell = cellrange[0,0] # Access cell by indices
rng = cellrange[0,1:2] # Access cell range by index,slice
rng = cellrange[1:2,0] # Access cell range by slice,index
rng = cellrange[0:1,2:3] # Access cell range by slices
rng = cellrange['A1:B2'] # Access cell range by descriptor
rng = cellrange['Name'] # Access cell range by name
Note that the indices used are in Python/C order, and differ from
the arguments to methods provided by XCellRange.
- The statement cellrange[r,c], which returns the cell from row r
and column c, is equivalent to calling
XCellRange::getCellByPosition(c,r)
- The statement cellrange[t:b,l:r], which returns a cell range
covering rows t to b(non-inclusive) and columns l to r(non-
inclusive), is equivalent to calling
XCellRange::getCellRangeByPosition(l,t,r-1,b-1).
In contrast to the handling of objects implementing XIndex*,
extended slice syntax is not supported. Negative indices (from-end
addresses) are supported only for objects which also implement
com::sun::star::table::XColumnRowRange (currently Calc spreadsheet
sheets and cell ranges created upon these). For such objects, the
following syntax is also available:
rng = cellrange[0] # Access cell range by row index
rng = cellrange[0,:] # Access cell range by row index
rng = cellrange[:,0] # Access cell range by column index
3. Elimination of explicit Any
==============================
PyUNO has not previously been able to cope with certain method
arguments which are typed as Any but require a sequence of specific
type to be passed. This is a particular issue for container
interfaces such as XIndexContainer and XNameContainer.
The existing solution to dealing with such methods is to use a
special method to pass an explicitly typed Any, giving code such as:
index = doc.createInstance("com.sun.star.text.ContentIndex");
...
uno.invoke( index.LevelParagraphStyles , "replaceByIndex",
(0, uno.Any("[]string", ('Caption',))) )
The new Pythonic container access is able to correctly infer the
expected type of the sequences required by these arguments. In the
new style, the above call to .replaceByIndex() can instead be
written:
index.LevelParagraphStyles[0] = ('Caption',)
4. List and iterator arguments
==============================
Wherever a UNO API expects a sequence, a Python list or iterator can
now be passed. This enables the use of list comprehensions and
generator expressions for method calls and property assignments.
Example:
tbl = doc.createInstance('com.sun.star.text.TextTable')
tbl.initialize(10,10)
# ... insert table ...
# Assign numbers 0..99 to the cells using a generator expression
tbl.Data = ((y for y in range(10*x,10*x + 10)) for x in range(10))
5. Tolerant struct initialisation
=================================
Previously, a UNO struct could be created fully uninitialised, or by
passing a combination of positional and/or named arguments to its
constructor. However, if any arguments were passed, all members were
required to be initialised or an exception was thrown.
This requirement is relaxed such that when all arguments passed to a
struct constructor are by name, some may be omitted. The existing
requirement that all members must be explicitly initialised when
some constructor arguments are unnamed (positional) is not affected.
Example:
from com.sun.star.beans import PropertyValue
prop = PropertyValue(Name='foo', Value='bar')
Change-Id: Id29bff10a18099b1a00af1abee1a6c1bc58b3978
Reviewed-on: https://gerrit.libreoffice.org/16272
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Matthew Francis <mjay.francis@gmail.com>
2015-06-01 18:34:04 +08:00
|
|
|
#include <list>
|
2003-03-23 11:12:59 +00:00
|
|
|
#include <typelib/typedescription.hxx>
|
|
|
|
|
2012-11-16 13:20:50 +01:00
|
|
|
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
|
2003-03-23 11:12:59 +00:00
|
|
|
#include <com/sun/star/beans/XMaterialHolder.hpp>
|
2014-03-07 10:31:07 +01:00
|
|
|
#include <com/sun/star/beans/theIntrospection.hpp>
|
2012-08-21 08:07:58 +02:00
|
|
|
#include <com/sun/star/script/Converter.hpp>
|
2013-05-14 09:52:58 +02:00
|
|
|
#include <com/sun/star/script/InvocationAdapterFactory.hpp>
|
2012-09-04 16:12:17 +02:00
|
|
|
#include <com/sun/star/reflection/theCoreReflection.hpp>
|
2015-11-19 09:14:59 +02:00
|
|
|
#include <comphelper/sequence.hxx>
|
2003-03-23 11:12:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
using com::sun::star::uno::Reference;
|
|
|
|
using com::sun::star::uno::XInterface;
|
|
|
|
using com::sun::star::uno::Any;
|
|
|
|
using com::sun::star::uno::TypeDescription;
|
|
|
|
using com::sun::star::uno::Sequence;
|
|
|
|
using com::sun::star::uno::Type;
|
|
|
|
using com::sun::star::uno::UNO_QUERY;
|
2011-08-20 17:14:24 +02:00
|
|
|
using com::sun::star::uno::Exception;
|
2003-03-23 11:12:59 +00:00
|
|
|
using com::sun::star::uno::RuntimeException;
|
|
|
|
using com::sun::star::uno::XComponentContext;
|
2012-11-16 13:20:50 +01:00
|
|
|
using com::sun::star::lang::WrappedTargetRuntimeException;
|
2003-03-23 11:12:59 +00:00
|
|
|
using com::sun::star::lang::XSingleServiceFactory;
|
|
|
|
using com::sun::star::lang::XUnoTunnel;
|
2012-09-04 16:12:17 +02:00
|
|
|
using com::sun::star::reflection::theCoreReflection;
|
2012-11-16 13:20:50 +01:00
|
|
|
using com::sun::star::reflection::InvocationTargetException;
|
2012-08-21 08:07:58 +02:00
|
|
|
using com::sun::star::script::Converter;
|
2003-03-23 11:12:59 +00:00
|
|
|
using com::sun::star::script::XTypeConverter;
|
2004-02-02 18:30:44 +00:00
|
|
|
using com::sun::star::script::XInvocation;
|
2003-03-23 11:12:59 +00:00
|
|
|
using com::sun::star::beans::XMaterialHolder;
|
2014-03-07 10:31:07 +01:00
|
|
|
using com::sun::star::beans::theIntrospection;
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2011-02-03 21:35:13 -08:00
|
|
|
#include <vector>
|
|
|
|
|
2003-03-23 11:12:59 +00:00
|
|
|
namespace pyuno
|
|
|
|
{
|
|
|
|
|
|
|
|
static PyTypeObject RuntimeImpl_Type =
|
|
|
|
{
|
2011-05-07 20:35:03 +01:00
|
|
|
PyVarObject_HEAD_INIT (&PyType_Type, 0)
|
2011-08-20 17:33:37 +02:00
|
|
|
"pyuno_runtime",
|
2003-03-23 11:12:59 +00:00
|
|
|
sizeof (RuntimeImpl),
|
|
|
|
0,
|
2015-06-08 16:27:02 +02:00
|
|
|
RuntimeImpl::del,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2015-11-10 10:20:48 +01:00
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2006-06-20 04:04:22 +00:00
|
|
|
0,
|
2015-11-10 10:20:48 +01:00
|
|
|
nullptr,
|
2015-06-08 16:27:02 +02:00
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2006-06-20 04:04:22 +00:00
|
|
|
0,
|
2015-06-08 16:27:02 +02:00
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2015-11-10 10:20:48 +01:00
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2015-06-08 16:27:02 +02:00
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2006-06-20 04:04:22 +00:00
|
|
|
0,
|
2015-06-08 16:27:02 +02:00
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2015-11-10 10:20:48 +01:00
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
2015-06-08 16:27:02 +02:00
|
|
|
nullptr
|
2009-03-14 17:15:26 +00:00
|
|
|
#if PY_VERSION_HEX >= 0x02060000
|
|
|
|
, 0
|
|
|
|
#endif
|
2014-05-18 18:10:58 +02:00
|
|
|
#if PY_VERSION_HEX >= 0x03040000
|
2015-11-10 10:20:48 +01:00
|
|
|
, nullptr
|
2014-05-18 18:10:58 +02:00
|
|
|
#endif
|
2003-03-23 11:12:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------
|
|
|
|
Runtime implementation
|
|
|
|
-----------------------------------------------------------------------*/
|
|
|
|
static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
|
2015-10-23 14:59:15 +02:00
|
|
|
throw ( css::uno::RuntimeException )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
PyThreadState * state = PyThreadState_Get();
|
|
|
|
if( ! state )
|
|
|
|
{
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
|
2014-01-28 09:22:26 +00:00
|
|
|
PyObject* pModule = PyImport_AddModule("__main__");
|
|
|
|
|
|
|
|
if (!pModule)
|
|
|
|
{
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException("can't import __main__ module");
|
2014-01-28 09:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
globalDict = PyRef( PyModule_GetDict(pModule));
|
2003-03-23 11:12:59 +00:00
|
|
|
|
|
|
|
if( ! globalDict.is() ) // FATAL !
|
|
|
|
{
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException("can't find __main__ module");
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyRef importUnoModule( ) throw ( RuntimeException )
|
|
|
|
{
|
|
|
|
// import the uno module
|
2014-06-03 17:08:06 +01:00
|
|
|
PyRef module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE, NOT_NULL );
|
2003-03-23 11:12:59 +00:00
|
|
|
if( PyErr_Occurred() )
|
|
|
|
{
|
|
|
|
PyRef excType, excValue, excTraceback;
|
2015-01-17 19:00:24 +01:00
|
|
|
PyErr_Fetch( reinterpret_cast<PyObject **>(&excType), reinterpret_cast<PyObject**>(&excValue), reinterpret_cast<PyObject**>(&excTraceback));
|
2011-08-20 17:44:53 +02:00
|
|
|
// As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>",
|
|
|
|
// but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace
|
|
|
|
// Who knows, a future Python might print something better.
|
|
|
|
PyRef str( PyObject_Str( excTraceback.get() ), SAL_NO_ACQUIRE );
|
2003-03-23 11:12:59 +00:00
|
|
|
|
|
|
|
OUStringBuffer buf;
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( "python object raised an unknown exception (" );
|
2003-03-23 11:12:59 +00:00
|
|
|
PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.appendAscii( PyStr_AsString( valueRep.get())).append( ", traceback follows\n" );
|
2012-11-25 15:59:18 +01:00
|
|
|
buf.appendAscii( PyStr_AsString( str.get() ) );
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( ")" );
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( buf.makeStringAndClear() );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
PyRef dict( PyModule_GetDict( module.get() ) );
|
|
|
|
return dict;
|
|
|
|
}
|
|
|
|
|
2006-03-22 09:51:22 +00:00
|
|
|
static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
|
|
|
|
{
|
|
|
|
*pLevel = LogLevel::NONE;
|
2015-11-10 10:20:48 +01:00
|
|
|
*ppFile = nullptr;
|
2006-03-22 09:51:22 +00:00
|
|
|
OUString fileName;
|
2006-06-20 04:04:22 +00:00
|
|
|
osl_getModuleURLFromFunctionAddress(
|
|
|
|
reinterpret_cast< oslGenericFunction >(readLoggingConfig),
|
2015-01-17 19:00:24 +01:00
|
|
|
&fileName.pData );
|
2013-11-04 14:00:40 +02:00
|
|
|
fileName = fileName.copy( fileName.lastIndexOf( '/' )+1 );
|
Make the "Mac-like" or "canonical" app bundle structure always used on OS X
In other words, only executable files go in the MacOS folder. Dynamic
libraries and bundled frameworks (i.e., LibreOfficePython), and
nothing else, go in the Frameworks folder, and all other files go in
the Resources folder.
Especially, note that Java class files and rc (.ini) files also go in
Resources.
Such an app bundle structure is what Apple strongly suggests one
should use, and it has been hinted that future versions of code
signing and/or Gatekeeper will require such a structure.
There is still some ugliness thanks to traces of the historical
separation of URE from "the office". Like there are two separate
"unorc" files, one for URE, one for the LibreOffice application. IMHO,
this should be cleaned up, but is probably controversial.
(Eek! I now see there are actually *three* unorc files in the app
bundle. Not intentional. Need to fix that later.)
Change-Id: Idcf235038deb5b8e1d061734993e9f31869b7606
2014-09-09 10:44:56 +03:00
|
|
|
#ifdef MACOSX
|
2013-08-16 11:08:32 +03:00
|
|
|
fileName += "../" LIBO_ETC_FOLDER "/";
|
|
|
|
#endif
|
2013-11-04 14:00:40 +02:00
|
|
|
fileName += SAL_CONFIGFILE("pyuno" );
|
2006-03-22 09:51:22 +00:00
|
|
|
rtl::Bootstrap bootstrapHandle( fileName );
|
|
|
|
|
|
|
|
OUString str;
|
2013-02-01 09:33:19 +01:00
|
|
|
if( bootstrapHandle.getFrom( "PYUNO_LOGLEVEL", str ) )
|
2006-03-22 09:51:22 +00:00
|
|
|
{
|
2012-04-06 14:28:18 +02:00
|
|
|
if ( str == "NONE" )
|
2006-03-22 09:51:22 +00:00
|
|
|
*pLevel = LogLevel::NONE;
|
2012-04-06 14:28:18 +02:00
|
|
|
else if ( str == "CALL" )
|
2006-03-22 09:51:22 +00:00
|
|
|
*pLevel = LogLevel::CALL;
|
2012-04-06 14:28:18 +02:00
|
|
|
else if ( str == "ARGS" )
|
2006-03-22 09:51:22 +00:00
|
|
|
*pLevel = LogLevel::ARGS;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf( stderr, "unknown loglevel %s\n",
|
|
|
|
OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( *pLevel > LogLevel::NONE )
|
|
|
|
{
|
|
|
|
*ppFile = stdout;
|
2013-02-01 09:33:19 +01:00
|
|
|
if( bootstrapHandle.getFrom( "PYUNO_LOGTARGET", str ) )
|
2006-03-22 09:51:22 +00:00
|
|
|
{
|
2012-04-06 14:28:18 +02:00
|
|
|
if ( str == "stdout" )
|
2006-03-22 09:51:22 +00:00
|
|
|
*ppFile = stdout;
|
2012-04-06 14:28:18 +02:00
|
|
|
else if ( str == "stderr" )
|
2006-03-22 09:51:22 +00:00
|
|
|
*ppFile = stderr;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
oslProcessInfo data;
|
|
|
|
data.Size = sizeof( data );
|
|
|
|
osl_getProcessInfo(
|
2015-11-10 10:20:48 +01:00
|
|
|
nullptr , osl_Process_IDENTIFIER , &data );
|
2006-03-22 09:51:22 +00:00
|
|
|
osl_getSystemPathFromFileURL( str.pData, &str.pData);
|
|
|
|
OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
|
|
|
|
o += ".";
|
2013-08-21 15:07:31 +02:00
|
|
|
o += OString::number( data.Ident );
|
2006-03-22 09:51:22 +00:00
|
|
|
|
|
|
|
*ppFile = fopen( o.getStr() , "w" );
|
|
|
|
if ( *ppFile )
|
|
|
|
{
|
|
|
|
// do not buffer (useful if e.g. analyzing a crash)
|
2015-11-10 10:20:48 +01:00
|
|
|
setvbuf( *ppFile, nullptr, _IONBF, 0 );
|
2006-03-22 09:51:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf( stderr, "couldn't create file %s\n",
|
|
|
|
OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-23 11:12:59 +00:00
|
|
|
/*-------------------------------------------------------------------
|
|
|
|
RuntimeImpl implementations
|
|
|
|
*-------------------------------------------------------------------*/
|
|
|
|
PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
|
2015-10-23 14:59:15 +02:00
|
|
|
throw( css::uno::RuntimeException, std::exception )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
2006-11-14 17:21:46 +00:00
|
|
|
RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
|
2003-03-23 11:12:59 +00:00
|
|
|
if( ! me )
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
|
2015-11-10 10:20:48 +01:00
|
|
|
me->cargo = nullptr;
|
2006-11-14 17:21:46 +00:00
|
|
|
// must use a different struct here, as the PyObject_New
|
2003-03-23 11:12:59 +00:00
|
|
|
// makes C++ unusable
|
|
|
|
RuntimeCargo *c = new RuntimeCargo();
|
2006-03-22 09:51:22 +00:00
|
|
|
readLoggingConfig( &(c->logLevel) , &(c->logFile) );
|
|
|
|
log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
|
|
|
|
|
2014-01-28 20:00:57 +01:00
|
|
|
c->valid = true;
|
2003-03-23 11:12:59 +00:00
|
|
|
c->xContext = ctx;
|
|
|
|
c->xInvocation = Reference< XSingleServiceFactory > (
|
|
|
|
ctx->getServiceManager()->createInstanceWithContext(
|
2015-10-30 08:40:11 +02:00
|
|
|
"com.sun.star.script.Invocation",
|
2003-03-23 11:12:59 +00:00
|
|
|
ctx ),
|
|
|
|
UNO_QUERY );
|
|
|
|
if( ! c->xInvocation.is() )
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( "pyuno: couldn't instantiate invocation service" );
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2012-08-21 08:07:58 +02:00
|
|
|
c->xTypeConverter = Converter::create(ctx);
|
2003-03-23 11:12:59 +00:00
|
|
|
if( ! c->xTypeConverter.is() )
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( "pyuno: couldn't instantiate typeconverter service" );
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2012-09-04 16:12:17 +02:00
|
|
|
c->xCoreReflection = theCoreReflection::get(ctx);
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2013-05-14 09:52:58 +02:00
|
|
|
c->xAdapterFactory = css::script::InvocationAdapterFactory::create(ctx);
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2014-03-07 10:31:07 +01:00
|
|
|
c->xIntrospection = theIntrospection::get(ctx);
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2013-06-29 21:24:12 +02:00
|
|
|
Any a = ctx->getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
|
2003-03-23 11:12:59 +00:00
|
|
|
a >>= c->xTdMgr;
|
|
|
|
if( ! c->xTdMgr.is() )
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
|
2003-03-23 11:12:59 +00:00
|
|
|
|
|
|
|
me->cargo =c;
|
|
|
|
return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
|
|
|
|
}
|
|
|
|
|
|
|
|
void stRuntimeImpl::del(PyObject* self)
|
|
|
|
{
|
|
|
|
RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
|
2006-03-22 09:51:22 +00:00
|
|
|
if( me->cargo->logFile )
|
|
|
|
fclose( me->cargo->logFile );
|
2003-03-23 11:12:59 +00:00
|
|
|
delete me->cargo;
|
2006-11-14 17:21:46 +00:00
|
|
|
PyObject_Del (self);
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Runtime::initialize( const Reference< XComponentContext > & ctx )
|
2015-07-02 08:40:23 +01:00
|
|
|
throw ( RuntimeException, std::exception )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
PyRef globalDict, runtime;
|
|
|
|
getRuntimeImpl( globalDict , runtime );
|
|
|
|
RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
|
|
|
|
|
|
|
|
if( runtime.is() && impl->cargo->valid )
|
|
|
|
{
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException("pyuno runtime has already been initialized before" );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
PyRef keep( RuntimeImpl::create( ctx ) );
|
|
|
|
PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
|
|
|
|
Py_XINCREF( keep.get() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Runtime::isInitialized() throw ( RuntimeException )
|
|
|
|
{
|
|
|
|
PyRef globalDict, runtime;
|
|
|
|
getRuntimeImpl( globalDict , runtime );
|
|
|
|
RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
|
|
|
|
return runtime.is() && impl->cargo->valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
Runtime::Runtime() throw( RuntimeException )
|
2015-11-10 10:20:48 +01:00
|
|
|
: impl( nullptr )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
PyRef globalDict, runtime;
|
|
|
|
getRuntimeImpl( globalDict , runtime );
|
|
|
|
if( ! runtime.is() )
|
|
|
|
{
|
|
|
|
throw RuntimeException(
|
2014-05-23 12:03:21 +02:00
|
|
|
"pyuno runtime is not initialized, "
|
|
|
|
"(the pyuno.bootstrap needs to be called before using any uno classes)" );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
|
|
|
|
Py_XINCREF( runtime.get() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Runtime::Runtime( const Runtime & r )
|
|
|
|
{
|
|
|
|
impl = r.impl;
|
|
|
|
Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
|
|
|
|
}
|
|
|
|
|
|
|
|
Runtime::~Runtime()
|
|
|
|
{
|
|
|
|
Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
|
|
|
|
}
|
|
|
|
|
|
|
|
Runtime & Runtime::operator = ( const Runtime & r )
|
|
|
|
{
|
|
|
|
PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
|
|
|
|
Py_XINCREF( temp.get() );
|
|
|
|
Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
|
|
|
|
impl = r.impl;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyRef Runtime::any2PyObject (const Any &a ) const
|
2015-10-23 14:59:15 +02:00
|
|
|
throw ( css::script::CannotConvertException,
|
|
|
|
css::lang::IllegalArgumentException,
|
2003-03-23 11:12:59 +00:00
|
|
|
RuntimeException)
|
|
|
|
{
|
|
|
|
if( ! impl->cargo->valid )
|
|
|
|
{
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (a.getValueTypeClass ())
|
|
|
|
{
|
|
|
|
case typelib_TypeClass_VOID:
|
|
|
|
{
|
|
|
|
Py_INCREF (Py_None);
|
|
|
|
return PyRef(Py_None);
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_CHAR:
|
|
|
|
{
|
2016-06-21 12:46:45 +02:00
|
|
|
sal_Unicode c = *o3tl::forceAccess<sal_Unicode>(a);
|
2003-03-23 11:12:59 +00:00
|
|
|
return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_BOOLEAN:
|
|
|
|
{
|
2014-05-08 11:43:40 +02:00
|
|
|
bool b;
|
2006-07-19 15:42:27 +00:00
|
|
|
if ((a >>= b) && b)
|
2003-03-23 11:12:59 +00:00
|
|
|
return Py_True;
|
|
|
|
else
|
|
|
|
return Py_False;
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_BYTE:
|
|
|
|
case typelib_TypeClass_SHORT:
|
|
|
|
case typelib_TypeClass_UNSIGNED_SHORT:
|
|
|
|
case typelib_TypeClass_LONG:
|
|
|
|
{
|
2006-11-21 16:39:42 +00:00
|
|
|
sal_Int32 l = 0;
|
2003-03-23 11:12:59 +00:00
|
|
|
a >>= l;
|
2011-05-07 20:35:03 +01:00
|
|
|
return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
case typelib_TypeClass_UNSIGNED_LONG:
|
|
|
|
{
|
2010-01-23 12:35:22 +00:00
|
|
|
sal_uInt32 l = 0;
|
2003-03-23 11:12:59 +00:00
|
|
|
a >>= l;
|
|
|
|
return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_HYPER:
|
|
|
|
{
|
2010-01-23 12:35:22 +00:00
|
|
|
sal_Int64 l = 0;
|
2003-03-23 11:12:59 +00:00
|
|
|
a >>= l;
|
|
|
|
return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_UNSIGNED_HYPER:
|
|
|
|
{
|
2010-01-23 12:35:22 +00:00
|
|
|
sal_uInt64 l = 0;
|
2003-03-23 11:12:59 +00:00
|
|
|
a >>= l;
|
|
|
|
return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_FLOAT:
|
|
|
|
{
|
2010-01-23 12:35:22 +00:00
|
|
|
float f = 0.0;
|
2003-03-23 11:12:59 +00:00
|
|
|
a >>= f;
|
|
|
|
return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_DOUBLE:
|
|
|
|
{
|
2010-01-23 12:35:22 +00:00
|
|
|
double d = 0.0;
|
2003-03-23 11:12:59 +00:00
|
|
|
a >>= d;
|
|
|
|
return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_STRING:
|
|
|
|
{
|
|
|
|
OUString tmp_ostr;
|
|
|
|
a >>= tmp_ostr;
|
|
|
|
return ustring2PyUnicode( tmp_ostr );
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_TYPE:
|
|
|
|
{
|
|
|
|
Type t;
|
|
|
|
a >>= t;
|
|
|
|
OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
|
|
|
|
return PyRef(
|
|
|
|
PyUNO_Type_new (
|
2015-10-23 14:59:15 +02:00
|
|
|
o.getStr(), (css::uno::TypeClass)t.getTypeClass(), *this),
|
2003-03-23 11:12:59 +00:00
|
|
|
SAL_NO_ACQUIRE);
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_ANY:
|
|
|
|
{
|
|
|
|
//I don't think this can happen.
|
|
|
|
Py_INCREF (Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_ENUM:
|
|
|
|
{
|
2015-03-28 19:05:27 +01:00
|
|
|
sal_Int32 l = *static_cast<sal_Int32 const *>(a.getValue());
|
2003-03-23 11:12:59 +00:00
|
|
|
TypeDescription desc( a.getValueType() );
|
|
|
|
if( desc.is() )
|
|
|
|
{
|
|
|
|
desc.makeComplete();
|
|
|
|
typelib_EnumTypeDescription *pEnumDesc =
|
2015-01-17 19:00:24 +01:00
|
|
|
reinterpret_cast<typelib_EnumTypeDescription *>(desc.get());
|
2003-03-23 11:12:59 +00:00
|
|
|
for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
|
|
|
|
{
|
|
|
|
if( pEnumDesc->pEnumValues[i] == l )
|
|
|
|
{
|
|
|
|
OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US);
|
|
|
|
OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US);
|
|
|
|
return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OUStringBuffer buf;
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( "Any carries enum " );
|
2003-03-23 11:12:59 +00:00
|
|
|
buf.append( a.getValueType().getTypeName());
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( " with invalid value " ).append( l );
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( buf.makeStringAndClear() );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
case typelib_TypeClass_EXCEPTION:
|
|
|
|
case typelib_TypeClass_STRUCT:
|
|
|
|
{
|
|
|
|
PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
|
2015-07-29 15:22:54 +08:00
|
|
|
PyRef value = PyUNOStruct_new( a, getImpl()->cargo->xInvocation );
|
2014-08-07 12:37:59 +01:00
|
|
|
PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE, NOT_NULL );
|
2003-03-23 11:12:59 +00:00
|
|
|
PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
|
2003-05-24 22:31:19 +00:00
|
|
|
PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
|
2003-03-23 11:12:59 +00:00
|
|
|
if( ! ret.is() )
|
|
|
|
{
|
|
|
|
OUStringBuffer buf;
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( "Couldn't instantiate python representation of structured UNO type " );
|
2003-03-23 11:12:59 +00:00
|
|
|
buf.append( a.getValueType().getTypeName() );
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( buf.makeStringAndClear() );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 12:46:45 +02:00
|
|
|
if( auto e = o3tl::tryAccess<css::uno::Exception>(a) )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
// add the message in a standard python way !
|
2014-07-10 11:56:06 +01:00
|
|
|
PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2016-06-21 12:46:45 +02:00
|
|
|
PyRef pymsg = ustring2PyString( e->Message );
|
2003-03-23 11:12:59 +00:00
|
|
|
PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
|
|
|
|
// the exception base functions want to have an "args" tuple,
|
|
|
|
// which contains the message
|
2011-08-20 17:33:37 +02:00
|
|
|
PyObject_SetAttrString( ret.get(), "args", args.get() );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_SEQUENCE:
|
|
|
|
{
|
|
|
|
Sequence<Any> s;
|
|
|
|
|
|
|
|
Sequence< sal_Int8 > byteSequence;
|
|
|
|
if( a >>= byteSequence )
|
|
|
|
{
|
|
|
|
// byte sequence is treated in a special way because of peformance reasons
|
|
|
|
// @since 0.9.2
|
|
|
|
return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
|
|
|
|
Reference< XSingleServiceFactory > ssf = getImpl()->cargo->xInvocation;
|
2015-04-01 08:40:15 +02:00
|
|
|
tc->convertTo (a, cppu::UnoType<decltype(s)>::get()) >>= s;
|
2014-06-03 17:07:18 +01:00
|
|
|
PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE, NOT_NULL);
|
2006-09-25 12:22:58 +00:00
|
|
|
int i=0;
|
2003-03-23 11:12:59 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
for ( i = 0; i < s.getLength (); i++)
|
|
|
|
{
|
|
|
|
PyRef element;
|
|
|
|
element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
|
|
|
|
OSL_ASSERT( element.is() );
|
|
|
|
PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
|
|
|
|
}
|
|
|
|
}
|
2015-10-23 14:59:15 +02:00
|
|
|
catch( css::uno::Exception & )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
for( ; i < s.getLength() ; i ++ )
|
|
|
|
{
|
|
|
|
Py_INCREF( Py_None );
|
|
|
|
PyTuple_SetItem( tuple.get(), i, Py_None );
|
|
|
|
}
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
return tuple;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case typelib_TypeClass_INTERFACE:
|
|
|
|
{
|
2015-07-23 11:36:38 +08:00
|
|
|
Reference<XInterface> tmp_interface;
|
|
|
|
a >>= tmp_interface;
|
|
|
|
if (!tmp_interface.is ())
|
|
|
|
return Py_None;
|
2014-08-28 15:11:37 +02:00
|
|
|
|
2015-07-29 15:22:54 +08:00
|
|
|
return PyUNO_new( a, getImpl()->cargo->xInvocation );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
OUStringBuffer buf;
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( "Unknown UNO type class " );
|
2003-03-23 11:12:59 +00:00
|
|
|
buf.append( (sal_Int32 ) a.getValueTypeClass() );
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException(buf.makeStringAndClear( ) );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
|
|
|
|
{
|
|
|
|
Sequence< Type > ret;
|
|
|
|
|
2011-08-20 17:33:37 +02:00
|
|
|
PyRef method( PyObject_GetAttrString( o , "getTypes" ), SAL_NO_ACQUIRE );
|
2003-03-23 11:12:59 +00:00
|
|
|
raiseInvocationTargetExceptionWhenNeeded( r );
|
|
|
|
if( method.is() && PyCallable_Check( method.get() ) )
|
|
|
|
{
|
2015-11-10 10:20:48 +01:00
|
|
|
PyRef types( PyObject_CallObject( method.get(), nullptr ) , SAL_NO_ACQUIRE );
|
2003-03-23 11:12:59 +00:00
|
|
|
raiseInvocationTargetExceptionWhenNeeded( r );
|
|
|
|
if( types.is() && PyTuple_Check( types.get() ) )
|
|
|
|
{
|
|
|
|
int size = PyTuple_Size( types.get() );
|
2004-02-02 18:30:44 +00:00
|
|
|
|
|
|
|
// add the XUnoTunnel interface for uno object identity concept (hack)
|
|
|
|
ret.realloc( size + 1 );
|
2003-03-23 11:12:59 +00:00
|
|
|
for( int i = 0 ; i < size ; i ++ )
|
|
|
|
{
|
|
|
|
Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
|
|
|
|
a >>= ret[i];
|
|
|
|
}
|
2015-10-23 14:59:15 +02:00
|
|
|
ret[size] = cppu::UnoType<css::lang::XUnoTunnel>::get();
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-11-16 13:20:50 +01:00
|
|
|
static OUString
|
|
|
|
lcl_ExceptionMessage(PyObject *const o, OUString const*const pWrapped)
|
|
|
|
{
|
|
|
|
OUStringBuffer buf;
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append("Couldn't convert ");
|
2012-11-16 13:20:50 +01:00
|
|
|
PyRef reprString( PyObject_Str(o), SAL_NO_ACQUIRE );
|
2012-11-25 15:59:18 +01:00
|
|
|
buf.appendAscii( PyStr_AsString(reprString.get()) );
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append(" to a UNO type");
|
2012-11-16 13:20:50 +01:00
|
|
|
if (pWrapped)
|
|
|
|
{
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append("; caught exception: ");
|
2012-11-16 13:20:50 +01:00
|
|
|
buf.append(*pWrapped);
|
|
|
|
}
|
|
|
|
return buf.makeStringAndClear();
|
|
|
|
}
|
|
|
|
|
Make PyUNO provide more Pythonic behaviour
- Simplifies working with UNO objects by giving the behaviour of
Python lists, dicts and iterators to objects which implement UNO
container interfaces
- Applies a custom behaviour to allow objects which implement
com::sun::star::table::XCellRange to yield cells and cell ranges by
subscript
- When UNO container objects are addressed in the new style,
eliminates the requirement to manually construct Any objects for
contained elements which are typed sequences
- Allows lists and iterators to be passed wherever a UNO method
accepts a sequence
- Relaxes the requirements for initialising UNO structs to allow
some members to be skipped when all initialisers are passed by name
1. Collection interfaces
========================
Objects which implement core UNO collection interfaces are made to
behave in a way that is more natural for Python code.
com::sun::star::container::XIndexAccess
com::sun::star::container::XIndexReplace
com::sun::star::container::XIndexContainer
- Objects provide Python list access semantics
num = len(obj) # Number of elements
val = obj[0] # Access by index
val1,val2 = obj[2:4] # Access by slice
val1,val2 = obj[0:3:2] # Access by extended slice
if val in obj: ... # Test value presence
for val in obj: ... # Implicit iterator (values)
itr = iter(obj) # Named iterator (values)
obj[0] = val # Replace by index
obj[2:4] = val1,val2 # Replace by slice
obj[0:3:2] = val1,val2 # Replace by extended slice
obj[2:3] = val1,val2 # Insert/replace by slice
obj[2:2] = (val,) # Insert by slice
obj[2:4] = (val,) # Replace/delete by slice
obj[2:3] = () # Delete by slice (implicit)
del obj[0] # Delete by index
del obj[2:4] # Delete by slice
com::sun::star::container::XNameAccess
com::sun::star::container::XNameReplace
com::sun::star::container::XNameContainer
- Objects provide Python dict access semantics
num = len(obj) # Number of keys
val = obj[key] # Access by key
if key in obj: ... # Test key presence
for key in obj: ... # Implicit iterator (keys)
itr = iter(obj) # Named iterator (keys)
obj[key] = val # Replace by key
obj[key] = val # Insert by key
del obj[key] # Delete by key
com::sun::star::container::XEnumerationAccess
- Objects provide Python iterable semantics
for val in obj: ... # Implicit iterator
itr = iter(obj) # Named iterator
com::sun::star::container::XEnumeration
- Objects provide Python iterator semantics
for val in itr: ... # Iteration of named iterator
if val in itr: ... # Test value presence
Objects which implement both XIndex* and XName* are supported, and
respond to both integer and string keys. However, iterating over
such an object will return the keys (like a Python dict) rather than
the values (like a Python list).
2. Cell ranges
==============
A custom behaviour is applied to objects which implement
com::sun::star::table::XCellRange to allow their cells and cell
ranges to be addressed by subscript, in the style of a Python list
or dict (read-only). This is applicable to Calc spreadsheet sheets,
Writer text tables and cell ranges created upon these.
cell = cellrange[0,0] # Access cell by indices
rng = cellrange[0,1:2] # Access cell range by index,slice
rng = cellrange[1:2,0] # Access cell range by slice,index
rng = cellrange[0:1,2:3] # Access cell range by slices
rng = cellrange['A1:B2'] # Access cell range by descriptor
rng = cellrange['Name'] # Access cell range by name
Note that the indices used are in Python/C order, and differ from
the arguments to methods provided by XCellRange.
- The statement cellrange[r,c], which returns the cell from row r
and column c, is equivalent to calling
XCellRange::getCellByPosition(c,r)
- The statement cellrange[t:b,l:r], which returns a cell range
covering rows t to b(non-inclusive) and columns l to r(non-
inclusive), is equivalent to calling
XCellRange::getCellRangeByPosition(l,t,r-1,b-1).
In contrast to the handling of objects implementing XIndex*,
extended slice syntax is not supported. Negative indices (from-end
addresses) are supported only for objects which also implement
com::sun::star::table::XColumnRowRange (currently Calc spreadsheet
sheets and cell ranges created upon these). For such objects, the
following syntax is also available:
rng = cellrange[0] # Access cell range by row index
rng = cellrange[0,:] # Access cell range by row index
rng = cellrange[:,0] # Access cell range by column index
3. Elimination of explicit Any
==============================
PyUNO has not previously been able to cope with certain method
arguments which are typed as Any but require a sequence of specific
type to be passed. This is a particular issue for container
interfaces such as XIndexContainer and XNameContainer.
The existing solution to dealing with such methods is to use a
special method to pass an explicitly typed Any, giving code such as:
index = doc.createInstance("com.sun.star.text.ContentIndex");
...
uno.invoke( index.LevelParagraphStyles , "replaceByIndex",
(0, uno.Any("[]string", ('Caption',))) )
The new Pythonic container access is able to correctly infer the
expected type of the sequences required by these arguments. In the
new style, the above call to .replaceByIndex() can instead be
written:
index.LevelParagraphStyles[0] = ('Caption',)
4. List and iterator arguments
==============================
Wherever a UNO API expects a sequence, a Python list or iterator can
now be passed. This enables the use of list comprehensions and
generator expressions for method calls and property assignments.
Example:
tbl = doc.createInstance('com.sun.star.text.TextTable')
tbl.initialize(10,10)
# ... insert table ...
# Assign numbers 0..99 to the cells using a generator expression
tbl.Data = ((y for y in range(10*x,10*x + 10)) for x in range(10))
5. Tolerant struct initialisation
=================================
Previously, a UNO struct could be created fully uninitialised, or by
passing a combination of positional and/or named arguments to its
constructor. However, if any arguments were passed, all members were
required to be initialised or an exception was thrown.
This requirement is relaxed such that when all arguments passed to a
struct constructor are by name, some may be omitted. The existing
requirement that all members must be explicitly initialised when
some constructor arguments are unnamed (positional) is not affected.
Example:
from com.sun.star.beans import PropertyValue
prop = PropertyValue(Name='foo', Value='bar')
Change-Id: Id29bff10a18099b1a00af1abee1a6c1bc58b3978
Reviewed-on: https://gerrit.libreoffice.org/16272
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Matthew Francis <mjay.francis@gmail.com>
2015-06-01 18:34:04 +08:00
|
|
|
// For Python 2.7 - see https://bugs.python.org/issue24161
|
|
|
|
// Fills aSeq and returns true if pObj is a valid iterator
|
|
|
|
bool Runtime::pyIterUnpack( PyObject *const pObj, Any &a ) const
|
|
|
|
{
|
|
|
|
if( !PyIter_Check( pObj ))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
PyObject *pItem = PyIter_Next( pObj );
|
|
|
|
if( !pItem )
|
|
|
|
{
|
|
|
|
if( PyErr_Occurred() )
|
|
|
|
{
|
|
|
|
PyErr_Clear();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
::std::list<Any> items;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
PyRef rItem( pItem, SAL_NO_ACQUIRE );
|
|
|
|
items.push_back( pyObject2Any( rItem.get() ) );
|
|
|
|
}
|
|
|
|
while( (pItem = PyIter_Next( pObj )) );
|
2015-11-19 09:14:59 +02:00
|
|
|
a <<= comphelper::containerToSequence<Any>(items);
|
Make PyUNO provide more Pythonic behaviour
- Simplifies working with UNO objects by giving the behaviour of
Python lists, dicts and iterators to objects which implement UNO
container interfaces
- Applies a custom behaviour to allow objects which implement
com::sun::star::table::XCellRange to yield cells and cell ranges by
subscript
- When UNO container objects are addressed in the new style,
eliminates the requirement to manually construct Any objects for
contained elements which are typed sequences
- Allows lists and iterators to be passed wherever a UNO method
accepts a sequence
- Relaxes the requirements for initialising UNO structs to allow
some members to be skipped when all initialisers are passed by name
1. Collection interfaces
========================
Objects which implement core UNO collection interfaces are made to
behave in a way that is more natural for Python code.
com::sun::star::container::XIndexAccess
com::sun::star::container::XIndexReplace
com::sun::star::container::XIndexContainer
- Objects provide Python list access semantics
num = len(obj) # Number of elements
val = obj[0] # Access by index
val1,val2 = obj[2:4] # Access by slice
val1,val2 = obj[0:3:2] # Access by extended slice
if val in obj: ... # Test value presence
for val in obj: ... # Implicit iterator (values)
itr = iter(obj) # Named iterator (values)
obj[0] = val # Replace by index
obj[2:4] = val1,val2 # Replace by slice
obj[0:3:2] = val1,val2 # Replace by extended slice
obj[2:3] = val1,val2 # Insert/replace by slice
obj[2:2] = (val,) # Insert by slice
obj[2:4] = (val,) # Replace/delete by slice
obj[2:3] = () # Delete by slice (implicit)
del obj[0] # Delete by index
del obj[2:4] # Delete by slice
com::sun::star::container::XNameAccess
com::sun::star::container::XNameReplace
com::sun::star::container::XNameContainer
- Objects provide Python dict access semantics
num = len(obj) # Number of keys
val = obj[key] # Access by key
if key in obj: ... # Test key presence
for key in obj: ... # Implicit iterator (keys)
itr = iter(obj) # Named iterator (keys)
obj[key] = val # Replace by key
obj[key] = val # Insert by key
del obj[key] # Delete by key
com::sun::star::container::XEnumerationAccess
- Objects provide Python iterable semantics
for val in obj: ... # Implicit iterator
itr = iter(obj) # Named iterator
com::sun::star::container::XEnumeration
- Objects provide Python iterator semantics
for val in itr: ... # Iteration of named iterator
if val in itr: ... # Test value presence
Objects which implement both XIndex* and XName* are supported, and
respond to both integer and string keys. However, iterating over
such an object will return the keys (like a Python dict) rather than
the values (like a Python list).
2. Cell ranges
==============
A custom behaviour is applied to objects which implement
com::sun::star::table::XCellRange to allow their cells and cell
ranges to be addressed by subscript, in the style of a Python list
or dict (read-only). This is applicable to Calc spreadsheet sheets,
Writer text tables and cell ranges created upon these.
cell = cellrange[0,0] # Access cell by indices
rng = cellrange[0,1:2] # Access cell range by index,slice
rng = cellrange[1:2,0] # Access cell range by slice,index
rng = cellrange[0:1,2:3] # Access cell range by slices
rng = cellrange['A1:B2'] # Access cell range by descriptor
rng = cellrange['Name'] # Access cell range by name
Note that the indices used are in Python/C order, and differ from
the arguments to methods provided by XCellRange.
- The statement cellrange[r,c], which returns the cell from row r
and column c, is equivalent to calling
XCellRange::getCellByPosition(c,r)
- The statement cellrange[t:b,l:r], which returns a cell range
covering rows t to b(non-inclusive) and columns l to r(non-
inclusive), is equivalent to calling
XCellRange::getCellRangeByPosition(l,t,r-1,b-1).
In contrast to the handling of objects implementing XIndex*,
extended slice syntax is not supported. Negative indices (from-end
addresses) are supported only for objects which also implement
com::sun::star::table::XColumnRowRange (currently Calc spreadsheet
sheets and cell ranges created upon these). For such objects, the
following syntax is also available:
rng = cellrange[0] # Access cell range by row index
rng = cellrange[0,:] # Access cell range by row index
rng = cellrange[:,0] # Access cell range by column index
3. Elimination of explicit Any
==============================
PyUNO has not previously been able to cope with certain method
arguments which are typed as Any but require a sequence of specific
type to be passed. This is a particular issue for container
interfaces such as XIndexContainer and XNameContainer.
The existing solution to dealing with such methods is to use a
special method to pass an explicitly typed Any, giving code such as:
index = doc.createInstance("com.sun.star.text.ContentIndex");
...
uno.invoke( index.LevelParagraphStyles , "replaceByIndex",
(0, uno.Any("[]string", ('Caption',))) )
The new Pythonic container access is able to correctly infer the
expected type of the sequences required by these arguments. In the
new style, the above call to .replaceByIndex() can instead be
written:
index.LevelParagraphStyles[0] = ('Caption',)
4. List and iterator arguments
==============================
Wherever a UNO API expects a sequence, a Python list or iterator can
now be passed. This enables the use of list comprehensions and
generator expressions for method calls and property assignments.
Example:
tbl = doc.createInstance('com.sun.star.text.TextTable')
tbl.initialize(10,10)
# ... insert table ...
# Assign numbers 0..99 to the cells using a generator expression
tbl.Data = ((y for y in range(10*x,10*x + 10)) for x in range(10))
5. Tolerant struct initialisation
=================================
Previously, a UNO struct could be created fully uninitialised, or by
passing a combination of positional and/or named arguments to its
constructor. However, if any arguments were passed, all members were
required to be initialised or an exception was thrown.
This requirement is relaxed such that when all arguments passed to a
struct constructor are by name, some may be omitted. The existing
requirement that all members must be explicitly initialised when
some constructor arguments are unnamed (positional) is not affected.
Example:
from com.sun.star.beans import PropertyValue
prop = PropertyValue(Name='foo', Value='bar')
Change-Id: Id29bff10a18099b1a00af1abee1a6c1bc58b3978
Reviewed-on: https://gerrit.libreoffice.org/16272
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Matthew Francis <mjay.francis@gmail.com>
2015-06-01 18:34:04 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2003-05-24 22:31:19 +00:00
|
|
|
Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
|
2015-10-23 14:59:15 +02:00
|
|
|
throw ( css::uno::RuntimeException )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
if( ! impl->cargo->valid )
|
|
|
|
{
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Any a;
|
|
|
|
PyObject *o = source.get();
|
|
|
|
if( Py_None == o )
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2011-05-07 20:35:03 +01:00
|
|
|
// In Python 3, there is no PyInt type.
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
2003-03-23 11:12:59 +00:00
|
|
|
else if (PyInt_Check (o))
|
|
|
|
{
|
|
|
|
if( o == Py_True )
|
|
|
|
{
|
2016-05-08 20:58:33 +10:00
|
|
|
a <<= true;
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
else if ( o == Py_False )
|
|
|
|
{
|
2016-05-08 20:58:33 +10:00
|
|
|
a <<= false;
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-05-07 20:35:03 +01:00
|
|
|
sal_Int32 l = (sal_Int32) PyLong_AsLong( o );
|
2003-03-23 11:12:59 +00:00
|
|
|
if( l < 128 && l >= -128 )
|
|
|
|
{
|
|
|
|
sal_Int8 b = (sal_Int8 ) l;
|
|
|
|
a <<= b;
|
|
|
|
}
|
|
|
|
else if( l <= 0x7fff && l >= -0x8000 )
|
|
|
|
{
|
|
|
|
sal_Int16 s = (sal_Int16) l;
|
|
|
|
a <<= s;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a <<= l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-07 20:35:03 +01:00
|
|
|
#endif /* PY_MAJOR_VERSION < 3 */
|
2003-03-23 11:12:59 +00:00
|
|
|
else if (PyLong_Check (o))
|
|
|
|
{
|
2011-05-07 20:35:03 +01:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
// Convert the Python 3 booleans that are actually of type PyLong.
|
|
|
|
if(o == Py_True)
|
|
|
|
{
|
2016-05-04 11:59:23 +02:00
|
|
|
a <<= true;
|
2011-05-07 20:35:03 +01:00
|
|
|
}
|
|
|
|
else if(o == Py_False)
|
|
|
|
{
|
2016-05-04 11:59:23 +02:00
|
|
|
a <<= false;
|
2011-05-07 20:35:03 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#endif /* PY_MAJOR_VERSION >= 3 */
|
2003-03-23 11:12:59 +00:00
|
|
|
sal_Int64 l = (sal_Int64)PyLong_AsLong (o);
|
2003-03-30 12:32:01 +00:00
|
|
|
if( l < 128 && l >= -128 )
|
|
|
|
{
|
|
|
|
sal_Int8 b = (sal_Int8 ) l;
|
|
|
|
a <<= b;
|
|
|
|
}
|
|
|
|
else if( l <= 0x7fff && l >= -0x8000 )
|
|
|
|
{
|
|
|
|
sal_Int16 s = (sal_Int16) l;
|
|
|
|
a <<= s;
|
|
|
|
}
|
2006-06-20 04:04:22 +00:00
|
|
|
else if( l <= SAL_CONST_INT64(0x7fffffff) &&
|
|
|
|
l >= -SAL_CONST_INT64(0x80000000) )
|
2003-03-30 12:32:01 +00:00
|
|
|
{
|
|
|
|
sal_Int32 l32 = (sal_Int32) l;
|
|
|
|
a <<= l32;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a <<= l;
|
|
|
|
}
|
2011-05-07 20:35:03 +01:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
}
|
|
|
|
#endif
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
else if (PyFloat_Check (o))
|
|
|
|
{
|
|
|
|
double d = PyFloat_AsDouble (o);
|
|
|
|
a <<= d;
|
|
|
|
}
|
2012-11-25 15:59:18 +01:00
|
|
|
else if (PyStrBytes_Check(o) || PyUnicode_Check(o))
|
2011-05-07 20:35:03 +01:00
|
|
|
{
|
|
|
|
a <<= pyString2ustring(o);
|
|
|
|
}
|
2003-03-23 11:12:59 +00:00
|
|
|
else if (PyTuple_Check (o))
|
|
|
|
{
|
|
|
|
Sequence<Any> s (PyTuple_Size (o));
|
2015-05-29 14:12:20 +02:00
|
|
|
for (Py_ssize_t i = 0; i < PyTuple_Size (o); i++)
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
2003-05-24 22:31:19 +00:00
|
|
|
s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
a <<= s;
|
|
|
|
}
|
Make PyUNO provide more Pythonic behaviour
- Simplifies working with UNO objects by giving the behaviour of
Python lists, dicts and iterators to objects which implement UNO
container interfaces
- Applies a custom behaviour to allow objects which implement
com::sun::star::table::XCellRange to yield cells and cell ranges by
subscript
- When UNO container objects are addressed in the new style,
eliminates the requirement to manually construct Any objects for
contained elements which are typed sequences
- Allows lists and iterators to be passed wherever a UNO method
accepts a sequence
- Relaxes the requirements for initialising UNO structs to allow
some members to be skipped when all initialisers are passed by name
1. Collection interfaces
========================
Objects which implement core UNO collection interfaces are made to
behave in a way that is more natural for Python code.
com::sun::star::container::XIndexAccess
com::sun::star::container::XIndexReplace
com::sun::star::container::XIndexContainer
- Objects provide Python list access semantics
num = len(obj) # Number of elements
val = obj[0] # Access by index
val1,val2 = obj[2:4] # Access by slice
val1,val2 = obj[0:3:2] # Access by extended slice
if val in obj: ... # Test value presence
for val in obj: ... # Implicit iterator (values)
itr = iter(obj) # Named iterator (values)
obj[0] = val # Replace by index
obj[2:4] = val1,val2 # Replace by slice
obj[0:3:2] = val1,val2 # Replace by extended slice
obj[2:3] = val1,val2 # Insert/replace by slice
obj[2:2] = (val,) # Insert by slice
obj[2:4] = (val,) # Replace/delete by slice
obj[2:3] = () # Delete by slice (implicit)
del obj[0] # Delete by index
del obj[2:4] # Delete by slice
com::sun::star::container::XNameAccess
com::sun::star::container::XNameReplace
com::sun::star::container::XNameContainer
- Objects provide Python dict access semantics
num = len(obj) # Number of keys
val = obj[key] # Access by key
if key in obj: ... # Test key presence
for key in obj: ... # Implicit iterator (keys)
itr = iter(obj) # Named iterator (keys)
obj[key] = val # Replace by key
obj[key] = val # Insert by key
del obj[key] # Delete by key
com::sun::star::container::XEnumerationAccess
- Objects provide Python iterable semantics
for val in obj: ... # Implicit iterator
itr = iter(obj) # Named iterator
com::sun::star::container::XEnumeration
- Objects provide Python iterator semantics
for val in itr: ... # Iteration of named iterator
if val in itr: ... # Test value presence
Objects which implement both XIndex* and XName* are supported, and
respond to both integer and string keys. However, iterating over
such an object will return the keys (like a Python dict) rather than
the values (like a Python list).
2. Cell ranges
==============
A custom behaviour is applied to objects which implement
com::sun::star::table::XCellRange to allow their cells and cell
ranges to be addressed by subscript, in the style of a Python list
or dict (read-only). This is applicable to Calc spreadsheet sheets,
Writer text tables and cell ranges created upon these.
cell = cellrange[0,0] # Access cell by indices
rng = cellrange[0,1:2] # Access cell range by index,slice
rng = cellrange[1:2,0] # Access cell range by slice,index
rng = cellrange[0:1,2:3] # Access cell range by slices
rng = cellrange['A1:B2'] # Access cell range by descriptor
rng = cellrange['Name'] # Access cell range by name
Note that the indices used are in Python/C order, and differ from
the arguments to methods provided by XCellRange.
- The statement cellrange[r,c], which returns the cell from row r
and column c, is equivalent to calling
XCellRange::getCellByPosition(c,r)
- The statement cellrange[t:b,l:r], which returns a cell range
covering rows t to b(non-inclusive) and columns l to r(non-
inclusive), is equivalent to calling
XCellRange::getCellRangeByPosition(l,t,r-1,b-1).
In contrast to the handling of objects implementing XIndex*,
extended slice syntax is not supported. Negative indices (from-end
addresses) are supported only for objects which also implement
com::sun::star::table::XColumnRowRange (currently Calc spreadsheet
sheets and cell ranges created upon these). For such objects, the
following syntax is also available:
rng = cellrange[0] # Access cell range by row index
rng = cellrange[0,:] # Access cell range by row index
rng = cellrange[:,0] # Access cell range by column index
3. Elimination of explicit Any
==============================
PyUNO has not previously been able to cope with certain method
arguments which are typed as Any but require a sequence of specific
type to be passed. This is a particular issue for container
interfaces such as XIndexContainer and XNameContainer.
The existing solution to dealing with such methods is to use a
special method to pass an explicitly typed Any, giving code such as:
index = doc.createInstance("com.sun.star.text.ContentIndex");
...
uno.invoke( index.LevelParagraphStyles , "replaceByIndex",
(0, uno.Any("[]string", ('Caption',))) )
The new Pythonic container access is able to correctly infer the
expected type of the sequences required by these arguments. In the
new style, the above call to .replaceByIndex() can instead be
written:
index.LevelParagraphStyles[0] = ('Caption',)
4. List and iterator arguments
==============================
Wherever a UNO API expects a sequence, a Python list or iterator can
now be passed. This enables the use of list comprehensions and
generator expressions for method calls and property assignments.
Example:
tbl = doc.createInstance('com.sun.star.text.TextTable')
tbl.initialize(10,10)
# ... insert table ...
# Assign numbers 0..99 to the cells using a generator expression
tbl.Data = ((y for y in range(10*x,10*x + 10)) for x in range(10))
5. Tolerant struct initialisation
=================================
Previously, a UNO struct could be created fully uninitialised, or by
passing a combination of positional and/or named arguments to its
constructor. However, if any arguments were passed, all members were
required to be initialised or an exception was thrown.
This requirement is relaxed such that when all arguments passed to a
struct constructor are by name, some may be omitted. The existing
requirement that all members must be explicitly initialised when
some constructor arguments are unnamed (positional) is not affected.
Example:
from com.sun.star.beans import PropertyValue
prop = PropertyValue(Name='foo', Value='bar')
Change-Id: Id29bff10a18099b1a00af1abee1a6c1bc58b3978
Reviewed-on: https://gerrit.libreoffice.org/16272
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Matthew Francis <mjay.francis@gmail.com>
2015-06-01 18:34:04 +08:00
|
|
|
else if (PyList_Check (o))
|
|
|
|
{
|
|
|
|
Py_ssize_t l = PyList_Size (o);
|
|
|
|
Sequence<Any> s (l);
|
2015-06-26 14:03:46 +02:00
|
|
|
for (Py_ssize_t i = 0; i < l; i++)
|
Make PyUNO provide more Pythonic behaviour
- Simplifies working with UNO objects by giving the behaviour of
Python lists, dicts and iterators to objects which implement UNO
container interfaces
- Applies a custom behaviour to allow objects which implement
com::sun::star::table::XCellRange to yield cells and cell ranges by
subscript
- When UNO container objects are addressed in the new style,
eliminates the requirement to manually construct Any objects for
contained elements which are typed sequences
- Allows lists and iterators to be passed wherever a UNO method
accepts a sequence
- Relaxes the requirements for initialising UNO structs to allow
some members to be skipped when all initialisers are passed by name
1. Collection interfaces
========================
Objects which implement core UNO collection interfaces are made to
behave in a way that is more natural for Python code.
com::sun::star::container::XIndexAccess
com::sun::star::container::XIndexReplace
com::sun::star::container::XIndexContainer
- Objects provide Python list access semantics
num = len(obj) # Number of elements
val = obj[0] # Access by index
val1,val2 = obj[2:4] # Access by slice
val1,val2 = obj[0:3:2] # Access by extended slice
if val in obj: ... # Test value presence
for val in obj: ... # Implicit iterator (values)
itr = iter(obj) # Named iterator (values)
obj[0] = val # Replace by index
obj[2:4] = val1,val2 # Replace by slice
obj[0:3:2] = val1,val2 # Replace by extended slice
obj[2:3] = val1,val2 # Insert/replace by slice
obj[2:2] = (val,) # Insert by slice
obj[2:4] = (val,) # Replace/delete by slice
obj[2:3] = () # Delete by slice (implicit)
del obj[0] # Delete by index
del obj[2:4] # Delete by slice
com::sun::star::container::XNameAccess
com::sun::star::container::XNameReplace
com::sun::star::container::XNameContainer
- Objects provide Python dict access semantics
num = len(obj) # Number of keys
val = obj[key] # Access by key
if key in obj: ... # Test key presence
for key in obj: ... # Implicit iterator (keys)
itr = iter(obj) # Named iterator (keys)
obj[key] = val # Replace by key
obj[key] = val # Insert by key
del obj[key] # Delete by key
com::sun::star::container::XEnumerationAccess
- Objects provide Python iterable semantics
for val in obj: ... # Implicit iterator
itr = iter(obj) # Named iterator
com::sun::star::container::XEnumeration
- Objects provide Python iterator semantics
for val in itr: ... # Iteration of named iterator
if val in itr: ... # Test value presence
Objects which implement both XIndex* and XName* are supported, and
respond to both integer and string keys. However, iterating over
such an object will return the keys (like a Python dict) rather than
the values (like a Python list).
2. Cell ranges
==============
A custom behaviour is applied to objects which implement
com::sun::star::table::XCellRange to allow their cells and cell
ranges to be addressed by subscript, in the style of a Python list
or dict (read-only). This is applicable to Calc spreadsheet sheets,
Writer text tables and cell ranges created upon these.
cell = cellrange[0,0] # Access cell by indices
rng = cellrange[0,1:2] # Access cell range by index,slice
rng = cellrange[1:2,0] # Access cell range by slice,index
rng = cellrange[0:1,2:3] # Access cell range by slices
rng = cellrange['A1:B2'] # Access cell range by descriptor
rng = cellrange['Name'] # Access cell range by name
Note that the indices used are in Python/C order, and differ from
the arguments to methods provided by XCellRange.
- The statement cellrange[r,c], which returns the cell from row r
and column c, is equivalent to calling
XCellRange::getCellByPosition(c,r)
- The statement cellrange[t:b,l:r], which returns a cell range
covering rows t to b(non-inclusive) and columns l to r(non-
inclusive), is equivalent to calling
XCellRange::getCellRangeByPosition(l,t,r-1,b-1).
In contrast to the handling of objects implementing XIndex*,
extended slice syntax is not supported. Negative indices (from-end
addresses) are supported only for objects which also implement
com::sun::star::table::XColumnRowRange (currently Calc spreadsheet
sheets and cell ranges created upon these). For such objects, the
following syntax is also available:
rng = cellrange[0] # Access cell range by row index
rng = cellrange[0,:] # Access cell range by row index
rng = cellrange[:,0] # Access cell range by column index
3. Elimination of explicit Any
==============================
PyUNO has not previously been able to cope with certain method
arguments which are typed as Any but require a sequence of specific
type to be passed. This is a particular issue for container
interfaces such as XIndexContainer and XNameContainer.
The existing solution to dealing with such methods is to use a
special method to pass an explicitly typed Any, giving code such as:
index = doc.createInstance("com.sun.star.text.ContentIndex");
...
uno.invoke( index.LevelParagraphStyles , "replaceByIndex",
(0, uno.Any("[]string", ('Caption',))) )
The new Pythonic container access is able to correctly infer the
expected type of the sequences required by these arguments. In the
new style, the above call to .replaceByIndex() can instead be
written:
index.LevelParagraphStyles[0] = ('Caption',)
4. List and iterator arguments
==============================
Wherever a UNO API expects a sequence, a Python list or iterator can
now be passed. This enables the use of list comprehensions and
generator expressions for method calls and property assignments.
Example:
tbl = doc.createInstance('com.sun.star.text.TextTable')
tbl.initialize(10,10)
# ... insert table ...
# Assign numbers 0..99 to the cells using a generator expression
tbl.Data = ((y for y in range(10*x,10*x + 10)) for x in range(10))
5. Tolerant struct initialisation
=================================
Previously, a UNO struct could be created fully uninitialised, or by
passing a combination of positional and/or named arguments to its
constructor. However, if any arguments were passed, all members were
required to be initialised or an exception was thrown.
This requirement is relaxed such that when all arguments passed to a
struct constructor are by name, some may be omitted. The existing
requirement that all members must be explicitly initialised when
some constructor arguments are unnamed (positional) is not affected.
Example:
from com.sun.star.beans import PropertyValue
prop = PropertyValue(Name='foo', Value='bar')
Change-Id: Id29bff10a18099b1a00af1abee1a6c1bc58b3978
Reviewed-on: https://gerrit.libreoffice.org/16272
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Matthew Francis <mjay.francis@gmail.com>
2015-06-01 18:34:04 +08:00
|
|
|
{
|
|
|
|
s[i] = pyObject2Any (PyList_GetItem (o, i), mode );
|
|
|
|
}
|
|
|
|
a <<= s;
|
|
|
|
}
|
|
|
|
else if (!pyIterUnpack (o, a))
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
Runtime runtime;
|
2003-03-30 12:32:01 +00:00
|
|
|
// should be removed, in case ByteSequence gets derived from String
|
2003-03-23 11:12:59 +00:00
|
|
|
if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
|
|
|
|
{
|
2011-08-20 17:33:37 +02:00
|
|
|
PyRef str(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
|
2003-03-23 11:12:59 +00:00
|
|
|
Sequence< sal_Int8 > seq;
|
2012-11-25 15:59:18 +01:00
|
|
|
if( PyStrBytes_Check( str.get() ) )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
seq = Sequence<sal_Int8 > (
|
2015-01-17 19:00:24 +01:00
|
|
|
reinterpret_cast<sal_Int8*>(PyStrBytes_AsString(str.get())), PyStrBytes_Size(str.get()));
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
a <<= seq;
|
|
|
|
}
|
2003-03-30 12:32:01 +00:00
|
|
|
else
|
|
|
|
if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
2006-06-20 04:04:22 +00:00
|
|
|
Type t = PyType2Type( o );
|
2003-03-23 11:12:59 +00:00
|
|
|
a <<= t;
|
|
|
|
}
|
|
|
|
else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
|
|
|
|
{
|
2006-06-20 04:04:22 +00:00
|
|
|
a = PyEnum2Enum( o );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
2006-06-20 04:04:22 +00:00
|
|
|
else if( isInstanceOfStructOrException( o ) )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
2011-08-20 17:33:37 +02:00
|
|
|
PyRef struc(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
|
2015-01-17 19:00:24 +01:00
|
|
|
PyUNO * obj = reinterpret_cast<PyUNO*>(struc.get());
|
2003-03-23 11:12:59 +00:00
|
|
|
Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
|
|
|
|
if( holder.is( ) )
|
|
|
|
a = holder->getMaterial();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw RuntimeException(
|
2014-05-23 12:03:21 +02:00
|
|
|
"struct or exception wrapper does not support XMaterialHolder" );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-21 15:21:16 +01:00
|
|
|
else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
2015-07-29 15:22:54 +08:00
|
|
|
PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
|
|
|
|
a = o_pi->members->wrappedObject;
|
|
|
|
}
|
|
|
|
else if( PyObject_IsInstance( o, getPyUnoStructClass().get() ) )
|
|
|
|
{
|
|
|
|
PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
|
|
|
|
Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY);
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2015-07-29 15:22:54 +08:00
|
|
|
if (!my_mh.is())
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
2015-07-29 15:22:54 +08:00
|
|
|
throw RuntimeException(
|
|
|
|
"struct wrapper does not support XMaterialHolder" );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
2015-07-29 15:22:54 +08:00
|
|
|
else
|
|
|
|
a = my_mh->getMaterial();
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
|
|
|
|
{
|
2016-05-30 14:31:24 +02:00
|
|
|
a <<= PyChar2Unicode( o );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
2003-05-24 22:31:19 +00:00
|
|
|
else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
|
|
|
|
{
|
|
|
|
if( ACCEPT_UNO_ANY == mode )
|
|
|
|
{
|
2011-08-20 17:33:37 +02:00
|
|
|
a = pyObject2Any( PyRef( PyObject_GetAttrString( o , "value" ), SAL_NO_ACQUIRE) );
|
2003-05-24 22:31:19 +00:00
|
|
|
Type t;
|
2011-08-20 17:33:37 +02:00
|
|
|
pyObject2Any( PyRef( PyObject_GetAttrString( o, "type" ), SAL_NO_ACQUIRE ) ) >>= t;
|
2003-05-24 22:31:19 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
|
|
|
|
}
|
2015-10-23 14:59:15 +02:00
|
|
|
catch( const css::uno::Exception & e )
|
2003-05-24 22:31:19 +00:00
|
|
|
{
|
2012-11-16 13:20:50 +01:00
|
|
|
throw WrappedTargetRuntimeException(
|
|
|
|
e.Message, e.Context, makeAny(e));
|
2003-05-24 22:31:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw RuntimeException(
|
2014-05-23 12:03:21 +02:00
|
|
|
"uno.Any instance not accepted during method call, "
|
|
|
|
"use uno.invoke instead" );
|
2003-05-24 22:31:19 +00:00
|
|
|
}
|
|
|
|
}
|
2003-03-23 11:12:59 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
Reference< XInterface > mappedObject;
|
2004-02-02 18:30:44 +00:00
|
|
|
Reference< XInvocation > adapterObject;
|
|
|
|
|
|
|
|
// instance already mapped out to the world ?
|
|
|
|
PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
|
|
|
|
if( ii != impl->cargo->mappedObjects.end() )
|
|
|
|
{
|
|
|
|
adapterObject = ii->second;
|
|
|
|
}
|
2003-03-23 11:12:59 +00:00
|
|
|
|
2004-02-02 18:30:44 +00:00
|
|
|
if( adapterObject.is() )
|
|
|
|
{
|
|
|
|
// object got already bridged !
|
2015-10-23 14:59:15 +02:00
|
|
|
Reference< css::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY );
|
2004-02-02 18:30:44 +00:00
|
|
|
|
2014-09-26 13:15:08 +02:00
|
|
|
Adapter *pAdapter = reinterpret_cast<Adapter*>(
|
2006-06-20 04:04:22 +00:00
|
|
|
tunnel->getSomething(
|
|
|
|
::pyuno::Adapter::getUnoTunnelImplementationId() ) );
|
2004-02-02 18:30:44 +00:00
|
|
|
|
|
|
|
mappedObject = impl->cargo->xAdapterFactory->createAdapter(
|
|
|
|
adapterObject, pAdapter->getWrappedTypes() );
|
|
|
|
}
|
|
|
|
else
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
2012-11-16 13:20:50 +01:00
|
|
|
try {
|
|
|
|
Sequence<Type> interfaces = invokeGetTypes(*this, o);
|
|
|
|
if (interfaces.getLength())
|
|
|
|
{
|
|
|
|
Adapter *pAdapter = new Adapter( o, interfaces );
|
|
|
|
mappedObject =
|
|
|
|
getImpl()->cargo->xAdapterFactory->createAdapter(
|
|
|
|
pAdapter, interfaces );
|
|
|
|
|
|
|
|
// keep a list of exported objects to ensure object identity !
|
|
|
|
impl->cargo->mappedObjects[ PyRef(o) ] =
|
2015-10-23 14:59:15 +02:00
|
|
|
css::uno::WeakReference< XInvocation > ( pAdapter );
|
2012-11-16 13:20:50 +01:00
|
|
|
}
|
|
|
|
} catch (InvocationTargetException const& e) {
|
|
|
|
OUString const msg(lcl_ExceptionMessage(o, &e.Message));
|
|
|
|
throw WrappedTargetRuntimeException( // re-wrap that
|
|
|
|
msg, e.Context, e.TargetException);
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if( mappedObject.is() )
|
|
|
|
{
|
2015-10-23 14:59:15 +02:00
|
|
|
a = css::uno::makeAny( mappedObject );
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-11-10 10:20:48 +01:00
|
|
|
OUString const msg(lcl_ExceptionMessage(o, nullptr));
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException(msg);
|
2003-03-23 11:12:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2003-12-17 17:46:50 +00:00
|
|
|
Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
|
|
|
|
{
|
2011-08-20 17:14:24 +02:00
|
|
|
OUString str;
|
2003-12-17 17:46:50 +00:00
|
|
|
Any ret;
|
|
|
|
if( excTraceback.is() )
|
|
|
|
{
|
2011-08-20 17:14:24 +02:00
|
|
|
Exception e;
|
|
|
|
PyRef unoModule;
|
|
|
|
if ( impl )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
unoModule = impl->cargo->getUnoModule();
|
|
|
|
}
|
2011-12-21 21:57:16 +09:00
|
|
|
catch (const Exception &ei)
|
2011-08-20 17:14:24 +02:00
|
|
|
{
|
|
|
|
e=ei;
|
|
|
|
}
|
|
|
|
}
|
2003-12-17 17:46:50 +00:00
|
|
|
if( unoModule.is() )
|
|
|
|
{
|
|
|
|
PyRef extractTraceback(
|
|
|
|
PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
|
|
|
|
|
2011-08-20 17:14:24 +02:00
|
|
|
if( PyCallable_Check(extractTraceback.get()) )
|
2003-12-17 17:46:50 +00:00
|
|
|
{
|
2014-05-26 15:02:11 +01:00
|
|
|
PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE, NOT_NULL );
|
2003-12-17 17:46:50 +00:00
|
|
|
PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
|
2011-08-20 17:14:24 +02:00
|
|
|
PyRef pyStr( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
|
2013-04-07 12:06:47 +02:00
|
|
|
str = OUString::createFromAscii( PyStr_AsString(pyStr.get()) );
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-04 14:00:40 +02:00
|
|
|
str = "Couldn't find uno._uno_extract_printable_stacktrace";
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-04 14:00:40 +02:00
|
|
|
str = "Could not load uno.py, no stacktrace available";
|
2012-01-02 15:58:10 -02:00
|
|
|
if ( !e.Message.isEmpty() )
|
2011-08-20 17:14:24 +02:00
|
|
|
{
|
2015-06-26 13:53:48 +02:00
|
|
|
str += " (Error loading uno.py: " + e.Message + ")";
|
2011-08-20 17:14:24 +02:00
|
|
|
}
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// it may occur, that no traceback is given (e.g. only native code below)
|
2013-11-04 14:00:40 +02:00
|
|
|
str = "no traceback available";
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
|
2006-06-20 04:04:22 +00:00
|
|
|
if( isInstanceOfStructOrException( excValue.get() ) )
|
2003-12-17 17:46:50 +00:00
|
|
|
{
|
|
|
|
ret = pyObject2Any( excValue );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OUStringBuffer buf;
|
|
|
|
PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
|
|
|
|
if( typeName.is() )
|
|
|
|
{
|
2012-11-25 15:59:18 +01:00
|
|
|
buf.appendAscii( PyStr_AsString( typeName.get() ) );
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( "no typename available" );
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( ": " );
|
2003-12-17 17:46:50 +00:00
|
|
|
PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
|
|
|
|
if( valueRep.is() )
|
|
|
|
{
|
2012-11-25 15:59:18 +01:00
|
|
|
buf.appendAscii( PyStr_AsString( valueRep.get()));
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( "Couldn't convert exception value to a string" );
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( ", traceback follows\n" );
|
2012-01-02 15:58:10 -02:00
|
|
|
if( !str.isEmpty() )
|
2003-12-17 17:46:50 +00:00
|
|
|
{
|
2011-08-20 17:14:24 +02:00
|
|
|
buf.append( str );
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( "\n" );
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-08-31 08:02:45 +02:00
|
|
|
buf.append( ", no traceback available\n" );
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
RuntimeException e;
|
|
|
|
e.Message = buf.makeStringAndClear();
|
2011-12-05 19:44:49 +00:00
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
|
|
fprintf( stderr, "Python exception: %s\n",
|
2013-04-07 12:06:47 +02:00
|
|
|
OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
|
2011-12-05 19:44:49 +00:00
|
|
|
#endif
|
2015-10-23 14:59:15 +02:00
|
|
|
ret = css::uno::makeAny( e );
|
2003-12-17 17:46:50 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2003-03-23 11:12:59 +00:00
|
|
|
|
|
|
|
PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
|
2015-10-23 14:59:15 +02:00
|
|
|
throw ( css::uno::RuntimeException )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
tstate = PyThreadState_New( interp );
|
|
|
|
if( !tstate )
|
2014-05-23 12:03:21 +02:00
|
|
|
throw RuntimeException( "Couldn't create a pythreadstate" );
|
2003-03-23 11:12:59 +00:00
|
|
|
PyEval_AcquireThread( tstate);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyThreadAttach::~PyThreadAttach()
|
|
|
|
{
|
|
|
|
PyThreadState_Clear( tstate );
|
|
|
|
PyEval_ReleaseThread( tstate );
|
|
|
|
PyThreadState_Delete( tstate );
|
|
|
|
}
|
|
|
|
|
2015-10-23 14:59:15 +02:00
|
|
|
PyThreadDetach::PyThreadDetach() throw ( css::uno::RuntimeException )
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
tstate = PyThreadState_Get();
|
|
|
|
PyEval_ReleaseThread( tstate );
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Acquires the global interpreter lock again
|
|
|
|
|
|
|
|
*/
|
|
|
|
PyThreadDetach::~PyThreadDetach()
|
|
|
|
{
|
|
|
|
PyEval_AcquireThread( tstate );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-18 09:22:27 +02:00
|
|
|
PyRef const & RuntimeCargo::getUnoModule()
|
2003-03-23 11:12:59 +00:00
|
|
|
{
|
|
|
|
if( ! dictUnoModule.is() )
|
|
|
|
{
|
|
|
|
dictUnoModule = importUnoModule();
|
|
|
|
}
|
|
|
|
return dictUnoModule;
|
|
|
|
}
|
|
|
|
}
|
2010-10-14 08:30:07 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|