The implementation loader for Python allows us to write UNO component in Python language.
The loader is separated in two parts. One of the part is C++ layer that instantiate Python runtime. And it loads Python code to behave as implementation loader of Python.
C++ layer of the loader is not special from other UNO component that loaded by com.sun.star.loader.SharedLibrary loader. Once the loader is requested to be instantiated, pythonloader.uno(rc|.ini) file is loaded to get initialize variables for Python runtime. PYUNO_LOADER_PYTHONHOME specifies the home directory of Python that is used to set PYTHONHOME. PYUNO_LOADER_PYTHONPATH specifies include path for Python libraries, these values are shown in sys.path of Python after the initialization. The instance of office keeps only an instance of Python runtime. Therefore, all Python script, UNO components and macros are executed in the same instance of Python. After the initialization of Python runtime, pyuno module is also initialized to be used to convert or to wrap the loader written in Python by pyuno::Adapter class. After these, pythonloader.py file is loaded and pythonloader.Loader class is instantiated and returned as front end of Python loader.
This class is the real implementation of com.sun.star.loader.Python component that provides com.sun.star.loader.XImplementationLoader. All loaders responses against registration requests and activation requests by central component factory.
The loader supports the following protocol to load components written in Python: - file, for user defined component in general. - vnd.openoffice.pymodule, imported by Python's normal import function, used for built-in components in common.
Activation of UNO Components
If the factory found com.sun.star.loader.Python loader as desired loader for requested UNO component, new instance of the loader is instantiated. XImplementationLoader::activate method is called with its implementation name and location URL for the file that contains its implementation. The loader loads something from the passed location and returns a value that exports com.sun.star.lang.XSingleComponentFactory and com.sun.star.lang.XService interfaces. If the implementation file defines g_ImplementationHelper variable in the loaded module, it is used to get the factory. If it is not found in the loaded module, getComponentFactory method of the module is called with implementation name, service manager and registry key. The result of the method called should be an instance of the class that implements XSingleComponentFactory and XServiceInfo interfaces.
Registration of UNO Components
Since Apache OpenOffice 3.4, the passive registration mechanism has been introduced. Until then, XImplementationLoader::writeRegistryInfo method is no longer usable but the mechanism of extension registration for Python component is not yet updated. Therefore the method is called during the registration of the component.
When the following registration is requested, the type registry keeps these informations.
<?xml version="1.0" encoding="UTF-8"?> <components xmlns="http://openoffice.org/2010/uno-components"> <component loader="com.sun.star.loader.Python" uri="help.py"> <implementation name="foo.bar.hoge.help.HelpHacker"> <service name="foo.bar.hoge.help.HelpHacker"/> </implementation> </component> </components>
In the above example, uri attribute of component node specifies the location of the file that provides the factory of the component. XImplementationLoader::writeRegistryInfo method is called with the file location that to be loaded to get component implementation and registration information.
From file Protocol
When the component location is specified by file protocol, the loader create new instance of module and exec function is called with it as the space. And then, __file__ attribute of the module is set to the URL to the component file.
If pythonpath.zip archive or pythonpath directory beside the file that is specified as component location, path to these files are added to sys.path list. Therefore your component can load some own modules from these paths.
From vnd.openoffice.pymodule Protocol
Simply, built-in __import__ function is used to load the module specified with vnd.openoffice.pymodule protocol.
Loaded components specified by file protocol in activation or registration process, they are cached in pythonloader.g_loadedCompoonents dict. If the component specified by vnd.openoffice.pymodule protocol, the loaded component is no cached in g_loadedCompoonents variable because it is already cached as a module by Python itself.