| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <html> |
| <head> |
| <meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=UTF-8"/> |
| <title> Python-UNO bridge</title> |
| </head> |
| <body> |
| |
| <h1> Python-UNO bridge</h1> |
| |
| <h2> IMPORTANT: Workarounds for pyuno problems in OOo3.0.0 </h2> |
| There are some problems with pyuno in OOo3.0.0 (in particular with the |
| python executable). Here the known problems and the workarounds for the moment |
| . |
| <ol> |
| <li> (windows only) The python scripting framework (scripts within openoffice via Extras/Macro/) does not work, when you have |
| a python 2.3 installed on your windows system (more precisly, when there exists a python23.dll in your windows/system32 directory). |
| You can work around it for now by copying Basis\program\python23.dll to program\. beside the soffice.bin executable. This forces |
| the soffice process to load the correct library beside the office process. (<a href="http://www.openoffice.org/issues/show_bug.cgi?id=94993">94993</a>) |
| |
| </li> |
| <li> (windows only) When you try to connect to a running office process, you get |
| <pre> __main__.com.sun.star.connection.NoConnectException: Connector couldn't connect to socket (WSANOTINITIALISED, WSAStartup() has not been called) </pre> |
| You can workaround this, by placing a |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import socket |
| </pre></td></tr></table> |
| |
| in the top of your script (<a href="http://www.openoffice.org/issues/show_bug.cgi?id=95028">95028</a>) |
| </li> |
| <li> (windows only) The python program crashes or you get an attribute error |
| <pre> |
| AttributeError: getCurrentComponent (or some other attribute) |
| </pre> |
| This is because the types could not be loaded due to changes in the |
| uno bootstrapping mechanism. You can work around it for now by setting the |
| URE_BOOTSTRAP variable (adapt to your installation path, replace every space with a %20, change \ to /). |
| <!-- set URE_BOOTSTRAP=file:///C:/Program%20Files/OpenOffice.org%203/program/fundamental.ini --> |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| set URE_BOOTSTRAP=file:///C:/Program%20Files/OpenOffice.org%203/program/fundamental.ini |
| </pre></td></tr></table> |
| and run python. Alternatively, you can set URE_BOOTSTRAP=fundamental.ini when |
| your current working directory is beside the python executable. (<a href="http://www.openoffice.org/issues/show_bug.cgi?id=95024">95024</a>) |
| |
| <li> (windows only) Interactive mode in python does not work correctly |
| When you start the python executable without parameters, the interactive session runs somewhat fuzzy (at least on my machine). |
| When you get the prompt >>>> , everything you type will be interpreted as a shell command. When you then just press return, you are prompted |
| with your current working directory, here you can place a python command, so in short, you have to press return 2 times after every python command |
| (<a href="http://www.openoffice.org/issues/show_bug.cgi?id=95037">95037</a>). |
| |
| </li> |
| <li>( unix only), you need to set LD_LIBRARY_PATH correctly before starting the python executable, eg. |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| export set LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../openoffice.org/ure/lib:../../openoffice.org/basis3.0/program |
| ./python |
| </pre></td></tr></table> |
| |
| </ol> |
| <h2> Contents </h2> |
| |
| - <a href="#translations">Translations</a><br/> |
| - <a href="#intro">Introduction</a><br/> |
| - <a href="#download">Download</a><br/> |
| - <a href="#state">State</a><br/> |
| - <a href="#tutorial">Tutorial</a><br/> |
| -- <a href="#install">PyUNO Installation</a><br/> |
| -- <a href="#modes">PyUNO Bridge Modes</a><br/> |
| -- <a href="#examples">More examples</a><br/> |
| - <a href="#binding">UNO language binding</a><br/> |
| -- <a href="#mapping">UNO type mapping</a><br/> |
| -- <a href="#objects">Implementing UNO objects</a><br/> |
| -- <a href="#components">Implementing UNO components</a><br/> |
| -- <a href="#outparas">Out parameter handling</a><br/> |
| -- <a href="#exception">Exception handling</a><br/> |
| -- <a href="#current_context">current context support (since OOo 2.0.2)</a><br/> |
| -- <a href="#helper">unohelper module</a><br/> |
| -- <a href="#logging">logging (since OOo 2.0.2)</a><br/> |
| -- <a href="#multiple_source_files">Implementing UNO components with multiple source files (since OOo 2.4)</a><br/> |
| - <a href="#dependencies">Dependencies</a><br/> |
| - <a href="#bootstrap">Bootstrapping in non-OOo environments</a><br/> |
| - <a href="#replacing">Replacing the python runtime</a><br/> |
| - <a href="#regressiontests">Regressiontests</a><br/> |
| <!-- - <a href="#scripting-framework">Support for the new scripting framework </a><br/> --> |
| - <a href="#references">External references</a><br/> |
| - <a href="#faq">FAQ</a> (read this FIRST when you have problems)<br/> |
| - <a href="#known_pyuno_extensions">Known pyuno extensions for OOo</a><br/> |
| - <a href="#pyuno_needs_you">PyUNO needs you !</a><br/> |
| - <a href="#authors">Authors</a><br/> |
| - <a href="#license">License</a><br/> |
| |
| <h2 id="translations"> Translations </h2> |
| <p> |
| Find <a href="http://www.openoffice.org/files/documents/73/1509/python_uno_bridge.htm"> |
| here</a> |
| a shortened Spanish version of this document. |
| |
| <h2 id="intro"> Introduction </h2> |
| <p>The Python-UNO bridge allows to |
| |
| <ul> |
| <li> use the standard OpenOffice.org API from the well known python scripting language. </li> |
| <li> to develop UNO components in python, thus python UNO components may be run within the |
| OpenOffice.org process and can be called from Java, C++ or the built in |
| StarBasic scripting language.</li> |
| <li> <a href="scriptingframework/index.html">create and invoke scripts</a> with the office scripting framework (OOo 2.0 and later).</li> |
| </ul> |
| </p> |
| |
| <p> You can find the most current version of this document from |
| <a href="http://udk.openoffice.org/python/python-bridge.html"> |
| http://udk.openoffice.org/python/python-bridge.html</a> |
| |
| <h2 id="download"> Download </h2> |
| <p>You can also download this documentation for offline work.</p> |
| |
| <p><strong>Download <a href="pyuno-doc.zip">pyuno-doc.zip</a> </strong>( less than 0.5 MB). |
| |
| <h2 id="state"> State </h2> |
| |
| <p>The Python-UNO bridge is feature complete, but has not been used |
| extensively, so it may contain some bugs. It is now integrated in the |
| OpenOffice.org source trees. (OpenOffice.org 1.0.x is not supported.) |
| |
| <p>The documentation in its current state is targeted at developers who have |
| already some experience with OpenOffice.org API and with some other programming |
| language (Java/C++/StarBasic). It is recommended that you read that some |
| background information from the |
| <a href="http://api.openoffice.org/DevelopersGuide/DevelopersGuide.html"> |
| developer manual</a> before looking at the specifics of python. |
| |
| <h2 id="tutorial"> PyUNO tutorial for OpenOffice.org </h2> |
| This tutorial shows, how the PyUNO bridge |
| can be used to automate OpenOffice.org. This is not an OpenOffice.org tutorial, |
| there is lots of resources available in the office development kit and |
| <a href="http://api.openoffice.org/DevelopersGuide/DevelopersGuide.html"> |
| the developer manual</a>. |
| |
| <h3 id="install"> PyUNO Installation </h3> |
| Since OpenOffice1.1, PyUNO is included in the default installation. |
| |
| <h3 id="modes"> PyUNO bridge modes </h3> |
| |
| <p>PyUNO can be used in three different modes: |
| |
| <ol> |
| <li><a href="scriptingframework/index.html"> Inside the OpenOffice.org process</a> |
| within the scripting framework (OOo 2.0 and later only !!), |
| |
| |
| <li> Inside the python executable (and outside the OOo process) |
| |
| <center><img src="images/mode_ipc.png" alt="Python ipc mode"></img></center> |
| |
| <p> Use this mode, when you |
| <ul> |
| <li> begin to use PyUNO (as it is the more intuitive approach). |
| <li> want to trigger script execution by starting a separate process (e.g. a cgi-script |
| within a http-server). |
| <li> want the shortest turnaround times (code - execute - code - execute ...) |
| |
| </ul> |
| |
| <h4> Hello World </h4> |
| <p>Make sure, that OpenOffice.org is not running (note that on windows you must also terminate |
| the quick starter in the system tray at the right bottom of your desktop). |
| Start a system shell ( cmd on Win NT/2000/XP, command on Win9x, tcsh or bash on |
| Unix). Switch to the Office program directory |
| (e.g. C:\Program Files\OpenOffice.org1.1\program ) and start the office with the |
| following command line parameters |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| |
| c:\Program Files\OpenOffice1.1\program> soffice "-accept=socket,host=localhost,port=2002;urp;" |
| |
| </pre></td></tr></table> |
| <p> |
| |
| Now use your favourite text editor |
| to create the following hello_world.py sample program: |
| |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import socket # only needed on win32-OOo3.0.0 |
| import uno |
| |
| # get the uno component context from the PyUNO runtime |
| localContext = uno.getComponentContext() |
| |
| # create the UnoUrlResolver |
| resolver = localContext.ServiceManager.createInstanceWithContext( |
| "com.sun.star.bridge.UnoUrlResolver", localContext ) |
| |
| # connect to the running office |
| ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" ) |
| smgr = ctx.ServiceManager |
| |
| # get the central desktop object |
| desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx) |
| |
| # access the current writer document |
| model = desktop.getCurrentComponent() |
| |
| # access the document's text property |
| text = model.Text |
| |
| # create a cursor |
| cursor = text.createTextCursor() |
| |
| # insert the text into the document |
| text.insertString( cursor, "Hello World", 0 ) |
| |
| # Do a nasty thing before exiting the python process. In case the |
| # last call is a oneway call (e.g. see idl-spec of insertString), |
| # it must be forced out of the remote-bridge caches before python |
| # exits the process. Otherwise, the oneway call may or may not reach |
| # the target object. |
| # I do this here by calling a cheap synchronous call (getPropertyValue). |
| ctx.ServiceManager |
| </pre></td></tr></table> |
| |
| <p> |
| Now start the above script with the python script located in the program directory |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| |
| c:\Program Files\OpenOffice1.1\program> .\python hello_world.py |
| </pre></td></tr></table> |
| |
| <font size="-1"><strong>Note:</strong> You must use the script/batch file in the |
| program directory to start python, simply starting the python executable |
| in the runtime directory (or from python installation installed somewhere else |
| on your machine) will not work. |
| </font><br/> |
| |
| <p>This scripts prints "Hello World" into the current writer document.</p> |
| |
| <li><p>Inside the OpenOffice.org (OOo) process</p> |
| |
| <center><img src="images/mode_component.png" alt="Python mode component"></img></center> |
| <p> Use this mode, when |
| |
| <ul> |
| <li> you want to easily roll out your code to multiple other machines (using UNO packages) |
| <li> your scripts shall get triggered by UI events (menu or toolbars) |
| <li> you have collected some experience with PyUNO |
| <li> you want your script to run with the best performance |
| </ul> |
| |
| <h4>Hello World</h4> |
| The above Hello World example is now recoded as a python UNO component, which means, that the |
| code that does the insertion needs to be embedded in a python class. Additionally, the |
| connecting-to-the-office-code needs to be replaced by a distinct entry point, which is |
| used by the python loader to instantiate the python class. |
| |
| <p> |
| <code>hello_world_comp.py:</code> |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import uno |
| import unohelper |
| |
| from com.sun.star.task import XJobExecutor |
| |
| # implement a UNO component by deriving from the standard unohelper.Base class |
| # and from the interface(s) you want to implement. |
| class HelloWorldJob( unohelper.Base, XJobExecutor ): |
| def __init__( self, ctx ): |
| # store the component context for later use |
| self.ctx = ctx |
| |
| def trigger( self, args ): |
| # note: args[0] == "HelloWorld", see below config settings |
| |
| # retrieve the desktop object |
| desktop = self.ctx.ServiceManager.createInstanceWithContext( |
| "com.sun.star.frame.Desktop", self.ctx ) |
| |
| # get current document model |
| model = desktop.getCurrentComponent() |
| |
| # access the document's text property |
| text = model.Text |
| |
| # create a cursor |
| cursor = text.createTextCursor() |
| |
| # insert the text into the document |
| text.insertString( cursor, "Hello World", 0 ) |
| |
| # pythonloader looks for a static g_ImplementationHelper variable |
| g_ImplementationHelper = unohelper.ImplementationHelper() |
| |
| # |
| g_ImplementationHelper.addImplementation( \ |
| HelloWorldJob, # UNO object class |
| "org.openoffice.comp.pyuno.demo.HelloWorld", # implementation name |
| # Change this name for your own |
| # script |
| ("com.sun.star.task.Job",),) # list of implemented services |
| # (the only service) |
| </pre></td></tr></table> |
| |
| <p> The code needs to be linked to a user event. This can be done e.g. with the |
| following configuration settings : |
| |
| |
| <p> <code>Addons.xcu:</code> |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| <?xml version="1.0" encoding="UTF-8"?> |
| <oor:node xmlns:oor="http://openoffice.org/2001/registry" |
| xmlns:xs="http://www.w3.org/2001/XMLSchema" |
| oor:name="Addons" oor:package="org.openoffice.Office"> |
| <node oor:name="AddonUI"> |
| <node oor:name="AddonMenu"> |
| <node oor:name="org.openoffice.comp.pyuno.demo.HelloWorld" oor:op="replace"> |
| <prop oor:name="URL" oor:type="xs:string"> |
| <value>service:org.openoffice.comp.pyuno.demo.HelloWorld?insert</value> |
| </prop> |
| <prop oor:name="ImageIdentifier" oor:type="xs:string"> |
| <value>private:image/3216</value> |
| </prop> |
| <prop oor:name="Title" oor:type="xs:string"> |
| <value xml:lang="en-US">Insert Hello World</value> |
| </prop> |
| </node> |
| </node> |
| </node> |
| </oor:node> |
| </pre></td></tr></table> |
| |
| <p>Both files must be packaged up into a single zip file by using your |
| favourite zip utility, e.g. infozip.</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| zip hello_world.zip Addons.xcu hello_world_comp.py |
| adding: Addons.xcu (deflated 55%) |
| adding: hello_world_comp.py (deflated 55%) </pre></td></tr></table> |
| |
| <p>This package can then be deployed into an OpenOffice.org installation using |
| the |
| <code>pkgchk</code> tool, which is located in the OOo program directory. Note, |
| that the office must have been stopped before installing the package.</p> |
| <p> |
| <font size="-1"><strong>Note:</strong> Make sure, that the PYTHONPATH |
| environment variable is NOT set when you start pkgchk or soffice |
| (see <a href="http://www.openoffice.org/issues/show_bug.cgi?id=17339">#i17339#</a>). |
| This may require, that you create a batch file for soffice on windows, |
| unset PYTHONPATH in the system configuration or always start soffice from the |
| shell with set PYTHONPATH= (windows) or unsetenv PYTHONPATH (Unix tcsh shell). |
| |
| </font> |
| |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| c:\Program Files\OpenOffice.org1.1\program> pkgchk hello_world.zip |
| c:\Program Files\OpenOffice.org1.1\program> |
| </pre></td></tr></table> |
| <p>On success no output is given by the tool. When OpenOffice.org starts |
| there is a new menu entry (see |
| <code>Tools/Additional Components/Insert Hello World</code>).</p> |
| |
| </ol> |
| As you have seen, the core script lines are identical, but the ways to |
| retrieve the office component context differ. |
| |
| <h3 id="examples"> Examples </h3> |
| |
| <ul> |
| <li><p><a href="samples/ooextract.py">ooextract.py</a> <br/> |
| A command line tool, that extracts the text, html or pdf content from a |
| StarWriter document and writes it to a different file or (optionally) |
| prints it to stdout (grep your office documents).</p> |
| |
| <li><p><a href="samples/oomerge.py">oomerge.py</a> <br/> |
| A command line tool, that creates a new document by appending multiple |
| single documents</p> |
| |
| <li><p><a href="samples/swriter.py">swriter.py</a><br/> |
| A command line program, that fills a writer document with some text and |
| tables.</p> |
| <li> <a href="samples/swritercomp.py">swritercomp.py</a>, |
| <a href="samples/swritercompclient.py">swritercompclient.py</a> <br/> |
| Same as above, but implemented as a python UNO component, so that it |
| runs within the office process. This shows the performance benefit |
| of having scripts run within one process. |
| |
| <p> You must add the swritercomp.py program with the pkgchk tool (see below) |
| to the office installation and can then use the swritercomp_client.py |
| program to execute it. |
| |
| <li><p><a href="samples/biblioaccess.py">biblioaccess.py</a><br/> |
| A command line program, that displays the contents of the biblio sample |
| database that comes with OpenOffice.org.</p> |
| <li><p><a name="calc-addin" href="samples/python-tokencounter-calc-addin.oxt">python-tokencounter-calc-addin.oxt</a><br> |
| Adds a function named <pre>tokencount</pre> to calc, which counts the number of words within a calc cell. |
| After adding the extension, the office must be restarted (including terminating the quickstarter) to make the function appear |
| in the function list. |
| |
| <li> Your example (Please send more examples, so that they can be added here). |
| </ul> |
| |
| <h2 id="binding"> UNO Language binding </h2> |
| In the following you find the full description about how UNO features are mapped to the |
| python language. |
| |
| <h3 id="mapping"> UNO Type mapping </h3> |
| |
| <table border> |
| <tr> |
| <th>IDL datatype</th> |
| <th>representation in python</th> |
| </tr> |
| <tr class="tableF0"> |
| <td valign="top"> integer types (byte, short, unsigned short, |
| long, unsigned long, hyper, unsigned hyper |
| </td> |
| <td> |
| Python internally knows only the C datatypes long and long long as integer types. |
| On most machines, a long is a 32 bit value while long long is a 64 bit value. |
| |
| <ul> |
| <li> Values coming from UNO (for instance the return value of a UNO method) |
| <p> |
| Values which have the type byte, short, unsigned short, long or unsigned long |
| are converted to a python long value. Values which have the type hyper or unsigned |
| hyper are converted to a python long long. |
| |
| <li> Values going to UNO (for instance the argument of a UNO method) |
| <p> If there is a concrete type in the idl method signature, the |
| value is converted to the concrete type (in fact the invocation service |
| does this work). |
| |
| If the method signature just has an any, every integer value is converted |
| to the smallest data type, where the value fits into and send to the UNO object |
| ( so 5 becomes a byte, 150 becomes a short, 0x1f023 becomes a long and values |
| larger than 0xffffffff become a hyper. |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top">boolean</td> |
| <td>Python internally has a boolean data type, which is derived from the |
| integer type ( see |
| <a href="http://python.org/peps/pep-0285.html"> |
| http://python.org/peps/pep-0285.html |
| </a> ). There exists the singletons <code>True</code> and |
| <code>False</code>, which pyuno uses to distinguish between integers |
| and boolean values. |
| |
| |
| <p> As long as a boolean is specified in the interface method signature, |
| you may also use numbers. In the following example, all calls are valid: |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| #idl signature void takeBool( [in] boolean bool ) |
| |
| unoObject.takeBool( 1 ) # valid, passing true (PyUNO runtime |
| # does the conversion |
| unoObject.takeBool( True) ) # valid, passing true |
| unoObject.takeBool( False ) # valid, passing false |
| </pre></td></tr></table> |
| |
| <p>However, when you want to explicitly pass a boolean, where only |
| an any is specified, you <strong>must</strong> use <code>True</code> |
| or <code>False</code>.</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # idl signature void foo( [in] any value ) |
| |
| # implementation expects a boolean (which is separately documented |
| # e.g. in the service specification. |
| unoObject.foo( True ) # valid, pass a true |
| unoObject.foo( 1 ) # bad, just passing a 1, implementation will |
| # probably not be able to deal with it correctly. |
| </pre></td></tr></table> |
| |
| |
| |
| <p> |
| Note: There also exists the uno.Bool class, which has been deprecated since |
| pyuno 0.9.2, but still supported. Don't use it anymore. |
| |
| |
| <tr> |
| <td valign="top"> string</td> |
| <td><p>In general, the string is mapped to the python Unicode string. However, |
| you may pass an |
| 8 bit python string where a UNO string is expected, the bridge converts the |
| 8 bit string to a Unicode string using the system locale.</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # idl signature foo( [in] string value ) |
| # both lines are valid |
| unoObject.foo( u'my foo string' ) |
| unoObject.foo( 'my foo string' ) |
| </pre></td></tr></table> |
| </td> |
| </tr> |
| |
| <tr> |
| <td valign="top">char</td> |
| <td> |
| <p>A char is mapped to a <code>uno.Char</code>. It has a public Unicode string member <code>value</code> |
| with length 1 containing the Unicode char.</p> |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # idl signature foo( [in] char c) |
| unoObject.foo( uno.Char( u'h' ) ) #valid |
| unoObject.foo( 'h' ) #wrong |
| </pre></td></tr></table> |
| </td> |
| </tr> |
| |
| <tr> |
| <td valign="top">enum</td> |
| <td>A concrete enum value is represented by an instance of the class <code>uno.Enum</code>. It has |
| two members, <code>typeName</code> is a string containing the name of the enum type and |
| <code>value</code> contains the value of the enum. |
| |
| <p>You may create concrete enum values in two ways |
| <ol> |
| <li> (suggested) by importing<br/> |
| |
| <code>from <i>enumname</i> import <i>enumvalue</i></code>. |
| |
| <p>For example:</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| from com.sun.star.uno.TypeClass import UNSIGNED_LONG |
| . |
| . |
| . |
| unoObject.setValue( UNSIGNED_LONG ) |
| if unoObject.getValue() == UNSIGNED_LONG: |
| . |
| . |
| </pre></td></tr></table> |
| |
| <li> (in rare situations)<br/> |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import uno |
| |
| unoObject.setValue( uno.Enum( "com.sun.star.uno.TypeClass", "UNSIGNED_LONG") ) |
| if unoObject.getValue() == uno.Enum( "com.sun.star.uno.TypeClass", "UNSIGNED_LONG"): |
| . |
| . |
| . |
| </pre></td></tr></table> |
| </ol> |
| |
| The first solution has the advantage, that a misspelled enum name already leads to a |
| RuntimeException, when the python source file is imported. |
| </td> |
| |
| |
| <tr> |
| <td valign="top">type</td> |
| <td> A type is mapped to a <code>uno.Type</code>. It has public members typeName (string) and |
| typeClass (enum value of com.sun.star.uno.TypeClass). |
| There exists a function uno.getTypeByName() to easily |
| create a type instance, the functions raises a RuntimeException in case the |
| type is unknown. |
| |
| |
| <p>You may create concrete type values in two ways |
| <ol> |
| <li> (suggested) by importing<br/> |
| |
| <code>from <i>module-where-type-lives-in</i> import <i>typeOfTypeName</i></code>. |
| |
| <p>For example to create XComponent's type, use</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| from com.sun.star.lang import typeOfXComponent |
| . |
| . |
| . |
| unoObject.setType( typeOfXComponent ) |
| if unoObject.getType() == typeOfXComponent: |
| . |
| . |
| </pre></td></tr></table> |
| |
| <li><p>(in rare situations, e.g. for types of simple values)</p> |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import uno |
| |
| unoObject.setType( uno.getTypeByName( "com.sun.star.uno.XComponent" ) ) |
| if unoObject.getType() == uno.getTypeByName( "com.sun.star.uno.XComponent"): |
| . |
| . |
| . |
| </pre></td></tr></table> |
| </ol> |
| </td> |
| </tr> |
| |
| <tr> |
| <td valign="top">struct (and exception)</td> |
| <td> |
| For each UNO struct (or exception), a new python class is generated on the fly. It |
| is guaranteed, that there is only one instance of the struct (or exception) class per |
| python interpreter instance. The generated class does reflect the inheritance |
| hierarchy of the concrete UNO type (e.g. important for exception handling, see below). |
| |
| <p> |
| One can generate a struct class by using the import mechanism. An instance of |
| a struct can then be instantiated by using the python constructor. The constructor |
| supports zero arguments (members get default constructed), 1 argument which the |
| same type (copy constructor), and n arguments, where n is the number of |
| elements of the concrete struct. The struct supports the equality operator, |
| two structs are equal, if they are of the same type and each member is equal. |
| |
| <p> |
| Example: |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| from com.sun.star.beans import PropertyValue |
| from com.sun.star.uno import Exception,RuntimeException |
| |
| propVal = PropertyValue() # Default constructor |
| propVal.Name = "foo" |
| propVal.Value = 2 |
| |
| if propVal == PropertyValue( "foo", 2 ): # Memberwise constructor |
| # true ! |
| pass |
| |
| if propVal == PropertyValue( propVal ): # Copy Constructor |
| # true |
| |
| |
| </pre></td></tr></table> |
| |
| An instance of a UNO struct can be initially constructed with the |
| function <code>uno.createUnoStruct()</code> and passing the name of the struct |
| as the first parameter and optional constructor arguments (see above for |
| an example of possible ctors). |
| |
| <p> |
| ATTENTION: In UNO, structs have value semantic, however the handling in python |
| does not reflect this. When a struct gets passed |
| as a parameter to a function, the values are passed to the callee. Later |
| modification of the struct instance does not influence the callee anymore. |
| |
| However, simply assigning a struct to another local variable does not |
| create a copy, but simply creates an alias to the original instance. |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| struct = uno.createUnoStruct( "com.sun.star.beans.PropertyValue" ) |
| |
| struct.Name = "foo" |
| struct2 = struct |
| struct2.Name = "python" # modifies also struct, probably not desired ! |
| unoObject.call( struct, struct2 ) # passes the same struct 2 times ! |
| |
| struct.Name = "doobidooo" # even worse style. If the UNO object is implemented |
| # in python, you possibly modify the callee's value. |
| # Don't do this ! |
| </pre></td></tr></table> |
| |
| |
| </td> |
| </tr> |
| |
| <tr> |
| <td valign="top">sequence</td> |
| <td>A sequence is in general mapped to a python tuple. A python list is not (!) |
| accepted. |
| |
| |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # idl signature XInterface createInstanceWithArguments( |
| # [in] string servicename, [in] sequence <any> ) |
| doc = smgr.createInstanceWithArguments( "foo.service", ("arg1",2)) |
| </pre></td></tr></table> |
| |
| <p><strong>Attention (since 0.9.2):</strong> The idl <code> |
| sequence<byte></code> is mapped to the class <code>uno.ByteSequence</code>. |
| It has a string member named <code>value</code>, which holds the data of the byte sequence. |
| As the bytesequence most often is a container for binary data, this class allows to handle |
| binaries efficiently. This also embeds pyuno nicely into python, as python keeps binary |
| data in strings. For example:</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # idl signature writeBytes( [in] sequence%lt; byte > data ) |
| # |
| out.writeBytes( uno.ByteSequence( "abc" ) ) |
| |
| # you could also write the following |
| begin = uno.ByteSequence( "ab" ) |
| out.writeBytes( begin + "c" ) |
| |
| # but this does not work ! |
| out.writeBytes( "abc" ) # ERROR, no implicit conversion supported by the runtime ! |
| |
| |
| # idl signature long readBytes( [out] sequence<byte> , [in] length ) |
| len,seq = in.readBytes( dummy, 3 ) |
| |
| # the statements do the same thing |
| print seq == "abc": |
| print seq == uno.ByteSequence( "abc" ) |
| </pre></td></tr></table> |
| |
| </td> |
| </tr> |
| |
| <tr> |
| <td valign="top">constants</td> |
| <td>An UNO idl constant can be given by the following ways: |
| |
| <ol> |
| <li> Use the concrete value specified in the idl file<br/> |
| A constant is its value and only its value. As modification of the constant values is incompatible, |
| one may simply rely on the values. |
| <li> (suggested) Use the import mechanism to create variable with the constant name<br/> |
| This solution is the most readable one. |
| <li> Use <code>uno.getConstantByName()</code><br/> |
| Might be useful from time to time. Function raises a RuntimeException in case the constant is unknown. |
| </ol> |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| from com.sun.star.beans.PropertyConcept import ATTRIBUTES |
| . |
| . |
| . |
| # the following 3 lines are equivalent |
| unoObject.setConcept( ATTRIBUTES ) |
| unoObject.setConcept( 4 ) |
| unoObject.setConcept( uno.getConstantByName( "com.sun.star.beans.PropertyConcept.ATTRIBUTES" ) ) |
| </pre></td></tr></table> |
| |
| </td> |
| </tr> |
| |
| |
| <tr> |
| <td valign="top">any</td> |
| <td>In general, the python programmer does not come into touch with anys. At all places |
| where anys appear in method signatures, the python programmer can simply pass a concrete |
| value. Consequently, return values or out parameters also never contain a concrete any. |
| |
| <p> |
| However, there are certain circumstances, where a python programmer may want to pass a concrete |
| typed value to a callee (note, this is only possible for 'bridged' calls, you can't pass |
| a typed any to another python uno object). |
| |
| <p> You can create a <code>uno.Any()</code> by passing the type (as typename or as uno.Type) and the |
| value. |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # constructs a uno.Any, that contains a byte |
| byteAny = uno.Any( "byte" , 5 ) |
| |
| # constructs a sequences of shorts |
| byteAny = uno.Any( "[]short", (4,5)) |
| </pre></td></tr></table> |
| |
| <p> These anys can only be used in conjunction with the <code>uno.invoke</code>, which allows |
| to invoke a method on an arbitrary UNO object with a typed any. |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # the normal call |
| uno.setPropertyValue( "foo", (4,5)) |
| |
| # the uno.invoke call |
| uno.invoke( obj, "setPropertyValue" , ("foo",uno.Any( "[]short", (4,5))) ) |
| </pre></td></tr></table> |
| |
| When obj is a bridged object, the callee gets the sequence as a <code>sequence<short></code>. |
| When obj is a local python object, it gets simply the <code>(4,5)</code> as it would have |
| got it with the normal call. |
| <p> |
| NOTE: There is currently a bug in pyuno (see <a href="http://www.openoffice.org/issues/show_bug.cgi?id=31159">#i31159#</a>), which does not let |
| you fill anys into structs (e.g. a PropertyValue struct contains an any). You can workaround |
| this with the following code sample: |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import uno |
| ctx = uno.getComponentContext() |
| class MagicTransformer: |
| def __init__( self , ctx ): |
| self.inv = ctx.ServiceManager.createInstanceWithContext( |
| "com.sun.star.script.Invocation", ctx ) |
| self.insp = ctx.ServiceManager.createInstanceWithContext( |
| "com.sun.star.beans.Introspection", ctx ) |
| def transform( self, struct , propName, value ): |
| myinv = self.inv.createInstanceWithArguments( (struct,) ) |
| access = self.insp.inspect( myinv ) |
| method = access.getMethod( "setValue" , -1 ) |
| uno.invoke( method, "invoke", ( myinv, ( propName , value ) )) |
| method = access.getMethod( "getMaterial" , -1 ) |
| ret,dummy = method.invoke(myinv,() ) |
| return ret |
| |
| transformer = MagicTransformer( ctx ) |
| |
| # by default, the 100 becomes a byte |
| special = PropertyValue("TabStopPosition",0,100,DIRECT_VALUE) |
| print "before" + str(special) |
| |
| # however, we want the 100 to be a int32 (which is a long in UNO idl) |
| special = transformer.transform( special, "Value" , uno.Any( "long", 100 ) ) |
| print "after" + str(special) |
| </pre></td></tr></table> |
| |
| The script gives you the following output:<br/> |
| before(com.sun.star.beans.PropertyValue){ Name = (string)"TabStopPosition", Handle = (long)0x0, Value = (any){ (<strong>byte</strong>)0x64 }, State = (com.sun.star.beans.PropertyState)DIRECT_VALUE }<br/> |
| after(com.sun.star.beans.PropertyValue){ Name = (string)"TabStopPosition", Handle = (long)0x0, Value = (any){ (<strong>long</strong>)0x64 }, State = (com.sun.star.beans.PropertyState)DIRECT_VALUE }<br/> |
| |
| </td> |
| </tr> |
| |
| </table> |
| |
| <h3 id="objects"> Implementing UNO objects </h3> |
| |
| One may use python classes to implement UNO objects. Instances of a python class may then |
| be passed as argument to UNO calls where anys or concrete interfaces are specified. |
| |
| <p> |
| To be an UNO object, a python class MUST implement the com.sun.star.lang.XTypeProvider |
| interface by implementing two methods getTypes() and getImplementationId(), |
| which inform the python-UNO bridge, |
| which concrete UNO interfaces the python class implements. The getTypes() function |
| defines, which interfaces are implemented by the class. |
| |
| <p> |
| To make this easier, there exists a <code>unohelper.Base</code> class, where |
| a python UNO object should derive from. You can then implement a UNO interface |
| simply by deriving from the wanted interfaces. The following example |
| implements a com.sun.star.io.XOutputStream, which stores |
| all data written into the stream within a ByteSequence. (Note that this is |
| quite a poor implementation, which is just for demonstration purposes). |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import unohelper |
| from com.sun.star.io import XOutputStream |
| class SequenceOutputStream( unohelper.Base, XOutputStream ): |
| def __init__( self ): |
| self.s = uno.ByteSequence("") |
| self.closed = 0 |
| |
| def closeOutput(self): |
| self.closed = 1 |
| |
| def writeBytes( self, seq ): |
| self.s = self.s + seq |
| |
| def flush( self ): |
| pass |
| |
| def getSequence( self ): |
| return self.s |
| |
| </pre></td></tr></table> |
| |
| From the list of base classes given (here only XOutputStream), |
| the unohelper.Base implementation correctly implements the XTypeProvider interface. |
| |
| |
| <h3 id="components"> Implementing Python UNO components </h3> |
| |
| <p>There exists a loader for python components. It allows to create instances of |
| python classes not just within the python process but in every arbitrary UNO process |
| including OpenOffice.org. The python loader loads the python runtime on demand if |
| it is not already loaded and executes python code within the root python interpreter. |
| |
| <p> If the reader is unfamiliar with the component registration process, it should |
| visit the OpenOffice.org developer manual for a comprehensive explanation. |
| |
| <p> The python loader currently supports the following protocols |
| for incoming urls : |
| |
| <table border> |
| <tr> |
| <th> Protocol name</th> |
| <th> Description</th> |
| </tr> |
| |
| <tr> |
| <td valign="top">vnd.openoffice.pymodule</td> |
| <td>The protocol dependent part is interpreted as a python module name, which is imported |
| using the common python import mechanism (which uses the PYTHONPATH environment variable). |
| <p> |
| Example: <code>vnd.openoffice.pymodule:MyPythonComponent</code><br/> |
| Using this url e.g. in XLoader.activate() will try to load a MyPythonComponent.py file |
| from directories, which are listed within the PYTHONPATH environment/bootstrap variable. |
| Note that you must not use the .py suffix here. |
| |
| <p> The given module is added to the <code>sys.modules</code> hash map. |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> file</td> |
| <td> A <strong>mandatory absolute</strong> file url to a python component file. |
| The file itself does not need to be contained within PYTHONPATH, but it may |
| only import files, which are contained within PYTHONPATH. |
| |
| The module is <strong>not added</strong> to <code>sys.modules</code>. |
| <p> |
| Example: <code>file:///path/to/MyPythonComponent.py</code> |
| |
| <p>Since OOo 2.4.x, you can import self written python files from your component |
| (see the <a href="#multiple_source_files"> multiple source file chapter </a>) |
| |
| |
| </td> |
| </tr> |
| |
| <tr> |
| <td valign="top"> vnd.sun.star.expand</td> |
| <td>The python loader supports the common macro expansion mechanisms as the Java or |
| C++ loader does. |
| <p> |
| Example: <code>vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/MyPythonComponent.py</code> |
| </td> |
| </tr> |
| |
| </table> |
| <p> |
| After the module has been imported, the python loader looks for a module-global variable |
| with the name <code>g_ImplementationHelper</code>, which is expected to be an instance |
| of <code>unohelper.ImplementationHelper</code>. |
| |
| |
| The following sample code makes a uno component out of the above UNO object |
| ( note that the component is not useful, because there is no UNO method to retrieve |
| the tuple nor does a com.sun.star.io.OutputStream service specification exist, it's just here |
| as an example). |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import unohelper |
| from com.sun.star.io import XOutputStream |
| |
| g_ImplementationHelper = unohelper.ImplementationHelper() |
| |
| class TupleOutputStream( unohelper.Base, XOutputStream ): |
| # The component must have a ctor with the component context as argument. |
| def __init__( self, ctx ): |
| self.t = () |
| self.closed = 0 |
| |
| # idl void closeOutput(); |
| def closeOutput(self): |
| self.closed = 1 |
| |
| # idl void writeBytes( [in] sequence<byte>seq ); |
| def writeBytes( self, seq ): |
| self.t = self.t + seq # simply add the incoming tuple to the member |
| |
| # idl void flush(); |
| def flush( self ): |
| pass |
| |
| # convenience function to retrieve the tuple later (no UNO function, may |
| # only be called from python ) |
| def getTuple( self ): |
| return self.t |
| |
| # add the TupleOutputStream class to the implementation container, |
| # which the loader uses to register/instantiate the component. |
| g_ImplementationHelper.addImplementation( \ |
| TupleOutputStream,"org.openoffice.pyuno.PythonOutputStream", |
| ("com.sun.star.io.OutputStream",),) |
| </pre></td></tr></table> |
| |
| Lets assume, that this code is stored in a file named tuplestrm.py and the |
| file exists somewhere within the PYTHONPATH variable, it can be registered |
| to an OO1.1beta build with the following command : |
| |
| <p> |
| <code> regcomp -register -br types.rdb -br services.rdb -r services.rdb -c vnd.openoffice.pymodule:tuplestrm</code> |
| |
| <p> You can of course also use the <code>pkgchk</code> tool as explained in the tutorial chapter with |
| <p> |
| <code> pkgchk tuplestrm.py </code> |
| <p>, but note, that this command creates a copy of the file (when the script changes,it must be |
| redeployed using the above command). |
| |
| <p> The component can be instantiated e.g. from OpenOffice.org Basic with |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| tupleStrm = createUnoService( "com.sun.star.io.OutputStream" ) |
| tupleStrm.flush() |
| </pre></td></tr></table> |
| |
| |
| <h3 id="outparas"> Out parameter handling </h3> |
| |
| <p>UNO out parameters are handled through the python multiple return value |
| feature. For |
| pure outparameters, a dummy <code>None</code> value should be used as a place holder. |
| This is best explained with an example. |
| |
| Lets' assume we have the following IDL method spec |
| |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| long foo( [in] long first, [inout] long second, [out] third ) |
| </pre></td></tr></table> |
| |
| <p>A python UNO object implements such a method the following way:</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| class Dummy( XFoo ): |
| def foo( self, first,second,third): |
| # Note: the value of third is always None, but it must be there |
| # as a placeholder if more args would follow ! |
| return first,2*second,second + first |
| </pre></td></tr></table> |
| |
| then such a method would be called from python the following way |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| ret,second,third = unoObject.foo( 2, 5 , None ) |
| print ret,second,third # results into 2,10,7 |
| </pre></td></tr></table> |
| |
| <p>This also emphasizes, that out-parameters are quite close to multiple return |
| values (though the semantic association of a inout parameter gets lost).</p> |
| |
| <p>However, note that</p> |
| |
| <ul> |
| <li> you must have the correct number of return values either in the calling and |
| implementing code, otherwise you will get a <code>RuntimeException</code> during the call. |
| <li> a void method always returns a <code>None</code> followed by possible |
| out parameters, so when you have a void method with one out parameter |
| you must assign the output to two variables (though the first one |
| will always be None). |
| <li> a python object implementing a void method with out parameters MUST always |
| return <code>None</code> as the first parameter. |
| |
| </ul> |
| |
| <h3 id="exception"> Exception handling </h3> |
| The Python-UNO bridge uses the common Python exception handling mechanism. For every |
| UNO exception, a concrete exception class is generated on the fly (see above type mapping |
| table for an explanation how to do this). |
| |
| <p> |
| Example for catching |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| from com.sun.star.uno import RuntimeException |
| from com.sun.star.lang import IllegalArgumentException |
| from com.sun.star.connection import NoConnectException |
| try: |
| uuresoler.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" ) |
| except NoConnectException e: |
| print "The OpenOffice.org process is not started or does not listen on the resource ("+e.Message+")" |
| except IllegalArgumentException e: |
| print "The url is invalid ( "+ e.Message+ ")" |
| except RuntimeException e: |
| print "An unknown error occurred: " + e.Message |
| </pre></td></tr></table> |
| |
| <p>Example for throwing</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| from com.sun.star.io import IOException |
| class TupleOutputStream(XOutputStream,unohelper.Base): |
| def writeBytes( self, seq ): |
| if self.closed: |
| raise IOException( "Output stream already closed", self ) |
| self.t = self.t + seq |
| </pre></td></tr></table> |
| |
| <h3 id="current_context"> current context support </h3> |
| NEW SINCE OOo 2.0.2 |
| <p>pyuno supports the <a href="http://udk.openoffice.org/common/man/concept/uno_contexts.html">uno current context concept</a>. There exist the functions |
| uno.getCurrentContext() und uno.setCurrentContext( newContext ). |
| |
| <p>Furthermore, there exists a class unohelper.CurrentContext. The constructor |
| accepts a hashmap with name/value pairs and the former context for delegation. |
| |
| Usage pattern: |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| oldContext = uno.getCurrentContext() |
| try: |
| uno.setCurrentContext( |
| unohelper.CurrentContext( oldContext,{"My42":42}) ) |
| |
| # ... do some uno calls, which may interpret the "My42" |
| finally: |
| uno.setCurrentContext( oldContext ) |
| </pre></td></tr></table> |
| (Note, the oldContext may also be None). |
| |
| <h3 id="helper"> unohelper module </h3> |
| |
| <p>The unohelper.py module contains some extra functions/classes, which |
| are nice to use with pyuno, but not mandatory. This paragraph lists |
| some of the unohelper.py features. |
| <table border> |
| <tr> |
| <td> |
| def <code>systemPathToFileUrl( systemPath )</code> |
| </td> |
| <td> |
| Returns a file-url for the given system path. Most of the OOo API functions |
| expect a file-url, while the python runtime functions in general only work |
| with system paths. The function is implemented using the core C function |
| <code>osl_getFileUrlFromSystemPath()</code>. |
| </td> |
| </tr> |
| <tr> |
| <td> def <code> fileUrlToSystemPath( url )</code></td> |
| <td>Returns a system path (determined by the system, the python interpreter |
| is running on). Most OOo function return a file-url, while most python |
| runtime functions expect system paths. The function is implemented by |
| using the core <code>osl_getSystemPathFromFileUrl()</code> function. |
| </td> |
| </tr> |
| <tr> |
| <td> |
| def <code> absolutize( path, relativeUrl )</code> |
| </td> |
| <td> |
| Returns an absolute file url from a given, mandatory absolute, directory url |
| and a relative file url, which may be absolute or relative (which includes |
| e.g. <code>../</code> parts. The function is implemented by using the core |
| <code>osl_getAbsolutePathFromFileUrl()</code> function. |
| </td> |
| </tr> |
| |
| <tr> |
| <td> |
| def addComponentsToContext( |
| toBeExtendedContext, |
| contextRuntime, |
| componentUrls, |
| loaderName ) |
| </td> |
| <td> |
| This functions adds a tuple of component urls |
| to the <code> |
| toBeExtendedContext</code> using the <code>contextRuntime</code> to |
| instantiate the loader loaderName and some other services needed for this |
| task. After completing the function, all services within these components |
| can be instantiated as long as the <code>toBeExtendedContext</code> is |
| not disposed. The changes are not made persistent. |
| </td> |
| </tr> |
| |
| <tr> |
| <td> |
| def <code> inspect( unoobject, file )</code> |
| </td> |
| <td> |
| Dumps the typeinformation about the given UNO object into a file |
| (in fact, file needs to be an instance of a class, that implements |
| a write method). |
| |
| The typeinformation include implementation name, supported services, |
| supported interfaces, supported methods and supported properties. |
| </td> |
| </tr> |
| |
| |
| </table> |
| |
| |
| <h3 id="logging"> Logging </h3> |
| NEW SINCE OOo 2.0.2 |
| |
| <p> |
| The pyuno bridge can now log every call bridged between python and uno. This |
| may be a useful help when you need to debug or profile your code. There are |
| two environment variables, which activate logging: |
| |
| <table border> |
| |
| <tr> |
| <td> PYUNO_LOGLEVEL </td> |
| <td> |
| Valid values are |
| <ul> |
| <li> NONE - nothing is logged |
| <li> CALL - the method name of every call is logged |
| <li> ARGS - additionally, the arguments of every call are logged |
| </ul> |
| NONE is default |
| </td> |
| </tr> |
| |
| <tr> |
| <td> PYUNO_LOGTARGET </td> |
| <td> |
| <ul> |
| <li> stdout - logs to stdout (doesnt work on windows within OpenOffifce.org) |
| <li> stderr - logs to stderr (doesnt work on windows within OpenOffifce.org) |
| <li> file-url-prefix(relative urls allowed) - logs to files, which start with this string. |
| The pid of the process is appended to the string (e.g. |
| file:///c:/temp/bla will write to c:\temp\bla.235 |
| if 235 is the pid of the current process) |
| </ul> |
| </td> |
| </tr> |
| </table> |
| |
| <h3 id="multiple_source_files"> (Since OOo 2.4) Implementing UNO components with multiple source files</h3> |
| Before the pythonloader tries to load a new python unocomponent, it looks |
| beside the uno component for a file with the |
| name <em>pythonpath.zip</em> or a directory named <em>pythonpath</em> . If it exists, it puts it into sys.path (if it is not |
| already in there) and then tries to load |
| the given component. Note, that the unocomponent file itself is not within PYTHONPATH and thus cannot be reimported |
| by other modules. |
| |
| <p> |
| This now means that python uno components can be implemented with an arbirtrary number of python source |
| files which can be deployed/undeployed via the uno package mechanism. It also means, that you can now use |
| the unohelper.Base implementation even if you have defined your own interface types (by <em>lazy loading</em> |
| the new types so that they don't get used during registration process). |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import uno |
| import unohelper |
| |
| def createInstance( ctx ): |
| # pythonpath/org/openoffice/comp/addin/sample/python/tokencounter.py contains the component implementation |
| # TokenCounter uses a new type, importing it at the top of this file |
| # leads to a failure during adding the extension to OOo. createInstance does not get called |
| # during registration |
| import org.openoffice.comp.addin.sample.python.tokencounter |
| return org.openoffice.comp.addin.sample.python.tokencounter.TokenCounter( ctx ) |
| |
| # pythonloader looks for a static g_ImplementationHelper variable |
| g_ImplementationHelper = unohelper.ImplementationHelper() |
| g_ImplementationHelper.addImplementation( \ |
| createInstance,"org.openoffice.comp.addin.sample.python.TokenCounter", |
| ("com.sun.star.sheet.AddIn",),) |
| </pre></td></tr></table> |
| |
| <p> Have a look at the <a href="#calc-addin"> sample calc addin</a> to see how it works. |
| |
| |
| |
| <p> |
| Note that there are some negative side effects: |
| |
| <ul> |
| <li> code added through this mechanism can only be changed with a restart of the |
| office process (as it got added to sys.modules). This is especially limitation for |
| script developers. |
| <li> two independend uno packages from different |
| developers may interfere each other, when they have name clashes in their |
| code (e.g. same 3rd party product, but different versions). |
| <li> if such a situation occurs, in general the last used component will not work |
| properly (which one is the last used component may also depend on the path of user |
| interactions in the office process) |
| </ul> |
| |
| <h2 id="dependencies"> Dependencies </h2> |
| <p>This chapter is most interesting for people who want to use the Python-UNO |
| bridge independently from OpenOffice.org.</p> |
| |
| <p>Unlike the Java or C++ UNO binding, the python UNO binding is not self |
| contained. It requires the C++ UNO binding and additional scripting |
| components. These additional components currently live in the shared libraries |
| typeconverter.uno, invocation.uno, corereflection.uno, introspection.uno, |
| invocadapt.uno, proxyfac.uno, pythonloader.uno (on windows |
| typeconverter.uno.dll,...; unix typeconverter.uno.so,...).</p> |
| |
| <p> Often, the <strong>components for setting up an interprocess connection</strong> |
| are also required. |
| These are uuresolver.uno, connector.uno, remotebridge.uno, bridgefac.uno shared libraries. |
| |
| <p> |
| The path environment variables ( LD_LIBRARY_PATH on Unix, PATH on Windows) |
| must point to a directory, where the core UNO libraries, the above listed |
| components and the pyuno shared library is located. (On Unix, there exists |
| two files: libpyuno.so containing the code and a pyuno.so which is needed |
| for importing a native python module). |
| |
| Additionally, the python module uno.py, unohelper.py and pythonloader.py must |
| be located in a directory, which is listed in the PYTHONPATH environment variable. |
| |
| <h2 id="bootstrap"> Bootstrapping pyuno from the python executable </h2> |
| <p> |
| When the uno module gets first imported from an arbitrary python script, it must |
| bootstrap a properly prepared UNO component context. |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # bootstraps the uno component context |
| import uno |
| |
| # retrieve the already bootstrapped component context |
| unoContext = uno.getComponentContext() |
| </pre></td></tr></table> |
| |
| |
| <p>As the python programmer |
| can't (and probably doesn't want to) give parameters while importing a module, |
| the python-uno binding uses the pyuno[rc|.ini] file located beside the pyuno |
| shared library to bootstrap the UNO context |
| (see <a href="/common/man/concept/micro_deployment.html">uno bootstrap variable concept</a>). The bootstrap variables |
| UNO_SERVICES must point to a registry file where the components, given above, |
| were registered. |
| |
| <p> |
| PYUNOLIBDIR is a special bootstrap variable, which contains the path to |
| the currently used pyuno shared library. |
| |
| Example: |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # The bootstrap variable PYUNOLIBDIR will be set by the pyuno runtime library |
| UNO_TYPES=$PYUNOLIBDIR/types.rdb |
| UNO_SERVICES=$PYUNOLIBDIR/pyuno_services.rdb |
| </pre></td></tr></table> |
| |
| <p>If the above preconditions are fulfilled, the script can simply be started |
| with</p> |
| <code>$ python myscript.py</code> |
| <p> |
| Sometimes it is preferable to mention the librarynames of the desired |
| components directly within the script instead of preparing a registry |
| (however note that the above mentioned bootstrap components always needs |
| to be registered in a registry). |
| This can be achieved by using the function |
| <code>unohelper.addComponentsToContext( |
| toBeExtendedContext, contextRuntime, componentUrls, loaderName )</code> |
| |
| <p> Example: |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import uno |
| import unohelper |
| |
| localContext = uno.getComponentContext() |
| |
| unohelper.addComponentsToContext( |
| localContext, localContext, ("streams.uno",), |
| "com.sun.star.loader.SharedLibrary") |
| |
| pipe = localContext.ServiceManager.createInstanceWithContext( |
| "com.sun.star.io.Pipe", localContext ) |
| |
| pipe.writeBytes( uno.ByteSequence( "abc" ) ) |
| ret,seq = pipe.readBytes( None, 3 ) |
| </pre></td></tr></table> |
| |
| |
| |
| <h2 id="replacing">Replacing the python runtime with your system's python installation</h2> |
| OOo by default ships with the Python-2.2.2 core runtime. This is fine for most |
| users, but some hackers (or Linux distributors) may want to replace the runtime |
| with the python system's installation, which may contain more optional packages |
| that you want to use in python. |
| |
| <p> The replacement is a little complicated however you just need an |
| installed python and office. |
| |
| <h4>Windows</h4> |
| <p>On windows, you can only use python-2.2. If you want to use python-2.3, you |
| must recompile the pyuno module with python-2.3 (see below)</p> |
| |
| <ul> |
| <li> Install OpenOffice.org</li> |
| <li> Install python 2.2</li> |
| <li> Use your favourite text editor (e.g. notepad) to open the file |
| OpenOffice.org/program/pythonloader.uno.ini and modify the lines there to something |
| like |
| <pre> |
| [Bootstrap] |
| PYTHONHOME=file:///c:/python-2.3.4 |
| PYTHONPATH=$PYTHONHOME/lib $ORIGIN |
| </pre> |
| The path elements must be entered as absolute file urls (note that you |
| need to escape using url syntax, for example a space is represented by %20). |
| The PYTHONPATH must point to the root |
| python library location and to OOo program directory. Add other libraries as you |
| need them ( space separated). |
| <li> Rename the following files and directories in the OpenOffice.org/program directory |
| to something else (e.g. add a .orig suffix) |
| |
| <ul> |
| <li> python.bat |
| <li> python22.dll |
| <li> python-core-2.2.2 |
| </ul> |
| </li> |
| <li> Start a cmd shell and add to the PATH variable both to python home directory and |
| OpenOffice.org/program directory</li> |
| <li> Add to the PYTHONPATH environment variable the OpenOffice.org/program directory</li> |
| </ul> |
| |
| <h4>Linux</h4> |
| <p>On Linux, you can use both use python-2.2 or python 2.3, but when using the |
| latter, |
| you get a warning on stderr (informing you about the version mismatch) |
| when starting python or the office, to avoid the warning, you need to rebuild pyuno |
| with python-2.3 (see below), however I haven't noticed any difficulties because |
| of the version mismatch.</p> |
| |
| <ul> |
| <li> You need a python configured with the --enable-shared option. When |
| OOo and python were not built with the same gcc compiler version, |
| you also need to rebuild python, because the default python uses some bad |
| switches during linking. |
| |
| <p> To rebuild do |
| <pre> |
| LINKCC=gcc |
| export LINKCC |
| ./configure --enable-shared |
| make |
| su -c "make install" |
| </pre> |
| |
| </li> |
| <li> Switch to the OpenOffice.org directory and move away the python |
| runtime coming with OOo. |
| <pre> |
| cd /path/to/openoffice.org/program |
| mv libpython.so.2 libpython.so.2.orig |
| mv python-core python-core.orig |
| cp pythonloader.unorc pythonloader.unorc.orig |
| ln -s /usr/local/lib/libpython2.3.so.1.0 libpython.so.2 |
| </pre> |
| </li> |
| <li>Add the office/program directory to the LD_LIBRARY_PATH and PYTHONPATH variable. |
| <li> |
| Create the file pythonloader.unorc in the office/program directory. |
| <pre> |
| [Bootstrap] |
| PYTHONHOME=file:///usr/local |
| PYTHONPATH=$PYTHONHOME/lib/python2.3 $ORIGIN |
| </pre> |
| The path elements must be entered as absolute file urls (note that you |
| need to use URL escape sequences for example replacing spaces with a %20). The PYTHONPATH must point to the root |
| python library location and to OOo program directory. Add other libraries as you |
| need them (space separated). |
| </li> |
| </ul> |
| |
| <h4> Testing</h4> |
| You should now be able to start system's python and type 'import uno'. If this works fine, |
| use pkgchk to deploy your script, for example the above swritercomp.py in |
| OpenOffice.org (Tip: add a print sys.version |
| to it). If this works fine, python should work well in OpenOffice.org itself. |
| |
| <p>I did only some rudimentary tests, but I didn't notice any significant |
| problems. <a href="www.openoffice.org/isses">Let us know</a>, |
| if you have some. |
| |
| <p> |
| Note that the <a href="http://bibus-biblio.sourceforge.net"> Bibus </a> project uses |
| an extended python 2.2.2 with the wxPython/wxWindows extension for the GUI. |
| |
| <h4>Rebuilding pyuno</h4> |
| You'll need to install OOo buildenv to do this. In the shell, replace the the PYTHONPATH |
| variable properly, e.g. |
| <pre> |
| setenv PYTHONPATH /usr/local/lib/python2.3:.:/usr/local/lib/python2.3/lib-dynload |
| </pre> |
| Make sure, that system's python is in the PATH variable. Build the office (or at least |
| all components, pyuno depends on) but leave out the python module. In the pyuno module |
| itself, you should only build pyuno/source/module, pyuno/source/loader and pyuno/test, |
| leave out the zipcore directory. |
| |
| You'll need to modify the pyuno/source/module/makefile.mk and pyuno/source/loader/makefile.mk. |
| Replace the CFLAGS+= line with CFLAGS+=-I/usr/local/include/python2.3 and all occurrences |
| of -lpython with -lpython2.3. |
| <p> |
| When the test runs fine, you can now replace pyuno.so, libpyuno.so and pythonloader.uno.so |
| in the office with your rebuilt version. |
| |
| |
| <!-- |
| <h2 id="scripting-framework"> Support for the new scripting framework </h2> |
| There is now a uno-package available, which allows the support of the new scripting |
| framework for OpenOffice.org 2.0. It is included in the <a href="#download">above download</a> |
| . It allows to execute python scripts in the new framework. |
| This paragraph shall just explain how to install and use the python part of the new |
| framework, it shall not explain the framework itself. |
| |
| <h3> Installation</h3> |
| <ol> |
| <li> Install an OpenOffice.org 1.1rc or newer with PyUNO activated |
| ( see <a href="#install">above</a> ). |
| |
| <li> Install the <a href="http://framework.openoffice.org/scripting">scripting framework</a> |
| (tested with version 0.3) |
| |
| <li> Copy the file scriptrt4python-0.1.0.zip into |
| <office-install>/user/uno_packages |
| |
| <li> run pkgchk in <office-install>/program |
| |
| <li> Deploy the sample script stored in the |
| samples/hello-framework-python.sxp parcel into the office |
| (e.g. with the scripting-framework CommandLineTools, for example |
| <p> |
| <pre> |
| java CommandLineTools -d hello-framework-python.sxp \ |
| /usr/local/joerg/OpenOffice.org1.1/user/Scripts |
| </pre> |
| ). |
| </ol> |
| |
| |
| <h3> Deinstallation </h3> |
| |
| <ol> |
| <li> Uninstall the hello-framework-python.sxp |
| <li> delete the file <office-install>/user/uno_packages/scriptrt4python-0.1.0.zip |
| <li> run pkchk |
| </ol> |
| |
| <h3> Writing your own scripts</h3> |
| You can write scripts simply by defining python functions. You can |
| have multiple functions within one file, but the file must be selfcontained |
| meaning that it may only reference the core python library but not any self written |
| scripting files (may be a future extension). |
| |
| <p> |
| Below you can find the sample script, which just pastes a |
| 'Hello Scriptingframework' into the current document. The following |
| script is stored as <code>HelloFramework.py</code>. |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| # Sample python script for the scripting framework |
| |
| # scriptCtx supports getDocument(), getComponentContext(), getDesktop() |
| def Hello( scriptCtx ): |
| print "entering HelloFramework.Hello" |
| |
| model = scriptCtx.getDocument() |
| |
| # access the document's text property |
| text = model.Text |
| |
| # create a cursor |
| cursor = text.createTextCursor() |
| |
| # insert the text into the document |
| text.insertString( cursor, "Hello Scriptingframework", 0 ) |
| |
| return None |
| </pre></td></tr></table> |
| |
| Beside the script file you must provide a <code>parcel-descriptor.xml</code> |
| file which describes all functions, that shall be callable fromt the office. |
| Here is the sample file for the above script. |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| <?xml version="1.0" encoding="UTF-8"?> |
| <parcel language="Python" xmlns:parcel="scripting.dtd"> |
| <script language="Python"> |
| <locale lang="en"> |
| <displayname value="HelloFramework.Hello"/> |
| <description> |
| Prints a 'Hello Framework' into the current document |
| </description> |
| </locale> |
| <functionname value="HelloFramework.Hello"/> |
| <logicalname value="HelloFramework.Hello"/> |
| </script> |
| </parcel> |
| </pre></td></tr></table> |
| |
| Note, that the each reference to the script must be written as |
| <code><source-file-name-without-.py>.<function-name></code>. |
| |
| <p> |
| The function gets called with a XScriptContext implementation as the first parameter. |
| It provides the UNO component context (getComponentContext()), the desktop |
| (getDesktop()) and the current document model (getDocument()) (if any). |
| |
| <p> |
| Zip these two files as a .sxp file and deploy it into the office using |
| the scripting frameworks commandlinetool. When you restart the office, you |
| should be able to select the new script in the scriptinframework's dialogs. |
| |
| <p> |
| Things to keep in mind: |
| <ul> |
| <li> each function must leave with <code>return None</code></a> |
| <li> live editing while the office is running is possible (when you edit |
| the file at the place, where the CommandLineTool deploys it) |
| <li> performance is poor (script is recompiled for every execution), no caching </li> |
| <li> interface to the script may change in future releases |
| (e.g. the first parameter of the function) |
| <li> error messages are currently printed to stderr (only readable |
| on unix systems) |
| |
| </ul> |
| |
| --> |
| <h2 id="regressiontests">Regressiontests </h2> |
| In case you have modified python or pyuno, you should at least run the following regression tests. |
| |
| <ul> |
| <li> Build testtools module and run |
| |
| <pre> |
| cd testtools/source/bridgetest/pyuno && dmake runtest |
| </pre> |
| </li> |
| <li> Build installation sets and install openoffice. |
| <li> Start program/python and type |
| <pre> |
| import uno |
| </pre> |
| (should work without any errors). |
| <li> Start the office and add the pyuno_hello_world.zip from the above pyuno-doc.zip by using Tools/Package Manager. |
| <li> Start Tools/Macros/Run macro/OpenOffice.org Macros/pythonSamples/TableSample/createTable |
| </ul> |
| |
| <h2 id="references"> External references </h2> |
| |
| <table> |
| |
| <tr> |
| <td>Python homepage</td> |
| <td><a href="http://www.python.org">http://www.python.org</a></td> |
| </tr> |
| |
| <tr> |
| <td>The OpenOffice.org component model</td> |
| <td><a href="http://udk.openoffice.org">http://udk.openoffice.org</a></td> |
| </tr> |
| |
| <tr> |
| <td>OpenOffice.org developer manual</td> |
| <td><a href="http://api.openoffice.org/DevelopersGuide/DevelopersGuide.html">http://api.openoffice.org/DevelopersGuide/DevelopersGuide.html</a></td> |
| </tr> |
| |
| </table> |
| |
| |
| <h2 id="faq"> Frequently Asked Questions </h2> |
| |
| <ol> |
| |
| <li> <h4> Why do I get a 'bus error' when starting the hello-world-script on Solaris ?</h4> |
| There seems to be a corrupted version of the libpyuno.so in the OpenOffice.org1.1.0 |
| installation set. The reason is not yet clear, might be either a bug in pyuno code or |
| a build error. Please download <a href="libpyuno.so.gz">libpyuno.so.gz</a> |
| to patch OOo1.1.0 version (do not apply |
| this patch on any other version than OOo1.1.0 Solaris sparc!). |
| |
| |
| |
| <li> <h4> Why do I get a 'SystemError: pyuno runtime is not initialized, ...' when starting the script ?</h4> |
| <ul> |
| |
| <li> Pyuno was not installed correctly (OO1.1RC2 and earlier, fixed with RC3). Please check |
| <p> |
| <code><openoffice-install>/program $ ls -c1d py*</code> |
| <pre> |
| pyunorc |
| pythonloader.py |
| pythonloader.unorc |
| python |
| python.sh |
| python-core |
| python-core-2.2.2 |
| pythonloader.uno.so |
| pyuno.so |
| </pre> |
| |
| Under certain circumstances, it may occur, that the following ini files are missing |
| |
| <p> |
| pyunorc (or pyuno.ini on windows): |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| [Bootstrap] |
| UNO_TYPES=$ORIGIN/types.rdb |
| UNO_SERVICES=$ORIGIN/services.rdb |
| </pre></td></tr></table> |
| |
| <p> |
| pythonloader.unorc (or pythonloader.unorc on windows): |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| [Bootstrap] |
| PYTHONHOME=$ORIGIN/python-core |
| PYTHONPATH=$ORIGIN/python-core/lib $ORIGIN/python-core/lib/lib-dynload $ORIGIN |
| </pre></td></tr></table> |
| <p>Simply cut and paste them into a text editor to create them.</p> |
| |
| <li> There have been reported some failures with the above error message, which have not been |
| resolved yet. You may want to follow |
| <a href="http://www.openoffice.org/issues/show_bug.cgi?id=17339">#i17339#</a>. |
| </ul> |
| |
| <li> <h4>Why do I get a 'SystemError: _PyImport_FixupExtension: module pyuno not loaded' when starting the script ? </h4> |
| |
| This generally happens when you still start the system's python installation. |
| OpenOffice.org ships a python installation (because python and the office must |
| have been built with the identical compiler version). |
| Please check this with 'which python'. Simply use OpenOffice.org's python with |
| absolute path names, for example use |
| /usr/local/OpenOffice.org1.1/program/python myscript.py. |
| |
| <li> <h4>Why do I get a "error: python-loader:'No module named pythonloader'" when running pkgchk with a python component ?</h4> |
| Make sure to unset PYTHONPATH and PYTHONHOME (which you may have set, because you have |
| another python installed on your system) environment variables before |
| running soffice AND pkgchk. This is a workaround, We are currently |
| thinking about a better solution. |
| |
| <li> <h4>Why do I get an error message 'msvcr70.dll or python22.dll not found' when starting python ?<br/> |
| (or Why do I get an 'error while loading shared libraries: libstdc++.so.x' ? ) |
| </h4> |
| You probably try to start python from the exe not the bat file, for example, |
| c:\program files\OpenOffice.org1.1\program\python-runtime\bin\python.exe, |
| but you have to use c:\program files\OpenOffice.org1.1\program\python.bat. |
| |
| |
| <li> <h4>Why do I get 'PYTHONPATH=... is not an identifier' when starting python ?</h4> |
| <p>This is a bug in the python script which occurs with older bash shell |
| versions. Simply use a text editor to change the following lines in the |
| OOo-install/program/python.sh script</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| export PYTHONPATH="$sd_prog":"$sd_prog/python-core/lib":"$sd_prog/python-core/lib/lib-dynload":"$PYTHONPATH" |
| export PYTHONHOME="$sd_prog"/python-core |
| </pre></td></tr></table> |
| |
| <p>to</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| PYTHONPATH="$sd_prog":"$sd_prog/python-core/lib":"$sd_prog/python-core/lib/lib-dynload":"$PYTHONPATH" |
| export PYTHONPATH |
| PYTHONHOME="$sd_prog"/python-core |
| export PYTHONHOME |
| </pre></td></tr></table> |
| |
| <p>This bug is fixed with OOo 1.1.1.</p> |
| |
| |
| <li> <h4>I already have python installed on my system, why does the office ship another python ? </h4> |
| <p>Python itself is shipped with OpenOffice.org, because</p> |
| <ul> |
| <li> python must have been compiled with the same C++ compiler as the office itself on |
| all platforms that use the gcc compiler (e.g. Linux, BSD, etc.). |
| <li> On most Unix platforms, no python shared libraries are available by default |
| (though some distributions do so). This would have meant, that python UNO |
| components cannot be executed within the office process. |
| <li> Python component developers need a guaranteed minimum platform which |
| they can rely on. |
| <li> Recognition of a python runtime at the installation system would have been an |
| extremely difficult and time consuming task becausemany different python |
| installation schemes exist. |
| <li>Packagers of OpenOffice.org will create their own packages, for |
| example redhat or debian, without Python. The standard distribution must |
| run on low end systems. |
| </ul> |
| |
| <li> <h4>Can I use system's python installation ? </h4> |
| See <a href="#replacing"> here.</a> |
| |
| <li> <h4>Why does my UNO component crash OpenOffice.org, while the sample UNO |
| component runs fine?</h4> |
| |
| There is a known bug in the office, see |
| <a href="http://www.openoffice.org/issues/show_bug.cgi?id=13377"> |
| #i13377#</a>, which was not fixed for OpenOffice.org1.1. |
| The office in general crashes, when a python script leads to an unhandled |
| exception (for example an attribute error). |
| |
| <p> |
| You may try to workaround this bug by adding a <code>try: except:</code> level |
| in your trigger() implementation, which dumps an error message to stdout/stderr, but |
| sadly this will not help in all cases (for example compilation failure for |
| some reason, please follow the issue for further information). |
| |
| <p> Of course, there may be other reasons for a crash, you will only know, when you |
| try to retrieve a native callstack (for example by using gdb). |
| |
| <li><h4>Why doesn't Python's xml parser (expat) or the zip module work for me?</h4> |
| These libraries don't yet get built for OOo1.1. This will change for OOo2.0. Alternatively |
| you may use OpenOffice.org's xml parser service (see service com.sun.star.xml.sax.Parser) |
| or the zip content provider |
| (see <a href="http://ucb.openoffice.org"> http://ucb.openoffice.org</a>). |
| |
| <li><h4> Why doesn't socket and sre module work in OOo1.1. python distribution |
| on windows?</h4> |
| This is a known bug on windows in the OOo1.1 build. This should be fixed for OOo1.1.1 |
| (see issue <a href="http://www.openoffice.org/issues/show_bug.cgi?id=21281">21281</a> ). |
| It should work for the other platforms. You can workaround this by downloading the |
| official windows python distribution |
| (see <a href="http://www.python.org">http://www.python.org</a>) and replacing the |
| appropriate .pyd files in the OOo's python installation. |
| |
| <li> <h4>The samples are running fine, but how do I get more information about the API ?</h4> |
| |
| The semantics of the OpenOffice.org API is a very complex topic, which can't be |
| discussed in this python document. Try to gather information from other |
| resources, especially from the developer manual (see <a href="#references">below</a>). |
| <li> <h4>Most examples in the devguide are in Java. How do I translate them to python code ?</h4> |
| Most sample code you find there is written in Java. It is easy to translate |
| Java code to python,when you know the following differences: |
| <p> |
| |
| In python you don't need <code>queryInterface</code>. E.g. Java code like |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| oInterface = (XInterface) oMSF.createInstance( |
| "com.sun.star.frame.Desktop" ); |
| oCLoader = ( XComponentLoader ) UnoRuntime.queryInterface( |
| XComponentLoader.class, oInterface ); |
| PropertyValue [] szEmptyArgs = new PropertyValue [0]; |
| aDoc = oCLoader.loadComponentFromURL( |
| "private:factory/swriter" , "_blank", 0, szEmptyArgs ); |
| </pre></td></tr></table> |
| |
| <p>becomes in python simply</p> |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| oCLoader = oMSF.createInstance( "com.sun.star.frame.Desktop" ) |
| aDoc = oCLoader.loadComponentFromURL( |
| "private:factory/swriter", "_blank", 0, () ) |
| </pre></td></tr></table> |
| <p>You don't need this intermediate oInterface variable anymore. |
| So the python code simplifies the example a lot, with a little training, you |
| shouldn't have too many problems to translating Java to python code.</p> |
| |
| <li> <h4>Why can't I call the print method?</h4> |
| In python, 'print' is a |
| <a href="http://docs.python.org/ref/print.html">statement</a>. This |
| basicly means there is no way to get a variable, method or anything else |
| with this name. For example the below code does not work: |
| |
| <pre> |
| doc = desktop.loadComponentFromURL(infileurl, "_blank", 0, ()) |
| doc.storeAsURL(outfileurl, ()) |
| doc.print(()) |
| </pre> |
| You can workaround the problem by using the <code>uno.invoke()</code> |
| function like below : |
| <pre> |
| uno.invoke(doc, "print", ((), )) |
| </pre> |
| |
| |
| <li> <h4>Why can't I do a replace on the 'NumberingRules' object ? </h4> |
| |
| <p>There are some places, where the loss in type safety leads to |
| difficulties, as this issue shows |
| <a href="http://www.openoffice.org/issues/show_bug.cgi?id=12504"> |
| http://www.openoffice.org/issues/show_bug.cgi?id=12504</a>. The problem |
| here is, that the C++ implementation within the office expects a |
| <code>sequence< PropertyValue ></code>, while the PyUNO runtime |
| converts it to a <code>sequence< any></code>, where each <code>any</code> |
| contains a <code>PropertyValue</code>. In my eyes, this is a bug within |
| the C++ code. However here is a workaround for pyuno that the python |
| scripter can use. See the sample below: |
| |
| <table width="100%" bgcolor="silver"><tr><td><pre> |
| import uno |
| import unohelper |
| |
| localContext = uno.getComponentContext() |
| |
| resolver = localContext.ServiceManager.createInstanceWithContext( |
| "com.sun.star.bridge.UnoUrlResolver", localContext) |
| ctx = resolver.resolve( |
| "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext") |
| smgr= ctx.ServiceManager |
| desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx) |
| doc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ()) |
| |
| style = doc.createInstance("com.sun.star.style.NumberingStyle") |
| family = doc.getStyleFamilies().getByName('NumberingStyles') |
| family.insertByName('List test', style) |
| |
| rule = style.getPropertyValue('NumberingRules') |
| level = rule.getByIndex(0) |
| |
| # the normal call would have been: |
| # rule.replaceByIndex( 0, level ) |
| # but this will end up in a exception |
| # magic to pass the exact type to the callee |
| uno.invoke( rule , "replaceByIndex", (0, uno.Any("[]com.sun.star.beans.PropertyValue",level)) ) |
| </pre></td></tr></table> |
| |
| <p>This is the only place, where the uno.Any is used. Using the uno.Any in normal |
| calls will lead to RuntimeExceptions. A python uno object implementation will never |
| receive an instance of uno.Any() as a incoming parameter, instead always the value within the |
| is passed. |
| |
| <p> This solution looks really ugly, but it allows you to continue, where you |
| otherwise could only give up or use to another implementation language. |
| |
| <li> <h4>How can I activate encoding iso8859-1 for OpenOffice.org's python installation ?</h4> |
| Put a file called sitecustomize.py somewhere in your PYTHONPATH |
| containing: |
| |
| <pre> |
| import sys |
| sys.setdefaultencoding('iso8859-1') |
| </pre> |
| |
| (or any other encoding you wish). However, note that this is generally |
| not such a good idea. It would be much cleaner to do the necessary |
| conversions explicitly in the code, for example using Unicode(x, 'iso8859-1'). |
| </ol> |
| |
| <h2 id="known_pyuno_extensions"> Known PyUNO extensions for OpenOffice.org </h2> |
| |
| <p>Packages listed here can be taken as a demo of what is possible with pyuno. |
| Let me know, if you are aware of other extensions using pyuno. |
| |
| <table border> |
| <col width=50% /> <col width=50% /> |
| <tr> |
| <th>Title</th> |
| <th>Link</th> |
| </tr> |
| |
| <tr> |
| <td>PyOOoBib - The program will search library catalogs over the Internet for bibliographic records, you can select records and add them to the bibliographic database</td> |
| <td><a href="http://bibliographic.openoffice.org/servlets/NewsItemView?newsItemID=168"> |
| http://bibliographic.openoffice.org/servlets/NewsItemView?newsItemID=168</a> |
| </tr> |
| |
| <tr> |
| <td>Thessalonica - A tool to improve multilingual support in OOo </td> |
| <td><a href="http://www.thessalonica.org.ru/en">http://www.thessalonica.org.ru/en</a></td> |
| </tr> |
| |
| <tr> |
| <td>Bibus Bibliographic software </td> |
| <td><a href="http://bibus-biblio.sourceforge.net">http://bibus-biblio.sourceforge.net/</a></td> |
| </tr> |
| |
| <tr> |
| <td> oood.py - A demon for OpenOffice.org </td> |
| <td> <a href="oood/index.html">http://udk.openoffice.org/python/oood/index.html</a></td> |
| </tr> |
| |
| <tr> |
| <td>pyXray - Debugging tool to visualize uno objects via the office toolkit </td> |
| <td><a href="http://www.indesko.org/en/downloads/">http://www.indesko.org/en/downloads</a></td> |
| </tr> |
| |
| <tr> |
| <td>Ponto - A wrapper layer around writer documents </td> |
| <td><a href="http://www.ham.nw.schule.de/pub/bscw.cgi/0/73468">http://www.ham.nw.schule.de/pub/bscw.cgi/0/73468</a><br/> |
| <a href="http://ddi.cs.uni-dortmund.de/projekte/ponto">http://ddi.cs.uni-dortmund.de/projekte/ponto</a></td> |
| </tr> |
| |
| </table> |
| |
| |
| |
| <h2 id="pyuno_needs_you"> PyUNO needs YOU ! </h2> |
| |
| <p>PyUNO is currently (and will be in future) maintained by myself in my spare |
| time. |
| |
| <p>My main aim for pyuno is to provide a good |
| integration of OpenOffice.org's component model into python. Some guys |
| on <a href="mailto:dev@udk.openoffice.org">dev@udk.openoffice.org</a> demand to |
| have a |
| <strong>more feature rich python runtime |
| in OpenOffice.org</strong> and an integration with the system's |
| python installation. While this is an understandable demand, it is not |
| one of my favourite topics to work on and it involves quite a lot of work. As I also spend time on the |
| creation of a <a href="http://dba.openoffice.org/drivers/postgresql/index.html">postgresql driver |
| for OpenOffice.org</a>, there is simply no time left for this task. |
| |
| <p> So I am looking for other volunteers such as <strong>you</strong> to fill this gap. In case |
| you are interested, let me know via the dev@udk.openoffice.org |
| mailing list or drop me a mail privately. |
| |
| <p> I currently see the following main tasks |
| |
| <table border> |
| <tr> |
| <th> Task </th> |
| <th> Description</th> |
| <th> Main 'challenges'</th> |
| </tr> |
| |
| <tr> |
| <td> Raise OOo's python version to current python release</td> |
| <td> |
| <p>OOo currently uses python 2.2.2 with OOo 1.1.x and python 2.3.4, which is |
| considerably old already. |
| Someone doing this |
| will mainly spend time in the python module of the OpenOffice.org buildtree, where |
| the python tarball gets extracted, patched and built. This is a very platform dependent |
| task, typically for Mac OS X you'll need to do a lot of patches. |
| |
| </p> |
| </td> |
| <td> OOo build knowledge, port current OOo python patches to current python version, |
| maintain the build for both Windows and Unix platforms </td> |
| <td> </td> |
| </tr> |
| |
| <tr> |
| <td> Add support zlib library (and more ...) </td> |
| <td> Currently, OOo's python comes without these libraries which are |
| missed a lot by python users. Ideally, they should reuse the versions of zlib, |
| which are already in the OOo source tree. |
| </td> |
| <td> OOo build knowledge, continue to maintain the build for both Windows and |
| Unix platforms </td> |
| </tr> |
| |
| <tr> |
| <td>Reintegrate OOo's patches to python into the python source |
| tree (if sensible)</td> |
| <td>A lot of patches get applied to the python source tarball, |
| before it is built |
| for OpenOffice.org. You would need to review the patches and try to |
| convince with the |
| python code maintainers to integrate those patches |
| (if sensible) into their source tree. |
| This will make life easier when upgrading to future python versions. </td> |
| <td>OOo build knowledge, understanding of the patches and discussion with the python community.</td> |
| </tr> |
| |
| <tr> |
| <td> changes in python itself |
| </td> |
| <td> Real integration with the system's python installation will only |
| be possible, if python itself is modified. |
| |
| <ul> |
| <li> Unix: Is it really necessary, that the python executable is linked |
| to libstdc++ library ? |
| <li> Shared library: python should be built by default as a shared library |
| (on all platforms, where this is possible). |
| <li> Versioning: Python currently assumes, that native modules are built |
| and run with identical python versions (otherwise warnings are issued). |
| Newer python versions should guarantee binary backward compatibility for |
| native modules built with older python versions. |
| </ul> |
| </td> |
| <td> |
| Discuss with the python community. |
| </td> |
| </tr> |
| |
| |
| <tr> |
| <td>PyUNO FAQ maintainer</td> |
| <td>A lot of good questions on pyuno have already been, and will be, answered |
| in future in the <a |
| href="mailto:dev@udk.openoffice.org">dev@udk.openoffice.org</a> (or others) |
| mailing lists. |
| Someone should add it to the FAQ on this page. |
| </td> |
| <td>Follow OpenOffice.org mailing lists and maintain this page in CVS.<br/> |
| Knowledge of simple html.</td> |
| </tr> |
| |
| </table> |
| |
| |
| |
| <h2 id="authors"> Authors </h2> |
| |
| <p>The UNO python bridge was initially created by <a href="mailto:ralpht@sgi.com">Ralph Thomas</a> |
| and is now |
| maintained by <a href="mailto:JoergBudi@gmx.de">Joerg Budischewski</a>. |
| Christian Zagrodnick sent in some very useful patches. Many unmentioned porters |
| made it possible to have pyuno on all platforms supported by OOo. Last updated |
| $Date: 2008/10/16 22:02:35 $ |
| |
| <p>Please use the <a href="dev@udk.openoffice.org">dev@udk.openoffice.org</a> |
| mailing list for further questions.</p> |
| |
| <h2 id="license">License</h2> |
| This document is available under <a href="http://www.openoffice.org/licenses/PDL.html">PDL</a> (Public Documentation License). |
| |
| </body> |
| </html> |