Today, I tested a simple tool for news with the gnews python package:

Is a blog about python programming language. You can see my work with python programming language, tutorials and news.
from krita import *
from PyQt5.QtWidgets import QAction, QMessageBox
import os
class ExportGodotPNG(Extension):
def __init__(self, parent):
super().__init__(parent)
def setup(self):
pass
def export_png(self):
# Get the active document
doc = Krita.instance().activeDocument()
if not doc:
QMessageBox.warning(None, "Error", "No document open! Please open a document and try again.")
return
# Create an InfoObject for PNG export
info = InfoObject()
info.setProperty("alpha", True) # Keep alpha channel for transparency
info.setProperty("compression", 0) # No compression for maximum quality
info.setProperty("interlaced", False) # Disable interlacing
info.setProperty("forceSRGB", True) # Force sRGB for Godot compatibility
# Build the output file path
if doc.fileName():
base_path = os.path.splitext(doc.fileName())[0]
else:
base_path = os.path.join(os.path.expanduser("~"), "export_godot")
output_file = base_path + "_godot.png"
# Export the document as PNG
try:
doc.exportImage(output_file, info)
# Show success message with brief usage info
QMessageBox.information(None, "Success",
f"Successfully exported as PNG for Godot: {output_file}\n\n"
"This PNG has no compression, alpha channel support, and sRGB for Godot compatibility. "
"To use in Godot, import the PNG and adjust texture settings as needed."
)
except Exception as e:
QMessageBox.critical(None, "Error", f"Export failed: {str(e)}")
def createActions(self, window):
# Create only the export action in Tools > Scripts
action_export = window.createAction("export_godot_png", "Export Godot PNG", "tools/scripts")
action_export.triggered.connect(self.export_png)
# Register the plugin
Krita.instance().addExtension(ExportGodotPNG(Krita.instance()))
bl_info = {
"name": "Append Materials from Folder",
"author": "Grok",
"version": (1, 2),
"blender": (3, 0, 0),
"location": "View3D > Sidebar > Append Materials",
"description": "Select a folder and append all materials from .blend files recursively",
"category": "Import-Export",
}
import bpy
import os
from bpy.types import Operator, Panel, PropertyGroup
from bpy.props import StringProperty, PointerProperty
class AppendMaterialsProperties(PropertyGroup):
folder_path: StringProperty(
name="Folder Path",
description="Path to the folder containing .blend files",
default="",
maxlen=1024,
subtype='DIR_PATH'
)
class APPEND_OT_materials_from_folder(Operator):
bl_idname = "append.materials_from_folder"
bl_label = "Append Materials from Folder"
bl_options = {'REGISTER', 'UNDO'}
bl_description = "Append all materials from .blend files in the selected folder and subfolders"
def execute(self, context):
props = context.scene.append_materials_props
folder_path = props.folder_path
# Normalize path to avoid issues with slashes
folder_path = os.path.normpath(bpy.path.abspath(folder_path))
if not folder_path or not os.path.isdir(folder_path):
self.report({'ERROR'}, f"Invalid or no folder selected: {folder_path}")
return {'CANCELLED'}
self.report({'INFO'}, f"Scanning folder: {folder_path}")
blend_files_found = 0
materials_appended = 0
errors = []
# Walk recursively through the folder
for root, dirs, files in os.walk(folder_path):
self.report({'INFO'}, f"Checking folder: {root}")
for file in files:
if file.lower().endswith('.blend'):
blend_files_found += 1
blend_path = os.path.join(root, file)
self.report({'INFO'}, f"Found .blend file: {blend_path}")
try:
# Open the .blend file to inspect materials
with bpy.data.libraries.load(blend_path, link=False) as (data_from, data_to):
if data_from.materials:
data_to.materials = data_from.materials
materials_appended += len(data_from.materials)
self.report({'INFO'}, f"Appended {len(data_from.materials)} materials from: {blend_path}")
else:
self.report({'WARNING'}, f"No materials found in: {blend_path}")
except Exception as e:
errors.append(f"Failed to process {blend_path}: {str(e)}")
self.report({'WARNING'}, f"Error in {blend_path}: {str(e)}")
# Final report
if blend_files_found == 0:
self.report({'WARNING'}, f"No .blend files found in {folder_path} or its subfolders!")
else:
self.report({'INFO'}, f"Found {blend_files_found} .blend files, appended {materials_appended} materials.")
if errors:
self.report({'WARNING'}, f"Encountered {len(errors)} errors: {'; '.join(errors)}")
return {'FINISHED'}
class VIEW3D_PT_append_materials(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "Append Materials"
bl_label = "Append Materials from Folder"
def draw(self, context):
layout = self.layout
props = context.scene.append_materials_props
layout.prop(props, "folder_path")
layout.operator("append.materials_from_folder", text="Append Materials")
def register():
bpy.utils.register_class(AppendMaterialsProperties)
bpy.utils.register_class(APPEND_OT_materials_from_folder)
bpy.utils.register_class(VIEW3D_PT_append_materials)
bpy.types.Scene.append_materials_props = PointerProperty(type=AppendMaterialsProperties)
def unregister():
bpy.utils.unregister_class(VIEW3D_PT_append_materials)
bpy.utils.unregister_class(APPEND_OT_materials_from_folder)
bpy.utils.unregister_class(AppendMaterialsProperties)
del bpy.types.Scene.append_materials_props
if __name__ == "__main__":
register()
import subprocess
import sys
import os
import shutil
import importlib.util
import re
import concurrent.futures
from typing import List, Tuple, Set
class ModuleManager:
def __init__(self):
self.modules: Set[str] = set()
self.pip_path = self._get_pip_path()
def _get_pip_path(self) -> str:
possible_path = os.path.join(sys.exec_prefix, "Scripts", "pip.exe")
return shutil.which("pip") or (possible_path if os.path.exists(possible_path) else None)
def extract_imports_from_file(self, file_path: str) -> List[Tuple[str, str]]:
imports = []
try:
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
# Detect 'import module'
import_match = re.match(r'^\s*import\s+([a-zA-Z0-9_]+)(\s+as\s+.*)?$', line)
if import_match:
module = import_match.group(1)
imports.append((module, line.strip()))
continue
# Detect 'from module import ...'
from_match = re.match(r'^\s*from\s+([a-zA-Z0-9_]+)\s+import\s+.*$', line)
if from_match:
module = from_match.group(1)
imports.append((module, line.strip()))
except FileNotFoundError:
print(f"❌ Fișierul {file_path} nu a fost găsit.")
except Exception as e:
print(f"❌ Eroare la citirea fișierului {file_path}: {e}")
return imports
def scan_directory_for_py_files(self, directory: str = '.') -> List[str]:
py_files = []
for root, _, files in os.walk(directory):
for file in files:
if file.endswith('.py'):
py_files.append(os.path.join(root, file))
return py_files
def collect_unique_modules(self, directory: str = '.') -> None:
py_files = self.scan_directory_for_py_files(directory)
all_imports = []
with concurrent.futures.ThreadPoolExecutor() as executor:
future_to_file = {executor.submit(self.extract_imports_from_file, file_path): file_path for file_path in py_files}
for future in concurrent.futures.as_completed(future_to_file):
imports = future.result()
all_imports.extend(imports)
for module, _ in all_imports:
self.modules.add(module)
def is_module_installed(self, module: str) -> bool:
return importlib.util.find_spec(module) is not None
def run_pip_install(self, module: str) -> bool:
if not self.pip_path:
print(f"❌ Nu am găsit pip pentru {module}.")
return False
try:
subprocess.check_call([self.pip_path, "install", module])
print(f"✅ Pachetul {module} a fost instalat cu succes.")
return True
except subprocess.CalledProcessError as e:
print(f"❌ Eroare la instalarea pachetului {module}: {e}")
return False
def check_and_install_modules(self) -> None:
def process_module(module):
print(f"\n🔎 Verific dacă {module} este instalat...")
if self.is_module_installed(module):
print(f"✅ {module} este deja instalat.")
else:
print(f"📦 Instalez {module}...")
self.run_pip_install(module)
# Re-verifică după instalare
if self.is_module_installed(module):
print(f"✅ {module} funcționează acum.")
else:
print(f"❌ {module} nu funcționează după instalare.")
with concurrent.futures.ThreadPoolExecutor() as executor:
executor.map(process_module, self.modules)
def main():
print("🔍 Verific pip...")
manager = ModuleManager()
if manager.pip_path:
print(f"✅ Pip este disponibil la: {manager.pip_path}")
else:
print("⚠️ Pip nu este disponibil.")
return
directory = sys.argv[1] if len(sys.argv) > 1 else '.'
print(f"\n📜 Scanez directorul {directory} pentru fișiere .py...")
manager.collect_unique_modules(directory)
if not manager.modules:
print("⚠️ Nu s-au găsit module în importuri.")
return
print(f"\nModule unice detectate: {', '.join(manager.modules)}")
manager.check_and_install_modules()
if __name__ == "__main__":
main()
python catafest_build_package_001.py
🔍 Verificare module standard...
[✓] Modul standard 'json' este disponibil.
[✓] Modul standard 'subprocess' este disponibil.
[✓] Modul standard 'platform' este disponibil.
[✓] Modul standard 'datetime' este disponibil.
[✓] Modul standard 'os' este disponibil.
[✓] Modul standard 'sys' este disponibil.
📦 Verificare și instalare module pip...
[✓] Modulul 'PyQt6' este deja instalat.
[✓] Modulul 'build' este deja instalat.
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
- setuptools
- wheel
...
import torch
import torch.nn as nn
import numpy as np
data = np.array([
[1800.5, 1810.0, 1795.0, 1000, 1805.2],
[1805.2, 1815.0, 1800.0, 1200, 1812.8],
[1812.8, 1820.0, 1808.0, 1100, 1810.5],
[1810.5, 1818.0, 1805.0, 1300, 1825.0],
[1825.0, 1830.0, 1815.0, 1400, 1820.3],
[1820.3, 1828.0, 1810.0, 1250, 1835.7]
])
X, y = torch.tensor(data[:, :4], dtype=torch.float32), torch.tensor(data[:, 4], dtype=torch.float32)
model = nn.Sequential(nn.Linear(4, 6), nn.ReLU(), nn.Linear(6, 4), nn.ReLU(), nn.Linear(4, 1))
optimizer = torch.optim.Adam(model.parameters())
loss_fn = nn.MSELoss()
for _ in range(3000):
optimizer.zero_grad()
y_pred = model(X).squeeze()
loss = loss_fn(y_pred, y)
loss.backward()
optimizer.step()
prediction = model(torch.tensor([[1830.0, 1840.0, 1825.0, 1150]], dtype=torch.float32))
print("Predicted XAU/USD closing price:", round(prediction.item(), 2))
python torch_001.py
Predicted XAU/USD closing price: 1819.57
import tensorflow as tf
import numpy as np
data = np.array([
[1800.5, 1810.0, 1795.0, 1000, 1805.2],
[1805.2, 1815.0, 1800.0, 1200, 1812.8],
[1812.8, 1820.0, 1808.0, 1100, 1810.5],
[1810.5, 1818.0, 1805.0, 1300, 1825.0],
[1825.0, 1830.0, 1815.0, 1400, 1820.3],
[1820.3, 1828.0, 1810.0, 1250, 1835.7]
])
X, y = data[:, :4], data[:, 4]
model = tf.keras.Sequential([
tf.keras.layers.Dense(6, activation='relu', input_shape=(4,)),
tf.keras.layers.Dense(4, activation='relu'),
tf.keras.layers.Dense(1)
])
model.compile(optimizer='adam', loss='mse')
model.fit(X, y, epochs=3000, verbose=0)
prediction = model.predict(np.array([[1830.0, 1840.0, 1825.0, 1150]]))
print("Predicted XAU/USD closing price:", round(prediction[0][0], 2))
python tf_001.py
2025-08-30 21:11:13.966066: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
C:\Python313\Lib\site-packages\google\protobuf\runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/attr_value.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
...
Predicted XAU/USD closing price: 2.9
from sklearn.neural_network import MLPRegressor
import numpy as np
data = np.array([
[1800.5, 1810.0, 1795.0, 1000, 1805.2],
[1805.2, 1815.0, 1800.0, 1200, 1812.8],
[1812.8, 1820.0, 1808.0, 1100, 1810.5],
[1810.5, 1818.0, 1805.0, 1300, 1825.0],
[1825.0, 1830.0, 1815.0, 1400, 1820.3],
[1820.3, 1828.0, 1810.0, 1250, 1835.7]
])
X, y = data[:, :4], data[:, 4]
model = MLPRegressor(hidden_layer_sizes=(6, 4), max_iter=3000)
model.fit(X, y)
prediction = model.predict([[1830.0, 1840.0, 1825.0, 1150]])
print("Predicted XAU/USD closing price:", round(prediction[0], 2))
import os
import subprocess
from PyQt6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QPushButton,
QListWidget, QMessageBox
)
# fisier download : yt-dlp.exe -vU https://www.youtube.com/watch?v=xxxxxx -f bestvideo*+bestaudio/best
FOLDER_PATH = r"D:\Software"
class FFmpegMerger(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Combinare Video + Audio cu FFmpeg")
self.resize(600, 400)
self.layout = QVBoxLayout()
self.file_list = QListWidget()
self.process_button = QPushButton("Prelucrează în MP4")
self.layout.addWidget(self.file_list)
self.layout.addWidget(self.process_button)
self.setLayout(self.layout)
self.process_button.clicked.connect(self.process_files)
self.populate_file_list()
def populate_file_list(self):
files = os.listdir(FOLDER_PATH)
video_files = [f for f in files if f.endswith(".f401.mp4")]
audio_files = [f for f in files if f.endswith(".f251-9.webm")]
base_names = set(f.split(".f401.mp4")[0] for f in video_files)
candidates = []
for base in base_names:
audio_name = f"{base}.f251-9.webm"
output_name = f"{base}.mp4"
if audio_name in audio_files and output_name not in files:
candidates.append(base)
for name in candidates:
self.file_list.addItem(name)
def process_files(self):
for i in range(self.file_list.count()):
base = self.file_list.item(i).text()
video_path = os.path.join(FOLDER_PATH, f"{base}.f401.mp4")
audio_path = os.path.join(FOLDER_PATH, f"{base}.f251-9.webm")
output_path = os.path.join(FOLDER_PATH, f"{base}.mp4")
cmd = [
"ffmpeg",
"-i", video_path,
"-i", audio_path,
"-c:v", "copy",
"-c:a", "aac",
"-strict", "experimental",
output_path
]
try:
subprocess.run(cmd, check=True)
except subprocess.CalledProcessError as e:
QMessageBox.critical(self, "Eroare", f"Eroare la procesarea {base}: {e}")
return
QMessageBox.information(self, "Succes", "Toate fișierele au fost prelucrate cu succes!")
if __name__ == "__main__":
app = QApplication([])
window = FFmpegMerger()
window.show()
app.exec()