solokit 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- solokit/__init__.py +10 -0
- solokit/__version__.py +3 -0
- solokit/cli.py +374 -0
- solokit/core/__init__.py +1 -0
- solokit/core/cache.py +102 -0
- solokit/core/command_runner.py +278 -0
- solokit/core/config.py +453 -0
- solokit/core/config_validator.py +204 -0
- solokit/core/constants.py +291 -0
- solokit/core/error_formatter.py +279 -0
- solokit/core/error_handlers.py +346 -0
- solokit/core/exceptions.py +1567 -0
- solokit/core/file_ops.py +309 -0
- solokit/core/logging_config.py +166 -0
- solokit/core/output.py +99 -0
- solokit/core/performance.py +57 -0
- solokit/core/protocols.py +141 -0
- solokit/core/types.py +312 -0
- solokit/deployment/__init__.py +1 -0
- solokit/deployment/executor.py +411 -0
- solokit/git/__init__.py +1 -0
- solokit/git/integration.py +619 -0
- solokit/init/__init__.py +41 -0
- solokit/init/claude_commands_installer.py +87 -0
- solokit/init/dependency_installer.py +313 -0
- solokit/init/docs_structure.py +90 -0
- solokit/init/env_generator.py +160 -0
- solokit/init/environment_validator.py +334 -0
- solokit/init/git_hooks_installer.py +71 -0
- solokit/init/git_setup.py +188 -0
- solokit/init/gitignore_updater.py +195 -0
- solokit/init/initial_commit.py +145 -0
- solokit/init/initial_scans.py +109 -0
- solokit/init/orchestrator.py +246 -0
- solokit/init/readme_generator.py +207 -0
- solokit/init/session_structure.py +239 -0
- solokit/init/template_installer.py +424 -0
- solokit/learning/__init__.py +1 -0
- solokit/learning/archiver.py +115 -0
- solokit/learning/categorizer.py +126 -0
- solokit/learning/curator.py +428 -0
- solokit/learning/extractor.py +352 -0
- solokit/learning/reporter.py +351 -0
- solokit/learning/repository.py +254 -0
- solokit/learning/similarity.py +342 -0
- solokit/learning/validator.py +144 -0
- solokit/project/__init__.py +1 -0
- solokit/project/init.py +1162 -0
- solokit/project/stack.py +436 -0
- solokit/project/sync_plugin.py +438 -0
- solokit/project/tree.py +375 -0
- solokit/quality/__init__.py +1 -0
- solokit/quality/api_validator.py +424 -0
- solokit/quality/checkers/__init__.py +25 -0
- solokit/quality/checkers/base.py +114 -0
- solokit/quality/checkers/context7.py +221 -0
- solokit/quality/checkers/custom.py +162 -0
- solokit/quality/checkers/deployment.py +323 -0
- solokit/quality/checkers/documentation.py +179 -0
- solokit/quality/checkers/formatting.py +161 -0
- solokit/quality/checkers/integration.py +394 -0
- solokit/quality/checkers/linting.py +159 -0
- solokit/quality/checkers/security.py +261 -0
- solokit/quality/checkers/spec_completeness.py +127 -0
- solokit/quality/checkers/tests.py +184 -0
- solokit/quality/env_validator.py +306 -0
- solokit/quality/gates.py +655 -0
- solokit/quality/reporters/__init__.py +10 -0
- solokit/quality/reporters/base.py +25 -0
- solokit/quality/reporters/console.py +98 -0
- solokit/quality/reporters/json_reporter.py +34 -0
- solokit/quality/results.py +98 -0
- solokit/session/__init__.py +1 -0
- solokit/session/briefing/__init__.py +245 -0
- solokit/session/briefing/documentation_loader.py +53 -0
- solokit/session/briefing/formatter.py +476 -0
- solokit/session/briefing/git_context.py +282 -0
- solokit/session/briefing/learning_loader.py +212 -0
- solokit/session/briefing/milestone_builder.py +78 -0
- solokit/session/briefing/orchestrator.py +137 -0
- solokit/session/briefing/stack_detector.py +51 -0
- solokit/session/briefing/tree_generator.py +52 -0
- solokit/session/briefing/work_item_loader.py +209 -0
- solokit/session/briefing.py +353 -0
- solokit/session/complete.py +1188 -0
- solokit/session/status.py +246 -0
- solokit/session/validate.py +452 -0
- solokit/templates/.claude/commands/end.md +109 -0
- solokit/templates/.claude/commands/init.md +159 -0
- solokit/templates/.claude/commands/learn-curate.md +88 -0
- solokit/templates/.claude/commands/learn-search.md +62 -0
- solokit/templates/.claude/commands/learn-show.md +69 -0
- solokit/templates/.claude/commands/learn.md +136 -0
- solokit/templates/.claude/commands/start.md +114 -0
- solokit/templates/.claude/commands/status.md +22 -0
- solokit/templates/.claude/commands/validate.md +27 -0
- solokit/templates/.claude/commands/work-delete.md +119 -0
- solokit/templates/.claude/commands/work-graph.md +139 -0
- solokit/templates/.claude/commands/work-list.md +26 -0
- solokit/templates/.claude/commands/work-new.md +114 -0
- solokit/templates/.claude/commands/work-next.md +25 -0
- solokit/templates/.claude/commands/work-show.md +24 -0
- solokit/templates/.claude/commands/work-update.md +141 -0
- solokit/templates/CHANGELOG.md +17 -0
- solokit/templates/WORK_ITEM_TYPES.md +141 -0
- solokit/templates/__init__.py +1 -0
- solokit/templates/bug_spec.md +217 -0
- solokit/templates/config.schema.json +150 -0
- solokit/templates/dashboard_refine/base/.gitignore +36 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/layout.tsx +22 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/page.tsx +68 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/users/page.tsx +77 -0
- solokit/templates/dashboard_refine/base/app/globals.css +60 -0
- solokit/templates/dashboard_refine/base/app/layout.tsx +23 -0
- solokit/templates/dashboard_refine/base/app/page.tsx +9 -0
- solokit/templates/dashboard_refine/base/components/client-refine-wrapper.tsx +21 -0
- solokit/templates/dashboard_refine/base/components/layout/header.tsx +44 -0
- solokit/templates/dashboard_refine/base/components/layout/sidebar.tsx +82 -0
- solokit/templates/dashboard_refine/base/components/ui/button.tsx +53 -0
- solokit/templates/dashboard_refine/base/components/ui/card.tsx +78 -0
- solokit/templates/dashboard_refine/base/components/ui/table.tsx +116 -0
- solokit/templates/dashboard_refine/base/components.json +16 -0
- solokit/templates/dashboard_refine/base/lib/refine.tsx +65 -0
- solokit/templates/dashboard_refine/base/lib/utils.ts +13 -0
- solokit/templates/dashboard_refine/base/next.config.ts +10 -0
- solokit/templates/dashboard_refine/base/package.json.template +40 -0
- solokit/templates/dashboard_refine/base/postcss.config.mjs +8 -0
- solokit/templates/dashboard_refine/base/providers/refine-provider.tsx +26 -0
- solokit/templates/dashboard_refine/base/tailwind.config.ts +57 -0
- solokit/templates/dashboard_refine/base/tsconfig.json +27 -0
- solokit/templates/dashboard_refine/docker/Dockerfile +57 -0
- solokit/templates/dashboard_refine/docker/docker-compose.prod.yml +31 -0
- solokit/templates/dashboard_refine/docker/docker-compose.yml +21 -0
- solokit/templates/dashboard_refine/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/dashboard_refine/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/dashboard_refine/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/dashboard_refine/tier-1-essential/package.json.tier1.template +57 -0
- solokit/templates/dashboard_refine/tier-1-essential/tests/setup.ts +26 -0
- solokit/templates/dashboard_refine/tier-1-essential/tests/unit/example.test.tsx +73 -0
- solokit/templates/dashboard_refine/tier-2-standard/package.json.tier2.template +62 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/eslint.config.mjs +22 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/package.json.tier3.template +79 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/stryker.conf.json +38 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/dashboard.spec.ts +88 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/user-management.spec.ts +102 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/integration/dashboard.test.tsx +90 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/type-coverage.json +16 -0
- solokit/templates/dashboard_refine/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/dashboard_refine/tier-4-production/k6/dashboard-load-test.js +70 -0
- solokit/templates/dashboard_refine/tier-4-production/next.config.ts +46 -0
- solokit/templates/dashboard_refine/tier-4-production/package.json.tier4.template +89 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/deployment_spec.md +500 -0
- solokit/templates/feature_spec.md +248 -0
- solokit/templates/fullstack_nextjs/base/.gitignore +36 -0
- solokit/templates/fullstack_nextjs/base/app/api/example/route.ts +65 -0
- solokit/templates/fullstack_nextjs/base/app/globals.css +27 -0
- solokit/templates/fullstack_nextjs/base/app/layout.tsx +20 -0
- solokit/templates/fullstack_nextjs/base/app/page.tsx +32 -0
- solokit/templates/fullstack_nextjs/base/components/example-component.tsx +20 -0
- solokit/templates/fullstack_nextjs/base/lib/prisma.ts +17 -0
- solokit/templates/fullstack_nextjs/base/lib/utils.ts +13 -0
- solokit/templates/fullstack_nextjs/base/lib/validations.ts +20 -0
- solokit/templates/fullstack_nextjs/base/next.config.ts +7 -0
- solokit/templates/fullstack_nextjs/base/package.json.template +32 -0
- solokit/templates/fullstack_nextjs/base/postcss.config.mjs +8 -0
- solokit/templates/fullstack_nextjs/base/prisma/schema.prisma +21 -0
- solokit/templates/fullstack_nextjs/base/tailwind.config.ts +19 -0
- solokit/templates/fullstack_nextjs/base/tsconfig.json +27 -0
- solokit/templates/fullstack_nextjs/docker/Dockerfile +60 -0
- solokit/templates/fullstack_nextjs/docker/docker-compose.prod.yml +57 -0
- solokit/templates/fullstack_nextjs/docker/docker-compose.yml +47 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/package.json.tier1.template +48 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/api/example.test.ts +88 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/setup.ts +22 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/unit/example.test.tsx +22 -0
- solokit/templates/fullstack_nextjs/tier-2-standard/package.json.tier2.template +52 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/eslint.config.mjs +39 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/package.json.tier3.template +68 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/stryker.conf.json +33 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/e2e/flow.spec.ts +59 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/integration/api.test.ts +165 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/type-coverage.json +12 -0
- solokit/templates/fullstack_nextjs/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/fullstack_nextjs/tier-4-production/k6/load-test.js +45 -0
- solokit/templates/fullstack_nextjs/tier-4-production/next.config.ts +46 -0
- solokit/templates/fullstack_nextjs/tier-4-production/package.json.tier4.template +77 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/git-hooks/prepare-commit-msg +24 -0
- solokit/templates/integration_test_spec.md +363 -0
- solokit/templates/learnings.json +15 -0
- solokit/templates/ml_ai_fastapi/base/.gitignore +104 -0
- solokit/templates/ml_ai_fastapi/base/alembic/env.py +96 -0
- solokit/templates/ml_ai_fastapi/base/alembic.ini +114 -0
- solokit/templates/ml_ai_fastapi/base/pyproject.toml.template +91 -0
- solokit/templates/ml_ai_fastapi/base/requirements.txt.template +28 -0
- solokit/templates/ml_ai_fastapi/base/src/__init__.py +5 -0
- solokit/templates/ml_ai_fastapi/base/src/api/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/api/dependencies.py +20 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/example.py +134 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/health.py +66 -0
- solokit/templates/ml_ai_fastapi/base/src/core/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/core/config.py +64 -0
- solokit/templates/ml_ai_fastapi/base/src/core/database.py +50 -0
- solokit/templates/ml_ai_fastapi/base/src/main.py +64 -0
- solokit/templates/ml_ai_fastapi/base/src/models/__init__.py +7 -0
- solokit/templates/ml_ai_fastapi/base/src/models/example.py +61 -0
- solokit/templates/ml_ai_fastapi/base/src/services/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/services/example.py +115 -0
- solokit/templates/ml_ai_fastapi/docker/Dockerfile +59 -0
- solokit/templates/ml_ai_fastapi/docker/docker-compose.prod.yml +112 -0
- solokit/templates/ml_ai_fastapi/docker/docker-compose.yml +77 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pyproject.toml.tier1.template +112 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pyrightconfig.json +41 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pytest.ini +69 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/requirements-dev.txt +17 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/ruff.toml +81 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/conftest.py +72 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/test_main.py +49 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/test_example.py +113 -0
- solokit/templates/ml_ai_fastapi/tier-2-standard/pyproject.toml.tier2.template +130 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/locustfile.py +99 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/mutmut_config.py +53 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/pyproject.toml.tier3.template +150 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/conftest.py +74 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/test_api.py +131 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/pyproject.toml.tier4.template +162 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/requirements-prod.txt +25 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/api/routes/metrics.py +19 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/logging.py +74 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/monitoring.py +68 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/sentry.py +66 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/logging.py +79 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/tracing.py +60 -0
- solokit/templates/refactor_spec.md +287 -0
- solokit/templates/saas_t3/base/.gitignore +36 -0
- solokit/templates/saas_t3/base/app/api/trpc/[trpc]/route.ts +33 -0
- solokit/templates/saas_t3/base/app/globals.css +27 -0
- solokit/templates/saas_t3/base/app/layout.tsx +23 -0
- solokit/templates/saas_t3/base/app/page.tsx +31 -0
- solokit/templates/saas_t3/base/lib/api.tsx +77 -0
- solokit/templates/saas_t3/base/lib/utils.ts +13 -0
- solokit/templates/saas_t3/base/next.config.ts +7 -0
- solokit/templates/saas_t3/base/package.json.template +38 -0
- solokit/templates/saas_t3/base/postcss.config.mjs +8 -0
- solokit/templates/saas_t3/base/prisma/schema.prisma +20 -0
- solokit/templates/saas_t3/base/server/api/root.ts +19 -0
- solokit/templates/saas_t3/base/server/api/routers/example.ts +28 -0
- solokit/templates/saas_t3/base/server/api/trpc.ts +52 -0
- solokit/templates/saas_t3/base/server/db.ts +17 -0
- solokit/templates/saas_t3/base/tailwind.config.ts +19 -0
- solokit/templates/saas_t3/base/tsconfig.json +27 -0
- solokit/templates/saas_t3/docker/Dockerfile +60 -0
- solokit/templates/saas_t3/docker/docker-compose.prod.yml +59 -0
- solokit/templates/saas_t3/docker/docker-compose.yml +49 -0
- solokit/templates/saas_t3/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/saas_t3/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/saas_t3/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/saas_t3/tier-1-essential/package.json.tier1.template +54 -0
- solokit/templates/saas_t3/tier-1-essential/tests/setup.ts +22 -0
- solokit/templates/saas_t3/tier-1-essential/tests/unit/example.test.tsx +24 -0
- solokit/templates/saas_t3/tier-2-standard/package.json.tier2.template +58 -0
- solokit/templates/saas_t3/tier-3-comprehensive/eslint.config.mjs +39 -0
- solokit/templates/saas_t3/tier-3-comprehensive/package.json.tier3.template +74 -0
- solokit/templates/saas_t3/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/saas_t3/tier-3-comprehensive/stryker.conf.json +34 -0
- solokit/templates/saas_t3/tier-3-comprehensive/tests/e2e/home.spec.ts +41 -0
- solokit/templates/saas_t3/tier-3-comprehensive/tests/integration/api.test.ts +44 -0
- solokit/templates/saas_t3/tier-3-comprehensive/type-coverage.json +12 -0
- solokit/templates/saas_t3/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/saas_t3/tier-4-production/k6/load-test.js +51 -0
- solokit/templates/saas_t3/tier-4-production/next.config.ts +46 -0
- solokit/templates/saas_t3/tier-4-production/package.json.tier4.template +83 -0
- solokit/templates/saas_t3/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/saas_t3/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/saas_t3/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/saas_t3/tier-4-production/vercel.json +37 -0
- solokit/templates/security_spec.md +287 -0
- solokit/templates/stack-versions.yaml +617 -0
- solokit/templates/status_update.json +6 -0
- solokit/templates/template-registry.json +257 -0
- solokit/templates/work_items.json +11 -0
- solokit/testing/__init__.py +1 -0
- solokit/testing/integration_runner.py +550 -0
- solokit/testing/performance.py +637 -0
- solokit/visualization/__init__.py +1 -0
- solokit/visualization/dependency_graph.py +788 -0
- solokit/work_items/__init__.py +1 -0
- solokit/work_items/creator.py +217 -0
- solokit/work_items/delete.py +264 -0
- solokit/work_items/get_dependencies.py +185 -0
- solokit/work_items/get_dependents.py +113 -0
- solokit/work_items/get_metadata.py +121 -0
- solokit/work_items/get_next_recommendations.py +133 -0
- solokit/work_items/manager.py +235 -0
- solokit/work_items/milestones.py +137 -0
- solokit/work_items/query.py +376 -0
- solokit/work_items/repository.py +267 -0
- solokit/work_items/scheduler.py +184 -0
- solokit/work_items/spec_parser.py +838 -0
- solokit/work_items/spec_validator.py +493 -0
- solokit/work_items/updater.py +157 -0
- solokit/work_items/validator.py +205 -0
- solokit-0.1.1.dist-info/METADATA +640 -0
- solokit-0.1.1.dist-info/RECORD +323 -0
- solokit-0.1.1.dist-info/WHEEL +5 -0
- solokit-0.1.1.dist-info/entry_points.txt +2 -0
- solokit-0.1.1.dist-info/licenses/LICENSE +21 -0
- solokit-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Item service - handles business logic for items
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from sqlmodel import select
|
|
9
|
+
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
10
|
+
|
|
11
|
+
from src.models.example import Item, ItemCreate, ItemUpdate
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ItemService:
|
|
15
|
+
"""Service for managing items."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, db: AsyncSession):
|
|
18
|
+
"""
|
|
19
|
+
Initialize item service.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
db: Database session
|
|
23
|
+
"""
|
|
24
|
+
self.db = db
|
|
25
|
+
|
|
26
|
+
async def create_item(self, item_data: ItemCreate) -> Item:
|
|
27
|
+
"""
|
|
28
|
+
Create a new item.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
item_data: Item creation data
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Item: Created item
|
|
35
|
+
"""
|
|
36
|
+
item = Item.model_validate(item_data)
|
|
37
|
+
self.db.add(item)
|
|
38
|
+
await self.db.commit()
|
|
39
|
+
await self.db.refresh(item)
|
|
40
|
+
return item
|
|
41
|
+
|
|
42
|
+
async def get_item(self, item_id: int) -> Optional[Item]:
|
|
43
|
+
"""
|
|
44
|
+
Get an item by ID.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
item_id: Item ID
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Optional[Item]: Item if found, None otherwise
|
|
51
|
+
"""
|
|
52
|
+
statement = select(Item).where(Item.id == item_id)
|
|
53
|
+
result = await self.db.exec(statement)
|
|
54
|
+
return result.one_or_none()
|
|
55
|
+
|
|
56
|
+
async def get_items(self, skip: int = 0, limit: int = 100) -> list[Item]:
|
|
57
|
+
"""
|
|
58
|
+
Get all items with pagination.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
skip: Number of items to skip
|
|
62
|
+
limit: Maximum number of items to return
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
list[Item]: List of items
|
|
66
|
+
"""
|
|
67
|
+
statement = select(Item).offset(skip).limit(limit)
|
|
68
|
+
result = await self.db.exec(statement)
|
|
69
|
+
return list(result.all())
|
|
70
|
+
|
|
71
|
+
async def update_item(self, item_id: int, item_update: ItemUpdate) -> Optional[Item]:
|
|
72
|
+
"""
|
|
73
|
+
Update an item.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
item_id: Item ID
|
|
77
|
+
item_update: Fields to update
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Optional[Item]: Updated item if found, None otherwise
|
|
81
|
+
"""
|
|
82
|
+
item = await self.get_item(item_id)
|
|
83
|
+
if not item:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
# Update only provided fields
|
|
87
|
+
update_data = item_update.model_dump(exclude_unset=True)
|
|
88
|
+
for key, value in update_data.items():
|
|
89
|
+
setattr(item, key, value)
|
|
90
|
+
|
|
91
|
+
# Update timestamp
|
|
92
|
+
item.updated_at = datetime.utcnow()
|
|
93
|
+
|
|
94
|
+
self.db.add(item)
|
|
95
|
+
await self.db.commit()
|
|
96
|
+
await self.db.refresh(item)
|
|
97
|
+
return item
|
|
98
|
+
|
|
99
|
+
async def delete_item(self, item_id: int) -> bool:
|
|
100
|
+
"""
|
|
101
|
+
Delete an item.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
item_id: Item ID
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
bool: True if item was deleted, False if not found
|
|
108
|
+
"""
|
|
109
|
+
item = await self.get_item(item_id)
|
|
110
|
+
if not item:
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
await self.db.delete(item)
|
|
114
|
+
await self.db.commit()
|
|
115
|
+
return True
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Multi-stage Dockerfile for FastAPI application
|
|
2
|
+
# Stage 1: Builder - Install dependencies
|
|
3
|
+
FROM python:3.11-slim as builder
|
|
4
|
+
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
# Install build dependencies
|
|
8
|
+
RUN apt-get update && apt-get install -y \
|
|
9
|
+
gcc \
|
|
10
|
+
postgresql-client \
|
|
11
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
12
|
+
|
|
13
|
+
# Copy requirements first for better caching
|
|
14
|
+
COPY requirements.txt .
|
|
15
|
+
|
|
16
|
+
# Create virtual environment and install dependencies
|
|
17
|
+
RUN python -m venv /opt/venv
|
|
18
|
+
ENV PATH="/opt/venv/bin:$PATH"
|
|
19
|
+
RUN pip install --no-cache-dir --upgrade pip && \
|
|
20
|
+
pip install --no-cache-dir -r requirements.txt
|
|
21
|
+
|
|
22
|
+
# Stage 2: Runner - Production image
|
|
23
|
+
FROM python:3.11-slim
|
|
24
|
+
|
|
25
|
+
WORKDIR /app
|
|
26
|
+
|
|
27
|
+
# Install runtime dependencies
|
|
28
|
+
RUN apt-get update && apt-get install -y \
|
|
29
|
+
postgresql-client \
|
|
30
|
+
curl \
|
|
31
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
32
|
+
|
|
33
|
+
# Copy virtual environment from builder
|
|
34
|
+
COPY --from=builder /opt/venv /opt/venv
|
|
35
|
+
|
|
36
|
+
# Set environment variables
|
|
37
|
+
ENV PATH="/opt/venv/bin:$PATH" \
|
|
38
|
+
PYTHONUNBUFFERED=1 \
|
|
39
|
+
PYTHONDONTWRITEBYTECODE=1
|
|
40
|
+
|
|
41
|
+
# Copy application code
|
|
42
|
+
COPY src/ ./src/
|
|
43
|
+
COPY alembic/ ./alembic/
|
|
44
|
+
COPY alembic.ini .
|
|
45
|
+
|
|
46
|
+
# Create non-root user
|
|
47
|
+
RUN useradd -m -u 1000 appuser && \
|
|
48
|
+
chown -R appuser:appuser /app
|
|
49
|
+
USER appuser
|
|
50
|
+
|
|
51
|
+
# Expose port
|
|
52
|
+
EXPOSE 8000
|
|
53
|
+
|
|
54
|
+
# Health check
|
|
55
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
|
56
|
+
CMD curl -f http://localhost:8000/health || exit 1
|
|
57
|
+
|
|
58
|
+
# Run the application
|
|
59
|
+
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
# FastAPI application with Gunicorn
|
|
5
|
+
app:
|
|
6
|
+
build:
|
|
7
|
+
context: .
|
|
8
|
+
dockerfile: Dockerfile
|
|
9
|
+
environment:
|
|
10
|
+
- DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
|
|
11
|
+
- REDIS_URL=redis://redis:6379/0
|
|
12
|
+
- DEBUG=False
|
|
13
|
+
- ENVIRONMENT=production
|
|
14
|
+
- SECRET_KEY=${SECRET_KEY}
|
|
15
|
+
- SENTRY_DSN=${SENTRY_DSN}
|
|
16
|
+
depends_on:
|
|
17
|
+
db:
|
|
18
|
+
condition: service_healthy
|
|
19
|
+
redis:
|
|
20
|
+
condition: service_started
|
|
21
|
+
command: gunicorn src.main:app -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 --workers 4 --timeout 60
|
|
22
|
+
restart: unless-stopped
|
|
23
|
+
networks:
|
|
24
|
+
- app-network
|
|
25
|
+
logging:
|
|
26
|
+
driver: "json-file"
|
|
27
|
+
options:
|
|
28
|
+
max-size: "10m"
|
|
29
|
+
max-file: "3"
|
|
30
|
+
|
|
31
|
+
# Nginx reverse proxy
|
|
32
|
+
nginx:
|
|
33
|
+
image: nginx:alpine
|
|
34
|
+
ports:
|
|
35
|
+
- "80:80"
|
|
36
|
+
- "443:443"
|
|
37
|
+
volumes:
|
|
38
|
+
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
|
39
|
+
- ./ssl:/etc/nginx/ssl:ro
|
|
40
|
+
depends_on:
|
|
41
|
+
- app
|
|
42
|
+
restart: unless-stopped
|
|
43
|
+
networks:
|
|
44
|
+
- app-network
|
|
45
|
+
|
|
46
|
+
# PostgreSQL database (production)
|
|
47
|
+
db:
|
|
48
|
+
image: postgres:16-alpine
|
|
49
|
+
environment:
|
|
50
|
+
- POSTGRES_USER=${DB_USER}
|
|
51
|
+
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
|
52
|
+
- POSTGRES_DB=${DB_NAME}
|
|
53
|
+
volumes:
|
|
54
|
+
- postgres_data:/var/lib/postgresql/data
|
|
55
|
+
healthcheck:
|
|
56
|
+
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
|
|
57
|
+
interval: 10s
|
|
58
|
+
timeout: 5s
|
|
59
|
+
retries: 5
|
|
60
|
+
restart: unless-stopped
|
|
61
|
+
networks:
|
|
62
|
+
- app-network
|
|
63
|
+
|
|
64
|
+
# Redis cache (production)
|
|
65
|
+
redis:
|
|
66
|
+
image: redis:7-alpine
|
|
67
|
+
command: redis-server --appendonly yes
|
|
68
|
+
volumes:
|
|
69
|
+
- redis_data:/data
|
|
70
|
+
restart: unless-stopped
|
|
71
|
+
networks:
|
|
72
|
+
- app-network
|
|
73
|
+
|
|
74
|
+
# Prometheus monitoring
|
|
75
|
+
prometheus:
|
|
76
|
+
image: prom/prometheus:latest
|
|
77
|
+
ports:
|
|
78
|
+
- "9090:9090"
|
|
79
|
+
volumes:
|
|
80
|
+
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
|
81
|
+
- prometheus_data:/prometheus
|
|
82
|
+
command:
|
|
83
|
+
- '--config.file=/etc/prometheus/prometheus.yml'
|
|
84
|
+
- '--storage.tsdb.path=/prometheus'
|
|
85
|
+
restart: unless-stopped
|
|
86
|
+
networks:
|
|
87
|
+
- app-network
|
|
88
|
+
|
|
89
|
+
# Grafana dashboards
|
|
90
|
+
grafana:
|
|
91
|
+
image: grafana/grafana:latest
|
|
92
|
+
ports:
|
|
93
|
+
- "3000:3000"
|
|
94
|
+
environment:
|
|
95
|
+
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
|
|
96
|
+
volumes:
|
|
97
|
+
- grafana_data:/var/lib/grafana
|
|
98
|
+
depends_on:
|
|
99
|
+
- prometheus
|
|
100
|
+
restart: unless-stopped
|
|
101
|
+
networks:
|
|
102
|
+
- app-network
|
|
103
|
+
|
|
104
|
+
volumes:
|
|
105
|
+
postgres_data:
|
|
106
|
+
redis_data:
|
|
107
|
+
prometheus_data:
|
|
108
|
+
grafana_data:
|
|
109
|
+
|
|
110
|
+
networks:
|
|
111
|
+
app-network:
|
|
112
|
+
driver: bridge
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
# FastAPI application
|
|
5
|
+
app:
|
|
6
|
+
build:
|
|
7
|
+
context: .
|
|
8
|
+
dockerfile: Dockerfile
|
|
9
|
+
ports:
|
|
10
|
+
- "8000:8000"
|
|
11
|
+
environment:
|
|
12
|
+
- DATABASE_URL=postgresql://postgres:postgres@db:5432/app_db
|
|
13
|
+
- REDIS_URL=redis://redis:6379/0
|
|
14
|
+
- DEBUG=True
|
|
15
|
+
- ENVIRONMENT=development
|
|
16
|
+
depends_on:
|
|
17
|
+
db:
|
|
18
|
+
condition: service_healthy
|
|
19
|
+
redis:
|
|
20
|
+
condition: service_started
|
|
21
|
+
volumes:
|
|
22
|
+
- ./src:/app/src
|
|
23
|
+
- ./alembic:/app/alembic
|
|
24
|
+
command: uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload
|
|
25
|
+
networks:
|
|
26
|
+
- app-network
|
|
27
|
+
|
|
28
|
+
# PostgreSQL database
|
|
29
|
+
db:
|
|
30
|
+
image: postgres:16-alpine
|
|
31
|
+
environment:
|
|
32
|
+
- POSTGRES_USER=postgres
|
|
33
|
+
- POSTGRES_PASSWORD=postgres
|
|
34
|
+
- POSTGRES_DB=app_db
|
|
35
|
+
ports:
|
|
36
|
+
- "5432:5432"
|
|
37
|
+
volumes:
|
|
38
|
+
- postgres_data:/var/lib/postgresql/data
|
|
39
|
+
healthcheck:
|
|
40
|
+
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
41
|
+
interval: 10s
|
|
42
|
+
timeout: 5s
|
|
43
|
+
retries: 5
|
|
44
|
+
networks:
|
|
45
|
+
- app-network
|
|
46
|
+
|
|
47
|
+
# Redis cache
|
|
48
|
+
redis:
|
|
49
|
+
image: redis:7-alpine
|
|
50
|
+
ports:
|
|
51
|
+
- "6379:6379"
|
|
52
|
+
volumes:
|
|
53
|
+
- redis_data:/data
|
|
54
|
+
networks:
|
|
55
|
+
- app-network
|
|
56
|
+
|
|
57
|
+
# Database migrations (run once)
|
|
58
|
+
migrations:
|
|
59
|
+
build:
|
|
60
|
+
context: .
|
|
61
|
+
dockerfile: Dockerfile
|
|
62
|
+
environment:
|
|
63
|
+
- DATABASE_URL=postgresql://postgres:postgres@db:5432/app_db
|
|
64
|
+
depends_on:
|
|
65
|
+
db:
|
|
66
|
+
condition: service_healthy
|
|
67
|
+
command: alembic upgrade head
|
|
68
|
+
networks:
|
|
69
|
+
- app-network
|
|
70
|
+
|
|
71
|
+
volumes:
|
|
72
|
+
postgres_data:
|
|
73
|
+
redis_data:
|
|
74
|
+
|
|
75
|
+
networks:
|
|
76
|
+
app-network:
|
|
77
|
+
driver: bridge
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "{project_name}"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "{project_description}"
|
|
5
|
+
requires-python = ">=3.11"
|
|
6
|
+
dependencies = [
|
|
7
|
+
"fastapi==0.115.6",
|
|
8
|
+
"uvicorn[standard]==0.34.0",
|
|
9
|
+
"pydantic==2.12.4",
|
|
10
|
+
"pydantic-core==2.41.5",
|
|
11
|
+
"pydantic-settings==2.11.0",
|
|
12
|
+
"sqlmodel==0.0.25",
|
|
13
|
+
"sqlalchemy==2.0.37",
|
|
14
|
+
"psycopg2-binary==2.9.10",
|
|
15
|
+
"alembic==1.14.0",
|
|
16
|
+
"python-dotenv==1.2.1",
|
|
17
|
+
"asyncpg==0.30.0",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.optional-dependencies]
|
|
21
|
+
dev = [
|
|
22
|
+
"pytest==8.3.4",
|
|
23
|
+
"pytest-cov==6.0.0",
|
|
24
|
+
"pytest-asyncio==0.25.2",
|
|
25
|
+
"httpx==0.28.1",
|
|
26
|
+
"aiosqlite==0.20.0",
|
|
27
|
+
"ruff==0.9.2",
|
|
28
|
+
"pyright==1.1.396",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["setuptools>=61.0"]
|
|
33
|
+
build-backend = "setuptools.build_meta"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools]
|
|
36
|
+
packages = ["src"]
|
|
37
|
+
|
|
38
|
+
# Ruff configuration
|
|
39
|
+
[tool.ruff]
|
|
40
|
+
line-length = 100
|
|
41
|
+
target-version = "py311"
|
|
42
|
+
|
|
43
|
+
select = [
|
|
44
|
+
"E", # pycodestyle errors
|
|
45
|
+
"W", # pycodestyle warnings
|
|
46
|
+
"F", # pyflakes
|
|
47
|
+
"I", # isort
|
|
48
|
+
"N", # pep8-naming
|
|
49
|
+
"UP", # pyupgrade
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
ignore = [
|
|
53
|
+
"E501", # line too long (handled by formatter)
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
exclude = [
|
|
57
|
+
".git",
|
|
58
|
+
".venv",
|
|
59
|
+
"__pycache__",
|
|
60
|
+
"alembic/versions",
|
|
61
|
+
".pytest_cache",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[tool.ruff.format]
|
|
65
|
+
quote-style = "double"
|
|
66
|
+
indent-style = "space"
|
|
67
|
+
|
|
68
|
+
[tool.ruff.isort]
|
|
69
|
+
known-first-party = ["src"]
|
|
70
|
+
|
|
71
|
+
# Pytest configuration
|
|
72
|
+
[tool.pytest.ini_options]
|
|
73
|
+
asyncio_mode = "auto"
|
|
74
|
+
testpaths = ["tests"]
|
|
75
|
+
python_files = ["test_*.py", "*_test.py"]
|
|
76
|
+
python_classes = ["Test*"]
|
|
77
|
+
python_functions = ["test_*"]
|
|
78
|
+
addopts = [
|
|
79
|
+
"-v",
|
|
80
|
+
"--strict-markers",
|
|
81
|
+
"--tb=short",
|
|
82
|
+
"--cov=src",
|
|
83
|
+
"--cov-report=term-missing",
|
|
84
|
+
"--cov-fail-under=80",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
# Coverage configuration
|
|
88
|
+
[tool.coverage.run]
|
|
89
|
+
source = ["src"]
|
|
90
|
+
omit = [
|
|
91
|
+
"tests/*",
|
|
92
|
+
"alembic/*",
|
|
93
|
+
"*/__init__.py",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.coverage.report]
|
|
97
|
+
precision = 2
|
|
98
|
+
show_missing = true
|
|
99
|
+
skip_covered = false
|
|
100
|
+
exclude_lines = [
|
|
101
|
+
"pragma: no cover",
|
|
102
|
+
"def __repr__",
|
|
103
|
+
"raise AssertionError",
|
|
104
|
+
"raise NotImplementedError",
|
|
105
|
+
"if __name__ == .__main__.:",
|
|
106
|
+
"if TYPE_CHECKING:",
|
|
107
|
+
"@abstractmethod",
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
# Scripts (use with: python -m <command>)
|
|
111
|
+
[project.scripts]
|
|
112
|
+
dev = "uvicorn src.main:app --reload --host 0.0.0.0 --port 8000"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"include": [
|
|
3
|
+
"src",
|
|
4
|
+
"tests"
|
|
5
|
+
],
|
|
6
|
+
"exclude": [
|
|
7
|
+
"**/__pycache__",
|
|
8
|
+
".venv",
|
|
9
|
+
"venv",
|
|
10
|
+
"build",
|
|
11
|
+
"dist",
|
|
12
|
+
"alembic/versions"
|
|
13
|
+
],
|
|
14
|
+
"defineConstant": {
|
|
15
|
+
"DEBUG": true
|
|
16
|
+
},
|
|
17
|
+
"stubPath": "typings",
|
|
18
|
+
"reportMissingImports": true,
|
|
19
|
+
"reportMissingTypeStubs": false,
|
|
20
|
+
"pythonVersion": "3.11",
|
|
21
|
+
"pythonPlatform": "All",
|
|
22
|
+
"typeCheckingMode": "basic",
|
|
23
|
+
"useLibraryCodeForTypes": true,
|
|
24
|
+
"reportUnusedImport": true,
|
|
25
|
+
"reportUnusedClass": "warning",
|
|
26
|
+
"reportUnusedFunction": "warning",
|
|
27
|
+
"reportUnusedVariable": "warning",
|
|
28
|
+
"reportDuplicateImport": "warning",
|
|
29
|
+
"reportOptionalSubscript": "warning",
|
|
30
|
+
"reportOptionalMemberAccess": "warning",
|
|
31
|
+
"reportOptionalCall": "warning",
|
|
32
|
+
"reportOptionalIterable": "warning",
|
|
33
|
+
"reportOptionalContextManager": "warning",
|
|
34
|
+
"reportOptionalOperand": "warning",
|
|
35
|
+
"reportTypedDictNotRequiredAccess": "warning",
|
|
36
|
+
"reportPrivateUsage": "warning",
|
|
37
|
+
"reportConstantRedefinition": "error",
|
|
38
|
+
"reportIncompatibleMethodOverride": "error",
|
|
39
|
+
"reportIncompatibleVariableOverride": "error",
|
|
40
|
+
"reportInconsistentConstructor": "error"
|
|
41
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[pytest]
|
|
2
|
+
# Pytest configuration for FastAPI testing
|
|
3
|
+
|
|
4
|
+
# Async mode for pytest-asyncio
|
|
5
|
+
asyncio_mode = auto
|
|
6
|
+
asyncio_default_fixture_loop_scope = function
|
|
7
|
+
|
|
8
|
+
# Test discovery patterns
|
|
9
|
+
testpaths = tests
|
|
10
|
+
python_files = test_*.py *_test.py
|
|
11
|
+
python_classes = Test*
|
|
12
|
+
python_functions = test_*
|
|
13
|
+
|
|
14
|
+
# Additional options
|
|
15
|
+
addopts =
|
|
16
|
+
-v
|
|
17
|
+
--strict-markers
|
|
18
|
+
--tb=short
|
|
19
|
+
--cov=src
|
|
20
|
+
--cov-report=term-missing
|
|
21
|
+
--cov-report=html
|
|
22
|
+
--cov-report=xml
|
|
23
|
+
--cov-fail-under=80
|
|
24
|
+
|
|
25
|
+
# Markers for organizing tests
|
|
26
|
+
markers =
|
|
27
|
+
unit: Unit tests
|
|
28
|
+
integration: Integration tests
|
|
29
|
+
slow: Tests that take a long time to run
|
|
30
|
+
api: API endpoint tests
|
|
31
|
+
db: Database tests
|
|
32
|
+
|
|
33
|
+
# Ignore paths
|
|
34
|
+
norecursedirs =
|
|
35
|
+
.git
|
|
36
|
+
.venv
|
|
37
|
+
venv
|
|
38
|
+
__pycache__
|
|
39
|
+
alembic
|
|
40
|
+
build
|
|
41
|
+
dist
|
|
42
|
+
|
|
43
|
+
# Coverage options
|
|
44
|
+
[coverage:run]
|
|
45
|
+
source = src
|
|
46
|
+
omit =
|
|
47
|
+
tests/*
|
|
48
|
+
alembic/*
|
|
49
|
+
*/__init__.py
|
|
50
|
+
# Tier 4 Production modules (optional features)
|
|
51
|
+
src/api/routes/metrics.py
|
|
52
|
+
src/core/logging.py
|
|
53
|
+
src/core/monitoring.py
|
|
54
|
+
src/core/sentry.py
|
|
55
|
+
src/middleware/logging.py
|
|
56
|
+
src/middleware/tracing.py
|
|
57
|
+
|
|
58
|
+
[coverage:report]
|
|
59
|
+
precision = 2
|
|
60
|
+
show_missing = True
|
|
61
|
+
skip_covered = False
|
|
62
|
+
exclude_lines =
|
|
63
|
+
pragma: no cover
|
|
64
|
+
def __repr__
|
|
65
|
+
raise AssertionError
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
if __name__ == .__main__.:
|
|
68
|
+
if TYPE_CHECKING:
|
|
69
|
+
@abstractmethod
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Development Dependencies for {project_name}
|
|
2
|
+
|
|
3
|
+
# Testing
|
|
4
|
+
pytest==8.3.4
|
|
5
|
+
pytest-cov==6.0.0
|
|
6
|
+
pytest-asyncio==0.25.2
|
|
7
|
+
httpx==0.28.1
|
|
8
|
+
aiosqlite==0.20.0
|
|
9
|
+
|
|
10
|
+
# Linting & Formatting
|
|
11
|
+
ruff==0.9.2
|
|
12
|
+
|
|
13
|
+
# Type Checking
|
|
14
|
+
pyright==1.1.396
|
|
15
|
+
|
|
16
|
+
# Database (async support for testing)
|
|
17
|
+
asyncpg==0.30.0
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Ruff configuration for linting and formatting
|
|
2
|
+
# https://docs.astral.sh/ruff/
|
|
3
|
+
|
|
4
|
+
line-length = 100
|
|
5
|
+
target-version = "py311"
|
|
6
|
+
|
|
7
|
+
# Enable auto-fixing by default
|
|
8
|
+
fix = true
|
|
9
|
+
|
|
10
|
+
# Exclude common directories
|
|
11
|
+
exclude = [
|
|
12
|
+
".git",
|
|
13
|
+
".venv",
|
|
14
|
+
"venv",
|
|
15
|
+
"__pycache__",
|
|
16
|
+
"alembic/versions",
|
|
17
|
+
".pytest_cache",
|
|
18
|
+
".mypy_cache",
|
|
19
|
+
".ruff_cache",
|
|
20
|
+
"build",
|
|
21
|
+
"dist",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[lint]
|
|
25
|
+
select = [
|
|
26
|
+
"E", # pycodestyle errors
|
|
27
|
+
"W", # pycodestyle warnings
|
|
28
|
+
"F", # pyflakes
|
|
29
|
+
"I", # isort
|
|
30
|
+
"N", # pep8-naming
|
|
31
|
+
"UP", # pyupgrade
|
|
32
|
+
"B", # flake8-bugbear
|
|
33
|
+
"C4", # flake8-comprehensions
|
|
34
|
+
"DTZ", # flake8-datetimez
|
|
35
|
+
"T10", # flake8-debugger
|
|
36
|
+
"EM", # flake8-errmsg
|
|
37
|
+
"ISC", # flake8-implicit-str-concat
|
|
38
|
+
"ICN", # flake8-import-conventions
|
|
39
|
+
"G", # flake8-logging-format
|
|
40
|
+
"PIE", # flake8-pie
|
|
41
|
+
"T20", # flake8-print
|
|
42
|
+
"PT", # flake8-pytest-style
|
|
43
|
+
"Q", # flake8-quotes
|
|
44
|
+
"RET", # flake8-return
|
|
45
|
+
"SIM", # flake8-simplify
|
|
46
|
+
"TID", # flake8-tidy-imports
|
|
47
|
+
"ARG", # flake8-unused-arguments
|
|
48
|
+
"PTH", # flake8-use-pathlib
|
|
49
|
+
"ERA", # eradicate
|
|
50
|
+
"PD", # pandas-vet
|
|
51
|
+
"PL", # pylint
|
|
52
|
+
"TRY", # tryceratops
|
|
53
|
+
"NPY", # numpy-specific rules
|
|
54
|
+
"RUF", # ruff-specific rules
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
ignore = [
|
|
58
|
+
"E501", # line too long (handled by formatter)
|
|
59
|
+
"PLR0913", # too many arguments
|
|
60
|
+
"TRY003", # avoid specifying long messages outside exception class
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[lint.isort]
|
|
64
|
+
known-first-party = ["src"]
|
|
65
|
+
force-single-line = false
|
|
66
|
+
force-sort-within-sections = false
|
|
67
|
+
lines-after-imports = 2
|
|
68
|
+
|
|
69
|
+
[lint.mccabe]
|
|
70
|
+
max-complexity = 10
|
|
71
|
+
|
|
72
|
+
[lint.per-file-ignores]
|
|
73
|
+
"__init__.py" = ["F401", "F403"]
|
|
74
|
+
"tests/*" = ["S101", "PLR2004", "ARG001"]
|
|
75
|
+
"alembic/env.py" = ["F401"]
|
|
76
|
+
|
|
77
|
+
[format]
|
|
78
|
+
quote-style = "double"
|
|
79
|
+
indent-style = "space"
|
|
80
|
+
skip-magic-trailing-comma = false
|
|
81
|
+
line-ending = "auto"
|