otko/pyproject.toml
smillmorel f99b3a3efd build: add plotly to the GUI extra
Supplies the offline plotly.js bundle for the new canvas backend. The
GUI CI job now installs the gui extra so the Qt/WebEngine tests run
instead of being import-skipped.
2026-09-16 18:43:53 -04:00

148 lines
4.3 KiB
TOML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[build-system]
requires = ["hatchling>=1.24"]
build-backend = "hatchling.build"
[project]
name = "otko"
dynamic = ["version"]
description = "OTKO — a modern, SAP2000-style desktop GUI for OpenSeesPy."
readme = "README.md"
requires-python = ">=3.10"
license = { file = "LICENSE" }
authors = [{ name = "Ozan" }]
keywords = ["opensees", "openseespy", "structural", "earthquake", "fem", "gui"]
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
]
dependencies = [
# ── Headless base (core + services, no Qt required) ──────────────────────
"pydantic>=2.5",
"numpy>=1.26",
"h5py>=3.10",
"openseespy==3.8.0.0",
"openseespywin==3.8.0.0 ; sys_platform == 'win32'",
]
[project.optional-dependencies]
# ── GUI / visualization stack (desktop app only) ──────────────────────────
# Install with: pip install -e ".[gui]" (desktop)
# pip install -e ".[gui,dev]" (desktop + dev tools)
# Headless / web reuse: pip install -e . (base only, no Qt pulled in)
gui = [
"PySide6>=6.6",
"pyvista>=0.43",
"pyvistaqt>=0.11",
"vtk>=9.3",
"pyqtgraph>=0.13",
"imageio[ffmpeg]>=2.34",
"plotly>=5.18",
]
dev = [
"pytest>=7.4",
"pytest-qt>=4.2",
"pytest-cov>=4.1",
"ruff>=0.4",
"mypy>=1.8",
"pre-commit>=3.6",
"hatch>=1.9",
"tomli>=2.0; python_version < '3.11'",
]
docs = [
"sphinx>=7.2",
"myst-parser>=2.0",
"furo>=2024.1.29",
]
[project.scripts]
otko = "otko.__main__:main"
[project.urls]
Homepage = "https://github.com/ogunc/otko"
Issues = "https://github.com/ogunc/otko/issues"
[tool.hatch.build.targets.wheel]
packages = ["src/otko"]
[tool.hatch.version]
path = "src/otko/_const.py"
# ─────────── Ruff ───────────
[tool.ruff]
line-length = 100
target-version = "py310"
src = ["src", "tests"]
[tool.ruff.lint]
select = [
"E", "W", # pycodestyle
"F", # pyflakes
"I", # isort
"B", # bugbear
"UP", # pyupgrade
"N", # pep8-naming
"SIM", # simplify
"RUF", # ruff-specific
]
ignore = [
"E501", # line-length handled by the formatter
"RUF001", # ambiguous unicode: engineering notation (×, ≈, ²) is deliberate
"RUF002",
"RUF003",
]
[tool.ruff.lint.per-file-ignores]
# Engineering symbols (A, I, L, E, P) and `importorskip`-then-import blocks
# are normal in tests.
"tests/**" = ["E402", "E741", "N802", "N806", "N815"]
# Qt requires camelCase signal names and PascalCase event overrides.
"src/otko/views/**" = ["N802", "N815"]
"src/otko/viewmodels/**" = ["N815"]
# Material fields mirror the OpenSees parameter names verbatim (cR1, epsU, ...).
"src/otko/core/materials/__init__.py" = ["N815"]
# Engineering symbols in numeric code: L (length), Iz/Iy (second moments).
"src/otko/services/section_properties.py" = ["N806"]
"src/otko/views/canvas3d/model_renderer.py" = ["N802", "N806", "N815"]
[tool.ruff.format]
quote-style = "double"
# ─────────── Mypy ───────────
[tool.mypy]
python_version = "3.10"
warn_unused_configs = true
plugins = []
[[tool.mypy.overrides]]
module = ["otko.core.*", "otko.services.*", "otko.viewmodels.*"]
strict = true
[[tool.mypy.overrides]]
module = ["openseespy.*", "pyvista.*", "pyvistaqt.*", "vtk.*", "pyqtgraph.*"]
ignore_missing_imports = true
# ─────────── Pytest ───────────
[tool.pytest.ini_options]
minversion = "7.0"
addopts = "-ra -q --strict-markers"
testpaths = ["tests"]
markers = [
"gui: marks tests that require a Qt event loop",
"slow: marks slow tests (deselect with '-m \"not slow\"')",
]
[tool.coverage.run]
branch = true
source = ["src/otko"]
omit = ["src/otko/views/*"] # GUI excluded from coverage targets
[tool.coverage.report]
exclude_lines = ["if TYPE_CHECKING:", "raise NotImplementedError"]
# Conservative floor for the headless suite; raise deliberately with evidence.
fail_under = 50