pyside-live 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pyside-live
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Un reloaded/watcher ultra ligero y eficiente para desarrollo rápido con PySide/Qt en Python.
|
|
5
|
+
Project-URL: Homepage, https://github.com/tu-usuario/pyside-live
|
|
6
|
+
Author: Mauricio Ruiz
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: gui,hot-reload,live-reload,pyside,qt,watcher
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Requires-Dist: watchdog>=3.0.0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# PySide Live
|
|
24
|
+
|
|
25
|
+
Herramienta de línea de comandos ligera y eficiente para **Hot Reload / Live Reload** en desarrollo de aplicaciones de escritorio con PySide / Qt en Python.
|
|
26
|
+
|
|
27
|
+
## Instalación
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install pyside-live
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pyside-live"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Un reloaded/watcher ultra ligero y eficiente para desarrollo rápido con PySide/Qt en Python."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Mauricio Ruiz" }
|
|
12
|
+
]
|
|
13
|
+
license = { text = "MIT" }
|
|
14
|
+
keywords = ["pyside", "qt", "hot-reload", "live-reload", "gui", "watcher"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.8",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
]
|
|
27
|
+
requires-python = ">=3.8"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"watchdog>=3.0.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
pyside-live = "pyside_live.cli:main"
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/tu-usuario/pyside-live"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
import argparse
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from watchdog.observers import Observer
|
|
7
|
+
from watchdog.events import FileSystemEventHandler
|
|
8
|
+
|
|
9
|
+
EXCLUDE_DIRS = {
|
|
10
|
+
'.venv', 'venv', 'env', '__pycache__', '.git',
|
|
11
|
+
'build', 'dist', '.idea', '.vscode', '.pytest_cache'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
def get_python_interpreter(script_path: Path) -> str:
|
|
15
|
+
"""Busca un entorno virtual local o usa python3 del sistema."""
|
|
16
|
+
# Buscar .venv o venv en la ruta del script o sus padres
|
|
17
|
+
current = script_path.parent
|
|
18
|
+
for parent in [current, *current.parents]:
|
|
19
|
+
for venv_name in ('.venv', 'venv', 'env'):
|
|
20
|
+
venv_path = parent / venv_name
|
|
21
|
+
if venv_path.is_dir():
|
|
22
|
+
# Detectar estructura de binarios según el SO
|
|
23
|
+
if sys.platform == "win32":
|
|
24
|
+
python_bin = venv_path / "Scripts" / "python.exe"
|
|
25
|
+
else:
|
|
26
|
+
python_bin = venv_path / "bin" / "python"
|
|
27
|
+
|
|
28
|
+
if python_bin.exists():
|
|
29
|
+
return str(python_bin)
|
|
30
|
+
|
|
31
|
+
# Fallback al python del sistema
|
|
32
|
+
return "python3"
|
|
33
|
+
|
|
34
|
+
class PySideReloadHandler(FileSystemEventHandler):
|
|
35
|
+
def __init__(self, script_path, debounce_interval=0.4):
|
|
36
|
+
self.script_path = Path(script_path).resolve()
|
|
37
|
+
self.debounce_interval = debounce_interval
|
|
38
|
+
self.python_interpreter = get_python_interpreter(self.script_path)
|
|
39
|
+
self.process = None
|
|
40
|
+
self.last_restart = 0
|
|
41
|
+
self.start_process()
|
|
42
|
+
|
|
43
|
+
def start_process(self):
|
|
44
|
+
if self.process:
|
|
45
|
+
print("\n🔄 [pyside-live] Cambios detectados. Reiniciando ventana...")
|
|
46
|
+
self.process.terminate()
|
|
47
|
+
try:
|
|
48
|
+
self.process.wait(timeout=1.5)
|
|
49
|
+
except subprocess.TimeoutExpired:
|
|
50
|
+
self.process.kill()
|
|
51
|
+
|
|
52
|
+
self.process = subprocess.Popen([self.python_interpreter, str(self.script_path)])
|
|
53
|
+
|
|
54
|
+
def on_modified(self, event):
|
|
55
|
+
if event.is_directory:
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
file_path = Path(event.src_path)
|
|
59
|
+
|
|
60
|
+
if any(excluded in file_path.parts for excluded in EXCLUDE_DIRS):
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
if file_path.suffix in ('.py', '.ui', '.qml'):
|
|
64
|
+
current_time = time.time()
|
|
65
|
+
if (current_time - self.last_restart) > self.debounce_interval:
|
|
66
|
+
self.last_restart = current_time
|
|
67
|
+
self.start_process()
|
|
68
|
+
|
|
69
|
+
def main():
|
|
70
|
+
parser = argparse.ArgumentParser(
|
|
71
|
+
description="pyside-live: Recarga en caliente ligera para aplicaciones PySide/Qt."
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
"target",
|
|
75
|
+
help="Ruta al archivo .py principal de tu aplicación PySide."
|
|
76
|
+
)
|
|
77
|
+
args = parser.parse_args()
|
|
78
|
+
|
|
79
|
+
target_path = Path(args.target).resolve()
|
|
80
|
+
if not target_path.exists():
|
|
81
|
+
print(f"❌ Error: El archivo '{args.target}' no existe.")
|
|
82
|
+
sys.exit(1)
|
|
83
|
+
|
|
84
|
+
watch_dir = target_path.parent
|
|
85
|
+
event_handler = PySideReloadHandler(target_path)
|
|
86
|
+
|
|
87
|
+
print(f"🐍 Usando intérprete Python: {event_handler.python_interpreter}")
|
|
88
|
+
|
|
89
|
+
observer = Observer()
|
|
90
|
+
observer.schedule(event_handler, path=str(watch_dir), recursive=True)
|
|
91
|
+
observer.start()
|
|
92
|
+
|
|
93
|
+
print(f"🚀 [pyside-live] Vigilando cambios para: {target_path.name}")
|
|
94
|
+
print(f"📁 Directorio base: {watch_dir}")
|
|
95
|
+
print("💡 Presiona Ctrl+C para detener el proceso.\n")
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
while True:
|
|
99
|
+
time.sleep(0.5)
|
|
100
|
+
except KeyboardInterrupt:
|
|
101
|
+
print("\n🛑 [pyside-live] Deteniendo vigilante...")
|
|
102
|
+
observer.stop()
|
|
103
|
+
if event_handler.process:
|
|
104
|
+
event_handler.process.terminate()
|
|
105
|
+
observer.join()
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
main()
|