LibreOffice Module pyuno (master) 1
pythonloader.py
Go to the documentation of this file.
1# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
2#
3# This file is part of the LibreOffice project.
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0. If a copy of the MPL was not distributed with this
7# file, You can obtain one at http://mozilla.org/MPL/2.0/.
8#
9# This file incorporates work covered by the following license notice:
10#
11# Licensed to the Apache Software Foundation (ASF) under one or more
12# contributor license agreements. See the NOTICE file distributed
13# with this work for additional information regarding copyright
14# ownership. The ASF licenses this file to you under the Apache
15# License, Version 2.0 (the "License"); you may not use this file
16# except in compliance with the License. You may obtain a copy of
17# the License at http://www.apache.org/licenses/LICENSE-2.0 .
18#
19import uno
20import unohelper
21import sys
22import types
23import os
24from urllib.parse import unquote
25from com.sun.star.uno import Exception,RuntimeException
26from com.sun.star.loader import XImplementationLoader
27from com.sun.star.lang import XServiceInfo
28
29MODULE_PROTOCOL = "vnd.openoffice.pymodule:"
30DEBUG = 0
31
32g_supportedServices = "com.sun.star.loader.Python", # referenced by the native C++ loader !
33g_implementationName = "org.openoffice.comp.pyuno.Loader" # referenced by the native C++ loader !
34
35def splitUrl( url ):
36 nColon = url.find( ":" )
37 if -1 == nColon:
38 raise RuntimeException( "PythonLoader: No protocol in url " + url, None )
39 return url[0:nColon], url[nColon+1:len(url)]
40
41g_loadedComponents = {}
43 path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
44 if DEBUG == 1:
45 print(b"checking for existence of " + encfile( path ))
46 if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
47 if DEBUG == 1:
48 print(b"adding " + encfile( path ) + b" to sys.path")
49 sys.path.append( path )
50
51 path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
52 if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
53 if DEBUG == 1:
54 print(b"adding " + encfile( path ) + b" to sys.path")
55 sys.path.append( path )
56
57def encfile(uni):
58 return uni.encode( sys.getfilesystemencoding())
59
60class Loader( XImplementationLoader, XServiceInfo, unohelper.Base ):
61 def __init__(self, ctx ):
62 if DEBUG:
63 print("pythonloader.Loader ctor")
64 self.ctx = ctx
65
66 def getModuleFromUrl( self, url ):
67 if DEBUG:
68 print("pythonloader: interpreting url " + url)
69 protocol, dependent = splitUrl( url )
70 if "vnd.sun.star.expand" == protocol:
71 exp = self.ctx.getValueByName( "/singletons/com.sun.star.util.theMacroExpander" )
72 url = exp.expandMacros(unquote(dependent))
73 protocol,dependent = splitUrl( url )
74
75 if DEBUG:
76 print("pythonloader: after expansion " + protocol + ":" + dependent)
77
78 try:
79 if "file" == protocol:
80 # remove \..\ sequence, which may be useful e.g. in the build env
81 url = unohelper.absolutize( url, url )
82
83 # did we load the module already ?
84 mod = g_loadedComponents.get( url )
85 if not mod:
86 mod = types.ModuleType("uno_component")
87
88 # check for pythonpath.zip beside .py files
89 checkForPythonPathBesideComponent( url[0:url.rfind('/')] )
90
91 # read the file
92 filename = unohelper.fileUrlToSystemPath( url )
93
94 with open( filename, encoding='utf_8' ) as fileHandle:
95 src = fileHandle.read().replace("\r","")
96 if not src.endswith( "\n" ):
97 src = src + "\n"
98
99 # compile and execute the module
100 codeobject = compile( src, encfile(filename), "exec" )
101 mod.__file__ = filename
102 exec(codeobject, mod.__dict__)
103 g_loadedComponents[url] = mod
104 return mod
105 elif "vnd.openoffice.pymodule" == protocol:
106 nSlash = dependent.rfind('/')
107 if -1 != nSlash:
108 path = unohelper.fileUrlToSystemPath( dependent[0:nSlash] )
109 dependent = dependent[nSlash+1:len(dependent)]
110 if not path in sys.path:
111 sys.path.append( path )
112 mod = __import__( dependent )
113 path_component, dot, rest = dependent.partition('.')
114 while dot == '.':
115 path_component, dot, rest = rest.partition('.')
116 mod = getattr(mod, path_component)
117 return mod
118 else:
119 if DEBUG:
120 print("Unknown protocol '" + protocol + "'");
121 raise RuntimeException( "PythonLoader: Unknown protocol " +
122 protocol + " in url " +url, self )
123 except Exception as e:
124 if DEBUG:
125 print ("Python import exception " + str(type(e)) +
126 " message " + str(e) + " args " + str(e.args));
127 raise RuntimeException( "Couldn't load " + url + " for reason " + str(e), None )
128 return None
129
130 def activate( self, implementationName, dummy, locationUrl, regKey ):
131 if DEBUG:
132 print("pythonloader.Loader.activate")
133
134 mod = self.getModuleFromUrl( locationUrl )
135 implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
136 if DEBUG:
137 print ("Fetched ImplHelper as " + str(implHelper))
138 if implHelper is None:
139 return mod.getComponentFactory( implementationName, self.ctx.ServiceManager, regKey )
140 else:
141 return implHelper.getComponentFactory( implementationName,regKey,self.ctx.ServiceManager)
142
143 def writeRegistryInfo( self, regKey, dummy, locationUrl ):
144 if DEBUG:
145 print( "pythonloader.Loader.writeRegistryInfo" )
146
147 mod = self.getModuleFromUrl( locationUrl )
148 implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
149 if implHelper is None:
150 return mod.writeRegistryInfo( self.ctx.ServiceManager, regKey )
151 else:
152 return implHelper.writeRegistryInfo( regKey, self.ctx.ServiceManager )
153
155 return g_implementationName
156
157 def supportsService( self, ServiceName ):
158 return ServiceName in self.getSupportedServiceNames()
159
161 return g_supportedServices
162
163# vim: set shiftwidth=4 softtabstop=4 expandtab:
def activate(self, implementationName, dummy, locationUrl, regKey)
def __init__(self, ctx)
Definition: pythonloader.py:61
def getSupportedServiceNames(self)
def supportsService(self, ServiceName)
def writeRegistryInfo(self, regKey, dummy, locationUrl)
def getImplementationName(self)
def getModuleFromUrl(self, url)
Definition: pythonloader.py:66
def splitUrl(url)
Definition: pythonloader.py:35
def checkForPythonPathBesideComponent(url)
Definition: pythonloader.py:42
def encfile(uni)
Definition: pythonloader.py:57
def fileUrlToSystemPath(url)
Definition: unohelper.py:182
def absolutize(path, relativeUrl)
Definition: unohelper.py:186