soup-files 1.0.1__py3-none-any.whl → 1.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.
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.4
2
+ Name: soup_files
3
+ Version: 1.2
4
+ Summary: soup_files
5
+ Author: Bruno Chaves
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+
9
+ # soup_files
10
+
@@ -0,0 +1,4 @@
1
+ soup_files-1.2.dist-info/METADATA,sha256=MLZFMkC5m0e76krmmDZkyRCF2S3hsrHbRLFiTlWUpyg,172
2
+ soup_files-1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
3
+ soup_files-1.2.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
4
+ soup_files-1.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1 @@
1
+
soup_files/__init__.py DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- from .soup_files import *
soup_files/soup_files.py DELETED
@@ -1,403 +0,0 @@
1
- #!/usr/bin/env python3
2
- #
3
- """
4
- Esté módulo serve para manipulação de arquivos, diretórios e documentos
5
- entre outros. Não depende de módulos externos apenas de builtins e stdlib.
6
- """
7
- from __future__ import annotations
8
- from typing import List, Dict
9
- from enum import Enum
10
- import os
11
- import json
12
- import platform
13
- from pathlib import Path
14
- from hashlib import md5
15
-
16
- __version__ = '1.0'
17
-
18
- # Windows / Linux / ...
19
- KERNEL_TYPE = platform.system()
20
-
21
- class LibraryDocs(Enum):
22
- IMAGE = ['.png', '.jpg', '.jpeg', '.svg']
23
- PDF = ['.pdf']
24
- DOCUMENTS = ['.png', '.jpg', '.jpeg', '.svg', '.pdf']
25
- #
26
- EXCEL = ['.xlsx']
27
- CSV = ['.csv', '.txt']
28
- #
29
- SHEET = ['.csv', '.txt', '.xlsx', '.xls']
30
- JSON = ['.json']
31
- #
32
- ALL_DOCUMENTS = [
33
- '.png', '.jpg', '.jpeg', '.svg',
34
- '.csv', '.txt', '.xlsx',
35
- '.pdf',
36
- '.json',
37
- ]
38
- #
39
- ALL = None
40
-
41
-
42
- class File(object):
43
- def __init__(self, filename:str):
44
- if os.path.isdir(filename):
45
- raise ValueError(f'{__class__.__name__} File() não pode ser um diretório.')
46
- self.filename:str = os.path.abspath(filename)
47
- self.__path:Path = Path(self.filename)
48
-
49
- @property
50
- def path(self) -> Path:
51
- return self.__path
52
-
53
- @path.setter
54
- def path(self, new:Path):
55
- if not isinstance(new, Path):
56
- return
57
- self.__path = new
58
-
59
- def __eq__(self, value):
60
- if not isinstance(value, File):
61
- return NotImplemented
62
- return self.absolute() == value.absolute()
63
-
64
- def __hash__(self):
65
- return self.absolute().__hash__()
66
-
67
- def is_image(self) -> bool:
68
- try:
69
- return True if self.extension() in LibraryDocs.IMAGE.value else False
70
- except:
71
- return False
72
-
73
- def is_pdf(self) -> bool:
74
- try:
75
- return True if self.extension() in LibraryDocs.PDF.value else False
76
- except:
77
- return False
78
-
79
- def is_excel(self) -> bool:
80
- try:
81
- return True if self.extension() in LibraryDocs.EXCEL.value else False
82
- except:
83
- return False
84
-
85
- def is_csv(self) -> bool:
86
- try:
87
- return True if self.extension() in LibraryDocs.CSV.value else False
88
- except:
89
- return False
90
-
91
- def is_sheet(self) -> bool:
92
- try:
93
- return True if self.extension() in LibraryDocs.SHEET.value else False
94
- except:
95
- return False
96
-
97
- def update_extension(self, e:str) -> File:
98
- """
99
- Retorna uma instância de File() no mesmo diretório com a nova
100
- extensão informada.
101
- """
102
- current = self.extension()
103
- full_path = self.absolute().replace(current, '')
104
- return File(os.path.join(f'{full_path}{e}'))
105
-
106
- def get_text(self) -> str | None:
107
- try:
108
- return self.__path.read_text()
109
- except Exception as e:
110
- print(e)
111
- return None
112
-
113
- def write_string(self, s:str):
114
- self.__path.write_text(s)
115
-
116
- def write_list(self, items:List[str]):
117
- # Abrindo o arquivo em modo de escrita
118
- with open(self.filename, "w", encoding="utf-8") as file:
119
- for string in items:
120
- file.write(string + "\n") # Adiciona uma quebra de linha após cada string
121
-
122
- def name(self):
123
- e = self.extension()
124
- if (e is None) or (e == ''):
125
- return os.path.basename(self.filename)
126
- return os.path.basename(self.filename).replace(e, '')
127
-
128
- def name_absolute(self) -> str:
129
- e = self.extension()
130
- if (e is None) or (e == ''):
131
- return self.filename
132
- return self.filename.replace(e, '')
133
-
134
- def extension(self) -> str:
135
- return self.__path.suffix
136
-
137
- def dirname(self) -> str:
138
- return os.path.dirname(self.filename)
139
-
140
- def basename(self) -> str:
141
- return os.path.basename(self.filename)
142
-
143
- def exists(self) -> bool:
144
- return self.__path.exists()
145
-
146
- def absolute(self) -> str:
147
- return self.filename
148
-
149
- def size(self):
150
- return os.path.getsize(self.filename)
151
-
152
- def md5(self) -> str | None:
153
- """Retorna a hash md5 de um arquivo se ele existir no disco."""
154
- if not self.path.exists():
155
- return None
156
- _hash_md5 = md5()
157
- with open(self.absolute(), "rb") as f:
158
- for _block in iter(lambda: f.read(4096), b""):
159
- _hash_md5.update(_block)
160
- return _hash_md5.hexdigest()
161
-
162
-
163
- class Directory(object):
164
- def __init__(self, dirpath:str):
165
- self.dirpath:str = os.path.abspath(dirpath)
166
- self.path:Path = Path(self.dirpath)
167
-
168
- def __eq__(self, value):
169
- if not isinstance(value, Directory):
170
- return NotImplemented
171
- return self.absolute() == value.absolute()
172
-
173
- def __hash__(self):
174
- return self.absolute().__hash__()
175
-
176
- def iterpaths(self) -> List[Path]:
177
- return self.path.rglob('*')
178
-
179
- def content_files(self) -> List[File]:
180
- _paths = self.iterpaths()
181
- values = []
182
- for p in _paths:
183
- if p.is_file():
184
- values.append(
185
- File(
186
- os.path.abspath(p.absolute())
187
- )
188
- )
189
- return values
190
-
191
- def basename(self) -> str:
192
- return os.path.basename(self.absolute())
193
-
194
- def mkdir(self):
195
- try:
196
- os.makedirs(self.absolute())
197
- except:
198
- pass
199
-
200
- def absolute(self) -> str:
201
- return self.dirpath
202
-
203
- def concat(self, d:str, create:bool=False) -> Directory:
204
- if create == True:
205
- try:
206
- os.makedirs(os.path.join(self.absolute(), d))
207
- except:
208
- pass
209
- return Directory(
210
- os.path.join(self.absolute(), d)
211
- )
212
-
213
- def parent(self) -> Directory:
214
- return Directory(
215
- os.path.abspath(self.path.parent)
216
- )
217
-
218
- def join_file(self, name:str) -> File:
219
- return File(
220
- os.path.join(self.absolute(), name)
221
- )
222
-
223
-
224
- class InputFiles(object):
225
- """
226
- Obeter uma lista de arquivos/documentos do diretório informado.
227
- """
228
- def __init__(self, d:Directory, *, maxFiles:int=5000):
229
- if not isinstance(d, Directory):
230
- raise ValueError(f'{__class__.__name__}\nUse: Directory(), não {type(d)}')
231
- self.input_dir:Directory = d
232
- self.maxFiles:int = maxFiles
233
-
234
- def get_files_with(self, *, infile:str, sort:bool=True) -> List[File]:
235
- """
236
- Retorna arquivos que contém a ocorrência (infile) no nome absoluto.
237
- """
238
- content_files:List[File] = []
239
- count:int = 0
240
- paths = self.input_dir.iterpaths()
241
- for file in paths:
242
- if not file.is_file():
243
- continue
244
- if infile in os.path.abspath(file.absolute()):
245
- content_files.append(
246
- File(os.path.abspath(file.absolute()))
247
- )
248
- count += 1
249
- if count >= self.maxFiles:
250
- break
251
- return content_files
252
-
253
- def get_files(self, *, file_type:LibraryDocs = LibraryDocs.ALL_DOCUMENTS, sort:bool=True) -> List[File]:
254
- """
255
- Retorna uma lista de File() de acordo com o tipo de arquivo
256
- especificado.
257
- - LibraryDocs.ALL_DOCUMENTS => Retorna todos os documentos do diretório.
258
- - LibraryDocs.EXCEL => Retorna arquivos que são planilhas excel.
259
- - ...
260
-
261
- """
262
- _paths = self.input_dir.iterpaths()
263
- _all_files = []
264
- count:int = 0
265
- if file_type == LibraryDocs.ALL:
266
- # Todos os tipos de arquivos
267
- for p in _paths:
268
- if not p.is_file():
269
- continue
270
- _all_files.append(File(p.absolute()))
271
- count += 1
272
- if count >= self.maxFiles:
273
- break
274
- else:
275
- # Arquivos especificados em LibraryDocs
276
- for p in _paths:
277
- if not p.is_file():
278
- continue
279
- if (p.suffix is None) or (p.suffix == ''):
280
- continue
281
- if p.suffix in file_type.value:
282
- _all_files.append(File(p.absolute()))
283
- count += 1
284
- if count >= self.maxFiles:
285
- break
286
- if sort == True:
287
- _all_files.sort(key=File.absolute)
288
- return _all_files
289
-
290
-
291
- class JsonData(object):
292
- """
293
- Representação de um dado JSON apartir de uma string python.
294
- """
295
- def __init__(self, string:str):
296
- if not isinstance(string, str):
297
- raise ValueError(f'{__class__.__name__} o JSON informado precisa ser do tipo string, não {type(string)}')
298
- self.jsonString:str = string
299
-
300
- def is_null(self) -> bool:
301
- if (self.jsonString is None) or (self.jsonString == ''):
302
- return True
303
- return False
304
-
305
- def to_string(self) -> str:
306
- return self.jsonString
307
-
308
- def to_dict(self) -> Dict[str, object]:
309
- """
310
- Exportar/Converter o dado atual em um dicionário python.
311
- """
312
- return json.loads(self.jsonString)
313
-
314
- def to_file(self, f:File):
315
- """Exportar o dado atual para um arquivo .json"""
316
- _data:str = json.loads(self.jsonString)
317
- with open(f.absolute(), "w", encoding="utf-8") as file:
318
- json.dump(_data, file, indent=4, ensure_ascii=False)
319
-
320
-
321
- class JsonConvert(object):
322
- """
323
- Conversão de um dado JSON em dados python
324
- """
325
- def __init__(self, jsonData:JsonData):
326
- self.jsonData:JsonData = jsonData
327
-
328
- def to_json_data(self) -> JsonData:
329
- return self.jsonData
330
-
331
- @classmethod
332
- def from_file(cls, file:File) -> JsonConvert:
333
- """
334
- Gerar um dado JsonData apartir de um arquivo .json
335
- """
336
- # Ler o arquivo e carregar o JSON em um dicionário Python
337
- data = None
338
- try:
339
- with open(file.absolute(), "r", encoding="utf-8") as fp:
340
- data:str = json.load(fp)
341
- except Exception as e:
342
- print(f'{__class__.__name__}\n{e}')
343
- return cls(JsonData(''))
344
- else:
345
- #return JsonData(json.dumps(data, indent=4, ensure_ascii=False, sort_keys=True))
346
- return cls(JsonData(json.dumps(data, indent=4, ensure_ascii=False, sort_keys=True)))
347
-
348
- @classmethod
349
- def from_string_json(cls, data:str) -> JsonConvert:
350
- """
351
- Gerar um dado JsonData apartir de uma string.
352
- """
353
- json_string = json.dumps(data, indent=4, ensure_ascii=False, sort_keys=True)
354
- return cls(JsonData(json_string))
355
-
356
- @classmethod
357
- def from_dict(cls, data:Dict[str, object]) -> JsonConvert:
358
- """
359
- Converte um dicionário em objeto JSON/JsonData.
360
- """
361
- if not isinstance(data, dict):
362
- raise ValueError(f'{__class__.__name__} Informe um JSON em formato dict, não {type(data)}')
363
- json_string = json.dumps(data, indent=4, ensure_ascii=False, sort_keys=True)
364
- return cls(JsonData(json_string))
365
-
366
-
367
- class UserFileSystem(object):
368
- """
369
- Diretórios comuns para cache e configurações de usuário.
370
- """
371
- def __init__(self, base_home:Directory=None):
372
- if base_home is None:
373
- self.baseHome:Directory = Directory(os.path.abspath(Path().home()))
374
- elif isinstance(base_home, Directory):
375
- self.baseHome:Directory = base_home
376
- else:
377
- raise ValueError(f'{__class__.__name__}\nUse:Directory(), não {type(base_home)}')
378
- self.userDownloads:Directory = self.baseHome.concat('Downloads', create=True)
379
- self.userVarDir:Directory = self.baseHome.concat('var', create=True)
380
-
381
- def config_dir(self) -> Directory:
382
- return self.userVarDir.concat('config', create=True)
383
-
384
- def cache_dir(self) -> Directory:
385
- return self.userVarDir.concat('cache', create=True)
386
-
387
-
388
- class UserAppDir(object):
389
- """
390
- Diretório comun para cache e configurações do aplicativo.
391
- """
392
- def __init__(self, appname:str, *, user_file_system:UserFileSystem=UserFileSystem()):
393
- self.appname = appname
394
- self.userFileSystem:UserFileSystem = user_file_system
395
- self.workspaceDirApp:Directory = self.userFileSystem.userDownloads.concat(self.appname, create=True)
396
- self.installDir:Directory = self.userFileSystem.userVarDir.concat('opt').concat(self.appname, create=True)
397
-
398
- def cache_dir_app(self) -> Directory:
399
- return self.userFileSystem.cache_dir().concat(self.appname, create=True)
400
-
401
- def config_dir_app(self) -> Directory:
402
- return self.userFileSystem.config_dir().concat(self.appname, create=True)
403
-
@@ -1,19 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: soup-files
3
- Version: 1.0.1
4
- Summary: Leitura e manipulação de arquivos
5
- Author: Bruno
6
- License: MIT
7
- Requires-Python: >=3.11
8
- Description-Content-Type: text/markdown
9
-
10
- # file-utils
11
-
12
- # Uso
13
- from soup_files import File, Directory
14
-
15
- filename:str = 'path/to/file'
16
- dirpath:str = 'path/to/dir'
17
-
18
- f = File(filename)
19
- d = Directory(dirpath)
@@ -1,6 +0,0 @@
1
- soup_files/__init__.py,sha256=O9oM7fGDdnzHAhpsxXSqO_SH2yMn2O_6t0n2EyyzOFY,49
2
- soup_files/soup_files.py,sha256=JhigMvXDorHa_2io-kJSTmX8Z2U7B8MoGV5NOj9mXds,12891
3
- soup_files-1.0.1.dist-info/METADATA,sha256=ixYhA3xag-tz-mIwO2cegFzOHaFZ08fKR2DN9EoSG-4,352
4
- soup_files-1.0.1.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
5
- soup_files-1.0.1.dist-info/top_level.txt,sha256=CBSaCdIqL_Rlkr74APmmI0kXkPK9pVf6HTlOPZ-Kk4E,11
6
- soup_files-1.0.1.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- soup_files