diff options
author | Jean-Pierre Ledure <jp@ledure.be> | 2025-03-29 16:09:57 +0100 |
---|---|---|
committer | Jean-Pierre Ledure <jp@ledure.be> | 2025-03-30 11:12:08 +0200 |
commit | c8d2751a90cbf1eceaf34257876d09b4eb1efd9d (patch) | |
tree | 56c9a7edec6347b2e2c31574152dee903cb18dca /wizards/source | |
parent | 11f10c48688436129337ffc7a082a56023c58071 (diff) |
ScriptForge (SF_Exception) Return codes
So far, an exception raised in a user script
and detected by ScriptForge gave next behaviour:
- an error message was displayed to the user (1)
- the same error message was recorded in the
console (2)
- the execution of the script was stopped (3)
The actual commit introduces 4 new properties
in the SF_Exception service.
Next two boolean properties may optionally
change above behaviour:
exception.ReportScriptErrors (default = True)
exception.StopWhenError (default = True)
They may change resp. behaviours (1) and (3).
Note that behaviour (2) is preserved anyway.
Their values are set until they are set
again or until the LO session expires.
When StopWhenError is set to False, next two
properties allow to test the success of the
last call to the ScriptForge API and to
define an appropriate action, including the
continuation of the process:
exception.ReturnCode
exception.ReturnCodeDescription
Example:
exc = CreateScriptService("Exception")
fs = CreateScriptService("FileSystem")
exc.ReportScriptErrors = False
exc.StopWhenError = False
fs.OpenTextFile("/aaa/bbb")
if exc.ReturnCode = "UNKNOWNFILEERROR":
...
The test on the return code must precede any
next call to any ScriptForge API entry.
The list of the available return codes is
listed in the SF_Exception.xba source code.
These changes are applicable both for Basic
and Python user scripts.
The user documentation should be reviewed.
Change-Id: I6d274e54ee37702f244e729ea5c9d1751b69abec
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183486
Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
Tested-by: Jenkins
Diffstat (limited to 'wizards/source')
-rw-r--r-- | wizards/source/scriptforge/SF_Exception.xba | 123 | ||||
-rw-r--r-- | wizards/source/scriptforge/SF_Root.xba | 8 | ||||
-rw-r--r-- | wizards/source/scriptforge/SF_Utils.xba | 11 | ||||
-rw-r--r-- | wizards/source/scriptforge/dialog.xlb | 2 | ||||
-rw-r--r-- | wizards/source/scriptforge/python/scriptforge.py | 7 | ||||
-rw-r--r-- | wizards/source/scriptforge/python/scriptforge.pyi | 23 | ||||
-rw-r--r-- | wizards/source/scriptforge/script.xlb | 16 |
7 files changed, 154 insertions, 36 deletions
diff --git a/wizards/source/scriptforge/SF_Exception.xba b/wizards/source/scriptforge/SF_Exception.xba index ad0566ddfe9f..d8104e8c8596 100644 --- a/wizards/source/scriptforge/SF_Exception.xba +++ b/wizards/source/scriptforge/SF_Exception.xba @@ -33,10 +33,17 @@ Option Explicit ''' or during control events processing ''' => DebugPrint() ''' -''' The usual behaviour of the application when an error occurs is: -''' 1. Log the error in the console -''' 2, Inform the user about the error with either a standard or a customized message -''' 3. Optionally, stop the execution of the current macro +''' The behaviour of the application when an error occurs is: +''' 1. Log the error in the console. This is always done +''' 2. Inform the user about the error with either a standard or a localized message +''' To force a silent mode, set : +''' exception.ReportScriptErrors = False ' Default = True +''' 3. To not stop the execution of the current macro when ScriptForge detects +''' a user script error, set : +''' exception.StopWhenError = False ' Default = True +''' It then makes sense before further processing to explore the values of +''' exception.ReturnCode ' Short error description +''' exception.ReturnCodeDescription ' Long error description ''' ''' Detailed user documentation: ''' https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_exception.html?DbPAR=BASIC @@ -206,6 +213,41 @@ Property Let Number(ByVal pvNumber As Variant) End Property ' ScriptForge.SF_Exception.Number (let) REM ----------------------------------------------------------------------------- +Property Get ReportScriptErrors() As Variant +''' Indicates whether script errors are displayed in a message box when they occur +''' Example: +''' myException.ReportScriptErrors + ReportScriptErrors = _PropertyGet("ReportScriptErrors") +End Property ' ScriptForge.SF_Exception.ReportScriptErrors (get) + +REM ----------------------------------------------------------------------------- +Property Let ReportScriptErrors(ByVal pvReportScriptErrors As Variant) +''' When set to False, an error occur silently. Useful f.i. in Calc user-defined functions. +''' The set value is preserved until it is explicitly set again. +''' Example: +''' myException.ReportScriptErrors = False + _PropertySet "ReportScriptErrors", pvReportScriptErrors +End Property ' ScriptForge.SF_Exception.ReportScriptErrors (let) + +REM ----------------------------------------------------------------------------- +Property Get ReturnCode() As String +''' Returns the code returned by the last call to the ScriptForge API from a user script. +''' It is the zero-length string if everything ran without error +''' Example: +''' myException.ReturnCode + ReturnCode = _PropertyGet("ReturnCode") +End Property ' ScriptForge.SF_Exception.ReturnCode (get) + +REM ----------------------------------------------------------------------------- +Property Get ReturnCodeDescription() As String +''' Returns the localized description of the code returned by the last call to the ScriptForge API from a user script. +''' It is the zero-length string if everything ran without error +''' Example: +''' myException.ReturnCodeDescription + ReturnCodeDescription = _PropertyGet("ReturnCodeDescription") +End Property ' ScriptForge.SF_Exception.ReturnCodeDescription (get) + +REM ----------------------------------------------------------------------------- Property Get Source() As Variant ''' Returns the location of the last error that has occurred ''' Example: @@ -222,6 +264,23 @@ Property Let Source(ByVal pvSource As Variant) End Property ' ScriptForge.SF_Exception.Source (let) REM ----------------------------------------------------------------------------- +Property Get StopWhenError() As Variant +''' Indicates whether the Basic process is stopped when ScriptForge detects a user script error +''' Example: +''' myException.StopWhenError + StopWhenError = _PropertyGet("StopWhenError") +End Property ' ScriptForge.SF_Exception.StopWhenError (get) + +REM ----------------------------------------------------------------------------- +Property Let StopWhenError(ByVal pvStopWhenError As Variant) +''' When set to False, the Basic process continues when ScriptForge detects a user script error. Default = True. +''' The set value is preserved until it is explicitly set again. +''' Example: +''' myException.StopWhenError = False + _PropertySet "StopWhenError", pvStopWhenError +End Property ' ScriptForge.SF_Exception.StopWhenError (let) + +REM ----------------------------------------------------------------------------- Property Get ObjectType As String ''' Only to enable object representation ObjectType = "SF_Exception" @@ -237,7 +296,7 @@ REM ===================================================================== METHOD REM ----------------------------------------------------------------------------- Public Sub Clear() -''' Reset the current error status and clear the SF_Exception object +''' Reset the current error status, clear the SF_Exception object and reinitialize the return code. ''' Args: ''' Examples: ''' On Local Error GoTo Catch @@ -260,6 +319,11 @@ Try: ._SysDescription = "" End With + With _SF_ + .ReturnCode = "" + .ReturnCodeDescription = "" + End With + Finally: On Error GoTo 0 Exit Sub @@ -320,7 +384,7 @@ Try: ' Terminate the modal dialog If Modal Then Set .ConsoleControl = .ConsoleControl.Dispose() - Set .ConsoleDialog = .ConsoleDialog.Dispose() + .ConsoleDialog.Terminate() End If End If End With @@ -527,7 +591,7 @@ Const cstSubArgs = "" GetProperty = Null Check: - If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If SF_Utils._EnterFunction(cstThisSub, cstSubArgs, pbReinitRC := False) Then ' Keep return codes untouched If Not SF_Utils._Validate(PropertyName, "PropertyName", V_STRING, Properties()) Then GoTo Catch End If @@ -566,7 +630,11 @@ Public Function Properties() As Variant Properties = Array( _ "Description" _ , "Number" _ + , "ReportScriptErrors" _ + , "ReturnCode" _ + , "ReturnCodeDescription" _ , "Source" _ + , "StopWhenError" _ ) End Function ' ScriptForge.SF_Exception.Properties @@ -620,6 +688,7 @@ REM ---------------------------------------------------------------------------- Public Sub Raise(Optional ByVal Number As Variant _ , Optional ByVal Source As Variant _ , Optional ByVal Description As Variant _ + , Optional ByVal _Warning As Variant _ ) ''' Generate a run-time error. An error message is displayed to the user and logged ''' in the console. The execution is STOPPED @@ -628,6 +697,7 @@ Public Sub Raise(Optional ByVal Number As Variant _ ''' If numeric and <= 2000, it is considered a LibreOffice Basic run-time error (default = Err) ''' Source: the line where the error occurred (default = Erl) or any string describing the location of the error ''' Description: the error message to log in the console and to display to the user +''' _Warning: When True, do not stop the process. FOR INTERNAL USE ONLY ''' Examples: ''' On Local Error GoTo Catch ''' ' ... @@ -650,6 +720,7 @@ Check: If IsMissing(Number) Or IsEmpty(Number) Then Number = -1 If IsMissing(Source) Or IsEmpty(Source) Then Source = -1 If IsMissing(Description) Or IsEmpty(Description) Then Description = "" + If IsMissing(_Warning) Or IsEmpty(_Warning) Then _Warning = False If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then If Not SF_Utils._Validate(Number, "Number", Array(V_STRING, V_NUMERIC)) Then GoTo Finally If Not SF_Utils._Validate(Source, "Source", Array(V_STRING, V_NUMERIC)) Then GoTo Finally @@ -670,7 +741,7 @@ Try: Set L10N = _SF_._GetLocalizedInterface() sMessage = L10N.GetText("LONGERRORDESC", .Number, .Source, .Description) .DebugPrint(sMessage) - If _SF_.DisplayEnabled Then MsgBox L10N.GetText("ERRORNUMBER", .Number) _ + If _SF_.ReportScriptErrors Then MsgBox L10N.GetText("ERRORNUMBER", .Number) _ & SF_String.sfNewLine & L10N.GetText("ERRORLOCATION", .Source) _ & SF_String.sfNewLine & .Description _ , MB_OK + MB_ICONSTOP _ @@ -679,7 +750,7 @@ Try: Finally: SF_Utils._ExitFunction(cstThisSub) - If _SF_.StopWhenError Then + If Not _Warning Then SF_Exception.Clear() _SF_._StackReset() Stop @@ -729,7 +800,7 @@ Try: ' Log and display sMessage = L10N.GetText("LONGERRORDESC", .Number, .Source, .Description) .DebugPrint(sMessage) - If _SF_.DisplayEnabled Then + If _SF_.ReportScriptErrors Then sMessage = sLocation _ & L10N.GetText("INTERNALERROR") _ & L10N.GetText("ERRORLOCATION", Source & "/" & .Source) & SF_String.sfNewLine & .Description _ @@ -744,7 +815,7 @@ Try: Finally: _SF_._StackReset() - If _SF_.StopWhenError Then Stop + Stop ' Unconditional stop whatever the value of the StopWhenError flag Exit Sub Catch: GoTo Finally @@ -1096,7 +1167,7 @@ Try: _SF_._AddToConsole(sMessage) ' Display fatal event, if relevant (default) - If _SF_.DisplayEnabled Then + If _SF_.ReportScriptErrors Then If _SF_.StopWhenError Then sMessage = sMessage & "\n" & "\n" & "\n" & L10N.GetText("STOPEXECUTION") ' Do you need more help ? If Len(sMethod) > 0 Then @@ -1115,8 +1186,12 @@ Try: Finally: SF_Utils._ExitFunction(cstThisSub) - _SF_._StackReset() - If _SF_.StopWhenError Then Stop + With _SF_ + ._StackReset() + If .StopWhenError Then Stop + .ReturnCode = ErrorCode + .ReturnCodeDescription = sMessage + End With Exit Sub Catch: GoTo Finally @@ -1145,7 +1220,6 @@ Public Sub RaiseWarning(Optional ByVal Number As Variant _ ''' SF_Exception.RaiseWarning("MYAPPERROR", "myFunction", "Application error") ''' SF_Exception.RaiseWarning(,, "To divide by zero is not a good idea !") -Dim bStop As Boolean ' Alias for stop switch Const cstThisSub = "Exception.RaiseWarning" Const cstSubArgs = "[Number=Err], [Source=Erl], [Description]" @@ -1164,13 +1238,10 @@ Check: End If Try: - bStop = _SF_.StopWhenError ' Store current value to reset it before leaving the Sub - _SF_.StopWhenError = False - SF_Exception.Raise(Number, Source, Description) + SF_Exception.Raise(Number, Source, Description, _Warning := True) Finally: SF_Utils._ExitFunction(cstThisSub) - _SF_.StopWhenError = bStop Exit Sub Catch: GoTo Finally @@ -1248,7 +1319,7 @@ End Sub ' ScriptForge.SF_Exception._CloseConsole REM ----------------------------------------------------------------------------- Private Sub _ConsoleRefresh() ''' Reload the content of the console in the dialog -''' Needed when console first loaded or when totally or partially cleared +''' Needed when console loaded for the first time or when totally or partially cleared With _SF_ ' Do nothing if console inactive @@ -1302,8 +1373,16 @@ Const cstSubArgs = "" If _Description = "" Then _PropertyGet = _SysDescription Else _PropertyGet = _Description Case "Number" If IsEmpty(_Number) Then _PropertyGet = _SysNumber Else _PropertyGet = _Number + Case "ReportScriptErrors" + _PropertyGet = _SF_.ReportScriptErrors + Case "ReturnCode" + _PropertyGet = _SF_.ReturnCode + Case "ReturnCodeDescription" + _PropertyGet = _SF_.ReturnCodeDescription Case "Source" If IsEmpty(_Source) Then _PropertyGet = _SysSource Else _PropertyGet = _Source + Case "StopWhenError" + _PropertyGet = _SF_.StopWhenError Case Else _PropertyGet = Null End Select @@ -1346,6 +1425,8 @@ Const cstSubArgs = "" _Number = Empty Case Else End Select + Case "ReportScriptErrors" + If VarType(pvValue) = V_BOOLEAN Then _SF_.ReportScriptErrors = pvValue Case "Source" Select Case SF_Utils._VarTypeExt(pvValue) Case V_STRING @@ -1354,6 +1435,8 @@ Const cstSubArgs = "" _Source = CLng(pvValue) Case Else End Select + Case "StopWhenError" + If VarType(pvValue) = V_BOOLEAN Then _SF_.StopWhenError = pvValue Case Else End Select diff --git a/wizards/source/scriptforge/SF_Root.xba b/wizards/source/scriptforge/SF_Root.xba index 63aaf6bdb05a..fd1e566d04d0 100644 --- a/wizards/source/scriptforge/SF_Root.xba +++ b/wizards/source/scriptforge/SF_Root.xba @@ -34,8 +34,10 @@ Private ErrorHandler As Boolean ' True = error handling active, False = in Private ConsoleLines() As Variant ' Array of messages displayable in console Private ConsoleDialog As Object ' SFDialogs.Dialog object Private ConsoleControl As Object ' SFDialogs.DialogControl object -Private DisplayEnabled As Boolean ' When True, display of console or error messages is allowed +Private ReportScriptErrors As Boolean ' When True, error messages are displayed to the user Private StopWhenError As Boolean ' When True, process stops after error > "WARNING" +Private ReturnCode As String ' The short error code +Private ReturnCodeDescription As String ' The long and localized error message Private TriggeredByPython As Boolean ' When True, the actual user script is a Python script Private DebugMode As Boolean ' When True, log enter/exit each official Sub @@ -109,8 +111,10 @@ Private Sub Class_Initialize() ConsoleLines = Array() Set ConsoleDialog = Nothing Set ConsoleControl = Nothing - DisplayEnabled = True + ReportScriptErrors = True StopWhenError = True + ReturnCode = "" + ReturnCodeDescription = "" TriggeredByPython = False DebugMode = False Set ProgressBarDialog = Nothing diff --git a/wizards/source/scriptforge/SF_Utils.xba b/wizards/source/scriptforge/SF_Utils.xba index c84821898333..ef6b11c08129 100644 --- a/wizards/source/scriptforge/SF_Utils.xba +++ b/wizards/source/scriptforge/SF_Utils.xba @@ -153,7 +153,10 @@ Finally: End Function ' ScriptForge.SF_Utils._CStrToDate REM ----------------------------------------------------------------------------- -Public Function _EnterFunction(ByVal psSub As String, Optional ByVal psArgs As String) As Boolean +Public Function _EnterFunction(ByVal psSub As String _ + , Optional ByVal psArgs As String _ + , Optional ByVal pbReinitRC As Variant _ + ) As Boolean ''' Called on top of each public function ''' Used to trace routine in/outs (debug mode) ''' and to allow the explicit mention of the user call which caused an error @@ -164,11 +167,17 @@ Public Function _EnterFunction(ByVal psSub As String, Optional ByVal psArgs As S If IsEmpty(_SF_) Or IsNull(_SF_) Then SF_Utils._InitializeRoot() ' First use of ScriptForge during current LibO session If IsMissing(psArgs) Then psArgs = "" + If IsMissing(pbReinitRC) Then pbReinitRC = True With _SF_ If .StackLevel = 0 Then .MainFunction = psSub .MainFunctionArgs = psArgs _EnterFunction = True + If pbReinitRC Then + ' Reinitialize return code status + .ReturnCode = "" + .ReturnCodeDescription = "" + End If Else _EnterFunction = False End If diff --git a/wizards/source/scriptforge/dialog.xlb b/wizards/source/scriptforge/dialog.xlb index 5bd67a06a121..7b54d071c4f9 100644 --- a/wizards/source/scriptforge/dialog.xlb +++ b/wizards/source/scriptforge/dialog.xlb @@ -1,6 +1,6 @@ <?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="dlgProgress"/> <library:element library:name="dlgConsole"/> + <library:element library:name="dlgProgress"/> </library:library>
\ No newline at end of file diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index c364a9789ddb..534e11016919 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -1074,7 +1074,10 @@ class SFScriptForge: serviceimplementation = 'basic' servicename = 'ScriptForge.Exception' servicesynonyms = ('exception', 'scriptforge.exception') - serviceproperties = dict() + serviceproperties = dict(ReportScriptErrors = 3, ReturnCode = 1, ReturnCodeDescription = 1, StopWhenError = 3) + + def Clear(self): + return self.ExecMethod(self.vbMethod, 'Clear') def Console(self, modal = True): # From Python, the current XComponentContext must be added as last argument @@ -1170,7 +1173,7 @@ class SFScriptForge: serviceimplementation = 'basic' servicename = 'ScriptForge.FileSystem' servicesynonyms = ('filesystem', 'scriptforge.filesystem') - serviceproperties = dict(FileNaming = 3, ConfigFolder = 1, ExtensionsFolder = 1, HomeFolder = 1, + serviceproperties = dict(ConfigFolder = 1, ExtensionsFolder = 1, FileNaming = 3, HomeFolder = 1, InstallFolder = 1, TemplatesFolder = 1, TemporaryFolder = 1, UserTemplatesFolder = 1) # 1 because FileNaming determines every time the folder format # Open TextStream constants diff --git a/wizards/source/scriptforge/python/scriptforge.pyi b/wizards/source/scriptforge/python/scriptforge.pyi index 369ba40fcc3d..68d4e5d2c22c 100644 --- a/wizards/source/scriptforge/python/scriptforge.pyi +++ b/wizards/source/scriptforge/python/scriptforge.pyi @@ -780,7 +780,26 @@ class SFScriptForge: Console entries can be dumped to a text file or visualized in a dialogue. """ - def Console(self, modal: bool = ...): + ReportScriptErrors: bool + """ When set to ``False``, an error occur silently. Useful f.i. in Calc user-defined functions. + The set value is preserved until it is explicitly set again. """ + ReturnCode: str + """ Returns the code returned by the last call to the ScriptForge API from a user script. + It is the zero-length string if everything ran without error. """ + ReturnCodeDescription: str + """ Returns the localized description of the code returned by the last call to the ScriptForge API + from a user script. It is the zero-length string if everything ran without error. """ + StopWhenError: bool + """ When set to ``False``, the process continues when ScriptForge detects a user script error. + Default = ``True``. The set value is preserved until it is explicitly set again. """ + + def Clear(self): + """ + Reset the current error status and return code. + """ + ... + + def Console(self, modal: bool = ...) -> None: """ Displays the console messages in a modal or non-modal dialog. In both modes, all the past messages issued by a ``DebugPrint()`` method or resulting from an exception are displayed. In non-modal mode, @@ -796,7 +815,7 @@ class SFScriptForge: """ ... - def ConsoleClear(self, keep: int = ...): + def ConsoleClear(self, keep: int = ...) -> None: """ Clears the console keeping an optional number of recent messages. If the console is activated in non-modal mode, it is refreshed. diff --git a/wizards/source/scriptforge/script.xlb b/wizards/source/scriptforge/script.xlb index b91788543b81..8a853e5342e3 100644 --- a/wizards/source/scriptforge/script.xlb +++ b/wizards/source/scriptforge/script.xlb @@ -1,23 +1,23 @@ <?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="_ModuleModel"/> - <library:element library:name="SF_Session"/> - <library:element library:name="SF_Dictionary"/> <library:element library:name="SF_Exception"/> + <library:element library:name="SF_Dictionary"/> <library:element library:name="SF_Services"/> <library:element library:name="SF_UI"/> - <library:element library:name="SF_Timer"/> - <library:element library:name="SF_FileSystem"/> <library:element library:name="SF_TextStream"/> <library:element library:name="SF_Array"/> + <library:element library:name="SF_Region"/> + <library:element library:name="SF_L10N"/> <library:element library:name="SF_PythonHelper"/> <library:element library:name="SF_Platform"/> <library:element library:name="SF_String"/> + <library:element library:name="SF_Session"/> + <library:element library:name="_ModuleModel"/> <library:element library:name="_CodingConventions"/> <library:element library:name="SF_Utils"/> - <library:element library:name="SF_Root"/> <library:element library:name="__License"/> - <library:element library:name="SF_Region"/> - <library:element library:name="SF_L10N"/> + <library:element library:name="SF_Root"/> + <library:element library:name="SF_Timer"/> + <library:element library:name="SF_FileSystem"/> </library:library>
\ No newline at end of file |