summaryrefslogtreecommitdiffstats
path: root/wizards/source/scriptforge/python/ScriptForgeHelper.py
diff options
context:
space:
mode:
Diffstat (limited to 'wizards/source/scriptforge/python/ScriptForgeHelper.py')
-rw-r--r--wizards/source/scriptforge/python/ScriptForgeHelper.py317
1 files changed, 317 insertions, 0 deletions
diff --git a/wizards/source/scriptforge/python/ScriptForgeHelper.py b/wizards/source/scriptforge/python/ScriptForgeHelper.py
new file mode 100644
index 000000000..396273233
--- /dev/null
+++ b/wizards/source/scriptforge/python/ScriptForgeHelper.py
@@ -0,0 +1,317 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2019-2022 Jean-Pierre LEDURE, Rafael LIMA, Alain ROMEDENNE
+
+# ======================================================================================================================
+# === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
+# === Full documentation is available on https://help.libreoffice.org/ ===
+# ======================================================================================================================
+
+# ScriptForge is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# ScriptForge is free software; you can redistribute it and/or modify it under the terms of either (at your option):
+
+# 1) The Mozilla Public License, v. 2.0. If a copy of the MPL was not
+# distributed with this file, you can obtain one at http://mozilla.org/MPL/2.0/ .
+
+# 2) The GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version. If a copy of the LGPL was not
+# distributed with this file, see http://www.gnu.org/licenses/ .
+
+"""
+Collection of Python helper functions called from the ScriptForge Basic libraries
+to execute specific services that are not or not easily available from Basic directly.
+"""
+
+import getpass
+import os
+import platform
+import hashlib
+import filecmp
+import webbrowser
+import json
+
+
+class _Singleton(type):
+ """
+ A Singleton design pattern
+ Credits: « Python in a Nutshell » by Alex Martelli, O'Reilly
+ """
+ instances = {}
+
+ def __call__(cls, *args, **kwargs):
+ if cls not in cls.instances:
+ cls.instances[cls] = super(_Singleton, cls).__call__(*args, **kwargs)
+ return cls.instances[cls]
+
+
+# #################################################################
+# Dictionary service
+# #################################################################
+
+def _SF_Dictionary__ConvertToJson(propval, indent = None) -> str:
+ # used by Dictionary.ConvertToJson() Basic method
+ """
+ Given an array of PropertyValues as argument, convert it to a JSON string
+ """
+ # Array of property values => Dict(ionary) => JSON
+ pvDict = {}
+ for pv in propval:
+ pvDict[pv.Name] = pv.Value
+ return json.dumps(pvDict, indent=indent, skipkeys=True)
+
+
+def _SF_Dictionary__ImportFromJson(jsonstr: str): # used by Dictionary.ImportFromJson() Basic method
+ """
+ Given a JSON string as argument, convert it to a list of tuples (name, value)
+ The value must not be a (sub)dict. This doesn't pass the python-basic bridge.
+ """
+ # JSON => Dictionary => Array of tuples/lists
+ dico = json.loads(jsonstr)
+ result = []
+ for key in iter(dico):
+ value = dico[key]
+ item = value
+ if isinstance(value, dict): # check that first level is not itself a (sub)dict
+ item = None
+ elif isinstance(value, list): # check every member of the list is not a (sub)dict
+ for i in range(len(value)):
+ if isinstance(value[i], dict): value[i] = None
+ result.append((key, item))
+ return result
+
+
+# #################################################################
+# Exception service
+# #################################################################
+
+def _SF_Exception__PythonPrint(string: str) -> bool:
+ # used by SF_Exception.PythonPrint() Basic method
+ """
+ Write the argument to stdout.
+ If the APSO shell console is active, the argument will be displayed in the console window
+ """
+ print(string)
+ return True
+
+
+# #################################################################
+# FileSystem service
+# #################################################################
+
+def _SF_FileSystem__CompareFiles(filename1: str, filename2: str, comparecontents=True) -> bool:
+ # used by SF_FileSystem.CompareFiles() Basic method
+ """
+ Compare the 2 files, returning True if they seem equal, False otherwise.
+ By default, only their signatures (modification time, ...) are compared.
+ When comparecontents == True, their contents are compared.
+ """
+ try:
+ return filecmp.cmp(filename1, filename2, not comparecontents)
+ except Exception:
+ return False
+
+
+def _SF_FileSystem__GetFilelen(systemfilepath: str) -> str: # used by SF_FileSystem.GetFilelen() Basic method
+ return str(os.path.getsize(systemfilepath))
+
+
+def _SF_FileSystem__HashFile(filename: str, algorithm: str) -> str: # used by SF_FileSystem.HashFile() Basic method
+ """
+ Hash a given file with the given hashing algorithm
+ cfr. https://www.pythoncentral.io/hashing-files-with-python/
+ Example
+ hash = _SF_FileSystem__HashFile('myfile.txt','MD5')
+ """
+ algo = algorithm.lower()
+ try:
+ if algo in hashlib.algorithms_guaranteed:
+ BLOCKSIZE = 65535 # Provision for large size files
+ if algo == 'md5':
+ hasher = hashlib.md5()
+ elif algo == 'sha1':
+ hasher = hashlib.sha1()
+ elif algo == 'sha224':
+ hasher = hashlib.sha224()
+ elif algo == 'sha256':
+ hasher = hashlib.sha256()
+ elif algo == 'sha384':
+ hasher = hashlib.sha384()
+ elif algo == 'sha512':
+ hasher = hashlib.sha512()
+ else:
+ return ''
+ with open(filename, 'rb') as file: # open in binary mode
+ buffer = file.read(BLOCKSIZE)
+ while len(buffer) > 0:
+ hasher.update(buffer)
+ buffer = file.read(BLOCKSIZE)
+ return hasher.hexdigest()
+ else:
+ return ''
+ except Exception:
+ return ''
+
+
+# #################################################################
+# Platform service
+# #################################################################
+
+def _SF_Platform(propertyname: str): # used by SF_Platform Basic module
+ """
+ Switch between SF_Platform properties (read the documentation about the ScriptForge.Platform service)
+ """
+ pf = Platform()
+ if propertyname == 'Architecture':
+ return pf.Architecture
+ elif propertyname == 'ComputerName':
+ return pf.ComputerName
+ elif propertyname == 'CPUCount':
+ return pf.CPUCount
+ elif propertyname == 'CurrentUser':
+ return pf.CurrentUser
+ elif propertyname == 'Machine':
+ return pf.Machine
+ elif propertyname == 'OSName':
+ return pf.OSName
+ elif propertyname == 'OSPlatform':
+ return pf.OSPlatform
+ elif propertyname == 'OSRelease':
+ return pf.OSRelease
+ elif propertyname == 'OSVersion':
+ return pf.OSVersion
+ elif propertyname == 'Processor':
+ return pf.Processor
+ elif propertyname == 'PythonVersion':
+ return pf.PythonVersion
+ else:
+ return None
+
+
+class Platform(object, metaclass = _Singleton):
+ @property
+ def Architecture(self): return platform.architecture()[0]
+
+ @property # computer's network name
+ def ComputerName(self): return platform.node()
+
+ @property # number of CPU's
+ def CPUCount(self): return os.cpu_count()
+
+ @property
+ def CurrentUser(self):
+ try:
+ return getpass.getuser()
+ except Exception:
+ return ''
+
+ @property # machine type e.g. 'i386'
+ def Machine(self): return platform.machine()
+
+ @property # system/OS name e.g. 'Darwin', 'Java', 'Linux', ...
+ def OSName(self): return platform.system().replace('Darwin', 'macOS')
+
+ @property # underlying platform e.g. 'Windows-10-...'
+ def OSPlatform(self): return platform.platform(aliased = True)
+
+ @property # system's release e.g. '2.2.0'
+ def OSRelease(self): return platform.release()
+
+ @property # system's version
+ def OSVersion(self): return platform.version()
+
+ @property # real processor name e.g. 'amdk'
+ def Processor(self): return platform.processor()
+
+ @property # Python major.minor.patchlevel
+ def PythonVersion(self): return 'Python ' + platform.python_version()
+
+
+# #################################################################
+# Session service
+# #################################################################
+
+def _SF_Session__OpenURLInBrowser(url: str): # Used by SF_Session.OpenURLInBrowser() Basic method
+ """
+ Display url using the default browser
+ """
+ try:
+ webbrowser.open(url, new = 2)
+ finally:
+ return None
+
+
+# #################################################################
+# String service
+# #################################################################
+
+def _SF_String__HashStr(string: str, algorithm: str) -> str: # used by SF_String.HashStr() Basic method
+ """
+ Hash a given UTF-8 string with the given hashing algorithm
+ Example
+ hash = _SF_String__HashStr('This is a UTF-8 encoded string.','MD5')
+ """
+ algo = algorithm.lower()
+ try:
+ if algo in hashlib.algorithms_guaranteed:
+ ENCODING = 'utf-8'
+ bytestring = string.encode(ENCODING) # Hashing functions expect bytes, not strings
+ if algo == 'md5':
+ hasher = hashlib.md5(bytestring)
+ elif algo == 'sha1':
+ hasher = hashlib.sha1(bytestring)
+ elif algo == 'sha224':
+ hasher = hashlib.sha224(bytestring)
+ elif algo == 'sha256':
+ hasher = hashlib.sha256(bytestring)
+ elif algo == 'sha384':
+ hasher = hashlib.sha384(bytestring)
+ elif algo == 'sha512':
+ hasher = hashlib.sha512(bytestring)
+ else:
+ return ''
+ return hasher.hexdigest()
+ else:
+ return ''
+ except Exception:
+ return ''
+
+
+# #################################################################
+# lists the scripts, that shall be visible inside the Basic/Python IDE
+# #################################################################
+
+g_exportedScripts = ()
+
+if __name__ == "__main__":
+ print(_SF_Platform('Architecture'))
+ print(_SF_Platform('ComputerName'))
+ print(_SF_Platform('CPUCount'))
+ print(_SF_Platform('CurrentUser'))
+ print(_SF_Platform('Machine'))
+ print(_SF_Platform('OSName'))
+ print(_SF_Platform('OSPlatform'))
+ print(_SF_Platform('OSRelease'))
+ print(_SF_Platform('OSVersion'))
+ print(_SF_Platform('Processor'))
+ print(_SF_Platform('PythonVersion'))
+ #
+ print(hashlib.algorithms_guaranteed)
+ print(_SF_FileSystem__HashFile('/opt/libreoffice6.4/program/libbootstraplo.so', 'md5'))
+ print(_SF_FileSystem__HashFile('/opt/libreoffice6.4/share/Scripts/python/Capitalise.py', 'sha512'))
+ #
+ print(_SF_String__HashStr('œ∑¡™£¢∞§¶•ªº–≠œ∑´®†¥¨ˆøπ“‘åß∂ƒ©˙∆˚¬', 'MD5')) # 616eb9c513ad07cd02924b4d285b9987
+ #
+ # _SF_Session__OpenURLInBrowser('https://docs.python.org/3/library/webbrowser.html')
+ #
+ js = """
+ {"firstName": "John","lastName": "Smith","isAlive": true,"age": 27,
+ "address": {"streetAddress": "21 2nd Street","city": "New York","state": "NY","postalCode": "10021-3100"},
+ "phoneNumbers": [{"type": "home","number": "212 555-1234"},{"type": "office","number": "646 555-4567"}],
+ "children": ["Q", "M", "G", "T"],"spouse": null}
+ """
+ arr = _SF_Dictionary__ImportFromJson(js)
+ print(arr)