1# ************************************************************* 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20# ************************************************************* 21 22# XScript implementation for python 23import uno 24import unohelper 25import sys 26import os 27import imp 28import time 29import ast 30 31try: 32 unicode 33except NameError: 34 unicode = str 35 36class LogLevel: 37 NONE = 0 # production level 38 ERROR = 1 # for script developers 39 DEBUG = 2 # for script framework developers 40 41PYSCRIPT_LOG_ENV = "PYSCRIPT_LOG_LEVEL" 42PYSCRIPT_LOG_STDOUT_ENV = "PYSCRIPT_LOG_STDOUT" 43 44# Configuration ---------------------------------------------------- 45LogLevel.use = LogLevel.NONE 46if os.environ.get(PYSCRIPT_LOG_ENV) == "ERROR": 47 LogLevel.use = LogLevel.ERROR 48elif os.environ.get(PYSCRIPT_LOG_ENV) == "DEBUG": 49 LogLevel.use = LogLevel.DEBUG 50 51# True, writes to stdout (difficult on windows) 52# False, writes to user/Scripts/python/log.txt 53LOG_STDOUT = os.environ.get(PYSCRIPT_LOG_STDOUT_ENV, "1") != "0" 54 55ENABLE_EDIT_DIALOG=False # offers a minimal editor for editing. 56#------------------------------------------------------------------- 57 58def encfile(uni): 59 if sys.version_info[0] > 2: 60 return uni 61 else: 62 return uni.encode( sys.getfilesystemencoding()) 63 64def lastException2String(): 65 (excType,excInstance,excTraceback) = sys.exc_info() 66 ret = str(excType) + ": "+str(excInstance) + "\n" + \ 67 uno._uno_extract_printable_stacktrace( excTraceback ) 68 return ret 69 70def logLevel2String( level ): 71 ret = " NONE" 72 if level == LogLevel.ERROR: 73 ret = "ERROR" 74 elif level >= LogLevel.DEBUG: 75 ret = "DEBUG" 76 return ret 77 78def getLogTarget(): 79 ret = sys.stdout 80 if not LOG_STDOUT: 81 try: 82 pathSubst = uno.getComponentContext().ServiceManager.createInstance( 83 "com.sun.star.util.PathSubstitution" ) 84 userInstallation = pathSubst.getSubstituteVariableValue( "user" ) 85 if len( userInstallation ) > 0: 86 systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" ) 87 ret = open( systemPath , "a" ) 88 except Exception as e: 89 print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n") 90 return ret 91 92class Logger(LogLevel): 93 def __init__(self , target ): 94 self.target = target 95 96 def isDebugLevel( self ): 97 return self.use >= self.DEBUG 98 99 def debug( self, msg ): 100 if self.isDebugLevel(): 101 self.log( self.DEBUG, msg ) 102 103 def isErrorLevel( self ): 104 return self.use >= self.ERROR 105 106 def error( self, msg ): 107 if self.isErrorLevel(): 108 self.log( self.ERROR, msg ) 109 110 def log( self, level, msg ): 111 if self.use >= level: 112 try: 113 self.target.write( 114 time.asctime() + 115 " [" + 116 logLevel2String( level ) + 117 "] " + 118 encfile(msg) + 119 "\n" ) 120 self.target.flush() 121 except Exception as e: 122 print("Error during writing to stdout: " +lastException2String() + "\n") 123 124log = Logger( getLogTarget() ) 125 126log.debug( "pythonscript loading" ) 127 128#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider 129from com.sun.star.uno import RuntimeException 130from com.sun.star.lang import XServiceInfo 131from com.sun.star.io import IOException, XInputStream 132from com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command 133from com.sun.star.task import XInteractionHandler 134from com.sun.star.beans import XPropertySet, Property 135from com.sun.star.container import XNameContainer 136from com.sun.star.xml.sax import XDocumentHandler, InputSource 137from com.sun.star.uno import Exception as UnoException 138from com.sun.star.script import XInvocation 139from com.sun.star.awt import XActionListener 140 141from com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException 142from com.sun.star.script.browse import XBrowseNode 143from com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT 144from com.sun.star.util import XModifyListener 145 146LANGUAGENAME = "Python" 147GLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT" 148CALLABLE_CONTAINER_NAME = "g_exportedScripts" 149 150# pythonloader looks for a static g_ImplementationHelper variable 151g_ImplementationHelper = unohelper.ImplementationHelper() 152g_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME 153 154 155 156BLOCK_SIZE = 65536 157def readTextFromStream( inputStream ): 158 # read the file 159 code = uno.ByteSequence( b"" ) 160 while True: 161 read,out = inputStream.readBytes( None , BLOCK_SIZE ) 162 code = code + out 163 if read < BLOCK_SIZE: 164 break 165 if sys.version_info[0] > 2: 166 return str( code.value, 'utf-8' ) 167 else: 168 return code.value 169 170def toIniName( str ): 171 # TODO: what is the official way to get to know whether i am on the windows platform ? 172 if( hasattr(sys , "dllhandle") ): 173 return str + ".ini" 174 return str + "rc" 175 176class EmptyInputStream( unohelper.Base, XInputStream ): 177 def __init__( self ): 178 pass 179 180 def closeInput(self): 181 pass 182 183 def readBytes( self, seq, n ): 184 return 0, "" 185 186 def readSomeBytes( self, seq, n ): 187 return 0, "" 188 189 def skipBytes( self, n ): 190 pass 191 192 def available( self ): 193 return 0 194 195 196""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk 197 scriptURI is the system independent uri 198""" 199class MyUriHelper: 200 201 def __init__( self, ctx, location ): 202 self.s_UriMap = \ 203 { "share" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \ 204 "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \ 205 "user" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \ 206 "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" } 207 self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx) 208 if location.startswith( "vnd.sun.star.tdoc" ): 209 self.m_baseUri = location + "/Scripts/python" 210 self.m_scriptUriLocation = "document" 211 else: 212 self.m_baseUri = expandUri( self.s_UriMap[location] ) 213 self.m_scriptUriLocation = location 214 log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation ) 215 216 def getRootStorageURI( self ): 217 return self.m_baseUri 218 219 def getStorageURI( self, scriptURI ): 220 return self.scriptURI2StorageUri(scriptURI) 221 222 def getScriptURI( self, storageURI ): 223 return self.storageURI2ScriptUri(storageURI) 224 225 def storageURI2ScriptUri( self, storageURI ): 226 if not storageURI.startswith( self.m_baseUri ): 227 message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'" 228 log.debug( message ) 229 raise RuntimeException( message ) 230 231 ret = "vnd.sun.star.script:" + \ 232 storageURI[len(self.m_baseUri)+1:].replace("/","|") + \ 233 "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation 234 log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret ) 235 return ret 236 237 def scriptURI2StorageUri( self, scriptURI ): 238 try: 239 myUri = self.m_uriRefFac.parse(scriptURI) 240 ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" ) 241 log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret ) 242 return ret 243 except UnoException as e: 244 log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message) 245 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None ) 246 except Exception as e: 247 log.error( "error during converting scriptURI="+scriptURI + ": " + str(e)) 248 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None ) 249 250 251class ModuleEntry: 252 def __init__( self, lastRead, module ): 253 self.lastRead = lastRead 254 self.module = module 255 256def hasChanged( oldDate, newDate ): 257 return newDate.Year > oldDate.Year or \ 258 newDate.Month > oldDate.Month or \ 259 newDate.Day > oldDate.Day or \ 260 newDate.Hours > oldDate.Hours or \ 261 newDate.Minutes > oldDate.Minutes or \ 262 newDate.Seconds > oldDate.Seconds or \ 263 newDate.HundredthSeconds > oldDate.HundredthSeconds 264 265def ensureSourceState( code ): 266 if not code.endswith( "\n" ): 267 code = code + "\n" 268 code = code.replace( "\r", "" ) 269 return code 270 271 272def checkForPythonPathBesideScript( url ): 273 if url.startswith( "file:" ): 274 path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" ); 275 log.log( LogLevel.DEBUG, "checking for existence of " + path ) 276 if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 277 log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 278 sys.path.append( path ) 279 280 path = unohelper.fileUrlToSystemPath( url+"/pythonpath" ); 281 log.log( LogLevel.DEBUG, "checking for existence of " + path ) 282 if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 283 log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 284 sys.path.append( path ) 285 286 287class ScriptContext(unohelper.Base): 288 def __init__( self, ctx, doc, inv ): 289 self.ctx = ctx 290 self.doc = doc 291 self.inv = inv 292 293 # XScriptContext 294 def getDocument(self): 295 if self.doc: 296 return self.doc 297 return self.getDesktop().getCurrentComponent() 298 299 def getDesktop(self): 300 return self.ctx.ServiceManager.createInstanceWithContext( 301 "com.sun.star.frame.Desktop", self.ctx ) 302 303 def getComponentContext(self): 304 return self.ctx 305 306 def getInvocationContext(self): 307 return self.inv 308 309#---------------------------------- 310# Global Module Administration 311# does not fit together with script 312# engine lifetime management 313#---------------------------------- 314#g_scriptContext = ScriptContext( uno.getComponentContext(), None ) 315#g_modules = {} 316#def getModuleByUrl( url, sfa ): 317# entry = g_modules.get(url) 318# load = True 319# lastRead = sfa.getDateTimeModified( url ) 320# if entry: 321# if hasChanged( entry.lastRead, lastRead ): 322# log.debug("file " + url + " has changed, reloading") 323# else: 324# load = False 325# 326# if load: 327# log.debug( "opening >" + url + "<" ) 328# 329# code = readTextFromStream( sfa.openFileRead( url ) ) 330 331 # execute the module 332# entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 333# entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext 334# entry.module.__file__ = url 335# exec code in entry.module.__dict__ 336# g_modules[ url ] = entry 337# log.debug( "mapped " + url + " to " + str( entry.module ) ) 338# return entry.module 339 340class ProviderContext: 341 def __init__( self, storageType, sfa, uriHelper, scriptContext ): 342 self.storageType = storageType 343 self.sfa = sfa 344 self.uriHelper = uriHelper 345 self.scriptContext = scriptContext 346 self.modules = {} 347 self.rootUrl = None 348 self.mapPackageName2Path = None 349 350 def getTransientPartFromUrl( self, url ): 351 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 352 return rest[0:rest.find("/")] 353 354 def getPackageNameFromUrl( self, url ): 355 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 356 start = rest.find("/") +1 357 return rest[start:rest.find("/",start)] 358 359 360 def removePackageByUrl( self, url ): 361 items = list(self.mapPackageName2Path.items()) 362 for i in items: 363 if url in i[1].pathes: 364 self.mapPackageName2Path.pop(i[0]) 365 break 366 367 def addPackageByUrl( self, url ): 368 packageName = self.getPackageNameFromUrl( url ) 369 transientPart = self.getTransientPartFromUrl( url ) 370 log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl ) 371 if packageName in self.mapPackageName2Path: 372 package = self.mapPackageName2Path[ packageName ] 373 package.pathes = package.pathes + (url, ) 374 else: 375 package = Package( (url,), transientPart) 376 self.mapPackageName2Path[ packageName ] = package 377 378 def isUrlInPackage( self, url ): 379 values = list(self.mapPackageName2Path.values()) 380 for i in values: 381# print "checking " + url + " in " + str(i.pathes) 382 if url in i.pathes: 383 return True 384# print "false" 385 return False 386 387 def setPackageAttributes( self, mapPackageName2Path, rootUrl ): 388 self.mapPackageName2Path = mapPackageName2Path 389 self.rootUrl = rootUrl 390 391 def getPersistentUrlFromStorageUrl( self, url ): 392 # package name is the second directory 393 ret = url 394 if self.rootUrl: 395 pos = len( self.rootUrl) +1 396 ret = url[0:pos]+url[url.find("/",pos)+1:len(url)] 397 log.debug( "getPersistentUrlFromStorageUrl " + url + " -> "+ ret) 398 return ret 399 400 def getStorageUrlFromPersistentUrl( self, url): 401 ret = url 402 if self.rootUrl: 403 pos = len(self.rootUrl)+1 404 packageName = url[pos:url.find("/",pos+1)] 405 package = self.mapPackageName2Path[ packageName ] 406 ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)] 407 log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret) 408 return ret 409 410 def getFuncsByUrl( self, url ): 411 src = readTextFromStream( self.sfa.openFileRead( url ) ) 412 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 413 src = ensureSourceState( src ) 414 415 allFuncs = [] 416 g_exportedScripts = [] 417 418 a = ast.parse(src, url) 419 420 if isinstance(a, ast.Module): 421 for node in a.body: 422 if isinstance(node, ast.FunctionDef): 423 allFuncs.append(node.name) 424 elif isinstance(node, ast.Assign): 425 is_exported = False 426 for subnode in node.targets: 427 if isinstance(subnode, ast.Name) and \ 428 subnode.id == "g_exportedScripts": 429 is_exported = True 430 break 431 if is_exported: 432 value_node = node.value 433 if isinstance(value_node, ast.List) or \ 434 isinstance(value_node, ast.Tuple): 435 for elt in value_node.elts: 436 if isinstance(elt, ast.Str): 437 g_exportedScripts.append(elt.s) 438 elif isinstance(elt, ast.Name): 439 g_exportedScripts.append(elt.id) 440 elif isinstance(value_node, ast.Str): 441 g_exportedScripts.append(value_node.s) 442 elif isinstance(value_node, ast.Name): 443 g_exportedScripts.append(value_node.id) 444 return g_exportedScripts 445 return allFuncs 446 447 def getModuleByUrl( self, url ): 448 entry = self.modules.get(url) 449 load = True 450 lastRead = self.sfa.getDateTimeModified( url ) 451 if entry: 452 if hasChanged( entry.lastRead, lastRead ): 453 log.debug( "file " + url + " has changed, reloading" ) 454 else: 455 load = False 456 457 if load: 458 log.debug( "opening >" + url + "<" ) 459 460 src = readTextFromStream( self.sfa.openFileRead( url ) ) 461 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 462 src = ensureSourceState( src ) 463 464 # execute the module 465 entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 466 entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext 467 468 code = None 469 if url.startswith( "file:" ): 470 code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" ) 471 else: 472 code = compile( src, url, "exec" ) 473 exec(code, entry.module.__dict__) 474 entry.module.__file__ = url 475 self.modules[ url ] = entry 476 log.debug( "mapped " + url + " to " + str( entry.module ) ) 477 return entry.module 478 479#-------------------------------------------------- 480def isScript( candidate ): 481 ret = False 482 if isinstance( candidate, type(isScript) ): 483 ret = True 484 return ret 485 486#------------------------------------------------------- 487class ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, XInvocation, XActionListener ): 488 def __init__( self, provCtx, parent, fileName, funcName ): 489 self.parent = parent 490 self.fileName = fileName 491 self.funcName = funcName 492 self.provCtx = provCtx 493 494 def uri( self ): 495 return self.parent.uri() 496 497 def getName( self ): 498 return self.funcName 499 500 def getChildNodes(self): 501 return () 502 503 def hasChildNodes(self): 504 return False 505 506 def getType( self): 507 return SCRIPT 508 509 def getPropertyValue( self, name ): 510 ret = None 511 try: 512 if name == "URI": 513 ret = self.provCtx.uriHelper.getScriptURI( 514 self.provCtx.getPersistentUrlFromStorageUrl( self.uri() + "$" + self.funcName ) ) 515 elif name == "Editable" and ENABLE_EDIT_DIALOG: 516 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 517 518 log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 519 except Exception as e: 520 log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String()) 521 raise 522 523 return ret 524 def setPropertyValue( self, name, value ): 525 log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 526 def getPropertySetInfo( self ): 527 log.debug( "ScriptBrowseNode.getPropertySetInfo called " ) 528 return None 529 530 def getIntrospection( self ): 531 return None 532 533 def invoke( self, name, params, outparamindex, outparams ): 534 if name == "Editable": 535 servicename = "com.sun.star.awt.DialogProvider" 536 ctx = self.provCtx.scriptContext.getComponentContext() 537 dlgprov = ctx.ServiceManager.createInstanceWithContext( 538 servicename, ctx ) 539 540 self.editor = dlgprov.createDialog( 541 "vnd.sun.star.script:" + 542 "ScriptBindingLibrary.MacroEditor?location=application") 543 544 code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri())) 545 code = ensureSourceState( code ) 546 self.editor.getControl("EditorTextField").setText(code) 547 548 self.editor.getControl("RunButton").setActionCommand("Run") 549 self.editor.getControl("RunButton").addActionListener(self) 550 self.editor.getControl("SaveButton").setActionCommand("Save") 551 self.editor.getControl("SaveButton").addActionListener(self) 552 553 self.editor.execute() 554 555 return None, (), () 556 557 def actionPerformed( self, event ): 558 try: 559 if event.ActionCommand == "Run": 560 code = self.editor.getControl("EditorTextField").getText() 561 code = ensureSourceState( code ) 562 mod = imp.new_module("ooo_script_framework") 563 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext 564 exec(code, mod.__dict__) 565 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None ) 566 if not values: 567 values = list(mod.__dict__.values()) 568 569 for i in values: 570 if isScript( i ): 571 i() 572 break 573 574 elif event.ActionCommand == "Save": 575 toWrite = uno.ByteSequence( 576 str( 577 self.editor.getControl("EditorTextField").getText().encode( 578 sys.getdefaultencoding())) ) 579 copyUrl = self.uri() + ".orig" 580 self.provCtx.sfa.move( self.uri(), copyUrl ) 581 out = self.provCtx.sfa.openFileWrite( self.uri() ) 582 out.writeBytes( toWrite ) 583 out.close() 584 self.provCtx.sfa.kill( copyUrl ) 585# log.debug("Save is not implemented yet") 586# text = self.editor.getControl("EditorTextField").getText() 587# log.debug("Would save: " + text) 588 except Exception as e: 589 # TODO: add an error box here ! 590 log.error( lastException2String() ) 591 592 593 def setValue( self, name, value ): 594 return None 595 596 def getValue( self, name ): 597 return None 598 599 def hasMethod( self, name ): 600 return False 601 602 def hasProperty( self, name ): 603 return False 604 605 606#------------------------------------------------------- 607class FileBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ): 608 def __init__( self, provCtx, parent, name ): 609 self.provCtx = provCtx 610 self.parent = parent 611 self.name = name 612 self.funcnames = None 613 614 def uri( self ): 615 return self.parent.rootUrl + "/" + self.name + ".py" 616 617 def getName( self ): 618 return self.name 619 620 def getChildNodes(self): 621 ret = () 622 try: 623 self.funcnames = self.provCtx.getFuncsByUrl( self.uri() ) 624 625 scriptNodeList = [] 626 for i in self.funcnames: 627 scriptNodeList.append( 628 ScriptBrowseNode( 629 self.provCtx, self, self.name, i )) 630 ret = tuple( scriptNodeList ) 631 except Exception as e: 632 text = lastException2String() 633 log.error( "FileBrowseNode.getChildNodes error while evaluating " + self.uri() + ":" + text ) 634 raise 635 return ret 636 637 def hasChildNodes(self): 638 try: 639 return len(self.getChildNodes()) > 0 640 except Exception as e: 641 return False 642 643 def getType( self): 644 return CONTAINER 645 646 # XPropertySet 647 648 def getPropertyValue( self, name ): 649 ret = None 650 try: 651 if name == "Editable": 652 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 653 elif name == "Deletable": 654 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 655 elif name == "Renamable": 656 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 657 658 log.debug( "FileBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 659 except Exception as e: 660 log.error( "FileBrowseNode.getPropertyValue error " + lastException2String()) 661 raise 662 663 return ret 664 665 def setPropertyValue( self, name, value ): 666 log.debug( "FileBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 667 668 def getPropertySetInfo( self ): 669 log.debug( "FileBrowseNode.getPropertySetInfo called " ) 670 return None 671 672 # XInvocation 673 674 def getIntrospection( self ): 675 log.debug( "FileBrowseNode.getIntrospection() called" ) 676 return None 677 678 def invoke( self, name, params, outparamindex, outparams ): 679 log.debug("FileBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams)) 680 try: 681 if name == "Editable": 682 log.error("Editable not implemented") 683 elif name == "Deletable": 684 self.provCtx.sfa.kill( self.uri() ) 685 return True, (), () 686 elif name == "Renamable": 687 if params is None or not params: 688 raise IllegalArgumentException( "invoke with Creatable needs the name in params" ) 689 newUri = self.parent.rootUrl + "/" + params[0] + ".py" 690 self.provCtx.sfa.move( self.uri(), newUri ) 691 self.name = params[0] 692 return self, (), () 693 except Exception as e: 694 log.error( "FileBrowseNode.invoke error " + lastException2String() ) 695 raise 696 return None, (), () 697 698 def setValue( self, name, value ): 699 return None 700 701 def getValue( self, name ): 702 log.debug( "FileBrowseNode.getValue() called" ) 703 return None 704 705 def hasMethod( self, name ): 706 return False 707 708 def hasProperty( self, name ): 709 return False 710 711 712class DirBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ): 713 def __init__( self, provCtx, name, rootUrl, depth ): 714 self.provCtx = provCtx 715 self.name = name 716 self.rootUrl = rootUrl 717 self.depth = depth 718 log.debug( "DirBrowseNode constructor for " + name + "," + rootUrl ) 719 720 def getName( self ): 721 return self.name 722 723 def getChildNodes( self ): 724 try: 725 log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl ) 726 contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True ) 727 browseNodeList = [] 728 for i in contents: 729 if i.endswith( ".py" ): 730 log.debug( "adding filenode " + i ) 731 browseNodeList.append( 732 FileBrowseNode( self.provCtx, self, i[i.rfind("/")+1:len(i)-3] ) ) 733 elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"): 734 log.debug( "adding DirBrowseNode " + i ) 735 browseNodeList.append( 736 DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)], i, self.depth + 1 ) ) 737 return tuple( browseNodeList ) 738 except Exception as e: 739 text = lastException2String() 740 log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl) 741 log.error( text) 742 return () 743 744 def hasChildNodes( self ): 745 return True 746 747 def getType( self ): 748 return CONTAINER 749 750 # XScriptProvider 751 752 def getScript( self, uri ): 753 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 754 raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 755 756 # XPropertySet 757 758 def getPropertyValue( self, name ): 759 ret = None 760 try: 761 if name == "Creatable": 762 ret = True 763 elif name == "Deletable": 764 ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl ) 765 elif name == "Renamable": 766 ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl ) 767 768 log.debug( "DirBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 769 except Exception as e: 770 log.error( "DirBrowseNode.getPropertyValue error " + lastException2String()) 771 raise 772 773 return ret 774 775 def setPropertyValue( self, name, value ): 776 log.debug( "DirBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 777 778 def getPropertySetInfo( self ): 779 log.debug( "DirBrowseNode.getPropertySetInfo called " ) 780 return None 781 782 # XInvocation 783 784 def getIntrospection( self ): 785 log.debug( "DirBrowseNode.getIntrospection() called" ) 786 return None 787 788 def invoke( self, name, params, outparamindex, outparams ): 789 log.debug("DirBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams)) 790 try: 791 if name == "Creatable": 792 if params is None or not params: 793 raise IllegalArgumentException( "invoke with Creatable needs the name in params" ) 794 if self.depth == 0: 795 subFolderUrl = self.rootUrl + "/" + params[0] 796 self.provCtx.sfa.createFolder( subFolderUrl ) 797 childNode = DirBrowseNode( self.provCtx, subFolderUrl[subFolderUrl.rfind("/")+1:len(subFolderUrl)], subFolderUrl, self.depth + 1 ) 798 return childNode, (), () 799 else: 800 scriptUrl = self.rootUrl + "/" + params[0] + ".py" 801 # Creates an empty file 802 self.provCtx.sfa.writeFile( scriptUrl, EmptyInputStream() ) 803 childNode = FileBrowseNode( self.provCtx, self, params[0] ) 804 return childNode, (), () 805 elif name == "Deletable": 806 self.provCtx.sfa.kill( self.rootUrl ) 807 return True, (), () 808 elif name == "Renamable": 809 if params is None or not params: 810 raise IllegalArgumentException( "invoke with Renamable needs the name in params" ) 811 newUrl = self.rootUrl[0:self.rootUrl.rfind("/")+1] + params[0] 812 self.provCtx.sfa.move( self.rootUrl, newUrl ) 813 self.rootUrl = newUrl 814 self.name = params[0] 815 return self, (), () 816 except Exception as e: 817 log.error( "DirBrowseNode.invoke error: " + lastException2String()) 818 raise 819 return None, (), () 820 821 def setValue( self, name, value ): 822 return None 823 824 def getValue( self, name ): 825 log.debug( "DirBrowseNode.getValue() called" ) 826 return None 827 828 def hasMethod( self, name ): 829 return False 830 831 def hasProperty( self, name ): 832 return False 833 834 835class ManifestHandler( XDocumentHandler, unohelper.Base ): 836 def __init__( self, rootUrl ): 837 self.rootUrl = rootUrl 838 839 def startDocument( self ): 840 self.urlList = [] 841 842 def endDocument( self ): 843 pass 844 845 def startElement( self , name, attlist): 846 if name == "manifest:file-entry": 847 if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script": 848 self.urlList.append( 849 self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) ) 850 851 def endElement( self, name ): 852 pass 853 854 def characters ( self, chars ): 855 pass 856 857 def ignoreableWhitespace( self, chars ): 858 pass 859 860 def setDocumentLocator( self, locator ): 861 pass 862 863def isPyFileInPath( sfa, path ): 864 ret = False 865 contents = sfa.getFolderContents( path, True ) 866 for i in contents: 867 if sfa.isFolder(i): 868 ret = isPyFileInPath(sfa,i) 869 else: 870 if i.endswith(".py"): 871 ret = True 872 if ret: 873 break 874 return ret 875 876# extracts META-INF directory from 877def getPathesFromPackage( rootUrl, sfa ): 878 ret = () 879 try: 880 fileUrl = rootUrl + "/META-INF/manifest.xml" 881 inputStream = sfa.openFileRead( fileUrl ) 882 parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" ) 883 handler = ManifestHandler( rootUrl ) 884 parser.setDocumentHandler( handler ) 885 parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) ) 886 for i in tuple(handler.urlList): 887 if not isPyFileInPath( sfa, i ): 888 handler.urlList.remove(i) 889 ret = tuple( handler.urlList ) 890 except UnoException as e: 891 text = lastException2String() 892 log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text ) 893 pass 894 return ret 895 896 897class Package: 898 def __init__( self, pathes, transientPathElement ): 899 self.pathes = pathes 900 self.transientPathElement = transientPathElement 901 902class DummyInteractionHandler( unohelper.Base, XInteractionHandler ): 903 def __init__( self ): 904 pass 905 def handle( self, event): 906 log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) ) 907 908class DummyProgressHandler( unohelper.Base, XProgressHandler ): 909 def __init__( self ): 910 pass 911 912 def push( self,status ): 913 log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) ) 914 def update( self,status ): 915 log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) ) 916 def pop( self ): 917 log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) ) 918 919class CommandEnvironment(unohelper.Base, XCommandEnvironment): 920 def __init__( self ): 921 self.progressHandler = DummyProgressHandler() 922 self.interactionHandler = DummyInteractionHandler() 923 def getInteractionHandler( self ): 924 return self.interactionHandler 925 def getProgressHandler( self ): 926 return self.progressHandler 927 928#maybe useful for debugging purposes 929#class ModifyListener( unohelper.Base, XModifyListener ): 930# def __init__( self ): 931# pass 932# def modified( self, event ): 933# log.debug( "pythonscript: ModifyListener.modified " + str( event ) ) 934# def disposing( self, event ): 935# log.debug( "pythonscript: ModifyListener.disposing " + str( event ) ) 936 937def getModelFromDocUrl(ctx, url): 938 """Get document model from document url.""" 939 doc = None 940 args = ("Local", "Office") 941 ucb = ctx.getServiceManager().createInstanceWithArgumentsAndContext( 942 "com.sun.star.ucb.UniversalContentBroker", args, ctx) 943 identifier = ucb.createContentIdentifier(url) 944 content = ucb.queryContent(identifier) 945 p = Property() 946 p.Name = "DocumentModel" 947 p.Handle = -1 948 949 c = Command() 950 c.Handle = -1 951 c.Name = "getPropertyValues" 952 c.Argument = uno.Any("[]com.sun.star.beans.Property", (p,)) 953 954 env = CommandEnvironment() 955 try: 956 ret = content.execute(c, 0, env) 957 doc = ret.getObject(1, None) 958 except Exception as e: 959 log.isErrorLevel() and log.error("getModelFromDocUrl: %s" % url) 960 return doc 961 962def mapStorageType2PackageContext( storageType ): 963 ret = storageType 964 if( storageType == "share:uno_packages" ): 965 ret = "shared" 966 if( storageType == "user:uno_packages" ): 967 ret = "user" 968 return ret 969 970def getPackageName2PathMap( sfa, storageType ): 971 ret = {} 972 packageManagerFactory = uno.getComponentContext().getValueByName( 973 "/singletons/com.sun.star.deployment.thePackageManagerFactory" ) 974 packageManager = packageManagerFactory.getPackageManager( 975 mapStorageType2PackageContext(storageType)) 976# packageManager.addModifyListener( ModifyListener() ) 977 log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" ) 978 packages = packageManager.getDeployedPackages( 979 packageManager.createAbortChannel(), CommandEnvironment( ) ) 980 log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" ) 981 982 for i in packages: 983 log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" ) 984 transientPathElement = penultimateElement( i.URL ) 985 j = expandUri( i.URL ) 986 pathes = getPathesFromPackage( j, sfa ) 987 if len( pathes ) > 0: 988 # map package name to url, we need this later 989 log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) ) 990 ret[ lastElement( j ) ] = Package( pathes, transientPathElement ) 991 return ret 992 993def penultimateElement( aStr ): 994 lastSlash = aStr.rindex("/") 995 penultimateSlash = aStr.rindex("/",0,lastSlash-1) 996 return aStr[ penultimateSlash+1:lastSlash ] 997 998def lastElement( aStr): 999 return aStr[ aStr.rfind( "/" )+1:len(aStr)] 1000 1001class PackageBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ): 1002 def __init__( self, provCtx, name, rootUrl ): 1003 self.provCtx = provCtx 1004 self.name = name 1005 self.rootUrl = rootUrl 1006 1007 def getName( self ): 1008 return self.name 1009 1010 def getChildNodes( self ): 1011 items = list(self.provCtx.mapPackageName2Path.items()) 1012 browseNodeList = [] 1013 for i in items: 1014 if len( i[1].pathes ) == 1: 1015 browseNodeList.append( 1016 DirBrowseNode( self.provCtx, i[0], i[1].pathes[0], 0 )) 1017 else: 1018 for j in i[1].pathes: 1019 browseNodeList.append( 1020 DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j, 0 ) ) 1021 return tuple( browseNodeList ) 1022 1023 def hasChildNodes( self ): 1024 return len( self.mapPackageName2Path ) > 0 1025 1026 def getType( self ): 1027 return CONTAINER 1028 1029 def getScript( self, uri ): 1030 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 1031 raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 ) 1032 1033 # XPropertySet 1034 1035 def getPropertyValue( self, name ): 1036 ret = None 1037 log.debug( "PackageBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 1038 return ret 1039 1040 def setPropertyValue( self, name, value ): 1041 log.debug( "PackageBrowseNode.setPropertyValue " + name + "=" +str( value ) ) 1042 1043 def getPropertySetInfo( self ): 1044 log.debug( "PackageBrowseNode.getPropertySetInfo called" ) 1045 return None 1046 1047 # XInvocation 1048 1049 def getIntrospection( self ): 1050 log.debug( "PackageBrowseNode.getIntrospection() called" ) 1051 return None 1052 1053 def invoke( self, name, params, outparamindex, outparams ): 1054 log.debug( "PackageBrowseNode.invoke called for " + name + "," + str( params ) + "," + str( outparamindex ) + "," + str( outparams ) ) 1055 return None, (), () 1056 1057 def setValue( self, name, value ): 1058 log.debug( "PackageBrowseNode.setValue" ) 1059 return None 1060 1061 def getValue( self, name ): 1062 log.debug( "PackageBrowseNode.getValue" ) 1063 return None 1064 1065 def hasMethod( self, name ): 1066 log.debug( "PackageBrowseNode.hasMethod" ) 1067 return False 1068 1069 def hasProperty( self, name ): 1070 log.debug( "PackageBrowseNode.hasProperty" ) 1071 return False 1072 1073 1074 1075class PythonScript( unohelper.Base, XScript ): 1076 def __init__( self, func, mod ): 1077 self.func = func 1078 self.mod = mod 1079 def invoke(self, args, out, outindex ): 1080 log.debug( "PythonScript.invoke " + str( args ) ) 1081 try: 1082 ret = self.func( *args ) 1083 except UnoException as e: 1084 # UNO Exception continue to fly ... 1085 text = lastException2String() 1086 complete = "Error during invoking function " + \ 1087 str(self.func.__name__) + " in module " + \ 1088 self.mod.__file__ + " (" + text + ")" 1089 log.debug( complete ) 1090 # some people may beat me up for modifying the exception text, 1091 # but otherwise office just shows 1092 # the type name and message text with no more information, 1093 # this is really bad for most users. 1094 e.Message = e.Message + " (" + complete + ")" 1095 raise 1096 except Exception as e: 1097 # General python exception are converted to uno RuntimeException 1098 text = lastException2String() 1099 complete = "Error during invoking function " + \ 1100 str(self.func.__name__) + " in module " + \ 1101 self.mod.__file__ + " (" + text + ")" 1102 log.debug( complete ) 1103 raise RuntimeException( complete , self ) 1104 log.debug( "PythonScript.invoke ret = " + str( ret ) ) 1105 return ret, (), () 1106 1107def expandUri( uri ): 1108 if uri.startswith( "vnd.sun.star.expand:" ): 1109 uri = uri.replace( "vnd.sun.star.expand:", "",1) 1110 uri = uno.getComponentContext().getByName( 1111 "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri ) 1112 if uri.startswith( "file:" ): 1113 uri = uno.absolutize("",uri) # necessary to get rid of .. in uri 1114 return uri 1115 1116#-------------------------------------------------------------- 1117class PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer, XPropertySet, XInvocation): 1118 def __init__( self, ctx, *args ): 1119 if log.isDebugLevel(): 1120 mystr = "" 1121 for i in args: 1122 if len(mystr) > 0: 1123 mystr = mystr +"," 1124 mystr = mystr + str(i) 1125 log.debug( "Entering PythonScriptProvider.ctor with args " + mystr ) 1126 1127 doc = None 1128 inv = None 1129 storageType = "" 1130 1131 if isinstance(args[0],unicode ): 1132 storageType = args[0] 1133 if storageType.startswith( "vnd.sun.star.tdoc" ): 1134 doc = getModelFromDocUrl(ctx, storageType) 1135 else: 1136 inv = args[0] 1137 try: 1138 doc = inv.ScriptContainer 1139 content = ctx.getServiceManager().createInstanceWithContext( 1140 "com.sun.star.frame.TransientDocumentsDocumentContentFactory", 1141 ctx).createDocumentContent(doc) 1142 storageType = content.getIdentifier().getContentIdentifier() 1143 except Exception as e: 1144 text = lastException2String() 1145 log.error( text ) 1146 1147 isPackage = storageType.endswith( ":uno_packages" ) 1148 1149 try: 1150# urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext( 1151# "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx) 1152 urlHelper = MyUriHelper( ctx, storageType ) 1153 log.debug( "got urlHelper " + str( urlHelper ) ) 1154 1155 rootUrl = expandUri( urlHelper.getRootStorageURI() ) 1156 log.debug( storageType + " transformed to " + rootUrl ) 1157 1158 ucbService = "com.sun.star.ucb.SimpleFileAccess" 1159 sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx ) 1160 if not sfa: 1161 log.debug("PythonScriptProvider couldn't instantiate " +ucbService) 1162 raise RuntimeException( 1163 "PythonScriptProvider couldn't instantiate " +ucbService, self) 1164 self.provCtx = ProviderContext( 1165 storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), doc, inv ) ) 1166 if isPackage: 1167 mapPackageName2Path = getPackageName2PathMap( sfa, storageType ) 1168 self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl ) 1169 self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl ) 1170 else: 1171 self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl, 0 ) 1172 1173 except Exception as e: 1174 text = lastException2String() 1175 log.debug( "PythonScriptProvider could not be instantiated because of : " + text ) 1176 raise e 1177 1178 def getName( self ): 1179 return self.dirBrowseNode.getName() 1180 1181 def getChildNodes( self ): 1182 return self.dirBrowseNode.getChildNodes() 1183 1184 def hasChildNodes( self ): 1185 return self.dirBrowseNode.hasChildNodes() 1186 1187 def getType( self ): 1188 return self.dirBrowseNode.getType() 1189 1190 def getScript( self, uri ): 1191 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 1192 1193 raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 1194 1195 def getScript( self, scriptUri ): 1196 try: 1197 log.debug( "getScript " + scriptUri + " invoked") 1198 1199 storageUri = self.provCtx.getStorageUrlFromPersistentUrl( 1200 self.provCtx.uriHelper.getStorageURI(scriptUri) ); 1201 log.debug( "getScript: storageUri = " + storageUri) 1202 fileUri = storageUri[0:storageUri.find( "$" )] 1203 funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)] 1204 1205 mod = self.provCtx.getModuleByUrl( fileUri ) 1206 log.debug( " got mod " + str(mod) ) 1207 1208 func = mod.__dict__[ funcName ] 1209 1210 log.debug( "got func " + str( func ) ) 1211 return PythonScript( func, mod ) 1212 except Exception as e: 1213 text = lastException2String() 1214 log.error( text ) 1215 raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 ) 1216 1217 # XPropertySet 1218 1219 def getPropertyValue( self, name ): 1220 return self.dirBrowseNode.getPropertyValue( name ) 1221 1222 def setPropertyValue( self, name, value ): 1223 return self.dirBrowseNode.setPropertyValue( name, value ) 1224 1225 def getPropertySetInfo( self ): 1226 return self.dirBrowseNode.getPropertySetInfo() 1227 1228 # XInvocation 1229 1230 def getIntrospection( self ): 1231 return self.dirBrowseNode.getIntrospection() 1232 1233 def invoke( self, name, params, outparamindex, outparams ): 1234 return self.dirBrowseNode.invoke( name, params, outparamindex, outparams) 1235 1236 def setValue( self, name, value ): 1237 return self.dirBrowseNode.setValue( name, value ) 1238 1239 def getValue( self, name ): 1240 return self.dirBrowseNode.getValue( name ) 1241 1242 def hasMethod( self, name ): 1243 return self.dirBrowseNode.hasMethod( name ) 1244 1245 def hasProperty( self, name ): 1246 return self.dirBrowseNode.hasProperty( name ) 1247 1248 # XServiceInfo 1249 def getSupportedServices( self ): 1250 return g_ImplementationHelper.getSupportedServices(g_implName) 1251 1252 def supportsService( self, ServiceName ): 1253 return g_ImplementationHelper.supportsService( g_implName, ServiceName ) 1254 1255 def getImplementationName(self): 1256 return g_implName 1257 1258 def getByName( self, name ): 1259 log.debug( "getByName called" + str( name )) 1260 return None 1261 1262 1263 def getElementNames( self ): 1264 log.debug( "getElementNames called") 1265 return () 1266 1267 def hasByName( self, name ): 1268 try: 1269 log.debug( "hasByName called " + str( name )) 1270 uri = expandUri(name) 1271 ret = self.provCtx.isUrlInPackage( uri ) 1272 log.debug( "hasByName " + uri + " " +str( ret ) ) 1273 return ret 1274 except Exception as e: 1275 text = lastException2String() 1276 log.debug( "Error in hasByName:" + text ) 1277 return False 1278 1279 def removeByName( self, name ): 1280 log.debug( "removeByName called" + str( name )) 1281 uri = expandUri( name ) 1282 if self.provCtx.isUrlInPackage( uri ): 1283 self.provCtx.removePackageByUrl( uri ) 1284 else: 1285 log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" ) 1286 raise NoSuchElementException( uri + "is not in package" , self ) 1287 log.debug( "removeByName called" + str( uri ) + " successful" ) 1288 1289 def insertByName( self, name, value ): 1290 log.debug( "insertByName called " + str( name ) + " " + str( value )) 1291 uri = expandUri( name ) 1292 if isPyFileInPath( self.provCtx.sfa, uri ): 1293 self.provCtx.addPackageByUrl( uri ) 1294 else: 1295 # package is no python package ... 1296 log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" ) 1297 raise IllegalArgumentException( uri + " does not contain .py files", self, 1 ) 1298 log.debug( "insertByName called " + str( uri ) + " successful" ) 1299 1300 def replaceByName( self, name, value ): 1301 log.debug( "replaceByName called " + str( name ) + " " + str( value )) 1302 removeByName( name ) 1303 insertByName( name ) 1304 log.debug( "replaceByName called" + str( uri ) + " successful" ) 1305 1306 def getElementType( self ): 1307 log.debug( "getElementType called" ) 1308 return uno.getTypeByName( "void" ) 1309 1310 def hasElements( self ): 1311 log.debug( "hasElements got called") 1312 return False 1313 1314g_ImplementationHelper.addImplementation( \ 1315 PythonScriptProvider,g_implName, \ 1316 ("com.sun.star.script.provider.LanguageScriptProvider", 1317 "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),) 1318 1319 1320log.debug( "pythonscript finished initializing" ) 1321