csc-cia-stne 0.0.43__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.
- 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)}
|