bcpkgfox 0.15.30__py3-none-any.whl → 0.17.7__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.

Potentially problematic release.


This version of bcpkgfox might be problematic. Click here for more details.

bcpkgfox/__init__.py CHANGED
@@ -96,6 +96,20 @@ def create_dirs(specifics_dirs: Optional[list] = None, disable_print_response: b
96
96
  else:
97
97
  print(f" {DK_ORANGE}>{RESET} Todos os diretórios padrões presentes")
98
98
 
99
+ def resource_path(relative_path):
100
+ """
101
+ Returns the absolute path of a resource, whether running normally or in a PyInstaller executable.
102
+
103
+ Args:
104
+ relative_path (str): Relative path of the resource.
105
+
106
+ Returns:
107
+ str: Absolute path of the resource.
108
+ """
109
+ try: base_path = sys._MEIPASS
110
+ except AttributeError: base_path = os.path.abspath(".")
111
+ return os.path.join(base_path, relative_path)
112
+
99
113
  def initialize_driver(extension_path: Optional[str] = None, captcha_name: Optional[str] = None, captcha_api_key: Optional[str] = None) -> WebElement:
100
114
 
101
115
  """ Passe somente o nome da pasta, no mesmo diretório da main """
@@ -211,7 +225,7 @@ def wait_for_element_disappear(object, type, timeout=10):
211
225
 
212
226
  return find_elements.backcode__dont_use__wait_for_d(driver, object, type, timeout=tempo)
213
227
 
214
- def selectfox(elemento, method, key):
228
+ def selectfox(elemento, method, key, relative = None):
215
229
  """
216
230
  Seleciona uma opção em um elemento <select>.
217
231
 
@@ -219,6 +233,7 @@ def selectfox(elemento, method, key):
219
233
  - elemento: Elemento <select> encontrado pelo Selenium.
220
234
  - method: Método de seleção ('index', 'text' ou 'value').
221
235
  - key: Valor usado na seleção (índice, texto visível ou valor do atributo 'value').
236
+ - relative: Ao invés de selecionar um elemento identico, seleciona um elemento que apenas contém a 'key'
222
237
 
223
238
  - Exemplo:
224
239
  elemento_select = bc.find_element_with_wait("xpath", '//select[@value="VALUE_DO_PRIMEIRO_SELECT"]')
@@ -248,11 +263,17 @@ def selectfox(elemento, method, key):
248
263
  select.select_by_value(key)
249
264
 
250
265
  if method == "text":
251
- elements = WebDriverWait(elemento, 10).until(EC.visibility_of_all_elements_located((By.XPATH, '//option')))
266
+ elements = select.options
252
267
  for elm in elements:
253
- if key.lower() in elm.text.lower():
254
- select.select_by_visible_text(elm.text)
255
- return
268
+ if relative:
269
+ if key.lower().strip() in elm.text.lower().strip():
270
+ select.select_by_visible_text(elm.text)
271
+ return
272
+ else:
273
+ if key == elm.text:
274
+ select.select_by_visible_text(elm.text)
275
+ return
276
+
256
277
  raise ModuleNotFoundError(f"Option {key} não encontrada")
257
278
 
258
279
  if method == "index":
@@ -322,7 +343,6 @@ def cpf_or_cnpj(numero: str) -> str:
322
343
  janela = None
323
344
  @staticmethod
324
345
  def mostrar_mensagem(mensagem, tamanho_fonte=12, negrito=False, button: Optional[bool] = True):
325
-
326
346
  global janela
327
347
 
328
348
  try: fechar_janela(janela)
@@ -335,28 +355,61 @@ def mostrar_mensagem(mensagem, tamanho_fonte=12, negrito=False, button: Optional
335
355
  janela.title("Atenção!")
336
356
  janela.configure(bg="white")
337
357
 
338
- largura, altura = 400, 200
339
- pos_x = (janela.winfo_screenwidth() - largura) // 2
340
- pos_y = (janela.winfo_screenheight() - altura) // 2
341
- janela.geometry(f"{largura}x{altura}+{pos_x}+{pos_y}")
342
- janela.resizable(False, False)
343
- janela.attributes("-topmost", True)
344
-
345
358
  estilo_fonte = ("Helvetica", tamanho_fonte, "bold" if negrito else "normal")
346
359
 
347
- label = tk.Label(janela, text=mensagem, bg="white", fg="black",
348
- font=estilo_fonte, wraplength=380, justify="center")
349
- label.pack(expand=True, padx=20, pady=20)
360
+ # container para label + botões
361
+ container = tk.Frame(janela, bg="white")
362
+ container.pack(padx=20, pady=20)
363
+
364
+ label = tk.Label(container, text=mensagem, bg="white", fg="black",
365
+ font=estilo_fonte, wraplength=360, justify="center")
366
+ label.pack(fill="both", expand=True)
367
+
368
+ if isinstance(button, dict):
369
+ resultado = tk.IntVar()
370
+
371
+ def make_cmd(value):
372
+ return lambda: resultado.set(value)
373
+
374
+ frame_botoes = tk.Frame(container, bg="white")
375
+ frame_botoes.pack(pady=10)
376
+ for i, texto in enumerate(button.keys(), start=1):
377
+ tk.Button(frame_botoes, text=texto, command=make_cmd(i), width=10,
378
+ font=("Helvetica", 10)).pack(side="left", padx=5)
379
+
380
+ janela.grab_set()
381
+ janela.focus_set()
382
+ janela.update_idletasks()
383
+ # ajusta ao tamanho real
384
+ w = janela.winfo_reqwidth()
385
+ h = janela.winfo_reqheight()
386
+ x = (janela.winfo_screenwidth() - w) // 2
387
+ y = (janela.winfo_screenheight() - h) // 2
388
+ janela.geometry(f"{w}x{h}+{x}+{y}")
389
+ janela.wait_variable(resultado)
390
+ root.destroy()
391
+ return resultado.get()
350
392
 
351
- if button:
352
- tk.Button(janela, text="OK", command=lambda: (janela.destroy(), root.destroy()),
353
- width=10, font=("Helvetica", 10)).pack(pady=10)
354
-
355
- janela.grab_set()
356
- janela.focus_set()
357
- if button: janela.wait_window()
358
- else: root.mainloop()
359
- return janela
393
+ else:
394
+ if button:
395
+ tk.Button(container, text="OK",
396
+ command=lambda: (janela.destroy(), root.destroy()),
397
+ width=10, font=("Helvetica", 10)).pack(pady=10)
398
+
399
+ janela.grab_set()
400
+ janela.focus_set()
401
+ janela.update_idletasks()
402
+ w = janela.winfo_reqwidth()
403
+ h = janela.winfo_reqheight()
404
+ x = (janela.winfo_screenwidth() - w) // 2
405
+ y = (janela.winfo_screenheight() - h) // 2
406
+ janela.geometry(f"{w}x{h}+{x}+{y}")
407
+
408
+ if button:
409
+ janela.wait_window()
410
+ else:
411
+ root.mainloop()
412
+ return janela
360
413
 
361
414
  def fechar_janela(janela_=None):
362
415
  global janela
@@ -404,6 +457,6 @@ def move_mouse_smoothly(element, click=False):
404
457
  RESET, GR, ORANGE, DK_ORANGE = "\033[0m", "\033[38;5;34m", "\033[38;5;214m", "\033[38;5;130m"
405
458
  result = subprocess.run(['pip', 'show', "bcpkgfox"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
406
459
  version_line = next((line for line in result.stdout.decode().splitlines() if line.startswith('Version:')), None)
407
- try: print(f"\n\n{ORANGE}Biblioteca BCFOX importada - {re.sub(r"[^0-9.b]", "", version_line)}{RESET}")
460
+ try: print(f"\n\n{ORANGE}Biblioteca BCFOX importada - {re.sub(r'[^0-9.b]', '', version_line)}{RESET}")
408
461
  except: pass
409
462
  create_dirs()
bcpkgfox/clean.py ADDED
@@ -0,0 +1,257 @@
1
+ import subprocess
2
+ import threading
3
+ import argparse
4
+ import time
5
+ import sys
6
+ import os
7
+
8
+
9
+ class clean_main:
10
+
11
+ def __init__(self):
12
+ self.current_dir = os.getcwd()
13
+ self.args = None
14
+ self.file = None
15
+
16
+ def main(self):
17
+
18
+ # Detect the user input
19
+ self.args = self.parser.parse_args()
20
+ self.file = self.args.filename
21
+
22
+ self.data_dict = []
23
+ if self.args.exe:
24
+ if self.args.add_data:
25
+ for data in self.args.add_data:
26
+ self.data_dict.append(data)
27
+
28
+ # Icon check
29
+ if self.args.icon:
30
+ if len(self.args.icon) > 1:
31
+ raise ValueError("Put only one PATH in 'icon' argument.")
32
+
33
+ if not os.path.exists(os.path.join(self.current_dir, self.args.icon[0])):
34
+ raise ValueError(f"The path '{self.args.icon[0]}' not exists")
35
+
36
+ # Venv
37
+ if self.args.venv:
38
+ self.venv_manager.main()
39
+ elif self.args.venv_clean:
40
+ self.venv_manager.create_venv()
41
+ elif self.args.recreate_venv:
42
+ self.venv_manager.recreate_venv()
43
+ elif self.args.delete_venv:
44
+ self.venv_manager.delete_venv()
45
+
46
+ # Imports
47
+ if self.args.find_imports:
48
+ self.find_imports.main()
49
+ elif self.args.install_imports:
50
+ self.venv_manager.install_imports()
51
+
52
+ # EXEC
53
+ elif self.args.exe:
54
+ self.exec_gen.main()
55
+
56
+ if self.args.zip:
57
+ self.exec_gen.zip_file()
58
+
59
+ # LOG - Verify imports
60
+ if self.args.verify_imports:
61
+ if self.args.find_imports \
62
+ or self.args.install_imports \
63
+ or self.args.venv \
64
+ or self.args.recreate_venv \
65
+ or self.args.exe:
66
+ self.find_imports.verify_imports()
67
+ else:
68
+ print(f"{self.visuals.bold}{self.visuals.RD} > Error: You need to use one function that installs imports before verifying them.{self.visuals.RESET}")
69
+ print("\033[J", end='', flush=True)
70
+
71
+ self.clean_terminal()
72
+
73
+
74
+
75
+ class Visual():
76
+ def __init__(self):
77
+
78
+
79
+ # Colors
80
+ self.DK_ORANGE = "\033[38;5;130m"
81
+ self.ORANGE = "\033[38;5;214m"
82
+ self.YL = "\033[38;5;226m"
83
+ self.RD = "\033[38;5;196m"
84
+ self.GR = "\033[38;5;34m"
85
+ self.RESET = "\033[0m"
86
+ self.bold = "\033[1m"
87
+
88
+ class Visual(clean_main):
89
+ def __init__(self):
90
+ super().__init__()
91
+
92
+ self.hue = 0
93
+
94
+ def hsl_to_rgb(self, h, s, l):
95
+ h = h % 360
96
+ c = (1 - abs(2 * l - 1)) * s
97
+ x = c * (1 - abs((h / 60) % 2 - 1))
98
+ m = l - c / 2
99
+
100
+ if 0 <= h < 60: r, g, b = c, x, 0
101
+ elif 60 <= h < 120: r, g, b = x, c, 0
102
+ elif 120 <= h < 180: r, g, b = 0, c, x
103
+ elif 180 <= h < 240: r, g, b = 0, x, c
104
+ elif 240 <= h < 300: r, g, b = x, 0, c
105
+ elif 300 <= h < 360: r, g, b = c, 0, x
106
+
107
+ r = int((r + m) * 255) ; g = int((g + m) * 255) ; b = int((b + m) * 255)
108
+ return r, g, b
109
+
110
+ def rgb_text(self, text, r, g, b): return f"\033[38;2;{r};{g};{b}m{text}\033[0m"
111
+
112
+ def animate_rgb_text(self, text, delay=0.01):
113
+ r, g, b = self.hsl_to_rgb(self.hue, s=1.0, l=0.5)
114
+ self.hue = (self.hue + 1) % 360
115
+ time.sleep(delay)
116
+ return f" \033[1m{self.rgb_text(text, r, g, b)}\033[0m"
117
+
118
+ class animation:
119
+ def __init__(self, self_cli):
120
+ self.cli = self_cli
121
+ self.text = None
122
+ self.braille_spinner = [
123
+ '\u280B',
124
+ '\u2809',
125
+ '\u2839',
126
+ '\u2838',
127
+ '\u283C',
128
+ '\u2834',
129
+ '\u2826',
130
+ '\u2827',
131
+ '\u2807',
132
+ '\u280F'
133
+ ]
134
+
135
+ self.retro_computer_style = [
136
+ '\u23BA', # ⎺
137
+ '\u23BB', # ⎻
138
+ '\u23BC', # ⎼
139
+ '\u23BD', # ⎽
140
+ ]
141
+
142
+ self.footer_thread = None
143
+ self.process_finished = False
144
+
145
+ def print_footer(self):
146
+ s = 0
147
+ n = 0
148
+ while not self.process_finished:
149
+ if s % 10 == 0: n += 1
150
+ if n == len(self.retro_computer_style): n = 0
151
+
152
+ sys.stdout.write(f"\r \033[F\r\033[K\033[E {self.cli.visuals.animate_rgb_text(f" {self.cli.visuals.bold} {self.retro_computer_style[n]} {self.text} {self.retro_computer_style[n]} {self.cli.visuals.RESET}")} \033[0J\n\033[F")
153
+ sys.stdout.flush()
154
+ s += 1
155
+
156
+ def start(self, text):
157
+ self.text = text
158
+ self.footer_thread = threading.Thread(target=self.print_footer)
159
+ self.footer_thread.start()
160
+
161
+ def finish(self):
162
+ self.process_finished = True
163
+ self.footer_thread.join()
164
+
165
+ def main():
166
+
167
+ class visual():
168
+ def __init__(self):
169
+ self.RESET = "\033[0m"
170
+ self.DK_ORANGE = "\033[38;5;130m"
171
+ self.Neg = "\033[1m"
172
+ self.hue = 0
173
+
174
+ def hsl_to_rgb(self, h, s, l):
175
+ h = h % 360
176
+ c = (1 - abs(2 * l - 1)) * s
177
+ x = c * (1 - abs((h / 60) % 2 - 1))
178
+ m = l - c / 2
179
+
180
+ if 0 <= h < 60: r, g, b = c, x, 0
181
+ elif 60 <= h < 120: r, g, b = x, c, 0
182
+ elif 120 <= h < 180: r, g, b = 0, c, x
183
+ elif 180 <= h < 240: r, g, b = 0, x, c
184
+ elif 240 <= h < 300: r, g, b = x, 0, c
185
+ elif 300 <= h < 360: r, g, b = c, 0, x
186
+
187
+ r = int((r + m) * 255) ; g = int((g + m) * 255) ; b = int((b + m) * 255)
188
+ return r, g, b
189
+
190
+ def rgb_text(self, text, r, g, b): return f"\033[38;2;{r};{g};{b}m{text}\033[0m"
191
+
192
+ def animate_rgb_text(self, text, delay=0.01):
193
+ r, g, b = self.hsl_to_rgb(self.hue, s=1.0, l=0.5)
194
+ self.hue = (self.hue + 1) % 360
195
+ time.sleep(delay)
196
+ return f" \033[1m{self.rgb_text(text, r, g, b)}\033[0m"
197
+
198
+ class exec_gen():
199
+ def __init__(self):
200
+ self.current_dir = None
201
+ self.target_file = None
202
+ self.file_name = None
203
+
204
+ def preparations(self):
205
+ self.current_dir = os.getcwd()
206
+
207
+ parser = argparse.ArgumentParser(description="Script to generate .exe and preventing bugs")
208
+ parser.add_argument("file", type=str, help="Put the name of file after the command (with the extension '.py')")
209
+
210
+ args = parser.parse_args()
211
+ self.file_name = args.file
212
+ self.target_file = os.path.join(self.current_dir, self.file_name)
213
+
214
+ if not os.path.exists(self.target_file):
215
+ print(f"Error: File '{self.target_file}' does not exist.")
216
+ return
217
+
218
+ def run_pyinstaller(self):
219
+ global process_finished
220
+
221
+ def print_footer():
222
+ """Função que mantém a mensagem 'Aguarde download' na última linha."""
223
+ while not process_finished:
224
+ sys.stdout.write(f"\r \033[F\r\033[K\033[E {visuals.animate_rgb_text(f" {visuals.Neg}| Gerando executável do '{self.file_name}', aguarde finalização. |{visuals.RESET}")}\n\033[F")
225
+ sys.stdout.flush()
226
+
227
+ process_finished = False
228
+
229
+ command = ["pyinstaller", self.target_file]
230
+ process = subprocess.Popen(
231
+ command,
232
+ stdout=subprocess.PIPE,
233
+ stderr=subprocess.STDOUT,
234
+ universal_newlines=True,
235
+ bufsize=1
236
+ )
237
+ footer_thread = threading.Thread(target=print_footer)
238
+ footer_thread.start()
239
+
240
+ # Lê a saída do PyInstaller em tempo real
241
+ while True:
242
+ output = process.stdout.readline()
243
+ if output == '' and process.poll() is not None:
244
+ break
245
+ if output:
246
+ sys.stdout.write(f"\033[F\r\033[K{output.strip()}\033[K\n\n")
247
+ sys.stdout.flush()
248
+
249
+ process_finished = True
250
+ footer_thread.join()
251
+
252
+ print(f"\r \033[F\r\033[K\033[f\r\033[K\033[2E{visuals.Neg}{visuals.DK_ORANGE}>{visuals.RESET}{visuals.Neg} Executável gerado com sucesso!\n{visuals.RESET}\033[3E")
253
+
254
+ script = exec_gen()
255
+ visuals = visual()
256
+ script.preparations()
257
+ script.run_pyinstaller()