Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / pyuno / source / loader / pythonloader.py
blob3074d0f628a93516e2f0b682bece29a718884e7b
1 # -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 # This file is part of the LibreOffice project.
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/.
9 # This file incorporates work covered by the following license notice:
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 .
19 import uno
20 import unohelper
21 import sys
22 import imp
23 import os
24 from com.sun.star.uno import Exception,RuntimeException
25 from com.sun.star.loader import XImplementationLoader
26 from com.sun.star.lang import XServiceInfo
28 MODULE_PROTOCOL = "vnd.openoffice.pymodule:"
29 DEBUG = 0
31 g_supportedServices = "com.sun.star.loader.Python", # referenced by the native C++ loader !
32 g_implementationName = "org.openoffice.comp.pyuno.Loader" # referenced by the native C++ loader !
34 def splitUrl( url ):
35 nColon = url.find( ":" )
36 if -1 == nColon:
37 raise RuntimeException( "PythonLoader: No protocol in url " + url, None )
38 return url[0:nColon], url[nColon+1:len(url)]
40 g_loadedComponents = {}
41 def checkForPythonPathBesideComponent( url ):
42 path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
43 if DEBUG == 1:
44 print(b"checking for existence of " + encfile( path ))
45 if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
46 if DEBUG == 1:
47 print(b"adding " + encfile( path ) + b" to sys.path")
48 sys.path.append( path )
50 path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
51 if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
52 if DEBUG == 1:
53 print(b"adding " + encfile( path ) + b" to sys.path")
54 sys.path.append( path )
56 def encfile(uni):
57 return uni.encode( sys.getfilesystemencoding())
59 class Loader( XImplementationLoader, XServiceInfo, unohelper.Base ):
60 def __init__(self, ctx ):
61 if DEBUG:
62 print("pythonloader.Loader ctor")
63 self.ctx = ctx
65 def getModuleFromUrl( self, url ):
66 if DEBUG:
67 print("pythonloader: interpreting url " + url)
68 protocol, dependent = splitUrl( url )
69 if "vnd.sun.star.expand" == protocol:
70 exp = self.ctx.getValueByName( "/singletons/com.sun.star.util.theMacroExpander" )
71 url = exp.expandMacros(dependent)
72 protocol,dependent = splitUrl( url )
74 if DEBUG:
75 print("pythonloader: after expansion " + protocol + ":" + dependent)
77 try:
78 if "file" == protocol:
79 # remove \..\ sequence, which may be useful e.g. in the build env
80 url = unohelper.absolutize( url, url )
82 # did we load the module already ?
83 mod = g_loadedComponents.get( url )
84 if not mod:
85 mod = imp.new_module("uno_component")
87 # check for pythonpath.zip beside .py files
88 checkForPythonPathBesideComponent( url[0:url.rfind('/')] )
90 # read the file
91 filename = unohelper.fileUrlToSystemPath( url )
93 if sys.version >= '3':
94 fileHandle = open( filename, encoding='utf_8' )
95 else:
96 fileHandle = open( filename )
97 src = fileHandle.read().replace("\r","")
98 if not src.endswith( "\n" ):
99 src = src + "\n"
101 # compile and execute the module
102 codeobject = compile( src, encfile(filename), "exec" )
103 exec(codeobject, mod.__dict__)
104 mod.__file__ = encfile(filename)
105 g_loadedComponents[url] = mod
106 return mod
107 elif "vnd.openoffice.pymodule" == protocol:
108 nSlash = dependent.rfind('/')
109 if -1 != nSlash:
110 path = unohelper.fileUrlToSystemPath( dependent[0:nSlash] )
111 dependent = dependent[nSlash+1:len(dependent)]
112 if not path in sys.path:
113 sys.path.append( path )
114 mod = __import__( dependent )
115 path_component, dot, rest = dependent.partition('.')
116 while dot == '.':
117 path_component, dot, rest = rest.partition('.')
118 mod = getattr(mod, path_component)
119 return mod
120 else:
121 if DEBUG:
122 print("Unknown protocol '" + protocol + "'");
123 raise RuntimeException( "PythonLoader: Unknown protocol " +
124 protocol + " in url " +url, self )
125 except Exception as e:
126 if DEBUG:
127 print ("Python import exception " + str(type(e)) +
128 " message " + str(e) + " args " + str(e.args));
129 raise RuntimeException( "Couldn't load " + url + " for reason " + str(e), None )
130 return None
132 def activate( self, implementationName, dummy, locationUrl, regKey ):
133 if DEBUG:
134 print("pythonloader.Loader.activate")
136 mod = self.getModuleFromUrl( locationUrl )
137 implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
138 if DEBUG:
139 print ("Fetched ImplHelper as " + str(implHelper))
140 if implHelper is None:
141 return mod.getComponentFactory( implementationName, self.ctx.ServiceManager, regKey )
142 else:
143 return implHelper.getComponentFactory( implementationName,regKey,self.ctx.ServiceManager)
145 def writeRegistryInfo( self, regKey, dummy, locationUrl ):
146 if DEBUG:
147 print( "pythonloader.Loader.writeRegistryInfo" )
149 mod = self.getModuleFromUrl( locationUrl )
150 implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
151 if implHelper is None:
152 return mod.writeRegistryInfo( self.ctx.ServiceManager, regKey )
153 else:
154 return implHelper.writeRegistryInfo( regKey, self.ctx.ServiceManager )
156 def getImplementationName( self ):
157 return g_implementationName
159 def supportsService( self, ServiceName ):
160 return ServiceName in self.serviceNames
162 def getSupportedServiceNames( self ):
163 return g_supportedServices
165 # vim:set shiftwidth=4 softtabstop=4 expandtab: