[project] name = "berlin-picnic-api" version = "0.1.0" description = "API for finding perfect picnic zones in Berlin based on personality" authors = [ { name = "Your Name", email = "your.email@example.com" } ] readme = "README.md" requires-python = ">=3.11" license = { text = "MIT" } keywords = ["fastapi", "berlin", "picnic", "zones", "personality"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] dependencies = [ "fastapi>=0.104.0", "uvicorn[standard]>=0.24.0", "pydantic>=2.5.0", "pydantic-settings>=2.1.0", "pandas>=2.1.0", "shapely>=2.0.0", # Modern geometric operations "geojson>=3.1.0", # GeoJSON handling "geopy>=2.4.0", # Geocoding and distance calculations "haversine>=2.8.0", # Fast distance calculations "requests>=2.31.0", "httpx>=0.25.0", "python-multipart>=0.0.6", "python-jose[cryptography]>=3.3.0", "redis>=5.0.0", "aiofiles>=23.2.0", "openpyxl>=3.1.5", "tqdm>=4.67.1", "rtree>=1.4.0", ] [project.optional-dependencies] dev = [ "pytest>=7.4.0", "pytest-asyncio>=0.21.0", "pytest-cov>=4.1.0", "httpx>=0.25.0", # For testing "ruff>=0.1.0", "mypy>=1.7.0", "pre-commit>=3.5.0", "black>=23.11.0", # Backup formatter ] test = [ "pytest>=7.4.0", "pytest-asyncio>=0.21.0", "pytest-cov>=4.1.0", "httpx>=0.25.0", ] [project.urls] Homepage = "https://github.com/yourusername/berlin-picnic-api" Repository = "https://github.com/yourusername/berlin-picnic-api" Issues = "https://github.com/yourusername/berlin-picnic-api/issues" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["app"] [tool.uv] dev-dependencies = [ "pytest>=7.4.0", "pytest-asyncio>=0.21.0", "pytest-cov>=4.1.0", "httpx>=0.25.0", "ruff>=0.1.0", "mypy>=1.7.0", "pre-commit>=3.5.0", ] # Ruff configuration [tool.ruff] target-version = "py311" line-length = 88 select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "N", # pep8-naming "S", # bandit "T20", # flake8-print "SIM", # flake8-simplify "TCH", # flake8-type-checking ] ignore = [ "E501", # line too long, handled by black "B008", # do not perform function calls in argument defaults "S101", # use of assert "T201", # print statements (allowed in scripts) ] [tool.ruff.per-file-ignores] "__init__.py" = ["F401"] # Allow unused imports in __init__.py "tests/**/*" = ["S101", "T201", "ARG", "FBT"] # Allow prints and asserts in tests "scripts/**/*" = ["T201", "S101"] # Allow prints in scripts [tool.ruff.isort] known-first-party = ["app"] # MyPy configuration [tool.mypy] python_version = "3.11" check_untyped_defs = true disallow_any_generics = true disallow_incomplete_defs = true disallow_untyped_defs = true no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = true warn_unreachable = true strict_equality = true [[tool.mypy.overrides]] module = [ "shapely.*", "geojson.*", "geopy.*", "haversine.*", "pandas.*", "redis.*", ] ignore_missing_imports = true # Pytest configuration [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] addopts = [ "--strict-markers", "--strict-config", "--cov=app", "--cov-report=term-missing", "--cov-report=html", "--cov-fail-under=80", ] markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", "integration: marks tests as integration tests", ] # Coverage configuration [tool.coverage.run] source = ["app"] omit = [ "*/tests/*", "*/venv/*", "*/__pycache__/*", "*/migrations/*", ] [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", ]