Load module from package to another package

I’d love to understand! My module looks like this:

import os
import json
import pyuno
... # all imports here


def bal_launcher(*args):
    ...

def open_medias(*args):
     ...

g_exportedScripts = (
    bal_launcher,
    post_launcher,
    open_document,
    start_cq,
    convert_to_srt_format,
    convert_to_elan,
    register_new_correction,
 )

Ok you completed your answer. Thanks and where would you include your:

g_ImplementationHelper.addImplementation(
InterlinSettingsJob,
“name.JimK.LinguisticTools.InterlinSettings”,
(“com.sun.star.task.Job”,),)

EDIT: I’d like to clarify what I’m looking for exactly.

I made an extension for managers that interacts with a webserver and an other one, more public, that allows to work on local documents.

The second one allows to open a VLC player. So my goal was: 1/ check if the manager extension was installed 2/ if yes, this one has a function to get the url to open in VLC. If no, the url selection is done manually.

So I was thinking of using this pattern:

try:
    from rdt_bal import get_my_url
except:
    get_my_url = None

and in my function:

def open_vlc(**args):
    if get_my_url:
        vlc(get_my_url())
    else:
        vlc()

I’m afraid that in the case of using addImplementatiion It would crash if the manager extension is not installed.

I think it should work without crashing. Wrap code like the following in a try block as in your pattern.

    mri_obj = ctx.ServiceManager.createInstanceWithContext(
        "mytools.Mri", ctx)

I got this issue:

script.CannotConvertException: value does not implement com.sun.star.uno.XComponentContext

If you want help with that error message, post a complete example that shows how to reproduce the error. Python instructions for calling MRI are at https://github.com/hanya/MRI/wiki/RunMRI#Python.

Personal messages prevent collaboration among the group. I don’t like it when people use them to request more help.

You can post a follow-up question by creating a clear question with a simplified example. Include a link to the original question. See How do I ask a good question? - Help Center - Stack Overflow.

Ok. I meant professional help.

What are personal messages for if it’s not for helping without polluting a thread with very specific needs? I’m very conscious of the importance to share help and indeed, I have the habit after a long (sometimes very long) time to give a clear solution to the issue expressed. Unfortunately, I don’t have the time right now to find the solution as I’m not a LibreOffice dev. I don’t either know how to get a training class. Thanks god there’s specific forum places (like forum.openoffice.org where I posted this issue too) where I btw found all my knowledges but in this case, it’s too specific.
At least, if you don’t want to give a deeper look at this, would you be kind enough to address me to someone that might help me ?

If your code appears in Tools>Macros>Organize>Python… you have created a Python macro. A macro can be distributed as an extension package but it IS NOT an extension in the narrower sense because it does not add any UNO service to the office suite.

I distribute Python macros with my own script installer [Solved] Retrieve embedded Python script display in Writer (View topic) • Apache OpenOffice Community Forum which saves any text file anywhere in the user profile, for instance Scripts/python/pythonpath/my_tools.py
It is a simple Basic macro wrapped in a text template.

Thanks for your answer ! I was mislead by the fact that I distribute my macros using an extension package. They’re quite well integrated in Libreoffice Menu, Toolbar, Configuration in Options… I really thought it was an extension ! I’m a bit disappointed :slight_smile:
Is there some documentation about building a ‘real’ python extension then? And in what sense, could it solve my issue?

https://wiki.openoffice.org/wiki/UNO_component_packaging

g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(
        Wavelet,
        "name.vojta.openoffice.Wavelet",
        ("com.sun.star.task.Job",),)

The above declaration saves you a lot of typing. You declare the name of your own service name and that it supports the c.s.s.task.Job service. The service name is also used in Addons.xcu.
The module header and declaration of your class look like:

import uno
import unohelper
from com.sun.star.task import XJobExecutor
 
class Wavelet( unohelper.Base, XJobExecutor ):``

Your class implements XJobExecutor with the help of unohelper.Base. The ImplementationHelper takes care of all the missing functions, such as dispose().
Once the extension has been installed successfully, any macro code calls the trigger method like this:

REM Basic
srv = createUnoService("name.vojta.openoffice.Wavelet")
srv.trigger("dummy")

I’m not proficient with this complicated stuff. I have written 3 Python extensions that happen to work somehow. I copied most of the framework stuff from other extensions (simple ones) and replaced the strings.

Thanks for your very encouraging post (btw are you the author of the Wavelet example?)

I just wonder how to bind menu and toolbar il you have more than one function. From what I see, it launch a default trigger() method.

It’s maybe the solution given above by @jimk having more classes ! One foreach function.

No. It just looks like the smallest possible example. You may use one class and use the string argument to trigger(str) and call routines according to the passed argument.
You can also declare your own routines but then you have to compile some binary thingy using some tool in the development kit. I forgot all the details and will never do it again. Too cumbersome.

Menus and toolbars are defined in Addons.xcu in the extension.

  <node oor:name="m01" oor:op="replace">
    <prop oor:name="URL" oor:type="xs:string">
      <value>service:name.JimK.LinguisticTools.PhonologySettings?execute</value>
    </prop>

A caution about the Wavelet example: it’s nice and short, but there are declarations missing. Such old-style extensions often to fail to install and uninstall correctly. For a properly declared extension, see my struct.oxt example in the other post.

Thank you @jimk
As I said

[my extension is] quite well integrated in Libreoffice Menu, Toolbar, Configuration in Options…

So the question is much more about connecting many function through classes, which I haven’t done yet (lack of time).

You said:

For a properly declared extension, see my struct.oxt example in the other post.

I would appreciate so much if you could be more precise. Which other post? Your struct.oxt sounds very appeling to me!

The link to the post is in my answer above. Here is a link directly to the comment: Is it possible to transfer a struct from Python to StarBasic? - #10 by jimk

That is precisely what my answer and responding comment show.

Yes, so there was no need to ask again if you already knew how to add the menus.

It seems we are having some trouble communicating. Often when that happens, it is best to open a new, clearly worded question, as I also commented earlier. Or, you may already have all the information you need, and if so, now it is a matter of taking the time to get it working.

I did not know about this. From your warning, I think I’ll steer clear of it! The primary reason I prefer python rather than java is that there is no need for compiling and depending on the LO SDK when writing macros.

This is not about macros. It is about extensions adding real objects to this office suite.
Once upon a time I compiled some UNO blob from a declaration file like this:

module org { module openoffice { module sheet { module addin {
 
    interface XPySudoku
    {
        sequence< sequence< any > > pysudoku( [in] sequence< sequence< any > > InputArray);
    };
 
}; }; }; };

It declares an array function for Calc taking an array as argument (an unsolved 9x9 Sudoku) and returning an array (the solved 9x9 Sudoku).
The binaries are files with *.urd or *.rdb suffix.
https://extensions.libreoffice.org/en/extensions/show/1984

Oh, you’re talking about a Calc Add-In. My extension has one of those. I compiled the .rdb file a long time ago (don’t remember how) and it still works on my current version of LibreOffice.

      <node oor:name="AddInFunctions">
        <node oor:name="reverse" oor:op="replace">
          <prop oor:name="DisplayName"><value xml:lang="en">reverse</value></prop>
          <prop oor:name="Description">
            <value xml:lang="en">Flips a string backwards.  For example "apple" becomes "elppa".</value>
          </prop>
          <prop oor:name="Category"><value>Add-In</value></prop>
          <!-- This won't help, because there is no reverse() in Excel. -->
          <prop oor:name="CompatibilityName"><value xml:lang="en">reverse</value></prop>
          <node oor:name="Parameters">
            <node oor:name="s" oor:op="replace">
              <prop oor:name="DisplayName"><value xml:lang="en">s</value></prop>
              <prop oor:name="Description"><value xml:lang="en">The string to reverse.</value></prop>
            </node>
          </node>
        </node>
      </node>

This looks like Addon.xcu, the extension’s main configuration in XML syntax. The thing that is pushed into the compiler looks more like Java syntax. I think you have to compile interfaces with methods having their own in and out values, like a spreadsheet add-in or MRI with its inspect method. UNO IDL = interface definition language.

Okay, you have reminded me of how this all fits together. I will post another answer that is what the OP asked for, although it is probably way too cumbersome to be practical, as you mentioned.

My other answer assumes that an existing UNO interface is used. This is much easier. However there is a way to create methods of any interface, as @Villeroy commented.

An IDL file defines the interface that the method will use (name, arguments and so on). It needs to be compiled into an .rdb file with a tool in the LibreOffice SDK called idlc.

#include <com/sun/star/uno/XInterface.idl>

module name { module JimK { module LinguisticTools { module CalcFunctions {

    interface XCalcFunctions
    {
      string reverse( [in] string s );
    };

}; }; }; };

The compiled file is referenced in manifest.xml.

    <!-- Compiled type library for the Calc addin -->
    <manifest:file-entry
     manifest:full-path="idl/XCalcFunctions.rdb"
     manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"/>

The implementation in python looks like this in my extension.

from name.JimK.LinguisticTools.CalcFunctions import XCalcFunctions

class StringReverserAddIn(unohelper.Base, XCalcFunctions):
    def __init__(self, ctx):
        self.ctx = ctx

    @staticmethod
    def factory(ctx):
        return StringReverserAddIn(ctx)

    def reverse(self, inString):
        return inString[::-1]

g_ImplementationHelper.addImplementation(
    StringReverserAddIn.factory,
    "name.JimK.LinguisticTools.ReverseStringImpl",
    ("com.sun.star.sheet.AddIn",),)

If not creating an add-in, I think the interface name could be different, probably like this:

    "name.JimK.LinguisticTools.ReverseStringImpl",
    ("name.JimK.LinguisticTools.ReverseStringImpl",),)

Anyway, this works in a Basic macro.

svc = CreateUnoService("name.JimK.LinguisticTools.ReverseStringImpl")
s = svc.reverse("hamster")
MsgBox(s)

Result:

retsmah

Note: MRI also uses an IDL file but it derives from the existing interface com/sun/star/beans/XIntrospection.idl, so that may be a different case.