diff --git a/additions/PythonExtensionsCollection/File/CFile.py b/additions/PythonExtensionsCollection/File/CFile.py deleted file mode 100644 index 320424c6..00000000 --- a/additions/PythonExtensionsCollection/File/CFile.py +++ /dev/null @@ -1,1072 +0,0 @@ -# ************************************************************************************************************** -# -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ************************************************************************************************************** -# -# CFile.py -# -# XC-CT/ECA3-Queckenstedt -# -# 27.06.2022 -# -# ************************************************************************************************************** - -# -- import standard Python modules -import os, shutil, platform - -# -- import Bosch Python modules -from PythonExtensionsCollection.String.CString import CString - -# ************************************************************************************************************** - -class enFileStatiType: - """ -The class ``enFileStatiType`` defines the sollowing file states: - -* ``closed`` -* ``openedforwriting`` -* ``openedforappending`` -* ``openedforreading`` - """ - closed = "closed" - openedforwriting = "openedforwriting" - openedforappending = "openedforappending" - openedforreading = "openedforreading" - -# -------------------------------------------------------------------------------------------------------------- - -class CFile(object): - """ -The class ``CFile`` provides a small set of file functions with extended parametrization (like switches -defining if a file is allowed to be overwritten or not). - -Most of the functions at least returns ``bSuccess`` and ``sResult``. - -* ``bSuccess`` is ``True`` in case of no error occurred. -* ``bSuccess`` is ``False`` in case of an error occurred. -* ``bSuccess`` is ``None`` in case of a very fatal error occurred (exceptions). - -* ``sResult`` contains details about what happens during computation. - -Every instance of CFile handles one single file only and forces exclusive access to this file. - -It is not possible to create an instance of this class with a file that is already in use by another instance. - -It is also not possible to use ``CopyTo`` or ``MoveTo`` to overwrite files that are already in use by another instance. -This makes the file handling more save against access violations. - """ - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __init__(self, sFile=None): - self.__sFile = CString.NormalizePath(sFile) - self.__oFileHandle = None - self.__oFileStatus = enFileStatiType.closed - self.__sLastDestination = None - - try: - CFile.__listFilesInUse - except: - CFile.__listFilesInUse = [] - - # exclusive access is required (checked by self.__bIsFreeToUse; relevant for destination in CopyTo and MoveTo) - if self.__sFile in CFile.__listFilesInUse: - raise Exception(f"The file '{self.__sFile}' is already in use by another CFile instance.") - else: - CFile.__listFilesInUse.append(self.__sFile) - - # eof def __init__(self, sFile=None): - - def __del__(self): - self.Close() - if self.__sFile in CFile.__listFilesInUse: - CFile.__listFilesInUse.remove(self.__sFile) - - # eof def __del__(self): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __bIsFreeToUse(self, sFile=None): - """ -Checks if the file ``sFile`` is free to use, that means: not used by another instance of ``CFile``. - """ - - bIsFreeToUse = False # init - if sFile is None: - bIsFreeToUse = False # error handling - else: - if sFile in CFile.__listFilesInUse: - bIsFreeToUse = False - else: - bIsFreeToUse = True - return bIsFreeToUse - - # eof def __bIsFreeToUse(self, sFile=None): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __OpenForWriting(self): - """ -Opens a text file for writing. - -Returns ``bSuccess`` and ``sResult`` (feedback). - """ - - sMethod = "CFile.__OpenForWriting" - - if self.__sFile is None: - bSuccess = False - sResult = "self.__sFile is None; please provide path and name of a file when creating a CFile object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - bSuccess, sResult = self.Close() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - try: - self.__oFileHandle = open(self.__sFile, "w", encoding="utf-8") - self.__oFileStatus = enFileStatiType.openedforwriting - bSuccess = True - sResult = f"File '{self.__sFile}' is open for writing" - except Exception as reason: - self.Close() - bSuccess = None - sResult = f"Not possible to open file '{self.__sFile}' for writing.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def __OpenForWriting(self): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __OpenForAppending(self): - """ -Opens a text file for appending. - -Returns ``bSuccess`` and ``sResult`` (feedback). - """ - - sMethod = "CFile.__OpenForAppending" - - if self.__sFile is None: - bSuccess = False - sResult = "self.__sFile is None; please provide path and name of a file when creating a CFile object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - bSuccess, sResult = self.Close() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - try: - self.__oFileHandle = open(self.__sFile, "a", encoding="utf-8") - self.__oFileStatus = enFileStatiType.openedforappending - bSuccess = True - sResult = f"File '{self.__sFile}' is open for appending" - except Exception as reason: - self.Close() - bSuccess = None - sResult = f"Not possible to open file '{self.__sFile}' for appending.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def __OpenForAppending(self): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __OpenForReading(self): - """ -Opens a text file for reading. - -Returns ``bSuccess`` and ``sResult`` (feedback). - """ - - sMethod = "CFile.__OpenForReading" - - if self.__sFile is None: - bSuccess = False - sResult = "self.__sFile is None; please provide path and name of a file when creating a CFile object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - bSuccess, sResult = self.Close() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - try: - self.__oFileHandle = open(self.__sFile, "r", encoding="utf-8") - self.__oFileStatus = enFileStatiType.openedforreading - bSuccess = True - sResult = f"File '{self.__sFile}' is open for reading" - except Exception as reason: - self.Close() - bSuccess = None - sResult = f"Not possible to open file '{self.__sFile}' for reading.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def __OpenForReading(self): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def Close(self): - """ -Closes the opened file. - -**Arguments:** - -(no args) - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - sMethod = "CFile.Close" - - if self.__oFileHandle is not None: - try: - self.__oFileHandle.flush() - self.__oFileHandle.close() - bSuccess = True - sResult = f"File '{self.__sFile}' closed" - except Exception as reason: - bSuccess = None - sResult = f"Exception while closing file '{self.__sFile}'.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - self.__oFileHandle = None - else: - bSuccess = True - sResult = "Done" - - self.__oFileStatus = enFileStatiType.closed - - return bSuccess, sResult - - # eof def Close(self): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def Delete(self, bConfirmDelete=True): - """ -Deletes the current file. - -**Arguments:** - -* ``bConfirmDelete`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - Defines if it will be handled as error if the file does not exist. - - If ``True``: If the file does not exist, the method indicates an error (``bSuccess = False``). - - If ``False``: It doesn't matter if the file exists or not. - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - - sMethod = "CFile.Delete" - - if self.__sFile is None: - bSuccess = False - sResult = "self.__sFile is None; please provide path and name of a file when creating a CFile object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if os.path.isfile(self.__sFile) is False: - if bConfirmDelete is True: - bSuccess = False - else: - bSuccess = True - sResult = f"Nothing to delete. The file '{self.__sFile}' does not exist." - return bSuccess, sResult - - bSuccess, sResult = self.Close() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - try: - os.remove(self.__sFile) - bSuccess = True - sResult = f"File '{self.__sFile}' deleted." - except Exception as reason: - bSuccess = None - sResult = f"Exception while deleting file '{self.__sFile}'.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def Delete(self, bConfirmDelete=True): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __PrepareOutput(self, Content=""): - """ -Helper for ``Write`` and ``Append`` (consideration of composite data types). - -Returns a list of strings (that will be written to file). - """ - - listOut = [] - - if type(Content) == list: - for element in Content: - listOut.append(str(element)) - elif type(Content) == tuple: - for element in Content: - listOut.append(str(element)) - elif type(Content) == set: - for element in Content: - listOut.append(str(element)) - elif type(Content) == dict: - listKeys = Content.keys() - nRJust = 0 - for key in listKeys: - sKey = str(key) # because also numerical values can be keys - if len(sKey) > nRJust: - nRJust = len(sKey) - for key in listKeys: - sKey = str(key) # because also numerical values can be keys - sOut = sKey.rjust(nRJust, ' ') + " : " + str(Content[key]) - listOut.append(sOut) - elif str(type(Content)).lower().find('dotdict') >=0: - try: - listKeys = Content.keys() - nRJust = 0 - for key in listKeys: - sKey = str(key) # because also numerical values can be keys - if len(sKey) > nRJust: - nRJust = len(sKey) - for key in listKeys: - sKey = str(key) # because also numerical values can be keys - sOut = sKey.rjust(nRJust, ' ') + " : " + str(Content[key]) - listOut.append(sOut) - except Exception as reason: - listOut.append(str(Content)) - else: - listOut.append(str(Content)) - - return listOut - - # eof def __PrepareOutput(self, Content=""): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def Write(self, Content="", nVSpaceAfter=0, sPrefix=None, bToScreen=False): - """ -Writes the content of a variable ``Content`` to file. - -**Arguments:** - -* ``Content`` - - / *Condition*: required / *Type*: one of: str, list, tuple, set, dict, dotdict / - - If ``Content`` is not a string, the ``Write`` method resolves the data structure before writing the content to file. - -* ``nVSpaceAfter`` - - / *Condition*: optional / *Type*: int / *Default*: 0 / - - Adds vertical space ``nVSpaceAfter`` (= number of blank lines) after ``Content``. - -* ``sPrefix`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - `sPrefix`` is added to every line of output (in case of ``sPrefix`` is not ``None``). - -* ``bToScreen`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - Prints ``Content`` also to screen (in case of ``bToScreen`` is ``True``). - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - - sMethod = "CFile.Write" - - if self.__oFileStatus != enFileStatiType.openedforwriting: - bSuccess, sResult = self.__OpenForWriting() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - listOut = self.__PrepareOutput(Content) - - for nCnt in range(nVSpaceAfter): - listOut.append("") - - if bToScreen is True: - for sOut in listOut: - if ( (sPrefix is not None) and (sOut != '') ): - sOut = f"{sPrefix}{sOut}" - print(sOut) - - bSuccess = True - sResult = "Done" - try: - for sOut in listOut: - if ( (sPrefix is not None) and (sOut != '') ): - sOut = f"{sPrefix}{sOut}" - self.__oFileHandle.write(sOut + "\n") - except Exception as reason: - bSuccess = None - sResult = f"Not possible to write to file '{self.__sFile}'.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def Write(self, Content="", nVSpaceAfter=0, sPrefix=None, bToScreen=False): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def Append(self, Content="", nVSpaceAfter=0, sPrefix=None, bToScreen=False): - """ -Appends the content of a variable ``Content`` to file. - -**Arguments:** - -* ``Content`` - - / *Condition*: required / *Type*: one of: str, list, tuple, set, dict, dotdict / - - If ``Content`` is not a string, the ``Write`` method resolves the data structure before writing the content to file. - -* ``nVSpaceAfter`` - - / *Condition*: optional / *Type*: int / *Default*: 0 / - - Adds vertical space ``nVSpaceAfter`` (= number of blank lines) after ``Content``. - -* ``sPrefix`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - `sPrefix`` is added to every line of output (in case of ``sPrefix`` is not ``None``). - -* ``bToScreen`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - Prints ``Content`` also to screen (in case of ``bToScreen`` is ``True``). - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - sMethod = "CFile.Append" - - if self.__oFileStatus != enFileStatiType.openedforappending: - bSuccess, sResult = self.__OpenForAppending() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - listOut = self.__PrepareOutput(Content) - - for nCnt in range(nVSpaceAfter): - listOut.append("") - - if bToScreen is True: - for sOut in listOut: - if ( (sPrefix is not None) and (sOut != '') ): - sOut = f"{sPrefix}{sOut}" - print(sOut) - - bSuccess = True - sResult = "Done" - try: - for sOut in listOut: - if ( (sPrefix is not None) and (sOut != '') ): - sOut = f"{sPrefix}{sOut}" - self.__oFileHandle.write(sOut + "\n") - except Exception as reason: - bSuccess = None - sResult = f"Not possible to append to file '{self.__sFile}'.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def Append(self, Content="", nVSpaceAfter=0, sPrefix=None, bToScreen=False): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def ReadLines(self, - bCaseSensitive = True, - bSkipBlankLines = False, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = None, - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None, - bLStrip = False, - bRStrip = True, - bToScreen = False): - """ -Reads content from current file. Returns an array of lines together with ``bSuccess`` and ``sResult`` (feedback). - -The method takes care of opening and closing the file. The complete file content is read by ``ReadLines`` in one step, -but with the help of further parameters it is possible to reduce the content by including and excluding lines. - -The logical join of all filter is: ``AND``. - -**Arguments:** - -* ``bCaseSensitive`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - * If ``True``, the standard filters work case sensitive, otherwise not. - * This has no effect to the regular expression based filters ``sInclRegEx`` and ``sExclRegEx``. - -* ``bSkipBlankLines`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True``, blank lines will be skipped, otherwise not. - -* ``sComment`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - In case of a line starts with the string ``sComment``, this line is skipped. - -* ``sStartsWith`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * The criterion of this filter is fulfilled in case of the input string starts with the string ``sStartsWith`` - * More than one string can be provided (semicolon separated; logical join: ``OR``) - -* ``sEndsWith`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * The criterion of this filter is fulfilled in case of the input string ends with the string ``sEndsWith`` - * More than one string can be provided (semicolon separated; logical join: ``OR``) - -* ``sStartsNotWith`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * The criterion of this filter is fulfilled in case of the input string starts not with the string ``sStartsNotWith`` - * More than one string can be provided (semicolon separated; logical join: ``AND``) - -* ``sEndsNotWith`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * The criterion of this filter is fulfilled in case of the input string ends not with the string ``sEndsNotWith`` - * More than one string can be provided (semicolon separated; logical join: ``AND``) - -* ``sContains`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * The criterion of this filter is fulfilled in case of the input string contains the string ``sContains`` at any position - * More than one string can be provided (semicolon separated; logical join: ``OR``) - -* ``sContainsNot`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * The criterion of this filter is fulfilled in case of the input string does **not** contain the string ``sContainsNot`` at any position - * More than one string can be provided (semicolon separated; logical join: ``AND``) - -* ``sInclRegEx`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * *Include* filter based on regular expressions (consider the syntax of regular expressions!) - * The criterion of this filter is fulfilled in case of the regular expression ``sInclRegEx`` matches the input string - * Leading and trailing blanks within the input string are considered - * ``bCaseSensitive`` has no effect - * A semicolon separated list of several regular expressions is **not** supported - -* ``sExclRegEx`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - * *Exclude* filter based on regular expressions (consider the syntax of regular expressions!) - * The criterion of this filter is fulfilled in case of the regular expression ``sExclRegEx`` does **not** match the input string - * Leading and trailing blanks within the input string are considered - * ``bCaseSensitive`` has no effect - * A semicolon separated list of several regular expressions is **not** supported - -* ``bLStrip`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True``, leading spaces are removed from line before the filters are used, otherwise not. - -* ``bRStrip`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - If ``True``, trailing spaces are removed from line before the filters are used, otherwise not. - -* ``bToScreen`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True``, the content read from file is also printed to screen, otherwise not. - """ - - sMethod = "CFile.ReadLines" - - listLines = [] - - if os.path.isfile(self.__sFile) is False: - bSuccess = False - sResult = f"The file '{self.__sFile}' does not exist." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return listLines, bSuccess, sResult - - # !!! independend from: self.__oFileStatus != enFileStatiType.openedforreading: !!! - # Reason: Repeated call of ReadLines needs to have the read pointer at the beginning of the file. - bSuccess, sResult = self.__OpenForReading() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return listLines, bSuccess, sResult - - try: - sFileContent = self.__oFileHandle.read() - except Exception as reason: - bSuccess = None - sResult = f"Not possible to read from file '{self.__sFile}'.\nReason: " + str(reason) - return listLines, bSuccess, sResult - - bSuccess, sResult = self.Close() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return listLines, bSuccess, sResult - - listFileContent = sFileContent.splitlines() # in opposite to readlines this is OS independend! - - for sLine in listFileContent: - if CString.StringFilter(sString = sLine, - bCaseSensitive = bCaseSensitive, - bSkipBlankStrings = bSkipBlankLines, - sComment = sComment, - sStartsWith = sStartsWith, - sEndsWith = sEndsWith, - sStartsNotWith = sStartsNotWith, - sEndsNotWith = sEndsNotWith, - sContains = sContains, - sContainsNot = sContainsNot, - sInclRegEx = sInclRegEx, - sExclRegEx = sExclRegEx, - bDebug = False) is True: - if bLStrip is True: - sLine = sLine.lstrip(" \t\r\n") - - if bRStrip is True: - sLine = sLine.rstrip(" \t\r\n") - - if bToScreen is True: - print(sLine) - - listLines.append(sLine) - - # eof for sLine in listFileContent: - - del listFileContent - - nNrOfLines = len(listLines) - - bSuccess = True - sResult = f"Read {nNrOfLines} lines from '{self.__sFile}'." - return listLines, bSuccess, sResult - - # eof def ReadLines(...) - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def GetFileInfo(self): - """ -Returns the following informations about the file (encapsulated within a dictionary ``dFileInfo``): - -**Returns:** - -* Key ``sFile`` - - / *Type*: str / - - Path and name of current file - - -* Key ``bFileIsExisting`` - - / *Type*: bool / - - ``True`` if file is existing, otherwise ``False`` - -* Key ``sFileName`` - - / *Type*: str / - - The name of the current file (incl. extension) - -* Key ``sFileExtension`` - - / *Type*: str / - - The extension of the current file - -* Key ``sFileNameOnly`` - - / *Type*: str / - - The pure name of the current file (without extension) - -* Key ``sFilePath`` - - / *Type*: str / - - The the path to current file - -* Key ``bFilePathIsExisting`` - - / *Type*: bool / - - ``True`` if file path is existing, otherwise ``False`` - """ - - sMethod = "CFile.GetFileInfo" - - dFileInfo = {} - dFileInfo['sFile'] = None - dFileInfo['bFileIsExisting'] = None - dFileInfo['sFileName'] = None - dFileInfo['sFileExtension'] = None - dFileInfo['sFileNameOnly'] = None - dFileInfo['sFilePath'] = None - dFileInfo['bFilePathIsExisting'] = None - - if self.__sFile is None: - return None - - dFileInfo['sFile'] = self.__sFile - dFileInfo['bFileIsExisting'] = os.path.isfile(self.__sFile) - - sFileName = os.path.basename(self.__sFile) - dFileInfo['sFileName'] = sFileName - - sFileExtension = "" - sFileNameOnly = "" - listParts = sFileName.split('.') - if len(listParts) > 1: - sFileExtension = listParts[len(listParts)-1] - sFileNameOnly = sFileName[:-len(sFileExtension)-1] - else: - sFileExtension = "" - sFileNameOnly = sFileName - - dFileInfo['sFileExtension'] = sFileExtension - dFileInfo['sFileNameOnly'] = sFileNameOnly - dFileInfo['sFilePath'] = os.path.dirname(self.__sFile) - dFileInfo['bFilePathIsExisting'] = os.path.isdir(dFileInfo['sFilePath']) - - return dFileInfo - - # eof def GetFileInfo(self): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def CopyTo(self, sDestination=None, bOverwrite=False): - """ -Copies the current file to ``sDestination``, that can either be a path without file name or a path together with a file name. - -In case of the destination file already exists and ``bOverwrite`` is ``True``, than the destination file will be overwritten. - -In case of the destination file already exists and ``bOverwrite`` is ``False`` (default), than the destination file will not be overwritten -and ``CopyTo`` returns ``bSuccess = False``. - -**Arguments:** - -* ``sDestination`` - - / *Condition*: required / *Type*: string / - - The path to destination file (either incl. file name or without file name) - -* ``bOverwrite`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - * In case of the destination file already exists and ``bOverwrite`` is ``True``, than the destination file will be overwritten. - * In case of the destination file already exists and ``bOverwrite`` is ``False`` (default), than the destination file will not be overwritten - and ``CopyTo`` returns ``bSuccess = False``. - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - sMethod = "CFile.CopyTo" - - if self.__sFile is None: - bSuccess = False - sResult = "self.__sFile is None; please provide path and name of a file when creating a CFile object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if os.path.isfile(self.__sFile) is False: - bSuccess = False - sResult = f"The file '{self.__sFile}' does not exist, therefore nothing can be copied." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if sDestination is None: - bSuccess = False - sResult = "sDestination is None; please provide path and name of destination file. Or at least the destination path. In this case the file name will be taken over." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - sDestination = CString.NormalizePath(sDestination) - - bDeleteDestFile = False - - sDestFile = sDestination # default - - if os.path.isdir(sDestination) is True: - sFileName = os.path.basename(self.__sFile) - sDestFile = f"{sDestination}/{sFileName}" # file name in destination is required for: shutil.copyfile - - if self.__bIsFreeToUse(sDestFile) is False: - bSuccess = False - sResult = f"The destination file '{sDestFile}' is already in use by another CFile instance." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - self.__sLastDestination = sDestFile - - if os.path.isfile(sDestFile) is True: - # destination file already exists - if sDestFile == self.__sFile: - bSuccess = False - sResult = f"Source file and destination file are the same: '{self.__sFile}'. Therefore nothing to do." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if bOverwrite is True: - bDeleteDestFile = True - else: - bSuccess = False - sResult = f"Not allowed to overwrite existing destination file '{sDestFile}'. Therefore nothing to do." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - else: - # destination file not yet exists - # (we assume here that the destination shall be a file because we already have figured out that the destination is not a folder) - # => we have to check if the path to the file exists - sDestFilePath = os.path.dirname(sDestFile) - if os.path.isdir(sDestFilePath) is True: - bDeleteDestFile = False - else: - bSuccess = False - sResult = f"The destination path '{sDestFilePath}' does not exist. The file '{self.__sFile}' cannot be copied." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - # eof else - if os.path.isfile(sDestFile) is True: - - # analysis done, now the action - - bSuccess, sResult = self.Close() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if bDeleteDestFile is True: - # To delete the destination file explicitely before executing any copy-function is an addon here in this library. - # The purpose is to be independend from the way the used copy function is handling existing destination files. - # But this makes only sense under Windows and not under Linux, because Windows is much more strict with access - # violations than Linux. Therefore we avoid such kind of additional steps in case of the platform is not Windows. - if platform.system() == "Windows": - try: - os.remove(sDestFile) - bSuccess = True - sResult = f"File '{sDestFile}' deleted." - except Exception as reason: - bSuccess = None - sResult = f"Exception while deleting destination file '{sDestFile}'.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - # eof if bDeleteDestFile is True: - - try: - shutil.copyfile(self.__sFile, sDestFile) - bSuccess = True - sResult = f"File '{self.__sFile}' copied to '{sDestFile}'." - except Exception as reason: - bSuccess = None - sResult = f"Exception while copying file '{self.__sFile}' to '{sDestFile}'.\nReason: " + str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def CopyTo(self, sDestination=None, bOverwrite=False): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def MoveTo(self, sDestination=None, bOverwrite=False): - """ -Moves the current file to ``sDestination``, that can either be a path without file name or a path together with a file name. - -**Arguments:** - -* ``sDestination`` - - / *Condition*: required / *Type*: string / - - The path to destination file (either incl. file name or without file name) - -* ``bOverwrite`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - * In case of the destination file already exists and ``bOverwrite`` is ``True``, than the destination file will be overwritten. - * In case of the destination file already exists and ``bOverwrite`` is ``False`` (default), than the destination file will not be overwritten - and ``MoveTo`` returns ``bSuccess = False``. - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation was successful or not - -* ``sResult`` - - / *Type*: str / - - Contains details about what happens during computation - """ - sMethod = "CFile.MoveTo" - - bSuccess, sResult = self.CopyTo(sDestination, bOverwrite) - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if os.path.isfile(self.__sLastDestination) is False: - # the copied file should exist at new location - bSuccess = None - sResult = f"Someting went wrong while copying the file '{self.__sFile}' to '{self.__sLastDestination}'. Aborting." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - else: - bSuccess, sResult = self.Delete() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - bSuccess = True - sResult = f"File moved from '{self.__sFile}' to '{self.__sLastDestination}'" - return bSuccess, sResult - - # eof def MoveTo(self, sDestination=None, bOverwrite=False): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - -# eof class CFile(object): - -# ************************************************************************************************************** - - diff --git a/additions/PythonExtensionsCollection/File/__init__.py b/additions/PythonExtensionsCollection/File/__init__.py deleted file mode 100644 index 958420af..00000000 --- a/additions/PythonExtensionsCollection/File/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/additions/PythonExtensionsCollection/Folder/CFolder.py b/additions/PythonExtensionsCollection/Folder/CFolder.py deleted file mode 100644 index 451c32f9..00000000 --- a/additions/PythonExtensionsCollection/Folder/CFolder.py +++ /dev/null @@ -1,460 +0,0 @@ -# ************************************************************************************************************** -# -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ************************************************************************************************************** -# -# CFolder.py -# -# XC-CT/ECA3-Queckenstedt -# -# 28.06.2022 -# -# ************************************************************************************************************** - -# -- import standard Python modules -import os, shutil, time, stat - -# -- import Bosch Python modules -from PythonExtensionsCollection.String.CString import CString - -# -------------------------------------------------------------------------------------------------------------- - -# little helper to delete folders containing files that are write protected -def rm_dir_readonly(func, path, excinfo): - """ -Calls ``os.chmod`` in case of ``shutil.rmtree`` (within ``Delete()``) throws an exception (making files writable). - """ - # print(f"{excinfo}") # debug only - os.chmod(path, stat.S_IWRITE) - func(path) - -# -------------------------------------------------------------------------------------------------------------- - -class CFolder(object): - """ -The class ``CFolder`` provides a small set of folder functions with extended parametrization (like switches -defining if a folder is allowed to be overwritten or not). - -Most of the functions at least returns ``bSuccess`` and ``sResult``. - -* ``bSuccess`` is ``True`` in case of no error occurred. -* ``bSuccess`` is ``False`` in case of an error occurred. -* ``bSuccess`` is ``None`` in case of a very fatal error occurred (exceptions). - -* ``sResult`` contains details about what happens during computation. - -Every instance of CFolder handles one single folder only and forces exclusive access to this folder. - -It is not possible to create an instance of this class with a folder that is already in use by another instance. - -The constructor of ``CFolder`` requires the input parameter ``sFolder``, that is the path and the name of a folder -that is handled by the current class instance. - """ - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __init__(self, sFolder=None): - self.__sFolder = CString.NormalizePath(sFolder) - - try: - CFolder.__listFoldersInUse - except: - CFolder.__listFoldersInUse = [] - - # exclusive access is required (checked by self.__bIsFreeToUse; relevant for destination in CopyTo and MoveTo) - if self.__sFolder in CFolder.__listFoldersInUse: - raise Exception(f"The folder '{self.__sFolder}' is already in use by another CFolder instance.") - else: - CFolder.__listFoldersInUse.append(self.__sFolder) - - # eof def __init__(self, sFolder=None): - - def __del__(self): - if self.__sFolder in CFolder.__listFoldersInUse: - CFolder.__listFoldersInUse.remove(self.__sFolder) - - # eof def __del__(self): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __bIsFreeToUse(self, sFolder=None): - """ -Checks if the folder ``sFolder`` is free to use, that means: not used by another instance of ``CFolder``. - """ - - bIsFreeToUse = False # init - if sFolder is None: - bIsFreeToUse = False # error handling - else: - if sFolder in CFolder.__listFoldersInUse: - bIsFreeToUse = False - else: - bIsFreeToUse = True - return bIsFreeToUse - - # eof def __bIsFreeToUse(self, sFolder=None): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def __Delete(self, sFolder=None, bConfirmDelete=True): - """ -Deletes the folder ``sFolder``. - -**Arguments:** - -* ``sFolder`` - - / *Condition*: required / *Type*: str / - - Path and name of folder to be deleted - -* ``bConfirmDelete`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - Defines if it will be handled as error if the folder does not exist. - - If ``True``: If the folder does not exist, the method indicates an error (``bSuccess = False``). - - If ``False``: It doesn't matter if the folder exists or not. - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - sMethod = "CFolder.__Delete" - - if sFolder is None: - bSuccess = False - sResult = "sFolder is None; please provide path and name of a folder when creating a CFolder object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if os.path.isdir(sFolder) is False: - sResult = f"Nothing to delete. The folder '{sFolder}' does not exist." - if bConfirmDelete is True: - bSuccess = False - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - else: - bSuccess = True - return bSuccess, sResult - # eof if os.path.isdir(sFolder) is False: - - bSuccess = False - sResult = "UNKNOWN" - nCntTries = 1 - nTriesMax = 4 - nDelay = 2 # sec - listResults = [] - while nCntTries <= nTriesMax: - try: - print(f"Trying to delete '{sFolder}'") - print() - shutil.rmtree(sFolder, ignore_errors=False, onerror=rm_dir_readonly) - except Exception as reason: - listResults.append(str(reason)) - if os.path.isdir(sFolder) is True: - sResult = f"({nCntTries}/{nTriesMax}) Problem with deleting the folder '{sFolder}'. Folder still present." - listResults.append(sResult) - time.sleep(nDelay) # delay before next try - else: - bSuccess = True - sResult = f"Folder '{sFolder}' deleted." - break - nCntTries = nCntTries + 1 - # eof while nCntTries <= nTriesMax: - - if bSuccess is False: - sResult = "\n".join(listResults) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def __Delete(self, sFolder=None, bConfirmDelete=True): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def Delete(self, bConfirmDelete=True): - """ -Deletes the folder the current class instance contains. - -**Arguments:** - -* ``bConfirmDelete`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - Defines if it will be handled as error if the folder does not exist. - - If ``True``: If the folder does not exist, the method indicates an error (``bSuccess = False``). - - If ``False``: It doesn't matter if the folder exists or not. - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - sMethod = "CFolder.Delete" - bSuccess, sResult = self.__Delete(self.__sFolder, bConfirmDelete) - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - # eof def Delete(self, bConfirmDelete=True): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def Create(self, bOverwrite=False, bRecursive=False): - """ -Creates the current folder ``sFolder``. - -**Arguments:** - -* ``bOverwrite`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - * In case of the folder already exists and ``bOverwrite`` is ``True``, than the folder will be deleted before creation. - * In case of the folder already exists and ``bOverwrite`` is ``False`` (default), than the folder will not be touched. - - In both cases the return value ``bSuccess`` is ``True`` - because the folder exists. - -* ``bRecursive`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - * In case of ``bRecursive`` is ``True``, than the complete destination path will be created (including all intermediate subfolders). - * In case of ``bRecursive`` is ``False``, than it is expected that the parent folder of the new folder already exists. - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - sMethod = "CFolder.Create" - - if self.__sFolder is None: - bSuccess = False - sResult = "self.__sFolder is None; please provide path and name of a folder when creating a CFolder object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - bCreateFolder = False - if os.path.isdir(self.__sFolder) is True: - if bOverwrite is True: - bSuccess, sResult = self.Delete() - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - bCreateFolder = True - else: - bSuccess = True - sResult = f"Folder '{self.__sFolder}' already exists." - return bSuccess, sResult - else: - bCreateFolder = True - - bSuccess = False - sResult = "UNKNOWN" - - if bCreateFolder is True: - nCntTries = 1 - nTriesMax = 3 - nDelay = 2 # sec - listResults = [] - while nCntTries <= nTriesMax: - try: - print(f"Trying to create '{self.__sFolder}'") - print() - if bRecursive is True: - os.makedirs(self.__sFolder) - else: - os.mkdir(self.__sFolder) - except Exception as reason: - listResults.append(str(reason)) - if os.path.isdir(self.__sFolder) is False: - sResult = f"({nCntTries}/{nTriesMax}) Problem with creating the folder '{self.__sFolder}'." - listResults.append(sResult) - time.sleep(nDelay) # delay before next try - else: - bSuccess = True - sResult = f"Folder '{self.__sFolder}' created." - break - nCntTries = nCntTries + 1 - # eof while nCntTries <= nTriesMax: - - if bSuccess is False: - sResult = "\n".join(listResults) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - # eof if bCreateFolder is True: - - return bSuccess, sResult - - # eof def Create(self, bOverwrite=False, bRecursive=False): - - # -------------------------------------------------------------------------------------------------------------- - # TM*** - - def CopyTo(self, sDestination=None, bOverwrite=False): - """ -Copies the current folder to ``sDestination``, that has to be a path to a folder **within** the source folder will be copied to -(with it's original name), - -In case of the destination folder already exists and ``bOverwrite`` is ``True``, than the destination folder will be overwritten. - -In case of the destination folder already exists and ``bOverwrite`` is ``False`` (default), than the destination folder will not be overwritten -and ``CopyTo`` returns ``bSuccess = False``. - -**Arguments:** - -* ``sDestination`` - - / *Condition*: required / *Type*: string / - - The path to destination folder - -* ``bOverwrite`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - * In case of the destination folder already exists and ``bOverwrite`` is ``True``, than the destination folder will be overwritten. - * In case of the destination folder already exists and ``bOverwrite`` is ``False`` (default), than the destination folder will not be overwritten - and ``CopyTo`` returns ``bSuccess = False``. - -**Returns:** - -* ``bSuccess`` - - / *Type*: bool / - - Indicates if the computation of the method was successful or not. - -* ``sResult`` - - / *Type*: str / - - The result of the computation of the method. - """ - sMethod = "CFolder.CopyTo" - - if self.__sFolder is None: - bSuccess = False - sResult = "self.__sFolder is None; please provide path and name of a folder when creating a CFolder object." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if os.path.isdir(self.__sFolder) is False: - bSuccess = False - sResult = f"The folder '{self.__sFolder}' does not exist, therefore nothing can be copied." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if sDestination is None: - bSuccess = False - sResult = "sDestination is None; please provide a path to a destination folder." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - sDestination = CString.NormalizePath(sDestination) - - if os.path.isdir(sDestination) is False: - # the folder to be copied will be created within the destination folder, therefore we expect that the destination folder already exists - bSuccess = False - sResult = f"The destination folder '{sDestination}' does not exist." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - sSourceFolderName = os.path.basename(self.__sFolder) - sDestFolder = f"{sDestination}/{sSourceFolderName}" - - if sDestFolder == self.__sFolder: - bSuccess = False - sResult = f"Source folder and destination folder are the same: '{self.__sFolder}'. Therefore nothing to do." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if self.__bIsFreeToUse(sDestFolder) is False: - bSuccess = False - sResult = f"The destination folder '{sDestFolder}' is already in use by another CFolder instance." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - - if os.path.isdir(sDestFolder) is True: - # destination folder already exists - if bOverwrite is True: - bSuccess, sResult = self.__Delete(sDestFolder) - if bSuccess is not True: - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - else: - bSuccess = False - sResult = f"Not allowed to overwrite existing destination folder '{sDestFolder}'. Therefore nothing to do." - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - return bSuccess, sResult - # eof if os.path.isdir(sDestFolder) is True: - - # analysis and preconditions done, now the action - - try: - shutil.copytree(self.__sFolder, sDestFolder) - bSuccess = True - sResult = "Folder copied from\n> '" + self.__sFolder + "'\nto\n> '" + sDestFolder + "'" - except Exception as reason: - bSuccess = None - sResult = str(reason) - sResult = CString.FormatResult(sMethod, bSuccess, sResult) - - return bSuccess, sResult - - # eof def CopyTo(self, sDestination=None, bOverwrite=False): - -# -------------------------------------------------------------------------------------------------------------- - - diff --git a/additions/PythonExtensionsCollection/Folder/__init__.py b/additions/PythonExtensionsCollection/Folder/__init__.py deleted file mode 100644 index 958420af..00000000 --- a/additions/PythonExtensionsCollection/Folder/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/additions/PythonExtensionsCollection/String/CString.py b/additions/PythonExtensionsCollection/String/CString.py deleted file mode 100644 index 82aeb204..00000000 --- a/additions/PythonExtensionsCollection/String/CString.py +++ /dev/null @@ -1,1165 +0,0 @@ -# ************************************************************************************************************** -# -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ************************************************************************************************************** -# -# CString.py -# -# XC-CT/ECA3-Queckenstedt -# -# 02.06.2022 -# -# ************************************************************************************************************** - -# -- import standard Python modules -import os, ntpath, re - -# ************************************************************************************************************** - -class CString(object): - """ -The class ``CString`` contains some string computation methods like e.g. normalizing a path. - """ - - # -------------------------------------------------------------------------------------------------------------- - #TM*** - - def NormalizePath(sPath=None, bWin=False, sReferencePathAbs=None, bConsiderBlanks=False, bExpandEnvVars=True, bMask=True): - """ -Normalizes local paths, paths to local network resources and internet addresses - -**Arguments:** - -* ``sPath`` - - / *Condition*: required / *Type*: str / - - The path to be normalized - -* ``bWin`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True`` then returned path contains masked backslashes as separator, otherwise slashes - -* ``sReferencePathAbs`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - In case of ``sPath`` is relative and ``sReferencePathAbs`` (expected to be absolute) is given, then - the returned absolute path is a join of both input paths - -* ``bConsiderBlanks`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True`` then the returned path is encapsulated in quotes - in case of the path contains blanks - -* ``bExpandEnvVars`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - If ``True`` then in the returned path environment variables are resolved, otherwise not. - -* ``bMask`` - - / *Condition*: optional / *Type*: bool / *Default*: True (requires ``bWin=True``)/ - - * If ``bWin`` is ``True`` and ``bMask`` is ``True`` then the returned path contains masked backslashes as separator. - * If ``bWin`` is ``True`` and ``bMask`` is ``False`` then the returned path contains single backslashes only - this might be - required for applications, that are not able to handle masked backslashes. - * In case of ``bWin`` is ``False`` ``bMask`` has no effect. - -**Returns:** - -* ``sPath`` - - / *Type*: str / - - The normalized path (is ``None`` in case of ``sPath`` is ``None``) - """ - - if sPath is not None: - - # -- expand Windows environment variables - if bExpandEnvVars is True: - sPath = os.path.expandvars(sPath) - - # - remove leading and trailing horizontal space - sPath = sPath.strip(" \t\r\n") - - # - remove leading and trailing quotes - sPath = sPath.strip("\"'") - - # - remove once more leading and trailing horizontal space - # (after the removal of leading and trailing quotes further horizontal space might be there, that has to be removed; - # but further levels of nesting are not considered) - sPath = sPath.strip(" \t") - - if sPath == "": - return sPath - - # - remove trailing slash or backslash (maybe at end of path to folder) - sPath = sPath.rstrip("/\\") - - # -------------------------------------------------------------------------------------------------------------- - # consider internet addresses and local network resources - # -------------------------------------------------------------------------------------------------------------- - # -- local network resource / file server - # (prepare for Windows explorer) - # either (default) - # //server.com/abc/xyz - # or (with bWin=True); bMask must be False because \\server.com\\abc\\xyz is not allowed - # \\server.com\abc\xyz - # (=> user is allowed to select bWin but not bMask) - # - # -- local network resource / file server - # (prepare for web browser) - # after 'file://///' only single slashes allowed; bWin and bMask must be False - # file://///server.com/abc/xyz - # (=> user is NOT allowed to select bWin and bMask) - # - # -- internet address - # after server name only single slashes allowed; bWin and bMask must be False - # http://server.com/abc/xyz - # https://server.com/abc/xyz - # (=> user is NOT allowed to select bWin and bMask) - # - # - not allowed (=> this method must not return this format): - # http:\\server.com - # https:\\server.com - # -------------------------------------------------------------------------------------------------------------- - - sPathPrefix = None - - # In case there is any prefix, we remove this prefix, we compute the remaining part of the path separately, - # we also modify this prefix manually, and at the end we put the new prefix back to the path. - - if ( (sPath[:2] == "\\\\") or (sPath[:2] == "//") ): - sPath = sPath[2:] - if bWin is True: - sPathPrefix = "\\\\" - else: - sPathPrefix = "//" - bMask = False # !!! this overrules the input parameter value, because masked backslashes are not allowed in remaining path !!! - elif sPath[:10] == "file://///": # exactly this must be given; all other combinations of slashes and backslashes are not handled - sPath = sPath[10:] - sPathPrefix = "file://///" - bWin = False # !!! this overrules the input parameter value, because only single slashes allowed in remaining path !!! - bMask = False # !!! this overrules the input parameter value, because only single slashes allowed in remaining path !!! - elif ( (sPath[:7] == "http://") or (sPath[:7] == "http:\\\\") ): - sPath = sPath[7:] - sPathPrefix = "http://" - bWin = False # !!! this overrules the input parameter value, because only single slashes allowed in remaining path !!! - bMask = False # !!! this overrules the input parameter value, because only single slashes allowed in remaining path !!! - elif ( (sPath[:8] == "https://") or (sPath[:8] == "https:\\\\") ): - sPath = sPath[8:] - sPathPrefix = "https://" - bWin = False # !!! this overrules the input parameter value, because only single slashes allowed in remaining path !!! - bMask = False # !!! this overrules the input parameter value, because only single slashes allowed in remaining path !!! - else: - # Internet addresses and local network resources handled, now checking for relative paths: - # In case of sPath is a relative path AND an absolute reference path is provided - # merge them to an absolute path; without reference path use standard function to - # convert relative path to absolute path - if ( (sPath[0] != "%") and (sPath[0] != "$") ): - # If sPath starts with '%' or with '$' it is assumed that the path starts with an environment variable (Windows or Linux). - # But in this case 'os.path.isabs(sPath)' will not detect this to be an absolute path and will call - # 'sPath = os.path.abspath(sPath)' (depending on sReferencePathAbs). This will accidently merge - # the root path together with the path starting with the environment variable and cause invalid results. - if os.path.isabs(sPath) is False: - if sReferencePathAbs is not None: - sPath = os.path.join(sReferencePathAbs, sPath) - else: - sPath = os.path.abspath(sPath) - - # eof computation of sPathPrefix - - # - normalize the path (collapse redundant separators and up-level references) - # on Windows this converts slashes to backward slashes - # sPath = os.path.normpath(sPath) # under Linux this unfortunately keeps redundant separators (in opposite to Windows) - # -- alternative - sPath = ntpath.normpath(sPath) - - # - exchange single backslashes by single slashes (= partly we have to repair the outcome of normpath) - if bWin is False: - sPath = sPath.replace("\\", "/") - else: - if bMask is True: - sPath = sPath.replace("\\", "\\\\") - - # - restore the path prefix - if sPathPrefix is not None: - sPath = f"{sPathPrefix}{sPath}" - - # - consider blanks (prepare path for usage in Windows command line) - if bConsiderBlanks is True: - if sPath.find(" ") >= 0: - sPath = f"\"{sPath}\"" - - # eof if sPath is not None: - - return sPath - - # eof NormalizePath(sPath=None, bWin=False, sReferencePathAbs=None, bConsiderBlanks=False, bExpandEnvVars=True, bMask=True) - - # -------------------------------------------------------------------------------------------------------------- - #TM*** - - def DetectParentPath(sStartPath=None, sFolderName=None, sFileName=None): - """ -Computes the path to any parent folder inside a given path. Optionally DetectParentPath is able -to search for files inside the parent folder. - -**Arguments:** - -* ``sStartPath`` - - / *Condition*: required / *Type*: str / - - The path in which to search for a parent folder - -* ``sFolderName`` - - / *Condition*: required / *Type*: str / - - The name of the folder to search for within ``sStartPath``. It is possible to provide more than one folder name separated by semicolon - -* ``sFileName`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - The name of a file to search within the detected parent folder - -**Returns:** - -* ``sDestPath`` - - / *Type*: str / - - Path and name of parent folder found inside ``sStartPath``, ``None`` in case of ``sFolderName`` is not found inside ``sStartPath``. - In case of more than one parent folder is found ``sDestPath`` contains the first result and ``listDestPaths`` contains all results. - -* ``listDestPaths`` - - / *Type*: list / - - If ``sFolderName`` contains a single folder name this list contains only one element that is ``sDestPath``. - In case of ``FolderName`` contains a semicolon separated list of several folder names this list contains all found paths of the given folder names. - ``listDestPaths`` is ``None`` (and not an empty list!) in case of ``sFolderName`` is not found inside ``sStartPath``. - -* ``sDestFile`` - - / *Type*: str / - - Path and name of ``sFileName``, in case of ``sFileName`` is given and found inside ``listDestPaths``. - In case of more than one file is found ``sDestFile`` contains the first result and ``listDestFiles`` contains all results. - ``sDestFile`` is ``None`` in case of ``sFileName`` is ``None`` and also in case of ``sFileName`` is not found inside ``listDestPaths`` - (and therefore also in case of ``sFolderName`` is not found inside ``sStartPath``). - -* ``listDestFiles`` - - / *Type*: list / - - Contains all positions of ``sFileName`` found inside ``listDestPaths``. - - ``listDestFiles`` is ``None`` (and not an empty list!) in case of ``sFileName`` is ``None`` and also in case of ``sFileName`` - is not found inside ``listDestPaths`` (and therefore also in case of ``sFolderName`` is not found inside ``sStartPath``). - -* ``sDestPathParent`` - - / *Type*: str / - - The parent folder of ``sDestPath``, ``None`` in case of ``sFolderName`` is not found inside ``sStartPath`` (``sDestPath`` is ``None``). - """ - - sDestPath = None - listDestPaths = None - sDestFile = None - listDestFiles = None - sDestPathParent = None - - if sStartPath is None: - return sDestPath, listDestPaths, sDestFile, listDestFiles, sDestPathParent - - if sFolderName is None: - return sDestPath, listDestPaths, sDestFile, listDestFiles, sDestPathParent - - sStartPath = sStartPath.strip() - if sStartPath == "": - return sDestPath, listDestPaths, sDestFile, listDestFiles, sDestPathParent - - sFolderName = sFolderName.strip() - if sFolderName == "": - return sDestPath, listDestPaths, sDestFile, listDestFiles, sDestPathParent - - listSplit = sFolderName.split(';') - - listTopLevelFolders = [] - for sFolder in listSplit: - # removing duplicates - sFolder = sFolder.strip() - if sFolder != "": - if sFolder not in listTopLevelFolders: - listTopLevelFolders.append(sFolder) - # eof for sFolder in listSplit: - - nNrOfFolders = len(listTopLevelFolders) - sStartPath = CString.NormalizePath(sStartPath) - listLevels = sStartPath.split("/") - - listDestPaths = [] - - while len(listLevels) > 0: - # -- merging paths with folder names and search for existing combinations - sPathParent = "/".join(listLevels) - for sTLFolder in listTopLevelFolders: - sSubPath = sPathParent + "/" + sTLFolder - if os.path.isdir(sSubPath) is True: - listDestPaths.append(sSubPath) - if len(listTopLevelFolders) == len(listDestPaths): - # all folders found - break - else: - listLevels.pop() - # eof while len(listLevels) > 0: - - sDestPath = None - sDestPathParent = None - if len(listDestPaths) > 0: - # -- returning sDestPath and sDestPathParent related to first entry in list; just to return anything else than None - sDestPath = listDestPaths[0] - sDestPathParent = CString.NormalizePath(os.path.dirname(sDestPath)) - - # -- optionally searching also for a single file - # Input: file name - # Output: full path of file and list of full paths of files (!!! limited to 'listDestPaths' !!!) - - listDestFiles = [] - - if ( (sFileName is not None) and (len(listDestPaths) > 0) ): - for sDestPathToWalk in listDestPaths: - for sLocalRootPath, listFolderNames, listFileNames in os.walk(sDestPathToWalk): - for sFileNameTmp in listFileNames: - if sFileNameTmp == sFileName: - sFile = CString.NormalizePath(os.path.join(sLocalRootPath, sFileName)) - listDestFiles.append(sFile) - # eof for sLocalRootPath, listFolderNames, listFileNames in os.walk(sDestPathToWalk): - # eof for sDestPathToWalk in listDestPaths: - # eof if ( (sFileName is not None) and (len(listDestPaths) > 0) ): - - if len(listDestFiles) > 0: - listDestFiles.sort() - sDestFile = listDestFiles[0] # just to return anything else than None - - # -- preparing output (setting empty lists to None, to have unique criteria for results not available) - if listDestPaths is not None: - if len(listDestPaths) == 0: - listDestPaths = None - if listDestFiles is not None: - if len(listDestFiles) == 0: - listDestFiles = None - - return sDestPath, listDestPaths, sDestFile, listDestFiles, sDestPathParent - - # eof def DetectParentPath(sStartPath=None, sFolderName=None, sFileName=None): - - # -------------------------------------------------------------------------------------------------------------- - #TM*** - - def StringFilter(sString = None, - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = None, - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None, - bDebug = False): - """ -During the computation of strings there might occur the need to get to know if this string fulfils certain criteria or not. -Such a criterion can e.g. be that the string contains a certain substring. Also an inverse logic might be required: -In this case the criterion is that the string does **not** contain this substring. - -It might also be required to combine several criteria to a final conclusion if in total the criterion for a string is fulfilled or not. -For example: The string must start with the string *prefix* and must also contain either the string *substring1* or the string *substring2* -but must also **not** end with the string *suffix*. - -This method provides a bunch of predefined filters that can be used singly or combined to come to a final conclusion if the string fulfils all criteria or not. - -The filters are divided into three different types: - -1. Filters that are interpreted as raw strings (called 'standard filters'; no wild cards supported) -2. Filters that are interpreted as regular expressions (called 'regular expression based filters'; the syntax of regular expressions has to be considered) -3. Boolean switches (e.g. indicating if also an empty string is accepted or not) - -The input string might contain leading and trailing blanks and tabs. This kind of horizontal space is removed from the input string -before the standard filters start their work (except the regular expression based filters). - -The regular expression based filters consider the original input string (including the leading and trailing space). - -The outcome is that in case of the leading and trailing space shall be part of the criterion, the regular expression based filters can be used only. - -It is possible to decide if the standard filters shall work case sensitive or not. This decision has no effect on the regular expression based filters. - -The regular expression based filters always work with the original input string that is not modified in any way. - -Except the regular expression based filters it is possible to provide more than one string for every standard filter (must be a semikolon separated list in this case). -A semicolon that shall be part of the search string, has to be masked in this way: ``\;``. - -This method returns a boolean value that is ``True`` in case of all criteria are fulfilled, and ``False`` in case of some or all of them are not fulfilled. - -The default value for all filters is ``None`` (except ``bSkipBlankStrings``). In case of a filter value is ``None`` this filter has no influence on the result. - -In case of all filters are ``None`` (default) the return value is ``True`` (except the string itself is ``None`` -or the string is empty and ``bSkipBlankStrings`` is ``True``). - -In case of the string is ``None``, the return value is ``False``, because nothing concrete can be done with ``None`` strings. - -Internally every filter has his own individual acknowledge that indicates if the criterion of this filter is fulfilled or not. - -The meaning of *criterion fulfilled* of a filter is that the filter supports the final return value ``bAck`` of this method with ``True``. - -The final return value ``bAck`` of this method is a logical join (``AND``) of all individual acknowledges (except ``bSkipBlankStrings`` and ``sComment``; -in case of their criteria are **not** fulfilled, immediately ``False`` is returned). - -Summarized: - -* Filters are used to define *criteria* -* The return value of this method provides the *conclusion* - indicating if all criteria are fulfilled or not - -The following filters are available: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**bSkipBlankStrings** - - * Like already mentioned above leading and trailing spaces are removed from the input string at the beginning - * In case of the result is an empty string and ``bSkipBlankStrings`` is ``True``, the method immediately returns ``False`` - and all other filters are ignored - -**sComment** - - * In case of the input string starts with the string ``sComment``, the method immediately returns ``False`` - and all other filters are ignored - * Leading blanks within the input string have no effect - * The decision also depends on ``bCaseSensitive`` - * The idea behind this decision is: Ignore a string that is commented out - -**sStartsWith** - - * The criterion of this filter is fulfilled in case of the input string starts with the string ``sStartsWith`` - * Leading blanks within the input string have no effect - * The decision also depends on ``bCaseSensitive`` - * More than one string can be provided (semicolon separated; logical join: ``OR``) - -**sEndsWith** - - * The criterion of this filter is fulfilled in case of the input string ends with the string ``sEndsWith`` - * Trailing blanks within the input string have no effect - * The decision also depends on ``bCaseSensitive`` - * More than one string can be provided (semicolon separated; logical join: ``OR``) - -**sStartsNotWith** - - * The criterion of this filter is fulfilled in case of the input string does **not** start with the string ``sStartsNotWith`` - * Leading blanks within the input string have no effect - * The decision also depends on ``bCaseSensitive`` - * More than one string can be provided (semicolon separated; logical join: ``AND``) - -**sEndsNotWith** - - * The criterion of this filter is fulfilled in case of the input string does **not** end with the string ``sEndsNotWith`` - * Trailing blanks within the input string have no effect - * The decision also depends on ``bCaseSensitive`` - * More than one string can be provided (semicolon separated; logical join: ``AND``) - -**sContains** - - * The criterion of this filter is fulfilled in case of the input string contains the string ``sContains`` at any position - * Leading and trailing blanks within the input string have no effect - * The decision also depends on ``bCaseSensitive`` - * More than one string can be provided (semicolon separated; logical join: ``OR``) - -**sContainsNot** - - * The criterion of this filter is fulfilled in case of the input string does **not** contain the string ``sContainsNot`` at any position - * Leading and trailing blanks within the input string have no effect - * The decision also depends on ``bCaseSensitive`` - * More than one string can be provided (semicolon separated; logical join: ``AND``) - -**sInclRegEx** - - * *Include* filter based on regular expressions (consider the syntax of regular expressions!) - * The criterion of this filter is fulfilled in case of the regular expression ``sInclRegEx`` matches the input string - * Leading and trailing blanks within the input string are considered - * ``bCaseSensitive`` has no effect - * A semicolon separated list of several regular expressions is **not** supported - -**sExclRegEx** - - * *Exclude* filter based on regular expressions (consider the syntax of regular expressions!) - * The criterion of this filter is fulfilled in case of the regular expression ``sExclRegEx`` does **not** match the input string - * Leading and trailing blanks within the input string are considered - * ``bCaseSensitive`` has no effect - * A semicolon separated list of several regular expressions is **not** supported - -**Further arguments:** - -* ``sString`` - - / *Condition*: required / *Type*: str / - - The input string that has to be investigated. - -* ``bCaseSensitive`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - If ``True``, the standard filters work case sensitive, otherwise not. - -* ``bDebug`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True``, additional output is printed to console (e.g. the decision of every single filter), otherwise not. - -**Returns:** - -* ``bAck`` - - / *Type*: bool / - - Final statement about the input string ``sString`` after filter computation - -Examples: -~~~~~~~~~ - -1. Returns ``True``: - -.. code:: python - - StringFilter(sString = "Speed is 25 beats per minute", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = "Sp", - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = "beats", - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None) - -2. Returns ``False``: - -.. code:: python - - StringFilter(sString = "Speed is 25 beats per minute", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = "Sp", - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = "minute", - sContains = "beats", - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None) - -3. Returns ``True``: - -.. code:: python - - StringFilter(sString = "Speed is 25 beats per minute", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = None, - sContainsNot = "Beats", - sInclRegEx = None, - sExclRegEx = None) - -4. Returns ``True``: - -.. code:: python - - StringFilter(sString = "Speed is 25 beats per minute", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = None, - sContainsNot = None, - sInclRegEx = r"\d{2}", - sExclRegEx = None) - -5. Returns ``False``: - -.. code:: python - - StringFilter(sString = "Speed is 25 beats per minute", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = "Speed", - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = None, - sContainsNot = None, - sInclRegEx = r"\d{3}", - sExclRegEx = None) - -6. Returns ``False``: - -.. code:: python - - StringFilter(sString = "Speed is 25 beats per minute", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = "Speed", - sEndsWith = "minute", - sStartsNotWith = "speed", - sEndsNotWith = None, - sContains = "beats", - sContainsNot = None, - sInclRegEx = r"\d{2}", - sExclRegEx = r"\d{2}") - -7. Returns ``False``: - -.. code:: python - - StringFilter(sString = " ", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = None, - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None) - -8. Returns ``False``: - -.. code:: python - - StringFilter(sString = "# Speed is 25 beats per minute", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = "#", - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = "beats", - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None) - - -9. Returns ``False``: - -.. code:: python - - StringFilter(sString = " Alpha is not beta; and beta is not gamma ", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = " Alpha ", - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None) - -Because blanks around search strings (here ``" Alpha "``) are considered, whereas the blanks around the input string are removed before computation. -Therefore ``" Alpha "`` cannot be found within the (shortened) input string. - - -10. This alternative solution returns ``True``: - -.. code:: python - - StringFilter(sString = " Alpha is not beta; and beta is not gamma ", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = None, - sContainsNot = None, - sInclRegEx = r"\s{3}Alpha", - sExclRegEx = None) - - -11. Returns ``True``: - -.. code:: python - - StringFilter(sString = "Alpha is not beta; and beta is not gamma", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = "beta; and", - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None) - -The meaning of ``"beta; and"`` is: The criterion is fulfilled in case of either ``"beta"`` or ``" and"`` can be found. That's ``True`` in this example - but this -has nothing to do with the fact, that also this string ``"beta; and"`` can be found. Here the semikolon is a separator character and therefore part of the syntax. - -A semicolon that shall be part of the search string, has to be masked with '``\;``'! - -The meaning of ``"beta\; not"`` in the following example is: The criterion is fulfilled in case of ``"beta; not"`` can be found. - -That's **not** ``True``. Therefore the method returns ``False``: - -.. code:: python - - StringFilter(sString = "Alpha is not beta; and beta is not gamma", - bCaseSensitive = True, - bSkipBlankStrings = True, - sComment = None, - sStartsWith = None, - sEndsWith = None, - sStartsNotWith = None, - sEndsNotWith = None, - sContains = r"beta\; not", - sContainsNot = None, - sInclRegEx = None, - sExclRegEx = None) - """ - - if sString is None: - return False # hard coded here; no separate filter for that decision - - # The original string 'sString' is used by regular expression filters sInclRegEx and sExclRegEx. - # The stripped string 'sStringStripped' is used by all other filters. - sStringStripped = sString.strip(" \t\r\n") - - # -- skipping blank strings or strings commented out; other filters will not be considered any more in this case - - if bSkipBlankStrings is True: - if sStringStripped == "": - return False - - if sComment is not None: - if sComment != "": - if bCaseSensitive is True: - if sStringStripped.startswith(sComment) is True: - return False - else: - if sStringStripped.upper().startswith(sComment.upper()) is True: - return False - - # -- consider further filters - # - # No filter set (= no criteria defined) => use this string (bAck is True). - # - # At least one filter set (except sExclRegEx), at least one set filter fits (except sExclRegEx) => use this string. - # Filter sExclRegEx is set and fits => skip this string (final veto). - # At least one filter does not fit (except sExclRegEx) => skip this string. - # - # All filters (except sExclRegEx) are include filter (bAck is True in case of all set filters fit, also the 'not' filters) - # The filter sExclRegEx is an exclude filter and has final veto right (can revoke the True from other filters). - # - # All filters (except sInclRegEx and sExclRegEx) are handled as 'raw strings': no wild cards, just strings, considering bCaseSensitive. - # The filters sInclRegEx and sExclRegEx are handled as regular expressions; bCaseSensitive is not considered here. - - # -- filter specific flags (containing the names of the criteria within their names) - bStartsWith = None - bEndsWith = None - bStartsNotWith = None - bEndsNotWith = None - bContains = None - bContainsNot = None - bInclRegEx = None - bExclRegEx = None - - # Meaning: - # - Flag is None : filter not set => filter has no effect - # - Flag is True : filter set => result: use the input string (from this single filter flag point of view) - # - Flag is False: filter set => result: do not use the input string (from this single filter flag point of view) - # The results of all flags will be merged at the end of this function to one final conclusion to use the input string - # (bAck is True) or not (bAck is False). - # Logical join between all set filters: AND - - # substitute for the masked filter separator '\n' (hopefully the input string does not contain this substitute) - sSeparatorSubstitute = "#|S#|E#|P#|A#|R#|A#|T#|O#|R#" - - # -- filter: starts with - # > several filter strings possible (separated by semicolon; logical join: OR) - if sStartsWith is not None: - if sStartsWith != "": - sStartsWithModified = sStartsWith.replace(r"\;", sSeparatorSubstitute) # replace the masked separator by a substitute separator - listStartsWith = [] - if sStartsWith.find(";") >= 0: - listParts = sStartsWithModified.split(";") - for sPart in listParts: - sPart = sPart.replace(sSeparatorSubstitute , ";") # recover the original version - listStartsWith.append(sPart) - else: - sStartsWithModified = sStartsWith.replace(r"\;", ";") # convert to unmasked version - listStartsWith.append(sStartsWithModified) - - bStartsWith = False - for sStartsWith in listStartsWith: - if bCaseSensitive is True: - if sStringStripped.startswith(sStartsWith) is True: - bStartsWith = True - break - else: - if sStringStripped.upper().startswith(sStartsWith.upper()) is True: - bStartsWith = True - break - - # -- filter: ends with - # > several filter strings possible (separated by semicolon; logical join: OR) - if sEndsWith is not None: - if sEndsWith != "": - sEndsWithModified = sEndsWith.replace(r"\;", sSeparatorSubstitute) # replace the masked separator by a substitute separator - listEndsWith = [] - if sEndsWith.find(";") >= 0: - listParts = sEndsWithModified.split(";") - for sPart in listParts: - sPart = sPart.replace(sSeparatorSubstitute , ";") # recover the original version - listEndsWith.append(sPart) - else: - sEndsWithModified = sEndsWith.replace(r"\;", ";") # convert to unmasked version - listEndsWith.append(sEndsWithModified) - - bEndsWith = False - for sEndsWith in listEndsWith: - if bCaseSensitive is True: - if sStringStripped.endswith(sEndsWith) is True: - bEndsWith = True - break - else: - if sStringStripped.upper().endswith(sEndsWith.upper()) is True: - bEndsWith = True - break - - # -- filter: starts not with - # > several filter strings possible (separated by semicolon; logical join: AND) - if sStartsNotWith is not None: - if sStartsNotWith != "": - sStartsNotWithModified = sStartsNotWith.replace(r"\;", sSeparatorSubstitute) # replace the masked separator by a substitute separator - listStartsNotWith = [] - if sStartsNotWith.find(";") >= 0: - listParts = sStartsNotWithModified.split(";") - for sPart in listParts: - sPart = sPart.replace(sSeparatorSubstitute , ";") # recover the original version - listStartsNotWith.append(sPart) - else: - sStartsNotWithModified = sStartsNotWith.replace(r"\;", ";") # convert to unmasked version - listStartsNotWith.append(sStartsNotWithModified) - - bStartsNotWith = True - for sStartsNotWith in listStartsNotWith: - if bCaseSensitive is True: - if sStringStripped.startswith(sStartsNotWith) is True: - bStartsNotWith = False - break - else: - if sStringStripped.upper().startswith(sStartsNotWith.upper()) is True: - bStartsNotWith = False - break - - # -- filter: ends not with - # > several filter strings possible (separated by semicolon; logical join: AND) - if sEndsNotWith is not None: - if sEndsNotWith != "": - sEndsNotWithModified = sEndsNotWith.replace(r"\;", sSeparatorSubstitute) # replace the masked separator by a substitute separator - listEndsNotWith = [] - if sEndsNotWith.find(";") >= 0: - listParts = sEndsNotWithModified.split(";") - for sPart in listParts: - sPart = sPart.replace(sSeparatorSubstitute , ";") # recover the original version - listEndsNotWith.append(sPart) - else: - sEndsNotWithModified = sEndsNotWith.replace(r"\;", ";") # convert to unmasked version - listEndsNotWith.append(sEndsNotWithModified) - - bEndsNotWith = True - for sEndsNotWith in listEndsNotWith: - if bCaseSensitive is True: - if sStringStripped.endswith(sEndsNotWith) is True: - bEndsNotWith = False - break - else: - if sStringStripped.upper().endswith(sEndsNotWith.upper()) is True: - bEndsNotWith = False - break - - # -- filter: contains - # > several filter strings possible (separated by semicolon; logical join: OR) - if sContains is not None: - if sContains != "": - sContainsModified = sContains.replace(r"\;", sSeparatorSubstitute) # replace the masked separator by a substitute separator - listContains = [] - if sContainsModified.find(";") >= 0: - listParts = sContainsModified.split(";") - for sPart in listParts: - sPart = sPart.replace(sSeparatorSubstitute , ";") # recover the original version - print(f"- Part: '{sPart}'") - listContains.append(sPart) - else: - sContainsModified = sContains.replace(r"\;", ";") # convert to unmasked version - listContains.append(sContainsModified) - - bContains = False - for sContains in listContains: - if bCaseSensitive is True: - if sStringStripped.find(sContains) >= 0: - bContains = True - break - else: - if sStringStripped.upper().find(sContains.upper()) >= 0: - bContains = True - break - - # -- filter: contains not - # > several filter strings possible (separated by semicolon; logical join: AND) - if sContainsNot is not None: - if sContainsNot != "": - sContainsNotModified = sContainsNot.replace(r"\;", sSeparatorSubstitute) # replace the masked separator by a substitute separator - listContainsNot = [] - if sContainsNot.find(";") >= 0: - listParts = sContainsNotModified.split(";") - for sPart in listParts: - sPart = sPart.replace(sSeparatorSubstitute , ";") # recover the original version - listContainsNot.append(sPart) - else: - sContainsNotModified = sContainsNot.replace(r"\;", ";") # convert to unmasked version - listContainsNot.append(sContainsNotModified) - - bContainsNot = True - for sContainsNot in listContainsNot: - if bCaseSensitive is True: - if sStringStripped.find(sContainsNot) >= 0: - bContainsNot = False - break - else: - if sStringStripped.upper().find(sContainsNot.upper()) >= 0: - bContainsNot = False - break - - # -- filter: sInclRegEx - # > (take care to mask special characters that are part of the syntax of regular expressions!) - # > bCaseSensitive not considered here - if sInclRegEx is not None: - if sInclRegEx != "": - bInclRegEx = False - if re.search(sInclRegEx, sString) is not None: - bInclRegEx = True - - # -- last filter: sExclRegEx (final veto right) - # > (take care to mask special characters that are part of the syntax of regular expressions!) - # > bCaseSensitive not considered here - if sExclRegEx is not None: - if sExclRegEx != "": - bExclRegEx = True - if re.search(sExclRegEx, sString) is not None: - bExclRegEx = False - - # -- debug info - if bDebug is True: - print("\n* [sString] : '" + str(sString) + "'\n") - print(" -> [bStartsWith] : '" + str(bStartsWith) + "'") - print(" -> [bEndsWith] : '" + str(bEndsWith) + "'") - print(" -> [bStartsNotWith] : '" + str(bStartsNotWith) + "'") - print(" -> [bEndsNotWith] : '" + str(bEndsNotWith) + "'") - print(" -> [bContains] : '" + str(bContains) + "'") - print(" -> [bContainsNot] : '" + str(bContainsNot) + "'") - print(" -> [bInclRegEx] : '" + str(bInclRegEx) + "'") - print(" -> [bExclRegEx] : '" + str(bExclRegEx) + "'\n") - - # -- final conclusion (AND condition between filters) - - listDecisions = [] - listDecisions.append(bStartsWith) - listDecisions.append(bEndsWith) - listDecisions.append(bStartsNotWith) - listDecisions.append(bEndsNotWith) - listDecisions.append(bContains) - listDecisions.append(bContainsNot) - listDecisions.append(bInclRegEx) - listDecisions.append(bExclRegEx) - - bAck = False # initial - - # -- 1.) no filter set (all None) - nCntDecisions = 0 - for bDecision in listDecisions: - if bDecision is None: - nCntDecisions = nCntDecisions + 1 - if nCntDecisions == len(listDecisions): - bAck = True - if bDebug is True: - print(" > case [1] - bAck: " + str(bAck)) - - # -- 2.) final veto from exclude filter - if bExclRegEx is False: - bAck = False - if bDebug is True: - print(" > case [2] - bAck: " + str(bAck)) - - # -- 3.) exclude filter not set; decision only made by other filters (include) - if bExclRegEx is None: - bAck = True - for bDecision in listDecisions: - if bDecision is False: - bAck = False - break - if bDebug is True: - print(" > case [3] - bAck: " + str(bAck)) - - # -- 4.) exclude filter is True (only relevant in case of all other filters are not set; otherwise decision only made by other filters (include)) - if bExclRegEx is True: - if ( (bStartsWith is None) and - (bEndsWith is None) and - (bStartsNotWith is None) and - (bEndsNotWith is None) and - (bContains is None) and - (bContainsNot is None) and - (bInclRegEx is None) ): - bAck = True - if bDebug is True: - print(" > case [4.1] - bAck: " + str(bAck)) - else: - bAck = True - for bDecision in listDecisions: - if bDecision is False: - bAck = False - break - if bDebug is True: - print(" > case [4.2] - bAck: " + str(bAck)) - - if bDebug is True: - print() - - return bAck - - # eof def StringFilter(...) - - # -------------------------------------------------------------------------------------------------------------- - #TM*** - - def FormatResult(sMethod="", bSuccess=True, sResult=""): - """ -Formats the result string ``sResult`` depending on ``bSuccess``: - -* ``bSuccess`` is ``True`` indicates *success* -* ``bSuccess`` is ``False`` indicates an *error* -* ``bSuccess`` is ``None`` indicates an *exception* - -Additionally the name of the method that causes the result, can be provided (*optional*). -This is useful for debugging. - -**Arguments:** - -* ``sMethod`` - - / *Condition*: optional / *Type*: str / *Default*: (empty string) / - - Name of the method that causes the result. - -* ``bSuccess`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - Indicates if the computation of the method ``sMethod`` was successful or not. - -* ``sResult`` - - / *Condition*: optional / *Type*: str / *Default*: (empty string) / - - The result of the computation of the method ``sMethod``. - -**Returns:** - -* ``sResult`` - - / *Type*: str / - - The formatted result string. - """ - - if sMethod is None: - sMethod = str(sMethod) - if sResult is None: - sResult = str(sResult) - if bSuccess is True: - if sMethod != "": - sResult = f"[{sMethod}] : {sResult}" - elif bSuccess is False: - sError = "!!! ERROR !!!" - if sMethod != "": - sResult = f"{sError}\n[{sMethod}] : {sResult}" - else: - sResult = f"{sError}\n{sResult}" - else: - sException = "!!! EXCEPTION !!!" - if sMethod != "": - sResult = f"{sException}\n[{sMethod}] : {sResult}" - else: - sResult = f"{sException}\n{sResult}" - return sResult - - # eof def FormatResult(sMethod="", bSuccess=True, sResult=""): - - # -------------------------------------------------------------------------------------------------------------- - #TM*** - - # - make the methods static - - NormalizePath = staticmethod(NormalizePath) - DetectParentPath = staticmethod(DetectParentPath) - StringFilter = staticmethod(StringFilter) - FormatResult = staticmethod(FormatResult) - -# eof class CString(object): - -# ************************************************************************************************************** - - - diff --git a/additions/PythonExtensionsCollection/String/__init__.py b/additions/PythonExtensionsCollection/String/__init__.py deleted file mode 100644 index 958420af..00000000 --- a/additions/PythonExtensionsCollection/String/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/additions/PythonExtensionsCollection/Utils/CUtils.py b/additions/PythonExtensionsCollection/Utils/CUtils.py deleted file mode 100644 index 20447501..00000000 --- a/additions/PythonExtensionsCollection/Utils/CUtils.py +++ /dev/null @@ -1,374 +0,0 @@ -# ************************************************************************************************************** -# -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ************************************************************************************************************** -# -# CUtils.py -# -# XC-CT/ECA3-Queckenstedt -# -# 20.05.2022 -# -# ************************************************************************************************************** - -# -- import standard Python modules -from dotdict import dotdict - -# ************************************************************************************************************** -# wrapper -# ************************************************************************************************************** - -def PrettyPrint(oData=None, hOutputFile=None, bToConsole=True, nIndent=0, sPrefix=None, bHexFormat=False): - """ -Wrapper function to create and use a ``CTypePrint`` object. This wrapper function is responsible for -printing out the content to console and to a file (depending on input parameter). - -The content itself is prepared by the method ``TypePrint`` of class ``CTypePrint``. This happens ``PrettyPrint`` internally. - -The idea behind the ``PrettyPrint`` function is to resolve also the content of composite data types and provide for every parameter inside: - -* the type -* the total number of elements inside (e.g. the number of keys inside a dictionary) -* the counter number of the current element -* the value - -Example call: - -.. code:: python - - PrettyPrint(oData) - -(*with oData is a Python variable of any type*) - -The output can e.g. look like this: - -.. code:: python - - [DICT] (3/1) > {K1} [STR] : 'Val1' - [DICT] (3/2) > {K2} [LIST] (4/1) > [INT] : 1 - [DICT] (3/2) > {K2} [LIST] (4/2) > [STR] : 'A' - [DICT] (3/2) > {K2} [LIST] (4/3) > [INT] : 2 - [DICT] (3/2) > {K2} [LIST] (4/4) > [TUPLE] (2/1) > [INT] : 9 - [DICT] (3/2) > {K2} [LIST] (4/4) > [TUPLE] (2/2) > [STR] : 'Z' - [DICT] (3/3) > {K3} [INT] : 5 - -Every line of output has to be interpreted strictly from left to right. - -For example the meaning of the fifth line of output - -.. code:: python - - [DICT] (3/2) > {K2} [LIST] (4/4) > [TUPLE] (2/1) > [INT] : 9 - -is: - -* The type of input parameter (``oData``) is ``dict`` -* The dictionary contains 3 keys -* The current line gives information about the second key of the dictionary -* The name of the second key is 'K2' -* The value of the second key is of type ``list`` -* The list contains 4 elements -* The current line gives information about the fourth element of the list -* The fourth element of the list is of type ``tuple`` -* The tuple contains 2 elements -* The current line gives information about the first element of the tuple -* The first element of the tuple is of type ``int`` and has the value 9 - -Types are encapsulated in square brackets, counter in round brackets and key names are encapsulated in curly brackets. - -**Arguments:** - -* ``oData`` - - / *Condition*: required / *Type*: (*any Python data type*) / - - A variable of any Python data type. - -* ``hOutputFile`` - - / *Condition*: optional / *Type*: file handle / *Default*: None / - - If handle is not ``None`` the content is written to this file, otherwise not. - -* ``bToConsole`` - - / *Condition*: optional / *Type*: bool / *Default*: True / - - If ``True`` the content is written to console, otherwise not. - -* ``nIndent`` - - / *Condition*: optional / *Type*: int / *Default*: 0 / - - Sets the number of additional blanks at the beginning of every line of output (indentation). - -* ``sPrefix`` - - / *Condition*: optional / *Type*: str / *Default*: None / - - Sets a prefix string that is added at the beginning of every line of output. - -* ``bHexFormat`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True`` the output is printed in hexadecimal format (but valid for strings only). - -**Returns:** - -* ``listOutLines`` (*list*) - - / *Type*: list / - - List of lines containing the prepared output - """ - - oTypePrint = CTypePrint() - listOutLines = oTypePrint.TypePrint(oData, bHexFormat) - - listReturned = [] - for sLine in listOutLines: - # if requested add indentation and prefix - sLineOut = "" - if sPrefix is not None: - sLineOut = nIndent*" " + sPrefix + " " + sLine - else: - sLineOut = nIndent*" " + sLine - listReturned.append(sLineOut) - - if hOutputFile is not None: - hOutputFile.write(sLineOut + "\n") - if bToConsole is True: - print(sLineOut) - - return listReturned - -# eof def PrettyPrint(oData=None, hOutputFile=None, bToConsole=True, nIndent=0, sPrefix=None, bHexFormat=False): - -# -------------------------------------------------------------------------------------------------------------- -# TM*** - -class CTypePrint(object): - """ -The class ``CTypePrint`` provides a method (``TypePrint``) to compute the following data: - -* the type -* the total number of elements inside (e.g. the number of keys inside a dictionary) -* the counter number of the current element -* the value - -of simple and composite data types. - -The call of this method is encapsulated within the function ``PrettyPrint`` inside this module. - """ - def __init__(self): - self.listGlobalPrefixes = [] - self.listOutLines = [] - - def __del__(self): - pass - - def _ToHex(self, sString=None): - if ( (sString is None) or (sString == "") ): - return sString - listHex = [] - for sChar in sString: - listHex.append(hex(ord(sChar))) - sStringHex = " ".join(listHex) - return sStringHex - - def TypePrint(self, oData=None, bHexFormat=False): - """ -The method ``TypePrint`` computes details about the input variable ``oData``. - -**Arguments:** - -* ``oData`` - - / *Condition*: required / *Type*: any Python data type / - - Python variable of any data type. - -* ``bHexFormat`` - - / *Condition*: optional / *Type*: bool / *Default*: False / - - If ``True`` the output is provide in hexadecimal format. - -**Returns:** - -* ``listOutLines`` - - / *Type*: list / - - List of lines containing the resolved content of ``oData``. - """ - - if oData is None: - sLocalPrefix = "[NONE]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : " + str(oData) - self.listOutLines.append(sOut.strip()) - - elif type(oData) == int: - sLocalPrefix = "[INT]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : " + str(oData) - self.listOutLines.append(sOut.strip()) - - elif type(oData) == float: - sLocalPrefix = "[FLOAT]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : " + str(oData) - self.listOutLines.append(sOut.strip()) - - elif type(oData) == bool: - sLocalPrefix = "[BOOL]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : " + str(oData) - self.listOutLines.append(sOut.strip()) - - elif type(oData) == str: - sLocalPrefix = "[STR]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sData = str(oData) - if bHexFormat is True: - sData = self._ToHex(sData) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : '" + sData + "'" - self.listOutLines.append(sOut.strip()) - - elif type(oData) == list: - nNrOfElements = len(oData) - if nNrOfElements == 0: - # -- indicate empty list - sLocalPrefix = "[LIST]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : []" - self.listOutLines.append(sOut.strip()) - else: - # -- list elements of list - self.listGlobalPrefixes.append("[LIST]") - nCnt = 0 - for oElement in oData: - nCnt = nCnt + 1 - sCnt = "(" + str(nNrOfElements) + "/" + str(nCnt) + ") >" - self.listGlobalPrefixes.append(sCnt) - self.TypePrint(oElement, bHexFormat) # >>>> recursion - del self.listGlobalPrefixes[-1] # remove prefix count - del self.listGlobalPrefixes[-1] # remove prefix name - - elif type(oData) == tuple: - nNrOfElements = len(oData) - if nNrOfElements == 0: - # -- indicate empty tuple - sLocalPrefix = "[TUPLE]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : ()" - self.listOutLines.append(sOut.strip()) - else: - # -- list elements of tuple - self.listGlobalPrefixes.append("[TUPLE]") - nCnt = 0 - for oElement in oData: - nCnt = nCnt + 1 - sCnt = "(" + str(nNrOfElements) + "/" + str(nCnt) + ") >" - self.listGlobalPrefixes.append(sCnt) - self.TypePrint(oElement, bHexFormat) # >>>> recursion - del self.listGlobalPrefixes[-1] # remove prefix count - del self.listGlobalPrefixes[-1] # remove prefix name - - elif type(oData) == set: - nNrOfElements = len(oData) - if nNrOfElements == 0: - # -- indicate empty set - sLocalPrefix = "[SET]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : ()" - self.listOutLines.append(sOut.strip()) - else: - # -- list elements of set - self.listGlobalPrefixes.append("[SET]") - nCnt = 0 - for oElement in oData: - nCnt = nCnt + 1 - sCnt = "(" + str(nNrOfElements) + "/" + str(nCnt) + ") >" - self.listGlobalPrefixes.append(sCnt) - self.TypePrint(oElement, bHexFormat) # >>>> recursion - del self.listGlobalPrefixes[-1] # remove prefix count - del self.listGlobalPrefixes[-1] # remove prefix name - - elif type(oData) == dict: - nNrOfElements = len(oData) - if nNrOfElements == 0: - # -- indicate empty dictionary - sLocalPrefix = "[DICT]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : {}" - self.listOutLines.append(sOut.strip()) - else: - # -- list elements of dictionary - self.listGlobalPrefixes.append("[DICT]") - nCnt = 0 - listKeys = list(oData.keys()) - for sKey in listKeys: - nCnt = nCnt + 1 - oValue = oData[sKey] - sCntAndKey = "(" + str(nNrOfElements) + "/" + str(nCnt) + ") > {" + str(sKey) + "}" - self.listGlobalPrefixes.append(sCntAndKey) - self.TypePrint(oValue, bHexFormat) # >>>> recursion - del self.listGlobalPrefixes[-1] # remove prefix count - del self.listGlobalPrefixes[-1] # remove prefix name - - # elif type(oData) == dotdict: - elif ( (type(oData) == dotdict) or (str(type(oData)) == "") ): - nNrOfElements = len(oData) - if nNrOfElements == 0: - # -- indicate empty dot dictionary - sLocalPrefix = "[DOTDICT]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : {}" - self.listOutLines.append(sOut.strip()) - else: - # -- list elements of dot dictionary - self.listGlobalPrefixes.append("[DOTDICT]") - nCnt = 0 - listKeys = list(oData.keys()) - for sKey in listKeys: - nCnt = nCnt + 1 - oValue = oData[sKey] - sCntAndKey = "(" + str(nNrOfElements) + "/" + str(nCnt) + ") > {" + str(sKey) + "}" - self.listGlobalPrefixes.append(sCntAndKey) - self.TypePrint(oValue, bHexFormat) # >>>> recursion - del self.listGlobalPrefixes[-1] # remove prefix count - del self.listGlobalPrefixes[-1] # remove prefix name - - else: - sLocalPrefix = "[" + str(type(oData)) + "]" - sGlobalPrefix = " ".join(self.listGlobalPrefixes) - sData = str(oData) - if bHexFormat is True: - sData = self._ToHex(sData) - sOut = sGlobalPrefix + " " + sLocalPrefix + " : '" + sData + "'" - self.listOutLines.append(sOut.strip()) - - return self.listOutLines - - # eof def TypePrint(...): - -# eof class CTypePrint(): - -# ************************************************************************************************************** - diff --git a/additions/PythonExtensionsCollection/Utils/__init__.py b/additions/PythonExtensionsCollection/Utils/__init__.py deleted file mode 100644 index 958420af..00000000 --- a/additions/PythonExtensionsCollection/Utils/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/additions/PythonExtensionsCollection/__init__.py b/additions/PythonExtensionsCollection/__init__.py deleted file mode 100644 index 958420af..00000000 --- a/additions/PythonExtensionsCollection/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/additions/PythonExtensionsCollection/version.py b/additions/PythonExtensionsCollection/version.py deleted file mode 100644 index b5b224a4..00000000 --- a/additions/PythonExtensionsCollection/version.py +++ /dev/null @@ -1,23 +0,0 @@ -# ************************************************************************************************************** -# -# Copyright 2020-2022 Robert Bosch GmbH -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ************************************************************************************************************** -# -# Version and date of PythonExtensionsCollection -# -VERSION = "0.8.0" -VERSION_DATE = "28.06.2022" -