rpa-suite 1.5.2__py3-none-any.whl → 1.5.4__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.
rpa_suite/__init__.py CHANGED
@@ -1,65 +1,66 @@
1
1
  # rpa_suite/__init__.py
2
2
 
3
3
  """
4
- RPA Suite is a Python module that provides a set of tools for process automation.
5
-
6
- To use the module, import it as follows:
7
- >>> from rpa_suite import rpa
8
-
9
- Example of usage:
10
- >>> from rpa_suite import rpa
11
- >>> rpa.email.send_smtp(
12
- ... email_user="your@email.com",
13
- ... email_password="your_password",
14
- ... email_to="destination@email.com",
15
- ... subject_title="Test",
16
- ... body_message="<p>Test message</p>"
17
- ... )
18
- >>> rpa.alert_print("Hello World")
19
-
20
- Available modules:
21
- ``clock``: Utilities for time and stopwatch manipulation
22
- ``date``: Functions for date manipulation
23
- ``email``: Functionalities for sending emails via SMTP
24
- ``directory``: Operations with directories
25
- ``file``: File manipulation
26
- ``log``: Logging system
27
- ``printer``: Functions for formatted output
28
- ``regex``: Operations with regular expressions
29
- ``validate``: Data validation functions
30
- ``Browser``: Object Browser automation functions (neeeds Selenium and Webdriver_Manager)
4
+ RPA Suite is a Python module that provides a set of tools for process automation.
31
5
 
32
- pt-br
33
- -----
34
- RPA Suite é um módulo Python que fornece um conjunto de ferramentas para automação de processos.
35
-
36
- Para utilizar o módulo, importe-o da seguinte forma:
37
- >>> from rpa_suite import rpa
38
-
39
- Exemplo de uso:
40
- >>> from rpa_suite import rpa
41
- >>> rpa.email.send_smtp(
42
- ... email_user="seu@email.com",
43
- ... email_password="sua_senha",
44
- ... email_to="destino@email.com",
45
- ... subject_title="Teste",
46
- ... body_message="<p>Mensagem de teste</p>"
47
- ... )
48
- >>> rpa.alert_print("Hello World")
49
-
50
- Módulos disponíveis:
51
- ``clock``: Utilitários para manipulação de tempo e cronômetro
52
- ``date``: Funções para manipulação de datas
53
- ``email``: Funcionalidades para envio de emails via SMTP
54
- ``directory``: Operações com diretórios
55
- ``file``: Manipulação de arquivos
56
- ``log``: Sistema de logging
57
- ``printer``: Funções para output formatado
58
- ``regex``: Operações com expressões regulares
59
- ``validate``: Funções de validação de dados
60
- ``Browser``: Objeto de Automação de Navegadores (necessario Selenium e Webdriver_Manager)
6
+ To use the module, import it as follows:
7
+ >>> from rpa_suite import rpa
8
+
9
+ Example of usage:
10
+ >>> from rpa_suite import rpa
11
+ >>> rpa.email.send_smtp(
12
+ ... email_user="your@email.com",
13
+ ... email_password="your_password",
14
+ ... email_to="destination@email.com",
15
+ ... subject_title="Test",
16
+ ... body_message="<p>Test message</p>"
17
+ ... )
18
+ >>> rpa.alert_print("Hello World")
19
+
20
+ Available modules:
21
+ ``clock``: Utilities for time and stopwatch manipulation
22
+ ``date``: Functions for date manipulation
23
+ ``email``: Functionalities for sending emails via SMTP
24
+ ``directory``: Operations with directories
25
+ ``file``: File manipulation
26
+ ``log``: Logging system
27
+ ``printer``: Functions for formatted output
28
+ ``regex``: Operations with regular expressions
29
+ ``validate``: Data validation functions
30
+ ``Browser``: Object Browser automation functions (neeeds Selenium and Webdriver_Manager)
31
+
32
+ pt-br
33
+ -----
34
+ RPA Suite é um módulo Python que fornece um conjunto de ferramentas para automação de processos.
35
+
36
+ Para utilizar o módulo, importe-o da seguinte forma:
37
+ >>> from rpa_suite import rpa
38
+
39
+ Exemplo de uso:
40
+ >>> from rpa_suite import rpa
41
+ >>> rpa.email.send_smtp(
42
+ ... email_user="seu@email.com",
43
+ ... email_password="sua_senha",
44
+ ... email_to="destino@email.com",
45
+ ... subject_title="Teste",
46
+ ... body_message="<p>Mensagem de teste</p>"
47
+ ... )
48
+ >>> rpa.alert_print("Hello World")
49
+
50
+ Módulos disponíveis:
51
+ ``clock``: Utilitários para manipulação de tempo e cronômetro
52
+ ``date``: Funções para manipulação de datas
53
+ ``email``: Funcionalidades para envio de emails via SMTP
54
+ ``directory``: Operações com diretórios
55
+ ``file``: Manipulação de arquivos
56
+ ``log``: Sistema de logging
57
+ ``printer``: Funções para output formatado
58
+ ``regex``: Operações com expressões regulares
59
+ ``validate``: Funções de validação de dados
60
+ ``Browser``: Objeto de Automação de Navegadores (necessario Selenium e Webdriver_Manager)
61
61
  """
62
62
 
63
63
  # allows importing the rpa_suite module without the package name
64
64
  from .suite import rpa
65
+
65
66
  rpa
@@ -36,11 +36,12 @@ from .parallel import ParallelRunner
36
36
  from .asyncrun import AsyncRunner
37
37
 
38
38
 
39
-
40
39
  # On this case, we are importing the Browser class only if the selenium and webdriver_manager modules are installed.
41
40
  # This is useful to avoid unnecessary imports and dependencies if the user does not need the Browser functionality.
42
41
  import importlib.util
43
42
 
44
43
  # from .browser import Browser
45
- if importlib.util.find_spec("selenium") and importlib.util.find_spec("webdriver_manager"):
44
+ if importlib.util.find_spec("selenium") and importlib.util.find_spec(
45
+ "webdriver_manager"
46
+ ):
46
47
  from .browser import Browser
@@ -8,17 +8,17 @@ import traceback
8
8
  from functools import wraps
9
9
 
10
10
 
11
- T = TypeVar('T')
11
+ T = TypeVar("T")
12
12
 
13
13
 
14
14
  class AsyncRunner(Generic[T]):
15
15
  """
16
16
  Class to execute asynchronous functions while maintaining the main application flow.
17
-
17
+
18
18
  Allows executing asynchronous functions and retrieving their results later.
19
19
  Optimized for I/O bound operations (network, files, etc).
20
20
  """
21
-
21
+
22
22
  def __init__(self):
23
23
  """Start AsyncRunner."""
24
24
  self._task = None
@@ -29,24 +29,26 @@ class AsyncRunner(Generic[T]):
29
29
  def _to_async(func: Callable) -> Callable:
30
30
  """
31
31
  Converts a synchronous function into an asynchronous one if necessary.
32
-
32
+
33
33
  Args:
34
34
  func: The function to be converted.
35
-
35
+
36
36
  Returns:
37
37
  A callable that is asynchronous.
38
38
  """
39
+
39
40
  @wraps(func)
40
41
  async def wrapper(*args, **kwargs):
41
42
  if asyncio.iscoroutinefunction(func):
42
43
  return await func(*args, **kwargs)
43
44
  return await asyncio.to_thread(func, *args, **kwargs)
45
+
44
46
  return wrapper
45
47
 
46
48
  async def _execute_function(self, function, args, kwargs):
47
49
  """
48
50
  Executes the function and manages results/errors.
49
-
51
+
50
52
  Args:
51
53
  function: The function to be executed.
52
54
  args: Positional arguments for the function.
@@ -55,46 +57,42 @@ class AsyncRunner(Generic[T]):
55
57
  try:
56
58
  async_func = self._to_async(function)
57
59
  result = await async_func(*args, **kwargs)
58
-
59
- self._result = {
60
- 'status': 'success',
61
- 'result': result,
62
- 'success': True
63
- }
64
-
60
+
61
+ self._result = {"status": "success", "result": result, "success": True}
62
+
65
63
  except Exception as e:
66
64
  self._result = {
67
- 'status': 'error',
68
- 'error': str(e),
69
- 'traceback': traceback.format_exc(),
70
- 'success': False
65
+ "status": "error",
66
+ "error": str(e),
67
+ "traceback": traceback.format_exc(),
68
+ "success": False,
71
69
  }
72
70
 
73
- def run(self, function: Callable[..., T], *args, **kwargs) -> 'AsyncRunner[T]':
71
+ def run(self, function: Callable[..., T], *args, **kwargs) -> "AsyncRunner[T]":
74
72
  """
75
73
  Starts the execution of the function asynchronously.
76
-
74
+
77
75
  Args:
78
76
  function: The function to be executed.
79
77
  *args: Positional arguments for the function.
80
78
  **kwargs: Keyword arguments for the function.
81
-
79
+
82
80
  Returns:
83
81
  self: Returns the instance itself.
84
82
  """
85
83
  self._result.clear()
86
84
  self._start_time = time.time()
87
-
85
+
88
86
  # Creates and schedules the asynchronous task
89
87
  loop = asyncio.get_event_loop()
90
88
  self._task = loop.create_task(self._execute_function(function, args, kwargs))
91
-
89
+
92
90
  return self
93
91
 
94
92
  def is_running(self) -> bool:
95
93
  """
96
94
  Checks if the task is still running.
97
-
95
+
98
96
  Returns:
99
97
  True if the task is running, False otherwise.
100
98
  """
@@ -103,33 +101,33 @@ class AsyncRunner(Generic[T]):
103
101
  async def get_result(self, timeout: Optional[float] = None) -> Dict[str, Any]:
104
102
  """
105
103
  Retrieves the result of the asynchronous execution.
106
-
104
+
107
105
  Args:
108
106
  timeout: Maximum time (in seconds) to wait.
109
-
107
+
110
108
  Returns:
111
109
  A dictionary with the result or error information.
112
110
  """
113
111
  if self._task is None:
114
112
  return {
115
- 'success': False,
116
- 'error': 'No task has been started',
117
- 'execution_time': 0
113
+ "success": False,
114
+ "error": "No task has been started",
115
+ "execution_time": 0,
118
116
  }
119
117
 
120
118
  try:
121
119
  await asyncio.wait_for(self._task, timeout=timeout)
122
-
120
+
123
121
  except asyncio.TimeoutError:
124
122
  self._task.cancel()
125
123
  return {
126
- 'success': False,
127
- 'error': f'Operation canceled due to timeout after {time.time() - self._start_time:.2f} seconds',
128
- 'execution_time': time.time() - self._start_time
124
+ "success": False,
125
+ "error": f"Operation canceled due to timeout after {time.time() - self._start_time:.2f} seconds",
126
+ "execution_time": time.time() - self._start_time,
129
127
  }
130
128
 
131
129
  result = dict(self._result)
132
- result['execution_time'] = time.time() - self._start_time
130
+ result["execution_time"] = time.time() - self._start_time
133
131
  return result
134
132
 
135
133
  def cancel(self) -> None:
rpa_suite/core/browser.py CHANGED
@@ -16,28 +16,27 @@ from time import sleep
16
16
  import os, requests
17
17
 
18
18
 
19
- class Browser():
20
-
19
+ class Browser:
21
20
  """
22
21
  Browser Object for Automation (Work in Progress)
23
- This class provides an interface for automating browser interactions using
24
- Google Chrome with a debugging port. It includes methods for starting,
25
- configuring, navigating, and interacting with the browser. The implementation
22
+ This class provides an interface for automating browser interactions using
23
+ Google Chrome with a debugging port. It includes methods for starting,
24
+ configuring, navigating, and interacting with the browser. The implementation
26
25
  is still under development and may require further enhancements.
27
-
26
+
28
27
  Attributes:
29
28
  driver: The WebDriver instance used to control the browser.
30
29
  port (int): The debugging port used to connect to the browser. Default is 9393.
31
30
  path_driver (str): The path to the ChromeDriver executable.
32
-
31
+
33
32
  Methods:
34
33
  __init__(port: int = 9393, close_all_chrome_on_this_port: bool = False):
35
- Initializes the Browser object with the specified debugging port and
34
+ Initializes the Browser object with the specified debugging port and
36
35
  optionally closes all Chrome instances running on the same port.
37
36
  configure_browser() -> None:
38
37
  Configures the browser with debugging options and initializes the WebDriver.
39
38
  start_browser(close_chrome_on_this_port: bool = True, display_message: bool = False):
40
- Starts the Chrome browser with the specified debugging port and initializes
39
+ Starts the Chrome browser with the specified debugging port and initializes
41
40
  the WebDriver.
42
41
  find_ele(value, by=By.XPATH, timeout=12, display_message=True):
43
42
  Finds a single element on the page using the specified locator strategy.
@@ -47,29 +46,29 @@ class Browser():
47
46
  Closes all Chrome processes forcefully.
48
47
  close_browser(display_message: bool = False):
49
48
  Closes the browser instance and terminates the associated Chrome processes.
50
-
49
+
51
50
  pt-br
52
51
  ----------
53
52
  Objeto Browser para Automação (Em Desenvolvimento)
54
- Esta classe fornece uma interface para automação de interações com o navegador
55
- Google Chrome utilizando uma porta de depuração. Inclui métodos para iniciar,
56
- configurar, navegar e interagir com o navegador. A implementação ainda está em
53
+ Esta classe fornece uma interface para automação de interações com o navegador
54
+ Google Chrome utilizando uma porta de depuração. Inclui métodos para iniciar,
55
+ configurar, navegar e interagir com o navegador. A implementação ainda está em
57
56
  desenvolvimento e pode requerer melhorias adicionais.
58
-
57
+
59
58
  Atributos:
60
59
  driver: A instância do WebDriver usada para controlar o navegador.
61
60
  port (int): A porta de depuração usada para conectar ao navegador. O padrão é 9393.
62
61
  path_driver (str): O caminho para o executável do ChromeDriver.
63
-
62
+
64
63
  Métodos:
65
64
  __init__(port: int = 9393, close_all_chrome_on_this_port: bool = False):
66
- Inicializa o objeto Browser com a porta de depuração especificada e,
67
- opcionalmente, fecha todas as instâncias do Chrome que estão sendo executadas
65
+ Inicializa o objeto Browser com a porta de depuração especificada e,
66
+ opcionalmente, fecha todas as instâncias do Chrome que estão sendo executadas
68
67
  na mesma porta.
69
68
  configure_browser() -> None:
70
69
  Configura o navegador com opções de depuração e inicializa o WebDriver.
71
70
  start_browser(close_chrome_on_this_port: bool = True, display_message: bool = False):
72
- Inicia o navegador Chrome com a porta de depuração especificada e inicializa
71
+ Inicia o navegador Chrome com a porta de depuração especificada e inicializa
73
72
  o WebDriver.
74
73
  find_ele(value, by=By.XPATH, timeout=12, display_message=True):
75
74
  Localiza um único elemento na página usando a estratégia de localização especificada.
@@ -84,12 +83,13 @@ class Browser():
84
83
  driver: None
85
84
  port: int = None
86
85
  path_driver = None
87
-
86
+
88
87
  def __init__(self, port: int = 9393, close_all_chrome_on_this_port: bool = False):
89
88
  self.port = port
90
89
  self.path_driver = ChromeDriverManager().install()
91
90
 
92
- if close_all_chrome_on_this_port: self._close_all_chrome()
91
+ if close_all_chrome_on_this_port:
92
+ self._close_all_chrome()
93
93
  ...
94
94
 
95
95
  def configure_browser(self) -> None:
@@ -102,33 +102,40 @@ class Browser():
102
102
  FileNotFoundError: If the specified path to the ChromeDriver executable does not exist.
103
103
  Exception: For any other errors encountered during the browser configuration process.
104
104
  """
105
-
105
+
106
106
  try:
107
107
  # Use the absolute path from comment
108
-
108
+
109
109
  options = Options()
110
- options.add_experimental_option("debuggerAddress",
111
- f"127.0.0.1:{str(self.port)}")
112
-
113
- # Additional configs
110
+ options.add_experimental_option(
111
+ "debuggerAddress", f"127.0.0.1:{str(self.port)}"
112
+ )
113
+
114
+ # Additional configs
114
115
  options.add_argument("--start-maximized")
115
116
  options.add_argument("--disable-notifications")
116
-
117
+
117
118
  # Verifica se o caminho do driver está correto
118
119
  if not os.path.exists(self.path_driver):
119
- raise FileNotFoundError(f'O caminho do driver não foi encontrado: {self.path_driver}')
120
-
120
+ raise FileNotFoundError(
121
+ f"O caminho do driver não foi encontrado: {self.path_driver}"
122
+ )
123
+
121
124
  # Create driver with options and chromedriver path
122
125
  self.driver = webdriver.Chrome(
123
- #service=self.path_driver,
126
+ # service=self.path_driver,
124
127
  options=options,
125
- keep_alive=True
128
+ keep_alive=True,
126
129
  )
127
130
 
128
131
  except Exception as e:
129
- error_print(f'Erro durante a função: {self.configure_browser.__name__}! Error: {str(e)}.')
132
+ error_print(
133
+ f"Erro durante a função: {self.configure_browser.__name__}! Error: {str(e)}."
134
+ )
130
135
 
131
- def start_browser(self, close_chrome_on_this_port: bool = True, display_message: bool = False):
136
+ def start_browser(
137
+ self, close_chrome_on_this_port: bool = True, display_message: bool = False
138
+ ):
132
139
  """
133
140
  Starts a Chrome browser instance with remote debugging enabled.
134
141
  Args:
@@ -143,67 +150,74 @@ class Browser():
143
150
  - Configures the browser instance using the `configure_browser` method.
144
151
  - Optionally displays a success message if `display_message` is True.
145
152
  """
146
-
153
+
147
154
  try:
148
- if close_chrome_on_this_port: self.close_browser()
155
+ if close_chrome_on_this_port:
156
+ self.close_browser()
149
157
 
150
158
  # Inicia o Chrome com debugging port
151
- os.system(f'start chrome.exe --remote-debugging-port={str(self.port)} --user-data-dir="C:/temp/chrome_profile"')
159
+ os.system(
160
+ f'start chrome.exe --remote-debugging-port={str(self.port)} --user-data-dir="C:/temp/chrome_profile"'
161
+ )
152
162
 
153
163
  # Aguardar até que o Chrome esteja realmente aberto
154
164
  while True:
155
165
  try:
156
166
  # Tenta conectar ao Chrome na porta de depuração
157
- response = requests.get(f'http://127.0.0.1:{self.port}/json')
167
+ response = requests.get(f"http://127.0.0.1:{self.port}/json")
158
168
  if response.status_code == 200:
159
169
  break # O Chrome está aberto
160
170
  except requests.ConnectionError:
161
171
  sleep(1) # Espera um segundo antes de tentar novamente
162
-
172
+
163
173
  # Inicializa o Chrome com as opções
164
174
  self.configure_browser()
165
-
166
- if display_message: success_print(f'Browser: Iniciado com sucesso!')
167
-
168
- except Exception as e:
169
- error_print(f'Erro ao iniciar navegador: {str(e)}.')
170
175
 
176
+ if display_message:
177
+ success_print(f"Browser: Iniciado com sucesso!")
178
+
179
+ except Exception as e:
180
+ error_print(f"Erro ao iniciar navegador: {str(e)}.")
171
181
 
172
- def find_ele(self, value: str, by:By=By.XPATH, timeout=12, display_message=True):
182
+ def find_ele(self, value: str, by: By = By.XPATH, timeout=12, display_message=True):
173
183
  """
174
184
  Locate and return a web element on the page using the specified locator strategy.
175
185
  Args:
176
186
  value (str): The locator value to identify the web element.
177
- by (selenium.webdriver.common.by.By, optional): The locator strategy to use.
187
+ by (selenium.webdriver.common.by.By, optional): The locator strategy to use.
178
188
  Defaults to By.XPATH.
179
- timeout (int, optional): The maximum time to wait for the element to appear, in seconds.
189
+ timeout (int, optional): The maximum time to wait for the element to appear, in seconds.
180
190
  Defaults to 12.
181
- display_message (bool, optional): Whether to display an error message if the element
191
+ display_message (bool, optional): Whether to display an error message if the element
182
192
  is not found. Defaults to True.
183
193
  Returns:
184
194
  selenium.webdriver.remote.webelement.WebElement: The located web element if found.
185
195
  None: If the element is not found or an exception occurs.
186
196
  Raises:
187
- Exception: Propagates any exception encountered during the element search if
197
+ Exception: Propagates any exception encountered during the element search if
188
198
  `display_message` is set to False.
189
199
  """
190
-
200
+
191
201
  try:
192
202
  sleep(2)
193
203
  element = WebDriverWait(self.driver, timeout).until(
194
204
  EC.presence_of_element_located((by, value))
195
- ); return element
196
-
205
+ )
206
+ return element
207
+
197
208
  except Exception as e:
198
209
 
199
210
  if display_message:
200
- error_print(f'Erro durante a função: {self.find_ele.__name__}! Error: {str(e)}.')
211
+ error_print(
212
+ f"Erro durante a função: {self.find_ele.__name__}! Error: {str(e)}."
213
+ )
214
+ return None
215
+ else:
201
216
  return None
202
- else: return None
203
217
 
204
218
  # find elements (needs implementation)
205
219
  ...
206
-
220
+
207
221
  # navigate
208
222
  def get(self, url: str, display_message: bool = False):
209
223
  """
@@ -214,14 +228,14 @@ class Browser():
214
228
  Raises:
215
229
  Exception: If an error occurs while navigating to the URL, it logs the error message.
216
230
  """
217
-
231
+
218
232
  try:
219
233
  self.driver.get(url)
220
- if display_message: success_print(f'Browser: Navegando para: {url}')
221
-
222
- except Exception as e:
223
- error_print(f'Erro ao navegar para a URL: {url}. Error: {str(e)}.')
234
+ if display_message:
235
+ success_print(f"Browser: Navegando para: {url}")
224
236
 
237
+ except Exception as e:
238
+ error_print(f"Erro ao navegar para a URL: {url}. Error: {str(e)}.")
225
239
 
226
240
  def _close_all_browsers(self):
227
241
  """
@@ -233,11 +247,10 @@ class Browser():
233
247
  """
234
248
 
235
249
  try:
236
- os.system('taskkill /F /IM chrome.exe >nul 2>&1')
250
+ os.system("taskkill /F /IM chrome.exe >nul 2>&1")
237
251
  except:
238
252
  pass
239
253
 
240
-
241
254
  def close_browser(self, display_message: bool = False):
242
255
  """
243
256
  Fecha o navegador controlado pelo Selenium e encerra os processos relacionados ao Chrome.
@@ -257,46 +270,62 @@ class Browser():
257
270
  Observação:
258
271
  Use com cautela, especialmente o encerramento extremo, pois pode afetar outros processos do Chrome em execução.
259
272
  """
260
-
273
+
261
274
  try:
262
275
  # Primeiro tenta fechar todas as janelas via Selenium
263
276
  try:
264
277
  self.driver.close()
265
278
  except:
266
279
  pass
267
-
280
+
268
281
  # Depois tenta encerrar a sessão
269
282
  try:
270
283
  self.driver.quit()
271
284
  except:
272
285
  pass
273
-
286
+
274
287
  # Aguarda um momento para o processo ser liberado
275
288
  sleep(1)
276
-
289
+
277
290
  # Força o fechamento do processo específico do Chrome
278
- os.system(f'taskkill /f /im chrome.exe /fi "commandline like *--remote-debugging-port={str(self.port)}*" >nul 2>&1')
279
-
291
+ os.system(
292
+ f'taskkill /f /im chrome.exe /fi "commandline like *--remote-debugging-port={str(self.port)}*" >nul 2>&1'
293
+ )
294
+
280
295
  # Verifica se o processo foi realmente terminado
281
- check = os.system(f'tasklist /fi "imagename eq chrome.exe" /fi "commandline like *--remote-debugging-port={str(self.port)}*" >nul 2>&1')
282
-
296
+ check = os.system(
297
+ f'tasklist /fi "imagename eq chrome.exe" /fi "commandline like *--remote-debugging-port={str(self.port)}*" >nul 2>&1'
298
+ )
299
+
283
300
  if check == 0:
284
301
  # Processo ainda existe, tenta método mais agressivo
285
- os.system(f'taskkill /f /im chrome.exe /fi "commandline like *--remote-debugging-port={str(self.port)}*" /t >nul 2>&1')
286
- if display_message: alert_print(f'Browser: Fechado via força!')
287
-
302
+ os.system(
303
+ f'taskkill /f /im chrome.exe /fi "commandline like *--remote-debugging-port={str(self.port)}*" /t >nul 2>&1'
304
+ )
305
+ if display_message:
306
+ alert_print(f"Browser: Fechado via força!")
307
+
288
308
  else:
289
- if display_message: success_print(f'Browser: Fechado com sucesso!')
290
-
309
+ if display_message:
310
+ success_print(f"Browser: Fechado com sucesso!")
311
+
291
312
  except Exception as e:
292
-
293
-
313
+
294
314
  try:
295
- if display_message: alert_print(f'Erro ao fechar navegador: {str(e)}, Tentando meio mais forte!')
315
+ if display_message:
316
+ alert_print(
317
+ f"Erro ao fechar navegador: {str(e)}, Tentando meio mais forte!"
318
+ )
296
319
 
297
320
  # Último recurso - mata todos os processos do Chrome (use com cautela)
298
- os.system(f'taskkill /f /im chrome.exe /fi "commandline like *--remote-debugging-port={str(self.port)}*" /t >nul 2>&1')
299
- if display_message: alert_print(f'Browser: Fechado via força extrema!')
300
-
321
+ os.system(
322
+ f'taskkill /f /im chrome.exe /fi "commandline like *--remote-debugging-port={str(self.port)}*" /t >nul 2>&1'
323
+ )
324
+ if display_message:
325
+ alert_print(f"Browser: Fechado via força extrema!")
326
+
301
327
  except Exception as error_ultimate:
302
- if display_message: error_print(f'Falha crítica ao tentar fechar o navegador! Error: {str(error_ultimate)}!')
328
+ if display_message:
329
+ error_print(
330
+ f"Falha crítica ao tentar fechar o navegador! Error: {str(error_ultimate)}!"
331
+ )