analitics

Pages

Showing posts with label tutorial. Show all posts
Showing posts with label tutorial. Show all posts

Monday, September 21, 2026

tkinter : simple marshmallow demo.

About the marshmallow package
  • It checks if your data has the correct fields.
  • It verifies that each field has the right type.
  • It helps you validate JSON before using it.
  • It can convert Python data into clean JSON.
About your this source code:
  • It loads the marshmallow package when the app starts.
  • It reads the JSON you type in the input box.
  • It tries to convert that text into Python data.
  • It validates the data using your marshmallow schema.
  • It shows the result or the error directly in the output box.
  • It does not use print or message boxes.
Why this tool is useful
  • You can test JSON visually.
  • You can see validation errors instantly.
  • You avoid console output.
  • You keep everything inside the GUI.
Let's see the sourve code:
import json
import tkinter as tk
from tkinter import ttk

# ------------------ Package Load Test ------------------

try:
    from marshmallow import Schema, fields, ValidationError
    package_status = "Package marshmallow loaded successfully."
except Exception as e:
    package_status = "PACKAGE LOAD ERROR: " + str(e)


# ------------------ Marshmallow Schema ------------------

class PersonSchema(Schema):
    full_name = fields.Str(required=True)
    city = fields.Str(required=True)
    birth_date = fields.Date(required=True)
    nicknames = fields.List(fields.Str(), required=True)


schema = PersonSchema()


# ------------------ Tkinter UI ------------------

def process_json():
    raw = editor.get("1.0", tk.END).strip()

    output.delete("1.0", tk.END)

    # Step 1: package status
    output.insert(tk.END, package_status + "\n\n")

    # Step 2: show raw JSON
    output.insert(tk.END, "RAW JSON RECEIVED:\n" + raw + "\n\n")

    # Step 3: JSON parsing
    try:
        data = json.loads(raw)
        output.insert(tk.END, "JSON PARSED OK.\n\n")
    except Exception as e:
        output.insert(tk.END, "JSON ERROR:\n" + str(e))
        return

    # Step 4: Marshmallow validation
    try:
        result = schema.dump(data)
        output.insert(tk.END, "SCHEMA VALIDATION OK.\n\n")
    except ValidationError as e:
        output.insert(tk.END, "SCHEMA ERROR:\n" + json.dumps(e.messages, indent=2))
        return

    # Step 5: Final result
    output.insert(tk.END, "FINAL RESULT:\n" + json.dumps(result, indent=2))


root = tk.Tk()
root.title("Marshmallow Diagnostic Full Output")
root.geometry("750x550")

frm = ttk.Frame(root, padding=10)
frm.pack(fill="both", expand=True)

ttk.Label(frm, text="JSON Input:").pack(anchor="w")

editor = tk.Text(frm, height=14, width=90)
editor.pack(fill="x")

editor.insert(
    tk.END,
    json.dumps(
        {
            "full_name": "Catalin George Festila",
            "city": "Falticeni",
            "birth_date": "1976-03-07",
            "nicknames": ["catafest", "mythcat"]
        },
        indent=2
    )
)

ttk.Button(frm, text="Run", command=process_json).pack(pady=10)

ttk.Label(frm, text="Output:").pack(anchor="w")

output = tk.Text(frm, height=14, width=90)
output.pack(fill="both", expand=True)

root.mainloop()

Saturday, September 12, 2026

News : Real-Time Stock & ETF Analyzer in using tvscreener and Tkinter and pydroid3.

The tvscreener is a lightweight Python library designed to extract and analyze real-time financial data directly from TradingView's API without requiring paid API keys or complex authentication. It provides quick access to technical indicators, fundamental metrics, historical performance, and volume data for international stocks and ETFs. Explore the source code and documentation on the official tvscreener GitHub repository. The script provides a desktop interface (Tkinter GUI) powered by tvscreener logic to query market data on demand. This allow to choose a ticker symbol from the dropdown list (such as GOOGL, NVDA, AAPL, or ETFs like VUAA). Clicking Check triggers a background HTTP request without freezing the user interface, while displaying real-time progress via the progress bar. The script formats the API response into four core metric categories: Performance, Technical Indicators, Fundamentals, and Volume and Liquidity. Clicking Copy transfers the complete output directly to your system clipboard for quick sharing or note-taking.

Tuesday, August 25, 2026

tkinter : three algorithms for yahoo market with pydroid 3.

The script retrieves historical closing-price data for NVDA and VUAA.AS directly from Yahoo Finance.
First tab displays a candlestick chart for the selected time range. Two Simple Moving Averages are calculated automatically; their periods adapt to the chosen interval (for example SMA 5/10 on short ranges and SMA 50/200 on longer ones) and are shown in the legend. Clear dates appear on the horizontal axis.
Its second tab, ML Predictions, focuses on statistical modelling. The downloaded series is fitted with three algorithms: ordinary linear regression, polynomial regression (degree adjustable by the user), and a Random Forest regressor. All four lines—the original prices plus the three model outputs—are plotted on a single chart. Clear calendar dates appear on the horizontal axis, and an enlarged legend identifies each curve. Loading feedback is shown while data are fetched. The tab therefore converts raw Yahoo price history into immediate visual comparisons of linear, non-linear and ensemble trend estimates.

Monday, August 24, 2026

tkinter : python manager with pydroid 3.

The script is a lightweight package manager for Pydroid 3, built with Tkinter, designed to help you inspect, back up, and restore your Python environment on Android. It reads all installed packages using importlib.metadata, which works reliably in Pydroid 3, and displays them in a scrollable text area. A Check button scans the environment and lists every package with its version, while a Copy button places that list into the clipboard for quick sharing or documentation. The Save function opens a dialog and writes all detected packages into a Requirements.txt file, typically stored in the Download folder, allowing you to preserve the exact state of your environment. The Load function opens a file dialog, reads a requirements file, compares each entry with the currently installed packages, and installs only the missing or outdated ones using pip. Every operation updates a progress bar so you can see how many items have been processed. Overall, the script acts as a practical tool for backing up, restoring, and synchronizing Python packages on Pydroid 3, where traditional virtual environments and desktop-style package managers are not available.

Sunday, August 16, 2026

tkinter : test colorchooser script on pydroid 3.

Learn how to use the Python Tkinter colorchooser module to create interactive graphical interfaces. This simple script opens a native color picker dialog and instantly updates your application interface based on user selection.
How the Python script functions:
The colorchooser module is imported to launch the native system palette window.
The askcolor function runs when triggered and waits for user input.
The script extracts the returned HEX color code from the selection.
The main window background and label text update immediately with the chosen color.
This lightweight code provides a simple way to add dynamic customization to desktop applications without installing external libraries.
Let's see the source code:
import tkinter as tk
from tkinter import colorchooser

def choose_color():
    # Opens the color picker dialog and returns a tuple: ((R, G, B), "#HEX")
    color = colorchooser.askcolor(title="Choose a Background Color")
    
    # Check if the user selected a color (didn't click Cancel)
    if color[1]: 
        hex_code = color[1]
        root.config(bg=hex_code)
        label_color.config(text=f"HEX Code: {hex_code}", bg=hex_code)

# Create the main window
root = tk.Tk()
root.title("Tkinter Colorchooser Example")
root.geometry("300x200")

# Button to trigger the color chooser dialog
btn_choose = tk.Button(root, text="Select Color", command=choose_color)
btn_choose.pack(pady=30)

# Label to display the chosen HEX code
label_color = tk.Label(root, text="No color selected", font=("Arial", 12))
label_color.pack(pady=10)

root.mainloop()

Thursday, August 13, 2026

tkinter : simple tool for converting source code for blogger.

This tool helps you safely prepare source code for publishing on Blogger. You paste your code, press the convert button, and the app instantly transforms it into a format that displays correctly without being interpreted or altered by the platform. It keeps your code clean, readable, and protected. After conversion, you can copy the final result and insert it directly into your blog. It’s a fast and reliable solution for developers who want to share code snippets online.
import html
import tkinter as tk
from tkinter import ttk, messagebox

def paste_from_clipboard():
    try:
        text_input.insert(tk.INSERT, root.clipboard_get())
    except Exception:
        try:
            text_input.focus_set()
            text_input.event_generate("<<Paste>>")
        except Exception:
            pass

def process_code():
    raw_code = text_input.get("1.0", tk.END).strip()
    if not raw_code:
        return

    try:
        # 1. Escapam caracterele speciale HTML (<, >, &, ")
        escaped_code = html.escape(raw_code)

        # 2. Includem codul convertit in structura div -> pre -> code
        formatted_result = f"<div><pre><code>{escaped_code}</code></pre></div>"

        # 3. Afisam rezultatul
        text_output.config(state=tk.NORMAL)
        text_output.delete("1.0", tk.END)
        text_output.insert(tk.END, formatted_result)
        text_output.config(state=tk.DISABLED)
    except Exception as e:
        messagebox.showerror("Eroare", f"A aparut o eroare la conversie: {e}")

def copy_to_clipboard():
    cleaned_text = text_output.get("1.0", tk.END).strip()
    if cleaned_text:
        try:
            root.clipboard_clear()
            root.clipboard_append(cleaned_text)
            messagebox.showinfo("OK", "Copiat in clipboard!")
        except Exception as e:
            messagebox.showerror("Eroare", f"Nu s-a putut copia: {e}")

def clear_all():
    text_input.delete("1.0", tk.END)
    text_output.config(state=tk.NORMAL)
    text_output.delete("1.0", tk.END)
    text_output.config(state=tk.DISABLED)

# Constructie Interfata
root = tk.Tk()
root.title("Code Escaper for Blogger")
root.geometry("400x600")

# Input
lbl1 = ttk.Label(root, text="1. Cod Sursa de Convertit:")
lbl1.pack(anchor="w", padx=10, pady=(10, 0))

frame_btns = ttk.Frame(root)
frame_btns.pack(fill=tk.X, padx=10, pady=5)

btn_paste = ttk.Button(frame_btns, text="Lipeste (Paste)", command=paste_from_clipboard)
btn_paste.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))

btn_clear = ttk.Button(frame_btns, text="Sterge", command=clear_all)
btn_clear.pack(side=tk.RIGHT)

text_input = tk.Text(root, height=8)
text_input.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

# Procesare
btn_process = ttk.Button(root, text="Converteste pentru Blogger", command=process_code)
btn_process.pack(fill=tk.X, padx=10, pady=5)

# Output
lbl2 = ttk.Label(root, text="2. Rezultat de pus in Blogger:")
lbl2.pack(anchor="w", padx=10, pady=(5, 0))

text_output = tk.Text(root, height=8, state=tk.DISABLED)
text_output.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

btn_copy = ttk.Button(root, text="Copiaza Rezultatul", command=copy_to_clipboard)
btn_copy.pack(fill=tk.X, padx=10, pady=(5, 10))

root.mainloop()

Monday, August 10, 2026

tkinter : clean html source code with pydroid 3.

This script is an automated HTML cleaner designed to optimize web content for SEO, specifically tailored for HTML code generated by Blogger image uploads. By removing inline style attributes, CSS style blocks, and class parameters, it cleans clutter to improve the code-to-text ratio, enhancing page loading speed-a key ranking factor.
It strips anchor tags while preserving their internal content, eliminating unwanted external links or internal link equity leaks.
By keeping only structural tags like div and img, it produces lightweight, clean HTML markup that search engine crawlers can index and parse easily.
Let's see the source code:
import tkinter as tk
from tkinter import ttk, messagebox
from bs4 import BeautifulSoup

def paste_from_clipboard():
    try:
        text_input.insert(tk.INSERT, root.clipboard_get())
    except Exception:
        try:
            text_input.focus_set()
            text_input.event_generate("<<Paste>>")
        except Exception:
            pass

def process_html():
    raw_html = text_input.get("1.0", tk.END).strip()
    if not raw_html:
        return

    try:
        soup = BeautifulSoup(raw_html, "html.parser")

        # 1. Eliminare completă tag-uri style și script
        for tag in soup.find_all(["style", "script"]):
            tag.decompose()

        # 2. Eliminare ancore (<a>) și păstrare conținut
        for a_tag in soup.find_all("a"):
            a_tag.unwrap()

        # 3. Eliminare atribute 'style' și 'class' de pe TOATE elementele
        attributes_to_remove = ["style", "class"]
        for tag in soup.find_all(True):
            for attr in attributes_to_remove:
                if attr in tag.attrs:
                    del tag.attrs[attr]

        cleaned_html = str(soup)

        text_output.config(state=tk.NORMAL)
        text_output.delete("1.0", tk.END)
        text_output.insert(tk.END, cleaned_html)
        text_output.config(state=tk.DISABLED)
    except Exception as e:
        messagebox.showerror("Eroare", f"A aparut o eroare la procesare: {e}")

def copy_to_clipboard():
    cleaned_text = text_output.get("1.0", tk.END).strip()
    if cleaned_text:
        try:
            root.clipboard_clear()
            root.clipboard_append(cleaned_text)
            messagebox.showinfo("OK", "Copiat in clipboard!")
        except Exception as e:
            messagebox.showerror("Eroare", f"Nu s-a putut copia: {e}")

def clear_all():
    text_input.delete("1.0", tk.END)
    text_output.config(state=tk.NORMAL)
    text_output.delete("1.0", tk.END)
    text_output.config(state=tk.DISABLED)

# Constructie Interfata
root = tk.Tk()
root.title("HTML Cleaner")
root.geometry("400x600")

# Input
lbl1 = ttk.Label(root, text="1. Sursa HTML:")
lbl1.pack(anchor="w", padx=10, pady=(10, 0))

frame_btns = ttk.Frame(root)
frame_btns.pack(fill=tk.X, padx=10, pady=5)

btn_paste = ttk.Button(frame_btns, text="Lipeste (Paste)", command=paste_from_clipboard)
btn_paste.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))

btn_clear = ttk.Button(frame_btns, text="Sterge", command=clear_all)
btn_clear.pack(side=tk.RIGHT)

text_input = tk.Text(root, height=8)
text_input.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

# Procesare
btn_process = ttk.Button(root, text="Proceseaza HTML", command=process_html)
btn_process.pack(fill=tk.X, padx=10, pady=5)

# Output
lbl2 = ttk.Label(root, text="2. Rezultat Curatat:")
lbl2.pack(anchor="w", padx=10, pady=(5, 0))

text_output = tk.Text(root, height=8, state=tk.DISABLED)
text_output.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

btn_copy = ttk.Button(root, text="Copiaza Rezultatul", command=copy_to_clipboard)
btn_copy.pack(fill=tk.X, padx=10, pady=(5, 10))

root.mainloop()

Sunday, August 9, 2026

tkinter : Acode.log Viewer and Clipboard Tool on Pydroid 3

This Python script creates a clean graphical user interface (GUI) using Tkinter, specifically designed to run inside Pydroid 3 on Android devices. Its main purpose is to automatically locate, open, and display the content of the Acode.log file generated by the popular Acode code editor app.
The program checks several common storage paths used by both the free and paid versions of Acode. Once the log file is found, the full content is loaded into a scrollable text area with horizontal and vertical scrollbars for easy reading of long log files. The complete file path, file size in KB, and total number of lines are shown clearly in the status bar at the bottom of the window.
Users can interact with the application through a simple File menu that includes three essential options: Reload (to refresh the log content), Copy All (to copy the entire log text to the system clipboard with one click), and Exit. Keyboard shortcuts (Ctrl+R, Ctrl+C, Ctrl+Q) are also supported for faster operation. The script handles missing files and read errors gracefully, displaying clear status messages and helpful guidance when the log cannot be located or accessed. It uses UTF-8 encoding with error replacement to ensure special characters do not break the display.
Ideal for Android developers and Acode users who need a fast, lightweight way to inspect application logs directly on their device without leaving the Pydroid 3 environment. The pure Tkinter interface requires no external libraries, making it fully compatible with Pydroid 3 out of the box.
Let's see the source code:
import tkinter as tk
from tkinter import scrolledtext, messagebox, ttk
import os

# Possible paths for Acode.log (paid + free version)
POSSIBLE_PATHS = [
    "/storage/emulated/0/Android/data/com.foxdebug.acode/files/Acode.log",
    "/storage/emulated/0/Android/data/com.foxdebug.acode.free/files/Acode.log",
    "/storage/emulated/0/Android/data/com.foxdebug.acode/files/logs/Acode.log",
    "/storage/emulated/0/Android/data/com.foxdebug.acode.free/files/logs/Acode.log",
    "/sdcard/Android/data/com.foxdebug.acode/files/Acode.log",
    "/sdcard/Android/data/com.foxdebug.acode.free/files/Acode.log",
]

class AcodeLogViewer:
    def __init__(self, root):
        self.root = root
        self.root.title("Acode.log Viewer - Pydroid 3")
        self.root.geometry("900x650")
        self.root.minsize(600, 400)

        self.found_path = None
        self.file_content = ""

        self.create_menu()
        self.create_widgets()
        self.search_and_load()

    def create_menu(self):
        """Create the main application menu."""
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)

        # File menu
        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="File", menu=file_menu)
        file_menu.add_command(label="Reload", command=self.search_and_load, accelerator="Ctrl+R")
        file_menu.add_command(label="Copy All", command=self.copy_to_clipboard, accelerator="Ctrl+C")
        file_menu.add_separator()
        file_menu.add_command(label="Exit", command=self.root.quit, accelerator="Ctrl+Q")

        # Keyboard shortcuts
        self.root.bind("", lambda e: self.search_and_load())
        self.root.bind("", lambda e: self.copy_to_clipboard())
        self.root.bind("", lambda e: self.root.quit())

    def create_widgets(self):
        # Text area with scrollbars
        text_frame = ttk.Frame(self.root, padding=8)
        text_frame.pack(fill=tk.BOTH, expand=True)

        self.text_area = scrolledtext.ScrolledText(
            text_frame,
            wrap=tk.NONE,
            font=("Courier New", 10),
            state=tk.DISABLED
        )
        self.text_area.pack(fill=tk.BOTH, expand=True)

        # Horizontal scrollbar
        h_scroll = ttk.Scrollbar(text_frame, orient=tk.HORIZONTAL, command=self.text_area.xview)
        h_scroll.pack(fill=tk.X)
        self.text_area.configure(xscrollcommand=h_scroll.set)

        # Status bar – displays the found file path
        self.status_var = tk.StringVar(value="Ready.")
        status_bar = ttk.Label(
            self.root,
            textvariable=self.status_var,
            relief=tk.SUNKEN,
            anchor=tk.W,
            padding=(6, 3)
        )
        status_bar.pack(fill=tk.X, side=tk.BOTTOM)

    def search_and_load(self):
        self.found_path = None
        self.file_content = ""

        for path in POSSIBLE_PATHS:
            if os.path.isfile(path):
                self.found_path = path
                break

        if self.found_path is None:
            self.status_var.set("Acode.log file not found in the known locations.")
            self.display_text(
                "The Acode.log file could not be located.\n\n"
                "Please verify that the Acode application has already generated the log "
                "and that Pydroid 3 has storage access permissions."
            )
            return

        try:
            with open(self.found_path, "r", encoding="utf-8", errors="replace") as f:
                self.file_content = f.read()

            size_kb = len(self.file_content.encode("utf-8")) / 1024
            lines = len(self.file_content.splitlines())

            # Full path + additional information in the status bar
            self.status_var.set(
                f"{self.found_path}  •  {size_kb:.1f} KB  •  {lines} lines"
            )
            self.display_text(self.file_content)

        except Exception as e:
            self.status_var.set(f"Error reading file: {self.found_path}")
            self.display_text(f"Unable to read the file:\n{str(e)}")

    def display_text(self, content):
        self.text_area.config(state=tk.NORMAL)
        self.text_area.delete("1.0", tk.END)
        self.text_area.insert(tk.END, content)
        self.text_area.config(state=tk.DISABLED)
        self.text_area.see("1.0")

    def copy_to_clipboard(self):
        if not self.file_content:
            messagebox.showwarning("Clipboard", "There is no content to copy.")
            return

        try:
            self.root.clipboard_clear()
            self.root.clipboard_append(self.file_content)
            self.root.update()
            self.status_var.set(f"Content copied • {self.found_path or 'N/A'}")
            messagebox.showinfo("Clipboard", "The entire log content has been copied to the clipboard.")
        except Exception as e:
            messagebox.showerror("Clipboard Error", f"Unable to copy to clipboard:\n{str(e)}")


if __name__ == "__main__":
    root = tk.Tk()
    app = AcodeLogViewer(root)
    root.mainloop()

Monday, August 3, 2026

tkinter : simple rss feeds reader on pydroid 3.

Today, this is a simple rss feeds reader with tkinter on pydroid I.D.E. android. The source code is very simple and get feeds from web. See the result:
import tkinter as tk
from tkinter import messagebox, ttk
import webbrowser
import feedparser

RSS_URL = "https://blog.python.org/feeds/posts/default"

article_links = []


def clean_text(text):
    """Converts text to basic ASCII to strip non-supported Android Tkinter characters."""
    if not text:
        return ""
    # Encodes to ASCII ignoring emojis, special quotes, and unsupported byte sequences
    clean = text.encode("ascii", "ignore").decode("ascii")
    # Removes extra whitespace and linebreaks
    return " ".join(clean.split())


def load_feed():
    global article_links

    listbox.delete(0, tk.END)
    article_links.clear()

    status_label.config(text="Fetching articles...", foreground="blue")
    root.update()

    try:
        feed = feedparser.parse(RSS_URL)

        if not feed.entries:
            status_label.config(text="No articles found.", foreground="red")
            return

        for entry in feed.entries:
            title_raw = entry.get("title", "Untitled")
            title = clean_text(title_raw)
            link = entry.get("link", "")

            listbox.insert(tk.END, title)
            article_links.append(link)

        status_label.config(
            text=f"Loaded {len(feed.entries)} articles!", foreground="green"
        )

    except Exception as e:
        status_label.config(text="Connection error!", foreground="red")
        messagebox.showerror("Error", f"Failed to load feed:\n{e}")


def open_link(event):
    try:
        index = listbox.curselection()[0]
        url = article_links[index]
        if url:
            webbrowser.open(url)
    except IndexError:
        pass


# --- GUI Setup ---
root = tk.Tk()
root.title("Python Foundation RSS Reader")
root.geometry("600x800")

title_label = ttk.Label(
    root, text="Python Software Foundation Blog", font=("Helvetica", 14, "bold")
)
title_label.pack(pady=10)

refresh_btn = ttk.Button(root, text="Refresh", command=load_feed)
refresh_btn.pack(pady=5)

status_label = ttk.Label(
    root, text="Connecting...", font=("Helvetica", 10)
)
status_label.pack(pady=5)

frame = ttk.Frame(root)
frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

scrollbar = ttk.Scrollbar(frame, orient=tk.VERTICAL)

listbox = tk.Listbox(
    frame,
    font=("Helvetica", 11),
    selectbackground="#007ACC",
    selectforeground="white",
    activestyle="none",
    yscrollcommand=scrollbar.set,
    bd=1,
    relief="solid",
)

scrollbar.config(command=listbox.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

listbox.bind("<>", open_link)

root.after(500, load_feed)
root.mainloop()

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()

Thursday, July 30, 2026

tkinter : mini rss for NVDA

Today, I started new post with tkinter label. This is a demo real with pydroid3 android application to get data from rss and show me NVDA and more.
The tkinter package (“Tk interface”) is the standard Python interface to the Tcl/Tk GUI toolkit. Both Tk and tkinter are available on most Unix platforms, including macOS, as well as on Windows systems.

Tuesday, July 21, 2026

News : Quantum Computing 101: How to Get Started

Python 3.10.11 : testing default example with the pyui-0.1.0 python module.

A declarative, cross-platform GUI framework (ala SwiftUI) written in Python using SDL2. It provides tools and libraries that enable developers to create and manage user interfaces for desktop apps.
You need to install the pyui python module and the SDK with the pip tool.
python -m pip install pyui
Collecting pyui
  Downloading pyui-0.1.0-py3-none-any.whl.metadata (893 bytes)
Collecting PySDL2>=0.9.7 (from pyui)
  Downloading PySDL2-0.9.17-py3-none-any.whl.metadata (3.8 kB)
Downloading pyui-0.1.0-py3-none-any.whl (6.0 MB)
   ---------------------------------------- 6.0/6.0 MB 6.0 MB/s  0:00:01
Downloading PySDL2-0.9.17-py3-none-any.whl (583 kB)
   ---------------------------------------- 583.1/583.1 kB 2.1 MB/s  0:00:00
Installing collected packages: PySDL2, pyui
Successfully installed PySDL2-0.9.17 pyui-0.1.0
python -m pip install pysdl2-dll
Collecting pysdl2-dll
  Downloading pysdl2_dll-2.32.10-py2.py3-none-win_amd64.whl.metadata (4.7 kB)
Downloading pysdl2_dll-2.32.10-py2.py3-none-win_amd64.whl (4.1 MB)
   ---------------------------------------- 4.1/4.1 MB 4.1 MB/s  0:00:01
Installing collected packages: pysdl2-dll
Successfully installed pysdl2-dll-2.32.10
Let's see the default example with one grid.
Let's see the source code:
import pyui

class ItemGridView(pyui.View):
    def content(self):
        yield pyui.ScrollView(axis=self.axis)(
            pyui.Grid(num=self.num, size=self.size, axis=self.axis, flex=self.flex)(
                pyui.ForEach(
                    range(self.item_count),
                    lambda num: (
                        pyui.Rectangle()(pyui.Text(num + 1).color(255, 255, 255))
                        .background(120, 120, 120)
                        .radius(5)
                        .animate()
                    ),
                )
            )
        )

class GridTest(pyui.View):
    axis = pyui.State(default=1)
    item_count = pyui.State(int, default=50)
    size = pyui.State(default=100)
    num = pyui.State(default=4)
    size_or_num = pyui.State(default=0)
    flex = pyui.State(default=False)

    def content(self):
        if self.size_or_num.value == 0:
            size = None
            num = self.num.value
        else:
            size = self.size.value
            num = None
        yield pyui.HStack(alignment=pyui.Alignment.LEADING)(
            pyui.VStack(alignment=pyui.Alignment.LEADING)(
                pyui.Text("Axis"),
                pyui.SegmentedButton(self.axis)(
                    pyui.Text(pyui.Axis.HORIZONTAL.name),
                    pyui.Text(pyui.Axis.VERTICAL.name),
                ),
                pyui.HStack(
                    pyui.Text("Number of items"),
                    pyui.Spacer(),
                    pyui.Text(self.item_count.value)
                    .color(128, 128, 128)
                    .priority("high"),
                ),
                pyui.Slider(self.item_count, maximum=200),
                pyui.Text("Fill rows/columns by"),
                pyui.SegmentedButton(self.size_or_num)(
                    pyui.Text("Number"),
                    pyui.Text("Size"),
                ),
                pyui.HStack(
                    pyui.Text("Items per row/column"),
                    pyui.Spacer(),
                    pyui.Text(self.num.value).color(128, 128, 128).priority("high"),
                ),
                pyui.Slider(self.num, minimum=1, maximum=10).disable(
                    self.size_or_num.value == 1
                ),
                pyui.HStack(
                    pyui.Text("Item size"),
                    pyui.Spacer(),
                    pyui.Text(self.size.value).color(128, 128, 128).priority("high"),
                ),
                pyui.Slider(self.size, minimum=50, maximum=200).disable(
                    self.size_or_num.value == 0
                ),
                pyui.Toggle(self.flex, label="Adjust size to fit").disable(
                    self.size_or_num.value == 0
                ),
            )
            .padding(10)
            .size(width=300),
            ItemGridView(
                item_count=self.item_count.value,
                size=size,
                num=num,
                axis=self.axis.value,
                flex=self.flex.value,
            ),
        )

if __name__ == "__main__":
    app = pyui.Application("io.temp.GridTest")
    app.window("Grid Tester", GridTest())
    app.run()

Sunday, July 5, 2026

Python 3.10.11 : python library-skills for your artificial intelligence.

The Python package library-skills is a lightweight command‑line toolkit designed to help developers build, test, and validate modular AI “skills.” These skills are small, self‑contained units of logic that can be executed independently or integrated into larger AI agents. The package focuses on simplicity, portability, and clear structure, making it useful for developers who want to experiment with tool‑calling systems or create custom capabilities for AI workflows.
A skill typically consists of a JSON descriptor and a Python function. The JSON file defines the skill’s name, description, and input schema, while the Python file contains the actual execution logic. This separation ensures that skills remain easy to document, validate, and reuse across different projects. With library-skills, developers can quickly inspect a skill’s schema, run it with custom input, or verify that its output matches the expected structure.
The command‑line interface provided by the package allows users to list installed skills, execute them directly, and validate input files without writing additional code. This makes the development cycle faster and more predictable. Instead of manually wiring functions together, developers can rely on a consistent interface that handles loading, parsing, and execution.
One of the main advantages of library-skills is its role in AI agent development. Modern agents often rely on tool‑calling, where the AI selects and triggers external functions based on user intent. Skills created with this package can be easily integrated into such agents, providing clear schemas and predictable behavior. This helps ensure that AI systems remain reliable, debuggable, and easy to extend.
Overall, library-skills is a practical utility for anyone building structured AI tools. It encourages clean design, modularity, and transparency, making it a valuable addition to Python environments focused on AI experimentation and agent development.
Let's install this python package.
python -m pip install library-skills
Collecting library-skills
  Downloading library_skills-0.0.19-py3-none-any.whl.metadata (5.4 kB)
...
Successfully installed library-skills-0.0.19 rich-toolkit-0.20.1 tomli-2.4.1
Let's make the first run:
library-skills.exe

 context
Project root               c:\lucru\PythonProjects
Target Python environment  not found

 Warning:  No target Python environment with site-packages or node_modules was found. Run from a
project root after installing dependencies, for example with 'uv sync' for Python or 'npm install' for
Node.js.

No installed or discovered skills found.
Copy the Library Skills tool skill into the project so agents know how to update, repair, and check
managed skills?
■ Copy Library Skills tool skill into the project so agents know how to update, repair, and check
managed skills? Copy Library Skills tool skill

 Target     Status               Path
 universal  tool skill: missing  .agents\skills\library-skills
 Copied:  library-skills (universal) -> .agents\skills\library-skills
Now you can create skills for your artificial intelligence:
Create a folder with two files:
my_skill/
    skill.json
    skill.py
First file named skill.json:
{
    "name": "hello_skill",
    "description": "Returnează un mesaj simplu",
    "input_schema": {
        "type": "object",
        "properties": {
            "name": {"type": "string"}
        },
        "required": ["name"]
    }
}
The second file named skill.py
def run(input):
    name = input["name"]
    return {"message": f"Salut, {name}!"}
Run the skill into your folder:
library-skills run my_skill --input '{"name": "Catalin"}'
See the schema:
library-skills schema my_skill
Validate the input:
library-skills validate my_skill input.json
List the skills:
library-skills list
This is all you need for a default basic skill with the library-skills.

Python 3.10.11 : CVSS (Common Vulnerability Scoring System) with cvss python package.

This Python package contains CVSS v2, v3 and v4 computation utilities and interactive calculator (for v2 and v3 only) compatible with Python 3. CVSS (Common Vulnerability Scoring System) is an standardized method for rating the severity of security issues on a scale from 0 (no impact) to 10 (critical).
Let's install the cvss python package.
python -m pip install cvss
Collecting cvss
  Downloading cvss-3.6-py2.py3-none-any.whl.metadata (3.8 kB)
Downloading cvss-3.6-py2.py3-none-any.whl (31 kB)
Installing collected packages: cvss
  WARNING: The script cvss_calculator.exe is installed in 'C:\python-3_10_11\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed cvss-3.6
How this works:
NVD Database (online)
        |
        |  JSON feed
        v
Python script ----> parses CVE + CVSS vector
        |
        |  uses cvss library
        v
Scores vulnerabilities (Base, Temporal, Environmental)
        |
        |  inserts results
        v
Your local database (SQL)
        |
        v
Dashboard / API / Alerts 
Simple code source example :
#!/usr/bin/env python3

# Demonstrates how to score a CVSS vector using the open-source "cvss" library.
# Validation and error handling included.

from cvss import CVSS3  # CVSS2, CVSS3, CVSS4 are available
import sys

def score_cvss_vector(vector: str):
    """
    Validates and scores a CVSS3 vector string.
    Returns scores and severities.
    """
    if not isinstance(vector, str) or not vector.strip():
        raise ValueError("Vector must be a non-empty string.")

    try:
        c = CVSS3(vector)
    except Exception as e:
        raise ValueError(f"Invalid CVSS3 vector: {e}")

    return c.clean_vector(), c.scores(), c.severities()

def main():
    if len(sys.argv) != 2:
        print("Usage: python cvss_score.py '<CVSS3_VECTOR>'")
        print("Example:")
        print("python main.py 'CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'")
        sys.exit(1)

    vector = sys.argv[1]

    try:
        clean_v, scores, severity = score_cvss_vector(vector)
        print("Input vector:", vector)
        print("Normalized vector:", clean_v)
        print("Scores:", scores)
        print("Severity:", severity)
    except ValueError as e:
        print("Error:", e)
        sys.exit(1)

if __name__ == "__main__":
    main()
The result is this:
python main.py CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Input vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Normalized vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Scores: (9.8, 9.8, 9.8)
Severity: ('Critical', 'Critical', 'Critical')
Another source code with examples:
#!/usr/bin/env python3
# Requires: pip install cvss

from cvss import CVSS3

# Example vulnerabilities (safe, educational)
vulns = [
    {
        "language": "Python",
        "title": "Unsafe eval usage",
        "description": "Code that executes user-provided input using eval().",
        "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N"
    },
    {
        "language": "C#",
        "title": "Insecure deserialization",
        "description": "BinaryFormatter deserialization of untrusted data.",
        "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
    },
    {
        "language": "Godot Engine",
        "title": "Unvalidated file path access",
        "description": "Loading files from paths provided by the user without validation.",
        "cvss_vector": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N"
    }
]

def analyze_vulnerabilities(vuln_list):
    for v in vuln_list:
        print("\n====================================")
        print("Language:", v["language"])
        print("Issue:", v["title"])
        print("Description:", v["description"])
        print("CVSS Vector:", v["cvss_vector"])

        try:
            cv = CVSS3(v["cvss_vector"])
            base, temp, env = cv.scores()
            sev_base, sev_temp, sev_env = cv.severities()

            print("Base Score:", base, "-", sev_base)
            print("Temporal Score:", temp, "-", sev_temp)
            print("Environmental Score:", env, "-", sev_env)

        except Exception as e:
            print("Invalid CVSS vector:", e)

if __name__ == "__main__":
    analyze_vulnerabilities(vulns)
This is the result:
python main_002.py

====================================
Language: Python
Issue: Unsafe eval usage
Description: Code that executes user-provided input using eval().
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
Base Score: 8.1 - High
Temporal Score: 8.1 - High
Environmental Score: 8.1 - High

====================================
Language: C#
Issue: Insecure deserialization
Description: BinaryFormatter deserialization of untrusted data.
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Base Score: 9.8 - Critical
Temporal Score: 9.8 - Critical
Environmental Score: 9.8 - Critical

====================================
Language: Godot Engine
Issue: Unvalidated file path access
Description: Loading files from paths provided by the user without validation.
CVSS Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
Base Score: 4.4 - Medium
Temporal Score: 4.4 - Medium
Environmental Score: 4.4 - Medium

Python 3.10.11 : Show the CVE's results with opencve token.

Today, this simple source code use token from opencve.io - website to show CVE's results.
import requests

API_URL = "https://app.opencve.io/api/cve"
TOKEN = "opc_org.<token_id>.<secret>"

headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Accept": "application/json",
}

params = {
    "vendor": "microsoft",
    "cvss": "critical",
    "page": 1,
}

resp = requests.get(API_URL, headers=headers, params=params)
data = resp.json()

for cve in data["results"]:
    print(cve["cve_id"], cve["description"])
This is the result:
python main_001.py
CVE-2026-58289 Access of resource using incompatible type ('type confusion') in Microsoft Edge (Chromium-based) allows an unauthorized attacker to execute code over a network.
CVE-2026-45499 Server-side request forgery (ssrf) in Azure OpenAI allows an authorized attacker to elevate privileges over a network.
CVE-2026-41106 Url redirection to untrusted site ('open redirect') in M365 Copilot allows an unauthorized attacker to elevate privileges over a network.
CVE-2026-57100 Server-side request forgery (ssrf) in Microsoft Entra Provisioning Service (SyncFabric) allows an authorized attacker to elevate privileges over a network.
CVE-2026-54130 Missing authentication for critical function in M365 Copilot allows an unauthorized attacker to disclose information over a network.
CVE-2026-48584 Execution with unnecessary privileges in Azure Synapse allows an authorized attacker to elevate privileges over a network.
CVE-2026-45480 Improper authentication in Azure Active Directory allows an unauthorized attacker to elevate privileges over a network.
CVE-2025-62821 Microsoft HEIF Image Extensions 1.2.22.0 has an out-of-bounds read because CHEIFItemInfoEntry_GetDataSize can return success while leaving the reported data size as 0. This causes a caller to make a 1-byte allocation. Later, CopyPixels computes copy_size = stride * abs(roi_height) but does not check the source buffer length before a memmove call.
CVE-2026-47647 Improper access control in Microsoft Dynamics 365 allows an authorized attacker to elevate privileges over a network.
CVE-2026-48582 Missing authorization in Microsoft Exchange Online allows an authorized attacker to elevate privileges over a network.

Sunday, May 24, 2026

Python Qt : testing the SUA library using the pytrends and plotly.

People’s interactions can serve as a foundation for certain studies; here is a simple way to process data at low cost using Google Trends and lightweight Python packages such as SUA.
The script retrieves Google Trends search‑interest data for several Romanian economic keywords (such as munca, recesiune, somaj, inflatie, dobanzi) and I used copilot and gemini artificial intelligence. The copilot comes with bad result for fast asking simple scripts. It analyzes the data using the SUA library to estimate simple metrics like interest growth and volatility, then displays the results in a PyQt6 interactive chart where the X‑axis shows real calendar dates and the Y‑axis shows the Google Trends 0–100 normalized interest scale.
However, the script is limited by Google Trends constraints:
Google Trends allows maximum 5 keywords per request, so the script cannot query more terms at once.
Google Trends treats diacritic and non‑diacritic words as different searches (e.g., șomaj ≠ somaj), so the script uses non‑diacritic versions to avoid errors and improve compatibility.
Google Trends returns normalized values (0–100), not real search counts, meaning the data shows relative interest, not absolute volume.
The time series resolution is fixed by Google (weekly data for 12 months), so the X‑axis length depends on how many points Google provides.
These limitations come from Google Trends itself, not from the script.
python -m pip install sua
Collecting sua
...
Successfully installed MarkupSafe-3.0.3 altair-6.1.0 asttokens-3.0.1 attrs-26.1.0 beautifulsoup4-4.14.3 blinker-1.9.0 
cachetools-7.1.4 cffi-2.0.0 clarabel-0.11.1 click-8.4.1 cloudpickle-3.1.2 cmdstanpy-1.3.0 colorama-0.4.6 contourpy-1.3.2 
curl_cffi-0.15.0 cvxpy-1.7.5 cycler-0.12.1 darts-0.44.1 datetime-6.0 decorator-5.3.1 empyrical-0.5.5 executing-2.2.1 
fonttools-4.63.0 fpdf-1.7.2 gitdb-4.0.12 gitpython-3.1.50 holidays-0.97 httptools-0.7.1 importlib_resources-7.1.0 
ipython-8.39.0 itsdangerous-2.2.0 jedi-0.20.0 jinja2-3.1.6 joblib-1.5.3 jsonschema-4.26.0 jsonschema-specifications-2025.9.1 
kiwisolver-1.5.0 llvmlite-0.47.0 lxml-6.1.1 markdown-it-py-4.2.0 matplotlib-3.10.9 matplotlib-inline-0.2.2 mdurl-0.1.2 
multitasking-0.0.13 narwhals-2.21.2 nfoursid-1.0.2 numba-0.65.1 numpy-2.2.6 osqp-1.1.1 pandas-2.3.3 pandas-datareader-0.10.0 
parso-0.8.7 patsy-1.0.2 peewee-4.0.6 pillow-12.2.0 platformdirs-4.9.6 prompt_toolkit-3.0.52 prophet-1.3.0 protobuf-7.35.0 
pure-eval-0.2.3 pyarrow-24.0.0 pycparser-3.0 pydeck-0.9.2 pygments-2.20.0 pyod-3.5.2 pyparsing-3.3.2 pyportfolioopt-1.6.0 
python-dateutil-2.9.0.post0 python-multipart-0.0.29 pytz-2026.2 quantstats-0.0.81 referencing-0.37.0 rich-15.0.0 rpds-py-0.30.0 
scikit-base-0.13.2 scikit-learn-1.7.2 scipy-1.15.3 scs-3.2.11 seaborn-0.13.2 shap-0.49.1 six-1.17.0 slicer-0.0.8 smmap-5.0.3 
soupsieve-2.8.3 stack_data-0.6.3 stanio-0.5.1 starlette-1.1.0 statsmodels-0.14.6 streamlit-1.57.0 sua-1.1.5.1 tabulate-0.10.0 
tenacity-9.1.4 threadpoolctl-3.6.0 toml-0.10.2 tqdm-4.67.3 traitlets-5.15.0 tzdata-2026.2 uvicorn-0.48.0 watchdog-6.0.0 
wcwidth-0.7.0 websockets-16.0 xarray-2025.6.1 yfinance-1.4.0 zope.interface-8.4
python -m pip install pytrends
Collecting pytrends
...
Installing collected packages: pytrends
Successfully installed pytrends-4.9.2
python -m pip install plotly
Collecting plotly
...
Installing collected packages: plotly
...
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed plotly-6.7.0
Now, the plotty use an little tool and this want to access my Scripts folder by environment variables.
If you got this error, then you need to limit the words, because Google returns a 400 Bad Request when your request is not valid for the internal Google Trends API.
    raise exceptions.ResponseError.from_response(response)
pytrends.exceptions.ResponseError: The request failed: Google returned a response with code 400
Let's run teh python script and output is this:
python main.py
Average interest growth (returns):
munca: 0.0072
recesiune: 0.3387
somaj: 0.0308
inflatie: 0.0660
dobanzi: 0.0157

Volatility (risk):
munca: 0.0256
recesiune: 2.9473
somaj: 0.1348
inflatie: 0.1607
dobanzi: 0.0527
The PyQt6 will create this bad result, what 1970 ?:
PyQt_Google_trends_May_2026_2025_bad
The issue in your script occurs because PyQt’s QDateTimeAxis expects the X‑axis timestamp to be expressed in milliseconds (since the Unix epoch), while Python’s .timestamp() function returns the value in seconds. When you send seconds instead of milliseconds, PyQt interprets a value that is 1000 times smaller, which places all chart points somewhere at the beginning of 1970 (right after January 1st, 1970).
Let's fix this issue:
from pytrends.request import TrendReq
# Din moment ce modulele de mai jos erau importate dar nefolosite în codul tău, 
# m-am asigurat că restul rulării rămâne intactă.
try:
    from sua import expected_returns, risk_models
except ImportError:
    pass

from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt6.QtCharts import QChart, QChartView, QLineSeries, QDateTimeAxis, QValueAxis
from PyQt6.QtGui import QPainter
from PyQt6.QtCore import QPointF, QDateTime, Qt
import sys

# -----------------------------
# 1. Keywords (fără diacritice)
# -----------------------------
keywords = ["munca", "recesiune", "somaj", "inflatie", "dobanzi"]

# -----------------------------
# 2. Preluare date Pytrends
# -----------------------------
pytrends = TrendReq(hl='ro-RO', tz=180)
pytrends.build_payload(keywords, timeframe='today 12-m', geo='RO')

raw = pytrends.interest_over_time()

# Convertim în structuri simple
dates = list(raw.index)  # Python datetime objects
data = {k: list(raw[k]) for k in keywords}

# -----------------------------
# 3. Calcul SUA (randament + risc)
# -----------------------------
returns = {k: [] for k in keywords}

for k in keywords:
    series = data[k]
    for i in range(1, len(series)):
        prev = series[i-1] or 1
        curr = series[i] or 1
        returns[k].append((curr - prev) / prev)

mu = {k: sum(returns[k]) / len(returns[k]) for k in keywords}

def covariance(a, b):
    mean_a = sum(a) / len(a)
    mean_b = sum(b) / len(b)
    return sum((a[i]-mean_a)*(b[i]-mean_b) for i in range(len(a))) / len(a)

S = {k: covariance(returns[k], returns[k]) for k in keywords}

print("Average interest growth (returns):")
for k, v in mu.items():
    print(f"{k}: {v:.4f}")

print("\nVolatility (risk):")
for k, v in S.items():
    print(f"{k}: {v:.4f}")

# -----------------------------
# 4. PyQt6 Chart GUI cu date reale (CORECTAT)
# -----------------------------
class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Google Trends Economic Interest (RO)")

        chart = QChart()
        chart.setTitle("Interest Over Time (Google Trends Romania)")

        # Axa X = date reale
        axis_x = QDateTimeAxis()
        axis_x.setFormat("yyyy-MM-dd")
        axis_x.setTitleText("Date")
        axis_x.setTickCount(10)

        # !!! CORECȚIE 1: Să îi spunem axei care este limita minimă și maximă reală !!!
        # Conversie din primul și ultimul obiect datetime din Pytrends în QDateTime
        qt_start_date = QDateTime.fromMSecsSinceEpoch(int(dates[0].timestamp() * 1000))
        qt_end_date = QDateTime.fromMSecsSinceEpoch(int(dates[-1].timestamp() * 1000))
        axis_x.setRange(qt_start_date, qt_end_date)

        # Axa Y = valori 0–100
        axis_y = QValueAxis()
        axis_y.setRange(0, 100)
        axis_y.setTitleText("Interest (0–100)")

        chart.addAxis(axis_x, Qt.AlignmentFlag.AlignBottom)
        chart.addAxis(axis_y, Qt.AlignmentFlag.AlignLeft)

        # Adăugăm seriile
        for k in keywords:
            series = QLineSeries()
            series.setName(k)

            for i, val in enumerate(data[k]):
                # !!! CORECȚIE 2: Înmulțim cu 1000 pentru a transforma în milisecunde !!!
                timestamp_ms = int(dates[i].timestamp() * 1000)
                series.append(QPointF(float(timestamp_ms), float(val)))

            chart.addSeries(series)
            series.attachAxis(axis_x)
            series.attachAxis(axis_y)

        view = QChartView(chart)
        view.setRenderHint(QPainter.RenderHint.Antialiasing)

        self.setCentralWidget(view)

app = QApplication(sys.argv)
window = Window()
window.resize(1400, 700)
window.show()
sys.exit(app.exec())
This result is good and is fixed by Gemnini artificial intelligence, but if you want real development then you need to use more then simple issue to artificial intelligence:
python main.py
Average interest growth (returns):
munca: 0.0073
recesiune: 0.3387
somaj: 0.0308
inflatie: 0.0660
dobanzi: 0.0189

Volatility (risk):
munca: 0.0258
recesiune: 2.9473
somaj: 0.1348
inflatie: 0.1607
dobanzi: 0.0594
PyQt_Google_trends_May_2026_2025_good