wizards/source/scriptforge/SF_PythonHelper.xba | 41 +++++++++++++++-------- wizards/source/scriptforge/python/scriptforge.py | 10 +++-- wizards/source/scriptforge/script.xlb | 26 +++++++------- 3 files changed, 47 insertions(+), 30 deletions(-)
New commits: commit 8bc9ddf83236789328cc0fb4154a0bbf80d66078 Author: Jean-Pierre Ledure <j...@ledure.be> AuthorDate: Sun Sep 14 18:05:14 2025 +0200 Commit: Jean-Pierre Ledure <j...@ledure.be> CommitDate: Mon Sep 15 07:35:37 2025 +0200 ScriptForge Extend Python-Basic gateway for objects A Python ScriptForge object may be passed to Basic functions, so far only when it is positioned as the first argument in the method signature. Like in: dialogB.Center(dialogA) The actual commit extends the protocol between Python and Basic to allow passing Python objects from another position in the method signature. However this possibility is limited to maximum 1 such argument. (Note that removing this limitation, if ever needed, would not require a big change.) No impact on user existing scripts. No documentation update. Change-Id: I191b7bb7c32b158b7274815577349ddfa1406b93 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190931 Tested-by: Jenkins Reviewed-by: Jean-Pierre Ledure <j...@ledure.be> diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba b/wizards/source/scriptforge/SF_PythonHelper.xba index 085d5ff639af..06048c3b598a 100644 --- a/wizards/source/scriptforge/SF_PythonHelper.xba +++ b/wizards/source/scriptforge/SF_PythonHelper.xba @@ -603,6 +603,9 @@ Public Function _PythonDispatcher(ByRef BasicObject As Variant _ ''' Args: ''' BasicObject: a module or a class instance - May also be the reserved string: "SF_Services" ''' CallType: one of the constants applicable to a CallByName statement + optional protocol flags +''' When CallType is an array (applicable when CallType includes cstObject) +''' CallType[0] = CallType scalar +''' CallType[1] = argument index on which to apply the scalar value ''' Script: the name of the method or property ''' Args: the arguments to pass to the method. Input arguments can contain symbolic constants for Null, Missing, etc. ''' Returns: @@ -621,6 +624,8 @@ Public Function _PythonDispatcher(ByRef BasicObject As Variant _ Dim vReturn As Variant ' The value returned by the invoked property or method Dim vReturnArray As Variant ' Return value +Dim iCallType As Integer ' Alias of CallType +Dim iArgIndex As Integer ' Index companion when CallType is an array Dim vBasicObject As Variant ' Alias of BasicObject to avoid "Object reference not set" error Dim iNbArgs As Integer ' Number of valid input arguments Dim vArg As Variant ' Alias for a single argument @@ -653,7 +658,8 @@ Const cstDateRet = 128 ' Return value can be a date Const cstUno = 256 ' Return value can be a UNO object Const cstArgArray = 512 ' Any argument can be a 2D array Const cstRetArray = 1024 ' Return value can be an array -Const cstObject = 2048 ' 1st argument is a Basic object when numeric +Const cstObject = 2048 ' n-th argument is a Basic object when numeric + ' n (default = 0) can be passed as companion in an array Const cstHardCode = 4096 ' Method must not be executed with CallByName() ' Returned object nature Const objMODULE = 1, objCLASS = 2, objDICT = 3, objUNO = 4 @@ -665,6 +671,15 @@ Check: ' Ignore Null basic objects (Null = Null or Nothing) If IsNull(BasicObject) Or IsEmpty(BasicObject) Then GoTo Catch + ' Intercept CallType when the targeted argument should be identified + If IsArray(CallType) Then + iCallType = CallType(0) + iArgIndex = CallType(1) + Else + iCallType = CallType + iArgIndex = 0 + End If + ' Reinterpret arguments one by one into vArgs ' - convert UNO dates/times ' - identify conventional NoArgs/Empty/Null/Missing constants @@ -680,7 +695,7 @@ Check: If vArg = cstNoArgs Then Exit For End If ' Is 1st argument a reference to a Basic object ? - If i = 0 And (( CallType And cstObject ) = cstObject) And SF_Utils._VarTypeExt(vArg) = V_NUMERIC Then + If i = iArgIndex And (( iCallType And cstObject ) = cstObject) And SF_Utils._VarTypeExt(vArg) = V_NUMERIC Then If vArg < 0 Or Not IsArray(_SF_.PythonStorage) Then GoTo Catch If vArg > UBound(_SF_.PythonStorage) Then GoTo Catch vArg = _SF_.PythonStorage(vArg) @@ -695,8 +710,8 @@ Check: Exit For ' Next arguments must be missing also End If ElseIf VarType(vArg) = V_OBJECT Then - If ( CallType And cstDateArg ) = cstDateArg Then vArg = CDateFromUnoDateTime(vArg) - ElseIf ( CallType And cstDictArg ) = cstDictArg Then + If ( iCallType And cstDateArg ) = cstDateArg Then vArg = CDateFromUnoDateTime(vArg) + ElseIf ( iCallType And cstDictArg ) = cstDictArg Then If IsArray(vArg) Then If UBound(vArg) >= 0 Then If sess.UnoObjectType(vArg(0)) = "com.sun.star.beans.PropertyValue" Then @@ -776,7 +791,7 @@ Try: sLibrary = Split(sServiceName, ".")(0) ' Methods in standard modules are called by ExecuteBasicScript() when arrays are returned - If Not bBasicClass And (CallType And vbMethod) = vbMethod And (CallType And cstRetArray) = cstRetArray Then + If Not bBasicClass And (iCallType And vbMethod) = vbMethod And (iCallType And cstRetArray) = cstRetArray Then sScript = sLibrary & "." & sObjectType & "." & Script ' Force validation in targeted function, not in ExecuteBasicScript() _SF_.StackLevel = -1 @@ -794,14 +809,14 @@ Try: _SF_.StackLevel = 0 ' Properties in any service are got and set with obj.GetProperty/SetProperty(...) - ElseIf (CallType And vbGet) = vbGet Then ' In some cases (Calc ...) GetProperty may have an argument + ElseIf (iCallType And vbGet) = vbGet Then ' In some cases (Calc ...) GetProperty may have an argument If UBound(vArgs) < 0 Then vReturn = vBasicObject.GetProperty(Script) Else vReturn = vBasicObject.GetProperty(Script, vArgs(0)) - ElseIf (CallType And vbLet) = vbLet Then + ElseIf (iCallType And vbLet) = vbLet Then vReturn = vBasicObject.SetProperty(Script, vArgs(0)) ' Methods in class modules using a 2D array or returning arrays are hardcoded as exceptions. Bug #138155 - ElseIf ((CallType And vbMethod) + (CallType And cstArgArray)) = vbMethod + cstArgArray Or _ - ((CallType And vbMethod) + (CallType And cstRetArray)) = vbMethod + cstRetArray Then + ElseIf ((iCallType And vbMethod) + (iCallType And cstArgArray)) = vbMethod + cstArgArray Or _ + ((iCallType And vbMethod) + (iCallType And cstRetArray)) = vbMethod + cstRetArray Then If Script = "Methods" Then vReturn = vBasicObject.Methods() ElseIf Script = "Properties" Then @@ -875,7 +890,7 @@ Try: End If ' Specific methods in class modules may better not be executed with CallByName() because they do not return immediately - ElseIf bBasicClass And ((CallType And vbMethod) + (CallType And cstHardCode)) = vbMethod + cstHardCode Then + ElseIf bBasicClass And ((iCallType And vbMethod) + (iCallType And cstHardCode)) = vbMethod + cstHardCode Then Select Case sServiceName Case "SFDialogs.Dialog" Select Case Script @@ -884,7 +899,7 @@ Try: End Select ' Methods in all modules are invoked with CallByName - ElseIf ((CallType And vbMethod) = vbMethod) Then + ElseIf ((iCallType And vbMethod) = vbMethod) Then Select Case UBound(vArgs) ' Dirty alternatives to process usual and ParamArray cases ' But, up to ... how many ? @@ -934,7 +949,7 @@ Try: End If ' Post processing - If (CallType And cstPost) = cstPost Then + If (iCallType And cstPost) = cstPost Then If Script = "Dispose" Then ' Special case: Dispose() must update the cache for class objects created in Python scripts Set _SF_.PythonStorage(BasicObject) = Nothing @@ -971,7 +986,7 @@ Try: ElseIf VarType(vReturn) = V_OBJECT And Not IsNull(vReturn) Then ' Uno or not Uno ? bUno = False - If (CallType And cstUno) = cstUno Then ' UNO considered only when pre-announced in CallType + If (iCallType And cstUno) = cstUno Then ' UNO considered only when pre-announced in CallType Set oObjDesc = SF_Utils._VarTypeObj(vReturn) bUno = ( oObjDesc.iVarType = V_UNOOBJECT ) End If diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index 3e21db3f114b..2ba18e377a60 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -348,9 +348,10 @@ class ScriptForge(object, metaclass = _Singleton): argslist[i] = argdict.ConvertToPropertyValues() return tuple(argslist) - # + # Intercept flags is a tuple + flag = (flags[0] if isinstance(flags, tuple) else flags) # Intercept dictionary arguments - if flags & SFServices.flgDictArg == SFServices.flgDictArg: # Bits comparison + if flag & SFServices.flgDictArg == SFServices.flgDictArg: # Bits comparison args = ConvertDictArgs() # # Run the basic script @@ -395,7 +396,7 @@ class ScriptForge(object, metaclass = _Singleton): # Intercept empty array if isinstance(returnvalue, uno.ByteSequence): return () - if flags & SFServices.flgDateRet == SFServices.flgDateRet: # Bits comparison + if flag & SFServices.flgDateRet == SFServices.flgDateRet: # Bits comparison # Intercept all UNO dates in the 1D or 2D array if isinstance(returnvalue[0], tuple): # tuple of tuples arr = [] @@ -555,7 +556,8 @@ class SFServices(object): flgArrayArg = 512 # 1st argument can be a 2D array flgArrayRet = 1024 # Invoked service method can return a 2D array (standard modules) or any array (class modules) flgUno = 256 # Invoked service method/property can return a UNO object - flgObject = 2048 # 1st argument may be a Basic object + flgObject = 2048 # N-th argument may be a Basic object + # N (default = 0) can be passed as companion in a tuple flgHardCode = 4096 # Force hardcoded call to method, avoid CallByName() # Basic class type moduleClass, moduleStandard = 2, 1 diff --git a/wizards/source/scriptforge/script.xlb b/wizards/source/scriptforge/script.xlb index 7c5f29231c27..bead89b8a66e 100644 --- a/wizards/source/scriptforge/script.xlb +++ b/wizards/source/scriptforge/script.xlb @@ -1,6 +1,19 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd"> <library:library xmlns:library="http://openoffice.org/2000/library" library:name="ScriptForge" library:readonly="false" library:passwordprotected="false"> + <library:element library:name="SF_Timer"/> + <library:element library:name="SF_FileSystem"/> + <library:element library:name="__License"/> + <library:element library:name="SF_Root"/> + <library:element library:name="SF_Region"/> + <library:element library:name="SF_L10N"/> + <library:element library:name="SF_SharedMemory"/> + <library:element library:name="_CodingConventions"/> + <library:element library:name="SF_Session"/> + <library:element library:name="SF_Dictionary"/> + <library:element library:name="SF_Exception"/> + <library:element library:name="SF_UI"/> + <library:element library:name="SF_Services"/> <library:element library:name="SF_PythonHelper"/> <library:element library:name="SF_Platform"/> <library:element library:name="SF_Array"/> @@ -8,17 +21,4 @@ <library:element library:name="SF_Utils"/> <library:element library:name="SF_String"/> <library:element library:name="_ModuleModel"/> - <library:element library:name="SF_SharedMemory"/> - <library:element library:name="SF_L10N"/> - <library:element library:name="SF_Region"/> - <library:element library:name="__License"/> - <library:element library:name="SF_Root"/> - <library:element library:name="SF_Timer"/> - <library:element library:name="SF_FileSystem"/> - <library:element library:name="SF_Services"/> - <library:element library:name="SF_UI"/> - <library:element library:name="SF_Exception"/> - <library:element library:name="SF_Dictionary"/> - <library:element library:name="SF_Session"/> - <library:element library:name="_CodingConventions"/> </library:library> \ No newline at end of file