From 7fe16349c6579123f0a55a73d08d8ad782c58580 Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Fri, 11 Jul 2025 16:15:02 +0200 Subject: [PATCH 01/17] Add New Script --- README.md | 6 + scripts/pdf_combiner.py | 642 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 648 insertions(+) create mode 100644 scripts/pdf_combiner.py diff --git a/README.md b/README.md index 553385b..cec68aa 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,9 @@ Introdotto il file `main.py` che gestisce: ├── remove.py ├── sposta_file.py ├── transcribe_wav.py + ├── pdf_combiner.py └── trash.py + ``` ### 📂 Idex Progetto @@ -148,6 +150,10 @@ Introdotto il file `main.py` che gestisce: estensioni.py ❯ Analisi e elenco ordinato delle estensioni file in una directory. + + + pdf_combiner.py + ❯ Genera PDF da immagini Jpeg. diff --git a/scripts/pdf_combiner.py b/scripts/pdf_combiner.py new file mode 100644 index 0000000..b2d804d --- /dev/null +++ b/scripts/pdf_combiner.py @@ -0,0 +1,642 @@ +# Genera PDF da immagini Jpeg. +""" +Script per l'elaborazione di documenti scansionati +Versione: 1.5 +Autore: MagnetarMan + Claude AI +Data: 2025 + +Questo script fornisce un'interfaccia grafica per processare immagini di documenti scansionati +e convertirle in un PDF ottimizzato. +""" + +import os +import sys +import cv2 +import numpy as np +from datetime import datetime +from PIL import Image, ImageFilter, ImageEnhance +import tkinter as tk +from tkinter import filedialog, messagebox, ttk +import threading +from reportlab.pdfgen import canvas +from reportlab.lib.pagesizes import letter, A4 +from reportlab.lib.utils import ImageReader +import io + +class DocumentProcessor: + def __init__(self): + self.processed_images = [] + self.original_folder = None + + def analyze_image(self, image_path): + """ + Analizza l'immagine per identificare il contenuto del documento + """ + try: + # Carica l'immagine con OpenCV + image = cv2.imread(image_path) + if image is None: + raise ValueError(f"Impossibile caricare l'immagine: {image_path}") + + # Converti in RGB per PIL + image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + return image_rgb + except Exception as e: + print(f"Errore nell'analisi dell'immagine {image_path}: {e}") + return None + + def enhance_sharpness(self, image): + """ + Aumenta la nitidezza dell'immagine (funzione rimossa per problemi di leggibilità) + """ + # Funzione disabilitata: l'aumento della nitidezza rendeva la pagina illegibile + # Ritorna l'immagine senza modifiche + return image + + def detect_and_correct_orientation(self, image): + """ + Rileva e corregge l'orientamento della pagina usando metodi più robusti + """ + # Converte in scala di grigi per l'analisi + gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) + + # Applica blur per ridurre il rumore + blurred = cv2.GaussianBlur(gray, (5, 5), 0) + + # Applica soglia per evidenziare il testo + _, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) + + # Prova diversi metodi per rilevare l'orientamento + + # Metodo 1: Analisi delle linee usando Hough Transform + edges = cv2.Canny(binary, 50, 150, apertureSize=3) + lines = cv2.HoughLines(edges, 1, np.pi/180, threshold=100) + + angles = [] + if lines is not None: + for line in lines: + rho, theta = line[0] + angle = np.degrees(theta) - 90 + angles.append(angle) + + # Metodo 2: Analisi dei contorni di testo + contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + + # Filtra e analizza i contorni più significativi + text_contours = [] + for contour in contours: + area = cv2.contourArea(contour) + if area > 50: # Filtra contorni troppo piccoli + x, y, w, h = cv2.boundingRect(contour) + aspect_ratio = w / h + # Considera solo contorni che potrebbero essere testo + if 0.1 < aspect_ratio < 10 and w > 10 and h > 5: + text_contours.append(contour) + + # Calcola angoli dai contorni di testo + for contour in text_contours: + if cv2.contourArea(contour) > 100: + rect = cv2.minAreaRect(contour) + angle = rect[2] + if rect[1][0] < rect[1][1]: # width < height + angle = angle + 90 + angles.append(angle) + + # Metodo 3: Analisi della distribuzione dei pixel + # Calcola le proiezioni orizzontali e verticali + h_projection = np.sum(binary, axis=1) + v_projection = np.sum(binary, axis=0) + + # Calcola la varianza delle proiezioni per diversi angoli + test_angles = [-90, -45, 0, 45, 90] + variances = [] + + for test_angle in test_angles: + if test_angle != 0: + center = (image.shape[1] // 2, image.shape[0] // 2) + rotation_matrix = cv2.getRotationMatrix2D(center, test_angle, 1.0) + rotated_binary = cv2.warpAffine(binary, rotation_matrix, (binary.shape[1], binary.shape[0])) + h_proj = np.sum(rotated_binary, axis=1) + else: + h_proj = h_projection + + # Calcola la varianza della proiezione orizzontale + variance = np.var(h_proj) + variances.append(variance) + + # L'angolo con la varianza maggiore dovrebbe essere quello corretto + if variances: + best_angle_idx = np.argmax(variances) + best_angle = test_angles[best_angle_idx] + angles.append(best_angle) + + # Determina l'angolo finale + if angles: + # Raggruppa angoli simili + angle_groups = {} + for angle in angles: + # Normalizza l'angolo + normalized = angle % 90 + if normalized > 45: + normalized = normalized - 90 + + # Raggruppa per intervalli di 10 gradi + group_key = round(normalized / 10) * 10 + if group_key not in angle_groups: + angle_groups[group_key] = [] + angle_groups[group_key].append(angle) + + # Trova il gruppo con più angoli + if angle_groups: + best_group = max(angle_groups.items(), key=lambda x: len(x[1])) + rotation_angle = np.median(best_group[1]) + + # Determina la rotazione da applicare + if rotation_angle > 60: + final_rotation = 90 + elif rotation_angle > 30: + final_rotation = 45 + elif rotation_angle < -60: + final_rotation = -90 + elif rotation_angle < -30: + final_rotation = -45 + elif abs(rotation_angle) < 5: + final_rotation = 0 + else: + final_rotation = rotation_angle + + # Applica la rotazione se necessaria + if abs(final_rotation) > 2: # Soglia minima per evitare rotazioni inutili + center = (image.shape[1] // 2, image.shape[0] // 2) + rotation_matrix = cv2.getRotationMatrix2D(center, final_rotation, 1.0) + + # Calcola le nuove dimensioni per evitare di tagliare l'immagine + cos_angle = abs(rotation_matrix[0, 0]) + sin_angle = abs(rotation_matrix[0, 1]) + new_width = int((image.shape[0] * sin_angle) + (image.shape[1] * cos_angle)) + new_height = int((image.shape[0] * cos_angle) + (image.shape[1] * sin_angle)) + + # Aggiusta la matrice di rotazione per centrare l'immagine + rotation_matrix[0, 2] += (new_width / 2) - (image.shape[1] / 2) + rotation_matrix[1, 2] += (new_height / 2) - (image.shape[0] / 2) + + # Applica la rotazione + rotated = cv2.warpAffine(image, rotation_matrix, (new_width, new_height), + borderMode=cv2.BORDER_CONSTANT, borderValue=(255, 255, 255)) + + print(f"Immagine ruotata di {final_rotation} gradi") + return rotated + + return image + + def convert_to_bw(self, image): + """ + Converte l'immagine in bianco e nero puro + """ + # Converte in scala di grigi + gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) + + # Applica soglia adattiva per un migliore risultato + binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, + cv2.THRESH_BINARY, 11, 2) + + # Converte in RGB per mantenere compatibilità + return cv2.cvtColor(binary, cv2.COLOR_GRAY2RGB) + + def clean_noise(self, image): + """ + Applica filtri di pulizia del rumore mantenendo i testi nitidi + """ + # Converte in scala di grigi per l'elaborazione + if len(image.shape) == 3: + gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) + else: + gray = image + + # 1. Filtro mediano per rimuovere il rumore salt-and-pepper + # Usa un kernel piccolo per non danneggiare i dettagli del testo + denoised = cv2.medianBlur(gray, 3) + + # 2. Morfologia: apertura per rimuovere piccoli punti di rumore + # Crea un kernel molto piccolo per preservare i caratteri + kernel_opening = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2)) + opened = cv2.morphologyEx(denoised, cv2.MORPH_OPEN, kernel_opening) + + # 3. Morfologia: chiusura per riempire piccoli buchi nei caratteri + kernel_closing = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2)) + closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel_closing) + + # 4. Filtro bilaterale per ridurre ulteriormente il rumore preservando i bordi + # Usa parametri conservativi per mantenere la nitidezza del testo + bilateral = cv2.bilateralFilter(closed, 5, 80, 80) + + # 5. Riapplica una soglia per assicurare il bianco e nero puro + _, clean_binary = cv2.threshold(bilateral, 127, 255, cv2.THRESH_BINARY) + + # 6. Operazione finale di pulizia: rimuove componenti connesse troppo piccole + # Trova tutte le componenti connesse + num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats( + 255 - clean_binary, connectivity=8, ltype=cv2.CV_32S) + + # Crea una maschera per le componenti da mantenere + min_area = 10 # Rimuove componenti più piccole di 10 pixel + mask = np.zeros_like(clean_binary) + + for i in range(1, num_labels): # Salta il background (label 0) + if stats[i, cv2.CC_STAT_AREA] >= min_area: + mask[labels == i] = 255 + + # Applica la maschera + result = clean_binary.copy() + result[mask == 255] = 0 # Rende neri i pixel del testo + + # Converte in RGB per mantenere compatibilità + return cv2.cvtColor(result, cv2.COLOR_GRAY2RGB) + + def enhance_contrast(self, image): + """ + Enfatizza leggermente il contrasto dell'immagine (funzione rimossa per problemi di leggibilità) + """ + # Funzione disabilitata: il contrasto eccessivo rendeva la pagina illegibile + # Ritorna l'immagine senza modifiche + return image + + def remove_borders(self, image): + """ + Rimuove i bordi esterni identificando automaticamente il foglio + """ + # Converte in scala di grigi per l'analisi + gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) + + # Applica blur per ridurre il rumore + blurred = cv2.GaussianBlur(gray, (5, 5), 0) + + # Applica soglia per separare il foglio dallo sfondo + _, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) + + # Trova i contorni + contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + + if contours: + # Trova il contorno più grande (presumibilmente il foglio) + largest_contour = max(contours, key=cv2.contourArea) + + # Calcola il rettangolo di delimitazione + x, y, w, h = cv2.boundingRect(largest_contour) + + # Aggiungi un piccolo margine per sicurezza + margin = 10 + x = max(0, x - margin) + y = max(0, y - margin) + w = min(image.shape[1] - x, w + 2 * margin) + h = min(image.shape[0] - y, h + 2 * margin) + + # Ritaglia l'immagine + cropped = image[y:y+h, x:x+w] + + # Verifica che il ritaglio sia ragionevole + if cropped.shape[0] > image.shape[0] * 0.3 and cropped.shape[1] > image.shape[1] * 0.3: + return cropped + + # Se non riesce a trovare un contorno valido, ritorna l'immagine originale + return image + + def process_single_image(self, image_path, progress_callback=None): + """ + Processa una singola immagine attraverso tutte le fasi + """ + try: + if progress_callback: + progress_callback("Analisi immagine...") + + # 1. Analisi iniziale + image = self.analyze_image(image_path) + if image is None: + return None + + if progress_callback: + progress_callback("Aumento nitidezza...") + + # 2. Aumento della nitidezza (disabilitato) + # image = self.enhance_sharpness(image) + + if progress_callback: + progress_callback("Correzione orientamento...") + + # 3. Correzione dell'orientamento + image = self.detect_and_correct_orientation(image) + + if progress_callback: + progress_callback("Conversione in bianco e nero...") + + # 4. Conversione in bianco e nero + image = self.convert_to_bw(image) + + if progress_callback: + progress_callback("Pulizia del rumore...") + + # 5. Pulizia del rumore (nuovo passaggio) + image = self.clean_noise(image) + + if progress_callback: + progress_callback("Enfatizzazione contrasto...") + + # 5. Enfatizzazione del contrasto (disabilitata) + # image = self.enhance_contrast(image) + + if progress_callback: + progress_callback("Rimozione bordi...") + + # 6. Eliminazione dei bordi + image = self.remove_borders(image) + + return image + + except Exception as e: + print(f"Errore nel processamento dell'immagine {image_path}: {e}") + return None + + def create_pdf(self, processed_images, output_path): + """ + Crea un PDF dalle immagini processate + """ + try: + # Crea il canvas PDF + c = canvas.Canvas(output_path, pagesize=A4) + + for i, image_array in enumerate(processed_images): + # Converte l'array numpy in PIL Image + pil_image = Image.fromarray(image_array) + + # Crea un buffer in memoria per l'immagine + img_buffer = io.BytesIO() + pil_image.save(img_buffer, format='PNG') + img_buffer.seek(0) + + # Dimensioni della pagina A4 + page_width, page_height = A4 + + # Calcola le dimensioni dell'immagine mantenendo le proporzioni + img_width, img_height = pil_image.size + aspect_ratio = img_width / img_height + + if aspect_ratio > page_width / page_height: + # L'immagine è più larga, adatta alla larghezza + new_width = page_width + new_height = page_width / aspect_ratio + else: + # L'immagine è più alta, adatta all'altezza + new_height = page_height + new_width = page_height * aspect_ratio + + # Centro l'immagine nella pagina + x = (page_width - new_width) / 2 + y = (page_height - new_height) / 2 + + # Disegna l'immagine sul PDF + c.drawImage(ImageReader(img_buffer), x, y, width=new_width, height=new_height) + + # Aggiungi una nuova pagina se non è l'ultima immagine + if i < len(processed_images) - 1: + c.showPage() + + # Salva il PDF + c.save() + return True + + except Exception as e: + print(f"Errore nella creazione del PDF: {e}") + return False + +class DocumentScannerGUI: + def __init__(self): + self.root = tk.Tk() + self.root.title("Elaboratore Documenti Scansionati") + self.root.geometry("600x500") + self.root.resizable(True, True) + + self.processor = DocumentProcessor() + self.image_paths = [] + self.is_processing = False + + self.setup_gui() + + def setup_gui(self): + """ + Configura l'interfaccia grafica + """ + # Frame principale + main_frame = ttk.Frame(self.root, padding="10") + main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) + + # Configura il ridimensionamento + self.root.columnconfigure(0, weight=1) + self.root.rowconfigure(0, weight=1) + main_frame.columnconfigure(1, weight=1) + + # Titolo + title_label = ttk.Label(main_frame, text="Elaboratore Documenti Scansionati", + font=("Arial", 16, "bold")) + title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20)) + + # Sezione selezione file + ttk.Label(main_frame, text="Seleziona Immagini:").grid(row=1, column=0, sticky=tk.W, pady=5) + + self.file_listbox = tk.Listbox(main_frame, height=8) + self.file_listbox.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5) + + # Scrollbar per la listbox + scrollbar = ttk.Scrollbar(main_frame, orient=tk.VERTICAL, command=self.file_listbox.yview) + scrollbar.grid(row=2, column=2, sticky=(tk.N, tk.S), pady=5) + self.file_listbox.configure(yscrollcommand=scrollbar.set) + + # Pulsanti per gestire i file + button_frame = ttk.Frame(main_frame) + button_frame.grid(row=3, column=0, columnspan=3, pady=10) + + ttk.Button(button_frame, text="Aggiungi Immagini", + command=self.add_images).pack(side=tk.LEFT, padx=5) + ttk.Button(button_frame, text="Rimuovi Selezionata", + command=self.remove_selected).pack(side=tk.LEFT, padx=5) + ttk.Button(button_frame, text="Svuota Lista", + command=self.clear_list).pack(side=tk.LEFT, padx=5) + + # Pulsante elaborazione + self.process_button = ttk.Button(main_frame, text="Elabora Documenti", + command=self.start_processing, style="Accent.TButton") + self.process_button.grid(row=4, column=0, columnspan=3, pady=20) + + # Barra di progresso + self.progress_var = tk.StringVar() + self.progress_var.set("Pronto per l'elaborazione") + + ttk.Label(main_frame, text="Stato:").grid(row=5, column=0, sticky=tk.W, pady=5) + self.status_label = ttk.Label(main_frame, textvariable=self.progress_var) + self.status_label.grid(row=5, column=1, sticky=tk.W, pady=5) + + self.progress_bar = ttk.Progressbar(main_frame, mode='indeterminate') + self.progress_bar.grid(row=6, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=5) + + # Informazioni aggiuntive + info_frame = ttk.LabelFrame(main_frame, text="Informazioni", padding="10") + info_frame.grid(row=7, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=10) + + info_text = """Operazioni eseguite su ogni immagine: +1. Analisi e caricamento dell'immagine +2. Correzione automatica dell'orientamento (migliorata) +3. Conversione in bianco e nero +4. Pulizia del rumore (nuovo - rimuove effetto fotocopiatrice) +5. Rimozione automatica dei bordi + +Il PDF finale sarà salvato nella stessa cartella delle immagini. +Nota: Le funzioni di aumento nitidezza e contrasto sono state rimosse per migliorare la leggibilità.""" + + ttk.Label(info_frame, text=info_text, justify=tk.LEFT).pack(anchor=tk.W) + + def add_images(self): + """ + Aggiunge immagini alla lista + """ + file_paths = filedialog.askopenfilenames( + title="Seleziona immagini", + filetypes=[("Immagini JPEG", "*.jpg *.jpeg"), ("Tutte le immagini", "*.jpg *.jpeg *.png")] + ) + + for file_path in file_paths: + if file_path not in self.image_paths: + self.image_paths.append(file_path) + self.file_listbox.insert(tk.END, os.path.basename(file_path)) + + self.update_ui_state() + + def remove_selected(self): + """ + Rimuove l'immagine selezionata dalla lista + """ + selected_indices = self.file_listbox.curselection() + if selected_indices: + index = selected_indices[0] + self.file_listbox.delete(index) + del self.image_paths[index] + self.update_ui_state() + + def clear_list(self): + """ + Svuota la lista delle immagini + """ + self.file_listbox.delete(0, tk.END) + self.image_paths.clear() + self.update_ui_state() + + def update_ui_state(self): + """ + Aggiorna lo stato dell'interfaccia + """ + has_images = len(self.image_paths) > 0 + self.process_button.configure(state=tk.NORMAL if has_images and not self.is_processing else tk.DISABLED) + + if has_images: + self.progress_var.set(f"Pronto per elaborare {len(self.image_paths)} immagini") + else: + self.progress_var.set("Pronto per l'elaborazione") + + def start_processing(self): + """ + Avvia il processo di elaborazione in un thread separato + """ + if not self.image_paths: + messagebox.showwarning("Attenzione", "Seleziona almeno un'immagine da elaborare.") + return + + self.is_processing = True + self.progress_bar.start() + self.update_ui_state() + + # Avvia il thread di elaborazione + thread = threading.Thread(target=self.process_images) + thread.daemon = True + thread.start() + + def process_images(self): + """ + Processa tutte le immagini e crea il PDF + """ + try: + processed_images = [] + total_images = len(self.image_paths) + + # Determina la cartella di output + if self.image_paths: + output_folder = os.path.dirname(self.image_paths[0]) + else: + output_folder = os.path.expanduser("~") + + # Processa ogni immagine + for i, image_path in enumerate(self.image_paths): + def update_progress(message): + self.root.after(0, lambda: self.progress_var.set(f"Immagine {i+1}/{total_images}: {message}")) + + processed_image = self.processor.process_single_image(image_path, update_progress) + + if processed_image is not None: + processed_images.append(processed_image) + else: + self.root.after(0, lambda: messagebox.showerror("Errore", f"Impossibile processare l'immagine: {os.path.basename(image_path)}")) + + if processed_images: + # Crea il nome del file PDF + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + pdf_filename = f"Documenti_Scansionati_{timestamp}.pdf" + pdf_path = os.path.join(output_folder, pdf_filename) + + # Aggiorna il progresso + self.root.after(0, lambda: self.progress_var.set("Creazione PDF...")) + + # Crea il PDF + if self.processor.create_pdf(processed_images, pdf_path): + self.root.after(0, lambda: self.show_success_message(pdf_path)) + else: + self.root.after(0, lambda: messagebox.showerror("Errore", "Errore nella creazione del PDF")) + else: + self.root.after(0, lambda: messagebox.showerror("Errore", "Nessuna immagine è stata processata con successo")) + + except Exception as e: + self.root.after(0, lambda: messagebox.showerror("Errore", f"Errore durante l'elaborazione: {str(e)}")) + finally: + # Ripristina l'interfaccia + self.root.after(0, self.processing_complete) + + def show_success_message(self, pdf_path): + """ + Mostra il messaggio di successo + """ + messagebox.showinfo("Successo", f"Elaborazione completata!\nIl PDF è stato salvato in:\n{pdf_path}") + + def processing_complete(self): + """ + Ripristina l'interfaccia dopo l'elaborazione + """ + self.is_processing = False + self.progress_bar.stop() + self.progress_var.set("Elaborazione completata") + self.update_ui_state() + + def run(self): + """ + Avvia l'applicazione + """ + self.root.mainloop() + +def main(): + """ + Funzione principale + """ + try: + app = DocumentScannerGUI() + app.run() + except Exception as e: + print(f"Errore nell'avvio dell'applicazione: {e}") + messagebox.showerror("Errore", f"Errore nell'avvio dell'applicazione: {e}") + +if __name__ == "__main__": + main() \ No newline at end of file From d7fe80ea24b3e904f5239e3547cbf9845072d785 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 17 Jul 2025 07:18:14 +0000 Subject: [PATCH 02/17] chore: auto-update requirements.txt --- requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 5a61dc5..ac999c0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,10 @@ beautifulsoup4==4.13.4 matplotlib==3.10.3 numpy==2.3.1 -pandas==2.3.0 +pandas==2.3.1 pdfkit==1.0.0 -Pillow==11.2.1 +Pillow==11.3.0 +reportlab==4.4.2 Requests==2.32.4 scikit_learn==1.7.0 whisper==1.1.10 From e477d76a5aad1cc2ff8d77d18eb73a349cf77c1f Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Thu, 17 Jul 2025 09:21:23 +0200 Subject: [PATCH 03/17] Improve user home detection and update Whisper model Replaced os.getlogin() with USERPROFILE environment variable for more reliable user home directory detection. Updated default Whisper model from 'medium' to 'large-v3' in transcribe_podcast for improved transcription quality. --- scripts/transcribe_wav.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/transcribe_wav.py b/scripts/transcribe_wav.py index c10c7f5..2f95346 100644 --- a/scripts/transcribe_wav.py +++ b/scripts/transcribe_wav.py @@ -8,8 +8,8 @@ def upgrade_pip_and_install_whisper(): """ Aggiorna pip e installa o reinstalla correttamente whisper. """ - user_name = os.getlogin() - python_path = os.path.join(f"C:\\Users\\{user_name}\\AppData\\Local\\Programs\\Python\\Python310", "python.exe") + user_home = os.environ.get('USERPROFILE') + python_path = os.path.join(user_home, "AppData", "Local", "Programs", "Python", "Python310", "python.exe") if not os.path.exists(python_path): print(f"Errore: Python 3.10 non trovato in {python_path}.") @@ -43,11 +43,11 @@ def ensure_python_3_10(): if sys.version_info[0] != 3 or sys.version_info[1] != 10: print("Forzando l'esecuzione con Python 3.10...") - # Recupera il nome dell'utente corrente - user_name = os.getlogin() + # Recupera il percorso della home directory reale + user_home = os.environ.get('USERPROFILE') # Costruisci il percorso di Python 3.10 dinamicamente - python_path = os.path.join(f"C:\\Users\\{user_name}\\AppData\\Local\\Programs\\Python\\Python310", "python.exe") + python_path = os.path.join(user_home, "AppData", "Local", "Programs", "Python", "Python310", "python.exe") if not os.path.exists(python_path): print(f"Errore: Python 3.10 non trovato in {python_path}. Verifica che Python 3.10 sia installato correttamente.") @@ -82,7 +82,7 @@ def import_whisper(): print(f"Impossibile importare whisper anche dopo l'installazione: {e}") sys.exit(1) -def transcribe_podcast(file_path, model_name='medium', language='it'): +def transcribe_podcast(file_path, model_name='large-v3', language='it'): """ Trascrive un file audio in formato .wav utilizzando il modello Whisper. """ From 8c0aa7b0dd4cba94ca6a10863f1230a4cccd0a6a Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Thu, 17 Jul 2025 09:24:33 +0200 Subject: [PATCH 04/17] Fix indentation in README file tree Corrected the indentation for the pdf_combiner.py entry in the project file tree for consistency and readability. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cec68aa..27c7a7e 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Introdotto il file `main.py` che gestisce: ├── remove.py ├── sposta_file.py ├── transcribe_wav.py - ├── pdf_combiner.py + ├── pdf_combiner.py └── trash.py ``` From 0ea5b6b34b60c4f58d019dd9d54cd42212d71bdf Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Thu, 17 Jul 2025 09:32:42 +0200 Subject: [PATCH 05/17] Update "Readme.md" --- README.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 27c7a7e..0a205c9 100644 --- a/README.md +++ b/README.md @@ -26,15 +26,19 @@ ## 👾 Features -**Versione 3.0** - Nuovo approccio all'esecuzione: non si esegue più uno script isolato, ma tramite un unico punto d’ingresso interattivo. +**Experimental Branch** - Ramo Sperimentale pubblico. + +> **ATTENZIONE** - Questo ramo è da interdersi come sviluppo attivo, è sconsigliato utilizzare la versione degli script presenti in questo ramo in quanto potrebbero avere problemi di funzionamento o non avviarsi del tutto. **Consigliato l'utilizzo a personale esperto.** -Introdotto il file `main.py` che gestisce: +**Versione 3.0** - Nuovo approccio all'esecuzione: non si esegue più uno script isolato, ma tramite un unico punto d’ingresso interattivo. -- L'installazione automatica delle dipendenze dal file `requirements.txt`. -- Un menu interattivo per scegliere quale script eseguire. -- Organizzazione automatica degli script in ordine alfabetico. -- Breve descrizione affiancata a ciascuno script. -- Migliore gestione e chiarezza degli strumenti disponibili. +> Introdotto il file `main.py` che gestisce: +> +> - L'installazione automatica delle dipendenze dal file `requirements.txt`. +> - Un menu interattivo per scegliere quale script eseguire. +> - Organizzazione automatica degli script in ordine alfabetico. +> - Breve descrizione affiancata a ciascuno script. +> - Migliore gestione e chiarezza degli strumenti disponibili. --- @@ -65,9 +69,7 @@ Introdotto il file `main.py` che gestisce: ├── remove.py ├── sposta_file.py ├── transcribe_wav.py - ├── pdf_combiner.py └── trash.py - ``` ### 📂 Idex Progetto @@ -150,10 +152,6 @@ Introdotto il file `main.py` che gestisce: estensioni.py ❯ Analisi e elenco ordinato delle estensioni file in una directory. - - - pdf_combiner.py - ❯ Genera PDF da immagini Jpeg. From aab168e41f4a2ea1c876060ab371affbafbff455 Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Sun, 20 Jul 2025 21:59:53 +0200 Subject: [PATCH 06/17] - Change the default model to "medium" for better performance mod: scripts/transcribe_wav.sh --- scripts/transcribe_wav.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/transcribe_wav.py b/scripts/transcribe_wav.py index 2f95346..6976146 100644 --- a/scripts/transcribe_wav.py +++ b/scripts/transcribe_wav.py @@ -82,7 +82,7 @@ def import_whisper(): print(f"Impossibile importare whisper anche dopo l'installazione: {e}") sys.exit(1) -def transcribe_podcast(file_path, model_name='large-v3', language='it'): +def transcribe_podcast(file_path, model_name='medium', language='it'): """ Trascrive un file audio in formato .wav utilizzando il modello Whisper. """ From 932f5acf1a5a65bfcc79818733cdf0ed1ea90bda Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Sun, 20 Jul 2025 22:55:28 +0200 Subject: [PATCH 07/17] Update Sciript Documentation and README - mod: "readme.md" - add: "\docs\pdf_combiner.md" --- Docs/pdf_combiner.md | 60 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 20 +++++++-------- 2 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 Docs/pdf_combiner.md diff --git a/Docs/pdf_combiner.md b/Docs/pdf_combiner.md new file mode 100644 index 0000000..6620f6c --- /dev/null +++ b/Docs/pdf_combiner.md @@ -0,0 +1,60 @@ +## 🖼️ _Generazione PDF da Immagini JPEG_ - **pdf_combiner.py** + +Uno script Python con interfaccia grafica che consente di selezionare immagini JPEG e convertirle in un **PDF ottimizzato**, pronto per l’archiviazione o la stampa. + +--- + +## Descrizione 📄 + +L'**Elaboratore di Documenti Scansionati** permette di importare una o più immagini, migliorarne automaticamente la leggibilità e generare un PDF ordinato e pulito. + +Ideale per: + +- **Digitalizzare documenti cartacei** in modo rapido. +- **Migliorare la leggibilità** di scansioni non perfette. +- **Creare archivi PDF** partendo da immagini di bassa qualità. + +--- + +## Funzionalità 🌟 + +- **Correzione orientamento**: Rileva automaticamente la rotazione delle pagine. +- **Pulizia avanzata**: Rimuove bordi, rumore e migliora la leggibilità del testo. +- **Conversione bianco/nero**: Per un output chiaro, leggibile e leggero. +- **Interfaccia intuitiva**: Selezione immagini con un semplice click. +- **Output ordinato**: Salva un PDF nella cartella delle immagini, con nome e data. + +--- + +### Esempio di utilizzo 🧪 + +1. Avvia lo script. +2. Seleziona una o più immagini `.jpeg` o `.jpg`. +3. Clicca su **"Elabora Documenti"**. +4. Attendi la fine del processo: il PDF sarà generato automaticamente. + +--- + +## Output 📊 + +### Output PDF + +- Nome file: `Documenti_Scansionati_YYYYMMDD_HHMMSS.pdf` +- Posizione: stessa cartella delle immagini originali. + +### Output Terminale / Log + +```plaintext +Immagine 1/3: Analisi immagine... +Immagine 1/3: Correzione orientamento... +Immagine 1/3: Conversione in bianco e nero... +... +Creazione PDF... +Elaborazione completata! +``` + +## Note 📝 + +- Compatibilità: Supporta immagini .jpeg, .jpg e .png. +- Performance: Il processo potrebbe richiedere alcuni secondi per immagine. +- Nitidezza & Contrasto: Le funzioni di aumento sono disabilitate per migliorare la leggibilità del testo. diff --git a/README.md b/README.md index 0a205c9..22382ef 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ ├── remove.py ├── sposta_file.py ├── transcribe_wav.py + ├── pdf_combiner.py └── trash.py ``` @@ -152,6 +153,11 @@ estensioni.py ❯ Analisi e elenco ordinato delle estensioni file in una directory. + + + pdf_combiner.py + ❯ Genera PDF da immagini Jpeg. + @@ -197,8 +203,10 @@ Utilizza Python-Script seguendo questi step: - [x] **`V 3.0`**: Creazione 'main.py'. - [x] **`V 3.1`**: Refactor 'Readme.md'. Creazione Cartella 'Docs' con la documentazione di ogni script. +- [x] **`V 3.1.1`**: Aggiunta Script PDF Combiner in versione Stabile. +- [x] **`V 3.1.2`**: il wrapper `main.py` aggiunge automaticamente i nuovi script all'avvio. - [ ] **`V 3.2`**: Automatizzare il processo di installazione di Python e dipendenze al 100%. -- [ ] **`V 4.0`**: unificare il tutto in un unico'main.py' con aggiunta di Interfaccia grafica. +- [ ] **`V 4.0`**: unificare il tutto in un unico 'main.py' con aggiunta di Interfaccia grafica. --- @@ -233,16 +241,6 @@ Utilizza Python-Script seguendo questi step: 8. **Revisione**: Una volta che la tua PR sarà revisionata e approvata, verrà unita ("merged") nel branch principale. Congratulazioni per il tuo contributo! -
-Contributor Graph -
-

- - - -

-
- --- ## 🎗 Licenza From e18089111f56c24d986c33f7a514e51a37103437 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 20 Jul 2025 20:56:12 +0000 Subject: [PATCH 08/17] chore: auto-update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ac999c0..4d1fd51 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,5 +6,5 @@ pdfkit==1.0.0 Pillow==11.3.0 reportlab==4.4.2 Requests==2.32.4 -scikit_learn==1.7.0 +scikit_learn==1.7.1 whisper==1.1.10 From 75c7cb9012de9819fed692b3d080f0c8f7905876 Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Sun, 20 Jul 2025 22:58:46 +0200 Subject: [PATCH 09/17] Fix Typos - mod: "README.md" --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22382ef..da0d489 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ├── remove.py ├── sposta_file.py ├── transcribe_wav.py - ├── pdf_combiner.py + ├── pdf_combiner.py └── trash.py ``` From 19952fcf5f3e1274849d2175852292f75a1be064 Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Sun, 20 Jul 2025 23:01:39 +0200 Subject: [PATCH 10/17] Update README - mod: "README.md" --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da0d489..9688dd3 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@


- versione + versione last-commit repo-top-language repo-language-count From 909fd5b826e9e3e52ee220d5c7c84422f522d38c Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Sun, 20 Jul 2025 23:03:46 +0200 Subject: [PATCH 11/17] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9688dd3..9210f6a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@

versione - last-commit + last-commit repo-top-language repo-language-count license From f232410a68e0415347cef60cceb1e55859fe2fea Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:28:37 +0200 Subject: [PATCH 12/17] Update "Readme.md" e "install.ps1" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Aggiornato `Readme.md` con le istruzioni per l'installazione alternativa. - Aggiornato `install.ps1` per installare versioni multiple di Python e risolvere problemi di compatibilità. --- README.md | 22 ++++++++++ install.ps1 | 115 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 131 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9210f6a..11b72c2 100644 --- a/README.md +++ b/README.md @@ -197,6 +197,28 @@ Utilizza Python-Script seguendo questi step: ❯ py main.py ``` +### ⚙️ Installatione Alternativa + +1. Clona la repository the Python-Script: + +```sh +❯ git clone https://github.com/Magnetarman/Python-Script +``` + +2. utilizza il terminale per Navigare fino alla cartella: + +```sh +❯ cd Python-Script +``` + +3. Avvia lo script `install.ps1`: + +```sh +❯ /install.ps1 +``` + +> Lo script `install.ps1` avviato installerà Python e dipendenze minimali. Successivamente lo scipt si occuperà di avviare automaticamente il `main.py` per utilizzare gli script disponibili. + --- ## 📌 Roadmap diff --git a/install.ps1 b/install.ps1 index 588f6b7..f8e8c32 100644 --- a/install.ps1 +++ b/install.ps1 @@ -20,6 +20,18 @@ function Check-PythonVersion { ) $pythonPath = Get-Command "python$version" -ErrorAction SilentlyContinue + if ($pythonPath -eq $null) { + $pythonPath = Get-Command "py" -ErrorAction SilentlyContinue + if ($pythonPath -ne $null) { + try { + $output = py -$version --version 2>$null + return $output -match "Python $version" + } + catch { + return $false + } + } + } return $pythonPath -ne $null } @@ -32,18 +44,106 @@ function Install-Python { Write-Host "Installando Python $version tramite winget..." switch ($version) { "3.10" { winget install --id Python.Python.3.10 -e --source winget } - default { Write-Host "Versione Python non supportata. Procedo con Python.Launcher." } + "3.11" { winget install --id Python.Python.3.11 -e --source winget } + "3.12" { winget install --id Python.Python.3.12 -e --source winget } + default { + Write-Host "Versione Python non supportata. Procedo con Python.Launcher." + winget install --id Python.Launcher -e --source winget + } } } -# Controllo e installazione per Python 3.10 -$pythonVersion = "3.10" +# Funzione per verificare i requisiti delle librerie +function Check-Requirements { + $scriptDir = Get-Location + $requirementsFile = Join-Path $scriptDir "requirements.txt" + + if (Test-Path $requirementsFile) { + Write-Host "Trovato file requirements.txt. Controllo compatibilità versioni Python..." + + $content = Get-Content $requirementsFile + $needsPython311 = $false + + foreach ($line in $content) { + if ($line -match "numpy==2\.[3-9]" -or $line -match "numpy>=2\.[3-9]") { + $needsPython311 = $true + Write-Host "Rilevata dipendenza numpy 2.3+ che richiede Python 3.11+" + break + } + } + + return $needsPython311 + } + + return $false +} + +# Controllo dei requisiti per determinare la versione Python necessaria +$needsPython311 = Check-Requirements +$pythonVersion = if ($needsPython311) { "3.11" } else { "3.10" } + +Write-Host "Versione Python richiesta: $pythonVersion" + +# Controllo e installazione per la versione Python necessaria if (-not (Check-PythonVersion -version $pythonVersion)) { Install-Python -version $pythonVersion } else { Write-Host "Python $pythonVersion è già installato." } +# Funzione per installare le dipendenze Python +function Install-PythonDependencies { + $scriptDir = Get-Location + $requirementsFile = Join-Path $scriptDir "requirements.txt" + + if (Test-Path $requirementsFile) { + Write-Host "Installando le dipendenze da requirements.txt..." + + # Aggiorna pip alla versione più recente + Write-Host "Aggiornamento di pip..." + py -$pythonVersion -m pip install --upgrade pip + + # Installa le dipendenze + Write-Host "Installazione delle librerie richieste..." + py -$pythonVersion -m pip install -r $requirementsFile + + if ($LASTEXITCODE -eq 0) { + Write-Host "Tutte le dipendenze sono state installate con successo." + } else { + Write-Host "Errore durante l'installazione delle dipendenze. Tentativo con versioni compatibili..." + + # Se fallisce, prova con versioni compatibili + $content = Get-Content $requirementsFile + foreach ($line in $content) { + if ($line -match "numpy==2\.[3-9]") { + Write-Host "Installando numpy versione compatibile con Python $pythonVersion..." + if ($pythonVersion -eq "3.10") { + py -$pythonVersion -m pip install "numpy>=1.21.0,<2.3.0" + } else { + py -$pythonVersion -m pip install numpy + } + } elseif ($line -match "^[a-zA-Z]" -and -not $line.StartsWith("#")) { + Write-Host "Installando: $line" + py -$pythonVersion -m pip install $line + } + } + } + } else { + Write-Host "File requirements.txt non trovato. Installando librerie comuni..." + + # Installa librerie comuni se non c'è requirements.txt + $commonLibraries = @("numpy", "pandas", "matplotlib", "requests") + + foreach ($lib in $commonLibraries) { + Write-Host "Installando $lib..." + py -$pythonVersion -m pip install $lib + } + } +} + +# Installa le dipendenze Python +Install-PythonDependencies + # Visualizzare il messaggio "Attendere..." per 2 secondi Write-Host "Attendere..." Start-Sleep -Seconds 2 @@ -54,10 +154,13 @@ $scriptDir = Get-Location # Verifica se il file main.py esiste nella stessa cartella dello script PowerShell $mainScript = Join-Path $scriptDir "main.py" if (Test-Path $mainScript) { - Write-Host "Eseguo main.py..." + Write-Host "Eseguo main.py con Python $pythonVersion..." - # Esegui main.py nella stessa finestra di PowerShell - py $mainScript + # Esegui main.py con la versione Python corretta + py -$pythonVersion $mainScript } else { Write-Host "Il file main.py non è stato trovato nella stessa cartella dello script PowerShell." } + +Write-Host "Installazione completata. Premere un tasto per continuare..." +$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") \ No newline at end of file From b2c9213efedb28a4e210c797eaa26d114c7ddd4e Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:38:27 +0200 Subject: [PATCH 13/17] Update "Readme.md" e "install.ps1" - Fix Typo Error nel file "Readme.md" - Fix installazione Python "install.ps1" --- README.md | 8 +- install.ps1 | 238 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 150 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index 11b72c2..664d0c1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ ├── README.md ├── install.ps1 ├── main.py - ├── Docs + ├── Docs ├── pipreqs-config.toml ├── requirements.txt └── scripts @@ -185,7 +185,7 @@ Utilizza Python-Script seguendo questi step: ❯ git clone https://github.com/Magnetarman/Python-Script ``` -2. utilizza il terminale per Navigare fino alla cartella: +2. Utilizza il terminale per Navigare fino alla cartella: ```sh ❯ cd Python-Script @@ -205,7 +205,7 @@ Utilizza Python-Script seguendo questi step: ❯ git clone https://github.com/Magnetarman/Python-Script ``` -2. utilizza il terminale per Navigare fino alla cartella: +2. Avvia il terminale in **modalita amministratore**, Naviga fino alla cartella:: ```sh ❯ cd Python-Script @@ -214,7 +214,7 @@ Utilizza Python-Script seguendo questi step: 3. Avvia lo script `install.ps1`: ```sh -❯ /install.ps1 +❯ ./install.ps1 ``` > Lo script `install.ps1` avviato installerà Python e dipendenze minimali. Successivamente lo scipt si occuperà di avviare automaticamente il `main.py` per utilizzare gli script disponibili. diff --git a/install.ps1 b/install.ps1 index f8e8c32..fa01f5e 100644 --- a/install.ps1 +++ b/install.ps1 @@ -19,20 +19,17 @@ function Check-PythonVersion { [string]$version ) - $pythonPath = Get-Command "python$version" -ErrorAction SilentlyContinue - if ($pythonPath -eq $null) { - $pythonPath = Get-Command "py" -ErrorAction SilentlyContinue - if ($pythonPath -ne $null) { - try { - $output = py -$version --version 2>$null - return $output -match "Python $version" - } - catch { - return $false - } + try { + $output = py -$version --version 2>$null + if ($output -match "Python $version") { + return $true } } - return $pythonPath -ne $null + catch { + # Ignora l'errore e continua + } + + return $false } # Funzione per installare Python tramite winget @@ -42,110 +39,142 @@ function Install-Python { ) Write-Host "Installando Python $version tramite winget..." - switch ($version) { - "3.10" { winget install --id Python.Python.3.10 -e --source winget } - "3.11" { winget install --id Python.Python.3.11 -e --source winget } - "3.12" { winget install --id Python.Python.3.12 -e --source winget } - default { - Write-Host "Versione Python non supportata. Procedo con Python.Launcher." - winget install --id Python.Launcher -e --source winget - } - } -} - -# Funzione per verificare i requisiti delle librerie -function Check-Requirements { - $scriptDir = Get-Location - $requirementsFile = Join-Path $scriptDir "requirements.txt" - if (Test-Path $requirementsFile) { - Write-Host "Trovato file requirements.txt. Controllo compatibilità versioni Python..." - - $content = Get-Content $requirementsFile - $needsPython311 = $false - - foreach ($line in $content) { - if ($line -match "numpy==2\.[3-9]" -or $line -match "numpy>=2\.[3-9]") { - $needsPython311 = $true - Write-Host "Rilevata dipendenza numpy 2.3+ che richiede Python 3.11+" - break + try { + switch ($version) { + "3.10" { + winget install --id Python.Python.3.10 -e --source winget --accept-source-agreements --accept-package-agreements + } + "3.11" { + winget install --id Python.Python.3.11 -e --source winget --accept-source-agreements --accept-package-agreements + } + "3.12" { + winget install --id Python.Python.3.12 -e --source winget --accept-source-agreements --accept-package-agreements + } + default { + Write-Host "Versione Python non supportata: $version" + return $false } } - return $needsPython311 + # Aspetta un momento per permettere l'installazione + Start-Sleep -Seconds 3 + + # Verifica se l'installazione è riuscita + if (Check-PythonVersion -version $version) { + Write-Host "Python $version installato con successo." + return $true + } else { + Write-Host "Installazione di Python $version completata, ma verifica fallita." + return $false + } + } + catch { + Write-Host "Errore durante l'installazione di Python $version : $($_.Exception.Message)" + return $false } - - return $false -} - -# Controllo dei requisiti per determinare la versione Python necessaria -$needsPython311 = Check-Requirements -$pythonVersion = if ($needsPython311) { "3.11" } else { "3.10" } - -Write-Host "Versione Python richiesta: $pythonVersion" - -# Controllo e installazione per la versione Python necessaria -if (-not (Check-PythonVersion -version $pythonVersion)) { - Install-Python -version $pythonVersion -} else { - Write-Host "Python $pythonVersion è già installato." } # Funzione per installare le dipendenze Python -function Install-PythonDependencies { +function Install-Dependencies { + param ( + [string]$pythonVersion + ) + $scriptDir = Get-Location $requirementsFile = Join-Path $scriptDir "requirements.txt" + Write-Host "Installando dipendenze con Python $pythonVersion..." + + # Aggiorna pip + Write-Host "Aggiornamento di pip..." + py -$pythonVersion -m pip install --upgrade pip + if (Test-Path $requirementsFile) { - Write-Host "Installando le dipendenze da requirements.txt..." - - # Aggiorna pip alla versione più recente - Write-Host "Aggiornamento di pip..." - py -$pythonVersion -m pip install --upgrade pip - - # Installa le dipendenze - Write-Host "Installazione delle librerie richieste..." + Write-Host "Trovato requirements.txt. Installando dipendenze..." py -$pythonVersion -m pip install -r $requirementsFile if ($LASTEXITCODE -eq 0) { - Write-Host "Tutte le dipendenze sono state installate con successo." + Write-Host "Dipendenze installate con successo da requirements.txt" + return $true } else { - Write-Host "Errore durante l'installazione delle dipendenze. Tentativo con versioni compatibili..." - - # Se fallisce, prova con versioni compatibili - $content = Get-Content $requirementsFile - foreach ($line in $content) { - if ($line -match "numpy==2\.[3-9]") { - Write-Host "Installando numpy versione compatibile con Python $pythonVersion..." - if ($pythonVersion -eq "3.10") { - py -$pythonVersion -m pip install "numpy>=1.21.0,<2.3.0" - } else { - py -$pythonVersion -m pip install numpy - } - } elseif ($line -match "^[a-zA-Z]" -and -not $line.StartsWith("#")) { - Write-Host "Installando: $line" - py -$pythonVersion -m pip install $line - } - } + Write-Host "Errore durante l'installazione da requirements.txt" + return $false } } else { Write-Host "File requirements.txt non trovato. Installando librerie comuni..." - # Installa librerie comuni se non c'è requirements.txt - $commonLibraries = @("numpy", "pandas", "matplotlib", "requests") + $commonLibraries = @("numpy", "pandas", "matplotlib", "requests", "pillow") + $allSuccess = $true foreach ($lib in $commonLibraries) { Write-Host "Installando $lib..." py -$pythonVersion -m pip install $lib + if ($LASTEXITCODE -ne 0) { + Write-Host "Errore durante l'installazione di $lib" + $allSuccess = $false + } } + + return $allSuccess } } -# Installa le dipendenze Python -Install-PythonDependencies +# Lista delle versioni Python da installare +$pythonVersions = @("3.10", "3.11", "3.12") +$installedVersions = @() +$primaryVersion = "" + +Write-Host "Controllo e installazione delle versioni Python..." + +# Controlla e installa ogni versione +foreach ($version in $pythonVersions) { + Write-Host "`nControllo Python $version..." + + if (Check-PythonVersion -version $version) { + Write-Host "Python $version è già installato." + $installedVersions += $version + if ($primaryVersion -eq "") { + $primaryVersion = $version + } + } else { + Write-Host "Python $version non trovato. Procedo con l'installazione..." + if (Install-Python -version $version) { + $installedVersions += $version + if ($primaryVersion -eq "") { + $primaryVersion = $version + } + } + } +} + +# Mostra riepilogo versioni installate +Write-Host "`nRiepilogo versioni Python installate:" +foreach ($version in $installedVersions) { + Write-Host " - Python $version" +} + +# Determina la versione da usare per le dipendenze +if ($installedVersions.Count -gt 0) { + # Preferisci 3.11 se disponibile, altrimenti usa la più recente + if ($installedVersions -contains "3.11") { + $primaryVersion = "3.11" + } elseif ($installedVersions -contains "3.12") { + $primaryVersion = "3.12" + } else { + $primaryVersion = $installedVersions[-1] + } + + Write-Host "`nUsando Python $primaryVersion per installare le dipendenze..." + Install-Dependencies -pythonVersion $primaryVersion +} else { + Write-Host "`nNessuna versione di Python è stata installata correttamente." + Write-Host "Tentativo di installazione del Python Launcher..." + winget install --id Python.Launcher -e --source winget --accept-source-agreements --accept-package-agreements +} # Visualizzare il messaggio "Attendere..." per 2 secondi -Write-Host "Attendere..." +Write-Host "`nAttendere..." Start-Sleep -Seconds 2 # Ottieni il percorso della cartella in cui è stato eseguito lo script PowerShell @@ -154,13 +183,38 @@ $scriptDir = Get-Location # Verifica se il file main.py esiste nella stessa cartella dello script PowerShell $mainScript = Join-Path $scriptDir "main.py" if (Test-Path $mainScript) { - Write-Host "Eseguo main.py con Python $pythonVersion..." - - # Esegui main.py con la versione Python corretta - py -$pythonVersion $mainScript + Write-Host "`nTrovato main.py nella cartella dello script." + + # Determina la versione Python migliore da usare + $versionToUse = "" + + if ($installedVersions -contains "3.11") { + $versionToUse = "3.11" + } elseif ($installedVersions -contains "3.12") { + $versionToUse = "3.12" + } elseif ($installedVersions -contains "3.10") { + $versionToUse = "3.10" + } + + if ($versionToUse -ne "") { + Write-Host "Eseguo main.py con Python $versionToUse..." + + # Esegui main.py con la versione Python corretta + py -$versionToUse $mainScript + } else { + Write-Host "Nessuna versione Python valida trovata. Tentativo con 'python'..." + python $mainScript + + if ($LASTEXITCODE -ne 0) { + Write-Host "Tentativo con 'py'..." + py $mainScript + } + } } else { - Write-Host "Il file main.py non è stato trovato nella stessa cartella dello script PowerShell." + Write-Host "`nIl file main.py non è stato trovato nella stessa cartella dello script PowerShell." + Write-Host "Cartella corrente: $scriptDir" + Write-Host "File cercato: $mainScript" } -Write-Host "Installazione completata. Premere un tasto per continuare..." +Write-Host "`nScript completato. Premere un tasto per chiudere..." $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") \ No newline at end of file From 0226d83fbe50d1955ac63505c14ecb6b59fa4e12 Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:46:27 +0200 Subject: [PATCH 14/17] Update "install.ps1" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - **Rifattorizzazione Script:** Migliorata la rilevazione delle versioni di Python, aggiungendo il tentativo di installazione delle versioni mancanti tramite `winget`. - **Miglioramento Dipendenze:** Aggiunta una migliore gestione degli errori e strategie di fallback per l'installazione delle dipendenze, anche in caso di mancanza del file `requirements.txt`. - **Logica e Output:** Migliorato l'output per essere più informativo e la logica per la selezione della migliore versione di Python. - **Esecuzione `main.py`:** Aumentata la resilienza nell'esecuzione del file `main.py`. --- install.ps1 | 341 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 239 insertions(+), 102 deletions(-) diff --git a/install.ps1 b/install.ps1 index fa01f5e..23f5781 100644 --- a/install.ps1 +++ b/install.ps1 @@ -13,61 +13,87 @@ if (-not (Check-Admin)) { exit } -# Funzione per verificare se una versione specifica di Python è installata -function Check-PythonVersion { - param ( - [string]$version - ) +# Funzione per ottenere tutte le versioni Python realmente disponibili +function Get-AvailablePythonVersions { + $availableVersions = @() try { - $output = py -$version --version 2>$null - if ($output -match "Python $version") { - return $true + # Usa py -0 per ottenere la lista delle versioni installate + $output = py -0 2>&1 + + if ($output) { + foreach ($line in $output) { + if ($line -match '-(\d+\.\d+)') { + $version = $matches[1] + if ($version -notin $availableVersions) { + $availableVersions += $version + } + } + } } } catch { - # Ignora l'errore e continua + Write-Host "Errore nel rilevamento versioni Python: $($_.Exception.Message)" + } + + # Se py -0 non funziona, prova metodi alternativi + if ($availableVersions.Count -eq 0) { + # Prova con comandi diretti + $testVersions = @("3.12", "3.11", "3.10", "3.9", "3.8") + foreach ($version in $testVersions) { + try { + $result = py -$version --version 2>$null + if ($result -and $result -match "Python $version") { + $availableVersions += $version + } + } + catch { + # Versione non disponibile + } + } } - return $false + return $availableVersions } -# Funzione per installare Python tramite winget -function Install-Python { +# Funzione per installare Python tramite winget se necessario +function Install-PythonIfNeeded { param ( [string]$version ) - Write-Host "Installando Python $version tramite winget..." + Write-Host "Tentativo di installazione Python $version tramite winget..." try { switch ($version) { "3.10" { - winget install --id Python.Python.3.10 -e --source winget --accept-source-agreements --accept-package-agreements + winget install --id Python.Python.3.10 -e --source winget --accept-source-agreements --accept-package-agreements --silent } "3.11" { - winget install --id Python.Python.3.11 -e --source winget --accept-source-agreements --accept-package-agreements + winget install --id Python.Python.3.11 -e --source winget --accept-source-agreements --accept-package-agreements --silent } "3.12" { - winget install --id Python.Python.3.12 -e --source winget --accept-source-agreements --accept-package-agreements - } - default { - Write-Host "Versione Python non supportata: $version" - return $false + winget install --id Python.Python.3.12 -e --source winget --accept-source-agreements --accept-package-agreements --silent } } - # Aspetta un momento per permettere l'installazione - Start-Sleep -Seconds 3 + # Attendi e ricontrolla + Start-Sleep -Seconds 5 - # Verifica se l'installazione è riuscita - if (Check-PythonVersion -version $version) { - Write-Host "Python $version installato con successo." - return $true - } else { - Write-Host "Installazione di Python $version completata, ma verifica fallita." - return $false + # Verifica se ora è disponibile + try { + $result = py -$version --version 2>$null + if ($result -and $result -match "Python $version") { + Write-Host "Python $version installato e verificato con successo." + return $true + } + } + catch { + # Installazione fallita } + + Write-Host "Installazione di Python $version non riuscita o non verificabile." + return $false } catch { Write-Host "Errore durante l'installazione di Python $version : $($_.Exception.Message)" @@ -75,7 +101,7 @@ function Install-Python { } } -# Funzione per installare le dipendenze Python +# Funzione per installare le dipendenze function Install-Dependencies { param ( [string]$pythonVersion @@ -86,32 +112,89 @@ function Install-Dependencies { Write-Host "Installando dipendenze con Python $pythonVersion..." + # Verifica che la versione sia realmente disponibile prima di procedere + try { + $testResult = py -$pythonVersion --version 2>$null + if (-not ($testResult -match "Python $pythonVersion")) { + Write-Host "ERRORE: Python $pythonVersion non è realmente disponibile!" + return $false + } + } + catch { + Write-Host "ERRORE: Impossibile verificare Python $pythonVersion!" + return $false + } + # Aggiorna pip Write-Host "Aggiornamento di pip..." - py -$pythonVersion -m pip install --upgrade pip + try { + py -$pythonVersion -m pip install --upgrade pip --quiet + Write-Host "Pip aggiornato con successo." + } + catch { + Write-Host "Errore nell'aggiornamento di pip, continuo comunque..." + } if (Test-Path $requirementsFile) { Write-Host "Trovato requirements.txt. Installando dipendenze..." - py -$pythonVersion -m pip install -r $requirementsFile - - if ($LASTEXITCODE -eq 0) { - Write-Host "Dipendenze installate con successo da requirements.txt" - return $true - } else { - Write-Host "Errore durante l'installazione da requirements.txt" + try { + py -$pythonVersion -m pip install -r $requirementsFile + + if ($LASTEXITCODE -eq 0) { + Write-Host "Dipendenze installate con successo da requirements.txt" + return $true + } else { + Write-Host "Errore durante l'installazione da requirements.txt (codice: $LASTEXITCODE)" + + # Prova installazione delle dipendenze una per una + Write-Host "Tentativo di installazione individuale delle dipendenze..." + $content = Get-Content $requirementsFile + $success = $true + + foreach ($line in $content) { + $line = $line.Trim() + if ($line -and -not $line.StartsWith("#")) { + Write-Host "Installando: $line" + try { + py -$pythonVersion -m pip install $line + if ($LASTEXITCODE -ne 0) { + Write-Host "Errore con $line, continuo con le altre..." + $success = $false + } + } + catch { + Write-Host "Eccezione durante l'installazione di $line" + $success = $false + } + } + } + + return $success + } + } + catch { + Write-Host "Eccezione durante l'installazione delle dipendenze: $($_.Exception.Message)" return $false } } else { Write-Host "File requirements.txt non trovato. Installando librerie comuni..." - $commonLibraries = @("numpy", "pandas", "matplotlib", "requests", "pillow") + $commonLibraries = @("numpy", "pandas", "matplotlib", "requests") $allSuccess = $true foreach ($lib in $commonLibraries) { Write-Host "Installando $lib..." - py -$pythonVersion -m pip install $lib - if ($LASTEXITCODE -ne 0) { - Write-Host "Errore durante l'installazione di $lib" + try { + py -$pythonVersion -m pip install $lib --quiet + if ($LASTEXITCODE -eq 0) { + Write-Host "$lib installato con successo." + } else { + Write-Host "Errore durante l'installazione di $lib" + $allSuccess = $false + } + } + catch { + Write-Host "Eccezione durante l'installazione di $lib" $allSuccess = $false } } @@ -120,61 +203,88 @@ function Install-Dependencies { } } -# Lista delle versioni Python da installare -$pythonVersions = @("3.10", "3.11", "3.12") -$installedVersions = @() -$primaryVersion = "" +Write-Host "=== INIZIO CONTROLLO E INSTALLAZIONE PYTHON ===" -Write-Host "Controllo e installazione delle versioni Python..." +# Ottieni versioni Python realmente disponibili +Write-Host "Rilevamento versioni Python disponibili..." +$availableVersions = Get-AvailablePythonVersions -# Controlla e installa ogni versione -foreach ($version in $pythonVersions) { - Write-Host "`nControllo Python $version..." +if ($availableVersions.Count -gt 0) { + Write-Host "Versioni Python trovate:" + foreach ($version in $availableVersions) { + Write-Host " - Python $version" + } +} else { + Write-Host "Nessuna versione Python trovata. Installazione di Python 3.11..." + + # Installa Python Launcher se non presente + Write-Host "Installando Python Launcher..." + winget install --id Python.Launcher -e --source winget --accept-source-agreements --accept-package-agreements --silent + + # Installa Python 3.11 + if (Install-PythonIfNeeded -version "3.11") { + $availableVersions += "3.11" + } - if (Check-PythonVersion -version $version) { - Write-Host "Python $version è già installato." - $installedVersions += $version - if ($primaryVersion -eq "") { - $primaryVersion = $version + # Se 3.11 fallisce, prova 3.10 + if ($availableVersions.Count -eq 0) { + if (Install-PythonIfNeeded -version "3.10") { + $availableVersions += "3.10" } - } else { - Write-Host "Python $version non trovato. Procedo con l'installazione..." - if (Install-Python -version $version) { - $installedVersions += $version - if ($primaryVersion -eq "") { - $primaryVersion = $version - } + } +} + +# Installa versioni aggiuntive se necessario +$targetVersions = @("3.11", "3.12") +foreach ($targetVersion in $targetVersions) { + if ($targetVersion -notin $availableVersions) { + Write-Host "Tentativo di installazione Python $targetVersion..." + if (Install-PythonIfNeeded -version $targetVersion) { + $availableVersions += $targetVersion } } } -# Mostra riepilogo versioni installate -Write-Host "`nRiepilogo versioni Python installate:" -foreach ($version in $installedVersions) { - Write-Host " - Python $version" +# Ri-rileva le versioni dopo le installazioni +Write-Host "Ri-rilevamento versioni Python dopo installazioni..." +$finalVersions = Get-AvailablePythonVersions + +Write-Host "Versioni Python finali disponibili:" +if ($finalVersions.Count -gt 0) { + foreach ($version in $finalVersions) { + Write-Host " - Python $version" + } +} else { + Write-Host "ATTENZIONE: Nessuna versione Python rilevata!" } -# Determina la versione da usare per le dipendenze -if ($installedVersions.Count -gt 0) { - # Preferisci 3.11 se disponibile, altrimenti usa la più recente - if ($installedVersions -contains "3.11") { - $primaryVersion = "3.11" - } elseif ($installedVersions -contains "3.12") { - $primaryVersion = "3.12" - } else { - $primaryVersion = $installedVersions[-1] +# Scegli la versione migliore per installare le dipendenze +$versionToUse = "" +$preferenceOrder = @("3.11", "3.12", "3.10", "3.9", "3.8") + +foreach ($preferredVersion in $preferenceOrder) { + if ($preferredVersion -in $finalVersions) { + $versionToUse = $preferredVersion + break } +} + +if ($versionToUse -ne "") { + Write-Host "Usando Python $versionToUse per installare le dipendenze..." + $installResult = Install-Dependencies -pythonVersion $versionToUse - Write-Host "`nUsando Python $primaryVersion per installare le dipendenze..." - Install-Dependencies -pythonVersion $primaryVersion + if ($installResult) { + Write-Host "Dipendenze installate con successo!" + } else { + Write-Host "Problemi durante l'installazione delle dipendenze." + } } else { - Write-Host "`nNessuna versione di Python è stata installata correttamente." - Write-Host "Tentativo di installazione del Python Launcher..." - winget install --id Python.Launcher -e --source winget --accept-source-agreements --accept-package-agreements + Write-Host "ERRORE: Nessuna versione Python utilizzabile trovata!" } # Visualizzare il messaggio "Attendere..." per 2 secondi -Write-Host "`nAttendere..." +Write-Host "" +Write-Host "Attendere..." Start-Sleep -Seconds 2 # Ottieni il percorso della cartella in cui è stato eseguito lo script PowerShell @@ -182,39 +292,66 @@ $scriptDir = Get-Location # Verifica se il file main.py esiste nella stessa cartella dello script PowerShell $mainScript = Join-Path $scriptDir "main.py" +Write-Host "Verifica esistenza main.py in: $scriptDir" + if (Test-Path $mainScript) { - Write-Host "`nTrovato main.py nella cartella dello script." + Write-Host "Trovato main.py nella cartella dello script." - # Determina la versione Python migliore da usare - $versionToUse = "" - - if ($installedVersions -contains "3.11") { - $versionToUse = "3.11" - } elseif ($installedVersions -contains "3.12") { - $versionToUse = "3.12" - } elseif ($installedVersions -contains "3.10") { - $versionToUse = "3.10" + # Usa la versione Python migliore disponibile + $executionVersion = "" + foreach ($preferredVersion in $preferenceOrder) { + if ($preferredVersion -in $finalVersions) { + $executionVersion = $preferredVersion + break + } } - if ($versionToUse -ne "") { - Write-Host "Eseguo main.py con Python $versionToUse..." + if ($executionVersion -ne "") { + Write-Host "Eseguo main.py con Python $executionVersion..." - # Esegui main.py con la versione Python corretta - py -$versionToUse $mainScript + # Verifica finale che la versione sia utilizzabile + try { + $testResult = py -$executionVersion --version 2>$null + if ($testResult -match "Python $executionVersion") { + # Esegui main.py con la versione Python corretta + py -$executionVersion $mainScript + } else { + Write-Host "Versione $executionVersion non verificabile, uso comando generico..." + py $mainScript + } + } + catch { + Write-Host "Errore nella verifica finale, uso comando generico..." + py $mainScript + } } else { - Write-Host "Nessuna versione Python valida trovata. Tentativo con 'python'..." - python $mainScript - - if ($LASTEXITCODE -ne 0) { - Write-Host "Tentativo con 'py'..." + Write-Host "Nessuna versione Python valida, tentativo con comando generico..." + try { py $mainScript } + catch { + Write-Host "Tentativo con 'python'..." + python $mainScript + } } } else { - Write-Host "`nIl file main.py non è stato trovato nella stessa cartella dello script PowerShell." + Write-Host "Il file main.py non è stato trovato nella stessa cartella dello script PowerShell." Write-Host "Cartella corrente: $scriptDir" Write-Host "File cercato: $mainScript" + + # Lista i file .py nella cartella per debug + $pyFiles = Get-ChildItem -Path $scriptDir -Filter "*.py" -ErrorAction SilentlyContinue + if ($pyFiles.Count -gt 0) { + Write-Host "File Python trovati nella cartella:" + foreach ($file in $pyFiles) { + Write-Host " - $($file.Name)" + } + } else { + Write-Host "Nessun file Python trovato nella cartella." + } } -Write-Host "`nScript completato. Premere un tasto per chiudere..." +Write-Host "" +Write-Host "=== SCRIPT COMPLETATO ===" +Write-Host "Premere un tasto per chiudere..." $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") \ No newline at end of file From e5a449b8ebc207e620b21ede3dd3f5207dfe35d1 Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:57:53 +0200 Subject: [PATCH 15/17] update "install.ps1" - Add aggiunta funzione di aggiunta al PATH di windows per utilizzare nativamente Pip e Python --- install.ps1 | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/install.ps1 b/install.ps1 index 23f5781..f3e0e7a 100644 --- a/install.ps1 +++ b/install.ps1 @@ -282,6 +282,92 @@ if ($versionToUse -ne "") { Write-Host "ERRORE: Nessuna versione Python utilizzabile trovata!" } +# Funzione per aggiungere Python e pip al PATH di Windows +function Add-PythonToPath { + param ( + [string]$pythonVersion + ) + + Write-Host "Aggiungendo Python $pythonVersion al PATH di Windows..." + + try { + # Ottieni il percorso di installazione di Python + $pythonOutput = py -$pythonVersion -c "import sys; print(sys.executable)" 2>$null + + if ($pythonOutput) { + $pythonPath = Split-Path $pythonOutput + $scriptsPath = Join-Path $pythonPath "Scripts" + + Write-Host "Percorso Python: $pythonPath" + Write-Host "Percorso Scripts: $scriptsPath" + + # Ottieni il PATH corrente + $currentPath = [Environment]::GetEnvironmentVariable("PATH", "User") + + # Controlla se i percorsi sono già nel PATH + $pathsToAdd = @() + + if ($currentPath -notlike "*$pythonPath*") { + $pathsToAdd += $pythonPath + Write-Host "Aggiungendo $pythonPath al PATH..." + } else { + Write-Host "Python path già presente nel PATH." + } + + if ($currentPath -notlike "*$scriptsPath*") { + $pathsToAdd += $scriptsPath + Write-Host "Aggiungendo $scriptsPath al PATH..." + } else { + Write-Host "Scripts path già presente nel PATH." + } + + # Aggiungi i percorsi al PATH se necessario + if ($pathsToAdd.Count -gt 0) { + $newPath = $currentPath + foreach ($pathToAdd in $pathsToAdd) { + if ($newPath -ne "") { + $newPath += ";" + } + $newPath += $pathToAdd + } + + # Imposta il nuovo PATH per l'utente corrente + [Environment]::SetEnvironmentVariable("PATH", $newPath, "User") + + # Aggiorna il PATH nella sessione corrente + $env:PATH = $newPath + + Write-Host "PATH aggiornato con successo!" + Write-Host "I percorsi Python sono ora disponibili globalmente." + + return $true + } else { + Write-Host "Tutti i percorsi Python sono già nel PATH." + return $true + } + } else { + Write-Host "Impossibile ottenere il percorso di Python $pythonVersion" + return $false + } + } + catch { + Write-Host "Errore durante l'aggiunta di Python al PATH: $($_.Exception.Message)" + return $false + } +} + +# Aggiungi la versione Python principale al PATH +if ($versionToUse -ne "") { + Write-Host "Configurazione PATH per Python $versionToUse..." + $pathResult = Add-PythonToPath -pythonVersion $versionToUse + + if ($pathResult) { + Write-Host "PATH configurato correttamente!" + } else { + Write-Host "Problemi nella configurazione del PATH, continuo comunque..." + } +} + # Visualizzare il messaggio "Attendere..." per 2 secondi Write-Host "" Write-Host "Attendere..." @@ -309,11 +395,18 @@ if (Test-Path $mainScript) { if ($executionVersion -ne "") { Write-Host "Eseguo main.py con Python $executionVersion..." + # Aggiungi anche questa versione al PATH se diversa da quella usata per le dipendenze + if ($executionVersion -ne $versionToUse) { + Write-Host "Configurazione PATH per Python $executionVersion..." + Add-PythonToPath -pythonVersion $executionVersion + } + # Verifica finale che la versione sia utilizzabile try { $testResult = py -$executionVersion --version 2>$null if ($testResult -match "Python $executionVersion") { # Esegui main.py con la versione Python corretta + Write-Host "Avvio di main.py..." py -$executionVersion $mainScript } else { Write-Host "Versione $executionVersion non verificabile, uso comando generico..." From 6f7a972c1f325dad79fa1d16b5a36ce91d2f8c5b Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Fri, 1 Aug 2025 20:05:57 +0200 Subject: [PATCH 16/17] Update "install.ps1" - Clean Script Code --- install.ps1 | 511 +++++++++++++++------------------------------------- 1 file changed, 144 insertions(+), 367 deletions(-) diff --git a/install.ps1 b/install.ps1 index f3e0e7a..9b54474 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1,450 +1,227 @@ -# Funzione per verificare se PowerShell è in modalità amministratore +# Funzione per verificare privilegi amministratore function Check-Admin { - $isAdmin = [bool]([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) - return $isAdmin + return [bool]([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } -# Se PowerShell non è in modalità amministratore, chiedi i privilegi di amministratore +# Richiedi privilegi amministratore se necessario if (-not (Check-Admin)) { Write-Host "PowerShell non è in modalità amministratore. Avvio con privilegi di amministratore..." - - # Crea un nuovo processo PowerShell con privilegi di amministratore Start-Process powershell -ArgumentList "Start-Process powershell -Verb runAs -ArgumentList '$PSCommandPath'" -Verb runAs exit } -# Funzione per ottenere tutte le versioni Python realmente disponibili +# Funzione per ottenere versioni Python disponibili function Get-AvailablePythonVersions { - $availableVersions = @() - + $versions = @() try { - # Usa py -0 per ottenere la lista delle versioni installate $output = py -0 2>&1 - if ($output) { - foreach ($line in $output) { - if ($line -match '-(\d+\.\d+)') { - $version = $matches[1] - if ($version -notin $availableVersions) { - $availableVersions += $version - } - } - } + $versions = $output | Where-Object { $_ -match '-(\d+\.\d+)' } | ForEach-Object { $matches[1] } | Sort-Object -Unique } - } - catch { - Write-Host "Errore nel rilevamento versioni Python: $($_.Exception.Message)" - } - - # Se py -0 non funziona, prova metodi alternativi - if ($availableVersions.Count -eq 0) { - # Prova con comandi diretti - $testVersions = @("3.12", "3.11", "3.10", "3.9", "3.8") - foreach ($version in $testVersions) { - try { - $result = py -$version --version 2>$null - if ($result -and $result -match "Python $version") { - $availableVersions += $version - } - } - catch { - # Versione non disponibile + + # Fallback se py -0 non funziona + if ($versions.Count -eq 0) { + @("3.12", "3.11", "3.10", "3.9", "3.8") | ForEach-Object { + try { + if ((py -$_ --version 2>$null) -match "Python $_") { $versions += $_ } + } catch { } } } - } - - return $availableVersions + } catch { } + return $versions } -# Funzione per installare Python tramite winget se necessario +# Funzione per installare Python tramite winget function Install-PythonIfNeeded { - param ( - [string]$version - ) - - Write-Host "Tentativo di installazione Python $version tramite winget..." + param([string]$version) + Write-Host "Installando Python $version tramite winget..." try { - switch ($version) { - "3.10" { - winget install --id Python.Python.3.10 -e --source winget --accept-source-agreements --accept-package-agreements --silent - } - "3.11" { - winget install --id Python.Python.3.11 -e --source winget --accept-source-agreements --accept-package-agreements --silent - } - "3.12" { - winget install --id Python.Python.3.12 -e --source winget --accept-source-agreements --accept-package-agreements --silent - } + $packageId = switch ($version) { + "3.10" { "Python.Python.3.10" } + "3.11" { "Python.Python.3.11" } + "3.12" { "Python.Python.3.12" } + default { return $false } } - # Attendi e ricontrolla + winget install --id $packageId -e --source winget --accept-source-agreements --accept-package-agreements --silent | Out-Null Start-Sleep -Seconds 5 - # Verifica se ora è disponibile - try { - $result = py -$version --version 2>$null - if ($result -and $result -match "Python $version") { - Write-Host "Python $version installato e verificato con successo." - return $true - } - } - catch { - # Installazione fallita + $result = py -$version --version 2>$null + if ($result -match "Python $version") { + Write-Host "Python $version installato con successo." + return $true } + } catch { } + + Write-Host "Installazione di Python $version fallita." + return $false +} + +# Funzione per aggiungere Python al PATH +function Add-PythonToPath { + param([string]$pythonVersion) + + Write-Host "Configurando PATH per Python $pythonVersion..." + try { + $pythonExe = py -$pythonVersion -c "import sys; print(sys.executable)" 2>$null + if (-not $pythonExe) { return $false } - Write-Host "Installazione di Python $version non riuscita o non verificabile." - return $false - } - catch { - Write-Host "Errore durante l'installazione di Python $version : $($_.Exception.Message)" + $pythonPath = Split-Path $pythonExe + $scriptsPath = Join-Path $pythonPath "Scripts" + $currentPath = [Environment]::GetEnvironmentVariable("PATH", "User") + $pathsToAdd = @($pythonPath, $scriptsPath) | Where-Object { $currentPath -notlike "*$_*" } + + if ($pathsToAdd.Count -gt 0) { + $newPath = ($currentPath, $pathsToAdd) -join ";" + [Environment]::SetEnvironmentVariable("PATH", $newPath, "User") + $env:PATH = $newPath + Write-Host "PATH aggiornato: $($pathsToAdd -join ', ')" + return $true + } else { + Write-Host "PATH già configurato correttamente." + return $true + } + } catch { + Write-Host "Errore configurazione PATH: $($_.Exception.Message)" return $false } } -# Funzione per installare le dipendenze +# Funzione per installare dipendenze function Install-Dependencies { - param ( - [string]$pythonVersion - ) - - $scriptDir = Get-Location - $requirementsFile = Join-Path $scriptDir "requirements.txt" + param([string]$pythonVersion) - Write-Host "Installando dipendenze con Python $pythonVersion..." - - # Verifica che la versione sia realmente disponibile prima di procedere - try { - $testResult = py -$pythonVersion --version 2>$null - if (-not ($testResult -match "Python $pythonVersion")) { - Write-Host "ERRORE: Python $pythonVersion non è realmente disponibile!" - return $false - } - } - catch { - Write-Host "ERRORE: Impossibile verificare Python $pythonVersion!" + # Verifica disponibilità versione + if (-not ((py -$pythonVersion --version 2>$null) -match "Python $pythonVersion")) { + Write-Host "ERRORE: Python $pythonVersion non disponibile!" return $false } + Write-Host "Installando dipendenze con Python $pythonVersion..." + # Aggiorna pip - Write-Host "Aggiornamento di pip..." try { - py -$pythonVersion -m pip install --upgrade pip --quiet - Write-Host "Pip aggiornato con successo." - } - catch { - Write-Host "Errore nell'aggiornamento di pip, continuo comunque..." + py -$pythonVersion -m pip install --upgrade pip --quiet | Out-Null + Write-Host "Pip aggiornato." + } catch { + Write-Host "Warning: Errore aggiornamento pip." } + $scriptDir = Get-Location + $requirementsFile = Join-Path $scriptDir "requirements.txt" + if (Test-Path $requirementsFile) { - Write-Host "Trovato requirements.txt. Installando dipendenze..." - try { - py -$pythonVersion -m pip install -r $requirementsFile - - if ($LASTEXITCODE -eq 0) { - Write-Host "Dipendenze installate con successo da requirements.txt" - return $true - } else { - Write-Host "Errore durante l'installazione da requirements.txt (codice: $LASTEXITCODE)" - - # Prova installazione delle dipendenze una per una - Write-Host "Tentativo di installazione individuale delle dipendenze..." - $content = Get-Content $requirementsFile - $success = $true - - foreach ($line in $content) { - $line = $line.Trim() - if ($line -and -not $line.StartsWith("#")) { - Write-Host "Installando: $line" - try { - py -$pythonVersion -m pip install $line - if ($LASTEXITCODE -ne 0) { - Write-Host "Errore con $line, continuo con le altre..." - $success = $false - } - } - catch { - Write-Host "Eccezione durante l'installazione di $line" - $success = $false - } - } - } - - return $success + Write-Host "Installando da requirements.txt..." + py -$pythonVersion -m pip install -r $requirementsFile + + if ($LASTEXITCODE -eq 0) { + Write-Host "Dipendenze installate con successo." + return $true + } else { + # Installazione individuale come fallback + Write-Host "Tentativo installazione individuale..." + $success = $true + Get-Content $requirementsFile | Where-Object { $_.Trim() -and -not $_.StartsWith("#") } | ForEach-Object { + Write-Host "Installando: $_" + py -$pythonVersion -m pip install $_ --quiet + if ($LASTEXITCODE -ne 0) { $success = $false } } - } - catch { - Write-Host "Eccezione durante l'installazione delle dipendenze: $($_.Exception.Message)" - return $false + return $success } } else { - Write-Host "File requirements.txt non trovato. Installando librerie comuni..." - - $commonLibraries = @("numpy", "pandas", "matplotlib", "requests") - $allSuccess = $true + Write-Host "Installando librerie comuni..." + $libs = @("numpy", "pandas", "matplotlib", "requests") + $success = $true - foreach ($lib in $commonLibraries) { - Write-Host "Installando $lib..." - try { - py -$pythonVersion -m pip install $lib --quiet - if ($LASTEXITCODE -eq 0) { - Write-Host "$lib installato con successo." - } else { - Write-Host "Errore durante l'installazione di $lib" - $allSuccess = $false - } - } - catch { - Write-Host "Eccezione durante l'installazione di $lib" - $allSuccess = $false + $libs | ForEach-Object { + Write-Host "Installando $_..." + py -$pythonVersion -m pip install $_ --quiet + if ($LASTEXITCODE -ne 0) { + Write-Host "Errore con $_" + $success = $false } } - - return $allSuccess + return $success } } -Write-Host "=== INIZIO CONTROLLO E INSTALLAZIONE PYTHON ===" +# === ESECUZIONE PRINCIPALE === +Write-Host "=== SETUP PYTHON E DIPENDENZE ===" -# Ottieni versioni Python realmente disponibili -Write-Host "Rilevamento versioni Python disponibili..." +# Rileva versioni disponibili +Write-Host "Rilevamento versioni Python..." $availableVersions = Get-AvailablePythonVersions if ($availableVersions.Count -gt 0) { - Write-Host "Versioni Python trovate:" - foreach ($version in $availableVersions) { - Write-Host " - Python $version" - } + Write-Host "Versioni trovate: $($availableVersions -join ', ')" } else { - Write-Host "Nessuna versione Python trovata. Installazione di Python 3.11..." - - # Installa Python Launcher se non presente - Write-Host "Installando Python Launcher..." - winget install --id Python.Launcher -e --source winget --accept-source-agreements --accept-package-agreements --silent + Write-Host "Nessuna versione trovata. Installando Python..." + winget install --id Python.Launcher -e --source winget --accept-source-agreements --accept-package-agreements --silent | Out-Null - # Installa Python 3.11 - if (Install-PythonIfNeeded -version "3.11") { - $availableVersions += "3.11" - } - - # Se 3.11 fallisce, prova 3.10 - if ($availableVersions.Count -eq 0) { - if (Install-PythonIfNeeded -version "3.10") { - $availableVersions += "3.10" - } - } + # Installa 3.11 come priorità + if (Install-PythonIfNeeded -version "3.11") { $availableVersions += "3.11" } + elseif (Install-PythonIfNeeded -version "3.10") { $availableVersions += "3.10" } } -# Installa versioni aggiuntive se necessario -$targetVersions = @("3.11", "3.12") -foreach ($targetVersion in $targetVersions) { - if ($targetVersion -notin $availableVersions) { - Write-Host "Tentativo di installazione Python $targetVersion..." - if (Install-PythonIfNeeded -version $targetVersion) { - $availableVersions += $targetVersion - } - } +# Installa versioni target se mancanti +@("3.11", "3.12") | Where-Object { $_ -notin $availableVersions } | ForEach-Object { + if (Install-PythonIfNeeded -version $_) { $availableVersions += $_ } } -# Ri-rileva le versioni dopo le installazioni -Write-Host "Ri-rilevamento versioni Python dopo installazioni..." +# Ri-rileva versioni finali $finalVersions = Get-AvailablePythonVersions +Write-Host "Versioni finali: $($finalVersions -join ', ')" -Write-Host "Versioni Python finali disponibili:" -if ($finalVersions.Count -gt 0) { - foreach ($version in $finalVersions) { - Write-Host " - Python $version" - } -} else { - Write-Host "ATTENZIONE: Nessuna versione Python rilevata!" -} - -# Scegli la versione migliore per installare le dipendenze -$versionToUse = "" -$preferenceOrder = @("3.11", "3.12", "3.10", "3.9", "3.8") +# Seleziona versione ottimale +$versionToUse = @("3.11", "3.12", "3.10", "3.9", "3.8") | Where-Object { $_ -in $finalVersions } | Select-Object -First 1 -foreach ($preferredVersion in $preferenceOrder) { - if ($preferredVersion -in $finalVersions) { - $versionToUse = $preferredVersion - break - } -} - -if ($versionToUse -ne "") { - Write-Host "Usando Python $versionToUse per installare le dipendenze..." +if ($versionToUse) { + Write-Host "Usando Python $versionToUse per dipendenze..." $installResult = Install-Dependencies -pythonVersion $versionToUse - if ($installResult) { - Write-Host "Dipendenze installate con successo!" - } else { - Write-Host "Problemi durante l'installazione delle dipendenze." - } -} else { - Write-Host "ERRORE: Nessuna versione Python utilizzabile trovata!" -} - -# Funzione per aggiungere Python e pip al PATH di Windows -function Add-PythonToPath { - param ( - [string]$pythonVersion - ) + # Configura PATH + Add-PythonToPath -pythonVersion $versionToUse | Out-Null - Write-Host "Aggiungendo Python $pythonVersion al PATH di Windows..." + Write-Host "Attendere..." + Start-Sleep -Seconds 2 - try { - # Ottieni il percorso di installazione di Python - $pythonOutput = py -$pythonVersion -c "import sys; print(sys.executable)" 2>$null - - if ($pythonOutput) { - $pythonPath = Split-Path $pythonOutput - $scriptsPath = Join-Path $pythonPath "Scripts" - - Write-Host "Percorso Python: $pythonPath" - Write-Host "Percorso Scripts: $scriptsPath" - - # Ottieni il PATH corrente - $currentPath = [Environment]::GetEnvironmentVariable("PATH", "User") - - # Controlla se i percorsi sono già nel PATH - $pathsToAdd = @() - - if ($currentPath -notlike "*$pythonPath*") { - $pathsToAdd += $pythonPath - Write-Host "Aggiungendo $pythonPath al PATH..." - } else { - Write-Host "Python path già presente nel PATH." - } - - if ($currentPath -notlike "*$scriptsPath*") { - $pathsToAdd += $scriptsPath - Write-Host "Aggiungendo $scriptsPath al PATH..." - } else { - Write-Host "Scripts path già presente nel PATH." - } - - # Aggiungi i percorsi al PATH se necessario - if ($pathsToAdd.Count -gt 0) { - $newPath = $currentPath - foreach ($pathToAdd in $pathsToAdd) { - if ($newPath -ne "") { - $newPath += ";" - } - $newPath += $pathToAdd - } - - # Imposta il nuovo PATH per l'utente corrente - [Environment]::SetEnvironmentVariable("PATH", $newPath, "User") - - # Aggiorna il PATH nella sessione corrente - $env:PATH = $newPath - - Write-Host "PATH aggiornato con successo!" - Write-Host "I percorsi Python sono ora disponibili globalmente." - - return $true - } else { - Write-Host "Tutti i percorsi Python sono già nel PATH." - return $true - } - } else { - Write-Host "Impossibile ottenere il percorso di Python $pythonVersion" - return $false - } - } - catch { - Write-Host "Errore durante l'aggiunta di Python al PATH: $($_.Exception.Message)" - return $false - } -} - -# Aggiungi la versione Python principale al PATH -if ($versionToUse -ne "") { - Write-Host "Configurazione PATH per Python $versionToUse..." - $pathResult = Add-PythonToPath -pythonVersion $versionToUse - - if ($pathResult) { - Write-Host "PATH configurato correttamente!" - } else { - Write-Host "Problemi nella configurazione del PATH, continuo comunque..." - } -} - -# Visualizzare il messaggio "Attendere..." per 2 secondi -Write-Host "" -Write-Host "Attendere..." -Start-Sleep -Seconds 2 - -# Ottieni il percorso della cartella in cui è stato eseguito lo script PowerShell -$scriptDir = Get-Location - -# Verifica se il file main.py esiste nella stessa cartella dello script PowerShell -$mainScript = Join-Path $scriptDir "main.py" -Write-Host "Verifica esistenza main.py in: $scriptDir" - -if (Test-Path $mainScript) { - Write-Host "Trovato main.py nella cartella dello script." + # === ESECUZIONE MAIN.PY === + $scriptDir = Get-Location + $mainScript = Join-Path $scriptDir "main.py" - # Usa la versione Python migliore disponibile - $executionVersion = "" - foreach ($preferredVersion in $preferenceOrder) { - if ($preferredVersion -in $finalVersions) { - $executionVersion = $preferredVersion - break - } - } + Write-Host "Verifica main.py in: $scriptDir" - if ($executionVersion -ne "") { - Write-Host "Eseguo main.py con Python $executionVersion..." + if (Test-Path $mainScript) { + Write-Host "Trovato main.py. Eseguendo con Python $versionToUse..." - # Aggiungi anche questa versione al PATH se diversa da quella usata per le dipendenze - if ($executionVersion -ne $versionToUse) { - Write-Host "Configurazione PATH per Python $executionVersion..." - Add-PythonToPath -pythonVersion $executionVersion - } - - # Verifica finale che la versione sia utilizzabile + # Verifica ed esegui try { - $testResult = py -$executionVersion --version 2>$null - if ($testResult -match "Python $executionVersion") { - # Esegui main.py con la versione Python corretta - Write-Host "Avvio di main.py..." - py -$executionVersion $mainScript + if ((py -$versionToUse --version 2>$null) -match "Python $versionToUse") { + py -$versionToUse $mainScript } else { - Write-Host "Versione $executionVersion non verificabile, uso comando generico..." + Write-Host "Fallback a comando generico..." py $mainScript } - } - catch { - Write-Host "Errore nella verifica finale, uso comando generico..." - py $mainScript + } catch { + Write-Host "Tentativo con python..." + python $mainScript } } else { - Write-Host "Nessuna versione Python valida, tentativo con comando generico..." - try { - py $mainScript - } - catch { - Write-Host "Tentativo con 'python'..." - python $mainScript + Write-Host "main.py non trovato in: $scriptDir" + + # Debug: mostra file Python disponibili + $pyFiles = Get-ChildItem -Path $scriptDir -Filter "*.py" -ErrorAction SilentlyContinue + if ($pyFiles) { + Write-Host "File Python disponibili: $($pyFiles.Name -join ', ')" + } else { + Write-Host "Nessun file Python trovato." } } } else { - Write-Host "Il file main.py non è stato trovato nella stessa cartella dello script PowerShell." - Write-Host "Cartella corrente: $scriptDir" - Write-Host "File cercato: $mainScript" - - # Lista i file .py nella cartella per debug - $pyFiles = Get-ChildItem -Path $scriptDir -Filter "*.py" -ErrorAction SilentlyContinue - if ($pyFiles.Count -gt 0) { - Write-Host "File Python trovati nella cartella:" - foreach ($file in $pyFiles) { - Write-Host " - $($file.Name)" - } - } else { - Write-Host "Nessun file Python trovato nella cartella." - } + Write-Host "ERRORE: Nessuna versione Python utilizzabile!" } -Write-Host "" -Write-Host "=== SCRIPT COMPLETATO ===" +Write-Host "`n=== COMPLETATO ===" Write-Host "Premere un tasto per chiudere..." $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") \ No newline at end of file From 9f971667e8b5afdedafa11a3ddb3848f79074f0b Mon Sep 17 00:00:00 2001 From: Magnetar Man <40738529+Magnetarman@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:32:00 +0200 Subject: [PATCH 17/17] `Readme.md` Fix --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 664d0c1..5579e81 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@


- versione - last-commit + versione + last-commit repo-top-language repo-language-count license @@ -227,7 +227,7 @@ Utilizza Python-Script seguendo questi step: - [x] **`V 3.1`**: Refactor 'Readme.md'. Creazione Cartella 'Docs' con la documentazione di ogni script. - [x] **`V 3.1.1`**: Aggiunta Script PDF Combiner in versione Stabile. - [x] **`V 3.1.2`**: il wrapper `main.py` aggiunge automaticamente i nuovi script all'avvio. -- [ ] **`V 3.2`**: Automatizzare il processo di installazione di Python e dipendenze al 100%. +- [x] **`V 3.2`**: Automatizzare il processo di installazione di Python e dipendenze al 100%. - [ ] **`V 4.0`**: unificare il tutto in un unico 'main.py' con aggiunta di Interfaccia grafica. ---