[S0-T02] Set up packages/engine with Poetry, Ruff, mypy strict, pytest

This commit is contained in:
Manohar Gupta 2026-05-07 02:14:45 +05:30
parent 7d7b0fb797
commit 8b61c03d3c
6 changed files with 119 additions and 0 deletions

37
packages/engine/README.md Normal file
View file

@ -0,0 +1,37 @@
# remodel-engine
UI-agnostic Python calculation library for hybrid RE (Solar + Wind + BESS) project finance.
## Setup
```bash
poetry install
```
## Common commands
```bash
poetry run pytest # run tests with coverage
poetry run ruff check . # lint
poetry run mypy src/ # type-check
poetry run remodel --help # CLI (after implementation)
```
## Package layout
```
src/remodel_engine/
├── schemas/ Pydantic models (single source of truth)
├── catalog/ Default values, CostItem catalog, profiles
├── generation/ solar.py, wind.py, bess_state.py
├── dispatch/ hybrid_rtc.py, mcp_settlement.py
├── commercial/ ppa.py, dsm.py, charges.py, losses.py
├── capex/ cost_items.py, phasing.py, idc.py
├── financial/ pnl.py, cfs.py, bs.py, depreciation.py, tax.py
├── debt/ sizing.py, sculpting.py, schedule.py, compliance.py
├── irr/ metrics.py
├── solver/ tariff.py
├── scenarios/ runner.py, sweep.py
├── io/ parquet_io.py, excel_export.py
└── cli.py
```

View file

@ -0,0 +1,68 @@
[tool.poetry]
name = "remodel-engine"
version = "0.1.0"
description = "RE project finance calculation engine for hybrid solar/wind/BESS projects"
authors = ["Manohar <manohar6839@gmail.com>"]
readme = "README.md"
packages = [{include = "remodel_engine", from = "src"}]
[tool.poetry.dependencies]
python = "^3.12"
pydantic = "^2.7"
numpy = "^2.0"
pandas = "^2.2"
scipy = ">=1.13"
numpy-financial = "^1.0"
pyarrow = ">=19.0"
openpyxl = "^3.1"
typer = "^0.12"
[tool.poetry.group.dev.dependencies]
ruff = "^0.4"
mypy = "^1.10"
pytest = "^8.2"
pytest-cov = "^5.0"
pre-commit = "^3.7"
pandas-stubs = "^2.2"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.ruff]
target-version = "py312"
line-length = 100
src = ["src", "tests"]
[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "B", "SIM", "ANN", "RUF"]
ignore = ["ANN101", "ANN102", "ANN401"]
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["ANN"]
[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_any_generics = true
check_untyped_defs = true
no_implicit_reexport = true
files = ["src"]
[[tool.mypy.overrides]]
module = ["scipy.*", "numpy_financial.*"]
ignore_missing_imports = true
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=remodel_engine --cov-report=term-missing --cov-fail-under=85"
[tool.coverage.run]
source = ["remodel_engine"]
branch = true
[tool.coverage.report]
exclude_lines = ["pragma: no cover", "if TYPE_CHECKING:"]

View file

@ -0,0 +1,3 @@
"""REmodel calculation engine for hybrid RE project finance."""
__version__ = "0.1.0"

View file

@ -0,0 +1,11 @@
from remodel_engine import __version__
def test_version_is_string() -> None:
assert isinstance(__version__, str)
def test_version_format() -> None:
parts = __version__.split(".")
assert len(parts) == 3
assert all(p.isdigit() for p in parts)