wizards/source/scriptforge/SF_PythonHelper.xba | 3 wizards/source/scriptforge/python/scriptforge.py | 126 ++++++++++++++--------- 2 files changed, 79 insertions(+), 50 deletions(-)
New commits: commit 32dda25037c01567cf97115fe4ee8ab06489d214 Author: Jean-Pierre Ledure <j...@ledure.be> AuthorDate: Wed Apr 21 16:39:44 2021 +0200 Commit: Jean-Pierre Ledure <j...@ledure.be> CommitDate: Thu Apr 22 10:48:35 2021 +0200 ScriptForge - (scriptforge.py) @classmethods A number of methods were defined implicitly as instance methods. Where apropriate they are replaced by class methods: - insertion of the @classmethod decorator - self replaced with cls 1 line in SF_PythonHelper.xba uncommented: it was so far commented in for debugging Change-Id: Ie8c3dd740f0129511295877ef947b1db35475c48 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114440 Tested-by: Jean-Pierre Ledure <j...@ledure.be> 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 b083e86b1db4..46c28293415b 100644 --- a/wizards/source/scriptforge/SF_PythonHelper.xba +++ b/wizards/source/scriptforge/SF_PythonHelper.xba @@ -569,7 +569,7 @@ Const cstObject = 2048 ' 1st argument is a Basic object when numeric Const objMODULE = 1, objCLASS = 2, objUNO = 3 Check: - 'If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch _PythonDispatcher = Null ' Ignore Null basic objects (Null = Null or Nothing) @@ -628,6 +628,7 @@ Try: ' Requires Python and Basic update in the concerned library but is transparent for this dispatcher ' Initialize Python persistent storage at 1st call + If IsEmpty(_SF_.PythonStorage) Then _SF_._InitPythonStorage() ' Reset any error _SF_._Stackreset() diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index 94fe0fe5a7bd..dfca66cb0b89 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -96,6 +96,7 @@ class ScriptForge(object, metaclass = _Singleton): port = 0 componentcontext = None scriptprovider = None + SCRIPTFORGEINITDONE = False # ######################################################################### # Class constants @@ -146,6 +147,8 @@ class ScriptForge(object, metaclass = _Singleton): # All properties and methods of the ScriptForge API are ProperCased # Compute their synonyms as lowercased and camelCased names ScriptForge.SetAttributeSynonyms() + # + ScriptForge.SCRIPTFORGEINITDONE = True @classmethod def ConnectToLOProcess(cls, hostname = '', port = 0): @@ -450,6 +453,9 @@ class SFServices(object): # enumerate all types of properties and adapt __getattr__() and __setattr__() according to their type internal_attributes = ('objectreference', 'objecttype', 'name', 'internal', 'servicename', 'serviceimplementation', 'classmodule', 'EXEC', 'SIMPLEEXEC') + # Shortcuts to script provider interfaces + SIMPLEEXEC = ScriptForge.InvokeSimpleScript + EXEC = ScriptForge.InvokeBasicService def __init__(self, reference = -1, objtype = None, classmodule = 0, name = ''): """ @@ -463,8 +469,6 @@ class SFServices(object): self.name = name # '' when no name self.internal = False # True to exceptionally allow assigning a new value to a read-only property self.localProperties = [] # the properties reserved for internal use (often empty) - self.SIMPLEEXEC = ScriptForge.InvokeSimpleScript # Shortcuts to script provider interfaces - self.EXEC = ScriptForge.InvokeBasicService def __getattr__(self, name): """ @@ -618,53 +622,63 @@ class SFScriptForge: MB_OK, MB_OKCANCEL, MB_RETRYCANCEL, MB_YESNO, MB_YESNOCANCEL = 0, 1, 5, 4, 3 IDABORT, IDCANCEL, IDIGNORE, IDNO, IDOK, IDRETRY, IDYES = 3, 2, 5, 7, 1, 4, 6 - def ConvertFromUrl(self, url): - return self.SIMPLEEXEC(self.module + '.PyConvertFromUrl', url) + @classmethod + def ConvertFromUrl(cls, url): + return cls.SIMPLEEXEC(cls.module + '.PyConvertFromUrl', url) - def ConvertToUrl(self, systempath): - return self.SIMPLEEXEC(self.module + '.PyConvertToUrl', systempath) + @classmethod + def ConvertToUrl(cls, systempath): + return cls.SIMPLEEXEC(cls.module + '.PyConvertToUrl', systempath) - def CreateUnoService(self, servicename): - return self.SIMPLEEXEC(self.module + '.PyCreateUnoService', servicename) + @classmethod + def CreateUnoService(cls, servicename): + return cls.SIMPLEEXEC(cls.module + '.PyCreateUnoService', servicename) - def DateAdd(self, interval, number, date): + @classmethod + def DateAdd(cls, interval, number, date): if isinstance(date, datetime.datetime): date = date.isoformat() - dateadd = self.SIMPLEEXEC(self.module + '.PyDateAdd', interval, number, date) + dateadd = cls.SIMPLEEXEC(cls.module + '.PyDateAdd', interval, number, date) return datetime.datetime.fromisoformat(dateadd) - def DateDiff(self, interval, date1, date2, firstdayofweek = 1, firstweekofyear = 1): + @classmethod + def DateDiff(cls, interval, date1, date2, firstdayofweek = 1, firstweekofyear = 1): if isinstance(date1, datetime.datetime): date1 = date1.isoformat() if isinstance(date2, datetime.datetime): date2 = date2.isoformat() - return self.SIMPLEEXEC(self.module + '.PyDateDiff', interval, date1, date2, firstdayofweek, firstweekofyear) + return cls.SIMPLEEXEC(cls.module + '.PyDateDiff', interval, date1, date2, firstdayofweek, firstweekofyear) - def DatePart(self, interval, date, firstdayofweek = 1, firstweekofyear = 1): + @classmethod + def DatePart(cls, interval, date, firstdayofweek = 1, firstweekofyear = 1): if isinstance(date, datetime.datetime): date = date.isoformat() - return self.SIMPLEEXEC(self.module + '.PyDatePart', interval, date, firstdayofweek, firstweekofyear) + return cls.SIMPLEEXEC(cls.module + '.PyDatePart', interval, date, firstdayofweek, firstweekofyear) - def DateValue(self, string): + @classmethod + def DateValue(cls, string): if isinstance(string, datetime.datetime): string = string.isoformat() - datevalue = self.SIMPLEEXEC(self.module + '.PyDateValue', string) + datevalue = cls.SIMPLEEXEC(cls.module + '.PyDateValue', string) return datetime.datetime.fromisoformat(datevalue) - def Format(self, expression, format = ''): + @classmethod + def Format(cls, expression, format = ''): if isinstance(expression, datetime.datetime): expression = expression.isoformat() - return self.SIMPLEEXEC(self.module + '.PyFormat', expression, format) + return cls.SIMPLEEXEC(cls.module + '.PyFormat', expression, format) @classmethod def GetDefaultContext(cls): return ScriptForge.componentcontext - def GetGuiType(self): - return self.SIMPLEEXEC(self.module + '.PyGetGuiType') + @classmethod + def GetGuiType(cls): + return cls.SIMPLEEXEC(cls.module + '.PyGetGuiType') - def GetSystemTicks(self): - return self.SIMPLEEXEC(self.module + '.PyGetSystemTicks') + @classmethod + def GetSystemTicks(cls): + return cls.SIMPLEEXEC(cls.module + '.PyGetSystemTicks') @classmethod def GetPathSeparator(cls): @@ -679,13 +693,15 @@ class SFScriptForge: def DialogLibraries(cls): return ScriptForge.InvokeSimpleScript(SFScriptForge.SF_Basic.module + '.PyGlobalScope', 'Dialog') - def InputBox(self, prompt, title = '', default = '', xpostwips = -1, ypostwips = -1): + @classmethod + def InputBox(cls, prompt, title = '', default = '', xpostwips = -1, ypostwips = -1): if xpostwips < 0 or ypostwips < 0: - return self.SIMPLEEXEC(self.module + '.PyInputBox', prompt, title, default) - return self.SIMPLEEXEC(self.module + '.PyInputBox', prompt, title, default, xpostwips, ypostwips) + return cls.SIMPLEEXEC(cls.module + '.PyInputBox', prompt, title, default) + return cls.SIMPLEEXEC(cls.module + '.PyInputBox', prompt, title, default, xpostwips, ypostwips) - def MsgBox(self, prompt, buttons = 0, title = ''): - return self.SIMPLEEXEC(self.module + '.PyMsgBox', prompt, buttons, title) + @classmethod + def MsgBox(cls, prompt, buttons = 0, title = ''): + return cls.SIMPLEEXEC(cls.module + '.PyMsgBox', prompt, buttons, title) @classmethod def Now(cls): @@ -695,8 +711,8 @@ class SFScriptForge: def RGB(cls, red, green, blue): return int('%02x%02x%02x' % (red, green, blue), 16) - @classmethod - def StarDesktop(cls): + @property + def StarDesktop(self): ctx = ScriptForge.componentcontext if ctx is None: return None @@ -704,9 +720,11 @@ class SFScriptForge: DESK = 'com.sun.star.frame.Desktop' desktop = smgr.createInstanceWithContext(DESK, ctx) return desktop + starDesktop, stardesktop = StarDesktop, StarDesktop - def Xray(self, unoobject = None): - return self.SIMPLEEXEC('XrayTool._main.xray', unoobject) + @classmethod + def Xray(cls, unoobject = None): + return cls.SIMPLEEXEC('XrayTool._main.xray', unoobject) # ######################################################################### # SF_Dictionary CLASS @@ -789,6 +807,7 @@ class SFScriptForge: for i in range(len(value)): if isinstance(value[i], dict): value[i] = None + item = value elif isinstance(value, (datetime.datetime, datetime.date, datetime.time)): item = CDateToUno(value) pv = uno.createUnoStruct('com.sun.star.beans.PropertyValue') @@ -864,23 +883,25 @@ class SFScriptForge: param = '\t'.join(list(map(repr, args))).expandtabs(tabsize = 4) return self.ExecMethod(self.vbMethod, 'DebugPrint', param) - def RaiseFatal(self, errorcode, *args): + @classmethod + def RaiseFatal(cls, errorcode, *args): """ Generate a run-time error caused by an anomaly in a user script detected by ScriptForge The message is logged in the console. The execution is STOPPED For INTERNAL USE only """ # Direct call because RaiseFatal forces an execution stop in Basic - return self.SIMPLEEXEC('SF_Exception.RaiseFatal', errorcode, *args) + return cls.SIMPLEEXEC('SF_Exception.RaiseFatal', errorcode, *args) - def _RaiseFatal(self, sub, subargs, errorcode, *args): + @classmethod + def _RaiseFatal(cls, sub, subargs, errorcode, *args): """ Wrapper of RaiseFatal(). Includes method and syntax of the failed Python routine to simulate the exact behaviour of the Basic RaiseFatal() method For INTERNAL USE only """ ScriptForge.InvokeSimpleScript('ScriptForge.SF_Utils._EnterFunction', sub, subargs) - self.RaiseFatal(errorcode, *args) + cls.RaiseFatal(errorcode, *args) raise RuntimeError("The execution of the method '" + sub.split('.')[-1] + "' failed. Execution stops.") # ######################################################################### @@ -993,9 +1014,10 @@ class SFScriptForge: def SubFolders(self, foldername, filter = ''): return self.ExecMethod(self.vbMethod, 'SubFolders', foldername, filter) - def _ConvertFromUrl(self, filename): + @classmethod + def _ConvertFromUrl(cls, filename): # Alias for same function in FileSystem Basic module - return self.SIMPLEEXEC('ScriptForge.SF_FileSystem._ConvertFromUrl', filename) + return cls.SIMPLEEXEC('ScriptForge.SF_FileSystem._ConvertFromUrl', filename) # ######################################################################### # SF_L10N CLASS @@ -1112,27 +1134,30 @@ class SFScriptForge: SCRIPTISSHAROXT = 'share:uno_packages' # in an extension installed for all users (Python) SCRIPTISOXT = 'uno_packages' # in an extension but the installation parameters are unknown (Python) - def ExecuteBasicScript(self, scope = '', script = '', *args): + @classmethod + def ExecuteBasicScript(cls, scope = '', script = '', *args): if scope is None or scope == '': - scope = self.SCRIPTISAPPLICATION + scope = cls.SCRIPTISAPPLICATION if len(args) == 0: args = (scope,) + (script,) + (None,) else: args = (scope,) + (script,) + args # ExecuteBasicScript method has a ParamArray parameter in Basic - return self.SIMPLEEXEC('@SF_Session.ExecuteBasicScript', args) + return cls.SIMPLEEXEC('@SF_Session.ExecuteBasicScript', args) - def ExecuteCalcFunction(self, calcfunction, *args): + @classmethod + def ExecuteCalcFunction(cls, calcfunction, *args): if len(args) == 0: # Arguments of Calc functions are strings or numbers. None == Empty is a good alias for no argument args = (calcfunction,) + (None,) else: args = (calcfunction,) + args # ExecuteCalcFunction method has a ParamArray parameter in Basic - return self.SIMPLEEXEC('@SF_Session.ExecuteCalcFunction', args) + return cls.SIMPLEEXEC('@SF_Session.ExecuteCalcFunction', args) - def ExecutePythonScript(self, scope = '', script = '', *args): - return self.SIMPLEEXEC(scope + ':' + script, *args) + @classmethod + def ExecutePythonScript(cls, scope = '', script = '', *args): + return cls.SIMPLEEXEC(scope + ':' + script, *args) def HasUnoMethod(self, unoobject, methodname): return self.ExecMethod(self.vbMethod, 'HasUnoMethod', unoobject, methodname) @@ -1140,9 +1165,10 @@ class SFScriptForge: def HasUnoProperty(self, unoobject, propertyname): return self.ExecMethod(self.vbMethod, 'HasUnoProperty', unoobject, propertyname) - def OpenURLInBrowser(self, url): + @classmethod + def OpenURLInBrowser(cls, url): py = ScriptForge.pythonhelpermodule + '$' + '_SF_Session__OpenURLInBrowser' - return self.SIMPLEEXEC(py, url) + return cls.SIMPLEEXEC(py, url) def RunApplication(self, command, parameters): return self.ExecMethod(self.vbMethod, 'RunApplication', command, parameters) @@ -1177,9 +1203,10 @@ class SFScriptForge: servicesynonyms = ('string', 'scriptforge.string') serviceproperties = dict() - def HashStr(self, inputstr, algorithm): + @classmethod + def HashStr(cls, inputstr, algorithm): py = ScriptForge.pythonhelpermodule + '$' + '_SF_String__HashStr' - return self.SIMPLEEXEC(py, inputstr, algorithm.lower()) + return cls.SIMPLEEXEC(py, inputstr, algorithm.lower()) def IsADate(self, inputstr, dateformat = 'YYYY-MM-DD'): return self.ExecMethod(self.vbMethod, 'IsADate', inputstr, dateformat) @@ -1894,7 +1921,8 @@ def CreateScriptService(service, *args): # Init at each CreateScriptService() invocation # CreateScriptService is usually the first statement in user scripts requesting ScriptForge services # ScriptForge() is optional in user scripts when Python process inside LibreOffice process - ScriptForge() + if ScriptForge.SCRIPTFORGEINITDONE is False: + ScriptForge() def ResolveSynonyms(servicename): """ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits