iniUts 1.2.1__tar.gz → 1.3.0__tar.gz

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.
@@ -28,4 +28,9 @@ Change Log
28
28
 
29
29
  1.0.7 (2023-04-28)
30
30
  ------------------
31
- - changing enviornment
31
+ - changing enviornment
32
+
33
+
34
+ 1.3.0 (2025-12-01)
35
+ ------------------
36
+ - encription and decription
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iniUts
3
- Version: 1.2.1
3
+ Version: 1.3.0
4
4
  Summary: Ini file manipulator
5
5
  Home-page:
6
6
  Author: Melque Lima
@@ -277,3 +277,8 @@ Change Log
277
277
  1.0.7 (2023-04-28)
278
278
  ------------------
279
279
  - changing enviornment
280
+
281
+
282
+ 1.3.0 (2025-12-01)
283
+ ------------------
284
+ - encription and decription
@@ -1,4 +1,4 @@
1
1
  pip3 install setuptools twine
2
2
  python setup.py sdist
3
3
  twine upload --config-file .\.pypirc --repository-url https://upload.pypi.org/legacy/ dist/*
4
- twine upload --config-file .\.pypirc .\dist\iniUts-1.1.
4
+ twine upload --config-file .\.pypirc .\dist\iniUts-1.1.
@@ -3,6 +3,8 @@ from dataclasses import dataclass
3
3
  from datetime import datetime
4
4
  import re
5
5
  import os
6
+ import types
7
+ from secret import decrypt, encrypt
6
8
 
7
9
  class envar():
8
10
  def __init__(self,key:str,default:str=None):
@@ -18,14 +20,46 @@ class envar():
18
20
  raise Exception(f"envar '{self.key}' not found!")
19
21
  return value
20
22
 
21
-
23
+
24
+ def save(self):
25
+ ini = self.__INIUTS__
26
+ types_to_str = [str,int,float,bool]
27
+ is_str = lambda t: any([t == x for x in types_to_str])
28
+
29
+ iniProd = IniUts(ini.prd_file)
30
+ iniDev = IniUts(ini.dev_file) if ini.dev_file else None
31
+
32
+
33
+ for k,t in self.__annotations__.items():
34
+ if k in self.__ENVARS__: continue
35
+
36
+ if is_str(t):
37
+ value = str(getattr(self,k))
38
+ elif t == tuple:
39
+ value = getattr(self,k)
40
+ delimiter = ini.delimiters[f"{str(self)}_{k}"]
41
+ value = delimiter.join(value)
42
+ elif t == datetime:
43
+ value = getattr(self,k)
44
+ dateFormat = ini.dateFormats[f"{str(self)}_{k}"]
45
+ value = value.strftime(dateFormat)
46
+
47
+ if k in self.__CRYPTED_KEYS__:
48
+ k = "&_" + k
49
+ value = encrypt(value,ini.encription_key)
50
+
51
+ if not ini.in_prd and k in iniDev.getKeys(self.__SECTION__):
52
+ iniDev.write(self.__SECTION__,k,value)
53
+ else:
54
+ iniProd.write(self.__SECTION__,k,value)
22
55
 
23
56
 
24
57
  class IniUts():
25
- def __init__(self,ini_prd,ini_dev=None,in_prd=True):
58
+ def __init__(self,ini_prd,ini_dev=None,in_prd=True,encription_key=None):
26
59
  self.prd_file = ini_prd
27
60
  self.dev_file = ini_dev
28
61
  self.in_prd = in_prd
62
+ self.encription_key = encription_key
29
63
  self.delimiters = {}
30
64
  self.dateFormats = {}
31
65
  self.dev_sections = []
@@ -91,6 +125,13 @@ class IniUts():
91
125
 
92
126
  return [k for k in config[section]]
93
127
 
128
+ def to_dict(self):
129
+ sections = self.getSections()
130
+ result = {}
131
+ for sect in sections:
132
+ result[sect] = self.Section2Dict(sect)
133
+ return result
134
+
94
135
  def Section2Dict(self,section,empty_as_null=False,fileIni=None):
95
136
  _file = self.dev_file if not self.in_prd and section in self.dev_sections else self.prd_file
96
137
  config = cp.RawConfigParser(allow_no_value=True)
@@ -102,6 +143,9 @@ class IniUts():
102
143
 
103
144
  def format_data(self,dtClass,k,v):
104
145
  cls = dtClass.__annotations__[k]
146
+ if k in dtClass.__CRYPTED_KEYS__:
147
+ v = decrypt(v,self.encription_key)
148
+
105
149
  if cls == tuple:
106
150
  name = f"{str(dtClass)}_{k}"
107
151
  if not name in self.delimiters:
@@ -141,6 +185,28 @@ class IniUts():
141
185
 
142
186
  dtClass = self.setup_initial_values(dtClass)
143
187
 
188
+ dtClass.save = types.MethodType(save, dtClass)
189
+ dtClass.__SECTION__ = section
190
+ dtClass.__ENVARS__ = []
191
+ dtClass.__INIUTS__ = self
192
+ dtClass.__CRYPTED_KEYS__ = [ x.replace("&_","") for x in dt2 if "&_" in x ]
193
+ dt2 = { x.replace("&_",""):dt2[x] for x in dt2 }
194
+ dt = { x.replace("&_",""):dt[x] for x in dt }
195
+
196
+ #ENCRIPTA VARIAVEIS INICIAIS
197
+ for k in dtClass.__CRYPTED_KEYS__:
198
+ # ENCRIPTA VARIAVEIS INICIAIS NO ARQUIVO DE DEV
199
+ if k in dt.keys() and dt[k].startswith('&_') and not self.in_prd:
200
+ dt[k] = encrypt(dt[k].replace('&_',''),self.encription_key)
201
+ IniUts(self.dev_file).write(section,"&_" + k,dt[k])
202
+
203
+ # ENCRIPTA VARIAVEIS INICIAIS NO ARQUIVO DE PRD
204
+ if k in dt2.keys() and dt2[k].startswith('&_'):
205
+ dt2[k] = encrypt(dt2[k].replace('&_',''),self.encription_key)
206
+ IniUts(self.prd_file).write(section,"&_" + k,dt2[k])
207
+
208
+
209
+
144
210
  #VALIDA AS KEYS NO INI DE DEV
145
211
  for k, v in dt.items():
146
212
  if not k in dtClass.__annotations__:
@@ -162,6 +228,7 @@ class IniUts():
162
228
  if isinstance(getattr(dtClass,k),envar):
163
229
  v = getattr(dtClass,k).get_value()
164
230
  setattr(dtClass, k, v)
231
+ dtClass.__ENVARS__.append(k)
165
232
  continue
166
233
  if not skip_missing:
167
234
  raise Exception(f"Cound not find '{k}' keys at section '{section}' in ini file")
@@ -173,6 +240,7 @@ class IniUts():
173
240
  if isinstance(getattr(dtClass,k),envar):
174
241
  v = getattr(dtClass,k).get_value()
175
242
  setattr(dtClass, k, v)
243
+ dtClass.__ENVARS__.append(k)
176
244
  continue
177
245
  if not skip_missing and MissingKeysFromClass(dt):
178
246
  raise Exception(f"Cound not find '{k}' keys at section '{section}' in ini file")
@@ -0,0 +1,52 @@
1
+ import os
2
+ import base64
3
+ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
4
+ from cryptography.hazmat.primitives import hashes
5
+
6
+ # Retorna 32 bytes (SHA-256) da senha (usada como chave final)
7
+ def _derive_key_from_password(password: str) -> bytes:
8
+ # Hash SHA-256 da senha -> chave de 32 bytes
9
+ digest = hashes.Hash(hashes.SHA256())
10
+ digest.update(password.encode('utf-8'))
11
+ return digest.finalize()
12
+
13
+ # Encripta texto (str) com senha (str). Retorna string Base64 contendo: nonce + ciphertext + tag
14
+ def encrypt(text: str, password: str) -> str:
15
+ """
16
+ // text: texto em claro
17
+ // password: senha/segredo que será transformado em hash (SHA-256) para usar como chave
18
+ // retorna: base64(nonce || ciphertext || tag)
19
+ """
20
+ key = _derive_key_from_password(password) # 32 bytes
21
+ aesgcm = AESGCM(key)
22
+ nonce = os.urandom(12) # nonce/IV recomendado para GCM: 12 bytes
23
+ plaintext = text.encode('utf-8')
24
+ ciphertext = aesgcm.encrypt(nonce, plaintext, None) # dados adicionais (AAD) = None
25
+ payload = nonce + ciphertext # armazenar nonce + ciphertext (ciphertext já inclui tag no AESGCM)
26
+ return base64.b64encode(payload).decode('utf-8')
27
+
28
+ # Decripta string Base64 gerada por encrypt()
29
+ def decrypt(token_b64: str, password: str) -> str:
30
+ """
31
+ // token_b64: string retornada por encrypt (base64(nonce||ciphertext||tag))
32
+ // password: mesma senha usada na encriptação
33
+ // retorna: texto em claro (str) ou levanta exceção se inválido
34
+ """
35
+ key = _derive_key_from_password(password)
36
+ data = base64.b64decode(token_b64)
37
+ if len(data) < 12:
38
+ raise ValueError("Payload inválido")
39
+ nonce = data[:12]
40
+ ciphertext = data[12:]
41
+ aesgcm = AESGCM(key)
42
+ plaintext = aesgcm.decrypt(nonce, ciphertext, None)
43
+ return plaintext.decode('utf-8')
44
+
45
+ # Exemplo de uso:
46
+ if __name__ == "__main__":
47
+ senha = "minha-senha-secreta"
48
+ texto = "mensagem ultra secreta"
49
+ cifrado = encrypt(texto, senha)
50
+ print("Cifrado:", cifrado)
51
+ dec = decrypt(cifrado, senha)
52
+ print("Decifrado:", dec)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iniUts
3
- Version: 1.2.1
3
+ Version: 1.3.0
4
4
  Summary: Ini file manipulator
5
5
  Home-page:
6
6
  Author: Melque Lima
@@ -277,3 +277,8 @@ Change Log
277
277
  1.0.7 (2023-04-28)
278
278
  ------------------
279
279
  - changing enviornment
280
+
281
+
282
+ 1.3.0 (2025-12-01)
283
+ ------------------
284
+ - encription and decription
@@ -6,6 +6,7 @@ commands.txt
6
6
  run.py
7
7
  setup.py
8
8
  iniUts/__init__.py
9
+ iniUts/secret.py
9
10
  iniUts.egg-info/PKG-INFO
10
11
  iniUts.egg-info/SOURCES.txt
11
12
  iniUts.egg-info/dependency_links.txt
@@ -7,7 +7,7 @@ from iniUts import *
7
7
  load_dotenv()
8
8
 
9
9
  ini = IniUts('prd_config.ini')
10
- ini = IniUts('prd_config.ini','dev_config.ini',in_prd=True)
10
+ ini = IniUts('prd_config.ini','dev_config.ini',in_prd=True,encription_key="asdoajhsdoiuayhsoidhasoidhalijksdhaioshdioaws")
11
11
 
12
12
  #TODAS AS CHAVES DE DEV DEVE CONTER EM PRD
13
13
 
@@ -21,6 +21,11 @@ class Person():
21
21
  friends: tuple = ','
22
22
  dob : datetime = "%Y-%m-%d"
23
23
 
24
+ Person.NAME = "Heitor"
25
+ Person.friends = ("friend1","friend2","friend3","friend4")
26
+ Person.save()
27
+
28
+
24
29
 
25
30
  pass
26
31
  # pass
@@ -10,7 +10,7 @@ classifiers = [
10
10
 
11
11
  setup(
12
12
  name='iniUts',
13
- version='1.2.1',
13
+ version='1.3.0',
14
14
  description='Ini file manipulator',
15
15
  long_description=open('README.md').read() + '\n\n' + open('CHANGELOG.txt').read(),
16
16
  long_description_content_type='text/markdown',
File without changes
File without changes
File without changes
File without changes