summaryrefslogtreecommitdiffstats
path: root/pyuno/source/loader/pythonloader.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyuno/source/loader/pythonloader.py')
-rw-r--r--pyuno/source/loader/pythonloader.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/pyuno/source/loader/pythonloader.py b/pyuno/source/loader/pythonloader.py
new file mode 100644
index 000000000..02f901942
--- /dev/null
+++ b/pyuno/source/loader/pythonloader.py
@@ -0,0 +1,163 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+import uno
+import unohelper
+import sys
+import types
+import os
+from urllib.parse import unquote
+from com.sun.star.uno import Exception,RuntimeException
+from com.sun.star.loader import XImplementationLoader
+from com.sun.star.lang import XServiceInfo
+
+MODULE_PROTOCOL = "vnd.openoffice.pymodule:"
+DEBUG = 0
+
+g_supportedServices = "com.sun.star.loader.Python", # referenced by the native C++ loader !
+g_implementationName = "org.openoffice.comp.pyuno.Loader" # referenced by the native C++ loader !
+
+def splitUrl( url ):
+ nColon = url.find( ":" )
+ if -1 == nColon:
+ raise RuntimeException( "PythonLoader: No protocol in url " + url, None )
+ return url[0:nColon], url[nColon+1:len(url)]
+
+g_loadedComponents = {}
+def checkForPythonPathBesideComponent( url ):
+ path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
+ if DEBUG == 1:
+ print(b"checking for existence of " + encfile( path ))
+ if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
+ if DEBUG == 1:
+ print(b"adding " + encfile( path ) + b" to sys.path")
+ sys.path.append( path )
+
+ path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
+ if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
+ if DEBUG == 1:
+ print(b"adding " + encfile( path ) + b" to sys.path")
+ sys.path.append( path )
+
+def encfile(uni):
+ return uni.encode( sys.getfilesystemencoding())
+
+class Loader( XImplementationLoader, XServiceInfo, unohelper.Base ):
+ def __init__(self, ctx ):
+ if DEBUG:
+ print("pythonloader.Loader ctor")
+ self.ctx = ctx
+
+ def getModuleFromUrl( self, url ):
+ if DEBUG:
+ print("pythonloader: interpreting url " + url)
+ protocol, dependent = splitUrl( url )
+ if "vnd.sun.star.expand" == protocol:
+ exp = self.ctx.getValueByName( "/singletons/com.sun.star.util.theMacroExpander" )
+ url = exp.expandMacros(unquote(dependent))
+ protocol,dependent = splitUrl( url )
+
+ if DEBUG:
+ print("pythonloader: after expansion " + protocol + ":" + dependent)
+
+ try:
+ if "file" == protocol:
+ # remove \..\ sequence, which may be useful e.g. in the build env
+ url = unohelper.absolutize( url, url )
+
+ # did we load the module already ?
+ mod = g_loadedComponents.get( url )
+ if not mod:
+ mod = types.ModuleType("uno_component")
+
+ # check for pythonpath.zip beside .py files
+ checkForPythonPathBesideComponent( url[0:url.rfind('/')] )
+
+ # read the file
+ filename = unohelper.fileUrlToSystemPath( url )
+
+ with open( filename, encoding='utf_8' ) as fileHandle:
+ src = fileHandle.read().replace("\r","")
+ if not src.endswith( "\n" ):
+ src = src + "\n"
+
+ # compile and execute the module
+ codeobject = compile( src, encfile(filename), "exec" )
+ mod.__file__ = filename
+ exec(codeobject, mod.__dict__)
+ g_loadedComponents[url] = mod
+ return mod
+ elif "vnd.openoffice.pymodule" == protocol:
+ nSlash = dependent.rfind('/')
+ if -1 != nSlash:
+ path = unohelper.fileUrlToSystemPath( dependent[0:nSlash] )
+ dependent = dependent[nSlash+1:len(dependent)]
+ if not path in sys.path:
+ sys.path.append( path )
+ mod = __import__( dependent )
+ path_component, dot, rest = dependent.partition('.')
+ while dot == '.':
+ path_component, dot, rest = rest.partition('.')
+ mod = getattr(mod, path_component)
+ return mod
+ else:
+ if DEBUG:
+ print("Unknown protocol '" + protocol + "'");
+ raise RuntimeException( "PythonLoader: Unknown protocol " +
+ protocol + " in url " +url, self )
+ except Exception as e:
+ if DEBUG:
+ print ("Python import exception " + str(type(e)) +
+ " message " + str(e) + " args " + str(e.args));
+ raise RuntimeException( "Couldn't load " + url + " for reason " + str(e), None )
+ return None
+
+ def activate( self, implementationName, dummy, locationUrl, regKey ):
+ if DEBUG:
+ print("pythonloader.Loader.activate")
+
+ mod = self.getModuleFromUrl( locationUrl )
+ implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
+ if DEBUG:
+ print ("Fetched ImplHelper as " + str(implHelper))
+ if implHelper is None:
+ return mod.getComponentFactory( implementationName, self.ctx.ServiceManager, regKey )
+ else:
+ return implHelper.getComponentFactory( implementationName,regKey,self.ctx.ServiceManager)
+
+ def writeRegistryInfo( self, regKey, dummy, locationUrl ):
+ if DEBUG:
+ print( "pythonloader.Loader.writeRegistryInfo" )
+
+ mod = self.getModuleFromUrl( locationUrl )
+ implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
+ if implHelper is None:
+ return mod.writeRegistryInfo( self.ctx.ServiceManager, regKey )
+ else:
+ return implHelper.writeRegistryInfo( regKey, self.ctx.ServiceManager )
+
+ def getImplementationName( self ):
+ return g_implementationName
+
+ def supportsService( self, ServiceName ):
+ return ServiceName in self.getSupportedServiceNames()
+
+ def getSupportedServiceNames( self ):
+ return g_supportedServices
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab: