analitics

Pages

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

Friday, August 7, 2026

News : Django 6.1 release ...

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 6.0 or earlier. We’ve begun the deprecation process for some features.

Tuesday, August 4, 2026

News : Python 3.15.0 candidate ...

This is a candidate preview of Python 3.15
This release, 3.15.0rc1, is the first of two planned candidate releases. Entering the release candidate phase, only reviewed code changes which are clear bug fixes are allowed between this release candidate and the final release.
The next release of Python 3.15 will be 3.15.0rc2, scheduled for 2026-09-01.

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