csc-cia-stne 0.1.2__py3-none-any.whl → 0.1.3__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.
@@ -175,8 +175,7 @@ class GoogleDrive:
175
175
 
176
176
  return {"success": False, "result": None, "error": str(e)}
177
177
 
178
-
179
- def _validate_folder_existence(self, folder:str, id_folder:str):
178
+ def _validate_folder_existence(self, folder: str, id_folder: str):
180
179
  """
181
180
  Verifica a existência de uma pasta no Google Drive.
182
181
  Args:
@@ -192,24 +191,39 @@ class GoogleDrive:
192
191
 
193
192
  try:
194
193
 
195
- response = self.service.files().list(q=query, spaces='drive', fields='nextPageToken, files(id, name, mimeType)', pageToken=None, includeItemsFromAllDrives = True, supportsAllDrives = True).execute()
194
+ response = (
195
+ self.service.files()
196
+ .list(
197
+ q=query,
198
+ spaces="drive",
199
+ fields="nextPageToken, files(id, name, mimeType)",
200
+ pageToken=None,
201
+ includeItemsFromAllDrives=True,
202
+ supportsAllDrives=True,
203
+ )
204
+ .execute()
205
+ )
196
206
 
197
- items = response.get('files', [])
207
+ items = response.get("files", [])
198
208
 
199
209
  for item in items:
200
210
 
201
- if item['mimeType'] == 'application/vnd.google-apps.folder' and item['name'] == folder:
211
+ if (
212
+ item["mimeType"] == "application/vnd.google-apps.folder"
213
+ and item["name"] == folder
214
+ ):
202
215
 
203
216
  return item
204
-
217
+
205
218
  return None
206
-
207
- except Exception as e:
208
219
 
209
- raise ValueError(f'Erro tentando procurar pela pasta:{e}')
220
+ except Exception as e:
210
221
 
222
+ raise ValueError(f"Erro tentando procurar pela pasta:{e}")
211
223
 
212
- def create_folder(self, name: str, parent_folder_id: str, validate_existence:bool=False):
224
+ def create_folder(
225
+ self, name: str, parent_folder_id: str, validate_existence: bool = False
226
+ ):
213
227
  """
214
228
  Cria uma pasta no Google Drive dentro de uma pasta existente.
215
229
 
@@ -221,7 +235,11 @@ class GoogleDrive:
221
235
  str: ID da pasta criada.
222
236
  """
223
237
  try:
224
- CreateFolderValidator(name=name, parent_folder_id=parent_folder_id,validate_existence=validate_existence)
238
+ CreateFolderValidator(
239
+ name=name,
240
+ parent_folder_id=parent_folder_id,
241
+ validate_existence=validate_existence,
242
+ )
225
243
  except ValidationError as e:
226
244
  raise ValueError(
227
245
  "Erro na validação dos dados de input da inicialização da instância:",
@@ -250,7 +268,7 @@ class GoogleDrive:
250
268
  return {"success": True, "result": folder}
251
269
  except Exception as e:
252
270
  return {"success": False, "result": None, "error": str(e)}
253
-
271
+
254
272
  return {"success": True, "result": status_existence}
255
273
 
256
274
  def list_items_folder(
@@ -342,7 +360,7 @@ class GoogleDrive:
342
360
  except Exception as e:
343
361
  return {"success": False, "result": None}
344
362
 
345
- def download_others_files(self, file: str, path: str):
363
+ def download_others_files(self, file: str, path: str):
346
364
  """
347
365
  Obtém o conteúdo de um arquivo armazenado nos seguintes formatos:
348
366
  .xlsx, .pdf, .jpg, etc.
@@ -373,9 +391,7 @@ class GoogleDrive:
373
391
  if not os.path.exists(path):
374
392
  os.makedirs(path)
375
393
  try:
376
- request = self.service.files().get_media(
377
- fileId=file.get("id")
378
- )
394
+ request = self.service.files().get_media(fileId=file.get("id"))
379
395
  file_path = f"{path}{file["name"]}"
380
396
  with open(file_path, "wb") as f:
381
397
  f.write(request.execute())
@@ -2,12 +2,15 @@ import requests
2
2
  import base64, json
3
3
  import os
4
4
  import logging
5
- from pydantic import ValidationError
5
+ from pydantic import ValidationError
6
6
  from .utilitarios.validations.ServiceNowValidator import *
7
7
 
8
+
8
9
  class ServiceNow:
9
-
10
- def __init__(self, username: str = None, password: str = None, env: str = None) -> None:
10
+
11
+ def __init__(
12
+ self, username: str = None, password: str = None, env: str = None
13
+ ) -> None:
11
14
  """
12
15
  Inicializa uma instância da classe ServiceNow.
13
16
 
@@ -15,10 +18,10 @@ class ServiceNow:
15
18
  username (str): Nome de usuário para autenticação. Obrigatório e não pode ser nulo ou vazio.
16
19
  password (str): Senha para autenticação. Obrigatória e não pode ser nula ou vazia.
17
20
  env (str): Ambiente no qual a instância será utilizada. Deve ser 'dev', 'qa', 'qas' ou 'prod'.
18
-
21
+
19
22
  Raises:
20
23
  ValueError: Caso qualquer um dos parâmetros não seja fornecido, seja nulo ou vazio, ou se 'env' não for um valor válido.
21
-
24
+
22
25
  Atributos:
23
26
  username (str): Nome de usuário normalizado.
24
27
  password (str): Senha normalizada.
@@ -27,47 +30,53 @@ class ServiceNow:
27
30
  api_header (dict): Cabeçalhos padrão para requisições API.
28
31
  """
29
32
  try:
30
- InitParamsValidator(username=username, password=password, env=env )
33
+ InitParamsValidator(username=username, password=password, env=env)
31
34
  except ValidationError as e:
32
- raise ValueError("Erro na validação dos dados de input da inicialização da instância 'ServiceNow':", e.errors())
33
-
35
+ raise ValueError(
36
+ "Erro na validação dos dados de input da inicialização da instância 'ServiceNow':",
37
+ e.errors(),
38
+ )
39
+
34
40
  # Normaliza o valor de 'env' para maiúsculas
35
41
  env = env.strip().upper()
36
42
 
37
43
  # Dicionário de ambientes válidos e URLs correspondentes
38
44
  valid_envs = {
39
- 'DEV': 'https://stonedev.service-now.com/api',
40
- 'QA': 'https://stoneqas.service-now.com/api',
41
- 'QAS': 'https://stoneqas.service-now.com/api',
42
- 'PROD': 'https://stone.service-now.com/api'
45
+ "DEV": "https://stonedev.service-now.com/api",
46
+ "QA": "https://stoneqas.service-now.com/api",
47
+ "QAS": "https://stoneqas.service-now.com/api",
48
+ "PROD": "https://stone.service-now.com/api",
43
49
  }
44
50
 
45
51
  # Verifica se 'env' é válido
46
52
  if env not in valid_envs:
47
- raise ValueError("O valor de 'env' precisa ser 'dev', 'qa', 'qas' ou 'prod'.")
53
+ raise ValueError(
54
+ "O valor de 'env' precisa ser 'dev', 'qa', 'qas' ou 'prod'."
55
+ )
48
56
 
49
57
  # Atribui as variáveis de instância
50
58
  self.__username = username.strip()
51
59
  self.__password = password.strip()
52
60
  self.env = env
53
61
  self.api_url = valid_envs[env]
54
- self.api_header = {"Content-Type":"application/json","Accept":"application/json"}
55
-
62
+ self.api_header = {
63
+ "Content-Type": "application/json",
64
+ "Accept": "application/json",
65
+ }
56
66
 
57
67
  def __auth(self):
58
68
  """
59
- Retorna o e-mail e senha para realizar a autenticação.
69
+ Retorna o e-mail e senha para realizar a autenticação.
60
70
  """
61
71
  return (self.__username, self.__password)
62
-
63
72
 
64
- def request (self, url : str , params : str = "", timeout : int = 15):
73
+ def request(self, url: str, params: str = "", timeout: int = 15):
65
74
  """
66
75
  Realiza uma requisição GET para a URL especificada.
67
76
 
68
77
  Parâmetros:
69
78
  url (str): URL para a qual a requisição será enviada.
70
- params (dict, opcional): Parâmetros de consulta (query parameters) a serem incluídos na requisição.
79
+ params (dict, opcional): Parâmetros de consulta (query parameters) a serem incluídos na requisição.
71
80
  Padrão é uma string vazia.
72
81
 
73
82
  Retorno:
@@ -93,49 +102,50 @@ class ServiceNow:
93
102
  try:
94
103
  RequestValidator(url=url, params=params, timeout=timeout)
95
104
  except ValidationError as e:
96
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
97
-
105
+ raise ValueError(
106
+ "Erro na validação dos dados de input do método:", e.errors()
107
+ )
108
+
98
109
  try:
99
110
  response = requests.get(
100
- url,
111
+ url,
101
112
  params=params,
102
113
  auth=self.__auth(),
103
114
  headers=self.api_header,
104
115
  timeout=timeout,
105
- verify=True
116
+ verify=True,
106
117
  )
107
118
 
108
119
  # VALIDA SE HOUVE SUCESSO NA REQUISIÇÃO
109
120
  response.raise_for_status()
110
121
 
111
- # Analisa o conteúdo da resposta JSON
122
+ # Analisa o conteúdo da resposta JSON
112
123
  result = response.json()
113
124
  if "result" in result:
114
- return {"success" : True, "result" : result.get("result")}
125
+ return {"success": True, "result": result.get("result")}
115
126
  else:
116
127
  logging.debug("A resposta não contém o campo 'result'.")
117
- return {"success" : False, "result" : result}
128
+ return {"success": False, "result": result}
118
129
 
119
130
  except requests.exceptions.HTTPError as http_err:
120
131
  logging.debug(f"Erro HTTP ao buscar os detalhes do ticket: {http_err}")
121
- return {"success" : False, "result" : None, "error" : str(http_err)}
122
-
132
+ return {"success": False, "result": None, "error": str(http_err)}
133
+
123
134
  except requests.exceptions.RequestException as req_err:
124
135
  logging.debug(f"Erro ao buscar os detalhes do ticket: {req_err}")
125
- return {"success" : False, "result" : None, "error" : str(req_err)}
126
-
136
+ return {"success": False, "result": None, "error": str(req_err)}
137
+
127
138
  except Exception as e:
128
139
  logging.debug(f"Erro inesperado: {e}")
129
- return {"success" : False, "result" : None, "error" : str(e)}
130
-
140
+ return {"success": False, "result": None, "error": str(e)}
131
141
 
132
- def __request_download(self, url, params = "", timeout = 15):
142
+ def __request_download(self, url, params="", timeout=15):
133
143
  """
134
144
  Realiza uma requisição GET para a URL especificada.
135
145
 
136
146
  Parâmetros:
137
147
  url (str): URL para a qual a requisição será enviada.
138
- params (dict, opcional): Parâmetros de consulta (query parameters) a serem incluídos na requisição.
148
+ params (dict, opcional): Parâmetros de consulta (query parameters) a serem incluídos na requisição.
139
149
  Padrão é uma string vazia.
140
150
 
141
151
  Retorno:
@@ -160,37 +170,36 @@ class ServiceNow:
160
170
  """
161
171
  try:
162
172
  response = requests.get(
163
- url,
173
+ url,
164
174
  params=params,
165
175
  auth=self.__auth(),
166
176
  headers=self.api_header,
167
177
  timeout=timeout,
168
- verify=True
178
+ verify=True,
169
179
  )
170
180
 
171
181
  # VALIDA SE HOUVE SUCESSO NA REQUISIÇÃO
172
182
  response.raise_for_status()
173
- # Analisa o conteúdo da resposta JSON
183
+ # Analisa o conteúdo da resposta JSON
174
184
  if response.status_code == 200:
175
- return {"success" : True, "result" : response}
185
+ return {"success": True, "result": response}
176
186
  else:
177
187
  logging.debug("Erro ao realizar a consulta")
178
- return {"success" : False, "result" : response.status_code}
188
+ return {"success": False, "result": response.status_code}
179
189
 
180
190
  except requests.exceptions.HTTPError as http_err:
181
191
  logging.debug(f"Erro HTTP ao buscar os detalhes do ticket: {http_err}")
182
- return {"success" : False, "error" : str(http_err), "result" : None}
183
-
192
+ return {"success": False, "error": str(http_err), "result": None}
193
+
184
194
  except requests.exceptions.RequestException as req_err:
185
195
  logging.debug(f"Erro ao buscar os detalhes do ticket: {req_err}")
186
- return {"success" : False, "error" : str(req_err), "result" : None}
187
-
196
+ return {"success": False, "error": str(req_err), "result": None}
197
+
188
198
  except Exception as e:
189
199
  logging.debug(f"Erro inesperado: {e}")
190
- return {"success" : False, "error" : str(e), "result" : None}
200
+ return {"success": False, "error": str(e), "result": None}
191
201
 
192
-
193
- def put(self, url, payload, timeout = 15):
202
+ def put(self, url, payload, timeout=15):
194
203
  """
195
204
  Realiza uma requisição PUT para a URL especificada.
196
205
 
@@ -221,18 +230,20 @@ class ServiceNow:
221
230
  try:
222
231
  PutValidator(url=url, payload=payload, timeout=timeout)
223
232
  except ValidationError as e:
224
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
225
-
233
+ raise ValueError(
234
+ "Erro na validação dos dados de input do método:", e.errors()
235
+ )
236
+
226
237
  payload = json.dumps(payload)
227
238
 
228
- try:
239
+ try:
229
240
  response = requests.put(
230
241
  f"{url}",
231
242
  auth=self.__auth(),
232
243
  headers=self.api_header,
233
244
  data=f"{payload}",
234
245
  timeout=timeout,
235
- verify=True
246
+ verify=True,
236
247
  )
237
248
 
238
249
  # VALIDA SE HOUVE SUCESSO NA REQUISIÇÃO
@@ -242,43 +253,51 @@ class ServiceNow:
242
253
  result = response.json()
243
254
  if "result" in result:
244
255
  update = result["result"]
245
- logging.debug(f"Atualização concluída com sucesso. Registro atualizado: {update['sys_id']} | Alterações: {payload}")
246
- return {"success" : True, "result" : update}
256
+ logging.debug(
257
+ f"Atualização concluída com sucesso. Registro atualizado: {update['sys_id']} | Alterações: {payload}"
258
+ )
259
+ return {"success": True, "result": update}
247
260
  else:
248
- logging.debug(f"A Resposta da sua requisição não contém o campo 'Result'. Segue o retorno: \n {result} | Alterações: {payload}")
249
- return {"success" : False, "result" : result}
250
-
251
- #TRATAMENTOS DE ERRO
261
+ logging.debug(
262
+ f"A Resposta da sua requisição não contém o campo 'Result'. Segue o retorno: \n {result} | Alterações: {payload}"
263
+ )
264
+ return {"success": False, "result": result}
265
+
266
+ # TRATAMENTOS DE ERRO
252
267
  except requests.exceptions.HTTPError as http_err:
253
- logging.debug(f"Erro HTTP ao tentar atualizar o ticket: {http_err} \n Reposta da solicitação: {response.json().get('error').get('message')}")
254
- return {"success" : False, "error" : str(http_err) , "result" : None}
255
-
268
+ logging.debug(
269
+ f"Erro HTTP ao tentar atualizar o ticket: {http_err} \n Reposta da solicitação: {response.json().get('error').get('message')}"
270
+ )
271
+ return {"success": False, "error": str(http_err), "result": None}
272
+
256
273
  except requests.exceptions.RequestException as req_err:
257
274
  logging.debug(f"Erro ao tentar atualizar o ticket: \n {req_err}")
258
- return {"success" : False, "error" : str(req_err) , "result" : None}
259
-
275
+ return {"success": False, "error": str(req_err), "result": None}
276
+
260
277
  except Exception as e:
261
278
  logging.debug(f"Erro inesperado: \n {e}")
262
- return {"success" : False, "error" : str(e) , "result" : None}
279
+ return {"success": False, "error": str(e), "result": None}
263
280
 
264
-
265
- def post(self, url : str, variables : dict, header_content_type = "", timeout : int = 15):
281
+ def post(
282
+ self, url: str, variables: dict, header_content_type="", timeout: int = 15
283
+ ):
266
284
  """
267
- Função para criar um novo ticket no servicenow usando o API REST.
285
+ Função para criar um novo ticket no servicenow usando o API REST.
268
286
 
269
- Parametros:
270
- - Payload (Dict): Dicionário contendo os dados que serão utilizados para criar o ticket
271
- Retorno:
272
- - Dict: Um dicionário contendo os detalhes do ticket criado
273
- Raises:
274
- - Exception: Se ocorrer um erro ao criar o ticket.
287
+ Parametros:
288
+ - Payload (Dict): Dicionário contendo os dados que serão utilizados para criar o ticket
289
+ Retorno:
290
+ - Dict: Um dicionário contendo os detalhes do ticket criado
291
+ Raises:
292
+ - Exception: Se ocorrer um erro ao criar o ticket.
275
293
 
276
294
  """
277
- try:
295
+ try:
278
296
  PostValidator(url=url, variables=variables)
279
297
  except ValidationError as e:
280
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
281
-
298
+ raise ValueError(
299
+ "Erro na validação dos dados de input do método:", e.errors()
300
+ )
282
301
 
283
302
  if header_content_type:
284
303
  header = header_content_type
@@ -286,17 +305,14 @@ class ServiceNow:
286
305
  header = self.api_header
287
306
 
288
307
  # Ajustar o Payload para a abertura do ticket
289
- payload = {
290
- "sysparm_quantity" : "1",
291
- "variables" : json.dumps(variables)
292
- }
293
- try:
308
+ payload = {"sysparm_quantity": "1", "variables": json.dumps(variables)}
309
+ try:
294
310
  response = requests.post(
295
311
  f"{url}",
296
312
  auth=self.__auth(),
297
313
  headers=header,
298
314
  data=f"{payload}",
299
- timeout=timeout
315
+ timeout=timeout,
300
316
  )
301
317
 
302
318
  # VALIDA SE HOUVE SUCESSO NA REQUISIÇÃO
@@ -307,28 +323,41 @@ class ServiceNow:
307
323
  if "result" in result:
308
324
  ticket_number = result["result"].get("number")
309
325
  ticket_sys_id = result["result"].get("sys_id")
310
- logging.debug(f"Ticket registrado com sucesso. Número: {ticket_number} | SYS_ID: {ticket_sys_id}")
311
- return {"success" : True, "result" : result["result"]}
326
+ logging.debug(
327
+ f"Ticket registrado com sucesso. Número: {ticket_number} | SYS_ID: {ticket_sys_id}"
328
+ )
329
+ return {"success": True, "result": result["result"]}
312
330
  else:
313
- logging.debug(f"A Resposta da sua requisição não contém o campo 'Result'. Segue o retorno: \n {result}")
314
- return {"success" : False, "result" : result}
315
-
316
- #TRATAMENTOS DE ERRO
331
+ logging.debug(
332
+ f"A Resposta da sua requisição não contém o campo 'Result'. Segue o retorno: \n {result}"
333
+ )
334
+ return {"success": False, "result": result}
335
+
336
+ # TRATAMENTOS DE ERRO
317
337
  except requests.exceptions.HTTPError as http_err:
318
338
 
319
- logging.debug(f"Erro HTTP ao tentar registrar o ticket: {http_err} \n Reposta da solicitação: {response.json().get('error').get('message')}")
320
- return {"success" : False, "error" : str(http_err) , "result" : None}
321
-
339
+ logging.debug(
340
+ f"Erro HTTP ao tentar registrar o ticket: {http_err} \n Reposta da solicitação: {response.json().get('error').get('message')}"
341
+ )
342
+ return {"success": False, "error": str(http_err), "result": None}
343
+
322
344
  except requests.exceptions.RequestException as req_err:
323
345
  logging.debug(f"Erro ao tentar registrar o ticket: \n {req_err}")
324
- return {"success" : False, "error" : str(req_err) , "result" : None}
325
-
346
+ return {"success": False, "error": str(req_err), "result": None}
347
+
326
348
  except Exception as e:
327
349
  logging.debug(f"Erro inesperado: \n {e}")
328
- return {"success" : False, "error" : str(e) , "result" : None}
329
-
330
-
331
- def listar_tickets(self, tabela: str = None, campos: list = None, query: str = None, limite: int = 50, timeout:int=15, sysparm_display_value: str = "")->dict:
350
+ return {"success": False, "error": str(e), "result": None}
351
+
352
+ def listar_tickets(
353
+ self,
354
+ tabela: str = None,
355
+ campos: list = None,
356
+ query: str = None,
357
+ limite: int = 50,
358
+ timeout: int = 15,
359
+ sysparm_display_value: str = "",
360
+ ) -> dict:
332
361
  """lista tickets do ServiceNow
333
362
 
334
363
  Args:
@@ -342,30 +371,42 @@ class ServiceNow:
342
371
  dict: dicionário com o resultado da query
343
372
  """
344
373
  try:
345
- ListTicketValidator(tabela=tabela, campos=campos, query=query, limite=limite, timeout=timeout)
374
+ ListTicketValidator(
375
+ tabela=tabela,
376
+ campos=campos,
377
+ query=query,
378
+ limite=limite,
379
+ timeout=timeout,
380
+ )
346
381
  except ValidationError as e:
347
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
348
-
382
+ raise ValueError(
383
+ "Erro na validação dos dados de input do método:", e.errors()
384
+ )
349
385
 
350
386
  params = {
351
- "sysparm_query" : query,
352
- "sysparm_fields" : ','.join(campos),
353
- "sysparm_display_value" : sysparm_display_value,
354
- "sysparm_limit" : limite
387
+ "sysparm_query": query,
388
+ "sysparm_fields": ",".join(campos),
389
+ "sysparm_display_value": sysparm_display_value,
390
+ "sysparm_limit": limite,
355
391
  }
356
392
 
357
393
  url = f"{self.api_url}/now/table/{tabela}"
358
-
394
+
359
395
  try:
360
396
  response = self.request(url=url, params=params, timeout=timeout)
361
397
  return response
362
-
398
+
363
399
  except Exception as e:
364
400
  logging.debug(f"erro: {e}")
365
401
  return str(e)
366
402
 
367
-
368
- def update_ticket(self, tabela: str = None, sys_id: str = None, payload: dict = None, timeout:int=15)->dict:
403
+ def update_ticket(
404
+ self,
405
+ tabela: str = None,
406
+ sys_id: str = None,
407
+ payload: dict = None,
408
+ timeout: int = 15,
409
+ ) -> dict:
369
410
  """Atualiza as informações de um ticket
370
411
 
371
412
  Args:
@@ -378,10 +419,14 @@ class ServiceNow:
378
419
  dict: resposta do ServiceNow
379
420
  """
380
421
  try:
381
- UpdateTicketValidator(tabela=tabela, sys_id=sys_id, payload=payload, timeout=timeout)
422
+ UpdateTicketValidator(
423
+ tabela=tabela, sys_id=sys_id, payload=payload, timeout=timeout
424
+ )
382
425
  except ValidationError as e:
383
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
384
-
426
+ raise ValueError(
427
+ "Erro na validação dos dados de input do método:", e.errors()
428
+ )
429
+
385
430
  payload["assigned_to"] = self.__username
386
431
 
387
432
  try:
@@ -393,8 +438,14 @@ class ServiceNow:
393
438
  except Exception as e:
394
439
  return str(e)
395
440
 
396
-
397
- def anexar_arquivo_no_ticket(self,header_content_type:dict=None, anexo_path:str=None, tabela:str=None, sys_id:str=None, timeout:int=15):
441
+ def anexar_arquivo_no_ticket(
442
+ self,
443
+ header_content_type: dict = None,
444
+ anexo_path: str = None,
445
+ tabela: str = None,
446
+ sys_id: str = None,
447
+ timeout: int = 15,
448
+ ):
398
449
  """Anexa arquivo em um ticket do ServiceNow
399
450
 
400
451
  Args:
@@ -408,37 +459,53 @@ class ServiceNow:
408
459
  dict: resposta do ServiceNow
409
460
  """
410
461
  if header_content_type is None:
411
- header_content_type = self.__valida_header_content_type(anexo_path, header_content_type)
412
-
462
+ header_content_type = self.__valida_header_content_type(
463
+ anexo_path, header_content_type
464
+ )
465
+
413
466
  try:
414
- AttachFileTicketValidator(header_content_type=header_content_type, anexo_path=anexo_path, tabela=tabela, sys_id=sys_id, timeout=timeout)
467
+ AttachFileTicketValidator(
468
+ header_content_type=header_content_type,
469
+ anexo_path=anexo_path,
470
+ tabela=tabela,
471
+ sys_id=sys_id,
472
+ timeout=timeout,
473
+ )
415
474
  except ValidationError as e:
416
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
417
-
475
+ raise ValueError(
476
+ "Erro na validação dos dados de input do método:", e.errors()
477
+ )
478
+
418
479
  if not os.path.exists(anexo_path):
419
480
  raise FileExistsError(f"O arquivo não foi encontrado ({anexo_path})")
420
481
 
421
-
422
-
423
482
  # Converte as chaves do dicionário para minúsculas
424
- header_content_type_lower = {k.lower(): v for k, v in header_content_type.items()}
483
+ header_content_type_lower = {
484
+ k.lower(): v for k, v in header_content_type.items()
485
+ }
425
486
 
426
-
427
487
  if "content-type" not in header_content_type_lower:
428
- raise ValueError("O parâmetro 'header_content_type' não possui a chave 'Content-Type' com o tipo do anexo")
488
+ raise ValueError(
489
+ "O parâmetro 'header_content_type' não possui a chave 'Content-Type' com o tipo do anexo"
490
+ )
429
491
 
430
492
  nome_arquivo = os.path.basename(anexo_path)
431
493
  try:
432
- with open(anexo_path, 'rb') as f:
494
+ with open(anexo_path, "rb") as f:
433
495
  url = f"{self.api_url}/now/attachment/file?table_name={tabela}&table_sys_id={sys_id}&file_name={nome_arquivo}"
434
- response = requests.post(url, headers=header_content_type, auth=(self.__username, self.__password), data=f, timeout=timeout)
435
-
496
+ response = requests.post(
497
+ url,
498
+ headers=header_content_type,
499
+ auth=(self.__username, self.__password),
500
+ data=f,
501
+ timeout=timeout,
502
+ )
503
+
436
504
  logging.debug("Arquivo adicionado no ticket")
437
- return {"success": True, "result" : response}
438
-
505
+ return {"success": True, "result": response}
506
+
439
507
  except Exception as e:
440
- return {"success" : False, "result" : None, "error" : str(e)}
441
-
508
+ return {"success": False, "result": None, "error": str(e)}
442
509
 
443
510
  def __valida_header_content_type(self, anexo_path, header_content_type):
444
511
  """
@@ -460,35 +527,49 @@ class ServiceNow:
460
527
 
461
528
  Observação:
462
529
  - O parâmetro `header_content_type` é uma variável local utilizada para compor os cabeçalhos HTTP, contendo informações do tipo de conteúdo do arquivo.
463
-
530
+
464
531
  """
465
532
 
466
533
  # Pré validando 'header_content_type'
467
- if os.path.splitext(anexo_path)[1].lower() == ".zip" and header_content_type is None:
468
-
534
+ if (
535
+ os.path.splitext(anexo_path)[1].lower() == ".zip"
536
+ and header_content_type is None
537
+ ):
538
+
469
539
  header_content_type = {"Content-Type": "application/zip"}
470
-
471
- elif os.path.splitext(anexo_path)[1].lower() == ".xlsx" and header_content_type is None:
472
-
473
- header_content_type = {"Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}
474
-
475
- elif os.path.splitext(anexo_path)[1].lower() == ".pdf" and header_content_type is None:
476
-
540
+
541
+ elif (
542
+ os.path.splitext(anexo_path)[1].lower() == ".xlsx"
543
+ and header_content_type is None
544
+ ):
545
+
546
+ header_content_type = {
547
+ "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
548
+ }
549
+
550
+ elif (
551
+ os.path.splitext(anexo_path)[1].lower() == ".pdf"
552
+ and header_content_type is None
553
+ ):
554
+
477
555
  header_content_type = {"Content-Type": "application/pdf"}
478
-
479
- elif os.path.splitext(anexo_path)[1].lower() == ".txt" and header_content_type is None:
480
-
556
+
557
+ elif (
558
+ os.path.splitext(anexo_path)[1].lower() == ".txt"
559
+ and header_content_type is None
560
+ ):
561
+
481
562
  header_content_type = {"Content-Type": "text/plain"}
482
563
 
483
564
  # Validação de 'header_content_type'
484
565
  if not isinstance(header_content_type, dict):
485
- raise ValueError("O parâmetro 'header_content_type' precisa ser um dicionário contendo o 'Content-Type' do arquivo a ser anexado. (Ex: {\"Content-Type\": \"application/zip\"})")
486
-
487
-
488
- return header_content_type
566
+ raise ValueError(
567
+ "O parâmetro 'header_content_type' precisa ser um dicionário contendo o 'Content-Type' do arquivo a ser anexado. (Ex: {\"Content-Type\": \"application/zip\"})"
568
+ )
489
569
 
570
+ return header_content_type
490
571
 
491
- def download_anexo(self, sys_id_file : str, file_path : str, timeout : int = 15):
572
+ def download_anexo(self, sys_id_file: str, file_path: str, timeout: int = 15):
492
573
  """
493
574
  Faz o download de um anexo do ServiceNow utilizando o `sys_id` do arquivo e salva no caminho especificado.
494
575
 
@@ -525,8 +606,10 @@ class ServiceNow:
525
606
  try:
526
607
  DownloadFileValidator(sys_id_file=sys_id_file, file_path=file_path)
527
608
  except ValidationError as e:
528
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
529
-
609
+ raise ValueError(
610
+ "Erro na validação dos dados de input do método:", e.errors()
611
+ )
612
+
530
613
  url = f"{self.api_url}/now/attachment/{sys_id_file}/file"
531
614
  response = self.__request_download(url=url, timeout=timeout)
532
615
  response = response.get("result")
@@ -537,50 +620,56 @@ class ServiceNow:
537
620
  print(diretorio)
538
621
  os.makedirs(diretorio, exist_ok=True)
539
622
  logging.debug(f"Diretorio criado: {diretorio}")
540
- with open(file_path, 'wb') as f:
623
+ with open(file_path, "wb") as f:
541
624
  f.write(response.content)
542
- return {"success" : True, "path" : file_path }
543
-
625
+ return {"success": True, "path": file_path}
626
+
544
627
  except FileNotFoundError:
545
628
  try:
546
629
  path = os.path.dirname(file_path)
547
630
  os.makedirs(path)
548
- with open(file_path, 'wb') as f:
631
+ with open(file_path, "wb") as f:
549
632
  f.write(response.content)
550
- return {"success" : True, "path" : file_path }
633
+ return {"success": True, "path": file_path}
551
634
  except Exception as e:
552
635
  logging.debug(f"Erro ao salvar o arquivo. Erro: {e}")
553
- return {"success" : False, "error" : str(e) }
636
+ return {"success": False, "error": str(e)}
554
637
  except Exception as e:
555
638
  logging.error(f"Erro ao salvar o arquivo. Erro: {e}")
556
- return {"success" : False, "error" : str(e) }
639
+ return {"success": False, "error": str(e)}
557
640
  else:
558
641
  logging.debug(f"{response.status_code}")
559
- return {"success" : False, "error" : f"Status code: {response.status_code }"}
642
+ return {"success": False, "error": f"Status code: {response.status_code }"}
560
643
 
561
- def get_variables_from_ticket(self, sys_id : str, campos : str = ''):
644
+ def get_variables_from_ticket(self, sys_id: str, campos: str = ""):
562
645
  """
563
646
  Obtém as variáveis associadas ao ticket.
564
647
  args:
565
648
  sys_id : STR - Id do ticket
566
649
  """
567
650
  if isinstance(campos, list):
568
- campos = ','.join(campos)
651
+ campos = ",".join(campos)
569
652
  if campos == "":
570
- campos = 'name,question_text,type,default_value, sys_id'
653
+ campos = "name,question_text,type,default_value, sys_id"
571
654
 
572
655
  logging.debug(f"Obtendo variáveis do ticket {sys_id}")
573
656
  url = f"{self.api_url}/now/table/item_option_new"
574
657
  params = {
575
- 'sysparm_query': f'cat_item={sys_id}',
576
- 'sysparm_display_value': 'true',
577
- 'sysparm_fields': campos,
658
+ "sysparm_query": f"cat_item={sys_id}",
659
+ "sysparm_display_value": "true",
660
+ "sysparm_fields": campos,
578
661
  }
579
662
  response = self.request(url, params=params)
580
663
  return response
581
-
582
664
 
583
- def get_anexo(self, sys_id: str = None, tabela: str = None, campo: str = 'default', download_dir:str=None, timeout:int=15)->dict:
665
+ def get_anexo(
666
+ self,
667
+ sys_id: str = None,
668
+ tabela: str = None,
669
+ campo: str = "default",
670
+ download_dir: str = None,
671
+ timeout: int = 15,
672
+ ) -> dict:
584
673
  """Traz os anexos de um campo do ticket especificado
585
674
 
586
675
  Args:
@@ -593,50 +682,57 @@ class ServiceNow:
593
682
  dict: dicionário com os anexos do ticket
594
683
  """
595
684
  try:
596
- GetAttachValidator(sys_id=sys_id,
597
- tabela=tabela,
598
- timeout=timeout,
599
- download_dir=download_dir)
685
+ GetAttachValidator(
686
+ sys_id=sys_id, tabela=tabela, timeout=timeout, download_dir=download_dir
687
+ )
600
688
  except ValidationError as e:
601
- raise ValueError("Erro na validação dos dados de input do método:", e.errors())
602
-
689
+ raise ValueError(
690
+ "Erro na validação dos dados de input do método:", e.errors()
691
+ )
692
+
603
693
  if download_dir is not None:
604
694
  if not isinstance(download_dir, str) or not download_dir.strip():
605
- raise ValueError("O parâmetro 'download_dir' precisa ser a pasta pra onde o anexo será feito o download.")
606
- if not os.path.exists(download_dir):
607
- raise NotADirectoryError(f"A pasta informada '{download_dir}' não existe")
608
-
695
+ raise ValueError(
696
+ "O parâmetro 'download_dir' precisa ser a pasta pra onde o anexo será feito o download."
697
+ )
698
+ if not os.path.exists(download_dir):
699
+ raise NotADirectoryError(
700
+ f"A pasta informada '{download_dir}' não existe"
701
+ )
702
+
609
703
  # Validação de 'campo'
610
704
  if not isinstance(campo, str) or not campo.strip():
611
- raise ValueError("O parâmetro 'campo' precisa ser uma string não vazia com o nome do campo do anexo.")
705
+ raise ValueError(
706
+ "O parâmetro 'campo' precisa ser uma string não vazia com o nome do campo do anexo."
707
+ )
612
708
 
613
709
  campo = str(campo).strip().lower()
614
710
 
615
711
  # Convert bytes to base64
616
712
  def __bytes_to_base64(image_bytes):
617
713
 
618
- return base64.b64encode(image_bytes).decode('utf-8')
619
-
714
+ return base64.b64encode(image_bytes).decode("utf-8")
715
+
620
716
  def __formatar_tamanho(tamanho_bytes):
621
717
  # Converte o valor de string para inteiro
622
718
  tamanho_bytes = int(tamanho_bytes)
623
-
719
+
624
720
  # Define os múltiplos de bytes
625
- unidades = ['B', 'KB', 'MB', 'GB', 'TB']
721
+ unidades = ["B", "KB", "MB", "GB", "TB"]
626
722
 
627
723
  # Itera sobre as unidades até encontrar a maior possível
628
724
  for unidade in unidades:
629
725
  if tamanho_bytes < 1024:
630
726
  return f"{tamanho_bytes:.2f} {unidade}"
631
727
  tamanho_bytes /= 1024
632
-
728
+
633
729
  # Caso o valor seja maior que o esperado (Exabyte ou superior)
634
730
  return f"{tamanho_bytes:.2f} PB" # Petabyte
635
731
 
636
- anexo_dict = {"var_servicenow": campo, "anexos":[]}
637
-
732
+ anexo_dict = {"var_servicenow": campo, "anexos": []}
733
+
638
734
  try:
639
- if campo == 'default':
735
+ if campo == "default":
640
736
  url = f"{self.api_url}/now/attachment?sysparm_query=table_name={tabela}^table_sys_id={sys_id}"
641
737
  response = self.__request_download(url, timeout=timeout)
642
738
  response = response.get("result")
@@ -646,18 +742,27 @@ class ServiceNow:
646
742
  "file_name": attachment["file_name"],
647
743
  "size": __formatar_tamanho(attachment["size_bytes"]),
648
744
  "content_type": attachment["content_type"],
649
- "base64": None
745
+ "base64": None,
650
746
  }
651
- byte_response = self.__request_download(attachment["download_link"], timeout=timeout)
747
+ byte_response = self.__request_download(
748
+ attachment["download_link"], timeout=timeout
749
+ )
652
750
  byte_response = byte_response.get("result")
653
751
  if byte_response.status_code == 200:
654
752
  arquivo["base64"] = __bytes_to_base64(byte_response.content)
655
753
  if download_dir:
656
- with open(os.path.join(download_dir, arquivo["file_name"]), 'wb') as f:
754
+ with open(
755
+ os.path.join(download_dir, arquivo["file_name"]),
756
+ "wb",
757
+ ) as f:
657
758
  f.write(byte_response.content)
658
759
  anexo_dict["anexos"].append(arquivo)
659
760
  return {"success": True, "result": anexo_dict}
660
- return {"success": False, "error": response.json(), "status_code": response.status_code}
761
+ return {
762
+ "success": False,
763
+ "error": response.json(),
764
+ "status_code": response.status_code,
765
+ }
661
766
 
662
767
  else:
663
768
  url = f"{self.api_url}/now/table/{tabela}?sysparm_query=sys_id={sys_id}&sysparm_fields={campo}&sysparm_display_value=all"
@@ -667,23 +772,38 @@ class ServiceNow:
667
772
  campo_data = response.json()["result"][0].get(campo)
668
773
  if campo_data:
669
774
  attachment_id = campo_data["value"]
670
- attachment_url = f"{self.api_url}/now/attachment/{attachment_id}/file"
671
- byte_response = self.__request_download(attachment["download_link"], timeout=timeout)
775
+ attachment_url = (
776
+ f"{self.api_url}/now/attachment/{attachment_id}/file"
777
+ )
778
+ byte_response = self.__request_download(
779
+ attachment["download_link"], timeout=timeout
780
+ )
672
781
  byte_response = byte_response.get("result")
673
782
  if byte_response.status_code == 200:
674
783
  arquivo = {
675
784
  "file_name": campo_data["display_value"],
676
- "size": __formatar_tamanho(byte_response.headers.get("Content-Length", 0)),
677
- "content_type": byte_response.headers.get("Content-Type"),
678
- "base64": __bytes_to_base64(byte_response.content)
785
+ "size": __formatar_tamanho(
786
+ byte_response.headers.get("Content-Length", 0)
787
+ ),
788
+ "content_type": byte_response.headers.get(
789
+ "Content-Type"
790
+ ),
791
+ "base64": __bytes_to_base64(byte_response.content),
679
792
  }
680
793
  if download_dir:
681
- with open(os.path.join(download_dir, arquivo["file_name"]), 'wb') as f:
794
+ with open(
795
+ os.path.join(download_dir, arquivo["file_name"]),
796
+ "wb",
797
+ ) as f:
682
798
  f.write(byte_response.content)
683
799
  anexo_dict["anexos"].append(arquivo)
684
- return {"success": True, "result": anexo_dict, "error" : None}
685
- return {"success": False, "error": response.json(), "status_code": response.status_code}
800
+ return {"success": True, "result": anexo_dict, "error": None}
801
+ return {
802
+ "success": False,
803
+ "error": response.json(),
804
+ "status_code": response.status_code,
805
+ }
686
806
 
687
807
  except Exception as e:
688
808
  logging.debug("Erro ao obter anexos.")
689
- return {"success": False, "error": str(e)}
809
+ return {"success": False, "error": str(e)}
@@ -33,6 +33,7 @@ class WebScreenBotCity(WebScreenAbstract):
33
33
  no_sandbox: bool = True,
34
34
  timeout: int = 10,
35
35
  security: bool = False,
36
+ download_path: str = "./tmp/",
36
37
  ):
37
38
  """
38
39
  Inicializa a classe com as configurações para o WebBot.
@@ -65,6 +66,7 @@ class WebScreenBotCity(WebScreenAbstract):
65
66
  self.web_bot.headless = headless
66
67
  self.web_bot.disable_gpu = disable_gpu
67
68
  self.web_bot.no_sandbox = no_sandbox
69
+ self.web_bot.download_folder_path = download_path
68
70
 
69
71
  except Exception as e:
70
72
  raise ValueError("Erro na inicialização da classe:", e)
@@ -1,10 +1,10 @@
1
1
  import time
2
+ import os
2
3
 
3
4
  # Selenium
4
5
  from selenium import webdriver
5
6
  from selenium.webdriver.common.by import By
6
7
  from selenium.webdriver.common.keys import Keys
7
- from webdriver_manager.chrome import ChromeDriverManager
8
8
  from selenium.webdriver.support.ui import WebDriverWait
9
9
  from selenium.webdriver.common.action_chains import ActionChains
10
10
  from selenium.webdriver.support import expected_conditions as EC
@@ -39,6 +39,7 @@ class WebScreenSelenium(WebScreenAbstract):
39
39
  timeout: int = 10,
40
40
  security: bool = False,
41
41
  scale: float = 0.8,
42
+ download_path: str = "./tmp/",
42
43
  ):
43
44
  """
44
45
  Inicializa a classe responsável por configurar e gerenciar o WebDriver do Selenium.
@@ -96,6 +97,16 @@ class WebScreenSelenium(WebScreenAbstract):
96
97
  chrome_options.add_argument("--disable-extensions")
97
98
  chrome_options.add_argument("--window-size=1920,1080")
98
99
  chrome_options.add_argument(f"--force-device-scale-factor={scale}")
100
+ os.makedirs(download_path, exist_ok=True)
101
+ chrome_options.add_experimental_option(
102
+ "prefs",
103
+ {
104
+ "download.default_directory": os.path.abspath(download_path),
105
+ "download.prompt_for_download": False, # Não perguntar onde salvar
106
+ "directory_upgrade": True,
107
+ "safebrowsing.enabled": True, # Para evitar bloqueios do Chrome
108
+ },
109
+ )
99
110
 
100
111
  chrome_options.add_argument(
101
112
  "user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
csc_cia_stne/web.py CHANGED
@@ -16,6 +16,7 @@ class web_screen:
16
16
  disable_gpu: bool = True,
17
17
  no_sandbox: bool = True,
18
18
  security: bool = True,
19
+ download_path: str = "./tmp/",
19
20
  ):
20
21
  """
21
22
  Inicializa a instância da classe Web.
@@ -59,6 +60,7 @@ class web_screen:
59
60
  no_sandbox=no_sandbox,
60
61
  timeout=timeout,
61
62
  security=security,
63
+ download_path=download_path,
62
64
  )
63
65
  if model.upper() == "SELENIUM"
64
66
  else WebScreenBotCity(
@@ -67,5 +69,6 @@ class web_screen:
67
69
  no_sandbox=no_sandbox,
68
70
  timeout=timeout,
69
71
  security=security,
72
+ download_path=download_path,
70
73
  )
71
74
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csc_cia_stne
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Biblioteca do time CSC-CIA utilizada no desenvolvimento de RPAs
5
5
  License: MIT
6
6
  Keywords: karavela,csc,cia,stone,rpa,botcity,stne
@@ -5,16 +5,16 @@ csc_cia_stne/email.py,sha256=K0DcgxTPKa_Rz_SJekjbW8Nw_1L9s_iuDDxZ-69bZfM,8387
5
5
  csc_cia_stne/ftp.py,sha256=M9WCaq2hm56jGyszNaPinliFaZS0BNrT7VrVPMjkMg4,10988
6
6
  csc_cia_stne/gcp_bigquery.py,sha256=foq8azvvv_f7uikMDslX9RcUIrx7RAS-Sn0AGW0QFQc,7231
7
7
  csc_cia_stne/gcp_bucket.py,sha256=nP77BtagZ7jQq6lS88ZEa1qshzBza6e_LvhgS3_JJJk,10268
8
- csc_cia_stne/google_drive.py,sha256=k6GnM8bxQUPbXhaK6Sa4JpWrCcJ0vzYgXP8Uexy7YR0,16073
8
+ csc_cia_stne/google_drive.py,sha256=VOaI_ZehDTqqNqk5aVqaU4g6yz_ClsPLYArqgg6-SPs,16348
9
9
  csc_cia_stne/karavela.py,sha256=jJCYX43D49gGuzmwwK6bN9XVnv2dXdp9iHnnV5H1LMQ,4794
10
10
  csc_cia_stne/logger_json.py,sha256=CXxSCOFGMymDi8XE9SKnPKjW4D0wJLqDLnxqePS26i8,3187
11
11
  csc_cia_stne/logger_rich.py,sha256=fklgkBb4rblKQd7YZ3q-eWfhGg9eflO2k2-z4pGh_yo,5201
12
12
  csc_cia_stne/provio.py,sha256=G-pDnHYLSp97joc7S7dvwjNvl3omnTmvdi3rOPQf5GA,3987
13
- csc_cia_stne/servicenow.py,sha256=cJtNtLZ8glWfs3OAzl78ZFlPyPz39CSBxHqpTdUU7i0,32136
13
+ csc_cia_stne/servicenow.py,sha256=2AeG9icBOjwKVVmGbcJvM2mPEFFzYSA1pN1qJYbnM2c,33721
14
14
  csc_cia_stne/slack.py,sha256=sPLeaQh_JewLcrBDjjwUgbjtC7d1Np03OTy06JimMV4,8117
15
15
  csc_cia_stne/stne_admin.py,sha256=4v_BVQAwZeWmxvjDOkwFAl9yIxJ3r54BY7pRgAgSXEM,24220
16
16
  csc_cia_stne/wacess.py,sha256=g-bWZNpm_tU7UsW1G_rqh_2fW2KShvxZHGOerX8DuQw,26768
17
- csc_cia_stne/web.py,sha256=g1T6GKfCZ77uRfzkHc_MGz8shUhyZ-VUIWdvAjQFk-Y,2377
17
+ csc_cia_stne/web.py,sha256=TBXUJ5eS36fytU3oFDuJsogi0sgw_qKgK-uphx4Nvxo,2506
18
18
  csc_cia_stne/utilitarios/__init__.py,sha256=eUaRttjY-F_zHAHC3L22VZxWyQd_k9zso-Mjz01Rj9o,306
19
19
  csc_cia_stne/utilitarios/functions/__init__.py,sha256=tBN1a6ZlvS1kLXIGopaqecJvlkOhLvLeYjp3JCAspWs,471
20
20
  csc_cia_stne/utilitarios/functions/func_b64.py,sha256=XGU34BIQQXWXBS0yM2B4A2wDlcrMl1unIJXjq4lpLnk,1254
@@ -34,10 +34,10 @@ csc_cia_stne/utilitarios/validations/waccess.py,sha256=8yfOrmIPUSLzbCt6P0F6vj3Fk
34
34
  csc_cia_stne/utilitarios/validations/web_validator.py,sha256=HYKYSpDv1RvRjZIuwTPt-AbEz-9392MxM_O329iYuSA,5722
35
35
  csc_cia_stne/utilitarios/web_screen/__init__.py,sha256=5QcOPXKd95SvP2DoZiHS0gaU68GlyFD9pQ9kae_9D1Q,100
36
36
  csc_cia_stne/utilitarios/web_screen/web_screen_abstract.py,sha256=PjL8Vgfj_JdKidia7RFyCkro3avYLQu4RZRos41sh3w,3241
37
- csc_cia_stne/utilitarios/web_screen/web_screen_botcity.py,sha256=3AzcP86nwBmitdXQNscv8fvg6dUogg2cAbG5KbuyqMM,12196
38
- csc_cia_stne/utilitarios/web_screen/web_screen_selenium.py,sha256=xtnU3gLHPhptrz7D4TzAXQNC_7xl01GxVFfE7VkMV_U,15104
39
- csc_cia_stne-0.1.2.dist-info/licenses/LICENCE,sha256=LPGMtgKki2C3KEZP7hDhA1HBrlq5JCHkIeStUCLEMx4,1073
40
- csc_cia_stne-0.1.2.dist-info/METADATA,sha256=Zq5e13HVgOUHN0ysAvytwUCRX44jEbr7ZtfvCfYq4s8,1418
41
- csc_cia_stne-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
42
- csc_cia_stne-0.1.2.dist-info/top_level.txt,sha256=ldo7GVv3tQx5KJvwBzdZzzQmjPys2NDVVn1rv0BOF2Q,13
43
- csc_cia_stne-0.1.2.dist-info/RECORD,,
37
+ csc_cia_stne/utilitarios/web_screen/web_screen_botcity.py,sha256=Xi5YJjl2pcxlX3OimqcBWRNXZEpAE7asyUjDJ4Oho5U,12297
38
+ csc_cia_stne/utilitarios/web_screen/web_screen_selenium.py,sha256=JLIcPJE9ZX3Pd6zG6oTRMqqUAY063UzLY3ReRlxmiSM,15581
39
+ csc_cia_stne-0.1.3.dist-info/licenses/LICENCE,sha256=LPGMtgKki2C3KEZP7hDhA1HBrlq5JCHkIeStUCLEMx4,1073
40
+ csc_cia_stne-0.1.3.dist-info/METADATA,sha256=9m7R6yZRqbL9ozjOe7vBBzsSh_uyiPnlftqacP0jDUY,1418
41
+ csc_cia_stne-0.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
42
+ csc_cia_stne-0.1.3.dist-info/top_level.txt,sha256=ldo7GVv3tQx5KJvwBzdZzzQmjPys2NDVVn1rv0BOF2Q,13
43
+ csc_cia_stne-0.1.3.dist-info/RECORD,,