Files
noteflow/pyproject.toml
Travis Vasceannie d8090a98e8
Some checks failed
CI / test-typescript (push) Has been cancelled
CI / test-rust (push) Has been cancelled
CI / test-python (push) Has been cancelled
ci/cd fixes
2026-01-26 00:28:15 +00:00

324 lines
8.9 KiB
TOML

[project]
name = "noteflow"
version = "0.1.0"
description = "Intelligent Meeting Notetaker - Local-first capture + navigable recall + evidence-linked summaries"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
# Core
"pydantic>=2.0",
# Spike 3: ASR
"faster-whisper>=1.0",
# Spike 4: Encryption
"keyring>=25.0",
"cryptography>=42.0",
# gRPC Client-Server
"grpcio>=1.60",
"protobuf>=4.25",
# Database (async PostgreSQL + pgvector)
"sqlalchemy[asyncio]>=2.0",
"asyncpg>=0.29",
"pgvector>=0.3",
"alembic>=1.13",
# Settings
"pydantic-settings>=2.0",
"psutil>=7.1.3",
# HTTP client for webhooks and integrations
"httpx>=0.27",
"authlib>=1.6.6",
"rich>=14.2.0",
# Structured logging
"structlog>=24.0",
"sounddevice>=0.5.3",
"spacy>=3.8.11",
"openai-whisper>=20250625",
"langgraph>=1.0.6",
"langgraph-checkpoint-postgres>=3.0.3",
"psycopg>=3.3.2",
]
[project.optional-dependencies]
audio = [
"sounddevice>=0.4.6",
"numpy>=1.26",
]
dev = [
"pytest>=8.0",
"pytest-cov>=4.0",
"pytest-asyncio>=0.23",
"pytest-httpx>=0.36.0",
"pytest-benchmark>=5.2.3",
"pytest-xdist>=3.8.0",
"mypy>=1.8",
"ruff>=0.3",
"basedpyright>=1.18",
"grpcio-tools>=1.60",
"pyrefly>=0.46.1",
"sourcery; sys_platform == 'darwin'",
"types-grpcio==1.0.0.20251001",
"types-psutil>=7.2.0.20251228",
"testcontainers[postgres]>=4.0",
]
triggers = [
"pywinctl>=0.3",
]
summarization = [
"ollama>=0.6.1",
"openai>=2.13.0",
"anthropic>=0.75.0",
]
diarization = [
"pyannote.audio>=3.3",
"diart>=0.9.2",
"torch>=2.0",
]
pdf = [
"weasyprint>=67.0",
]
ner = [
"spacy>=3.8.11",
]
ner-gliner = [
"gliner>=0.2.24",
]
calendar = [
"google-api-python-client>=2.100",
"google-auth>=2.23",
"google-auth-oauthlib>=1.1",
]
rocm = [
# ROCm GPU support for AMD GPUs
# Requires PyTorch with ROCm support (install separately)
# pip install torch --index-url https://download.pytorch.org/whl/rocm6.2
]
rocm-ctranslate2 = [
# Optional: CTranslate2-ROCm for faster inference
# Install manually: pip install git+https://github.com/arlo-phoenix/CTranslate2-rocm.git
"faster-whisper>=1.0",
]
observability = [
"opentelemetry-api>=1.28",
"opentelemetry-sdk>=1.28",
"opentelemetry-instrumentation-grpc>=0.49b",
"opentelemetry-exporter-otlp>=1.28",
]
optional = [
# Audio
"sounddevice>=0.4.6",
"numpy>=1.26",
# Triggers
"pywinctl>=0.3",
# Summarization
"ollama>=0.6.1",
"openai>=2.13.0",
"anthropic>=0.75.0",
# Diarization
"pyannote.audio>=3.3",
"diart>=0.9.2",
"torch>=2.0",
# PDF export
"weasyprint>=67.0",
# NER (spaCy backend)
"spacy>=3.8.11",
# NER (GLiNER backend)
"gliner>=0.2.24",
# Calendar
"google-api-python-client>=2.100",
"google-auth>=2.23",
"google-auth-oauthlib>=1.1",
# Observability
"opentelemetry-api>=1.28",
"opentelemetry-sdk>=1.28",
"opentelemetry-instrumentation-grpc>=0.49b",
"opentelemetry-exporter-otlp>=1.28",
]
all = [
"noteflow[audio,dev,triggers,summarization,diarization,pdf,ner,ner-gliner,calendar,observability]",
]
ollama = [
"anthropic>=0.75.0",
"openai>=2.13.0",
"pywinctl>=0.4.1",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/noteflow", "spikes"]
[tool.ruff]
line-length = 100
target-version = "py312"
extend-exclude = ["*_pb2.py", "*_pb2_grpc.py", "*_pb2.pyi", ".venv"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
"SIM", # flake8-simplify
"RUF", # Ruff-specific rules
]
ignore = [
"E501", # Line length handled by formatter
]
[tool.ruff.lint.per-file-ignores]
"**/grpc/service.py" = ["TC002", "TC003"] # numpy/Iterator used at runtime
"tests/quality/*.py" = ["SIM102"] # AST pattern matching needs nested conditionals
[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_configs = true
exclude = [".venv", ".*_pb2\\.py$", ".*_pb2_grpc\\.py$", ".*_pb2\\.pyi$"]
plugins = ["sqlalchemy.ext.mypy.plugin"]
[[tool.mypy.overrides]]
module = [
"diart.*",
"gliner.*",
"pyannote.*",
"faster_whisper.*",
"sounddevice.*",
"pgvector.*",
"asyncpg.*",
"noteflow.grpc.proto.noteflow_pb2",
"noteflow.grpc.proto.noteflow_pb2_grpc",
]
ignore_missing_imports = true
ignore_errors = true
[[tool.mypy.overrides]]
module = ["noteflow.infrastructure.persistence.models.*"]
# SQLAlchemy 2.0 declarative models use ClassVar for __tablename__ and __table_args__
# The mypy plugin handles this but has edge cases with some patterns
disable_error_code = ["misc"]
[[tool.mypy.overrides]]
module = ["noteflow.grpc._mixins.*", "noteflow.grpc._client_mixins.*"]
# gRPC ServicerContext is a generic type but the type parameters are complex
# and rarely needed in practice. Mixin protocols use structural typing.
# attr-defined: Streaming mixin methods are implemented in service.py, not the protocol
# no-any-return: Some methods return proto-generated types that resolve to Any
# arg-type: Proto enums accept ints at runtime; generated stubs are overly strict
# assignment: Proto response fields accept int values for enum types
disable_error_code = ["type-arg", "attr-defined", "no-any-return", "arg-type", "assignment"]
[[tool.mypy.overrides]]
module = ["noteflow.grpc.client"]
# Client mixin composition uses Protocol-based typing that mypy struggles with
# The "Invalid self argument" errors are false positives for correctly typed mixins
disable_error_code = ["misc", "no-untyped-call"]
[[tool.mypy.overrides]]
module = ["noteflow.grpc.service"]
# ServicerContext generic type parameters are complex (request/response types)
# and not needed for runtime behavior. The service works with ServicerContext as-is.
disable_error_code = ["type-arg"]
[[tool.mypy.overrides]]
module = ["noteflow.grpc.server"]
# add_NoteFlowServiceServicer_to_server is generated by grpc_tools.protoc
# and lacks type annotations in the generated stubs
disable_error_code = ["no-untyped-call"]
[[tool.mypy.overrides]]
module = ["noteflow.infrastructure.persistence.database"]
# asyncpg is installed but lacks type stubs or py.typed marker
disable_error_code = ["import-untyped"]
[tool.basedpyright]
pythonVersion = "3.12"
typeCheckingMode = "strict"
extraPaths = ["scripts", "src", "google"]
stubPath = "typings"
reportMissingTypeStubs = false
reportUnknownMemberType = true
reportUnknownArgumentType = true
reportUnknownVariableType = true
reportArgumentType = false # proto enums accept ints at runtime
reportIncompatibleVariableOverride = false # SQLAlchemy __table_args__
reportAttributeAccessIssue = false # SQLAlchemy mapped column assignments
reportMissingImports = "warning" # Optional deps (audio, summarization, triggers, etc.) may not be installed
exclude = [
"**/proto/*_pb2*.py",
"**/proto/*_pb2*.pyi",
"**/node_modules",
"**/node_modules/**",
"client",
"client/**",
".venv",
".venv/",
".venv/**",
".benchmarks",
".benchmarks/**",
".hygeine",
".hygeine/**",
"e2e-native",
"e2e-native/**",
".git",
".git/**",
"**/__pycache__",
"**/*.pyc",
"**/dist",
"**/build",
"workspaces",
]
venvPath = "."
venv = ".venv"
[tool.pyrefly]
python-version = "3.12"
python-interpreter-path = ".venv/bin/python"
site-package-path = [".venv/lib/python3.12/site-packages"]
search-path = [".", "src", "tests", "typings"]
project-includes = ["src", "tests"]
project-excludes = ["**/proto/*_pb2*.py", "**/proto/*_pb2*.pyi"]
ignore-missing-imports = []
replace-imports-with-any = []
ignore-errors-in-generated-code = true
untyped-def-behavior = "check-and-infer-return-type"
use-ignore-files = true
permissive-ignores = false
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "-v --tb=short"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
markers = [
"slow: marks tests as slow (model loading)",
"integration: marks tests requiring external services",
"stress: marks stress/concurrency tests",
]
filterwarnings = [
"ignore:The @wait_container_is_ready decorator is deprecated.*:DeprecationWarning:testcontainers.core.waiting_utils",
"ignore:invalid escape sequence '\\\\s':SyntaxWarning:pyannote",
]
[dependency-groups]
dev = [
"basedpyright>=1.36.1",
"gliner>=0.2.24",
"protobuf>=6.33.2",
"pyrefly>=0.46.1",
"pytest-benchmark>=5.2.3",
"pytest-httpx>=0.36.0",
"pytest-xdist>=3.8.0",
"ruff>=0.14.9",
"sourcery; sys_platform == 'darwin'",
"spacy>=3.8.11",
"types-grpcio==1.0.0.20251001",
"watchfiles>=1.1.1",
]