Files
AR-VMS-Seaman/pyproject.toml
T
alro65 813476c8db sprint-1: Studio shell PySide6 + wizard 8 pasos
Sprint 1 entrega el shell del Studio operativo. Para correrlo:
    uv run vms-studio

Componentes:

vmssailor/studio/theme.py
- Aplica design tokens del Sprint 0 (paleta Deep Ocean) a PySide6
- QSS global completo + QPalette + fuentes Inter/Space Grotesk/JetBrains Mono

vmssailor/studio/app.py
- StudioApp (QApplication) con tema, logo, version
- run_studio() entry point

vmssailor/studio/main_window.py
- Layout: topbar / sidebar / canvas central / statusbar
- Menus: Proyecto (Nuevo wizard, Abrir, Guardar, Guardar como, Salir),
  Edicion/Vista (stubs Sprint 2), Ayuda
- Operaciones funcionales: New from wizard, Open .vmsproj, Save, Save As,
  Validate (cross-entity), Compile (placeholder)
- Reloj live + statusbar con stats del proyecto

vmssailor/studio/widgets/system_sidebar.py
- Sidebar dinamico que muestra wizard steps + sistemas habilitados + disponibles
- Lee catalogo maestro y proyecto activo
- Senial systemActivated(SystemId) al doble-click

vmssailor/studio/widgets/vessel_canvas.py
- QGraphicsView central con grilla naval (1m por celda)
- Renderiza silueta del buque en planta + mamparos + equipos
- ship_to_scene() transformacion canonica naval -> escena
- Centerline + Pp axis marcados
- Ruler de eslora con marcas cada 5m
- Zoom con wheel + scroll-pan, label de zoom% en header

vmssailor/studio/wizard/ - QWizard 8 pasos
- step_01_vessel_type: tipo + subtipo + nombre proyecto + cliente
- step_02_template: selector con biblioteca curada (Sunseeker, Ferretti, blank)
- step_03_dimensions: LOA/manga/calado/mamparos con pre-fill de plantilla
- step_04_systems: checkboxes agrupados por categoria con pre-select por default_for
- step_57_placeholder: stubs visuales para Sprint 2 (pasos 5, 6, 7)
- step_08_confirm: resumen HTML completo del proyecto a crear
- VesselWizard.build_project() construye un Project valido

Tests (tests/studio/, 11 nuevos, total 110/110):
- pytest-qt offscreen
- Smoke tests del MainWindow, wizard, canvas, sidebar
- test_ship_to_scene_mapping (transformacion naval->escena)

Stack agregado:
- PySide6 6.11.1
- pytest-qt 4.5.0

Decisiones autonomas:
- QFont.setWeight requiere QFont.Weight enum en PySide6 6.11 (no int)
- QFrame.Shape.NoFrame (no QListWidget.NoFrame) para PySide6 6.11
- Pasos 5-7 quedan placeholders explicitos: Sprint 2 implementa rule engine
- Wizard crea Project sin equipment todavia (Sprint 2 los agrega)

Criterios de aceptacion Sprint 1:
- uv run vms-studio: abre ventana operativa
- 110/110 pytest verde
- ruff clean
- Smoke offscreen: MainWindow + Wizard + Canvas + Sidebar OK

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 07:52:31 -04:00

137 lines
3.1 KiB
TOML

[project]
name = "vmssailor"
version = "0.1.0.dev0"
description = "VMS-Sailor — Vessel Management System integrado (IAS) para buques 30-40m. Studio + Runtime + Mobile + Firmware."
readme = "README.md"
requires-python = ">=3.11,<3.12"
license = { text = "Proprietary — Álvaro" }
authors = [
{ name = "Álvaro (Aerom)" }
]
keywords = ["marine", "vessel-management", "ias", "automation", "nmea2000", "modbus", "ecdis"]
dependencies = [
"pydantic>=2.5,<3.0",
"pyyaml>=6.0",
"python-dateutil>=2.8",
]
[project.optional-dependencies]
studio = [
"PySide6>=6.6,<7.0",
]
dev = [
"pytest>=7.4",
"pytest-cov>=4.1",
"pytest-asyncio>=0.23",
"pytest-qt>=4.4",
"ruff>=0.4.0",
"mypy>=1.10",
"types-PyYAML",
"types-python-dateutil",
"PySide6>=6.6,<7.0",
]
[project.scripts]
vms-validate-library = "vmssailor.tools.validate_library:main"
vms-generate-test-project = "vmssailor.tools.generate_test_project:main"
vms-studio = "vmssailor.studio.app:run_studio"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["vmssailor"]
# ---------- ruff ----------
[tool.ruff]
line-length = 100
target-version = "py311"
extend-exclude = ["projects", "firmware", "mobile", "docs/mockups"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # bugbear
"C4", # comprehensions
"UP", # pyupgrade
"SIM", # simplify
"RUF", # ruff-specific
]
ignore = [
"E501", # handled by formatter
]
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["B011"]
"tools/**" = ["E402"]
"vmssailor/studio/**" = ["RUF001", "E402"] # caracteres tipograficos intencionales en UI ES; imports diferidos de Signal/Property en QWizard
[tool.ruff.format]
quote-style = "double"
# ---------- mypy ----------
[tool.mypy]
python_version = "3.11"
strict = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_return_any = true
warn_unreachable = true
exclude = ["^build/", "^dist/", "^projects/", "^firmware/", "^mobile/", "^docs/"]
[[tool.mypy.overrides]]
module = ["tests.*", "tools.*"]
disallow_untyped_defs = false
[[tool.mypy.overrides]]
module = ["yaml.*", "dateutil.*"]
ignore_missing_imports = true
# ---------- pytest ----------
[tool.pytest.ini_options]
minversion = "7.4"
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"--strict-config",
"--tb=short",
]
markers = [
"slow: marks tests as slow",
"integration: cross-module integration tests",
]
asyncio_mode = "auto"
[tool.coverage.run]
source = ["vmssailor"]
omit = [
"vmssailor/studio/*",
"vmssailor/runtime/*",
"vmssailor/__init__.py",
"vmssailor/version.py",
]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
]
fail_under = 80
show_missing = true