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