analitics

Pages

Tuesday, February 10, 2026

Python Qt6 : one simple markdown editor.

Today, I tested my simple Markdown editor. I used artificial intelligence.
This project is a custom Markdown editor built with PyQt6.
It provides a two‑panel interface where the user writes Markdown on the right side and sees a live HTML preview on the left side.
The goal is to offer a simple and efficient workflow similar to GitHub’s Markdown rendering.
Main Features
  • Two‑panel layout The left panel displays the rendered HTML preview, while the right panel contains the Markdown editor and formatting buttons.
  • Real‑time preview Every change in the editor updates the preview instantly. The preview uses multiple Markdown extensions to support tables, lists, code blocks, footnotes, and other GitHub‑style formatting.
  • Image support Images inserted through the editor are converted to local file URLs. This ensures that the preview panel can load them correctly, even when the image is stored outside the project folder.
  • Markdown extensions The editor enables a wide set of extensions, including:
    • tables
    • fenced code blocks
    • footnotes
    • definition lists
    • smart quotes
    • wiki links
    • admonitions
    • GitHub‑style lists
    These extensions allow the preview to closely match GitHub’s Markdown rendering.
  • Editing toolbar The editor includes quick‑insert buttons for bold, italic, lists, and images. These buttons modify only the Markdown text in the editor panel.
  • Zoom controls The preview panel includes buttons for resetting zoom to 100 percent, zooming in, and zooming out. This helps when working with long documents or detailed tables.
  • File operations The application supports creating, opening, and saving Markdown files. It also includes an option to export the rendered content as an HTML file.
  • Theme switching Users can switch between light and dark themes depending on their preference.
  • Drag and drop Markdown files can be opened by dragging them directly into the window.
  • Plugin system The editor includes a simple plugin mechanism that allows adding new features without modifying the core application.
  • Status bar The bottom bar displays the current file path, file size, and word count.

Monday, February 9, 2026

Python 3.13.0 : New Feature: Interactive History Search.

If you are using the new Python 3.13 REPL, you might have noticed a new prompt when pressing certain keys. This is the upgraded interactive shell that now supports built-in history searching.
What is f-search and r-search?
These features allow you to search through every command you have previously typed without using the arrow keys.
How to trigger it:
- Press Ctrl + R to initiate a Reverse Search. You will see (r-search ''). This looks through your history from newest to oldest.
- Press Ctrl + S to initiate a Forward Search. You will see (f-search ''). This looks through your history from oldest to newest.
How to use it:
1. Type the shortcut (Ctrl+R or Ctrl+S).
2. Start typing any part of a previous command (e.g., 'import' or 'def').
3. The shell will automatically complete the line with the best match.
4. Press Enter to run the command, or use the arrow keys to start editing the found line.
5. If you want to cancel the search, simply press Ctrl + G.
This feature makes the Python 3.13 terminal feel much more like a modern shell, saving time and reducing repetitive typing.
C:\Python313_64bit>python
Python 3.13.0 (tags/v3.13.0:60403a5, Oct  7 2024, 09:38:07) [MSC v.1941 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import sys
(r-search `os') import os

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

Monday, January 26, 2026

News : examples with rich python package.

Python's Rich package is a tool kit that helps you generate beautifully formatted and highlighted text in the console.
Let's see some examples:
Run the source code with these args --demo and --dashboard:
import time
import sys
import logging
import argparse
import msvcrt  # Windows keyboard input

from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn
from rich.syntax import Syntax
from rich.layout import Layout
from rich.live import Live
from rich.theme import Theme
from rich.logging import RichHandler

# ---------------------------------------------------------
# 1. DARK THEME
# ---------------------------------------------------------
dark_theme = Theme({
    "info": "bold cyan",
    "warning": "bold yellow",
    "error": "bold red",
    "success": "bold green",
    "title": "bold magenta",
    "data": "bold white",
})

console = Console(theme=dark_theme)

# ---------------------------------------------------------
# 2. LOGGING (RichHandler)
# ---------------------------------------------------------
logging.basicConfig(
    level="INFO",
    format="%(message)s",
    datefmt="[%H:%M:%S]",
    handlers=[RichHandler(console=console)]
)
log = logging.getLogger("CLI")

# ---------------------------------------------------------
# 3. CLI ARGUMENTS
# ---------------------------------------------------------
def parse_args():
    parser = argparse.ArgumentParser(
        description="Rich CLI + Dashboard + Menu + Buttons"
    )
    parser.add_argument("--demo", action="store_true", help="Run the demo")
    parser.add_argument("--dashboard", action="store_true", help="Start the dashboard")
    return parser.parse_args()

# ---------------------------------------------------------
# 4. WINDOWS KEY READER
# ---------------------------------------------------------
def get_key():
    if msvcrt.kbhit():
        return msvcrt.getch().decode(errors="ignore")
    return None

# ---------------------------------------------------------
# 5. MENU + BUTTONS
# ---------------------------------------------------------
menu_items = ["Statistics", "Processes", "Settings", "Exit"]
selected = 0

def render_menu():
    table = Table(show_header=False, expand=True)
    for i, item in enumerate(menu_items):
        if i == selected:
            table.add_row(f"[black on cyan] {item} [/]")
        else:
            table.add_row(f"[cyan] {item} [/]")
    return Panel(table, title="Menu", border_style="cyan")

def render_content():
    if menu_items[selected] == "Statistics":
        return Panel("CPU: 37%\nRAM: 62%\nDisk: 128MB/s", title="System Statistics")

    elif menu_items[selected] == "Processes":
        return Panel("proc1\nproc2\nproc3", title="Running Processes")

    elif menu_items[selected] == "Settings":
        return Panel("Settings will appear here", title="Settings")

    elif menu_items[selected] == "Exit":
        return Panel("[red]Press ENTER to exit[/red]", title="Exit")

# ---------------------------------------------------------
# 6. DASHBOARD LAYOUT (original + menu added)
# ---------------------------------------------------------
def build_dashboard():
    layout = Layout()

    layout.split(
        Layout(name="header", size=3),
        Layout(name="body", ratio=1),
        Layout(name="footer", size=3),
    )

    layout["body"].split_row(
        Layout(name="left", size=30),
        Layout(name="right")
    )

    layout["header"].update(
        Panel("[title]LIVE DASHBOARD — Rich Dark Mode[/title]", style="bold magenta")
    )

    layout["left"].update(render_menu())
    layout["right"].update(render_content())

    layout["footer"].update(
        Panel("[info]Status: Running in real time[/info]")
    )

    return layout

# ---------------------------------------------------------
# 7. DEMO (unchanged from first script)
# ---------------------------------------------------------
def run_demo():
    console.print("[success]Rich Dark Mode Demo Started[/success]")

    table = Table(title="Example Table", expand=True)
    table.add_column("ID", style="yellow")
    table.add_column("Name", style="cyan")
    table.add_column("Status", style="green")

    table.add_row("1", "Catalin", "Active")
    table.add_row("2", "Rich CLI", "OK")
    table.add_row("3", "Dashboard", "Ready")

    console.print(table)

    log.info("This is an INFO message")
    log.warning("This is a WARNING message")
    log.error("This is an ERROR message")

    with Progress(
        SpinnerColumn(),
        BarColumn(),
        TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
        console=console,
    ) as progress:
        task = progress.add_task("Processing...", total=100)
        for _ in range(100):
            time.sleep(0.02)
            progress.update(task, advance=1)

    code = """
def greet(name):
    return f"Hello, {name}!"

print(greet("Catalin"))
"""
    syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
    console.print(Panel(syntax, title="Syntax Highlight"))

# ---------------------------------------------------------
# 8. MAIN LOOP
# ---------------------------------------------------------
if __name__ == "__main__":
    args = parse_args()

    if args.demo:
        run_demo()

    if args.dashboard:
        with Live(build_dashboard(), refresh_per_second=10) as live:
            while True:
                key = get_key()

                if key == "w":
                    selected = (selected - 1) % len(menu_items)
                elif key == "s":
                    selected = (selected + 1) % len(menu_items)
                elif key == "\r":
                    if menu_items[selected] == "Exit":
                        break

                live.update(build_dashboard())

Sunday, January 25, 2026

Python 3.13.0 : ... build full-stack web applications entirely in Python with reflex.

NOTE : Yesterday I tested this framework and it blocked my python running and I couldn't display the result. Interesting about this framework is that you can also program your backend running.
The static motion is green because is not used with RGB colors.
Reflex is a library to build full-stack web apps in pure Python.
Reflex is a Python library designed to build full-stack web applications entirely in Python, eliminating the need to learn JavaScript. It allows developers to create both the frontend and backend of web applications seamlessly, offering flexibility and scalability for projects ranging from simple prototypes to complex systems.
See my test on Winodws O.S. :
mkdir my_app_catafest

cd my_app_catafest

my_app_catafest>python -m venv .venv

my_app_catafest>.venv\Scripts\activate

(.venv) C:\PyQt6\reflex_framework\my_app_catafest>pip install reflex
Collecting reflex
  Using cached reflex-0.8.26-py3-none-any.whl.metadata (13 kB)
...
Installing collected packages: wrapt, typing-extensions, redis, python-multipart, pygments, psutil, platformdirs, packaging, mdurl, MarkupSafe, idna, h11, greenlet, colorama, certifi, bidict, annotated-types, wsproto, typing-inspection, SQLAlchemy, pydantic-core, markdown-it-py, Mako, httpcore, click, anyio, watchfiles, starlette, simple-websocket, rich, pydantic, httpx, granian, alembic, sqlmodel, reflex-hosting-cli, python-engineio, python-socketio, reflex
Successfully installed Mako-1.3.10 MarkupSafe-3.0.3 SQLAlchemy-2.0.46 alembic-1.18.1 annotated-types-0.7.0 anyio-4.12.1 bidict-0.23.1 certifi-2026.1.4 click-8.3.1 colorama-0.4.6 granian-2.6.1 greenlet-3.3.1 h11-0.16.0 httpcore-1.0.9 httpx-0.28.1 idna-3.11 markdown-it-py-4.0.0 mdurl-0.1.2 packaging-25.0 platformdirs-4.5.1 psutil-7.2.1 pydantic-2.12.5 pydantic-core-2.41.5 pygments-2.19.2 python-engineio-4.13.0 python-multipart-0.0.22 python-socketio-5.16.0 redis-7.1.0 reflex-0.8.26 reflex-hosting-cli-0.1.61 rich-14.3.1 simple-websocket-1.1.0 sqlmodel-0.0.31 starlette-0.52.1 typing-extensions-4.15.0 typing-inspection-0.4.2 watchfiles-1.1.1 wrapt-2.0.1 wsproto-1.3.2

(.venv) C:\PyQt6\reflex_framework\my_app_catafest>reflex init
──────────────────────────────────────────── Initializing my_app_catafest ─────────────────────────────────────────────
[14:21:36] Initializing the web directory.                                         console.py:231

Get started with a template:
(0) A blank Reflex app.
(1) Premade templates built by the Reflex team.
(2) Try our AI builder.
Which template would you like to use? (0):
[14:21:39] Initializing the app directory.                                         console.py:231
Success: Initialized my_app_catafest using the blank template.

(.venv) C:\PyQt6\reflex_framework\my_app_catafest>reflex run
Warning: Windows Subsystem for Linux (WSL) is recommended for improving initial install times.
────────────────────────────────────── Starting Reflex App ──────────────────────────────────────
[14:27:31] Compiling: ---------------------------------------- 100% 21/21 0:00:02
⠙ Installing base frontend packages Resolving dependencies
... 

Saturday, January 24, 2026

Python Qt6 : tasks with libraries.io

Today, I tested the libraries.io API to see what's new and what differences exist on the web and on my local installation and to be able to update the installed packages.

Wednesday, January 21, 2026

Python Qt6 : testing CatBoost with loto 6/49 numbers.

CatBoost is a high-performance library for gradient boosting on decision trees, developed by Yandex and used for various tasks. It supports categorical features, GPU version, improved
python -m pip install catboost
Collecting catboost
...
Installing collected packages: narwhals, plotly, catboost
Successfully installed catboost-1.2.8 narwhals-2.15.0 plotly-6.5.2
The source code implements a single, clean, fully self‑contained Python application that relies exclusively on real lottery data loaded from a text file. It computes all required numerical relationships for each draw, including digit distribution, statistical measures, and parity-based metrics. Using only the real historical draws, the program automatically builds a training dataset where each row uses the previous extraction as input and the next extraction’s digit distribution as the prediction target. It then trains two CatBoost regression models—one for forecasting how many one‑digit numbers will appear in the next draw, and another for predicting how many two‑digit numbers will appear. All computed metrics and model predictions are displayed in a structured PyQt6 table, ensuring that every result is derived entirely from the real data provided by the user.
I used 217 old real numbers from loto 6/49:
1 6 12 16 17 33
17 26 30 35 36 44
23 24 28 34 48 49
5 11 22 34 42 43
7 12 17 30 33 49
12 23 32 41 43 48
4 6 33 35 36 39
4 6 33 35 36 39
13 14 20 21 38 49
4 9 11 15 37 47
...
This is the result:

Tuesday, January 20, 2026

News : Intro to Gemini 2.0 Flash by google.

Gemini 2.0 Flash is a new multimodal generative ai model from the Gemini family developed by Google DeepMind. It is available through the Gemini API in Vertex AI and Vertex AI Studio.
The documentation online can be found on this official webpage.
See one example on this colab notebook.

Sunday, January 18, 2026

Python 3.13.0 : Use image with ollama models Moondream and BakLLaVA.

Today, I tested with one big image 1366 x 768 px, with ollama on my laptop, only 16Gb RAM, Intel video card.
This script demonstrates how to send the same image to two different multimodal AI models (Moondream and BakLLaVA) using the Ollama API. It loads an image, encodes it in Base64 for Windows compatibility, sends it to both models, and prints their separate outputs so you can compare how each model interprets the same visual input.
import requests
import base64
import time

IMAGE_PATH = "test.png"
OLLAMA_URL = "http://localhost:11434/api/generate"

# Load and encode image
with open(IMAGE_PATH, "rb") as f:
    img_bytes = f.read()

img_b64 = base64.b64encode(img_bytes).decode("utf-8")

def query_model(model_name, prompt):
    payload = {
        "model": model_name,
        "prompt": prompt,
        "images": [img_b64],
        "stream": False
    }

    start = time.time()
    r = requests.post(OLLAMA_URL, json=payload)
    end = time.time()

    r.raise_for_status()
    response_text = r.json().get("response", "").strip()
    elapsed = end - start

    return response_text, elapsed

# Run Moondream
moondream_output, moondream_time = query_model("moondream", "Describe the image in detail")

# Run BakLLaVA
bakllava_output, bakllava_time = query_model("bakllava", "Describe the image in detail")

# Print results
print("=== Moondream Output ===")
print(moondream_output)
print(f"\n[Moondream time: {moondream_time:.2f} seconds]")

print("\n=== BakLLaVA Output ===")
print(bakllava_output)
print(f"\n[BakLLaVA time: {bakllava_time:.2f} seconds]")
python test_time.py
=== Moondream Output ===
The image shows a video game screen with four players engaged in an intense battle. The player on the left is holding 
a sword, while another player stands nearby wielding a shield. A third player is seen running towards them, and the 
fourth player is positioned further back, also armed with a sword. The background of the scene features a dark and 
mysterious setting, possibly a cave or underground area.

[Moondream time: 506.34 seconds]

=== BakLLaVA Output ===
The scene displays a group of monsters standing around a central point, creating an atmosphere reminiscent of a 
Dungeons & Dragons game. A total of nine monsters can be seen throughout the image, with some located closer to 
the center and others nearer corners.

In addition to the monsters, there are several items scattered around, such as a bottle situated in the lower-left
part of the scene. Interestingly, this image also contains text box information and appears to have a web address 
displayed, possibly related to the game or providing additional context for the scene.

[BakLLaVA time: 597.49 seconds]
This is the image, one screenshot from my favorite game Star Trek Online:

Saturday, January 17, 2026

Python Qt6 : ... simple validity of media files .

Today I tested the validity of media files and their display in a table with pyqt6, it is a simple example of functionality testing and can be applied to any type of file.

Sunday, January 11, 2026

Python Qt6 : test from PNG to SVG with potrace ...

Tests from two days ago with conversion from PNG format to SVG format with the python potrace package ...

Saturday, January 10, 2026

Python313 : testing the potracer python package.

Pure Python Port of Potrace. This is a python port of Peter Selinger's Potrace (based on 1.16 code).
Today, I install the python package with pip tool:
pip install potracer[cli]
Collecting potracer[cli]
...
Successfully installed potrace-cli-0.0.4 potracer-0.0.4
The dir command show me all of these :
dir(potrace)
['BezierSegment', 'Bitmap', 'COS179', 'CornerSegment', 'Curve', 'INFTY', 'Optional', 'POTRACE_CORNER', 
'POTRACE_CURVETO', 'POTRACE_TURNPOLICY_BLACK', 'POTRACE_TURNPOLICY_LEFT', 'POTRACE_TURNPOLICY_MAJORITY',
'POTRACE_TURNPOLICY_MINORITY', 'POTRACE_TURNPOLICY_RANDOM', 'POTRACE_TURNPOLICY_RIGHT', 'POTRACE_TURNPOLICY_WHITE',
'Path', 'Tuple', 'Union', '_Curve', '_Path', '_Point', '_Segment', '_Sums', '__builtins__', '__cached__', '__doc__',
'__file__', '__loader__', '__name__', '__package__', '__spec__', '_adjust_vertices', '_bestpolygon', '_calc_lon',
'_calc_sums', '_opticurve', '_smooth', 'bezier', 'bm_to_pathlist', 'cprod', 'cyclic', 'ddenom', 'ddist', 'detrand',
'detrand_t', 'dorth_infty', 'dpara', 'findnext', 'findpath', 'floordiv', 'interval', 'iprod', 'iprod1', 'majority',
'math', 'mod', 'np', 'opti_penalty', 'opti_t', 'pathlist_to_tree', 'penalty3', 'pointslope', 'process_path', 'quadform',
'reverse', 'setbbox_path', 'sign', 'sq', 'tangent', 'xor_path', 'xor_to_ref', 'xprod']
See GitHub project from the tatarize.
I used the default example from the github project and works very well.

Python Qt6 : use default PyQt styles to PyQt6 applications.

Today, about PyQt Styles to PyQt6 Applications.
This works with default themes and how to change these, and using different types of custom styling.
First , let's see the source code with default themes:
from PyQt6.QtWidgets import QStyleFactory
print(QStyleFactory.keys())
['windows11', 'windowsvista', 'Windows', 'Fusion']
Let's see the source code for this simple script with this theme windows11:
import sys
from PyQt6.QtWidgets import (
    QApplication, QLabel, QLineEdit, QComboBox, QPushButton,
    QCheckBox, QSlider, QVBoxLayout, QWidget
)
from PyQt6.QtCore import Qt

app = QApplication(sys.argv)
app.setStyle('windows11')

window = QWidget()
layout = QVBoxLayout(window)

# 1. QLabel
layout.addWidget(QLabel("Acesta este un QLabel"))

# 2. QLineEdit
layout.addWidget(QLineEdit("Text editabil"))

# 3. QComboBox
combo = QComboBox()
combo.addItems(["Optiunea 1", "Optiunea 2", "Optiunea 3"])
layout.addWidget(combo)

# 4. QCheckBox
layout.addWidget(QCheckBox("Bifează această opțiune"))

# 5. QSlider
slider = QSlider(Qt.Orientation.Horizontal)
layout.addWidget(slider)

# 5. QPushButton
button = QPushButton('Simple button !')
layout.addWidget(button)

# show the main windows 
window.show()
sys.exit(app.exec())

News : PyQt v6.10.2 Released .

PyQt v6.10.2 has been released. This is a bug-fix release.
  • Fixed a regression introduced in v6.5.0 in the handling of the return value of QSqlQueryModel.query().
  • Fixed a regression introduced in v6.10.1 in the handling of the return value of createMimeDataFromSelection() in QTextEdit and QPlainTextEdit.

Thursday, January 8, 2026

Python Qt6 : Check certificate of url.

Today, I will show this python script to check the certificate of url.
import sys
import ssl
import socket
from datetime import datetime

from cryptography import x509
from cryptography.hazmat.backends import default_backend

from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QLabel,
    QLineEdit, QPushButton, QTextEdit
)

def fetch_certificate_raw(hostname):
    """
    Connects to the server and retrieves the certificate in DER format.
    Also returns a validation status message.
    """

    # Create a default SSL context (validates certificates)
    context = ssl.create_default_context()

    try:
        # First attempt: strict validation
        with socket.create_connection((hostname, 443), timeout=5) as sock:
            with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                der_cert = ssock.getpeercert(binary_form=True)
                return der_cert, "Certificate is VALID"

    except ssl.SSLError as e:
        # Certificate is invalid → try to retrieve it anyway
        try:
            unverified_context = ssl._create_unverified_context()
            with socket.create_connection((hostname, 443), timeout=5) as sock:
                with unverified_context.wrap_socket(sock, server_hostname=hostname) as ssock:
                    der_cert = ssock.getpeercert(binary_form=True)
                    return der_cert, f"Certificate is INVALID: {str(e)}"
        except Exception:
            return None, f"Could not retrieve certificate: {str(e)}"

    except Exception as e:
        return None, f"Connection error: {str(e)}"

def parse_certificate(der_cert):
    """
    Converts a DER-encoded certificate into a cryptography.x509 object.
    """
    return x509.load_der_x509_certificate(der_cert, default_backend())

class CertViewer(QWidget):
    """
    Main GUI window for the HTTPS certificate viewer.
    """
    def __init__(self):
        super().__init__()

        self.setWindowTitle("HTTPS Certificate Checker")
        self.setGeometry(200, 200, 700, 600)

        layout = QVBoxLayout()

        # Input label + text field
        layout.addWidget(QLabel("Enter URL (example: example.com):"))
        self.input = QLineEdit()
        layout.addWidget(self.input)

        # Button to trigger certificate check
        self.button = QPushButton("Check Certificate")
        self.button.clicked.connect(self.check_certificate)
        layout.addWidget(self.button)

        # Output text box
        self.output = QTextEdit()
        self.output.setReadOnly(True)
        layout.addWidget(self.output)

        self.setLayout(layout)

    def check_certificate(self):
        """
        Triggered when the user presses the button.
        Retrieves and displays certificate information.
        """

        hostname = self.input.text().strip()

        # Clean URL (remove http://, https://, and paths)
        for prefix in ("https://", "http://"):
            if hostname.startswith(prefix):
                hostname = hostname[len(prefix):]

        hostname = hostname.split("/")[0]

        # Fetch certificate
        der_cert, status = fetch_certificate_raw(hostname)

        if der_cert is None:
            self.output.setText(status)
            return

        # Parse certificate
        cert = parse_certificate(der_cert)

        # Build output text
        text = f"=== CERTIFICATE STATUS ===\n{status}\n\n"
        text += "=== CERTIFICATE DETAILS ===\n\n"

        text += f"Subject:\n{cert.subject}\n\n"
        text += f"Issuer:\n{cert.issuer}\n\n"
        text += f"Serial Number: {cert.serial_number}\n\n"
        text += f"Version: {cert.version}\n\n"
        text += f"Valid From: {cert.not_valid_before}\n"
        text += f"Valid To:   {cert.not_valid_after}\n\n"

        # Check expiration
        if cert.not_valid_after < datetime.utcnow():
            text += f"⚠ Certificate EXPIRED on: {cert.not_valid_after}\n\n"

        # Subject Alternative Names (SAN)
        try:
            san = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName)
            text += f"Subject Alternative Names:\n{san.value}\n\n"
        except Exception:
            text += "Subject Alternative Names: (none)\n\n"

        self.output.setText(text)

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

Tuesday, January 6, 2026

Python 3.13.0 : PyWin32 is full compatible with Python 3.13 .

Today I tried to use these python packages:
import win32serviceutil
import win32service
import win32event
import servicemanager
The works , but python -m pywin32_postinstall -install comes with:
python.exe: No module named pywin32_postinstall
NOTE : The copilot artificial intelligence, search and give me an old answer , but is wrong ...
PyWin32 is updated slowly, and at this moment there are no wheels for Python 3.13.
The pip tool cannot install pywin32 does not install anything usable, and pywin32_postinstall does not exist
Possible solutions
PyWin32 works perfectly on:
  • Python 3.12
  • Python 3.11
  • Python 3.10
If you need win32service, win32api, win32com, etc., you must use a supported version.
Need to see the last tutorial from my blogger.
I tested on admin with simple service and works:
python service_test_001.py install
Installing service MyPythonService
Service installed
This is the source code:
import win32serviceutil
import win32service
import win32event
import servicemanager
import time

class MyService(win32serviceutil.ServiceFramework):
    _svc_name_ = "MyPythonService"
    _svc_display_name_ = "My Python Windows Service"
    _svc_description_ = "A minimal Windows service example written in Python."

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)
        self.running = True

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.stop_event)
        self.running = False

    def SvcDoRun(self):
        servicemanager.LogInfoMsg("MyPythonService is starting.")
        self.main()

    def main(self):
        while self.running:
            # Your service logic goes here
            time.sleep(5)
            servicemanager.LogInfoMsg("MyPythonService heartbeat.")


if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(MyService)

Sunday, January 4, 2026

Python 3.13.0 : how to install pywin32_postinstall.

Today a tutorial on how to install pywin32_postinstall.
This package is essential for accessing Windows-specific functionalities in Python.
The pywin32_postinstall missing python error typically occurs when the pywin32 package is not properly installed or the post-installation script is not executed correctly.
Fisrt install the pywin32 python package.
pip install pywin32
The next step is to run this command on the path with Script folder.
python C:\Python313\Scripts\pywin32_postinstall.py -install
Parsed arguments are: Namespace(install=True, remove=False, wait=None, silent=False, quiet=False, destination= ...
The next step is to run this command on the path with Script folder.
D:\Python313_64bit>python
Python 3.13.0 (tags/v3.13.0:60403a5, Oct  7 2024, 09:38:07) [MSC v.1941 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import win32api
>>> print(win32api.GetVersion())

Friday, January 2, 2026

Python Qt6 : script for impact on your development workflow using scans features.

Impact on development workflows that rely on Language Server Protocol (LSP) features.
1. Editor Limitations
Your editor (VS Code, Neovim, Qt Creator, etc.) attempts to send a file to the Language Server, but the file is not accessible through the file:// protocol.
When this happens, the LSP rejects the request, and you lose essential features such as:
  • IntelliSense
  • Autocomplete
  • Hover information
  • Diagnostics
  • Jump‑to‑definition
  • Refactoring tools
2. Issues in Non‑Standard Projects
This limitation becomes more severe when working with:
  • dynamically generated files
  • files inside containers
  • remote workspaces
  • build systems that create temporary or virtual files
Since the LSP cannot process these resources, you lose intelligent code support.
3. Toolchain Breakdowns
If you rely on an automated workflow (analysis, diagnostics, UI integration, etc.), an LSP restricted to file:// can break:
  • static analysis
  • code validation
  • report generation
  • plugin integrations
Real Risks in Development
1. False or Incomplete Diagnostics
The LSP may not see the actual files, leading to:
  • false errors
  • missed real errors
2. Dangerous Refactoring
If the LSP cannot access all files, automated refactoring may:
  • fail to update all references
  • introduce new bugs
3. Reduced Productivity
Without full LSP support, you lose:
  • intelligent completion
  • fast navigation
  • real‑time validation
4. Incompatibility With Modern Tooling
Many modern IDEs rely on virtual or remote workspaces. An LSP limited to file:// becomes outdated quickly.
5. Indirect Security Risks
Not a vulnerability by itself, but:
  • if the LSP cannot analyze remote files, you may miss security issues in generated or synchronized code.
I tested with a simple python source code to detect how bad is running on I.D.E. The script continuously scans your Windows system to detect, analyze, and report the real‑time behavior, resource usage, crashes, leaks, ports, and child processes of all VS Code, LSP, and Antigravity components, showing their impact on your development workflow through a live PyQt6 dashboard.
The result after runnig is:

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:

Python 3.12.12 : simple example with CompVis/stable-diffusion-v1-4 model on colab.

Because this year we need to start it as advanced and more prepared as we know and can do ...
Today I tested a simple source code with an interactive interface for text-to-image generation based on the CompVis/stable-diffusion-v1-4 model.
This is not an advanced model and you will have some dizzy images, but the learnning idea is the base of these colabs notebooks.
See the default example on my colab github project.
The colab notebook use this python version:
Python 3.12.12 (main, Oct 10 2025, 08:52:57) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
I'm mode advanced with some models like SDXL, image generation is not a priority at the moment ...
... and first image result is this: