PythonExtensionsCollection 0.2.0__py3-none-any.whl → 0.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. PythonExtensionsCollection/Comparison/CComparison.py +341 -0
  2. PythonExtensionsCollection/Comparison/__init__.py +13 -0
  3. PythonExtensionsCollection/File/CFile.py +326 -106
  4. PythonExtensionsCollection/File/__init__.py +1 -1
  5. PythonExtensionsCollection/Folder/CFolder.py +460 -0
  6. PythonExtensionsCollection/Folder/__init__.py +13 -0
  7. PythonExtensionsCollection/PythonExtensionsCollection.pdf +0 -0
  8. PythonExtensionsCollection/String/CString.py +128 -344
  9. PythonExtensionsCollection/String/__init__.py +1 -1
  10. PythonExtensionsCollection/Utils/CUtils.py +77 -74
  11. PythonExtensionsCollection/Utils/__init__.py +1 -1
  12. PythonExtensionsCollection/__init__.py +1 -1
  13. PythonExtensionsCollection/version.py +23 -0
  14. {PythonExtensionsCollection-0.2.0.dist-info → PythonExtensionsCollection-0.13.0.dist-info}/METADATA +57 -44
  15. PythonExtensionsCollection-0.13.0.dist-info/RECORD +18 -0
  16. {PythonExtensionsCollection-0.2.0.dist-info → PythonExtensionsCollection-0.13.0.dist-info}/WHEEL +1 -1
  17. PythonExtensionsCollection/doc/.buildinfo +0 -4
  18. PythonExtensionsCollection/doc/File.html +0 -315
  19. PythonExtensionsCollection/doc/String.html +0 -590
  20. PythonExtensionsCollection/doc/Utils.html +0 -209
  21. PythonExtensionsCollection/doc/_modules/PythonExtensionsCollection/File/CFile.html +0 -960
  22. PythonExtensionsCollection/doc/_modules/PythonExtensionsCollection/String/CString.html +0 -1221
  23. PythonExtensionsCollection/doc/_modules/PythonExtensionsCollection/Utils/CUtils.html +0 -431
  24. PythonExtensionsCollection/doc/_modules/index.html +0 -106
  25. PythonExtensionsCollection/doc/_sources/File.rst.txt +0 -28
  26. PythonExtensionsCollection/doc/_sources/String.rst.txt +0 -28
  27. PythonExtensionsCollection/doc/_sources/Utils.rst.txt +0 -28
  28. PythonExtensionsCollection/doc/_sources/additional_doc/Introduction.rst.txt +0 -365
  29. PythonExtensionsCollection/doc/_sources/index.rst.txt +0 -27
  30. PythonExtensionsCollection/doc/_static/_sphinx_javascript_frameworks_compat.js +0 -134
  31. PythonExtensionsCollection/doc/_static/alabaster.css +0 -701
  32. PythonExtensionsCollection/doc/_static/basic.css +0 -930
  33. PythonExtensionsCollection/doc/_static/custom.css +0 -1
  34. PythonExtensionsCollection/doc/_static/doctools.js +0 -264
  35. PythonExtensionsCollection/doc/_static/documentation_options.js +0 -14
  36. PythonExtensionsCollection/doc/_static/file.png +0 -0
  37. PythonExtensionsCollection/doc/_static/jquery-3.6.0.js +0 -10881
  38. PythonExtensionsCollection/doc/_static/jquery.js +0 -2
  39. PythonExtensionsCollection/doc/_static/language_data.js +0 -199
  40. PythonExtensionsCollection/doc/_static/minus.png +0 -0
  41. PythonExtensionsCollection/doc/_static/plus.png +0 -0
  42. PythonExtensionsCollection/doc/_static/pygments.css +0 -82
  43. PythonExtensionsCollection/doc/_static/searchtools.js +0 -531
  44. PythonExtensionsCollection/doc/_static/underscore-1.13.1.js +0 -2042
  45. PythonExtensionsCollection/doc/_static/underscore.js +0 -6
  46. PythonExtensionsCollection/doc/additional_doc/Introduction.html +0 -365
  47. PythonExtensionsCollection/doc/genindex.html +0 -292
  48. PythonExtensionsCollection/doc/index.html +0 -123
  49. PythonExtensionsCollection/doc/objects.inv +0 -0
  50. PythonExtensionsCollection/doc/py-modindex.html +0 -138
  51. PythonExtensionsCollection/doc/search.html +0 -127
  52. PythonExtensionsCollection/doc/searchindex.js +0 -1
  53. PythonExtensionsCollection-0.2.0.dist-info/RECORD +0 -48
  54. {PythonExtensionsCollection-0.2.0.dist-info → PythonExtensionsCollection-0.13.0.dist-info}/LICENSE +0 -0
  55. {PythonExtensionsCollection-0.2.0.dist-info → PythonExtensionsCollection-0.13.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright 2020-2022 Robert Bosch Car Multimedia GmbH
1
+ # Copyright 2020-2022 Robert Bosch GmbH
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,460 @@
1
+ # **************************************************************************************************************
2
+ #
3
+ # Copyright 2020-2022 Robert Bosch GmbH
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+ # **************************************************************************************************************
18
+ #
19
+ # CFolder.py
20
+ #
21
+ # XC-CT/ECA3-Queckenstedt
22
+ #
23
+ # 28.06.2022
24
+ #
25
+ # **************************************************************************************************************
26
+
27
+ # -- import standard Python modules
28
+ import os, shutil, time, stat
29
+
30
+ # -- import Bosch Python modules
31
+ from PythonExtensionsCollection.String.CString import CString
32
+
33
+ # --------------------------------------------------------------------------------------------------------------
34
+
35
+ # little helper to delete folders containing files that are write protected
36
+ def rm_dir_readonly(func, path, excinfo):
37
+ """
38
+ Calls ``os.chmod`` in case of ``shutil.rmtree`` (within ``Delete()``) throws an exception (making files writable).
39
+ """
40
+ # print(f"{excinfo}") # debug only
41
+ os.chmod(path, stat.S_IWRITE)
42
+ func(path)
43
+
44
+ # --------------------------------------------------------------------------------------------------------------
45
+
46
+ class CFolder(object):
47
+ """
48
+ The class ``CFolder`` provides a small set of folder functions with extended parametrization (like switches
49
+ defining if a folder is allowed to be overwritten or not).
50
+
51
+ Most of the functions at least returns ``bSuccess`` and ``sResult``.
52
+
53
+ * ``bSuccess`` is ``True`` in case of no error occurred.
54
+ * ``bSuccess`` is ``False`` in case of an error occurred.
55
+ * ``bSuccess`` is ``None`` in case of a very fatal error occurred (exceptions).
56
+
57
+ * ``sResult`` contains details about what happens during computation.
58
+
59
+ Every instance of CFolder handles one single folder only and forces exclusive access to this folder.
60
+
61
+ It is not possible to create an instance of this class with a folder that is already in use by another instance.
62
+
63
+ The constructor of ``CFolder`` requires the input parameter ``sFolder``, that is the path and the name of a folder
64
+ that is handled by the current class instance.
65
+ """
66
+ # --------------------------------------------------------------------------------------------------------------
67
+ # TM***
68
+
69
+ def __init__(self, sFolder=None):
70
+ self.__sFolder = CString.NormalizePath(sFolder)
71
+
72
+ try:
73
+ CFolder.__listFoldersInUse
74
+ except:
75
+ CFolder.__listFoldersInUse = []
76
+
77
+ # exclusive access is required (checked by self.__bIsFreeToUse; relevant for destination in CopyTo and MoveTo)
78
+ if self.__sFolder in CFolder.__listFoldersInUse:
79
+ raise Exception(f"The folder '{self.__sFolder}' is already in use by another CFolder instance.")
80
+ else:
81
+ CFolder.__listFoldersInUse.append(self.__sFolder)
82
+
83
+ # eof def __init__(self, sFolder=None):
84
+
85
+ def __del__(self):
86
+ if self.__sFolder in CFolder.__listFoldersInUse:
87
+ CFolder.__listFoldersInUse.remove(self.__sFolder)
88
+
89
+ # eof def __del__(self):
90
+
91
+ # --------------------------------------------------------------------------------------------------------------
92
+ # TM***
93
+
94
+ def __bIsFreeToUse(self, sFolder=None):
95
+ """
96
+ Checks if the folder ``sFolder`` is free to use, that means: not used by another instance of ``CFolder``.
97
+ """
98
+
99
+ bIsFreeToUse = False # init
100
+ if sFolder is None:
101
+ bIsFreeToUse = False # error handling
102
+ else:
103
+ if sFolder in CFolder.__listFoldersInUse:
104
+ bIsFreeToUse = False
105
+ else:
106
+ bIsFreeToUse = True
107
+ return bIsFreeToUse
108
+
109
+ # eof def __bIsFreeToUse(self, sFolder=None):
110
+
111
+ # --------------------------------------------------------------------------------------------------------------
112
+ # TM***
113
+
114
+ def __Delete(self, sFolder=None, bConfirmDelete=True):
115
+ """
116
+ Deletes the folder ``sFolder``.
117
+
118
+ **Arguments:**
119
+
120
+ * ``sFolder``
121
+
122
+ / *Condition*: required / *Type*: str /
123
+
124
+ Path and name of folder to be deleted
125
+
126
+ * ``bConfirmDelete``
127
+
128
+ / *Condition*: optional / *Type*: bool / *Default*: True /
129
+
130
+ Defines if it will be handled as error if the folder does not exist.
131
+
132
+ If ``True``: If the folder does not exist, the method indicates an error (``bSuccess = False``).
133
+
134
+ If ``False``: It doesn't matter if the folder exists or not.
135
+
136
+ **Returns:**
137
+
138
+ * ``bSuccess``
139
+
140
+ / *Type*: bool /
141
+
142
+ Indicates if the computation of the method was successful or not.
143
+
144
+ * ``sResult``
145
+
146
+ / *Type*: str /
147
+
148
+ The result of the computation of the method.
149
+ """
150
+ sMethod = "CFolder.__Delete"
151
+
152
+ if sFolder is None:
153
+ bSuccess = False
154
+ sResult = "sFolder is None; please provide path and name of a folder when creating a CFolder object."
155
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
156
+ return bSuccess, sResult
157
+
158
+ if os.path.isdir(sFolder) is False:
159
+ sResult = f"Nothing to delete. The folder '{sFolder}' does not exist."
160
+ if bConfirmDelete is True:
161
+ bSuccess = False
162
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
163
+ else:
164
+ bSuccess = True
165
+ return bSuccess, sResult
166
+ # eof if os.path.isdir(sFolder) is False:
167
+
168
+ bSuccess = False
169
+ sResult = "UNKNOWN"
170
+ nCntTries = 1
171
+ nTriesMax = 4
172
+ nDelay = 2 # sec
173
+ listResults = []
174
+ while nCntTries <= nTriesMax:
175
+ try:
176
+ print(f"Trying to delete '{sFolder}'")
177
+ print()
178
+ shutil.rmtree(sFolder, ignore_errors=False, onerror=rm_dir_readonly)
179
+ except Exception as reason:
180
+ listResults.append(str(reason))
181
+ if os.path.isdir(sFolder) is True:
182
+ sResult = f"({nCntTries}/{nTriesMax}) Problem with deleting the folder '{sFolder}'. Folder still present."
183
+ listResults.append(sResult)
184
+ time.sleep(nDelay) # delay before next try
185
+ else:
186
+ bSuccess = True
187
+ sResult = f"Folder '{sFolder}' deleted."
188
+ break
189
+ nCntTries = nCntTries + 1
190
+ # eof while nCntTries <= nTriesMax:
191
+
192
+ if bSuccess is False:
193
+ sResult = "\n".join(listResults)
194
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
195
+
196
+ return bSuccess, sResult
197
+
198
+ # eof def __Delete(self, sFolder=None, bConfirmDelete=True):
199
+
200
+ # --------------------------------------------------------------------------------------------------------------
201
+ # TM***
202
+
203
+ def Delete(self, bConfirmDelete=True):
204
+ """
205
+ Deletes the folder the current class instance contains.
206
+
207
+ **Arguments:**
208
+
209
+ * ``bConfirmDelete``
210
+
211
+ / *Condition*: optional / *Type*: bool / *Default*: True /
212
+
213
+ Defines if it will be handled as error if the folder does not exist.
214
+
215
+ If ``True``: If the folder does not exist, the method indicates an error (``bSuccess = False``).
216
+
217
+ If ``False``: It doesn't matter if the folder exists or not.
218
+
219
+ **Returns:**
220
+
221
+ * ``bSuccess``
222
+
223
+ / *Type*: bool /
224
+
225
+ Indicates if the computation of the method was successful or not.
226
+
227
+ * ``sResult``
228
+
229
+ / *Type*: str /
230
+
231
+ The result of the computation of the method.
232
+ """
233
+ sMethod = "CFolder.Delete"
234
+ bSuccess, sResult = self.__Delete(self.__sFolder, bConfirmDelete)
235
+ if bSuccess is not True:
236
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
237
+ return bSuccess, sResult
238
+
239
+ # eof def Delete(self, bConfirmDelete=True):
240
+
241
+ # --------------------------------------------------------------------------------------------------------------
242
+ # TM***
243
+
244
+ def Create(self, bOverwrite=False, bRecursive=False):
245
+ """
246
+ Creates the current folder ``sFolder``.
247
+
248
+ **Arguments:**
249
+
250
+ * ``bOverwrite``
251
+
252
+ / *Condition*: optional / *Type*: bool / *Default*: False /
253
+
254
+ * In case of the folder already exists and ``bOverwrite`` is ``True``, than the folder will be deleted before creation.
255
+ * In case of the folder already exists and ``bOverwrite`` is ``False`` (default), than the folder will not be touched.
256
+
257
+ In both cases the return value ``bSuccess`` is ``True`` - because the folder exists.
258
+
259
+ * ``bRecursive``
260
+
261
+ / *Condition*: optional / *Type*: bool / *Default*: False /
262
+
263
+ * In case of ``bRecursive`` is ``True``, than the complete destination path will be created (including all intermediate subfolders).
264
+ * In case of ``bRecursive`` is ``False``, than it is expected that the parent folder of the new folder already exists.
265
+
266
+ **Returns:**
267
+
268
+ * ``bSuccess``
269
+
270
+ / *Type*: bool /
271
+
272
+ Indicates if the computation of the method was successful or not.
273
+
274
+ * ``sResult``
275
+
276
+ / *Type*: str /
277
+
278
+ The result of the computation of the method.
279
+ """
280
+ sMethod = "CFolder.Create"
281
+
282
+ if self.__sFolder is None:
283
+ bSuccess = False
284
+ sResult = "self.__sFolder is None; please provide path and name of a folder when creating a CFolder object."
285
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
286
+ return bSuccess, sResult
287
+
288
+ bCreateFolder = False
289
+ if os.path.isdir(self.__sFolder) is True:
290
+ if bOverwrite is True:
291
+ bSuccess, sResult = self.Delete()
292
+ if bSuccess is not True:
293
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
294
+ return bSuccess, sResult
295
+ bCreateFolder = True
296
+ else:
297
+ bSuccess = True
298
+ sResult = f"Folder '{self.__sFolder}' already exists."
299
+ return bSuccess, sResult
300
+ else:
301
+ bCreateFolder = True
302
+
303
+ bSuccess = False
304
+ sResult = "UNKNOWN"
305
+
306
+ if bCreateFolder is True:
307
+ nCntTries = 1
308
+ nTriesMax = 3
309
+ nDelay = 2 # sec
310
+ listResults = []
311
+ while nCntTries <= nTriesMax:
312
+ try:
313
+ print(f"Trying to create '{self.__sFolder}'")
314
+ print()
315
+ if bRecursive is True:
316
+ os.makedirs(self.__sFolder)
317
+ else:
318
+ os.mkdir(self.__sFolder)
319
+ except Exception as reason:
320
+ listResults.append(str(reason))
321
+ if os.path.isdir(self.__sFolder) is False:
322
+ sResult = f"({nCntTries}/{nTriesMax}) Problem with creating the folder '{self.__sFolder}'."
323
+ listResults.append(sResult)
324
+ time.sleep(nDelay) # delay before next try
325
+ else:
326
+ bSuccess = True
327
+ sResult = f"Folder '{self.__sFolder}' created."
328
+ break
329
+ nCntTries = nCntTries + 1
330
+ # eof while nCntTries <= nTriesMax:
331
+
332
+ if bSuccess is False:
333
+ sResult = "\n".join(listResults)
334
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
335
+
336
+ # eof if bCreateFolder is True:
337
+
338
+ return bSuccess, sResult
339
+
340
+ # eof def Create(self, bOverwrite=False, bRecursive=False):
341
+
342
+ # --------------------------------------------------------------------------------------------------------------
343
+ # TM***
344
+
345
+ def CopyTo(self, sDestination=None, bOverwrite=False):
346
+ """
347
+ Copies the current folder to ``sDestination``, that has to be a path to a folder **within** the source folder will be copied to
348
+ (with it's original name),
349
+
350
+ In case of the destination folder already exists and ``bOverwrite`` is ``True``, than the destination folder will be overwritten.
351
+
352
+ In case of the destination folder already exists and ``bOverwrite`` is ``False`` (default), than the destination folder will not be overwritten
353
+ and ``CopyTo`` returns ``bSuccess = False``.
354
+
355
+ **Arguments:**
356
+
357
+ * ``sDestination``
358
+
359
+ / *Condition*: required / *Type*: string /
360
+
361
+ The path to destination folder
362
+
363
+ * ``bOverwrite``
364
+
365
+ / *Condition*: optional / *Type*: bool / *Default*: False /
366
+
367
+ * In case of the destination folder already exists and ``bOverwrite`` is ``True``, than the destination folder will be overwritten.
368
+ * In case of the destination folder already exists and ``bOverwrite`` is ``False`` (default), than the destination folder will not be overwritten
369
+ and ``CopyTo`` returns ``bSuccess = False``.
370
+
371
+ **Returns:**
372
+
373
+ * ``bSuccess``
374
+
375
+ / *Type*: bool /
376
+
377
+ Indicates if the computation of the method was successful or not.
378
+
379
+ * ``sResult``
380
+
381
+ / *Type*: str /
382
+
383
+ The result of the computation of the method.
384
+ """
385
+ sMethod = "CFolder.CopyTo"
386
+
387
+ if self.__sFolder is None:
388
+ bSuccess = False
389
+ sResult = "self.__sFolder is None; please provide path and name of a folder when creating a CFolder object."
390
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
391
+ return bSuccess, sResult
392
+
393
+ if os.path.isdir(self.__sFolder) is False:
394
+ bSuccess = False
395
+ sResult = f"The folder '{self.__sFolder}' does not exist, therefore nothing can be copied."
396
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
397
+ return bSuccess, sResult
398
+
399
+ if sDestination is None:
400
+ bSuccess = False
401
+ sResult = "sDestination is None; please provide a path to a destination folder."
402
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
403
+ return bSuccess, sResult
404
+
405
+ sDestination = CString.NormalizePath(sDestination)
406
+
407
+ if os.path.isdir(sDestination) is False:
408
+ # the folder to be copied will be created within the destination folder, therefore we expect that the destination folder already exists
409
+ bSuccess = False
410
+ sResult = f"The destination folder '{sDestination}' does not exist."
411
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
412
+ return bSuccess, sResult
413
+
414
+ sSourceFolderName = os.path.basename(self.__sFolder)
415
+ sDestFolder = f"{sDestination}/{sSourceFolderName}"
416
+
417
+ if sDestFolder == self.__sFolder:
418
+ bSuccess = False
419
+ sResult = f"Source folder and destination folder are the same: '{self.__sFolder}'. Therefore nothing to do."
420
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
421
+ return bSuccess, sResult
422
+
423
+ if self.__bIsFreeToUse(sDestFolder) is False:
424
+ bSuccess = False
425
+ sResult = f"The destination folder '{sDestFolder}' is already in use by another CFolder instance."
426
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
427
+ return bSuccess, sResult
428
+
429
+ if os.path.isdir(sDestFolder) is True:
430
+ # destination folder already exists
431
+ if bOverwrite is True:
432
+ bSuccess, sResult = self.__Delete(sDestFolder)
433
+ if bSuccess is not True:
434
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
435
+ return bSuccess, sResult
436
+ else:
437
+ bSuccess = False
438
+ sResult = f"Not allowed to overwrite existing destination folder '{sDestFolder}'. Therefore nothing to do."
439
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
440
+ return bSuccess, sResult
441
+ # eof if os.path.isdir(sDestFolder) is True:
442
+
443
+ # analysis and preconditions done, now the action
444
+
445
+ try:
446
+ shutil.copytree(self.__sFolder, sDestFolder)
447
+ bSuccess = True
448
+ sResult = "Folder copied from\n> '" + self.__sFolder + "'\nto\n> '" + sDestFolder + "'"
449
+ except Exception as reason:
450
+ bSuccess = None
451
+ sResult = str(reason)
452
+ sResult = CString.FormatResult(sMethod, bSuccess, sResult)
453
+
454
+ return bSuccess, sResult
455
+
456
+ # eof def CopyTo(self, sDestination=None, bOverwrite=False):
457
+
458
+ # --------------------------------------------------------------------------------------------------------------
459
+
460
+
@@ -0,0 +1,13 @@
1
+ # Copyright 2020-2022 Robert Bosch GmbH
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.