This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch AOO41X
in repository https://gitbox.apache.org/repos/asf/openoffice.git


The following commit(s) were added to refs/heads/AOO41X by this push:
     new 3492f04019 Merge branch 'python-editing-embedding' into trunk
3492f04019 is described below

commit 3492f040199cbf8c0c22e0df262dee73c8a0571a
Author: Damjan Jovanovic <[email protected]>
AuthorDate: Sun May 24 04:24:14 2026 +0200

    Merge branch 'python-editing-embedding' into trunk
    
    Fixes: #60849 - Python editing and embedding macros in documents
    Patch by: me
    
    (cherry picked from commit 4bb26738ff7ada5caefbfb03c42872fd9b2b6d18)
---
 main/scripting/README                        |   8 +-
 main/scripting/source/pyprov/pythonscript.py | 480 ++++++++++++++++++++++++---
 2 files changed, 432 insertions(+), 56 deletions(-)

diff --git a/main/scripting/README b/main/scripting/README
index 686e4ad30f..2b6a7936e1 100644
--- a/main/scripting/README
+++ b/main/scripting/README
@@ -19,6 +19,10 @@ browsing and executing scripts.
 C++ for a ProtocolHandler implementation that handles vnd.sun.star.script
 URIs and dispatches them for execution to the Scripting Framework.
 
+- source/pyprov
+
+LanguageScriptProvider for Python
+
 - source/basprov
 
 C++ implementation of the LanguageScriptProvider UNO service for Basic
@@ -57,10 +61,6 @@ Deprecated Code
 
 Support for developing scripts in IDEs such as NetBeans.
 
-- source/pyprov
-
-LanguageScriptProvider for Python
-
 - source/storage
 - source/runtimemgr
 
diff --git a/main/scripting/source/pyprov/pythonscript.py 
b/main/scripting/source/pyprov/pythonscript.py
index 23e82b558d..40eba13efe 100644
--- a/main/scripting/source/pyprov/pythonscript.py
+++ b/main/scripting/source/pyprov/pythonscript.py
@@ -52,7 +52,6 @@ elif os.environ.get(PYSCRIPT_LOG_ENV) == "DEBUG":
 # False, writes to user/Scripts/python/log.txt
 LOG_STDOUT = os.environ.get(PYSCRIPT_LOG_STDOUT_ENV, "1") != "0"
 
-ENABLE_EDIT_DIALOG=False                    # offers a minimal editor for 
editing.
 #-------------------------------------------------------------------
 
 def encfile(uni):
@@ -125,7 +124,7 @@ log.debug( "pythonscript loading" )
 #from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider
 from com.sun.star.uno import RuntimeException
 from com.sun.star.lang import XServiceInfo
-from com.sun.star.io import IOException
+from com.sun.star.io import IOException, XInputStream
 from com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, 
XProgressHandler, Command
 from com.sun.star.task import XInteractionHandler
 from com.sun.star.beans import XPropertySet, Property
@@ -133,7 +132,8 @@ from com.sun.star.container import XNameContainer
 from com.sun.star.xml.sax import XDocumentHandler, InputSource
 from com.sun.star.uno import Exception as UnoException
 from com.sun.star.script import XInvocation
-from com.sun.star.awt import XActionListener
+from com.sun.star.awt import XActionListener, FontDescriptor
+from com.sun.star.awt.FontPitch import FIXED
 
 from com.sun.star.script.provider import XScriptProvider, XScript, 
XScriptContext, ScriptFrameworkErrorException
 from com.sun.star.script.browse import XBrowseNode
@@ -167,6 +167,52 @@ def toIniName( str ):
         return str + ".ini"
     return str + "rc"
 
+class EmptyInputStream( unohelper.Base, XInputStream ):
+    def __init__( self ):
+        pass
+
+    def closeInput(self):
+        pass
+
+    def readBytes( self, seq, n ):
+        return 0, ""
+
+    def readSomeBytes( self, seq, n ):
+        return 0, ""
+
+    def skipBytes( self, n ):
+        pass
+
+    def available( self ):
+        return 0
+
+class BytesInputStream( unohelper.Base, XInputStream ):
+    def __init__( self, bytes ):
+        self.bytes = bytes
+        self.position = 0
+
+    def closeInput(self):
+        pass
+
+    def readBytes( self, seq, n ):
+        size = self.available()
+        if n < size:
+            size = n
+        curr = self.position
+        self.position += size
+        return size, uno.ByteSequence( self.bytes[curr:curr+size] )
+
+    def readSomeBytes( self, seq, n ):
+        return self.readBytes( seq, n )
+
+    def skipBytes( self, n ):
+        size = self.available()
+        if n < size:
+            size = n
+        self.position += size
+
+    def available( self ):
+        return len( self.bytes ) - self.position
 
 """ definition: storageURI is the system dependent, absolute file url, where 
the script is stored on disk
                 scriptURI is the system independent uri
@@ -451,6 +497,91 @@ class ProviderContext:
             log.debug( "mapped " + url + " to " + str( entry.module ) )
         return  entry.module
 
+    # Forgets a stale module so a fresh copy can be loaded in the future.
+    # This is necessary because getModuleByUrl()'s 
self.sfa.getDateTimeModified()
+    # doesn't always work, eg. for embedded scripts it always returns 
timestamps
+    # with all zeroes, and even if it worked, the smallest granularity for ZIP 
file
+    # timestamps is 2 seconds, which isn't good enough.
+    def removeModuleByUrl( self, url ):
+        self.modules.pop( url, None )
+
+def createEditorDialog( ctx ):
+    smgr = ctx.ServiceManager
+
+    dialogModel = smgr.createInstanceWithContext(
+        "com.sun.star.awt.UnoControlDialogModel", ctx)
+    dialogModel.PositionX = 105
+    dialogModel.PositionY = 117
+    dialogModel.Width = 240
+    dialogModel.Height = 320
+    dialogModel.Closeable = True
+    dialogModel.Moveable = True
+    dialogModel.Title = "Python Macro Editor"
+
+    runButtonModel = dialogModel.createInstance(
+        "com.sun.star.awt.UnoControlButtonModel" )
+    runButtonModel.PositionX = 57
+    runButtonModel.PositionY = 300
+    runButtonModel.Width = 40
+    runButtonModel.Height = 14
+    runButtonModel.TabIndex = 0
+    runButtonModel.Label = "Run"
+
+    saveButtonModel = dialogModel.createInstance(
+        "com.sun.star.awt.UnoControlButtonModel" )
+    saveButtonModel.PositionX = 100
+    saveButtonModel.PositionY = 300
+    saveButtonModel.Width = 40
+    saveButtonModel.Height = 14
+    saveButtonModel.TabIndex = 1
+    saveButtonModel.Label = "Save"
+
+    closeButtonModel = dialogModel.createInstance(
+        "com.sun.star.awt.UnoControlButtonModel" )
+    closeButtonModel.PositionX = 143
+    closeButtonModel.PositionY = 300
+    closeButtonModel.Width = 40
+    closeButtonModel.Height = 14
+    closeButtonModel.TabIndex = 2
+    closeButtonModel.PushButtonType = 2  # CANCEL
+    closeButtonModel.Label = "Close"
+
+    fontDescriptor = FontDescriptor()
+    fontDescriptor.Name = "SomeFixedWidthFont"
+    fontDescriptor.Pitch = FIXED
+
+    textFieldModel = dialogModel.createInstance(
+        "com.sun.star.awt.UnoControlEditModel" )
+    textFieldModel.PositionX = 6
+    textFieldModel.PositionY = 6
+    textFieldModel.Width = 228
+    textFieldModel.Height = 288
+    textFieldModel.TabIndex = 3
+    textFieldModel.HScroll = True
+    textFieldModel.VScroll = True
+    textFieldModel.MultiLine = True
+    textFieldModel.FontDescriptor = fontDescriptor
+
+    dialogModel.insertByName( "RunButton", runButtonModel )
+    dialogModel.insertByName( "SaveButton", saveButtonModel )
+    dialogModel.insertByName( "CloseButton", closeButtonModel )
+    dialogModel.insertByName( "EditorTextField", textFieldModel )
+
+    # create the dialog control and set the model
+    controlContainer = smgr.createInstanceWithContext(
+        "com.sun.star.awt.UnoControlDialog", ctx);
+    controlContainer.setModel(dialogModel);
+
+    # create a peer
+    toolkit = smgr.createInstanceWithContext(
+        "com.sun.star.awt.ExtToolkit", ctx);
+
+    controlContainer.setVisible(False);
+    controlContainer.createPeer(toolkit, None);
+
+    return controlContainer
+
+
 #--------------------------------------------------
 def isScript( candidate ):
     ret = False
@@ -459,12 +590,15 @@ def isScript( candidate ):
     return ret
 
 #-------------------------------------------------------
-class ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, 
XInvocation, XActionListener ):
-    def __init__( self, provCtx, uri, fileName, funcName ):
+class ScriptBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, 
XInvocation, XActionListener ):
+    def __init__( self, provCtx, parent, fileName, funcName ):
+        self.parent = parent
         self.fileName = fileName
         self.funcName = funcName
         self.provCtx = provCtx
-        self.uri = uri
+
+    def uri( self ):
+        return self.parent.uri()
 
     def getName( self ):
         return self.funcName
@@ -483,9 +617,9 @@ class ScriptBrowseNode( unohelper.Base, XBrowseNode , 
XPropertySet, XInvocation,
         try:
             if name == "URI":
                 ret = self.provCtx.uriHelper.getScriptURI(
-                    self.provCtx.getPersistentUrlFromStorageUrl( self.uri + 
"$" + self.funcName ) )
-            elif name == "Editable" and ENABLE_EDIT_DIALOG:
-                ret = not self.provCtx.sfa.isReadOnly( self.uri )
+                    self.provCtx.getPersistentUrlFromStorageUrl( self.uri() + 
"$" + self.funcName ) )
+            elif name == "Editable":
+                ret = not self.provCtx.sfa.isReadOnly( self.uri() )
 
             log.debug( "ScriptBrowseNode.getPropertyValue called for " + name 
+ ", returning " + str(ret) )
         except Exception as e:
@@ -504,16 +638,11 @@ class ScriptBrowseNode( unohelper.Base, XBrowseNode , 
XPropertySet, XInvocation,
 
     def invoke( self, name, params, outparamindex, outparams ):
         if name == "Editable":
-            servicename = "com.sun.star.awt.DialogProvider"
             ctx = self.provCtx.scriptContext.getComponentContext()
-            dlgprov = ctx.ServiceManager.createInstanceWithContext(
-                servicename, ctx )
 
-            self.editor = dlgprov.createDialog(
-                "vnd.sun.star.script:" +
-                "ScriptBindingLibrary.MacroEditor?location=application")
+            self.editor = createEditorDialog( ctx )
 
-            code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri))
+            code = 
readTextFromStream(self.provCtx.sfa.openFileRead(self.uri()))
             code = ensureSourceState( code )
             self.editor.getControl("EditorTextField").setText(code)
 
@@ -524,7 +653,7 @@ class ScriptBrowseNode( unohelper.Base, XBrowseNode , 
XPropertySet, XInvocation,
 
             self.editor.execute()
 
-        return None
+        return None, (), ()
 
     def actionPerformed( self, event ):
         try:
@@ -545,18 +674,10 @@ class ScriptBrowseNode( unohelper.Base, XBrowseNode , 
XPropertySet, XInvocation,
 
             elif event.ActionCommand == "Save":
                 toWrite = uno.ByteSequence(
-                    str(
-                    self.editor.getControl("EditorTextField").getText().encode(
-                    sys.getdefaultencoding())) )
-                copyUrl = self.uri + ".orig"
-                self.provCtx.sfa.move( self.uri, copyUrl )
-                out = self.provCtx.sfa.openFileWrite( self.uri )
-                out.writeBytes( toWrite )
-                out.close()
-                self.provCtx.sfa.kill( copyUrl )
-#                log.debug("Save is not implemented yet")
-#                text = self.editor.getControl("EditorTextField").getText()
-#                log.debug("Would save: " + text)
+                    
self.editor.getControl("EditorTextField").getText().encode("utf-8"))
+                log.debug( "Saving Python macro to URI " + self.uri() )
+                self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( 
toWrite.value ) )
+                self.provCtx.removeModuleByUrl( self.uri() )
         except Exception as e:
             # TODO: add an error box here !
             log.error( lastException2String() )
@@ -576,31 +697,33 @@ class ScriptBrowseNode( unohelper.Base, XBrowseNode , 
XPropertySet, XInvocation,
 
 
 #-------------------------------------------------------
-class FileBrowseNode( unohelper.Base, XBrowseNode ):
-    def __init__( self, provCtx, uri , name ):
+class FileBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation, 
XActionListener ):
+    def __init__( self, provCtx, parent, name ):
         self.provCtx = provCtx
-        self.uri = uri
+        self.parent = parent
         self.name = name
         self.funcnames = None
 
+    def uri( self ):
+        return self.parent.rootUrl + "/" + self.name + ".py"
+
     def getName( self ):
         return self.name
 
     def getChildNodes(self):
         ret = ()
         try:
-            self.funcnames = self.provCtx.getFuncsByUrl( self.uri )
+            self.funcnames = self.provCtx.getFuncsByUrl( self.uri() )
 
             scriptNodeList = []
             for i in self.funcnames:
                 scriptNodeList.append(
                     ScriptBrowseNode(
-                    self.provCtx, self.uri, self.name, i ))
+                    self.provCtx, self, self.name, i ))
             ret = tuple( scriptNodeList )
-            log.debug( "returning " +str(len(ret)) + " ScriptChildNodes on " + 
self.uri )
         except Exception as e:
             text = lastException2String()
-            log.error( "Error while evaluating " + self.uri + ":" + text )
+            log.error( "FileBrowseNode.getChildNodes error while evaluating " 
+ self.uri() + ":" + text )
             raise
         return ret
 
@@ -613,13 +736,121 @@ class FileBrowseNode( unohelper.Base, XBrowseNode ):
     def getType( self):
         return CONTAINER
 
+    # XPropertySet
+
+    def getPropertyValue( self, name ):
+        ret = None
+        try:
+            if name == "Editable":
+                ret = not self.provCtx.sfa.isReadOnly( self.uri() )
+            elif name == "Deletable":
+                ret = not self.provCtx.sfa.isReadOnly( self.uri() )
+            elif name == "Renamable":
+                ret = not self.provCtx.sfa.isReadOnly( self.uri() )
+
+            log.debug( "FileBrowseNode.getPropertyValue called for " + name + 
", returning " + str(ret) )
+        except Exception as e:
+            log.error( "FileBrowseNode.getPropertyValue error " + 
lastException2String())
+            raise
 
+        return ret
 
-class DirBrowseNode( unohelper.Base, XBrowseNode ):
-    def __init__( self, provCtx, name, rootUrl ):
+    def setPropertyValue( self, name, value ):
+        log.debug( "FileBrowseNode.setPropertyValue called " + name + "=" 
+str(value ) )
+
+    def getPropertySetInfo( self ):
+        log.debug( "FileBrowseNode.getPropertySetInfo called "  )
+        return None
+
+    # XInvocation
+
+    def getIntrospection( self ):
+        log.debug( "FileBrowseNode.getIntrospection() called" )
+        return None
+
+    def invoke( self, name, params, outparamindex, outparams ):
+        log.debug("FileBrowseNode.invoke called for " + name + "," + 
str(params) + "," + str(outparamindex) + "," + str(outparams))
+        try:
+            if name == "Editable":
+                ctx = self.provCtx.scriptContext.getComponentContext()
+
+                self.editor = createEditorDialog( ctx )
+
+                code = 
readTextFromStream(self.provCtx.sfa.openFileRead(self.uri()))
+                code = ensureSourceState( code )
+                self.editor.getControl("EditorTextField").setText(code)
+
+                self.editor.getControl("RunButton").setActionCommand("Run")
+                self.editor.getControl("RunButton").addActionListener(self)
+                self.editor.getControl("SaveButton").setActionCommand("Save")
+                self.editor.getControl("SaveButton").addActionListener(self)
+
+                self.editor.execute()
+            elif name == "Deletable":
+                self.provCtx.sfa.kill( self.uri() )
+                return True, (), ()
+            elif name == "Renamable":
+                if params is None or not params:
+                    raise IllegalArgumentException( "invoke with Creatable 
needs the name in params" )
+                newUri = self.parent.rootUrl + "/" + params[0] + ".py"
+                self.provCtx.sfa.move( self.uri(), newUri )
+                self.name = params[0]
+                return self, (), ()
+        except Exception as e:
+            log.error( "FileBrowseNode.invoke error " + lastException2String() 
)
+            raise
+        return None, (), ()
+
+    def setValue( self, name, value ):
+        return None
+
+    def getValue( self, name ):
+        log.debug( "FileBrowseNode.getValue() called" )
+        return None
+
+    def hasMethod( self, name ):
+        return False
+
+    def hasProperty( self, name ):
+        return False
+
+    # XActionListener
+
+    def actionPerformed( self, event ):
+        try:
+            if event.ActionCommand == "Run":
+                code = self.editor.getControl("EditorTextField").getText()
+                code = ensureSourceState( code )
+                mod = imp.new_module("ooo_script_framework")
+                mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = 
self.provCtx.scriptContext
+                exec(code, mod.__dict__)
+                values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None )
+                if not values:
+                    values = list(mod.__dict__.values())
+
+                for i in values:
+                    if isScript( i ):
+                        i()
+                        break
+
+            elif event.ActionCommand == "Save":
+                toWrite = uno.ByteSequence(
+                    
self.editor.getControl("EditorTextField").getText().encode("utf-8"))
+                log.debug( "Saving Python macro to URI " + self.uri() )
+                self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( 
toWrite.value ) )
+                self.provCtx.removeModuleByUrl( self.uri() )
+        except Exception as e:
+            # TODO: add an error box here !
+            log.error( lastException2String() )
+
+
+class DirBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ):
+    def __init__( self, provCtx, name, rootUrl, depth ):
         self.provCtx = provCtx
         self.name = name
         self.rootUrl = rootUrl
+        self.depth = depth
+        log.debug( "DirBrowseNode constructor for " + name + "," + rootUrl )
 
     def getName( self ):
         return self.name
@@ -633,10 +864,11 @@ class DirBrowseNode( unohelper.Base, XBrowseNode ):
                 if i.endswith( ".py" ):
                     log.debug( "adding filenode " + i )
                     browseNodeList.append(
-                        FileBrowseNode( self.provCtx, i, 
i[i.rfind("/")+1:len(i)-3] ) )
+                        FileBrowseNode( self.provCtx, self, 
i[i.rfind("/")+1:len(i)-3] ) )
                 elif self.provCtx.sfa.isFolder( i ) and not 
i.endswith("/pythonpath"):
                     log.debug( "adding DirBrowseNode " + i )
-                    browseNodeList.append( DirBrowseNode( self.provCtx, 
i[i.rfind("/")+1:len(i)],i))
+                    browseNodeList.append(
+                        DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)], 
i, self.depth + 1 ) )
             return tuple( browseNodeList )
         except Exception as e:
             text = lastException2String()
@@ -650,10 +882,90 @@ class DirBrowseNode( unohelper.Base, XBrowseNode ):
     def getType( self ):
         return CONTAINER
 
+    # XScriptProvider
+
     def getScript( self, uri ):
         log.debug( "DirBrowseNode getScript " + uri + " invoked" )
         raise IllegalArgumentException( "DirBrowseNode couldn't instantiate 
script " + uri , self , 0 )
 
+    # XPropertySet
+
+    def getPropertyValue( self, name ):
+        ret = None
+        try:
+            if name == "Creatable":
+                ret = True
+            elif name == "Deletable":
+                ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( 
self.rootUrl )
+            elif name == "Renamable":
+                ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( 
self.rootUrl )
+
+            log.debug( "DirBrowseNode.getPropertyValue called for " + name + 
", returning " + str(ret) )
+        except Exception as e:
+            log.error( "DirBrowseNode.getPropertyValue error " + 
lastException2String())
+            raise
+
+        return ret
+
+    def setPropertyValue( self, name, value ):
+        log.debug( "DirBrowseNode.setPropertyValue called " + name + "=" 
+str(value ) )
+
+    def getPropertySetInfo( self ):
+        log.debug( "DirBrowseNode.getPropertySetInfo called "  )
+        return None
+
+    # XInvocation
+
+    def getIntrospection( self ):
+        log.debug( "DirBrowseNode.getIntrospection() called" )
+        return None
+
+    def invoke( self, name, params, outparamindex, outparams ):
+        log.debug("DirBrowseNode.invoke called for " + name + "," + 
str(params) + "," + str(outparamindex) + "," + str(outparams))
+        try:
+            if name == "Creatable":
+                if params is None or not params:
+                    raise IllegalArgumentException( "invoke with Creatable 
needs the name in params" )
+                if self.depth == 0:
+                    subFolderUrl = self.rootUrl + "/" + params[0]
+                    self.provCtx.sfa.createFolder( subFolderUrl )
+                    childNode = DirBrowseNode( self.provCtx, 
subFolderUrl[subFolderUrl.rfind("/")+1:len(subFolderUrl)], subFolderUrl, 
self.depth + 1 )
+                    return childNode, (), ()
+                else:
+                    scriptUrl = self.rootUrl + "/" + params[0] + ".py"
+                    # Creates an empty file
+                    self.provCtx.sfa.writeFile( scriptUrl, EmptyInputStream() )
+                    childNode = FileBrowseNode( self.provCtx, self, params[0] )
+                    return childNode, (), ()
+            elif name == "Deletable":
+                self.provCtx.sfa.kill( self.rootUrl )
+                return True, (), ()
+            elif name == "Renamable":
+                if params is None or not params:
+                    raise IllegalArgumentException( "invoke with Renamable 
needs the name in params" )
+                newUrl = self.rootUrl[0:self.rootUrl.rfind("/")+1] + params[0]
+                self.provCtx.sfa.move( self.rootUrl, newUrl )
+                self.rootUrl = newUrl
+                self.name = params[0]
+                return self, (), ()
+        except Exception as e:
+            log.error( "DirBrowseNode.invoke error: " + lastException2String())
+            raise
+        return None, (), ()
+
+    def setValue( self, name, value ):
+        return None
+
+    def getValue( self, name ):
+        log.debug( "DirBrowseNode.getValue() called" )
+        return None
+
+    def hasMethod( self, name ):
+        return False
+
+    def hasProperty( self, name ):
+        return False
+
 
 class ManifestHandler( XDocumentHandler, unohelper.Base ):
     def __init__( self, rootUrl ):
@@ -821,7 +1133,7 @@ def penultimateElement( aStr ):
 def lastElement( aStr):
     return aStr[ aStr.rfind( "/" )+1:len(aStr)]
 
-class PackageBrowseNode( unohelper.Base, XBrowseNode ):
+class PackageBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, 
XInvocation ):
     def __init__( self, provCtx, name, rootUrl ):
         self.provCtx = provCtx
         self.name = name
@@ -836,11 +1148,11 @@ class PackageBrowseNode( unohelper.Base, XBrowseNode ):
         for i in items:
             if len( i[1].pathes ) == 1:
                 browseNodeList.append(
-                    DirBrowseNode( self.provCtx, i[0], i[1].pathes[0] ))
+                    DirBrowseNode( self.provCtx, i[0], i[1].pathes[0], 0 ))
             else:
                 for j in i[1].pathes:
                     browseNodeList.append(
-                        DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), 
j ) )
+                        DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), 
j, 0 ) )
         return tuple( browseNodeList )
 
     def hasChildNodes( self ):
@@ -853,6 +1165,45 @@ class PackageBrowseNode( unohelper.Base, XBrowseNode ):
         log.debug( "DirBrowseNode getScript " + uri + " invoked" )
         raise IllegalArgumentException( "PackageBrowseNode couldn't 
instantiate script " + uri , self , 0 )
 
+    # XPropertySet
+
+    def getPropertyValue( self, name ):
+        ret = None
+        log.debug( "PackageBrowseNode.getPropertyValue called for " + name + 
", returning " + str(ret) )
+        return ret
+
+    def setPropertyValue( self, name, value ):
+        log.debug( "PackageBrowseNode.setPropertyValue " + name + "=" +str( 
value ) )
+
+    def getPropertySetInfo( self ):
+        log.debug( "PackageBrowseNode.getPropertySetInfo called" )
+        return None
+
+    # XInvocation
+
+    def getIntrospection( self ):
+        log.debug( "PackageBrowseNode.getIntrospection() called" )
+        return None
+
+    def invoke( self, name, params, outparamindex, outparams ):
+        log.debug( "PackageBrowseNode.invoke called for " + name + "," + str( 
params ) + "," + str( outparamindex ) + "," + str( outparams ) )
+        return None, (), ()
+
+    def setValue( self, name, value ):
+        log.debug( "PackageBrowseNode.setValue" )
+        return None
+
+    def getValue( self, name ):
+        log.debug( "PackageBrowseNode.getValue" )
+        return None
+
+    def hasMethod( self, name ):
+        log.debug( "PackageBrowseNode.hasMethod" )
+        return False
+
+    def hasProperty( self, name ):
+        log.debug( "PackageBrowseNode.hasProperty" )
+        return False
 
 
 
@@ -898,7 +1249,7 @@ def expandUri(  uri ):
     return uri
 
 #--------------------------------------------------------------
-class PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, 
XNameContainer):
+class PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, 
XNameContainer, XPropertySet, XInvocation):
     def __init__( self, ctx, *args ):
         if log.isDebugLevel():
             mystr = ""
@@ -906,7 +1257,7 @@ class PythonScriptProvider( unohelper.Base, XBrowseNode, 
XScriptProvider, XNameC
                 if len(mystr) > 0:
                     mystr = mystr +","
                 mystr = mystr + str(i)
-            log.debug( "Entering PythonScriptProvider.ctor" + mystr )
+            log.debug( "Entering PythonScriptProvider.ctor with args " + mystr 
)
 
         doc = None
         inv = None
@@ -952,7 +1303,7 @@ class PythonScriptProvider( unohelper.Base, XBrowseNode, 
XScriptProvider, XNameC
                 self.provCtx.setPackageAttributes( mapPackageName2Path , 
rootUrl )
                 self.dirBrowseNode = PackageBrowseNode( self.provCtx, 
LANGUAGENAME, rootUrl )
             else:
-                self.dirBrowseNode = DirBrowseNode( self.provCtx, 
LANGUAGENAME, rootUrl )
+                self.dirBrowseNode = DirBrowseNode( self.provCtx, 
LANGUAGENAME, rootUrl, 0 )
 
         except Exception as e:
             text = lastException2String()
@@ -971,14 +1322,9 @@ class PythonScriptProvider( unohelper.Base, XBrowseNode, 
XScriptProvider, XNameC
     def getType( self ):
         return self.dirBrowseNode.getType()
 
-    def getScript( self, uri ):
-        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
-
-        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate 
script " + uri , self , 0 )
-
     def getScript( self, scriptUri ):
         try:
-            log.debug( "getScript " + scriptUri + " invoked")
+            log.debug( "DirBrowseNode getScript " + scriptUri + " invoked")
 
             storageUri = self.provCtx.getStorageUrlFromPersistentUrl(
                 self.provCtx.uriHelper.getStorageURI(scriptUri) );
@@ -998,6 +1344,36 @@ class PythonScriptProvider( unohelper.Base, XBrowseNode, 
XScriptProvider, XNameC
             log.error( text )
             raise ScriptFrameworkErrorException( text, self, scriptUri, 
LANGUAGENAME, 0 )
 
+    # XPropertySet
+
+    def getPropertyValue( self, name ):
+        return self.dirBrowseNode.getPropertyValue( name )
+
+    def setPropertyValue( self, name, value ):
+        return self.dirBrowseNode.setPropertyValue( name, value )
+
+    def getPropertySetInfo( self ):
+        return self.dirBrowseNode.getPropertySetInfo()
+
+    # XInvocation
+
+    def getIntrospection( self ):
+        return self.dirBrowseNode.getIntrospection()
+
+    def invoke( self, name, params, outparamindex, outparams ):
+        return self.dirBrowseNode.invoke( name, params, outparamindex, 
outparams)
+
+    def setValue( self, name, value ):
+        return self.dirBrowseNode.setValue( name, value )
+
+    def getValue( self, name ):
+        return self.dirBrowseNode.getValue( name )
+
+    def hasMethod( self, name ):
+        return self.dirBrowseNode.hasMethod( name )
+
+    def hasProperty( self, name ):
+        return self.dirBrowseNode.hasProperty( name )
 
     # XServiceInfo
     def getSupportedServices( self ):

Reply via email to