lyrpy 0.0.2__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.
lyr/LUFile.py ADDED
@@ -0,0 +1,1174 @@
1
+ """LUFile.py"""
2
+ # -*- coding: UTF-8 -*-
3
+ __annotations__ = """
4
+ =======================================================
5
+ Copyright (c) 2023-2024
6
+ Author:
7
+ Lisitsin Y.R.
8
+ Project:
9
+ LU_PY
10
+ Python (LU)
11
+ Module:
12
+ LUFile.py
13
+
14
+ =======================================================
15
+ """
16
+
17
+ #------------------------------------------
18
+ # БИБЛИОТЕКИ python
19
+ #------------------------------------------
20
+ import os
21
+ import platform
22
+ import stat
23
+ import datetime
24
+ import logging
25
+ import tempfile
26
+ import re
27
+ import ctypes
28
+ import copy
29
+ import pathlib
30
+
31
+ # if platform.system() == 'Windows':
32
+ # import win32api
33
+ # print('Windows')
34
+ # import win32con
35
+ # #endif
36
+ # if platform.system() == 'Linux':
37
+ # ...
38
+ # #endif
39
+
40
+ #------------------------------------------
41
+ # БИБЛИОТЕКИ сторонние
42
+ #------------------------------------------
43
+ import shutil
44
+ import chardet
45
+
46
+ #------------------------------------------
47
+ # БИБЛИОТЕКА LU
48
+ #------------------------------------------
49
+ import lyr.LUErrors as LUErrors
50
+ import lyr.LUStrDecode as LUStrDecode
51
+ import lyr.LUDateTime as LUDateTime
52
+ import lyr.LUos as LUos
53
+ import lyr.LULog as LULog
54
+
55
+ """
56
+ #--------------------------------------------------------------------------------
57
+ f = open(file_name, access_mode, encoding='')
58
+ file_name = имя открываемого файла
59
+ access_mode = режим открытия файла. Он может быть: для чтения, записи и т. д.
60
+ По умолчанию используется режим чтения (r), если другое не указано.
61
+ Далее полный список режимов открытия файла
62
+ Режим Описание
63
+ r Только для чтения.
64
+ w Только для записи. Создаст новый файл, если не найдет с указанным именем.
65
+ rb Только для чтения (бинарный).
66
+ wb Только для записи (бинарный). Создаст новый файл, если не найдет с указанным именем.
67
+ r+ Для чтения и записи.
68
+ rb+ Для чтения и записи (бинарный).
69
+ w+ Для чтения и записи. Создаст новый файл для записи, если не найдет с указанным именем.
70
+ wb+ Для чтения и записи (бинарный). Создаст новый файл для записи, если не найдет с указанным именем.
71
+ a Откроет для добавления нового содержимого. Создаст новый файл для записи, если не найдет с указанным именем.
72
+ a+ Откроет для добавления нового содержимого. Создаст новый файл для чтения записи, если не найдет с указанным именем.
73
+ ab Откроет для добавления нового содержимого (бинарный). Создаст новый файл для записи, если не найдет с указанным именем.
74
+ ab+ Откроет для добавления нового содержимого (бинарный). Создаст новый файл для чтения записи, если не найдет с указанным именем.
75
+
76
+ # LFile = open (AFileName, 'r', encoding='utf-8')
77
+ # LFile = open (AFileName, 'r', encoding='cp1251')
78
+ #--------------------------------------------------------------------------------
79
+ """
80
+
81
+ cDefaultEncoding = 'cp1251'
82
+
83
+ #--------------------------------------------------------------------------------
84
+ # DirectoryExists
85
+ #--------------------------------------------------------------------------------
86
+ def DirectoryExists (APath: str) -> bool:
87
+ """DirectoryExists """
88
+ #beginfunction
89
+ return os.path.isdir(APath)
90
+ #endfunction
91
+
92
+ #--------------------------------------------------------------------------------
93
+ # ForceDirectories
94
+ #--------------------------------------------------------------------------------
95
+ def ForceDirectories (ADir: str) -> bool:
96
+ """ForceDirectories"""
97
+ #beginfunction
98
+ try:
99
+ os.makedirs (ADir, exist_ok = True)
100
+ except:
101
+ s = f'Unable to create directory {ADir:s} ...'
102
+ LULog.LoggerTOOLS_AddLevel(logging.error, s)
103
+ #endtry
104
+ LResult = DirectoryExists (ADir)
105
+ return LResult
106
+ #endfunction
107
+
108
+ #--------------------------------------------------------------------------------
109
+ # GetDirectoryTreeSize
110
+ #--------------------------------------------------------------------------------
111
+ def GetDirectoryTreeSize(ADir: str) -> int:
112
+ """GetDirectoryTreeSize"""
113
+ """Return total size of files in given path and subdirs"""
114
+ #beginfunction
115
+ Ltotal = 0
116
+ for Lentry in os.scandir(ADir):
117
+ if Lentry.is_dir(follow_symlinks=False):
118
+ Ltotal += GetDirectoryTreeSize(Lentry.path)
119
+ else:
120
+ Ltotal += Lentry.stat(follow_symlinks=False).st_size
121
+ return Ltotal
122
+ #endfunction
123
+
124
+ #--------------------------------------------------------------------------------
125
+ # DeleteDirectoryTree
126
+ #--------------------------------------------------------------------------------
127
+ def DeleteDirectoryTree (ADir: str) -> bool:
128
+ """DeleteDirectoryTree"""
129
+ """
130
+ Удалить дерево каталогов в Windows,
131
+ где для некоторых файлов установлен бит только для чтения.
132
+ Он использует обратный вызов onerror, чтобы очистить бит readonly и повторить попытку удаления.
133
+ """
134
+ def remove_readonly (func, path, _):
135
+ """remove_readonly"""
136
+ #beginfunction
137
+ s = f'Clear the readonly bit and reattempt the removal {path:s} ...'
138
+ LULog.LoggerTOOLS_AddLevel(logging.DEBUG, s)
139
+ os.chmod (path, stat.S_IWRITE)
140
+ func (path)
141
+ #endfunction
142
+
143
+ def errorRemoveReadonly (func, path, exc):
144
+ """errorRemoveReadonly"""
145
+ #beginfunction
146
+ excvalue = exc [1]
147
+ if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
148
+ # change the file to be readable,writable,executable: 0777
149
+ os.chmod (path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
150
+ # retry
151
+ func (path)
152
+ else:
153
+ # raiseenter code here
154
+ ...
155
+ #endif
156
+ #endfunction
157
+
158
+ #beginfunction
159
+ if DirectoryExists (ADir):
160
+ s = f'DeleteDirectoryTree {ADir:s} ...'
161
+ LULog.LoggerTOOLS_AddLevel(logging.DEBUG, s)
162
+ try:
163
+ # shutil.rmtree (ADirectoryName, ignore_errors = True, onexc = None)
164
+ shutil.rmtree (ADir, ignore_errors = False, onerror = remove_readonly)
165
+ LResult = True
166
+ except:
167
+ s = f'Unable delete directory {ADir:s} ...'
168
+ LULog.LoggerTOOLS_AddLevel (logging.error, s)
169
+ LResult = False
170
+ #endtry
171
+ #endif
172
+ return LResult
173
+ #endfunction
174
+
175
+ #--------------------------------------------------------------------------------
176
+ # DeleteDirectory_walk
177
+ #--------------------------------------------------------------------------------
178
+ # Delete everything reachable from the directory named in 'top',
179
+ # assuming there are no symbolic links.
180
+ # CAUTION: This is dangerous! For example, if top == '/', it
181
+ # could delete all your disk files.
182
+ #--------------------------------------------------------------------------------
183
+ def DirectoryClear (ADir: str) -> bool:
184
+ """DirectoryClear"""
185
+ #beginfunction
186
+ LResult = True
187
+ if DirectoryExists (ADir):
188
+ for root, dirs, files in os.walk (ADir, topdown = False):
189
+ for file in files:
190
+ os.remove (os.path.join (root, file))
191
+ #endfor
192
+ for dir in dirs:
193
+ os.rmdir (os.path.join (root, dir))
194
+ #endfor
195
+ #endfor
196
+ LResult = True
197
+ #endif
198
+ return LResult
199
+ #endfunction
200
+
201
+ #--------------------------------------------------------------------------------
202
+ # FileExists
203
+ #--------------------------------------------------------------------------------
204
+ def FileExists (AFileName: str) -> bool:
205
+ """FileExists"""
206
+ #beginfunction
207
+ return os.path.isfile(AFileName)
208
+ #endfunction
209
+
210
+ #--------------------------------------------------------------------------------
211
+ # GetFileDateTime
212
+ #--------------------------------------------------------------------------------
213
+ def GetFileDateTime (AFileName: str) -> ():
214
+ """GetFileDateTime"""
215
+ #beginfunction
216
+ LTuple = ()
217
+ LFileTimeCreate = 0
218
+ LFileTimeMod = 0
219
+ LFileTimeCreateDate = 0
220
+ LFileTimeModDate = 0
221
+ if FileExists (AFileName):
222
+ # file creation
223
+ LFileTimeCreate: datetime = os.path.getctime (AFileName)
224
+ # file modification
225
+ LFileTimeMod: datetime = os.path.getmtime (AFileName)
226
+ # convert creation timestamp into DateTime object
227
+ LFileTimeCreateDate: datetime = datetime.datetime.fromtimestamp (LFileTimeCreate)
228
+ # convert timestamp into DateTime object
229
+ LFileTimeModDate: datetime = datetime.datetime.fromtimestamp (LFileTimeMod)
230
+ #endif
231
+ LTuple = (LFileTimeMod, LFileTimeCreate, LFileTimeModDate, LFileTimeCreateDate)
232
+ return LTuple
233
+ #endfunction
234
+
235
+ #--------------------------------------------------------------------------------
236
+ # GetDirDateTime
237
+ #--------------------------------------------------------------------------------
238
+ def GetDirDateTime (AFileName: str) -> ():
239
+ """GetDirDateTime"""
240
+ #beginfunction
241
+ LTuple = ()
242
+ LFileTimeCreate = 0
243
+ LFileTimeMod = 0
244
+ LFileTimeCreateDate = 0
245
+ LFileTimeModDate = 0
246
+ if DirectoryExists (AFileName):
247
+ # file creation
248
+ LFileTimeCreate: datetime = os.path.getctime (AFileName)
249
+ # file modification
250
+ LFileTimeMod: datetime = os.path.getmtime (AFileName)
251
+ # convert creation timestamp into DateTime object
252
+ LFileTimeCreateDate: datetime = datetime.datetime.fromtimestamp (LFileTimeCreate)
253
+ # convert timestamp into DateTime object
254
+ LFileTimeModDate: datetime = datetime.datetime.fromtimestamp (LFileTimeMod)
255
+ #endif
256
+ LTuple = (LFileTimeMod, LFileTimeCreate, LFileTimeModDate, LFileTimeCreateDate)
257
+ return LTuple
258
+ #endfunction
259
+
260
+ def cmptimestamps(AFileNameSource: str, AFileNameDest: str, _use_ctime):
261
+ """ Compare time stamps of two files and return True
262
+ if file1 (source) is more recent than file2 (target) """
263
+ #beginfunction
264
+ st1 = os.stat (AFileNameSource)
265
+ st2 = os.stat (AFileNameDest)
266
+ mtime_cmp = int((st1.st_mtime - st2.st_mtime) * 1000) > 0
267
+ if _use_ctime:
268
+ return mtime_cmp or int((AFileNameSource.st_ctime - AFileNameDest.st_mtime) * 1000) > 0
269
+ else:
270
+ return mtime_cmp
271
+ #endif
272
+ #endfunction
273
+
274
+ #--------------------------------------------------------------------------------
275
+ # COMPAREFILETIMES
276
+ #--------------------------------------------------------------------------------
277
+ def COMPAREFILETIMES (AFileNameSource: str, AFileNameDest: str) -> int:
278
+ """COMPAREFILETIMES"""
279
+ #beginfunction
280
+ if not FileExists (AFileNameSource):
281
+ #-2 File1 could not be opened (see @ERROR for more information).
282
+ return -2
283
+ #endif
284
+ if not FileExists (AFileNameDest):
285
+ #-3 File2 could not be opened (see @ERROR for more information).
286
+ return -3
287
+ #endif
288
+
289
+ LFileName1m = GetFileDateTime (AFileNameSource)[0]
290
+ LFileName2m = GetFileDateTime (AFileNameDest)[0]
291
+ LFileName1c = GetFileDateTime (AFileNameSource)[0]
292
+ LFileName2c = GetFileDateTime (AFileNameDest)[0]
293
+
294
+ if LFileName1m == LFileName2m:
295
+ #0 File1 and file2 have the same date and time.
296
+ return 0
297
+ else:
298
+ if LFileName1m > LFileName2m:
299
+ #1 File1 is more recent than file2.
300
+ return 1
301
+ else:
302
+ #-1 File1 is older than file2.
303
+ return -1
304
+ #endif
305
+ #endif
306
+ #------------------------------------------------------------------------------
307
+ # if int ((LFileName1m - LFileName2m) * 1000) == 0:
308
+ # return 0
309
+ # else:
310
+ # if int ((LFileName1m - LFileName2m) * 1000) > 0:
311
+ # return 1
312
+ # else:
313
+ # return -1
314
+ # #endif
315
+ # #endif
316
+ #------------------------------------------------------------------------------
317
+ #endfunction
318
+
319
+ #--------------------------------------------------------------------------------
320
+ # CheckFileExt
321
+ #--------------------------------------------------------------------------------
322
+ def CheckFileExt (AFileName: str, AExt: str) -> bool:
323
+ """CheckFileExt"""
324
+ #beginfunction
325
+ if AExt != "":
326
+ LResult = ExtractFileName(AFileName).endswith(AExt)
327
+ else:
328
+ LResult = False
329
+ #endif
330
+ return LResult
331
+ #endfunction
332
+
333
+ #--------------------------------------------------------------------------------
334
+ # GetFileSize
335
+ #--------------------------------------------------------------------------------
336
+ def GetFileSize (AFileName: str) -> int:
337
+ """GetFileSize"""
338
+ #beginfunction
339
+ if FileExists (AFileName):
340
+ LResult = os.path.getsize (AFileName)
341
+ else:
342
+ LResult = 0
343
+ #endif
344
+ return LResult
345
+ #endfunction
346
+
347
+ #--------------------------------------------------------------------------------
348
+ # ExpandFileName
349
+ #--------------------------------------------------------------------------------
350
+ def ExpandFileName (APath: str) -> str:
351
+ """ExpandFileName"""
352
+ #beginfunction
353
+ LResult = os.path.abspath(APath)
354
+ return LResult
355
+ #endfunction
356
+
357
+ #--------------------------------------------------------------------------------
358
+ # ExtractFileDir
359
+ #--------------------------------------------------------------------------------
360
+ def ExtractFileDir (APath: str) -> str:
361
+ """ExtractFileDir"""
362
+ #beginfunction
363
+ LDir, LFileName = os.path.split(APath)
364
+ return LDir
365
+ #endfunction
366
+
367
+ #--------------------------------------------------------------------------------
368
+ # ExtractFileName
369
+ #--------------------------------------------------------------------------------
370
+ def ExtractFileName (APath: str) -> str:
371
+ """ExtractFileName"""
372
+ #beginfunction
373
+ LPath, LFileName = os.path.split(APath)
374
+ return LFileName
375
+ #endfunction
376
+
377
+ #-------------------------------------------------------------------------------
378
+ # ExtractFileNameWithoutExt
379
+ #-------------------------------------------------------------------------------
380
+ def ExtractFileNameWithoutExt (AFileName: str) -> str:
381
+ """ExtractFileNameWithoutExt"""
382
+ #beginfunction
383
+ LResult = os.path.basename (AFileName).split ('.') [0]
384
+ return LResult
385
+ #endfunction
386
+
387
+ #--------------------------------------------------------------------------------
388
+ # ExtractFileExt
389
+ #--------------------------------------------------------------------------------
390
+ def ExtractFileExt (AFileName: str) -> str:
391
+ """ExtractFileExt"""
392
+ #beginfunction
393
+ LResult = os.path.basename(AFileName)
394
+ LFileName, LFileExt = os.path.splitext(LResult)
395
+ return LFileExt
396
+ #endfunction
397
+
398
+ #---------------------------------------------------------------------------------------------
399
+ # GetFileDir (APath: str) -> str:
400
+ #---------------------------------------------------------------------------------------------
401
+ def GetFileDir (APath: str) -> str:
402
+ """GetFileDir"""
403
+ #beginfunction
404
+ return ExtractFileDir (APath)
405
+ #endfunction
406
+
407
+ #--------------------------------------------------------------------------------
408
+ # GetFileName (APath: str) -> str:
409
+ #--------------------------------------------------------------------------------
410
+ def GetFileName (APath: str) -> str:
411
+ """GetFileName"""
412
+ #beginfunction
413
+ return ExtractFileNameWithoutExt (APath)
414
+ #endfunction
415
+
416
+ #-------------------------------------------------------------------------------
417
+ # GetFileNameWithoutExt (AFileName: str) -> str:
418
+ #-------------------------------------------------------------------------------
419
+ def GetFileNameWithoutExt (AFileName: str) -> str:
420
+ """GetFileNameWithoutExt"""
421
+ #beginfunction
422
+ return ExtractFileNameWithoutExt (AFileName)
423
+ #endfunction
424
+
425
+ #---------------------------------------------------------------------------------------------
426
+ # GetFileExt (AFileName: str) -> str:
427
+ #---------------------------------------------------------------------------------------------
428
+ def GetFileExt (AFileName: str) -> str:
429
+ """GetFileExt"""
430
+ #beginfunction
431
+ return ExtractFileExt (AFileName)
432
+ #endfunction
433
+
434
+ #--------------------------------------------------------------------------------
435
+ # GetFileEncoding (AFileName: str) -> str:
436
+ #--------------------------------------------------------------------------------
437
+ def GetFileEncoding (AFileName: str) -> str:
438
+ """GetFileEncoding"""
439
+ #beginfunction
440
+ LEncoding = ''
441
+ if FileExists(AFileName):
442
+ LFile = open (AFileName, 'rb')
443
+ LRawData = LFile.read ()
444
+ LResult = chardet.detect (LRawData)
445
+ LEncoding = LResult ['encoding']
446
+ LFile.close ()
447
+ #endif
448
+ return LEncoding
449
+ #endfunction
450
+
451
+ #--------------------------------------------------------------------------------
452
+ # IncludeTrailingBackslash
453
+ #--------------------------------------------------------------------------------
454
+ def IncludeTrailingBackslash (APath: str) -> str:
455
+ """IncludeTrailingBackslash"""
456
+ #beginfunction
457
+ LResult = APath.rstrip('\\')+'\\'
458
+ # LResult = pathlib.WindowsPath (APath)
459
+ # LResult = APath.rstrip('/')+'/'
460
+ return LResult
461
+ #endfunction
462
+
463
+ #--------------------------------------------------------------------------------
464
+ # GetDirNameYYMMDD
465
+ #--------------------------------------------------------------------------------
466
+ def GetDirNameYYMMDD (ARootDir: str, ADate: datetime.datetime) -> str:
467
+ """GetDirNameYYMMDD"""
468
+ #beginfunction
469
+ LYMDStr: str = LUDateTime.DateTimeStr(False, ADate, LUDateTime.cFormatDateYYMMDD_02, False)
470
+ LResult = IncludeTrailingBackslash(ARootDir)+LYMDStr
471
+ return LResult
472
+ #endfunction
473
+
474
+ #--------------------------------------------------------------------------------
475
+ # GetDirNameYYMM
476
+ #--------------------------------------------------------------------------------
477
+ def GetDirNameYYMM (ARootDir: str, ADate: datetime.datetime) -> str:
478
+ """GetDirNameYYMM"""
479
+ #beginfunction
480
+ LYMDStr: str = LUDateTime.DateTimeStr(False, ADate, LUDateTime.cFormatDateYYMM_02, False)
481
+ LResult = IncludeTrailingBackslash(ARootDir)+LYMDStr
482
+ return LResult
483
+ #endfunction
484
+
485
+ #--------------------------------------------------------------------------------
486
+ # GetTempDir
487
+ #--------------------------------------------------------------------------------
488
+ def GetTempDir () -> str:
489
+ """GetTempDir"""
490
+ #beginfunction
491
+ # LResult = win32api.GetTempPath()
492
+ LResult = tempfile.gettempdir ()
493
+ return LResult
494
+ #endfunction
495
+
496
+ #-------------------------------------------------------------------------------
497
+ # GetFileAttrStr
498
+ #-------------------------------------------------------------------------------
499
+ def GetFileAttrStr (Aattr: int) -> str:
500
+ """GetFileAttrStr"""
501
+ #beginfunction
502
+ #-------------------------------------------------------------------------------
503
+ # 0x 00 00 20 20
504
+ # 0b00000000 00000000 00100000 00100000
505
+ #-------------------------------------------------------------------------------
506
+ #stat.FILE_ATTRIBUTE_NO_SCRUB_DATA 0b00000000 00000010 00000000 00000000
507
+ #stat.FILE_ATTRIBUTE_VIRTUAL 0b00000000 00000001 00000000 00000000
508
+
509
+ #stat.FILE_ATTRIBUTE_INTEGRITY_STREAM 0b00000000 00000000 10000000 00000000
510
+ #stat.FILE_ATTRIBUTE_ENCRYPTED 0b00000000 00000000 01000000 00000000
511
+ #stat.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0b00000000 00000000 00100000 00000000
512
+ #stat.FILE_ATTRIBUTE_OFFLINE 0b00000000 00000000 00010000 00000000
513
+ #stat.FILE_ATTRIBUTE_COMPRESSED 0b00000000 00000000 00001000 00000000
514
+ #stat.FILE_ATTRIBUTE_REPARSE_POINT 0b00000000 00000000 00000100 00000000
515
+ #stat.FILE_ATTRIBUTE_SPARSE_FILE 0b00000000 00000000 00000010 00000000
516
+ #stat.FILE_ATTRIBUTE_TEMPORARY 0b00000000 00000000 00000001 00000000
517
+
518
+ #stat.FILE_ATTRIBUTE_NORMAL 0b00000000 00000000 00000000 10000000
519
+ #stat.FILE_ATTRIBUTE_DEVICE 0b00000000 00000000 00000000 01000000
520
+ #-------------------------------------------------------------------------------
521
+ #stat.FILE_ATTRIBUTE_ARCHIVE 0b00000000 00000000 00000000 00100000
522
+ #-------------------------------------------------------------------------------
523
+ #stat.FILE_ATTRIBUTE_DIRECTORY 0b00000000 00000000 00000000 00010000
524
+ #-------------------------------------------------------------------------------
525
+ #stat. 0b00000000 00000000 00000000 00001000
526
+ #-------------------------------------------------------------------------------
527
+ #stat.FILE_ATTRIBUTE_SYSTEM 0b00000000 00000000 00000000 00000100
528
+ #-------------------------------------------------------------------------------
529
+ #stat.FILE_ATTRIBUTE_HIDDEN 0b00000000 00000000 00000000 00000010
530
+ #-------------------------------------------------------------------------------
531
+ #stat.FILE_ATTRIBUTE_READONLY 0b00000000 00000000 00000000 00000001
532
+ #-------------------------------------------------------------------------------
533
+ Lattr = Aattr
534
+ sa = ''
535
+ sa += '????????'
536
+ sa += '1' if Lattr & 0b100000000000000000000000 else '?'
537
+ sa += '1' if Lattr & 0b010000000000000000000000 else '?'
538
+ sa += '1' if Lattr & 0b001000000000000000000000 else '?'
539
+ sa += '1' if Lattr & 0b000100000000000000000000 else '?'
540
+ sa += '1' if Lattr & 0b000010000000000000000000 else '?'
541
+ sa += '1' if Lattr & 0b000001000000000000000000 else '?'
542
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_NO_SCRUB_DATA else '.'
543
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_VIRTUAL else '.'
544
+
545
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_INTEGRITY_STREAM else '.'
546
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_ENCRYPTED else '.'
547
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED else '.'
548
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_OFFLINE else '.'
549
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_COMPRESSED else '.'
550
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_REPARSE_POINT else '.'
551
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_SPARSE_FILE else '.'
552
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_TEMPORARY else '.'
553
+
554
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_NORMAL else '.'
555
+ sa += '1' if Lattr & stat.FILE_ATTRIBUTE_DEVICE else '.'
556
+ sa += 'a' if Lattr & stat.FILE_ATTRIBUTE_ARCHIVE else '.'
557
+ sa += 'd' if Lattr & stat.FILE_ATTRIBUTE_DIRECTORY else '.'
558
+ sa += '.'
559
+ sa += 's' if Lattr & stat.FILE_ATTRIBUTE_SYSTEM else '.'
560
+ sa += 'h' if Lattr & stat.FILE_ATTRIBUTE_HIDDEN else '.'
561
+ sa += 'r' if Lattr & stat.FILE_ATTRIBUTE_READONLY else '.'
562
+ return sa
563
+ #endfunction
564
+
565
+ #-------------------------------------------------------------------------------
566
+ # GetFileModeStrUnix
567
+ #-------------------------------------------------------------------------------
568
+ def GetFileModeStrUnix (Amode: int) -> str:
569
+ """GetFileModeStrUnix"""
570
+ #beginfunction
571
+ # chmod(path,mode)
572
+ # s = f'stat.S_ISUID: {bin (stat.S_ISUID):s}'
573
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
574
+ # s = f'stat.S_ISGID: {bin (stat.S_ISGID):s}'
575
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
576
+ # s = f'stat.S_ENFMT: {bin (stat.S_ENFMT):s}'
577
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
578
+ # s = f'stat.S_ISVTX: {bin (stat.S_ISVTX):s}'
579
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
580
+ # s = f'stat.S_IREAD: {bin (stat.S_IREAD):s}'
581
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
582
+ # s = f'stat.S_IWRITE: {bin (stat.S_IWRITE):s}'
583
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
584
+ # s = f'stat.S_IEXEC: {bin (stat.S_IEXEC):s}'
585
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
586
+ # s = f'stat.S_IRWXU: {bin (stat.S_IRWXU):s}'
587
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
588
+ # s = f'stat.S_IRUSR: {bin (stat.S_IRUSR):s}'
589
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
590
+ # s = f'stat.S_IWUSR: {bin (stat.S_IWUSR):s}'
591
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
592
+ # s = f'stat.S_IXUSR: {bin (stat.S_IXUSR):s}'
593
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
594
+ # s = f'stat.S_IRWXG: {bin (stat.S_IRWXG):s}'
595
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
596
+ # s = f'stat.S_IRGRP: {bin (stat.S_IRGRP):s}'
597
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
598
+ # s = f'stat.S_IWGRP: {bin (stat.S_IWGRP):s}'
599
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
600
+ # s = f'stat.S_IXGRP: {bin (stat.S_IXGRP):s}'
601
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
602
+ # s = f'stat.S_IRWXO: {bin (stat.S_IRWXO):s}'
603
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
604
+ # s = f'stat.S_IROTH: {bin (stat.S_IROTH):s}'
605
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
606
+ # s = f'stat.S_IWOTH: {bin (stat.S_IWOTH):s}'
607
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
608
+ # s = f'stat.S_IXOTH: {bin (stat.S_IXOTH):s}'
609
+ # LULog.LoggerTOOLS_AddLevel (LULog.TEXT, s)
610
+
611
+ #-------------------------------------------------------------------------------
612
+ # stat.S_ISUID − Set user ID on execution
613
+ # stat.S_ISUID: 0b00010000 00000000
614
+ # stat.S_ISGID − Set group ID on execution
615
+ # stat.S_ISGID: 0b00000100 00000000
616
+ # stat.S_ENFMT – Enforced record locking
617
+ # stat.S_ENFMT: 0b00000100 00000000
618
+ # stat.S_ISVTX – After execution, save text image
619
+ # stat.S_ISVTX: 0b00000010 00000000
620
+ #-------------------------------------------------------------------------------
621
+ # stat.S_IREAD − Read by owner
622
+ # stat.S_IREAD: 0b00000001 00000000
623
+ # stat.S_IWRITE − Write by owner
624
+ # stat.S_IWRITE: 0b00000000 10000000
625
+ # stat.S_IEXEC − Execute by owner
626
+ # stat.S_IEXEC: 0b00000000 01000000
627
+ #-------------------------------------------------------------------------------
628
+ # stat.S_IRWXU − Read, write, and execute by owner
629
+ # stat.S_IRWXU: 0b00000001 11000000 Owner
630
+ #-------------------------------------------------------------------------------
631
+ # stat.S_IRUSR − Read by owner
632
+ # stat.S_IRUSR: 0b00000001 00000000
633
+ # stat.S_IWUSR − Write by owner
634
+ # stat.S_IWUSR: 0b00000000 10000000
635
+ # stat.S_IXUSR − Execute by owner
636
+ # stat.S_IXUSR: 0b00000000 01000000
637
+ #-------------------------------------------------------------------------------
638
+ # stat.S_IRWXG − Read, write, and execute by group
639
+ # stat.S_IRWXG: 0b00000000 00111000 Group
640
+ #-------------------------------------------------------------------------------
641
+ # stat.S_IRGRP − Read by group
642
+ # stat.S_IRGRP: 0b00000000 00100000
643
+ # stat.S_IWGRP − Write by group
644
+ # stat.S_IWGRP: 0b00000000 00010000
645
+ # stat.S_IXGRP − Execute by group
646
+ # stat.S_IXGRP: 0b00000000 00001000
647
+ #-------------------------------------------------------------------------------
648
+ # stat.S_IRWXO − Read, write, and execute by others
649
+ # stat.S_IRWXO: 0b00000000 00000111 Others
650
+ #-------------------------------------------------------------------------------
651
+ # stat.S_IROTH − Read by others
652
+ # stat.S_IROTH: 0b00000000 00000100
653
+ # stat.S_IWOTH − Write by others
654
+ # stat.S_IWOTH: 0b00000000 00000010
655
+ # stat.S_IXOTH − Execute by others
656
+ # stat.S_IXOTH: 0b00000000 00000001
657
+ #-------------------------------------------------------------------------------
658
+ Lmode = Amode
659
+ sa = ''
660
+ sa += '1' if Lmode & 0b1000000000000000 else '-'
661
+ sa += '1' if Lmode & 0b0100000000000000 else '-'
662
+ sa += '1' if Lmode & 0b0010000000000000 else '-'
663
+
664
+ sa += '1' if Lmode & stat.S_ISUID else '-'
665
+ sa += '1' if Lmode & stat.S_ISGID else '-'
666
+ sa += '1' if Lmode & stat.S_ENFMT else '-'
667
+ sa += '1' if Lmode & stat.S_ISVTX else '-'
668
+ #-------------------------------------------------------------------------------
669
+ sa += 'r' if Lmode & stat.S_IRUSR else '-'
670
+ sa += 'w' if Lmode & stat.S_IWUSR else '-'
671
+ sa += 'x' if Lmode & stat.S_IXUSR else '-'
672
+ #-------------------------------------------------------------------------------
673
+ sa += 'r' if Lmode & stat.S_IRGRP else '-'
674
+ sa += 'w' if Lmode & stat.S_IWGRP else '-'
675
+ sa += 'x' if Lmode & stat.S_IXGRP else '-'
676
+ #-------------------------------------------------------------------------------
677
+ sa += 'r' if Lmode & stat.S_IROTH else '-'
678
+ sa += 'w' if Lmode & stat.S_IWOTH else '-'
679
+ sa += 'x' if Lmode & stat.S_IXOTH else '-'
680
+ return sa
681
+ #endfunction
682
+
683
+ #-------------------------------------------------------------------------------
684
+ # GetFileAttr
685
+ #-------------------------------------------------------------------------------
686
+ def GetFileAttr (AFileName: str) -> int:
687
+ """GetFileAttr"""
688
+ #beginfunction
689
+ s = f'GetFileAttr: {AFileName:s}'
690
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
691
+ LResult = 0
692
+
693
+ if FileExists (AFileName) or DirectoryExists (AFileName):
694
+ LStat = os.stat (AFileName)
695
+
696
+ LOSInfo = LUos.TOSInfo ()
697
+ match LOSInfo.system:
698
+ case 'Windows':
699
+ Lmode = LStat.st_mode
700
+ s = f'Lmode: {Lmode:d} {hex (Lmode):s} {bin (Lmode):s} {stat.filemode (Lmode):s}'
701
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
702
+ Lattr = LStat.st_file_attributes
703
+
704
+ # Lattr = win32api.GetFileAttributes (AFileName)
705
+
706
+ s = f'Lattr:{Lattr:d} {hex (Lattr):s} {bin (Lattr):s} {GetFileAttrStr (Lattr):s}'
707
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
708
+ LResult = Lattr
709
+ case 'Linux':
710
+ Lmode = LStat.st_mode
711
+ s = f'Lmode:{Lmode:d} {hex (Lmode):s} {bin (Lmode):s} {GetFileModeStrUnix (Lmode):s}'
712
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
713
+ LResult = Lmode
714
+ case _:
715
+ s = f'Неизвестная система ...'
716
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
717
+ LResult = 0
718
+ #endmatch
719
+ #endif
720
+ return LResult
721
+ #endfunction
722
+
723
+ #-------------------------------------------------------------------------------
724
+ # SetFileAttr
725
+ #-------------------------------------------------------------------------------
726
+ def SetFileAttr (AFileName: str, Aattr: int, AClear: bool):
727
+ """SetFileAttr"""
728
+ #beginfunction
729
+ s = f'SetFileAttr: {Aattr:d} {hex (Aattr):s} {bin (Aattr):s}'
730
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
731
+
732
+ LOSInfo = LUos.TOSInfo ()
733
+ match LOSInfo.system:
734
+ case 'Windows':
735
+ Lattr = GetFileAttr(AFileName)
736
+ s = f'Lattr - current: {Lattr:d} {hex (Lattr):s} {bin (Lattr):s}'
737
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
738
+
739
+ if AClear:
740
+ LattrNew = Lattr & ~Aattr
741
+ s = f'[clear]: {bin (LattrNew):s} {LattrNew:d} {hex (LattrNew):s} {bin (LattrNew):s}'
742
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
743
+ else:
744
+ LattrNew = Lattr | Aflags
745
+ s = f'[set]: {bin (LattrNew):s} {LattrNew:d} {hex (LattrNew):s} {bin (LattrNew):s}'
746
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
747
+ #endif
748
+
749
+ # if os.path.isdir (AFileName):
750
+ # LResult = ctypes.windll.kernel32.SetFileAttributesW (AFileName, LattrNew)
751
+ # else:
752
+ # win32api.SetFileAttributes (AFileName, LattrNew)
753
+ # #endif
754
+
755
+ LResult = ctypes.windll.kernel32.SetFileAttributesW (AFileName, LattrNew)
756
+ case 'Linux':
757
+ raise NotImplementedError('SetFileAttr Linux not implemented ...')
758
+ case _:
759
+ s = f'Неизвестная система ...'
760
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
761
+ #endmatch
762
+ #endfunction
763
+
764
+ #-------------------------------------------------------------------------------
765
+ # SetFileMode
766
+ #-------------------------------------------------------------------------------
767
+ def SetFileMode (AFileName: str, Amode: int):
768
+ """SetFileMode"""
769
+ #beginfunction
770
+ s = f'SetFileMode: {Amode:d} {hex (Amode):s} {bin (Amode):s}'
771
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
772
+
773
+ LOSInfo = LUos.TOSInfo ()
774
+ match LOSInfo.system:
775
+ case 'Windows':
776
+ # Change the file's permissions to writable
777
+ # os.chmod (AFileName, os.W_OK)
778
+ ...
779
+ case 'Linux':
780
+ # os.chflags() method in Python used to set the flags of path to the numeric flags;
781
+ # available in Unix only
782
+ # os.UF_HIDDEN
783
+ if AClear:
784
+ LattrNew = Lattr & ~Aflags
785
+ s = f'SetFileAttr [clear]: {bin (Aflags):s} {LattrNew:d} {hex (LattrNew):s} {bin (LattrNew):s}'
786
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
787
+ else:
788
+ LattrNew = Lattr | Aflags
789
+ s = f'SetFileAttr [set]: {bin (Aflags):s}{LattrNew:d} {hex (LattrNew):s} {bin (LattrNew):s}'
790
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
791
+ #endif
792
+ os.chflags (AFileName, Aflags)
793
+ case _:
794
+ s = f'Неизвестная система ...'
795
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
796
+ #endmatch
797
+ #endfunction
798
+
799
+ #-------------------------------------------------------------------------------
800
+ # SetFileFlags
801
+ #-------------------------------------------------------------------------------
802
+ def SetFileFlags (AFileName: str, Aflags: int):
803
+ """SetFileMode"""
804
+ #beginfunction
805
+ s = f'SetFileMode: {Aflags:d} {hex (Aflags):s} {bin (Aflags):s}'
806
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
807
+
808
+ LOSInfo = lyr.LUos.TOSInfo ()
809
+ match LOSInfo.system:
810
+ case 'Windows':
811
+ raise NotImplementedError('SetFileAttr Windows not implemented...')
812
+ case 'Linux':
813
+ # os.chflags() method in Python used to set the flags of path to the numeric flags;
814
+ # available in Unix only
815
+ # os.UF_HIDDEN
816
+
817
+ Lattr = 0
818
+
819
+ if AClear:
820
+ LflagsNew = Lattr & ~Aflags
821
+ s = f'[clear]: {bin (LflagsNew):s} {LflagsNew:d} {hex (LflagsNew):s} {bin (LflagsNew):s}'
822
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
823
+ else:
824
+ LflagsNew = Lflags | Aflags
825
+ s = f'[set]: {bin (LflagsNew):s} {LflagsNew:d} {hex (LflagsNew):s} {bin (LflagsNew):s}'
826
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
827
+ #endif
828
+ os.chflags (AFileName, LflagsNew)
829
+ case _:
830
+ s = f'Неизвестная система ...'
831
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
832
+ #endmatch
833
+ #endfunction
834
+
835
+ #-------------------------------------------------------------------------------
836
+ # FileDelete
837
+ #-------------------------------------------------------------------------------
838
+ def FileDelete (AFileName: str) -> bool:
839
+ """FileDelete"""
840
+ #beginfunction
841
+ s = f'FileDelete: {AFileName:s}'
842
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
843
+ LResult = True
844
+
845
+ if FileExists (AFileName):
846
+ LOSInfo = LUos.TOSInfo ()
847
+ match LOSInfo.system:
848
+ case 'Windows':
849
+ try:
850
+ Lattr = GetFileAttr (AFileName)
851
+ if Lattr & stat.FILE_ATTRIBUTE_READONLY:
852
+ s = f'Clear ReadOnly ...'
853
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
854
+ LUFile.SetFileAttr (AFileName, stat.FILE_ATTRIBUTE_READONLY, True)
855
+
856
+ # FileSetAttr (FileName, FileGetAttr(FileName) and (faReadOnly xor $FF));
857
+ # Change the file's permissions to writable
858
+ # os.chmod (AFileName, os.W_OK)
859
+
860
+ #endif
861
+ os.remove (AFileName)
862
+ LResult = True
863
+ except:
864
+ s = f'ERROR: FileDelete ...'
865
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
866
+ LResult = False
867
+ #endtry
868
+ case 'Linux':
869
+ raise NotImplementedError('FileDelete Linux not implemented...')
870
+ case _:
871
+ s = f'Неизвестная система ...'
872
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
873
+ #endmatch
874
+ #endif
875
+ return LResult
876
+ #endfunction
877
+
878
+ #-------------------------------------------------------------------------------
879
+ # FileCopy
880
+ #-------------------------------------------------------------------------------
881
+ def FileCopy (AFileNameSource: str, AFileNameDest: str, Overwrite: bool) -> bool:
882
+ """FileCopy"""
883
+ #beginfunction
884
+ s = f'FileCopy: {AFileNameSource:s} -> {AFileNameDest:s}'
885
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
886
+
887
+ if FileExists (AFileNameSource):
888
+
889
+ LDestPath = ExtractFileDir (AFileNameDest)
890
+ if not DirectoryExists (LDestPath):
891
+ ForceDirectories (LDestPath)
892
+ #endif
893
+
894
+ LOSInfo = lyr.LUos.TOSInfo ()
895
+ match LOSInfo.system:
896
+ case 'Windows':
897
+ try:
898
+ # Функция shutil.copy() копирует данные файла и режима доступа к файлу.
899
+ # Другие метаданные, такие как время создания и время изменения файла не сохраняются.
900
+ # Чтобы сохранить все метаданные файла из оригинала, используйте функцию shutil.copy2().
901
+
902
+ # LResult = shutil.copy (AFileNameSource, AFileNameDest) != ''
903
+
904
+ LResult = shutil.copy2 (AFileNameSource, AFileNameDest) != ''
905
+ # LResult = shutil.copy2 (AFileNameSource, LDestPath) != ''
906
+ # shutil.copystat (AFileNameSource, AFileNameDest)
907
+
908
+ LResult = True
909
+ except:
910
+ s = f'ERROR: FileCopy ...'
911
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
912
+ LResult = False
913
+ #endtry
914
+ case 'Linux':
915
+ # unix
916
+ LFileNameSource_stat = os.stat (AFileNameSource)
917
+ Lowner = LFileNameSource_stat [stat.ST_UID]
918
+ Lgroup = LFileNameSource_stat [stat.ST_GID]
919
+ # os.chown (AFileNameDest, Lowner, Lgroup)
920
+ raise NotImplementedError('FileCopy Linux not implemented...')
921
+ case _:
922
+ s = f'Неизвестная система ...'
923
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
924
+ #endmatch
925
+ #endif
926
+ return LResult
927
+ #endfunction
928
+
929
+ #-------------------------------------------------------------------------------
930
+ # FileMove
931
+ #-------------------------------------------------------------------------------
932
+ def FileMove (AFileNameSource: str, APathNameDest: str) -> bool:
933
+ """FileMove"""
934
+ #beginfunction
935
+ s = f'FileMove: {AFileNameSource:s} -> {APathNameDest:s}'
936
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
937
+ LResult = True
938
+ if not LUFile.DirectoryExists(APathNameDest):
939
+ LUFile.ForceDirectories(APathNameDest)
940
+ #endif
941
+ LFileNameSource = ExtractFileName (AFileNameSource)
942
+ LFileNameDest = os.path.join (APathNameDest, LFileNameSource)
943
+ LResult = shutil.move(AFileNameSource, APathNameDest, copy_function=shutil.copy2())
944
+ return LResult
945
+ #endfunction
946
+
947
+ #-------------------------------------------------------------------------------
948
+ # CheckFileNameMask
949
+ #-------------------------------------------------------------------------------
950
+ def CheckFileNameMask (AFileName: str, AMask: str) -> bool:
951
+ """CheckFileNameMask"""
952
+ #beginfunction
953
+ if AMask != '':
954
+ LFileName = AFileName
955
+ # LMask = '^[a-zA-Z0-9]+.py$' # *.py - только латинские буквы и цифры
956
+ # LMask = '^.*..*$' # *.* - все символы
957
+ # LMask = '^.*.py$' # *.py - все символы
958
+ # LMask = '^[\\S ]*.py$' # *.py - все символы включая пробелы
959
+ # LMask = '^[a-zA-Z0-9]*.py$' # *.py - только латинские буквы и цифры
960
+ LMask = AMask
961
+
962
+ #-------------------------------------------------------------------------------
963
+ # regex = re.compile (LMask)
964
+ # Lresult = regex.match(LFileName)
965
+ #-------------------------------------------------------------------------------
966
+ # эквивалентно
967
+ #-------------------------------------------------------------------------------
968
+ Lresult = re.match (LMask, LFileName)
969
+ # Lresult = re.search (LMask, LFileName)
970
+ #-------------------------------------------------------------------------------
971
+ else:
972
+ Lresult = False
973
+ #endif
974
+ return Lresult
975
+ #endfunction
976
+
977
+ #-------------------------------------------------------------------------------
978
+ # CreateTextFile
979
+ #-------------------------------------------------------------------------------
980
+ def CreateTextFile(AFileName: str, AText: str, AEncoding: str):
981
+ """CreateTextFile"""
982
+ #beginfunction
983
+ s = f'CreateTextFile: {AFileName:s} ...'
984
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
985
+
986
+ LEncoding = AEncoding
987
+ if AEncoding == '':
988
+ # LEncoding = LUStrDecode.cCP1251
989
+ LEncoding = cDefaultEncoding
990
+ #endif
991
+ if len(AText) > 0:
992
+ LHandle = open (AFileName, 'w', encoding = LEncoding)
993
+ LHandle.write (AText + '\n')
994
+ LHandle.flush ()
995
+ LHandle.close ()
996
+ else:
997
+ FileDelete (AFileName)
998
+ LHandle = open (AFileName, 'w', encoding = LEncoding)
999
+ LHandle.flush ()
1000
+ LHandle.close ()
1001
+ #endif
1002
+ #endfunction
1003
+
1004
+ #--------------------------------------------------------------------------------
1005
+ # WriteStrToFile
1006
+ #--------------------------------------------------------------------------------
1007
+ def WriteStrToFile (AFileName: str, AStr: str):
1008
+ """WriteStrToFile"""
1009
+ #beginfunction
1010
+ s = f'WriteStrToFile: {AFileName:s} ...'
1011
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
1012
+
1013
+ # Откроет для добавления нового содержимого.
1014
+ # Создаст новый файл для чтения записи, если не найдет с указанным именем.
1015
+ LEncoding = GetFileEncoding (AFileName)
1016
+ if LEncoding == '':
1017
+ # LEncoding = LUStrDecode.cCP1251
1018
+ LEncoding = cDefaultEncoding
1019
+ #endif
1020
+
1021
+ if len(AStr) > 0:
1022
+ LHandle = open (AFileName, 'a+', encoding = LEncoding)
1023
+ LHandle.write (AStr + '\n')
1024
+ LHandle.flush ()
1025
+ LHandle.close ()
1026
+ #endif
1027
+ #endfunction
1028
+
1029
+ #-------------------------------------------------------------------------------
1030
+ # OpenTextFile
1031
+ #-------------------------------------------------------------------------------
1032
+ def OpenTextFile(AFileName: str, AEncoding: str) -> int:
1033
+ """OpenTextFile"""
1034
+ #beginfunction
1035
+ s = f'OpenTextFile: {AFileName:s} ...'
1036
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
1037
+
1038
+ LEncoding = AEncoding
1039
+ if AEncoding == '':
1040
+ # LEncoding = LUStrDecode.cCP1251
1041
+ LEncoding = cDefaultEncoding
1042
+ #endif
1043
+ LHandle = open (AFileName, 'a+', encoding = LEncoding)
1044
+ return LHandle
1045
+ #endfunction
1046
+
1047
+ #-------------------------------------------------------------------------------
1048
+ # WriteTextFile
1049
+ #-------------------------------------------------------------------------------
1050
+ def WriteTextFile(AHandle, AStr: str):
1051
+ """WriteTextFile"""
1052
+ #beginfunction
1053
+ AHandle.write (AStr+'\n')
1054
+ AHandle.flush ()
1055
+ #endfunction
1056
+
1057
+ #-------------------------------------------------------------------------------
1058
+ # CloseTextFile
1059
+ #-------------------------------------------------------------------------------
1060
+ def CloseTextFile (AHandle):
1061
+ """CloseTextFile"""
1062
+ #beginfunction
1063
+ s = f'CloseTextFile ...'
1064
+ LULog.LoggerTOOLS_AddLevel (logging.DEBUG, s)
1065
+
1066
+ AHandle.flush ()
1067
+ AHandle.close ()
1068
+ #endfunction
1069
+
1070
+ #--------------------------------------------------------------------------------
1071
+ # SearchFile
1072
+ #--------------------------------------------------------------------------------
1073
+ def __SearchFile (ADir: str, AFileName: str, AMask: str, AExt: str, ASubDir: bool) -> []:
1074
+ """SearchFile"""
1075
+ #beginfunction
1076
+ LList = []
1077
+ if ADir == '':
1078
+ # искать в текущем каталоге
1079
+ LDir = LUos.GetCurrentDir ()
1080
+ else:
1081
+ # искать в каталоге ADir
1082
+ LDir = ExpandFileName (ADir)
1083
+ #endif
1084
+ Lhere = pathlib.Path (LDir)
1085
+ # print('LDir:', LDir)
1086
+ LFileName = ExtractFileName (AFileName)
1087
+ # print('LFileName:', LFileName)
1088
+ # print('AMask:', AMask)
1089
+ # print('AExt:', AExt)
1090
+
1091
+ if ASubDir:
1092
+ # Searching for LDir Recursively in Python
1093
+ LStr = '**/*'
1094
+ else:
1095
+ # Searching for LDir
1096
+ LStr = '*'
1097
+ #endif
1098
+ # Finding a Single File Recursively
1099
+ # LStr = here.glob ("**/something.txt")
1100
+
1101
+ Lfiles = Lhere.glob (LStr)
1102
+ for item in Lfiles:
1103
+ if item.name == LFileName:
1104
+ # print (item)
1105
+ LList.append (item)
1106
+ else:
1107
+ if CheckFileNameMask (item.name, AMask):
1108
+ # print (item)
1109
+ LList.append (item)
1110
+ else:
1111
+ if CheckFileExt (item, AExt):
1112
+ # print (item)
1113
+ LList.append (item)
1114
+ #endif
1115
+ #endif
1116
+ #endif
1117
+ #endfor
1118
+ return LList
1119
+ #endfunction
1120
+
1121
+ #--------------------------------------------------------------------------------
1122
+ # SearchFileDirs
1123
+ #--------------------------------------------------------------------------------
1124
+ def SearchFileDirs (ADirs: [], AFileName: str, AMask: str, AExt: str, ASubDir: bool) -> []:
1125
+ """SearchFileDirs"""
1126
+ #beginfunction
1127
+ LListDirs = []
1128
+ for LDir in ADirs:
1129
+ # print('LDir:', LDir)
1130
+ LList = __SearchFile (LDir, AFileName, AMask, AExt, ASubDir)
1131
+ if len(LList) > 0:
1132
+ LListDirs += LList
1133
+ #endif
1134
+ #endfor
1135
+ return LListDirs
1136
+ #endfunction
1137
+
1138
+ #--------------------------------------------------------------------------------
1139
+ # GetWindowsPath
1140
+ #--------------------------------------------------------------------------------
1141
+ def GetWindowsPath (APath: str) -> str:
1142
+ """GetWindowsPat"""
1143
+ #beginfunction
1144
+ LResult = pathlib.WindowsPath (APath)
1145
+ return LResult
1146
+ #endfunction
1147
+
1148
+ #--------------------------------------------------------------------------------
1149
+ # GetPureWindowsPath
1150
+ #--------------------------------------------------------------------------------
1151
+ def GetPureWindowsPath (APath: str) -> str:
1152
+ """GetPureWindowsPath"""
1153
+ #beginfunction
1154
+ LResult = pathlib.PureWindowsPath (APath)
1155
+ return LResult
1156
+ #endfunction
1157
+
1158
+ #-------------------------------------------------------------------------------
1159
+ # main
1160
+ #-------------------------------------------------------------------------------
1161
+ def main ():
1162
+ #beginfunction
1163
+ print('main LUFile.py ...')
1164
+ #endfunction
1165
+
1166
+ #------------------------------------------
1167
+ # module
1168
+ #------------------------------------------
1169
+ #beginmodule
1170
+ if __name__ == "__main__":
1171
+ main()
1172
+ #endif
1173
+
1174
+ #endmodule