csc-cia-stne 0.0.43__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- csc_cia_stne/__init__.py +89 -0
- csc_cia_stne/bc_correios.py +529 -0
- csc_cia_stne/bc_sta.py +416 -0
- csc_cia_stne/email.py +239 -0
- csc_cia_stne/gcp_bigquery.py +224 -0
- csc_cia_stne/google_drive.py +268 -0
- csc_cia_stne/karavela.py +135 -0
- csc_cia_stne/logger_json.py +92 -0
- csc_cia_stne/logger_rich.py +249 -0
- csc_cia_stne/provio.py +103 -0
- csc_cia_stne/servicenow.py +689 -0
- csc_cia_stne/slack.py +227 -0
- csc_cia_stne/stne_admin.py +597 -0
- csc_cia_stne/utilitarios/__init__.py +9 -0
- csc_cia_stne/utilitarios/functions/__init__.py +14 -0
- csc_cia_stne/utilitarios/functions/func_b64.py +50 -0
- csc_cia_stne/utilitarios/functions/func_converters.py +18 -0
- csc_cia_stne/utilitarios/functions/func_recriar_pastas.py +29 -0
- csc_cia_stne/utilitarios/functions/func_settings.py +66 -0
- csc_cia_stne/utilitarios/functions/func_titulo.py +141 -0
- csc_cia_stne/utilitarios/validations/GcpBigQueryValidator.py +133 -0
- csc_cia_stne/utilitarios/validations/GoogleDriveValidator.py +144 -0
- csc_cia_stne/utilitarios/validations/ServiceNowValidator.py +403 -0
- csc_cia_stne/utilitarios/validations/__init__.py +3 -0
- csc_cia_stne-0.0.43.dist-info/LICENCE +21 -0
- csc_cia_stne-0.0.43.dist-info/METADATA +33 -0
- csc_cia_stne-0.0.43.dist-info/RECORD +29 -0
- csc_cia_stne-0.0.43.dist-info/WHEEL +5 -0
- csc_cia_stne-0.0.43.dist-info/top_level.txt +1 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
import logging
|
2
|
+
from pythonjsonlogger import jsonlogger
|
3
|
+
|
4
|
+
def setup_json_logger():
|
5
|
+
|
6
|
+
def add_log_level(level_name, level_num, method_name=None):
|
7
|
+
"""
|
8
|
+
Adiciona um log level
|
9
|
+
|
10
|
+
Parâmetros:
|
11
|
+
level_name (str): Nome do level
|
12
|
+
level_num (int): Número do level
|
13
|
+
"""
|
14
|
+
if not method_name:
|
15
|
+
|
16
|
+
method_name = level_name.lower()
|
17
|
+
|
18
|
+
if hasattr(logging, level_name):
|
19
|
+
|
20
|
+
raise AttributeError('{} already defined in logging module'.format(level_name))
|
21
|
+
|
22
|
+
if hasattr(logging, method_name):
|
23
|
+
|
24
|
+
raise AttributeError('{} already defined in logging module'.format(method_name))
|
25
|
+
|
26
|
+
if hasattr(logging.getLoggerClass(), method_name):
|
27
|
+
|
28
|
+
raise AttributeError('{} already defined in logger class'.format(method_name))
|
29
|
+
|
30
|
+
def log_for_level(self, message, *args, **kwargs):
|
31
|
+
|
32
|
+
if self.isEnabledFor(level_num):
|
33
|
+
|
34
|
+
#self._log(level_num, message, args, **kwargs)
|
35
|
+
self._log(level_num, message, args, **{**kwargs, "stacklevel": 2})
|
36
|
+
|
37
|
+
def log_to_root(message, *args, **kwargs):
|
38
|
+
|
39
|
+
logging.log(level_num, message, *args, **kwargs)
|
40
|
+
|
41
|
+
logging.addLevelName(level_num, level_name)
|
42
|
+
setattr(logging, level_name, level_num)
|
43
|
+
setattr(logging.getLoggerClass(), method_name, log_for_level)
|
44
|
+
setattr(logging, method_name, log_to_root)
|
45
|
+
|
46
|
+
if not 'SUCCESS' in logging._nameToLevel:
|
47
|
+
add_log_level("SUCCESS",21)
|
48
|
+
logger = logging.getLogger(__name__)
|
49
|
+
logger.setLevel(logging.INFO)
|
50
|
+
|
51
|
+
# Remove handlers anteriores, se houver
|
52
|
+
if logger.hasHandlers():
|
53
|
+
logger.handlers.clear()
|
54
|
+
|
55
|
+
log_handler = logging.StreamHandler()
|
56
|
+
formatter = jsonlogger.JsonFormatter(
|
57
|
+
fmt='%(asctime)s %(levelname)s %(name)s %(message)s %(pathname)s %(lineno)d %(exc_info)s %(stack_info)s %(funcName)s %(module)s',
|
58
|
+
json_ensure_ascii=False
|
59
|
+
)
|
60
|
+
log_handler.setFormatter(formatter)
|
61
|
+
logger.addHandler(log_handler)
|
62
|
+
|
63
|
+
# Capturando logs da biblioteca FastAPI/Uvicorn
|
64
|
+
#uvicorn_logger = logging.getLogger("uvicorn")
|
65
|
+
#uvicorn_logger.handlers = logger.handlers
|
66
|
+
#uvicorn_logger.setLevel(logging.INFO)
|
67
|
+
|
68
|
+
#uvicorn_error_logger = logging.getLogger("uvicorn.error")
|
69
|
+
#uvicorn_error_logger.handlers = logger.handlers
|
70
|
+
#uvicorn_error_logger.setLevel(logging.INFO)
|
71
|
+
|
72
|
+
#uvicorn_access_logger = logging.getLogger("uvicorn.access")
|
73
|
+
#uvicorn_access_logger.handlers = logger.handlers
|
74
|
+
#uvicorn_access_logger.setLevel(logging.INFO)
|
75
|
+
|
76
|
+
return logger
|
77
|
+
|
78
|
+
# Chama a função para configurar o logger
|
79
|
+
#logger = setup_json_logger()
|
80
|
+
|
81
|
+
def get_logger():
|
82
|
+
"""
|
83
|
+
logger = logging.getLogger("my_json_logger")
|
84
|
+
if not logger.hasHandlers(): # Evita configurar múltiplas vezes
|
85
|
+
handler = logging.StreamHandler()
|
86
|
+
formatter = logging.Formatter(json.dumps({"level": "%(levelname)s", "message": "%(message)s"}))
|
87
|
+
handler.setFormatter(formatter)
|
88
|
+
logger.setLevel(logging.DEBUG)
|
89
|
+
logger.addHandler(handler)
|
90
|
+
"""
|
91
|
+
logger = setup_json_logger()
|
92
|
+
return logger
|
@@ -0,0 +1,249 @@
|
|
1
|
+
import logging
|
2
|
+
from rich.logging import RichHandler
|
3
|
+
from rich.theme import Theme
|
4
|
+
from rich.console import Console
|
5
|
+
from rich.traceback import install
|
6
|
+
import re
|
7
|
+
import traceback
|
8
|
+
import os
|
9
|
+
"""
|
10
|
+
# Instala formatações de exception da biblioteca Rich
|
11
|
+
install()
|
12
|
+
|
13
|
+
# Definindo o nível de log baseado nas configurações
|
14
|
+
if os.getenv('log_level') is None:
|
15
|
+
|
16
|
+
log_config_level = logging.DEBUG
|
17
|
+
|
18
|
+
elif os.getenv('log_level') == "DEBUG":
|
19
|
+
|
20
|
+
log_config_level = logging.DEBUG
|
21
|
+
|
22
|
+
elif os.getenv('log_level') == "INFO":
|
23
|
+
|
24
|
+
log_config_level = logging.INFO
|
25
|
+
|
26
|
+
else:
|
27
|
+
|
28
|
+
log_config_level = logging.WARNING # ou outro nível padrão
|
29
|
+
|
30
|
+
# Definindo o tema customizado
|
31
|
+
custom_theme = Theme({
|
32
|
+
# python -m rich.color - cores
|
33
|
+
# python -m rich.default_styles - item + cor padrão
|
34
|
+
"logging.level.debug": "bold bright_cyan",
|
35
|
+
"logging.level.info": "bold bright_white",
|
36
|
+
"logging.level.warning": "bold orange1",
|
37
|
+
"logging.level.error": "bold red blink",
|
38
|
+
"logging.level.critical": "bold white on red blink",
|
39
|
+
"logging.level.success": "bold bright_green",
|
40
|
+
"log.time":"bold white",
|
41
|
+
"log.message":"bold gray70",
|
42
|
+
"repr.str":"dark_olive_green3",
|
43
|
+
"inspect.value.border":"blue",
|
44
|
+
})
|
45
|
+
|
46
|
+
console = Console(theme=custom_theme)
|
47
|
+
|
48
|
+
class CustomRichHandler(RichHandler):
|
49
|
+
def __init__(self, *args, rich_tracebacks=True, show_time=True, show_level=True, show_path=True, console=console, omit_repeated_times=True, **kwargs):
|
50
|
+
super().__init__(rich_tracebacks=rich_tracebacks, show_time=show_time, show_level=show_level, show_path=show_path, console=console, omit_repeated_times=omit_repeated_times, *args, **kwargs)
|
51
|
+
self.show_time = show_time
|
52
|
+
|
53
|
+
|
54
|
+
def format(self, record: logging.LogRecord) -> str:
|
55
|
+
try:
|
56
|
+
msg = f"| {record.getMessage()}"
|
57
|
+
#msg = f"{record.getMessage()}"
|
58
|
+
|
59
|
+
return(str(msg))
|
60
|
+
except Exception as e:
|
61
|
+
print("FALHA AO FORMATAR O LOG")
|
62
|
+
print(e)
|
63
|
+
|
64
|
+
# Configurando o logging com o CustomRichHandler
|
65
|
+
logging.basicConfig(
|
66
|
+
level=log_config_level,
|
67
|
+
handlers=[CustomRichHandler()],
|
68
|
+
datefmt="%d/%m/%Y %H:%M:%S |",
|
69
|
+
format="| %(message)s"
|
70
|
+
)
|
71
|
+
|
72
|
+
def add_log_level(level_name, level_num, method_name=None):
|
73
|
+
#""
|
74
|
+
#Adiciona um log level
|
75
|
+
#
|
76
|
+
#Parâmetros:
|
77
|
+
# level_name (str): Nome do level
|
78
|
+
# level_num (int): Número do level
|
79
|
+
#""
|
80
|
+
if not method_name:
|
81
|
+
|
82
|
+
method_name = level_name.lower()
|
83
|
+
|
84
|
+
if hasattr(logging, level_name):
|
85
|
+
|
86
|
+
raise AttributeError('{} already defined in logging module'.format(level_name))
|
87
|
+
|
88
|
+
if hasattr(logging, method_name):
|
89
|
+
|
90
|
+
raise AttributeError('{} already defined in logging module'.format(method_name))
|
91
|
+
|
92
|
+
if hasattr(logging.getLoggerClass(), method_name):
|
93
|
+
|
94
|
+
raise AttributeError('{} already defined in logger class'.format(method_name))
|
95
|
+
|
96
|
+
def log_for_level(self, message, *args, **kwargs):
|
97
|
+
|
98
|
+
if self.isEnabledFor(level_num):
|
99
|
+
|
100
|
+
#self._log(level_num, message, args, **kwargs)
|
101
|
+
self._log(level_num, message, args, **{**kwargs, "stacklevel": 2})
|
102
|
+
|
103
|
+
def log_to_root(message, *args, **kwargs):
|
104
|
+
|
105
|
+
logging.log(level_num, message, *args, **kwargs)
|
106
|
+
|
107
|
+
logging.addLevelName(level_num, level_name)
|
108
|
+
setattr(logging, level_name, level_num)
|
109
|
+
setattr(logging.getLoggerClass(), method_name, log_for_level)
|
110
|
+
setattr(logging, method_name, log_to_root)
|
111
|
+
|
112
|
+
add_log_level("SUCCESS",21)
|
113
|
+
|
114
|
+
logger = logging.getLogger()
|
115
|
+
|
116
|
+
"""
|
117
|
+
|
118
|
+
def get_logger():
|
119
|
+
"""
|
120
|
+
Retorna um objeto logger configurado com base nas variáveis de ambiente.
|
121
|
+
Returns:
|
122
|
+
logging.Logger: Objeto logger configurado.
|
123
|
+
Raises:
|
124
|
+
ValueError: Se o valor da variável de ambiente 'log_level' não for 'DEBUG', 'INFO', 'WARNING', 'ERROR' ou 'CRITICAL'.
|
125
|
+
"""
|
126
|
+
# Instala formatações de exception da biblioteca Rich
|
127
|
+
install()
|
128
|
+
|
129
|
+
# Definindo o nível de log baseado nas configurações
|
130
|
+
if os.getenv('log_level') is None or os.getenv('log_level') == "DEBUG":
|
131
|
+
|
132
|
+
log_config_level = logging.DEBUG
|
133
|
+
|
134
|
+
elif os.getenv('log_level') == "INFO":
|
135
|
+
|
136
|
+
log_config_level = logging.INFO
|
137
|
+
|
138
|
+
elif os.getenv('log_level') == "WARNING" or os.getenv('log_level') == "WARN":
|
139
|
+
|
140
|
+
log_config_level = logging.WARNING
|
141
|
+
|
142
|
+
elif os.getenv('log_level') == "ERROR":
|
143
|
+
|
144
|
+
log_config_level = logging.ERROR
|
145
|
+
|
146
|
+
elif os.getenv('log_level') == "CRITICAL":
|
147
|
+
|
148
|
+
log_config_level = logging.CRITICAL
|
149
|
+
|
150
|
+
else:
|
151
|
+
|
152
|
+
log_config_level = logging.INFO # ou outro nível padrão
|
153
|
+
raise ValueError("'log_level' precisa ser 'DEBUG,'INFO','WARNING','ERROR' ou 'CRITICAL'")
|
154
|
+
|
155
|
+
# Definindo o tema customizado
|
156
|
+
custom_theme = Theme({
|
157
|
+
# python -m rich.color - cores
|
158
|
+
# python -m rich.default_styles - item + cor padrão
|
159
|
+
"logging.level.debug": "bold bright_cyan",
|
160
|
+
"logging.level.info": "bold bright_white",
|
161
|
+
"logging.level.warning": "bold orange1",
|
162
|
+
"logging.level.error": "bold red blink",
|
163
|
+
"logging.level.critical": "bold white on red blink",
|
164
|
+
"logging.level.success": "bold bright_green",
|
165
|
+
"log.time":"bold white",
|
166
|
+
"log.message":"bold gray70",
|
167
|
+
"repr.str":"dark_olive_green3",
|
168
|
+
"inspect.value.border":"blue",
|
169
|
+
})
|
170
|
+
|
171
|
+
console = Console(theme=custom_theme)
|
172
|
+
|
173
|
+
class CustomRichHandler(RichHandler):
|
174
|
+
def __init__(self, *args, rich_tracebacks=True, show_time=True, show_level=True, show_path=True, console=console, omit_repeated_times=True, **kwargs):
|
175
|
+
super().__init__(rich_tracebacks=rich_tracebacks, show_time=show_time, show_level=show_level, show_path=show_path, console=console, omit_repeated_times=omit_repeated_times, *args, **kwargs)
|
176
|
+
self.show_time = show_time
|
177
|
+
|
178
|
+
|
179
|
+
def format(self, record: logging.LogRecord) -> str:
|
180
|
+
try:
|
181
|
+
msg = f"| {record.getMessage()}"
|
182
|
+
#msg = f"{record.getMessage()}"
|
183
|
+
|
184
|
+
return(str(msg))
|
185
|
+
except Exception as e:
|
186
|
+
print("FALHA AO FORMATAR O LOG")
|
187
|
+
print(e)
|
188
|
+
|
189
|
+
# Configurando o logging com o CustomRichHandler
|
190
|
+
# Comentado pois estava gerando logs de libs como slack_sdk e big query
|
191
|
+
# logging.basicConfig(
|
192
|
+
# level=log_config_level,
|
193
|
+
# handlers=[CustomRichHandler()],
|
194
|
+
# datefmt="%d/%m/%Y %H:%M:%S |",
|
195
|
+
# format="| %(message)s"
|
196
|
+
# )
|
197
|
+
|
198
|
+
def add_log_level(level_name, level_num, method_name=None):
|
199
|
+
"""
|
200
|
+
Adiciona um log level
|
201
|
+
|
202
|
+
Parâmetros:
|
203
|
+
level_name (str): Nome do level
|
204
|
+
level_num (int): Número do level
|
205
|
+
"""
|
206
|
+
if not method_name:
|
207
|
+
|
208
|
+
method_name = level_name.lower()
|
209
|
+
|
210
|
+
if hasattr(logging, level_name):
|
211
|
+
|
212
|
+
raise AttributeError('{} already defined in logging module'.format(level_name))
|
213
|
+
|
214
|
+
if hasattr(logging, method_name):
|
215
|
+
|
216
|
+
raise AttributeError('{} already defined in logging module'.format(method_name))
|
217
|
+
|
218
|
+
if hasattr(logging.getLoggerClass(), method_name):
|
219
|
+
|
220
|
+
raise AttributeError('{} already defined in logger class'.format(method_name))
|
221
|
+
|
222
|
+
def log_for_level(self, message, *args, **kwargs):
|
223
|
+
|
224
|
+
if self.isEnabledFor(level_num):
|
225
|
+
|
226
|
+
#self._log(level_num, message, args, **kwargs)
|
227
|
+
self._log(level_num, message, args, **{**kwargs, "stacklevel": 2})
|
228
|
+
|
229
|
+
def log_to_root(message, *args, **kwargs):
|
230
|
+
|
231
|
+
logging.log(level_num, message, *args, **kwargs)
|
232
|
+
|
233
|
+
logging.addLevelName(level_num, level_name)
|
234
|
+
setattr(logging, level_name, level_num)
|
235
|
+
setattr(logging.getLoggerClass(), method_name, log_for_level)
|
236
|
+
setattr(logging, method_name, log_to_root)
|
237
|
+
|
238
|
+
if not 'SUCCESS' in logging._nameToLevel:
|
239
|
+
add_log_level("SUCCESS",21)
|
240
|
+
|
241
|
+
logger = logging.getLogger(__name__)
|
242
|
+
|
243
|
+
# Sendo setado aqui pois no basicConfig estava gerando logs para as libs do slack_sdk e big query
|
244
|
+
|
245
|
+
logger.addHandler(CustomRichHandler())
|
246
|
+
|
247
|
+
logger.setLevel(log_config_level)
|
248
|
+
|
249
|
+
return logger
|
csc_cia_stne/provio.py
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
import logging
|
2
|
+
import requests
|
3
|
+
from requests.auth import HTTPBasicAuth
|
4
|
+
from pydantic import BaseModel, Field, ValidationError
|
5
|
+
from typing import List, Dict, Union
|
6
|
+
|
7
|
+
# Validadores
|
8
|
+
class ProvioModel(BaseModel):
|
9
|
+
"""
|
10
|
+
Modelo para validação das credenciais de autenticação.
|
11
|
+
"""
|
12
|
+
username: str = Field(..., strip_whitespace=True, min_length=1)
|
13
|
+
password: str = Field(..., strip_whitespace=True, min_length=1)
|
14
|
+
|
15
|
+
class ExportarRelatorioParams(BaseModel):
|
16
|
+
"""
|
17
|
+
Modelo para validação dos parâmetros do relatório.
|
18
|
+
"""
|
19
|
+
ano: int = Field(..., gt=2015, description="O ano deve ser maior que 2015")
|
20
|
+
mes: int = Field(..., ge=1, le=12, description="O mês deve estar entre 1 e 12")
|
21
|
+
verbose: bool = Field(False, description="Indica se as mensagens detalhadas devem ser exibidas")
|
22
|
+
|
23
|
+
# Classe provio
|
24
|
+
class Provio:
|
25
|
+
"""
|
26
|
+
Classe para interagir com a API do Provio.
|
27
|
+
"""
|
28
|
+
|
29
|
+
def __init__(self, username: str, password: str):
|
30
|
+
"""
|
31
|
+
Inicializa a classe com as credenciais de autenticação.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
username (str): Nome de usuário para autenticação.
|
35
|
+
password (str): Senha para autenticação.
|
36
|
+
|
37
|
+
Raises:
|
38
|
+
ValidationError: Se as credenciais forem inválidas de acordo com o modelo `ProvioModel`.
|
39
|
+
"""
|
40
|
+
# Validação usando Pydantic
|
41
|
+
data = ProvioModel(username=username, password=password)
|
42
|
+
|
43
|
+
self.api_url = "https://provio.apps.stone.com.br/api/reports"
|
44
|
+
self.auth = HTTPBasicAuth(data.username, data.password)
|
45
|
+
|
46
|
+
def exportar_relatorio_geral(self, ano: int, mes: int, verbose: bool=False) -> Dict[str, Union[bool, str, List[Dict]]]:
|
47
|
+
"""
|
48
|
+
Exporta o relatório geral para o período especificado.
|
49
|
+
|
50
|
+
Args:
|
51
|
+
ano (int): Ano do relatório (deve ser maior que 2015).
|
52
|
+
mes (int): Mês do relatório (deve estar entre 1 e 12).
|
53
|
+
verbose (bool): informa se as requisições devem ser expostas na console
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
Dict[str, Union[bool, str, List[Dict]]]: Um dicionário contendo:
|
57
|
+
- `success` (bool): Indica se a exportação foi bem-sucedida.
|
58
|
+
- `error` (str): Mensagem de erro, se houver.
|
59
|
+
- `report` (List[Dict]): Lista de registros exportados, se `success` for `True`.
|
60
|
+
|
61
|
+
Raises:
|
62
|
+
ValidationError: Se os parâmetros `ano` e `mes` forem inválidos.
|
63
|
+
"""
|
64
|
+
# Validação dos parâmetros
|
65
|
+
params = ExportarRelatorioParams(ano=ano, mes=mes, verbose=verbose)
|
66
|
+
periodo = f"{params.ano}-{params.mes:02d}"
|
67
|
+
skip = 0
|
68
|
+
todos_os_dados = [] # Lista para armazenar todos os resultados
|
69
|
+
requisicao = 0
|
70
|
+
try:
|
71
|
+
|
72
|
+
while True:
|
73
|
+
|
74
|
+
url = f"{self.api_url}/general/{periodo}/{skip}"
|
75
|
+
response = requests.get(url=url, auth=self.auth)
|
76
|
+
|
77
|
+
if response.status_code == 200:
|
78
|
+
|
79
|
+
dados = response.json()
|
80
|
+
|
81
|
+
# Verifica se há itens na resposta
|
82
|
+
if not dados: # Se a resposta for vazia, interrompa o loop
|
83
|
+
|
84
|
+
break
|
85
|
+
|
86
|
+
# Adiciona os dados recebidos à lista total
|
87
|
+
todos_os_dados.extend(dados)
|
88
|
+
|
89
|
+
# Incrementa o skip para buscar a próxima página
|
90
|
+
skip += 500
|
91
|
+
requisicao += 1
|
92
|
+
if verbose:
|
93
|
+
logging.info(f"Exportando relatório: Requisição #{str(requisicao).zfill(3)} - {len(todos_os_dados)} registros no total")
|
94
|
+
|
95
|
+
else:
|
96
|
+
|
97
|
+
return {"success": False, "error": f"{response.status_code} - {response.text}"}
|
98
|
+
|
99
|
+
return {"success": True, "error": None, "report": todos_os_dados}
|
100
|
+
|
101
|
+
except Exception as e:
|
102
|
+
|
103
|
+
return {"success": False, "error": str(e)}
|