calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / pyuno / source / loader / pythonloader.py
blob02f901942cbb19f8f2ab2132206d2de8328b8e30
1 # -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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 types
23 import os
24 from urllib.parse import unquote
25 from com.sun.star.uno import Exception,RuntimeException
26 from com.sun.star.loader import XImplementationLoader
27 from com.sun.star.lang import XServiceInfo
29 MODULE_PROTOCOL = "vnd.openoffice.pymodule:"
30 DEBUG = 0
32 g_supportedServices = "com.sun.star.loader.Python", # referenced by the native C++ loader !
33 g_implementationName = "org.openoffice.comp.pyuno.Loader" # referenced by the native C++ loader !
35 def 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)]
41 g_loadedComponents = {}
42 def checkForPythonPathBesideComponent( url ):
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 )
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 )
57 def encfile(uni):
58 return uni.encode( sys.getfilesystemencoding())
60 class Loader( XImplementationLoader, XServiceInfo, unohelper.Base ):
61 def __init__(self, ctx ):
62 if DEBUG:
63 print("pythonloader.Loader ctor")
64 self.ctx = ctx
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 )
75 if DEBUG:
76 print("pythonloader: after expansion " + protocol + ":" + dependent)
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 )
83 # did we load the module already ?
84 mod = g_loadedComponents.get( url )
85 if not mod:
86 mod = types.ModuleType("uno_component")
88 # check for pythonpath.zip beside .py files
89 checkForPythonPathBesideComponent( url[0:url.rfind('/')] )
91 # read the file
92 filename = unohelper.fileUrlToSystemPath( url )
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"
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
130 def activate( self, implementationName, dummy, locationUrl, regKey ):
131 if DEBUG:
132 print("pythonloader.Loader.activate")
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)
143 def writeRegistryInfo( self, regKey, dummy, locationUrl ):
144 if DEBUG:
145 print( "pythonloader.Loader.writeRegistryInfo" )
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 )
154 def getImplementationName( self ):
155 return g_implementationName
157 def supportsService( self, ServiceName ):
158 return ServiceName in self.getSupportedServiceNames()
160 def getSupportedServiceNames( self ):
161 return g_supportedServices
163 # vim: set shiftwidth=4 softtabstop=4 expandtab: