io4it 3.0.2__tar.gz → 3.0.2.1__tar.gz

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.
Files changed (92) hide show
  1. {io4it-3.0.2 → io4it-3.0.2.1}/PKG-INFO +1 -1
  2. {io4it-3.0.2 → io4it-3.0.2.1}/io4it.egg-info/PKG-INFO +1 -1
  3. {io4it-3.0.2 → io4it-3.0.2.1}/io4it.egg-info/SOURCES.txt +1 -1
  4. io4it-3.0.2/orangecontrib/IO4IT/utils/offuscation_basique.py → io4it-3.0.2.1/orangecontrib/IO4IT/utils/keys_manager.py +192 -18
  5. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/utils/mail.py +15 -15
  6. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWChatGpt.py +4 -4
  7. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWDeep_Search.py +3 -3
  8. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWExtractTablesDocxToXlsx.py +4 -1
  9. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWInboxMailMonitoring.py +5 -5
  10. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWPdfType.py +26 -22
  11. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWSpeechToText.py +3 -0
  12. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWWebSearch.py +3 -3
  13. {io4it-3.0.2 → io4it-3.0.2.1}/setup.py +1 -1
  14. {io4it-3.0.2 → io4it-3.0.2.1}/io4it.egg-info/dependency_links.txt +0 -0
  15. {io4it-3.0.2 → io4it-3.0.2.1}/io4it.egg-info/entry_points.txt +0 -0
  16. {io4it-3.0.2 → io4it-3.0.2.1}/io4it.egg-info/namespace_packages.txt +0 -0
  17. {io4it-3.0.2 → io4it-3.0.2.1}/io4it.egg-info/requires.txt +0 -0
  18. {io4it-3.0.2 → io4it-3.0.2.1}/io4it.egg-info/top_level.txt +0 -0
  19. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/__init__.py +0 -0
  20. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/ocr_function/__init__.py +0 -0
  21. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/ocr_function/word_converter.py +0 -0
  22. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/utils/__init__.py +0 -0
  23. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/utils/config.json +0 -0
  24. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/utils/pool_exec_utils.py +0 -0
  25. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/utils/secret_manager.py +0 -0
  26. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/utils/utils_md.py +0 -0
  27. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWDoclingASR.py +0 -0
  28. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWDoclingToMarkdown.py +0 -0
  29. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWExportMarkdown.py +0 -0
  30. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWMD2HTML.py +0 -0
  31. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWMarkdownLoader.py +0 -0
  32. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWMarkdownizer.py +0 -0
  33. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWOfficeNormalizer.py +0 -0
  34. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWParserHTML.py +0 -0
  35. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWProcessPoolExecutor.py +0 -0
  36. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWS3Uploader.py +0 -0
  37. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWS3downloader.py +0 -0
  38. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWS3list.py +0 -0
  39. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWmailLoader.py +0 -0
  40. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWmailSender.py +0 -0
  41. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/OWwordpdf2docx.py +0 -0
  42. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/__init__.py +0 -0
  43. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/__init__.py +0 -0
  44. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/nogui.ui +0 -0
  45. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui +0 -0
  46. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owchatgpt.ui +0 -0
  47. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui +0 -0
  48. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owdoclingasr.ui +0 -0
  49. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owdoclingtomarkdown.ui +0 -0
  50. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owdocxtoxlsx.ui +0 -0
  51. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui +0 -0
  52. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owinboxmailmonitoring.ui +0 -0
  53. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owmailloader.ui +0 -0
  54. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owmailsender.ui +0 -0
  55. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui +0 -0
  56. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owmarkdownloader.ui +0 -0
  57. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owmd2html.ui +0 -0
  58. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owofficenormalizer.ui +0 -0
  59. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owparserhtml.ui +0 -0
  60. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owpdftype.ui +0 -0
  61. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owprocesspoolexecutor.ui +0 -0
  62. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui +0 -0
  63. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owvisualizationer.ui +0 -0
  64. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/owwebsearch.ui +0 -0
  65. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/designer/wordpdf2docx.ui +0 -0
  66. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/__init__.py +0 -0
  67. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/chatgpt.png +0 -0
  68. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/check_pdf.png +0 -0
  69. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/deepsearch.svg +0 -0
  70. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/dep_md_old.png +0 -0
  71. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/download.png +0 -0
  72. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/export_md.png +0 -0
  73. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/extract_table.png +0 -0
  74. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/file_extensor.png +0 -0
  75. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/html.png +0 -0
  76. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/list_aws.png +0 -0
  77. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/load_md.png +0 -0
  78. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/mail_loader.png +0 -0
  79. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/mail_writer.png +0 -0
  80. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/md.png +0 -0
  81. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/monitor-email.svg +0 -0
  82. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/office_normalizer.png +0 -0
  83. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/owmd2html.svg +0 -0
  84. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/process_pool_executor.png +0 -0
  85. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/speech_to_text.png +0 -0
  86. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/upload.png +0 -0
  87. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/visualizationer.png +0 -0
  88. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/websearch.png +0 -0
  89. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons/wordpdf2docx.png +0 -0
  90. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/IO4IT/widgets/icons_dev/__init__.py +0 -0
  91. {io4it-3.0.2 → io4it-3.0.2.1}/orangecontrib/__init__.py +0 -0
  92. {io4it-3.0.2 → io4it-3.0.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: io4it
3
- Version: 3.0.2
3
+ Version: 3.0.2.1
4
4
  Home-page:
5
5
  Author:
6
6
  Author-email:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: io4it
3
- Version: 3.0.2
3
+ Version: 3.0.2.1
4
4
  Home-page:
5
5
  Author:
6
6
  Author-email:
@@ -11,8 +11,8 @@ orangecontrib/IO4IT/__init__.py
11
11
  orangecontrib/IO4IT/ocr_function/__init__.py
12
12
  orangecontrib/IO4IT/ocr_function/word_converter.py
13
13
  orangecontrib/IO4IT/utils/__init__.py
14
+ orangecontrib/IO4IT/utils/keys_manager.py
14
15
  orangecontrib/IO4IT/utils/mail.py
15
- orangecontrib/IO4IT/utils/offuscation_basique.py
16
16
  orangecontrib/IO4IT/utils/pool_exec_utils.py
17
17
  orangecontrib/IO4IT/utils/secret_manager.py
18
18
  orangecontrib/IO4IT/utils/utils_md.py
@@ -135,7 +135,40 @@ def enregistrer_config_imap4_ssl(agent, my_domain, password, interval_second, al
135
135
  print(f"❌ Erreur lors de l'enregistrement : {e}")
136
136
  return 1
137
137
 
138
+ def enregistrer_config_imap4_ssl_secure(agent, my_domain, password, interval_second, alias=""):
139
+ try:
140
+ dossier = get_keys_dir("IMAP4_SSL")
141
+ # Crée le dossier s'il n'existe pas
142
+ if not os.path.exists(dossier):
143
+ os.makedirs(dossier)
138
144
 
145
+
146
+ # Nom du fichier (remplace @ par _at_ pour éviter les problèmes)
147
+ nom_fichier = os.path.join(dossier, f"{agent}{my_domain.replace('@', '_at_')}.sec")
148
+ service_name = f"IMAP4_SSL__{agent}{my_domain.replace('@', '_at_')}"
149
+ if alias == "''" or alias == "\"\"":
150
+ alias = ""
151
+
152
+ # Contenu à écrire dans le fichier
153
+ contenu = {
154
+ "agent": agent,
155
+ "domain": my_domain,
156
+ "interval_second": interval_second,
157
+ "password": password,
158
+ "alias": alias
159
+ }
160
+ sm = secret_manager.SecretManager(service_name)
161
+ sm.store(contenu)
162
+ # Écriture du fichier
163
+ with open(nom_fichier, "w", encoding="utf-8") as f:
164
+ pass
165
+
166
+ print(f"✅ Fichier enregistré : {nom_fichier}")
167
+ return 0
168
+
169
+ except Exception as e:
170
+ print(f"❌ Erreur lors de l'enregistrement : {e}")
171
+ return 1
139
172
  def enregistrer_config_owa(mail, alias, server, username, password, interval):
140
173
  try:
141
174
  dossier = get_keys_dir("MICROSOFT_EXCHANGE_OWA")
@@ -178,10 +211,6 @@ def enregistrer_config_owa_secure(mail, alias, server, username, password, inter
178
211
  if not os.path.exists(dossier):
179
212
  os.makedirs(dossier)
180
213
 
181
- # Récupère l'adresse MAC et chiffre le mot de passe
182
- key = get_user_key()
183
- mdp_chiffre = xor_crypt(password, key)
184
-
185
214
  # Nom du fichier (remplace @ par _at_ pour éviter les problèmes)
186
215
  nom_fichier = os.path.join(dossier, f"{alias.replace('@', '_at_')}.sec")
187
216
  service_name=f"MICROSOFT_EXCHANGE_OWA__{alias.replace('@', '_at_')}"
@@ -214,6 +243,25 @@ def enregistrer_config_owa_secure(mail, alias, server, username, password, inter
214
243
  # Fonction pour lire le fichier de configuration et déchiffrer le mot de passe
215
244
  def lire_config_imap4_ssl(chemin_fichier):
216
245
  # renvoie une liste =["agent","domain",mdp,"interval_second"]
246
+ if len(chemin_fichier)<5:
247
+ print(f"❌ Error path not correct", chemin_fichier)
248
+ return None
249
+ if chemin_fichier.endswith(".sec"):
250
+ try:
251
+ service = "IMAP4_SSL__" + chemin_fichier[:-4]
252
+ sm = secret_manager.SecretManager(service)
253
+ contenu = sm.load_all()
254
+ return [
255
+ contenu["agent"],
256
+ contenu["domain"],
257
+ contenu["password"],
258
+ int(contenu["interval_second"]),
259
+ contenu.get("alias", "")
260
+ ]
261
+
262
+ except Exception as e:
263
+ print(f"❌ Erreur lors de la lecture : {e}")
264
+ return None
217
265
  try:
218
266
  chemin_fichier = os.path.join(get_keys_dir("IMAP4_SSL"), chemin_fichier)
219
267
  # Lecture du fichier JSON
@@ -318,9 +366,14 @@ def enregistrer_config_cli_imap4_ssl():
318
366
  mdp = input("📨mot de passe? : ").strip()
319
367
  interval = int(input("⏱️ Intervalle en secondes : ").strip())
320
368
  alias = input("Nom de l'alias : ").strip()
321
- if 0 != enregistrer_config_imap4_ssl(agent, domaine, mdp, interval, alias):
369
+ store = ask_secure()
370
+ if not store:
371
+ if 0 != enregistrer_config_imap4_ssl(agent, domaine, mdp, interval, alias):
372
+ print("erreur!")
373
+ return
374
+ if 0 != enregistrer_config_imap4_ssl_secure(agent, domaine, mdp, interval, alias):
322
375
  print("erreur!")
323
-
376
+ return
324
377
 
325
378
  def enregistrer_config_cli_owa():
326
379
  print("\n📝 Écriture d’un fichier de configuration owa :")
@@ -335,7 +388,6 @@ def enregistrer_config_cli_owa():
335
388
  if alias == "''" or alias == "\"\"" or alias == "":
336
389
  alias = mail
337
390
  if not store:
338
- print("not secure")
339
391
  if 0 != enregistrer_config_owa(mail, alias, server, username, mdp, interval):
340
392
  print("erreur!")
341
393
  return
@@ -354,8 +406,8 @@ def enregistrer_config_cli_oauth2():
354
406
  client_secret_enc = xor_crypt(client_secret, key)
355
407
  tenant_id_enc = xor_crypt(tenant_id, key)
356
408
  nom_fichier = input("💾 Nom du fichier à enregistrer (ex: config_oauth2.json) : ").strip()
357
- choix_enregistrement = input("Voulez vous enregistrer en offuscation basique (1) ou enregistrer une clée dans "
358
- "le trousseau (2) ?")
409
+ choix_enregistrement = input("Voulez vous enregistrer en non securisé (1) ou enregistrer une clée dans "
410
+ "le trousseau (secure) (2) ?")
359
411
  match choix_enregistrement:
360
412
  case "1":
361
413
  config = {
@@ -393,7 +445,7 @@ def enregistrer_config_cli_oauth2():
393
445
 
394
446
 
395
447
  def lire_config_cli_oauth2():
396
- chemin_fichier = input("📄 non fichier json (pas le chemin!) JSON : ").strip()
448
+ chemin_fichier = input("📄 nom fichier json (pas le chemin!) JSON : ").strip()
397
449
  config = lire_config_oauth2(chemin_fichier)
398
450
  if config == None:
399
451
  print("erreur")
@@ -402,7 +454,7 @@ def lire_config_cli_oauth2():
402
454
 
403
455
 
404
456
  def lecture_config_cli_owa():
405
- chemin_fichier = input("📄 non fichier json (pas le chemin!) JSON ou sec : ").strip()
457
+ chemin_fichier = input("📄 nom fichier json ou sec (pas le chemin!) JSON / sec : ").strip()
406
458
  config = lire_config_owa(chemin_fichier)
407
459
 
408
460
  if config == None:
@@ -411,7 +463,7 @@ def lecture_config_cli_owa():
411
463
 
412
464
 
413
465
  def lire_config_cli_imap4_ssl():
414
- chemin_fichier = input("📄 non fichier json (pas le chemin!) JSON : ").strip()
466
+ chemin_fichier = input("📄 nom fichier json ou sec (pas le chemin!) JSON / SEC: ").strip()
415
467
  config = lire_config_imap4_ssl(chemin_fichier)
416
468
 
417
469
  if config == None:
@@ -444,11 +496,62 @@ def enregistrer_config_api(service_name, api_key, description=""):
444
496
  print(f"❌ Erreur d’enregistrement : {e}")
445
497
  return 1
446
498
 
499
+ # Gestion clés API (HARD dossier aait_store/keys)
500
+ # Enregistre un fichier JSON {service, api_key_encrypted, description}
501
+ def enregistrer_config_api_secure(service_name, api_key, description=""):
502
+ try:
503
+ dossier = get_keys_dir("API")
504
+ # Crée le dossier s'il n'existe pas
505
+ if not os.path.exists(dossier):
506
+ os.makedirs(dossier)
507
+ service_name_windows=f"API__{service_name}"
508
+
509
+
510
+ contenu = {
511
+ "service": service_name,
512
+ "api_key": api_key,
513
+ "description": description
514
+ }
515
+ sm = secret_manager.SecretManager(service_name_windows)
516
+ sm.store(contenu)
517
+ chemin_fic = os.path.join(get_keys_dir("API"), f"{service_name}.sec")
518
+ with open(chemin_fic, "w", encoding="utf-8") as fp:
519
+ pass
520
+
521
+ #print(f"✅ Fichier enregistré : {chemin_fic}")
522
+ #print(get_user_key())
523
+ return 0
524
+ except Exception as e:
525
+ print(f"❌ Erreur d’enregistrement : {e}")
526
+ return 1
447
527
 
448
528
  # Lecture + déchiffrement → dict {"service", "api_key", "description"}
449
529
  def lire_config_api(service_name):
530
+ chemin_sec = os.path.join(get_keys_dir("API"), f"{service_name}")
531
+ if not service_name.endswith(".sec"):
532
+ chemin_sec += ".sec"
533
+ if os.path.exists(chemin_sec):
534
+ try:
535
+ if service_name.endswith(".sec"):
536
+ service_name=service_name[:-4]
537
+ service=f"API__{service_name}"
538
+ sm = secret_manager.SecretManager(service)
539
+ contenu=sm.load_all()
540
+ return {
541
+ "service": contenu["service"],
542
+ "api_key": contenu["api_key"],
543
+ "description": contenu.get("description", "")
544
+ }
545
+
546
+
547
+ except Exception as e:
548
+ print(f"❌ Erreur lors de la lecture : {e}")
549
+ return None
550
+
450
551
  try:
451
- chemin_fic = os.path.join(get_keys_dir("API"), f"{service_name}.json")
552
+ chemin_fic = os.path.join(get_keys_dir("API"), f"{service_name}")
553
+ if not service_name.endswith(".json"):
554
+ chemin_fic += ".json"
452
555
  with open(chemin_fic, "r", encoding="utf-8") as fp:
453
556
  contenu = json.load(fp)
454
557
 
@@ -475,13 +578,18 @@ def enregistrer_config_cli_api():
475
578
  service = input("🔖 Nom du service : ").strip()
476
579
  api_key = input("🔑 Clé API : ").strip()
477
580
  desc = input("✏️ Description : ").strip()
478
- if 0 != enregistrer_config_api(service, api_key, desc):
581
+ store = ask_secure()
582
+ if not store:
583
+ if 0 != enregistrer_config_api(service, api_key, desc):
584
+ print("erreur!")
585
+ return
586
+ if 0 != enregistrer_config_api_secure(service, api_key, desc):
479
587
  print("erreur!")
480
588
 
481
589
 
482
590
  def lire_config_cli_api(service=""):
483
591
  if service == "":
484
- service = input("🔖 Nom du service : ").strip()
592
+ service = input("🔖 Nom du service (ou nom du fichier .sec/.json): ").strip()
485
593
  try:
486
594
  cfg = lire_config_api(service)
487
595
  if cfg is None:
@@ -529,10 +637,67 @@ def enregistrer_config_nxp(
529
637
  print(f"❌ Erreur d’enregistrement : {e}")
530
638
  return 1
531
639
 
640
+ def enregistrer_config_nxp_secure(
641
+ dossier_node_id: str,
642
+ serveur: str,
643
+ username: str,
644
+ password: str,
645
+ description: str = ""
646
+ ) -> int:
647
+ try:
648
+ service_name = f"NXP__{serveur}"
649
+ dossier = get_keys_dir("NXP")
650
+ # Crée le dossier s'il n'existe pas
651
+ if not os.path.exists(dossier):
652
+ os.makedirs(dossier)
653
+ contenu = {
654
+ "dossier_node_id": dossier_node_id,
655
+ "serveur": serveur,
656
+ "username": username,
657
+ "password": password,
658
+ "description": description
659
+ }
660
+ sm = secret_manager.SecretManager(service_name)
661
+ sm.store(contenu)
662
+ # ⬅️ Ici : plus de "conn_", juste {serveur}.json
663
+ chemin = os.path.join(get_keys_dir("NXP"), f"{serveur}.sec")
664
+ with open(chemin, "w", encoding="utf-8") as f:
665
+ pass
666
+
667
+ print(f"✅ Fichier enregistré : {chemin}")
668
+ return 0
669
+ except Exception as e:
670
+ print(f"❌ Erreur d’enregistrement : {e}")
671
+ return 1
672
+
532
673
 
533
674
  def lire_config_nxp(serveur: str) -> dict | None:
675
+ chemin_sec = os.path.join(get_keys_dir("NXP"), f"{serveur}")
676
+ if not serveur.endswith(".sec"):
677
+ chemin_sec += ".sec"
678
+ if os.path.exists(chemin_sec):
679
+ try:
680
+ if serveur.endswith(".sec"):
681
+ serveur=serveur[:-4]
682
+ service=f"NXP__{serveur}"
683
+ sm = secret_manager.SecretManager(service)
684
+ contenu=sm.load_all()
685
+ return {
686
+ "dossier_node_id": contenu["dossier_node_id"],
687
+ "serveur": contenu["serveur"],
688
+ "username": contenu["username"],
689
+ "password": contenu["password"],
690
+ "description": contenu["description"]
691
+ }
692
+
693
+ except Exception as e:
694
+ print(f"❌ Erreur lors de la lecture : {e}")
695
+ return None
696
+
534
697
  try:
535
- chemin = os.path.join(get_keys_dir("NXP"), f"{serveur}.json") # ⬅️ même logique
698
+ chemin = os.path.join(get_keys_dir("NXP"), f"{serveur}") # ⬅️ même logique
699
+ if not serveur.endswith(".json"):
700
+ chemin += ".json"
536
701
  with open(chemin, "r", encoding="utf-8") as f:
537
702
  contenu = json.load(f)
538
703
 
@@ -561,7 +726,17 @@ def enregistrer_config_cli_nxp():
561
726
  username = input("👤 USERNAME : ").strip()
562
727
  password = getpass.getpass("🔑 PASSWORD : ").strip()
563
728
  description = input("✏️ Description : ").strip()
564
- enregistrer_config_nxp(
729
+ store = ask_secure()
730
+ if not store:
731
+ enregistrer_config_nxp(
732
+ dossier_node_id,
733
+ serveur,
734
+ username,
735
+ password,
736
+ description
737
+ )
738
+ return
739
+ enregistrer_config_nxp_secure(
565
740
  dossier_node_id,
566
741
  serveur,
567
742
  username,
@@ -569,7 +744,6 @@ def enregistrer_config_cli_nxp():
569
744
  description
570
745
  )
571
746
 
572
-
573
747
  def lire_config_cli_nxp():
574
748
  serveur = input("🌐 SERVEUR : ").strip() # ⬅️ on demande le serveur
575
749
  cfg = lire_config_nxp(serveur)
@@ -24,10 +24,10 @@ from oauthlib.oauth2 import OAuth2Token
24
24
 
25
25
  if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).replace("\\", "/"):
26
26
  from Orange.widgets.orangecontrib.AAIT.utils import MetManagement
27
- from Orange.widgets.orangecontrib.IO4IT.utils import offuscation_basique
27
+ from Orange.widgets.orangecontrib.IO4IT.utils import keys_manager
28
28
  else:
29
29
  from orangecontrib.AAIT.utils import MetManagement
30
- from orangecontrib.IO4IT.utils import offuscation_basique
30
+ from orangecontrib.IO4IT.utils import keys_manager
31
31
 
32
32
 
33
33
  def clean_addresses(field,myemail):
@@ -62,7 +62,7 @@ def mail_in_folder(agent_name, type="in"):
62
62
  def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
63
63
  if type_co=="IMAP4_SSL":
64
64
  try:
65
- agent,my_domain,password,interl_seconds,alias=offuscation_basique.lire_config_imap4_ssl(offusc_conf_agent)
65
+ agent,my_domain,password,interl_seconds,alias=keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
66
66
  myemail=agent + my_domain
67
67
  imap = imaplib.IMAP4_SSL("imap.gmail.com")
68
68
  imap.login(myemail, password)
@@ -74,7 +74,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
74
74
  else:
75
75
  for mail_id in mail_ids:
76
76
  if list_agent_email != []:
77
- white_list, black_list = offuscation_basique.lire_list_email(list_agent_email)
77
+ white_list, black_list = keys_manager.lire_list_email(list_agent_email)
78
78
  else:
79
79
  white_list=[]
80
80
  black_list=[]
@@ -194,7 +194,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
194
194
  print(f"Erreur lors de la vérification des mails : {e}")
195
195
  elif type_co=="MICROSOFT_EXCHANGE_OWA":
196
196
  try:
197
- mail, alias, server, username, password, interval_second = offuscation_basique.lire_config_owa(
197
+ mail, alias, server, username, password, interval_second = keys_manager.lire_config_owa(
198
198
  offusc_conf_agent)
199
199
  credentials = Credentials(username=username, password=password)
200
200
  config = Configuration(
@@ -219,7 +219,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
219
219
  else:
220
220
  for item in inbox.order_by('datetime_received'):
221
221
  if list_agent_email != []:
222
- white_list, black_list = offuscation_basique.lire_list_email(list_agent_email)
222
+ white_list, black_list = keys_manager.lire_list_email(list_agent_email)
223
223
  else:
224
224
  white_list, black_list = [], []
225
225
  if not isinstance(item,Message):
@@ -310,7 +310,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
310
310
  print(f"Erreur lors du traitement du mail : {e}")
311
311
  elif type_co == "MICROSOFT_EXCHANGE_OAUTH2":
312
312
  try:
313
- client_id, client_secret, tenant_id, user_email= offuscation_basique.lire_config_oauth2(
313
+ client_id, client_secret, tenant_id, user_email= keys_manager.lire_config_oauth2(
314
314
  offusc_conf_agent)
315
315
  authority = f"https://login.microsoftonline.com/{tenant_id}"
316
316
 
@@ -359,7 +359,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
359
359
  else:
360
360
  for item in inbox.order_by('datetime_received'):
361
361
  if list_agent_email:
362
- white_list, black_list = offuscation_basique.lire_list_email(list_agent_email)
362
+ white_list, black_list = keys_manager.lire_list_email(list_agent_email)
363
363
  else:
364
364
  white_list, black_list = [], []
365
365
 
@@ -436,7 +436,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
436
436
  elif type_co == "MICROSOFT_EXCHANGE_OAUTH2_MICROSOFT_GRAPH":
437
437
  try:
438
438
  print("🔍 [DEBUG] Début de la vérification des emails avec Microsoft Graph OAuth2")
439
- client_id, client_secret, tenant_id, user_email = offuscation_basique.lire_config_oauth2(
439
+ client_id, client_secret, tenant_id, user_email = keys_manager.lire_config_oauth2(
440
440
  offusc_conf_agent)
441
441
  print(f"🔍 [DEBUG] Configuration lue - User: {user_email}, Tenant: {tenant_id}")
442
442
 
@@ -513,7 +513,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
513
513
  for i, email_item in enumerate(emails_data['value']):
514
514
  print(f"🔍 [DEBUG] Traitement de l'email {i + 1}/{len(emails_data['value'])}")
515
515
  if list_agent_email:
516
- white_list, black_list = offuscation_basique.lire_list_email(list_agent_email)
516
+ white_list, black_list = keys_manager.lire_list_email(list_agent_email)
517
517
  print(f"🔍 [DEBUG] Listes chargées - White: {len(white_list)}, Black: {len(black_list)}")
518
518
  else:
519
519
  white_list, black_list = [], []
@@ -688,7 +688,7 @@ def send_mail(expediteur, offusc_conf_agent, destinataire, sujet, contenu_html,
688
688
  except Exception as e:
689
689
  print(f"Erreur lors de l'ajout de la pièce jointe '{piece_path}': {e}")
690
690
  try:
691
- _, _, mot_de_passe, _, _ = offuscation_basique.lire_config_imap4_ssl(offusc_conf_agent)
691
+ _, _, mot_de_passe, _, _ = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
692
692
  with smtplib.SMTP(serveur, port) as smtp:
693
693
  smtp.starttls()
694
694
  smtp.login(expediteur, mot_de_passe)
@@ -700,7 +700,7 @@ def send_mail(expediteur, offusc_conf_agent, destinataire, sujet, contenu_html,
700
700
 
701
701
  def check_send_new_emails(offusc_conf_agent,type_co):
702
702
  if type_co=="IMAP4_SSL":
703
- agent, domain, _, _,alias = offuscation_basique.lire_config_imap4_ssl(offusc_conf_agent)
703
+ agent, domain, _, _,alias = keys_manager.lire_config_imap4_ssl(offusc_conf_agent)
704
704
  mail = agent+domain
705
705
  if alias != "":
706
706
  agent = alias
@@ -733,7 +733,7 @@ def check_send_new_emails(offusc_conf_agent,type_co):
733
733
  print("Le dossier n'existe pas ou le chemin n'est pas un dossier.")
734
734
  elif type_co=="MICROSOFT_EXCHANGE_OWA":
735
735
  try:
736
- mail, alias, server, username, password, interval_second = offuscation_basique.lire_config_owa(
736
+ mail, alias, server, username, password, interval_second = keys_manager.lire_config_owa(
737
737
  offusc_conf_agent)
738
738
  credentials = Credentials(username=username, password=password)
739
739
  config = Configuration(server=server,
@@ -776,7 +776,7 @@ def check_send_new_emails(offusc_conf_agent,type_co):
776
776
  print(f"Erreur lors du traitement du mail : {e}")
777
777
  elif type_co == "MICROSOFT_EXCHANGE_OAUTH2":
778
778
  try:
779
- client_id, client_secret, tenant_id, user_email = offuscation_basique.lire_config_oauth2(
779
+ client_id, client_secret, tenant_id, user_email = keys_manager.lire_config_oauth2(
780
780
  offusc_conf_agent)
781
781
  # Déduire l'alias pour le nom du dossier
782
782
  agent = user_email
@@ -859,7 +859,7 @@ def check_send_new_emails(offusc_conf_agent,type_co):
859
859
  elif type_co == "MICROSOFT_EXCHANGE_OAUTH2_MICROSOFT_GRAPH":
860
860
  try:
861
861
  print("📤 [DEBUG] Début de la vérification des emails à envoyer avec Microsoft Graph OAuth2")
862
- client_id, client_secret, tenant_id, user_email = offuscation_basique.lire_config_oauth2(
862
+ client_id, client_secret, tenant_id, user_email = keys_manager.lire_config_oauth2(
863
863
  offusc_conf_agent)
864
864
  print(f"📤 [DEBUG] Configuration lue - User: {user_email}, Tenant: {tenant_id}")
865
865
 
@@ -12,11 +12,11 @@ from AnyQt.QtWidgets import QApplication, QLineEdit, QSpinBox, QDoubleSpinBox, Q
12
12
  if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).replace("\\", "/"):
13
13
  from Orange.widgets.orangecontrib.AAIT.utils import thread_management
14
14
  from Orange.widgets.orangecontrib.AAIT.utils.import_uic import uic
15
- from Orange.widgets.orangecontrib.IO4IT.utils import offuscation_basique
15
+ from Orange.widgets.orangecontrib.IO4IT.utils import keys_manager
16
16
  else:
17
17
  from orangecontrib.AAIT.utils.import_uic import uic
18
18
  from orangecontrib.AAIT.utils import thread_management
19
- from orangecontrib.IO4IT.utils import offuscation_basique
19
+ from orangecontrib.IO4IT.utils import keys_manager
20
20
 
21
21
  class ChatGpt(OWWidget):
22
22
  name = "CallChatGptApi"
@@ -46,8 +46,8 @@ class ChatGpt(OWWidget):
46
46
  if "image_paths" in in_data.domain:
47
47
  self.image_paths = in_data.get_column("image_paths")[0]
48
48
  if "api_keys" not in in_data.domain:
49
- self.api_keys = offuscation_basique.lire_config_cli_api("CHAT_GPT")
50
- if offuscation_basique.lire_config_cli_api("CHAT_GPT") is None:
49
+ self.api_keys = keys_manager.lire_config_cli_api("CHAT_GPT")
50
+ if keys_manager.lire_config_cli_api("CHAT_GPT") is None:
51
51
  self.error("input table need a api_keys column or a folder API with you CHAT_GPT keys in aait store")
52
52
  if self.api_keys is None:
53
53
  self.api_keys = in_data.get_column("api_keys")[0]
@@ -15,13 +15,13 @@ if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).
15
15
  from Orange.widgets.orangecontrib.AAIT.utils import thread_management
16
16
  from Orange.widgets.orangecontrib.AAIT.utils.import_uic import uic
17
17
  from Orange.widgets.orangecontrib.AAIT.utils.initialize_from_ini import apply_modification_from_python_file
18
- from Orange.widgets.orangecontrib.IO4IT.utils.offuscation_basique import lire_config_api
18
+ from Orange.widgets.orangecontrib.IO4IT.utils.keys_manager import lire_config_api
19
19
  else:
20
20
  # from orangecontrib.AAIT.llm import answers
21
21
  from orangecontrib.AAIT.utils import thread_management
22
22
  from orangecontrib.AAIT.utils.import_uic import uic
23
23
  from orangecontrib.AAIT.utils.initialize_from_ini import apply_modification_from_python_file
24
- from orangecontrib.IO4IT.utils.offuscation_basique import lire_config_api
24
+ from orangecontrib.IO4IT.utils.keys_manager import lire_config_api
25
25
 
26
26
  @apply_modification_from_python_file(filepath_original_widget=__file__)
27
27
  class OWDeep_Search(widget.OWWidget):
@@ -86,7 +86,7 @@ class OWDeep_Search(widget.OWWidget):
86
86
  cfg = lire_config_api(self.SERVICE_NAME)
87
87
  if cfg is None:
88
88
  self.error(f"⚠️ No API key stored for service '{self.SERVICE_NAME}'.\n"
89
- "Use offuscation_basique.enregistrer_config_cli_api() to add one.")
89
+ "Use keys_manager.enregistrer_config_cli_api() to add one.")
90
90
  self.api_key = None
91
91
  else:
92
92
  self.api_key = cfg["api_key"]
@@ -349,4 +349,7 @@ if __name__ == "__main__":
349
349
  app = QApplication(sys.argv)
350
350
  my_widget = OWExtractTablesDocxToXlsx()
351
351
  my_widget.show()
352
- app.exec()
352
+ if hasattr(app, "exec"):
353
+ app.exec()
354
+ else:
355
+ app.exec_()
@@ -14,13 +14,13 @@ if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).
14
14
  from Orange.widgets.orangecontrib.AAIT.utils import thread_management
15
15
  from Orange.widgets.orangecontrib.AAIT.utils.import_uic import uic
16
16
  from Orange.widgets.orangecontrib.IO4IT.utils import mail
17
- from Orange.widgets.orangecontrib.IO4IT.utils import offuscation_basique
17
+ from Orange.widgets.orangecontrib.IO4IT.utils import keys_manager
18
18
  from Orange.widgets.orangecontrib.AAIT.utils import MetManagement
19
19
  else:
20
20
  from orangecontrib.AAIT.utils import thread_management
21
21
  from orangecontrib.AAIT.utils.import_uic import uic
22
22
  from orangecontrib.IO4IT.utils import mail
23
- from orangecontrib.IO4IT.utils import offuscation_basique
23
+ from orangecontrib.IO4IT.utils import keys_manager
24
24
  from orangecontrib.AAIT.utils import MetManagement
25
25
 
26
26
  class OWInboxMailMonitoring(widget.OWWidget):
@@ -140,13 +140,13 @@ class OWInboxMailMonitoring(widget.OWWidget):
140
140
  try:
141
141
  agent = ""
142
142
  if self.type_co == "IMAP4_SSL":
143
- agent, _, _, _, alias = offuscation_basique.lire_config_imap4_ssl(self.your_email_conf)
143
+ agent, _, _, _, alias = keys_manager.lire_config_imap4_ssl(self.your_email_conf)
144
144
  if alias != "":
145
145
  agent = alias
146
146
  if self.type_co == "MICROSOFT_EXCHANGE_OWA":
147
- _, agent, _, _, _, _ = offuscation_basique.lire_config_owa(self.your_email_conf)
147
+ _, agent, _, _, _, _ = keys_manager.lire_config_owa(self.your_email_conf)
148
148
  if self.type_co == "MICROSOFT_EXCHANGE_OAUTH2":
149
- _, _, _, agent = offuscation_basique.lire_config_cli_oauth2(self.your_email_conf)
149
+ _, _, _, agent = keys_manager.lire_config_cli_oauth2(self.your_email_conf)
150
150
  if agent != "":
151
151
  chemin_dossier = MetManagement.get_path_mailFolder()
152
152
  self.input_dir = chemin_dossier + str(agent) + "/in"
@@ -10,7 +10,6 @@ from Orange.widgets.utils.signals import Input, Output
10
10
 
11
11
  # --- Ajout pour l'écriture Excel ---
12
12
  from openpyxl import Workbook
13
- import pypdf
14
13
 
15
14
  # Les imports sont adaptés pour correspondre au style de l'autre script
16
15
  if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).replace("\\", "/"):
@@ -74,7 +73,6 @@ class OWPdfType(widget.OWWidget):
74
73
  self.Outputs.text_data.send(None)
75
74
  self.Outputs.image_data.send(None)
76
75
  self.Outputs.status_data.send(None)
77
- QApplication.quit()
78
76
  return
79
77
 
80
78
  self.error("")
@@ -82,17 +80,19 @@ class OWPdfType(widget.OWWidget):
82
80
  self.data.domain["file_path"]
83
81
  except KeyError:
84
82
  self.error("You need a 'file_path' column in input data.")
85
- QApplication.quit()
86
83
  return
87
84
 
88
85
  if type(self.data.domain["file_path"]).__name__ != 'StringVariable':
89
86
  self.error("'file_path' column needs to be a Text.")
90
- QApplication.quit()
91
87
  return
92
88
 
93
89
  self.progressBarInit()
94
- self.processed_statuses = []
90
+ self.processed_statuses = [] # Reset status list for a new run
91
+
92
+ # Connect the internal status update signal to a new handler
95
93
  self.status_update_signal.connect(self.handle_status_update)
94
+
95
+ # Pass the status update signal's emit method to the thread
96
96
  self.thread = Thread(self._process_pdfs, self.data, status_callback=self.status_update_signal.emit)
97
97
  self.thread.progress.connect(self.handle_progress)
98
98
  self.thread.result.connect(self.handle_result)
@@ -102,6 +102,7 @@ class OWPdfType(widget.OWWidget):
102
102
  def _process_pdfs(self, in_data: Table, progress_callback: callable, status_callback: callable) -> tuple[
103
103
  Table | None, Table | None]:
104
104
 
105
+ # Extraction des chemins de fichiers avant de commencer le traitement
105
106
  paths = [str(x) for x in in_data.get_column("file_path")]
106
107
 
107
108
  excel_output_dir = Path.cwd() / "pdf_check_results"
@@ -131,7 +132,7 @@ class OWPdfType(widget.OWWidget):
131
132
  for i, p in enumerate(paths):
132
133
  progress_callback(i / total_files * 100)
133
134
  fp = Path(p)
134
- result_row = [p, "", ""]
135
+ result_row = [p, "", ""] # Initialisation de la ligne de résultat
135
136
 
136
137
  if not fp.exists() or fp.suffix.lower() != ".pdf":
137
138
  result_row[1] = "ko"
@@ -142,25 +143,22 @@ class OWPdfType(widget.OWWidget):
142
143
  continue
143
144
 
144
145
  try:
145
- # Vérification de l'attribut is_encrypted de PyPDF avant de traiter le fichier.
146
- reader = pypdf.PdfReader(fp)
147
- if reader.is_encrypted:
148
- result_row[1] = "ko"
149
- result_row[2] = "Error: PDF is password protected."
146
+ is_text = utils_md.is_pdf_text_based(fp)
147
+ if is_text:
148
+ text_indices.append(i)
149
+ result_row[1] = "ok"
150
+ result_row[2] = "Text-based PDF"
150
151
  else:
151
- is_text = utils_md.is_pdf_text_based(fp)
152
- if is_text:
153
- text_indices.append(i)
154
- result_row[1] = "ok"
155
- result_row[2] = "Text-based PDF"
156
- else:
157
- image_indices.append(i)
158
- result_row[1] = "ok"
159
- result_row[2] = "Image-based PDF"
152
+ image_indices.append(i)
153
+ result_row[1] = "ok"
154
+ result_row[2] = "Image-based PDF"
155
+
156
+ status_callback(result_row)
157
+ ws.append(result_row)
158
+ wb.save(excel_path)
160
159
  except Exception as e:
161
160
  result_row[1] = "ko"
162
161
  result_row[2] = f"Error: {str(e)}"
163
- finally:
164
162
  status_callback(result_row)
165
163
  ws.append(result_row)
166
164
  wb.save(excel_path)
@@ -183,9 +181,15 @@ class OWPdfType(widget.OWWidget):
183
181
  self.progressBarSet(value)
184
182
 
185
183
  def handle_status_update(self, new_status: list):
184
+ """
185
+ Receives a single status update from the thread, appends it to the list,
186
+ and sends a new, updated status table.
187
+ """
186
188
  self.processed_statuses.append(new_status)
189
+
190
+ # Correct Domain creation: move "file_path" to metas
187
191
  status_domain = Domain(
188
- [],
192
+ [], # The variables list should be empty
189
193
  metas=[
190
194
  StringVariable("file_path"),
191
195
  DiscreteVariable("status", values=["ok", "ko"]),
@@ -1,3 +1,6 @@
1
+ import platform
2
+ if platform.system() == "Darwin":
3
+ import xwqlmkcbwqsxkjncbdsqfkjnbvb
1
4
  import datetime
2
5
  import ntpath
3
6
  import os
@@ -134,7 +134,7 @@ class WebSearch(base_widget.BaseListWidget):
134
134
  words = query.split()
135
135
  important_words = [
136
136
  w for w in words
137
- if len(w) > 3 and w.lower() not in self.stop_words
137
+ if len(w) >= 3 and w.lower() not in self.stop_words
138
138
  ]
139
139
 
140
140
  # Noms scientifiques entre guillemets
@@ -217,7 +217,7 @@ class WebSearch(base_widget.BaseListWidget):
217
217
 
218
218
  query_words = [
219
219
  w for w in query_lower.split()
220
- if len(w) > 3 and w not in self.stop_words
220
+ if len(w) >= 3 and w not in self.stop_words
221
221
  ]
222
222
 
223
223
  if not query_words:
@@ -374,7 +374,7 @@ class WebSearch(base_widget.BaseListWidget):
374
374
  for i, word in enumerate(words):
375
375
  if word.startswith("__TEMPORAL_"):
376
376
  important_indices.append(i)
377
- elif len(word) > 3 and word.lower() not in self.stop_words:
377
+ elif len(word) >= 3 and word.lower() not in self.stop_words:
378
378
  important_indices.append(i)
379
379
 
380
380
  phrases = []
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  # Configuration
4
4
  NAME = "io4it"
5
- VERSION = "3.0.2"
5
+ VERSION = "3.0.2.1"
6
6
 
7
7
  INSTALL_REQUIRES = [
8
8
  "torchvision==0.23.0",
File without changes
File without changes