feat(backend): каркас — конфиг, движок БД, базовые модели и первая миграция
SQLAlchemy 2 async на asyncpg, Alembic, pydantic-settings. Деньги везде NUMERIC(24,10) с колонкой валюты рядом (db/base.py), postgres-enum'ы хранят значения, а не имена, чтобы база читалась так же, как API. Первая миграция: app_user, account, portfolio, instrument, sync_run, sync_job. metrics/refresh.py задаёт порядок пересборки metric_* и сериализует параллельные пересчёты advisory-локом на отдельном соединении: каждый шаг заменяет свою таблицу целиком, два одновременных прогона затёрли бы друг друга.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
[project]
|
||||
name = "fintracker"
|
||||
version = "0.1.0"
|
||||
description = "Personal finance + investment analytics: ZenMoney and brokers in one place"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"fastapi>=0.115",
|
||||
"uvicorn[standard]>=0.30",
|
||||
"sqlalchemy[asyncio]>=2.0.36",
|
||||
"asyncpg>=0.30",
|
||||
"alembic>=1.14",
|
||||
"pydantic[email]>=2.9",
|
||||
"pydantic-settings>=2.5",
|
||||
"httpx[socks]>=0.27",
|
||||
"pyjwt>=2.9",
|
||||
"pwdlib[argon2]>=0.2",
|
||||
"typer>=0.12",
|
||||
"apscheduler>=3.10,<4",
|
||||
"python-multipart>=0.0.12",
|
||||
"t-tech-investments>=1.51.0",
|
||||
"pyxirr>=0.10.8",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
fintracker = "fintracker.cli:app"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.3",
|
||||
"pytest-asyncio>=0.24",
|
||||
"pytest-postgresql>=6.1",
|
||||
"psycopg[binary]>=3.2",
|
||||
"ruff>=0.7",
|
||||
"pyright>=1.1.380",
|
||||
"respx>=0.21",
|
||||
]
|
||||
|
||||
# T-Invest SDK lives on T-Bank's own index (public PyPI copy is quarantined).
|
||||
[[tool.uv.index]]
|
||||
name = "tbank-invest"
|
||||
url = "https://opensource.tbank.ru/api/v4/projects/238/packages/pypi/simple"
|
||||
explicit = true
|
||||
|
||||
[tool.uv.sources]
|
||||
t-tech-investments = { index = "tbank-invest" }
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/fintracker"]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
src = ["src", "tests"]
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
|
||||
ignore = ["RUF001", "RUF002", "RUF003"] # cyrillic in strings/comments is intended
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/*" = ["E501"]
|
||||
"alembic/versions/*" = ["E501"]
|
||||
|
||||
[tool.pyright]
|
||||
venvPath = "."
|
||||
venv = ".venv"
|
||||
include = ["src", "tests"]
|
||||
extraPaths = ["src"]
|
||||
pythonVersion = "3.12"
|
||||
typeCheckingMode = "standard"
|
||||
reportMissingImports = "warning"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
pythonpath = ["src"]
|
||||
testpaths = ["tests"]
|
||||
asyncio_mode = "auto"
|
||||
asyncio_default_fixture_loop_scope = "session"
|
||||
asyncio_default_test_loop_scope = "session"
|
||||
Reference in New Issue
Block a user