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 .
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:"
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 !
36 nColon
= url
.find( ":" )
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" );
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
:
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
:
54 print(b
"adding " + encfile( path
) + b
" to sys.path")
55 sys
.path
.append( path
)
58 return uni
.encode( sys
.getfilesystemencoding())
60 class Loader( XImplementationLoader
, XServiceInfo
, unohelper
.Base
):
61 def __init__(self
, ctx
):
63 print("pythonloader.Loader ctor")
66 def getModuleFromUrl( self
, url
):
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
)
76 print("pythonloader: after expansion " + protocol
+ ":" + dependent
)
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
)
86 mod
= types
.ModuleType("uno_component")
88 # check for pythonpath.zip beside .py files
89 checkForPythonPathBesideComponent( url
[0:url
.rfind('/')] )
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" ):
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
105 elif "vnd.openoffice.pymodule" == protocol
:
106 nSlash
= dependent
.rfind('/')
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('.')
115 path_component
, dot
, rest
= rest
.partition('.')
116 mod
= getattr(mod
, path_component
)
120 print("Unknown protocol '" + protocol
+ "'");
121 raise RuntimeException( "PythonLoader: Unknown protocol " +
122 protocol
+ " in url " +url
, self
)
123 except Exception as e
:
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 )
130 def activate( self
, implementationName
, dummy
, locationUrl
, regKey
):
132 print("pythonloader.Loader.activate")
134 mod
= self
.getModuleFromUrl( locationUrl
)
135 implHelper
= mod
.__dict
__.get( "g_ImplementationHelper" , None )
137 print ("Fetched ImplHelper as " + str(implHelper
))
138 if implHelper
is None:
139 return mod
.getComponentFactory( implementationName
, self
.ctx
.ServiceManager
, regKey
)
141 return implHelper
.getComponentFactory( implementationName
,regKey
,self
.ctx
.ServiceManager
)
143 def writeRegistryInfo( self
, regKey
, dummy
, locationUrl
):
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
)
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: