analitics

Pages

Showing posts with label subprocess. Show all posts
Showing posts with label subprocess. Show all posts

Saturday, August 1, 2026

tkinter : tau package on pydroid 3

Today, I test the tau python package with tkinter on pydroid3 on my phone.
/div>
Let's see the source code;
div>
import os
import platform
import subprocess
import sys
import tkinter as tk
from tkinter import ttk

def get_android_prop(prop_name):
    """Citește o proprietate de sistem Android folosind comanda getprop."""
    try:
        val = (
            subprocess.check_output(f"getprop {prop_name}", shell=True, text=True)
            .strip()
        )
        return val if val else "N/A"
    except Exception:
        return "Indisponibil"


def get_system_info():
    """Colectează informații extinse despre telefon și modulul Tau."""
    # 1. Verificare modul Tau
    tau_info = "Neinstalat"
    try:
        import tau

        tau_info = getattr(tau, "__version__", "Instalat (fără __version__)")
    except ImportError:
        tau_info = "Pachetul 'tau-ai' nu este instalat"

    # 2. Preluare date extinse Android
    model = get_android_prop("ro.product.model")
    brand = get_android_prop("ro.product.brand")
    manufacturer = get_android_prop("ro.product.manufacturer")
    android_version = get_android_prop("ro.build.version.release")
    sdk_version = get_android_prop("ro.build.version.sdk")
    device_board = get_android_prop("ro.product.board")
    hardware = get_android_prop("ro.hardware")

    info = {
        "Versiune Tau": tau_info,
        "Producător": f"{manufacturer.capitalize()} ({brand.capitalize()})",
        "Model Telefon": model,
        "Versiune Android": f"Android {android_version} (API {sdk_version})",
        "Placă / Hardware": f"{device_board} / {hardware}",
        "Arhitectură CPU": platform.machine(),
        "Sistem Python": f"{platform.system()} {platform.release()}",
        "Versiune Python": sys.version.split()[0],
    }
    return info


def main():
    root = tk.Tk()
    root.title("Tau & Detalii Android")
    root.geometry("420x560")
    root.configure(bg="#212121")

    title = tk.Label(
        root,
        text="Informații Dispozitiv & Tau",
        font=("Helvetica", 15, "bold"),
        fg="#00E676",
        bg="#212121",
        pady=12,
    )
    title.pack()

    # Zonă de text pentru date
    text_area = tk.Text(
        root,
        font=("Courier", 10),
        bg="#303030",
        fg="#FFFFFF",
        padx=10,
        pady=10,
        relief=tk.FLAT,
    )
    text_area.pack(fill=tk.BOTH, expand=True, padx=15, pady=5)

    # Inserare date în fereastră
    info_data = get_system_info()
    text_content = "=== SPECIFICAȚII TELEFON & APP ===\n\n"
    for key, value in info_data.items():
        text_content += f"• {key}:\n  {value}\n\n"

    text_area.insert(tk.END, text_content)
    text_area.config(state=tk.DISABLED)

    # Buton de închidere
    btn_close = tk.Button(
        root,
        text="Închide",
        font=("Helvetica", 11, "bold"),
        bg="#FF5252",
        fg="white",
        activebackground="#FF1744",
        activeforeground="white",
        command=root.destroy,
        pady=8,
    )
    btn_close.pack(fill=tk.X, padx=15, pady=15)
    root.mainloop()
if __name__ == "__main__":
    main()

Saturday, July 4, 2026

Python Qt : simple uninstall and reinstall all packages.

This Python program creates a small desktop application using PyQt6. Its purpose is to show all Python packages installed in your environment and then uninstall and reinstall them. The interface has a button to load the list of installed packages, a list widget to display them, a button to start the reinstall process, and a progress bar to show how far the process has gone.
When you press Load Installed Packages, the program runs the command pip list --format=freeze and reads all installed packages. It extracts only the package names and displays them in the GUI list.
When you press Uninstall + Reinstall All, the program goes through each package one by one. For every package, it runs pip uninstall -y package to remove it, and then pip install package to install it again. The progress bar updates after each package so you can see the progress.
The important detail is that the program does not use threads. All operations run in the main GUI thread. Because of this, the window may freeze or stop responding while uninstalling and reinstalling packages. This is normal behavior for PyQt6 applications that perform long tasks without threading. Let's see the source code:
import sys
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QPushButton,
    QListWidget, QProgressBar, QMessageBox
)
from PyQt6.QtCore import Qt

def get_installed_packages():
    result = subprocess.run(
        [sys.executable, "-m", "pip", "list", "--format=freeze"],
        capture_output=True, text=True
    )
    lines = result.stdout.strip().split("\n")
    pkgs = [line.split("==")[0] for line in lines if "==" in line]
    return pkgs

def uninstall_package(pkg):
    subprocess.run([sys.executable, "-m", "pip", "uninstall", "-y", pkg])

def install_package(pkg):
    subprocess.run([sys.executable, "-m", "pip", "install", pkg])

class PipReinstaller(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Reinstall All Python Packages")

        layout = QVBoxLayout()

        self.btn_load = QPushButton("Load Installed Packages")
        self.btn_load.clicked.connect(self.load_packages)
        layout.addWidget(self.btn_load)

        self.list = QListWidget()
        layout.addWidget(self.list)

        self.btn_reinstall = QPushButton("Uninstall + Reinstall All")
        self.btn_reinstall.clicked.connect(self.reinstall_all)
        layout.addWidget(self.btn_reinstall)

        self.progress = QProgressBar()
        layout.addWidget(self.progress)

        self.setLayout(layout)

    def load_packages(self):
        self.list.clear()
        pkgs = get_installed_packages()
        for p in pkgs:
            self.list.addItem(p)

    def reinstall_all(self):
        pkgs = [self.list.item(i).text() for i in range(self.list.count())]

        if not pkgs:
            QMessageBox.warning(self, "Warning", "No packages loaded.")
            return

        total = len(pkgs)
        self.progress.setValue(0)

        for idx, pkg in enumerate(pkgs):
            uninstall_package(pkg)
            install_package(pkg)

            percent = int((idx + 1) / total * 100)
            self.progress.setValue(percent)

        QMessageBox.information(self, "Done", "All packages reinstalled.")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = PipReinstaller()
    win.show()
    sys.exit(app.exec())

Tuesday, June 16, 2026

Python Qt : Network intrusion detection tool with alerts and real‑time HTTP attack detection.

This Python script acts as a local security monitor that watches incoming HTTP requests and alerts the user when suspicious activity is detected. It runs a lightweight HTTP server and inspects every GET and POST request for signs of intrusion, such as dangerous protocols (gopher://), command‑execution keywords (bash, powershell, cmd.exe), encoded payloads, or other attack patterns. Before scanning the request, the script verifies that the incoming connection comes from a specific trusted IP and MAC address. This prevents unauthorized devices from interacting with the server. If the IP or MAC does not match the configured values, the request is immediately rejected.
When a malicious pattern is detected, the script logs the event and displays a popup alert window on the user’s desktop. This popup is implemented using PyQt6 and appears as a small, always‑on‑top notification in the corner of the screen. It fades out automatically after a few seconds, ensuring the user is visually warned without relying on Windows system notifications.
The script also includes a tray icon with a menu that allows the user to update the trusted IP and MAC address. All events are written to a log file for later review. Overall, it functions as a simple intrusion‑detection and alerting tool for local network traffic.
This is a groper test on my browser and result was:
Let's see the source code:
import re
import threading
import queue
import subprocess
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
from datetime import datetime
import sys
from urllib.parse import unquote

# FIX pentru Windows 10/11 – AppID
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("Python.SecurityMonitor")

from PyQt6.QtWidgets import (
    QApplication, QSystemTrayIcon, QMenu, QDialog,
    QVBoxLayout, QLabel, QLineEdit, QPushButton, QWidget
)
from PyQt6.QtGui import QIcon
from PyQt6.QtCore import QTimer, Qt, QPropertyAnimation

# ---------------- CONFIG ---------------- #

ALERT_QUEUE = queue.Queue()
LOG_FILE = "security_log.txt"

MONITOR_IP = "192.168.0.136"
MONITOR_MAC = "60:45:cb:c3:4d:02"   # normalizat

RULES = {
    "Gopher protocol": r"gopher://",
    "CRLF injection": r"%0d%0a",
    "WinRM port": r"5985",
    "Base64 payload": r"base64",
    "bash execution": r"bash",
    "powershell execution": r"powershell",
    "cmd execution": r"cmd\.exe",
}

# ---------------------------------------- #

def log_event(text: str):
    ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    line = f"[{ts}] {text}\n"
    with open(LOG_FILE, "a", encoding="utf-8") as f:
        f.write(line)
    print(line, end="")

def get_mac(ip):
    try:
        output = subprocess.check_output(["arp", "-a", ip], text=True)
        for line in output.splitlines():
            if ip in line:
                mac = line.split()[1]
                mac = mac.replace("-", ":").lower()
                return mac
    except:
        return None

# ---------------- POPUP ALERT ---------------- #

class AlertPopup(QWidget):
    def __init__(self, message):
        super().__init__()
        self.setWindowFlags(
            Qt.WindowType.FramelessWindowHint |
            Qt.WindowType.Tool |
            Qt.WindowType.WindowStaysOnTopHint
        )

        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)

        layout = QVBoxLayout()
        label = QLabel(message)
        label.setStyleSheet("""
            background-color: #CC0000;
            color: white;
            padding: 12px;
            border-radius: 8px;
            font-size: 14px;
        """)
        layout.addWidget(label)
        self.setLayout(layout)

        self.resize(350, 80)

        screen = QApplication.primaryScreen().geometry()
        self.move(screen.width() - 380, screen.height() - 150)

        self.show()

        self.anim = QPropertyAnimation(self, b"windowOpacity")
        self.anim.setDuration(6000)
        self.anim.setStartValue(1.0)
        self.anim.setEndValue(0.0)
        self.anim.finished.connect(self.close)
        self.anim.start()

# ---------------- HTTP SERVER ---------------- #

class SecurityHandler(BaseHTTPRequestHandler):

    def _check_ip_mac(self):
        global MONITOR_IP, MONITOR_MAC

        client_ip = self.client_address[0]
        # bypass MAC check dacă este același PC
        if client_ip == MONITOR_IP:
            return True, None

        if client_ip != MONITOR_IP:
            return False, f"IP neautorizat: {client_ip}"

        mac = get_mac(client_ip)
        if mac is None:
            return False, f"MAC necunoscut pentru {client_ip}"

        if mac.lower() != MONITOR_MAC.lower():
            return False, f"MAC neautorizat: {mac} pentru IP {client_ip}"

        return True, None

    def _scan_and_block(self, source: str, data: str):
        data_lower = data.lower()
        for reason, pattern in RULES.items():
            if re.search(pattern, data_lower):
                msg = f"Blocked {source}: {reason} → {data}"
                log_event(msg)
                ALERT_QUEUE.put(msg)

                self.send_response(403)
                self.end_headers()
                self.wfile.write(f"Cerere blocată: {reason}".encode("utf-8"))
                return True
        return False

    def do_GET(self):
        ok, reason = self._check_ip_mac()
        if not ok:
            ALERT_QUEUE.put(reason)
            log_event(reason)
            self.send_response(403)
            self.end_headers()
            self.wfile.write(reason.encode())
            return

        url = unquote(self.path)

        if self._scan_and_block("GET URL", url):
            return

        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Cerere GET permisa")
        log_event(f"Allowed GET: {url}")

    def do_POST(self):
        ok, reason = self._check_ip_mac()
        if not ok:
            ALERT_QUEUE.put(reason)
            log_event(reason)
            self.send_response(403)
            self.end_headers()
            self.wfile.write(reason.encode())
            return

        url = unquote(self.path)

        content_length = int(self.headers.get("Content-Length", 0))
        body = unquote(self.rfile.read(content_length).decode("utf-8", errors="ignore"))

        if self._scan_and_block("POST URL", url):
            return
        if self._scan_and_block("POST body", body):
            return

        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Cerere POST permisa")
        log_event(f"Allowed POST: {url} | body: {body[:200]}")

def run_server():
    server = HTTPServer(("0.0.0.0", 8080), SecurityHandler)
    log_event("Security server running on http://0.0.0.0:8080")
    server.serve_forever()

# ---------------- DIALOG IP & MAC ---------------- #

class IpMacDialog(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Set IP & MAC")

        layout = QVBoxLayout()

        self.ip_label = QLabel("IP Address:")
        self.ip_input = QLineEdit()
        self.ip_input.setText(MONITOR_IP)

        self.mac_label = QLabel("MAC Address:")
        self.mac_input = QLineEdit()
        self.mac_input.setText(MONITOR_MAC)

        self.save_btn = QPushButton("Save")
        self.save_btn.clicked.connect(self.save_values)

        layout.addWidget(self.ip_label)
        layout.addWidget(self.ip_input)
        layout.addWidget(self.mac_label)
        layout.addWidget(self.mac_input)
        layout.addWidget(self.save_btn)

        self.setLayout(layout)

    def save_values(self):
        global MONITOR_IP, MONITOR_MAC
        MONITOR_IP = self.ip_input.text().strip()
        MONITOR_MAC = self.mac_input.text().strip().replace("-", ":").lower()
        log_event(f"Updated IP/MAC → IP={MONITOR_IP}, MAC={MONITOR_MAC}")
        self.hide()

# ---------------- TRAY APP ---------------- #

class TrayApp:
    def __init__(self):
        self.app = QApplication(sys.argv)

        icon = QIcon("icon.svg") if os.path.exists("icon.svg") else QIcon()
        self.tray = QSystemTrayIcon(icon)
        self.tray.setToolTip("Python Security Monitor")

        menu = QMenu()

        set_ip_mac = menu.addAction("Set IP & MAC")
        set_ip_mac.triggered.connect(self.open_ip_mac_dialog)

        exit_action = menu.addAction("Exit")
        exit_action.triggered.connect(self.app.quit)

        self.tray.setContextMenu(menu)
        self.tray.show()

        self.dialog = None

        self.timer = QTimer()
        self.timer.timeout.connect(self.check_alerts)
        self.timer.start(300)

    def open_ip_mac_dialog(self):
        if self.dialog is None:
            self.dialog = IpMacDialog()
        self.dialog.show()
        self.dialog.raise_()
        self.dialog.activateWindow()

    def check_alerts(self):
        while not ALERT_QUEUE.empty():
            msg = ALERT_QUEUE.get()
            AlertPopup(msg)

    def run(self):
        self.app.exec()

# ---------------- MAIN ---------------- #

def main():
    server_thread = threading.Thread(target=run_server, daemon=True)
    server_thread.start()

    tray = TrayApp()
    tray.run()

if __name__ == "__main__":
    main()

Friday, June 12, 2026

Python Qt : Simple script to use wandb and weave.

WandB and Weave work together as complementary tools that enhance the process of evaluating, monitoring, and understanding machine‑learning and large‑language‑model behavior, each focusing on a different layer of the workflow while sharing the same ecosystem. WandB functions primarily as an experiment‑tracking platform that records metrics, logs model outputs, stores configuration details, and organizes results into interactive dashboards, making it easy to compare multiple runs, visualize performance trends, and maintain a structured history of experiments across time. It acts like a scientific notebook that automatically captures everything relevant during evaluation, from scores and prompts to timing information, enabling reproducibility and long‑term analysis. Weave complements this by focusing on the granular tracing of LLM calls, capturing each prompt, response, intermediate step, and metadata associated with model execution, which allows developers to inspect how a model arrived at a particular answer, debug unexpected behavior, and analyze qualitative aspects of model reasoning. While WandB summarizes experiments at a high level, Weave dives deep into the internals of each interaction, providing structured logs that can be searched, filtered, and compared. Together, they create a unified workflow where WandB offers experiment‑level insights and Weave provides call‑level transparency, giving developers a complete picture of model performance, reliability, and behavior across different prompts, models, or configurations, especially useful when benchmarking or refining LLMs.
Let's install these:
python -m pip install wandb weave
Collecting wandb
...
Successfully installed abnf-2.2.0 backoff-2.2.1 chardet-7.4.3 cint-1.0.0 diskcache-weave-5.6.3.post1 fickling-0.1.11
googleapis-common-protos-1.75.0 gql-4.0.0 graphql-core-3.2.11 intervaltree-3.2.1 kaitaistruct-0.11 
opentelemetry-api-1.42.1 opentelemetry-exporter-otlp-proto-common-1.42.1 opentelemetry-exporter-otlp-proto-http-1.42.1
opentelemetry-proto-1.42.1 opentelemetry-sdk-1.42.1 opentelemetry-semantic-conventions-0.63b1 pdfminer.six-20260107
polyfile-weave-0.5.9 protobuf-6.33.6 sentry-sdk-2.62.0 sortedcontainers-2.4.0 wandb-0.27.2 weave-0.52.42
Let's see one exemple with my custom artificial intelligence model and PyQt6.
The PyQt6 script is a small LLM evaluation application that takes two inputs: the Ollama model you select and a fixed set of short test prompts. When you start the evaluation, the script sends each prompt to the chosen model, collects the generated responses, then sends those responses to a smaller judge model to obtain a numerical quality score. All generation uses reduced context and limited output length to keep execution fast on an i3 CPU. As it runs, the script displays each answer in the text panel and updates a progress bar. When all prompts are processed, it compiles the collected scores and displays them as a bar chart in the canvas, giving you a quick visual summary of the model’s performance.
The online tool show this result for this script:

Tuesday, June 9, 2026

Python Qt : Simple script to install the G'MIC archive to the Krita folder.

Today, this simple script will install the G'MIC archive to the Krita folder:
import sys
import os
import zipfile
import shutil
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QWidget, QPushButton, QFileDialog,
    QVBoxLayout, QLabel, QMessageBox
)

class GMICInstaller(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("GMIC Installer for Krita")

        self.gmic_zip = ""
        self.krita_folder = ""

        layout = QVBoxLayout()

        self.label_zip = QLabel("GMIC archive: Not selected")
        self.label_krita = QLabel("Krita folder: Not selected")

        btn_zip = QPushButton("Select GMIC Archive (.zip)")
        btn_zip.clicked.connect(self.select_gmic_zip)

        btn_krita = QPushButton("Select Krita Folder")
        btn_krita.clicked.connect(self.select_krita_folder)

        btn_install = QPushButton("Install on Krita")
        btn_install.clicked.connect(self.install_gmic)

        layout.addWidget(self.label_zip)
        layout.addWidget(btn_zip)
        layout.addWidget(self.label_krita)
        layout.addWidget(btn_krita)
        layout.addWidget(btn_install)

        self.setLayout(layout)

    def select_gmic_zip(self):
        file, _ = QFileDialog.getOpenFileName(self, "Select GMIC ZIP", "", "ZIP Files (*.zip)")
        if file:
            self.gmic_zip = file
            self.label_zip.setText(f"GMIC archive: {file}")

    def select_krita_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "Select Krita Folder")
        if folder:
            self.krita_folder = folder
            self.label_krita.setText(f"Krita folder: {folder}")

    def install_gmic(self):
        if not self.gmic_zip or not self.krita_folder:
            QMessageBox.warning(self, "Error", "Select both GMIC archive and Krita folder first.")
            return

        # Step 1: Extract GMIC ZIP
        extract_path = os.path.join(os.getcwd(), "gmic_extracted")
        if os.path.exists(extract_path):
            shutil.rmtree(extract_path)
        os.makedirs(extract_path)

        with zipfile.ZipFile(self.gmic_zip, 'r') as zip_ref:
            zip_ref.extractall(extract_path)

        # Step 2: Find GMIC folder inside extracted content
        gmic_folder = None
        for root, dirs, files in os.walk(extract_path):
            if "gmic_krita_qt.dll" in files or "gmic_qt.exe" in files:
                gmic_folder = root
                break

        if not gmic_folder:
            QMessageBox.critical(self, "Error", "GMIC plugin files not found in archive.")
            return

        # Step 3: Find Krita plugin folders
        possible_paths = [
            os.path.join(self.krita_folder, "share", "krita", "pykrita"),
            os.path.join(self.krita_folder, "lib", "krita", "plugins"),
            os.path.join(os.getenv("APPDATA"), "krita", "pykrita")
        ]

        installed = False

        for path in possible_paths:
            if os.path.exists(path):
                try:
                    shutil.copytree(gmic_folder, os.path.join(path, "gmic_qt"), dirs_exist_ok=True)
                    installed = True
                except Exception as e:
                    print("Copy error:", e)

        if not installed:
            QMessageBox.critical(self, "Error", "Could not find a valid Krita plugin folder.")
            return

        # Step 4: Launch Krita
        krita_bin = os.path.join(self.krita_folder, "bin", "krita.exe")
        if os.path.exists(krita_bin):
            subprocess.Popen([krita_bin])
        else:
            QMessageBox.warning(self, "Warning", "GMIC installed, but Krita executable not found.")

        QMessageBox.information(self, "Success", "GMIC successfully installed into Krita!")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = GMICInstaller()
    window.show()
    sys.exit(app.exec())

Thursday, May 7, 2026

Python Qt : simple tiktok downloader.

Today, simple example with PyQt6 and yt_dlp.
Get the link from tiktok browser and use it to download the video for your storage.
I used the Copilot tool. It seems to know the Romanian language. For a developer, comments and source code are not an impediment, because it is very simplistic.
Let's see the source code:
import sys
import os
import yt_dlp
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
    QLineEdit, QLabel, QFileDialog, QListWidget, QListWidgetItem,
    QProgressBar, QMessageBox
)
from PyQt6.QtCore import Qt

class TikTokDownloader(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("TikTok Downloader (yt-dlp)")
        self.setMinimumWidth(600)

        self.url_input = QLineEdit()
        self.url_input.setPlaceholderText("Introdu URL TikTok...")

        self.folder_input = QLineEdit()
        self.folder_input.setPlaceholderText("Folder download...")

        browse_btn = QPushButton("Selectează folder")
        browse_btn.clicked.connect(self.select_folder)

        fetch_btn = QPushButton("Caută stream-uri")
        fetch_btn.clicked.connect(self.fetch_streams)

        self.stream_list = QListWidget()

        download_btn = QPushButton("Descarcă")
        download_btn.clicked.connect(self.download_selected)

        self.progress = QProgressBar()
        self.progress.setValue(0)

        layout = QVBoxLayout()
        layout.addWidget(QLabel("URL TikTok:"))
        layout.addWidget(self.url_input)

        folder_layout = QHBoxLayout()
        folder_layout.addWidget(self.folder_input)
        folder_layout.addWidget(browse_btn)
        layout.addLayout(folder_layout)

        layout.addWidget(fetch_btn)
        layout.addWidget(QLabel("Stream-uri găsite:"))
        layout.addWidget(self.stream_list)
        layout.addWidget(download_btn)
        layout.addWidget(self.progress)

        self.setLayout(layout)

        self.streams = []
        self.selected_format = None

    def select_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "Selectează folder")
        if folder:
            self.folder_input.setText(folder)

    def fetch_streams(self):
        url = self.url_input.text().strip()
        if not url:
            QMessageBox.warning(self, "Eroare", "Introdu URL TikTok")
            return

        self.stream_list.clear()
        self.streams = []

        ydl_opts = {
            "quiet": True,
            "skip_download": True,
            "forcejson": True,
        }

        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                info = ydl.extract_info(url, download=False)

            formats = info.get("formats", [])

            for f in formats:
                desc = f"{f.get('format_id')} | {f.get('ext')} | {f.get('resolution', '')} | {f.get('filesize', 'N/A')}"
                item = QListWidgetItem(desc)
                self.stream_list.addItem(item)
                self.streams.append(f)

        except Exception as e:
            QMessageBox.critical(self, "Eroare", str(e))

    def progress_hook(self, d):
        if d["status"] == "downloading":
            if d.get("total_bytes"):
                pct = int(d["downloaded_bytes"] * 100 / d["total_bytes"])
                self.progress.setValue(pct)

        if d["status"] == "finished":
            self.progress.setValue(100)

    def download_selected(self):
        folder = self.folder_input.text().strip()
        if not folder:
            QMessageBox.warning(self, "Eroare", "Selectează folderul de download")
            return

        selected = self.stream_list.currentRow()
        if selected < 0:
            QMessageBox.warning(self, "Eroare", "Selectează un stream din listă")
            return

        fmt = self.streams[selected]
        url = self.url_input.text().strip()

        ydl_opts = {
            "outtmpl": os.path.join(folder, "%(id)s.%(ext)s"),
            "format": fmt["format_id"],
            "progress_hooks": [self.progress_hook],
        }

        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download([url])

            QMessageBox.information(self, "Succes", "Download complet!")

        except Exception as e:
            QMessageBox.critical(self, "Eroare", str(e))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = TikTokDownloader()
    win.show()
    sys.exit(app.exec())

Tuesday, May 5, 2026

Python Qt : python alias manager tool.

This script allow you to add alias commands on each python install.
NOTE : If this script find some python.exe and not works, it means that this python.exe is not a full Python installation, but only a launcher or an embedded runtime that is designed to run inside a virtual environment or a complete Python directory structure.
I used artificial intelligence, tested and works well, lets see the source code:
import sys
import os
import json
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QPushButton,
    QTableWidget, QTableWidgetItem, QFileDialog, QMessageBox
)
from PyQt6.QtCore import Qt

CONFIG_FILE = "python_aliases.json"
ALIAS_DIR = os.path.join(os.environ["LOCALAPPDATA"], "Microsoft", "WindowsApps")

# ------------------------------
# Persistență JSON
# ------------------------------

def load_aliases():
    if os.path.isfile(CONFIG_FILE):
        try:
            with open(CONFIG_FILE, "r") as f:
                return json.load(f)
        except:
            return []
    return []

def save_aliases(data):
    with open(CONFIG_FILE, "w") as f:
        json.dump(data, f, indent=4)


# ------------------------------
# Detectare Python
# ------------------------------

def detect_where_python():
    """Detectează instalările Python folosind 'where python'."""
    found = []
    try:
        out = subprocess.check_output(["where", "python"], stderr=subprocess.STDOUT)
        lines = out.decode().splitlines()
        for line in lines:
            if line.lower().endswith("python.exe"):
                found.append(line.strip())
    except:
        pass
    return found


def search_python_in_folder_recursive(folder):
    """Caută python.exe în folder și în toate subfolderele recursiv."""
    found = []
    for root, dirs, files in os.walk(folder):
        if "python.exe" in files:
            found.append(os.path.join(root, "python.exe"))
    return found

# ------------------------------
# Detectare aliasuri existente
# ------------------------------

def detect_existing_aliases():
    """Caută aliasuri existente (*.cmd) în WindowsApps."""
    aliases = {}
    if not os.path.isdir(ALIAS_DIR):
        return aliases

    for file in os.listdir(ALIAS_DIR):
        if file.endswith(".cmd"):
            alias_name = file[:-4]
            cmd_path = os.path.join(ALIAS_DIR, file)

            try:
                with open(cmd_path, "r") as f:
                    line = f.readline().strip()
                    if line.startswith("@\"") and line.endswith("%*"):
                        python_path = line[2:-3].strip('"')
                        aliases[alias_name] = python_path
            except:
                pass

    return aliases

# ------------------------------
# Creare alias
# ------------------------------

def create_alias(alias_name, python_path):
    """Creează un fișier .cmd în WindowsApps pentru alias."""
    cmd_path = os.path.join(ALIAS_DIR, alias_name + ".cmd")

    try:
        with open(cmd_path, "w") as f:
            f.write(f'@"{python_path}" %*\n')
        return True
    except Exception as e:
        print("Eroare alias:", e)
        return False

# ------------------------------
# Interfață PyQt6
# ------------------------------

class PythonAliasManager(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Python Alias Manager – PyQt6")
        self.resize(800, 550)

        layout = QVBoxLayout(self)

        self.table = QTableWidget(0, 2)
        self.table.setHorizontalHeaderLabels(["Path Python", "Alias (editabil)"])
        self.table.horizontalHeader().setStretchLastSection(True)
        layout.addWidget(self.table)

        btn_detect = QPushButton("Detectează instalări (where python)")
        btn_detect.clicked.connect(self.detect_where)
        layout.addWidget(btn_detect)

        btn_add_folder = QPushButton("Adaugă folder custom (recursiv)")
        btn_add_folder.clicked.connect(self.add_folder)
        layout.addWidget(btn_add_folder)

        btn_search_folder = QPushButton("Caută python.exe recursiv în folder selectat")
        btn_search_folder.clicked.connect(self.search_folder)
        layout.addWidget(btn_search_folder)

        btn_aliases = QPushButton("Afișează aliasuri existente")
        btn_aliases.clicked.connect(self.show_existing_aliases)
        layout.addWidget(btn_aliases)

        btn_apply = QPushButton("Aplică aliasuri în Windows")
        btn_apply.clicked.connect(self.apply_aliases)
        layout.addWidget(btn_apply)

        self.data = load_aliases()
        self.refresh_table()

    # --------------------------
    # Tabel
    # --------------------------

    def refresh_table(self):
        self.table.setRowCount(0)
        for entry in self.data:
            row = self.table.rowCount()
            self.table.insertRow(row)

            self.table.setItem(row, 0, QTableWidgetItem(entry["path"]))

            alias_item = QTableWidgetItem(entry["alias"])
            alias_item.setFlags(alias_item.flags() | Qt.ItemFlag.ItemIsEditable)
            self.table.setItem(row, 1, alias_item)

    # --------------------------
    # Detectare instalări
    # --------------------------

    def detect_where(self):
        paths = detect_where_python()
        for p in paths:
            self.add_entry(p)
        self.refresh_table()
        save_aliases(self.data)

    def add_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "Selectează folder Python")
        if folder:
            paths = search_python_in_folder_recursive(folder)
            for p in paths:
                self.add_entry(p)
            self.refresh_table()
            save_aliases(self.data)

    def search_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "Selectează folder pentru scanare")
        if folder:
            paths = search_python_in_folder_recursive(folder)
            for p in paths:
                self.add_entry(p)
            self.refresh_table()
            save_aliases(self.data)

    # --------------------------
    # Aliasuri existente
    # --------------------------

    def show_existing_aliases(self):
        aliases = detect_existing_aliases()
        if not aliases:
            QMessageBox.information(self, "Aliasuri", "Nu există aliasuri în WindowsApps.")
            return

        msg = "\n".join([f"{a} → {p}" for a, p in aliases.items()])
        QMessageBox.information(self, "Aliasuri existente", msg)

    # --------------------------
    # Adăugare în listă
    # --------------------------

    def add_entry(self, path):
        if not any(e["path"] == path for e in self.data):
            alias = "python_" + os.path.basename(os.path.dirname(path)).replace(".", "_")
            self.data.append({"path": path, "alias": alias})

    # --------------------------
    # Aplicare aliasuri
    # --------------------------

    def apply_aliases(self):
        # actualizează aliasurile din tabel
        for row in range(self.table.rowCount()):
            self.data[row]["path"] = self.table.item(row, 0).text()
            self.data[row]["alias"] = self.table.item(row, 1).text()

        save_aliases(self.data)

        ok = 0
        for entry in self.data:
            if create_alias(entry["alias"], entry["path"]):
                ok += 1

        QMessageBox.information(
            self,
            "Aliasuri aplicate",
            f"Aliasuri create: {ok}\nAcum poți folosi comenzile în CMD/PowerShell."
        )

# ------------------------------
# Main
# ------------------------------

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = PythonAliasManager()
    win.show()
    sys.exit(app.exec())

Saturday, February 28, 2026

Python 3.13.0 : simple script for update all python packages.

Simple script for update all python packages:
import subprocess
import sys
import datetime

log_file = "upgrade_log.txt"

def log(msg):
    with open(log_file, "a", encoding="utf-8") as f:
        f.write(msg + "\n")
    print(msg)

def get_installed_packages():
    result = subprocess.run(
        [sys.executable, "-m", "pip", "list", "--format=freeze"],
        capture_output=True,
        text=True
    )
    lines = result.stdout.strip().split("\n")
    packages = []
    for line in lines:
        if "@" in line:  # skip direct URL installs
            pkg = line.split("@")[0]
        else:
            pkg = line.split("==")[0]
        packages.append(pkg)
    return sorted(packages)

def upgrade_package(package):
    log(f"\n=== Updating: {package} ===")
    try:
        subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", package])
        log(f"[OK] Updated: {package}")
    except subprocess.CalledProcessError:
        log(f"[FAILED] Could not update: {package}")

def main():
    log(f"\n--- Upgrade started at {datetime.datetime.now()} ---\n")

    packages = get_installed_packages()
    log(f"Found {len(packages)} packages.\n")

    for pkg in packages:
        upgrade_package(pkg)

    log(f"\n--- Upgrade finished at {datetime.datetime.now()} ---\n")

if __name__ == "__main__":
    main()

Wednesday, January 28, 2026

Python 3.13.0 : Motion extraction from video with python programming.

... based on this video - Motion Extraction with python source code.
  • 1. Temporal Displacement
    Let V(t) represent the video frame at the current time t.
    A secondary reference frame is generated at time t + Δt, where Δt is the defined time delay (shift).
  • 2. Absolute Difference Calculation
    For every pixel coordinate (x, y), the algorithm calculates the absolute difference between the two points in time:
    D(x,y) = | V(x,y,t) - V(x,y,t + Δt) |
  • 3. Result Interpretation
    • Static Areas: If the pixel value remains constant, the result is 0 (Black).
    • Motion: If the pixel value changes, the result is a positive integer > 0 (the "ghosting" trail).
  • 4. Signal Amplification (Contrast)
    The raw difference values are multiplied by a constant factor k to make faint motion visible:
    Output(x,y) = D(x,y) × k

Thursday, January 1, 2026

Python Qt6 : QCalendarWidget simple example with csv file.

Here is a simple example of source code with PyQt6 and QCalendarWidget to create a calendar. You click on the date and enter a note. This is saved in a file with the date time ... and the note. When you reopen the script, it opens in notepad and the saved notes. Obviously it is a simple example but you can improve it with databases, make a note management, encrypt it, link it to an external database, etc.
import sys
import csv
import os
import subprocess
from datetime import datetime
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QCalendarWidget,
    QInputDialog, QMessageBox
)
from PyQt6.QtCore import QDate


CSV_FILE = "note.csv"


class CalendarApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Calendar cu notițe")
        self.resize(400, 300)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.calendar = QCalendarWidget()
        self.calendar.clicked.connect(self.adauga_nota)
        self.layout.addWidget(self.calendar)

        # Dicționar pentru notițe
        self.note = {}

        # La pornire, citește CSV și deschide în Notepad
        self.incarca_note()

    def adauga_nota(self, date: QDate):
        zi = date.toString("yyyy-MM-dd")

        text, ok = QInputDialog.getText(self, "Adaugă notiță",
                                        f"Introdu text pentru {zi}:")
        if ok and text.strip():
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
            self.note[timestamp] = text.strip()
            QMessageBox.information(self, "Salvat",
                                    "Notița a fost adăugată.")

    def incarca_note(self):
        if os.path.exists(CSV_FILE):
            try:
                with open(CSV_FILE, "r", newline="", encoding="utf-8") as f:
                    reader = csv.reader(f)
                    for row in reader:
                        if len(row) == 2:
                            self.note[row[0]] = row[1]

                # Deschide în Notepad
                subprocess.Popen(["notepad.exe", CSV_FILE])

            except Exception as e:
                QMessageBox.warning(self, "Eroare",
                                    f"Nu pot citi fișierul CSV:\n{e}")

    def closeEvent(self, event):
        try:
            with open(CSV_FILE, "w", newline="", encoding="utf-8") as f:
                writer = csv.writer(f)
                for timestamp, text in self.note.items():
                    writer.writerow([timestamp, text])
        except Exception as e:
            QMessageBox.warning(self, "Eroare",
                                f"Nu pot salva fișierul CSV:\n{e}")

        event.accept()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = CalendarApp()
    window.show()
    sys.exit(app.exec())
... this is the result:

Wednesday, December 17, 2025

Python Qt6 : Run Visual Studio Code directly from RAM using ImDisk and python.

I built a small tool using Python + PyQt6 that lets me run Visual Studio Code directly from a RAM Disk for maximum speed and minimal SSD wear.
The setup uses ImDisk Toolkit to automatically create a 6 GB RAM Disk (drive O:).
The tool then copies VS Code into RAM and launches it instantly through a simple graphical interface with three buttons:
  • Create RAM Disk
  • Copy VS Code to RAM
  • Launch VS Code from RAM
This method provides much faster startup times and a smoother workflow, making it a great performance boost for Windows users.

Saturday, December 13, 2025

Python Qt6 : ... search custom data in files with python and PyQt6.

The other day I noticed that I can't find what I worked on in the past, some files were blocked... Another task was blocking the artificial intelligence due to the number of uses. I could have used artificial intelligence to open old projects and ask where what I worked on is, but it would be a risk to waste my queries. Since I always use a specific signature when working on separate projects and the backup is distributed on storage that is always filling up, I created a simple script that would search for my custom with custom files, custom content and output a spreader with them. Here is the result of a 310-line source code script, obviously created with artificial intelligence.

Monday, September 8, 2025

Python 3.13.0 : Script for python modules then installs them - updated with fix.

This script scans a folder full of .py files Python scripts, identifies all the external modules they import, filters out built-in ones, writes the installable ones to a requirements.txt file, and then installs them using pip—in parallel threads for speed.
I use the copilot and some comments are into my language, but I tested and works well:
NOTE: I updated with detection python modules based "from" and another issue: check if python module is instaled and step over that python module ...
This script will try to install many python modules, I can update to be better with these issues:
...some modules are default , some scripts are from another area, see Blender 3D with bpy python modules, some packages comes with same modules, this can be soleved with defined lists with unique items.
import subprocess
import sys
import os
import shutil
import importlib.util
import re
import concurrent.futures
from typing import List, Tuple, Set

class ModuleManager:
    def __init__(self):
        self.modules: Set[str] = set()
        self.pip_path = self._get_pip_path()

    def _get_pip_path(self) -> str:
        possible_path = os.path.join(sys.exec_prefix, "Scripts", "pip.exe")
        return shutil.which("pip") or (possible_path if os.path.exists(possible_path) else None)

    def extract_imports_from_file(self, file_path: str) -> List[Tuple[str, str]]:
        imports = []
        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                for line in file:
                    # Detect 'import module'
                    import_match = re.match(r'^\s*import\s+([a-zA-Z0-9_]+)(\s+as\s+.*)?$', line)
                    if import_match:
                        module = import_match.group(1)
                        imports.append((module, line.strip()))
                        continue
                    
                    # Detect 'from module import ...'
                    from_match = re.match(r'^\s*from\s+([a-zA-Z0-9_]+)\s+import\s+.*$', line)
                    if from_match:
                        module = from_match.group(1)
                        imports.append((module, line.strip()))
        except FileNotFoundError:
            print(f"❌ Fișierul {file_path} nu a fost găsit.")
        except Exception as e:
            print(f"❌ Eroare la citirea fișierului {file_path}: {e}")
        return imports

    def scan_directory_for_py_files(self, directory: str = '.') -> List[str]:
        py_files = []
        for root, _, files in os.walk(directory):
            for file in files:
                if file.endswith('.py'):
                    py_files.append(os.path.join(root, file))
        return py_files

    def collect_unique_modules(self, directory: str = '.') -> None:
        py_files = self.scan_directory_for_py_files(directory)
        all_imports = []
        with concurrent.futures.ThreadPoolExecutor() as executor:
            future_to_file = {executor.submit(self.extract_imports_from_file, file_path): file_path for file_path in py_files}
            for future in concurrent.futures.as_completed(future_to_file):
                imports = future.result()
                all_imports.extend(imports)
        
        for module, _ in all_imports:
            self.modules.add(module)

    def is_module_installed(self, module: str) -> bool:
        return importlib.util.find_spec(module) is not None

    def run_pip_install(self, module: str) -> bool:
        if not self.pip_path:
            print(f"❌ Nu am găsit pip pentru {module}.")
            return False
        try:
            subprocess.check_call([self.pip_path, "install", module])
            print(f"✅ Pachetul {module} a fost instalat cu succes.")
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ Eroare la instalarea pachetului {module}: {e}")
            return False

    def check_and_install_modules(self) -> None:
        def process_module(module):
            print(f"\n🔎 Verific dacă {module} este instalat...")
            if self.is_module_installed(module):
                print(f"✅ {module} este deja instalat.")
            else:
                print(f"📦 Instalez {module}...")
                self.run_pip_install(module)
                # Re-verifică după instalare
                if self.is_module_installed(module):
                    print(f"✅ {module} funcționează acum.")
                else:
                    print(f"❌ {module} nu funcționează după instalare.")

        with concurrent.futures.ThreadPoolExecutor() as executor:
            executor.map(process_module, self.modules)

def main():
    print("🔍 Verific pip...")
    manager = ModuleManager()
    if manager.pip_path:
        print(f"✅ Pip este disponibil la: {manager.pip_path}")
    else:
        print("⚠️ Pip nu este disponibil.")
        return

    directory = sys.argv[1] if len(sys.argv) > 1 else '.'
    print(f"\n📜 Scanez directorul {directory} pentru fișiere .py...")
    manager.collect_unique_modules(directory)
    
    if not manager.modules:
        print("⚠️ Nu s-au găsit module în importuri.")
        return
    
    print(f"\nModule unice detectate: {', '.join(manager.modules)}")
    manager.check_and_install_modules()

if __name__ == "__main__":
    main()

Saturday, August 30, 2025

Python Qt6 : ... management of installations and build python package.

Yesterday I created a small project for managing Python packages and building a new package based on added modules. I only tested the local installations of various Python versions and the creation of a new package, but it worked.
python catafest_build_package_001.py
🔍 Verificare module standard...
[✓] Modul standard 'json' este disponibil.
[✓] Modul standard 'subprocess' este disponibil.
[✓] Modul standard 'platform' este disponibil.
[✓] Modul standard 'datetime' este disponibil.
[✓] Modul standard 'os' este disponibil.
[✓] Modul standard 'sys' este disponibil.

📦 Verificare și instalare module pip...
[✓] Modulul 'PyQt6' este deja instalat.
[✓] Modulul 'build' este deja instalat.
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - setuptools
  - wheel
...

Thursday, August 21, 2025

Python Qt6 : Use python with ffmpeg tool ...

If you download a video from youtube with high resolution using a tool as yt-dlp then you can get two files with video and audio content:
... one with be with .f401.mp4 and another with .f251-9.webm and using the ffmpeg tool you can create one .mp4 file with both audio and video content.
Let's see a source code with python and PyQt6 module to search into D:\Software folder and create the mp4 file.

import os
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QPushButton,
    QListWidget, QMessageBox
)
# fisier download : yt-dlp.exe -vU https://www.youtube.com/watch?v=xxxxxx -f bestvideo*+bestaudio/best
FOLDER_PATH = r"D:\Software"

class FFmpegMerger(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Combinare Video + Audio cu FFmpeg")
        self.resize(600, 400)

        self.layout = QVBoxLayout()
        self.file_list = QListWidget()
        self.process_button = QPushButton("Prelucrează în MP4")

        self.layout.addWidget(self.file_list)
        self.layout.addWidget(self.process_button)
        self.setLayout(self.layout)

        self.process_button.clicked.connect(self.process_files)

        self.populate_file_list()

    def populate_file_list(self):
        files = os.listdir(FOLDER_PATH)
        video_files = [f for f in files if f.endswith(".f401.mp4")]
        audio_files = [f for f in files if f.endswith(".f251-9.webm")]

        base_names = set(f.split(".f401.mp4")[0] for f in video_files)
        candidates = []

        for base in base_names:
            audio_name = f"{base}.f251-9.webm"
            output_name = f"{base}.mp4"
            if audio_name in audio_files and output_name not in files:
                candidates.append(base)

        for name in candidates:
            self.file_list.addItem(name)

    def process_files(self):
        for i in range(self.file_list.count()):
            base = self.file_list.item(i).text()
            video_path = os.path.join(FOLDER_PATH, f"{base}.f401.mp4")
            audio_path = os.path.join(FOLDER_PATH, f"{base}.f251-9.webm")
            output_path = os.path.join(FOLDER_PATH, f"{base}.mp4")

            cmd = [
                "ffmpeg",
                "-i", video_path,
                "-i", audio_path,
                "-c:v", "copy",
                "-c:a", "aac",
                "-strict", "experimental",
                output_path
            ]

            try:
                subprocess.run(cmd, check=True)
            except subprocess.CalledProcessError as e:
                QMessageBox.critical(self, "Eroare", f"Eroare la procesarea {base}: {e}")
                return

        QMessageBox.information(self, "Succes", "Toate fișierele au fost prelucrate cu succes!")

if __name__ == "__main__":
    app = QApplication([])
    window = FFmpegMerger()
    window.show()
    app.exec()

Saturday, March 15, 2025

Python Qt6 : Dependency checker for python packages with pipdeptree and PyQt6.

Today I created this python script to test and check python package dependency.
You need to install the pipdeptree with the pip tool.
I used the Python 3.13.0rc1 version and the result is this:
This is the source code I used:
import sys
import subprocess
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QVBoxLayout, QTreeWidget, QTreeWidgetItem, QWidget
)
from PyQt6.QtWidgets import QHeaderView
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QStyle


class DependencyViewer(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Dependency Checker")

        # Maximizarea ferestrei la lansare
        self.showMaximized()

        # Creează un QTreeWidget pentru afișarea dependențelor
        self.tree_widget = QTreeWidget()
        self.tree_widget.setHeaderLabels(["Dependency", "Status"])

        # Ajustează aliniamentul central pentru fiecare coloană
        for i in range(2):  # Pentru cele două coloane
            self.tree_widget.headerItem().setTextAlignment(i, Qt.AlignmentFlag.AlignCenter)

        # Configurarea automată a lățimii coloanelor
        self.tree_widget.header().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(self.tree_widget)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

        # Obține și afișează dependențele
        self.display_dependencies()

    def display_dependencies(self):
        try:
            # Rulează pipdeptree pentru a obține ierarhia dependențelor
            result = subprocess.run(['pipdeptree', '--warn', 'silence'], capture_output=True, text=True)
            dependencies = result.stdout.splitlines()

            for line in dependencies:
                # Determină nivelul de indentare pentru ierarhia dependențelor
                indent_level = len(line) - len(line.lstrip())
                dependency_name = line.strip()

                # Creează un item pentru fiecare dependență
                item = QTreeWidgetItem([dependency_name])

                # Atribuie iconițe pe baza compatibilității (exemplu simplificat)
                if "(*)" in dependency_name:  # Exemplu de incompatibilitate (poți schimba după caz)
                    item.setIcon(0, self.style().standardIcon(QStyle.StandardPixmap.SP_DialogCancelButton))
                    item.setText(1, "Incompatible")
                else:
                    item.setIcon(0, self.style().standardIcon(QStyle.StandardPixmap.SP_DialogApplyButton))
                    item.setText(1, "Compatible")

                # Adaugă item-ul în arbore
                if indent_level == 0:
                    self.tree_widget.addTopLevelItem(item)
                else:
                    # Alege ultimul item părinte și adaugă dependența ca sub-item
                    parent_item = self.tree_widget.topLevelItem(self.tree_widget.topLevelItemCount() - 1)
                    parent_item.addChild(item)

            # Extinde toate elementele din arbore
            self.tree_widget.expandAll()

        except Exception as e:
            error_item = QTreeWidgetItem(["Error", str(e)])
            error_item.setIcon(0, self.style().standardIcon(QStyle.StandardPixmap.SP_MessageBoxCritical))
            self.tree_widget.addTopLevelItem(error_item)


if __name__ == "__main__":
    from PyQt6.QtCore import Qt

    app = QApplication(sys.argv)
    viewer = DependencyViewer()
    viewer.show()
    sys.exit(app.exec())

Sunday, September 22, 2024

Python 3.13.0rc1 : ... pkg_resources is deprecated as an API .

I tried an old version of python script for upgrade all my ython packages on windows 10 with pkg_resources python package.
I got this error:
DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
... and this python script will upgrade all python packages
import subprocess

try:
    # Obține lista pachetelor învechite
    outdated_packages = subprocess.check_output(["pip", "list", "--outdated", "--format=columns"]).decode("utf-8")
    packages = [line.split()[0] for line in outdated_packages.splitlines()[2:]]
    
    if not packages:
        print("Toate pachetele sunt deja actualizate.")
    else:
        print("Pachete Python învechite: ", packages)
        
        # Actualizează fiecare pachet
        for package in packages:
            print("Actualizează pachetul: ", package)
            subprocess.check_call(["pip", "install", "--upgrade", package])
except subprocess.CalledProcessError as e:
    print("A apărut o eroare la rularea comenzii pip:", e)
except Exception as e:
    print("A apărut o eroare neașteptată:", e)

Saturday, April 20, 2024

Python 3.12.1 : Using the subprocess python module - part 001.

The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions:
See the official webpage for Python verison 3.12.3 same like version 3.12.1 I used.
Let's see two examples with this python module:
First script will get output of net users command and will parse all into a list:
import subprocess

def find_users():
    try:
        result = subprocess.run(["net", "users"], capture_output=True, text=True)
        users = result.stdout.splitlines()      
        # define list content         
        user_list = []
        for line in users[4:-2]:  # inser only some rows 
            #print(line) #only users        
            user = line.split()
            user_list += user
        # print the right result
        print(user_list)
    except Exception as e:
        print(f"Error : {str(e)}")

# run find_users
find_users()
The result is this:
python test_001.py
['Administrator', 'catafest', 'DefaultAccount', 'Guest', 'WDAGUtilityAccount']
This source code will show data from tasklist and will print result of this ... :
import subprocess

def find_processes():
    try:
        result = subprocess.run(['tasklist', '/v'], capture_output=True, text=True)
        output_lines = result.stdout.splitlines()

        for line in output_lines[3:]:
            columns = line.split()
            #print(columns)
            #if len(columns) >= 8 and columns[9] == 'N/A':
            if len(columns) >= 8 and columns[0] == 'tasklist.exe':
                print(line)
    except Exception as e:
        print(f"A apărut o eroare la găsirea proceselor suspendate: {str(e)}")

find_processes()
The result will be like this:
python test_pid_003.py
tasklist.exe 8348 Console 1 10,304 K Unknown DESKTOP-mycomputer 0:00:00 N/A

Monday, October 7, 2019

Python 3.7.4 : Example with subprocess - part 001.

This is a simple example with the python 3 subprocess package.
The source code is simple to understand.
The execute_proceess_with_communicate let run the ls command with the sudo user permissions:
import os
import sys
import string
import subprocess
import codecs

inp = ''
cmd = 'ls'
password = ''

def execute_proceess_with_communicate(inp):
    """Return a list of hops from traceroute command."""
    p = subprocess.Popen(
            ['sudo', cmd, inp],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            shell=False)
    text, _ = p.communicate(password)
    #print(type(text))
    outp = codecs.decode(text,'utf8')
    out_split=outp.split('\n')
    return out_split

def normalize_out(list_outp):
    """Extract information from traceroute line per line."""

    normalized_out = []
    for op in list_outp:
        # filer out if an empty line
        if len(op) is 0:
            continue
        op_split = op.split()
        normalized_out.append(op_split)
    return normalized_out

if __name__ == '__main__':
    inp = sys.argv[1]

    out = execute_proceess_with_communicate(inp)
    n_out = normalize_out(out)
    print(n_out)
The result is this:
[mythcat@desk scripts]$ python3 subprocess_001.py '/' 
[['bin'], ['boot'], ['dev'], ['etc'], ['home'], ['lib'], ['lib64'], ['media'], ['mnt'], ['opt'], ['proc'],
 ['root'], ['run'], ['sbin'], ['srv'], ['sys'], ['tmp'], ['usr'], ['var']]

Friday, September 1, 2017

The beauty of Python: subprocess module - part 004 .

This series of python tutorials that we started at the beginning of this blog and called "The beauty of Python" is part of the series of tutorials aimed at the simplicity and beauty of the Python programming language.
The main goal for us is how to use this programming language in everyday life with different tasks.
Today I will come up with examples to cover this goal and show you how to use the subprocess python module.
  • using the PowerShell with python :
  • >>> import subprocess
    >>> process=subprocess.Popen(["powershell","Get-Childitem C:\\Windows\\*.log"],stdout=subprocess.PIPE);
    >>> result=process.communicate()[0]
    >>> print result
  • get and print the hostname :
  • >>> print subprocess.check_output("hostname")
  • print the output of ping command :
  • >>> print subprocess.check_output("ping localhost", shell=True)
  • print the output of dir command :
  • >>> cmd = 'dir *'
    >>> supcmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    >>> print supcmd.communicate()[0]
    
  • run the python script like python shell :
  • >>> import sys
    >>> import subprocess
    >>> pid = subprocess.Popen([sys.executable, "calc.py"])