moai-adk 0.8.0__py3-none-any.whl → 0.34.0__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.
Files changed (654) hide show
  1. moai_adk/__init__.py +2 -6
  2. moai_adk/__main__.py +136 -21
  3. moai_adk/cli/__init__.py +6 -2
  4. moai_adk/cli/commands/__init__.py +1 -4
  5. moai_adk/cli/commands/analyze.py +116 -0
  6. moai_adk/cli/commands/doctor.py +17 -5
  7. moai_adk/cli/commands/init.py +118 -48
  8. moai_adk/cli/commands/language.py +248 -0
  9. moai_adk/cli/commands/status.py +8 -13
  10. moai_adk/cli/commands/update.py +1978 -149
  11. moai_adk/cli/main.py +3 -2
  12. moai_adk/cli/prompts/init_prompts.py +144 -91
  13. moai_adk/cli/spec_status.py +263 -0
  14. moai_adk/cli/ui/__init__.py +44 -0
  15. moai_adk/cli/ui/progress.py +422 -0
  16. moai_adk/cli/ui/prompts.py +389 -0
  17. moai_adk/cli/ui/theme.py +129 -0
  18. moai_adk/cli/worktree/__init__.py +27 -0
  19. moai_adk/cli/worktree/__main__.py +31 -0
  20. moai_adk/cli/worktree/cli.py +683 -0
  21. moai_adk/cli/worktree/exceptions.py +89 -0
  22. moai_adk/cli/worktree/manager.py +493 -0
  23. moai_adk/cli/worktree/models.py +65 -0
  24. moai_adk/cli/worktree/registry.py +422 -0
  25. moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
  26. moai_adk/core/__init__.py +0 -1
  27. moai_adk/core/analysis/__init__.py +9 -0
  28. moai_adk/core/analysis/session_analyzer.py +400 -0
  29. moai_adk/core/claude_integration.py +393 -0
  30. moai_adk/core/command_helpers.py +270 -0
  31. moai_adk/core/comprehensive_monitoring_system.py +1183 -0
  32. moai_adk/core/config/__init__.py +6 -0
  33. moai_adk/core/config/auto_spec_config.py +340 -0
  34. moai_adk/core/config/migration.py +148 -17
  35. moai_adk/core/config/unified.py +436 -0
  36. moai_adk/core/context_manager.py +273 -0
  37. moai_adk/core/diagnostics/slash_commands.py +0 -1
  38. moai_adk/core/enterprise_features.py +1404 -0
  39. moai_adk/core/error_recovery_system.py +1902 -0
  40. moai_adk/core/event_driven_hook_system.py +1371 -0
  41. moai_adk/core/git/__init__.py +8 -1
  42. moai_adk/core/git/branch.py +0 -1
  43. moai_adk/core/git/branch_manager.py +2 -10
  44. moai_adk/core/git/checkpoint.py +1 -7
  45. moai_adk/core/git/commit.py +0 -1
  46. moai_adk/core/git/conflict_detector.py +413 -0
  47. moai_adk/core/git/event_detector.py +3 -5
  48. moai_adk/core/git/manager.py +91 -2
  49. moai_adk/core/hooks/post_tool_auto_spec_completion.py +901 -0
  50. moai_adk/core/input_validation_middleware.py +1006 -0
  51. moai_adk/core/integration/__init__.py +22 -0
  52. moai_adk/core/integration/engine.py +157 -0
  53. moai_adk/core/integration/integration_tester.py +226 -0
  54. moai_adk/core/integration/models.py +88 -0
  55. moai_adk/core/integration/utils.py +211 -0
  56. moai_adk/core/issue_creator.py +305 -0
  57. moai_adk/core/jit_context_loader.py +956 -0
  58. moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
  59. moai_adk/core/language_config.py +202 -0
  60. moai_adk/core/language_config_resolver.py +572 -0
  61. moai_adk/core/language_validator.py +543 -0
  62. moai_adk/core/mcp/setup.py +116 -0
  63. moai_adk/core/merge/__init__.py +9 -0
  64. moai_adk/core/merge/analyzer.py +481 -0
  65. moai_adk/core/migration/__init__.py +18 -0
  66. moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
  67. moai_adk/core/migration/backup_manager.py +277 -0
  68. moai_adk/core/migration/custom_element_scanner.py +358 -0
  69. moai_adk/core/migration/file_migrator.py +209 -0
  70. moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
  71. moai_adk/core/migration/selective_restorer.py +470 -0
  72. moai_adk/core/migration/template_utils.py +74 -0
  73. moai_adk/core/migration/user_selection_ui.py +338 -0
  74. moai_adk/core/migration/version_detector.py +139 -0
  75. moai_adk/core/migration/version_migrator.py +228 -0
  76. moai_adk/core/performance/__init__.py +6 -0
  77. moai_adk/core/performance/cache_system.py +316 -0
  78. moai_adk/core/performance/parallel_processor.py +116 -0
  79. moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
  80. moai_adk/core/project/__init__.py +0 -1
  81. moai_adk/core/project/backup_utils.py +2 -7
  82. moai_adk/core/project/checker.py +2 -4
  83. moai_adk/core/project/detector.py +189 -22
  84. moai_adk/core/project/initializer.py +218 -27
  85. moai_adk/core/project/phase_executor.py +416 -44
  86. moai_adk/core/project/validator.py +7 -32
  87. moai_adk/core/quality/__init__.py +1 -1
  88. moai_adk/core/quality/trust_checker.py +37 -101
  89. moai_adk/core/quality/validators/__init__.py +1 -1
  90. moai_adk/core/quality/validators/base_validator.py +1 -1
  91. moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
  92. moai_adk/core/robust_json_parser.py +611 -0
  93. moai_adk/core/rollback_manager.py +918 -0
  94. moai_adk/core/session_manager.py +651 -0
  95. moai_adk/core/skill_loading_system.py +579 -0
  96. moai_adk/core/spec/confidence_scoring.py +680 -0
  97. moai_adk/core/spec/ears_template_engine.py +1247 -0
  98. moai_adk/core/spec/quality_validator.py +687 -0
  99. moai_adk/core/spec_status_manager.py +478 -0
  100. moai_adk/core/template/__init__.py +0 -1
  101. moai_adk/core/template/backup.py +82 -17
  102. moai_adk/core/template/config.py +112 -40
  103. moai_adk/core/template/languages.py +0 -1
  104. moai_adk/core/template/merger.py +75 -26
  105. moai_adk/core/template/processor.py +750 -72
  106. moai_adk/core/template_engine.py +310 -0
  107. moai_adk/core/template_variable_synchronizer.py +417 -0
  108. moai_adk/core/unified_permission_manager.py +745 -0
  109. moai_adk/core/user_behavior_analytics.py +851 -0
  110. moai_adk/core/version_sync.py +429 -0
  111. moai_adk/foundation/__init__.py +56 -0
  112. moai_adk/foundation/backend.py +1027 -0
  113. moai_adk/foundation/database.py +1115 -0
  114. moai_adk/foundation/devops.py +1585 -0
  115. moai_adk/foundation/ears.py +431 -0
  116. moai_adk/foundation/frontend.py +870 -0
  117. moai_adk/foundation/git/commit_templates.py +557 -0
  118. moai_adk/foundation/git.py +376 -0
  119. moai_adk/foundation/langs.py +484 -0
  120. moai_adk/foundation/ml_ops.py +1162 -0
  121. moai_adk/foundation/testing.py +1524 -0
  122. moai_adk/foundation/trust/trust_principles.py +676 -0
  123. moai_adk/foundation/trust/validation_checklist.py +1573 -0
  124. moai_adk/project/__init__.py +0 -0
  125. moai_adk/project/configuration.py +1084 -0
  126. moai_adk/project/documentation.py +566 -0
  127. moai_adk/project/schema.py +447 -0
  128. moai_adk/statusline/__init__.py +38 -0
  129. moai_adk/statusline/alfred_detector.py +105 -0
  130. moai_adk/statusline/config.py +376 -0
  131. moai_adk/statusline/enhanced_output_style_detector.py +372 -0
  132. moai_adk/statusline/git_collector.py +190 -0
  133. moai_adk/statusline/main.py +322 -0
  134. moai_adk/statusline/metrics_tracker.py +78 -0
  135. moai_adk/statusline/renderer.py +343 -0
  136. moai_adk/statusline/update_checker.py +129 -0
  137. moai_adk/statusline/version_reader.py +741 -0
  138. moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +670 -0
  139. moai_adk/templates/.claude/agents/moai/builder-agent.md +474 -0
  140. moai_adk/templates/.claude/agents/moai/builder-command.md +1172 -0
  141. moai_adk/templates/.claude/agents/moai/builder-skill.md +666 -0
  142. moai_adk/templates/.claude/agents/moai/expert-backend.md +899 -0
  143. moai_adk/templates/.claude/agents/moai/expert-database.md +777 -0
  144. moai_adk/templates/.claude/agents/moai/expert-debug.md +401 -0
  145. moai_adk/templates/.claude/agents/moai/expert-devops.md +720 -0
  146. moai_adk/templates/.claude/agents/moai/expert-frontend.md +734 -0
  147. moai_adk/templates/.claude/agents/moai/expert-performance.md +657 -0
  148. moai_adk/templates/.claude/agents/moai/expert-security.md +509 -0
  149. moai_adk/templates/.claude/agents/moai/expert-testing.md +733 -0
  150. moai_adk/templates/.claude/agents/moai/expert-uiux.md +1041 -0
  151. moai_adk/templates/.claude/agents/moai/manager-claude-code.md +432 -0
  152. moai_adk/templates/.claude/agents/moai/manager-docs.md +573 -0
  153. moai_adk/templates/.claude/agents/moai/manager-git.md +1020 -0
  154. moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
  155. moai_adk/templates/.claude/agents/moai/manager-quality.md +624 -0
  156. moai_adk/templates/.claude/agents/moai/manager-spec.md +809 -0
  157. moai_adk/templates/.claude/agents/moai/manager-strategy.md +780 -0
  158. moai_adk/templates/.claude/agents/moai/manager-tdd.md +784 -0
  159. moai_adk/templates/.claude/agents/moai/mcp-context7.md +458 -0
  160. moai_adk/templates/.claude/agents/moai/mcp-figma.md +1607 -0
  161. moai_adk/templates/.claude/agents/moai/mcp-notion.md +789 -0
  162. moai_adk/templates/.claude/agents/moai/mcp-playwright.md +469 -0
  163. moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +1032 -0
  164. moai_adk/templates/.claude/commands/moai/0-project.md +1384 -0
  165. moai_adk/templates/.claude/commands/moai/1-plan.md +1427 -0
  166. moai_adk/templates/.claude/commands/moai/2-run.md +943 -0
  167. moai_adk/templates/.claude/commands/moai/3-sync.md +1324 -0
  168. moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
  169. moai_adk/templates/.claude/hooks/__init__.py +8 -0
  170. moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
  171. moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
  172. moai_adk/templates/.claude/hooks/{alfred/core → moai/lib}/checkpoint.py +10 -37
  173. moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
  174. moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
  175. moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
  176. moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
  177. moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
  178. moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
  179. moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
  180. moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
  181. moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
  182. moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
  183. moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
  184. moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
  185. moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
  186. moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +1075 -0
  187. moai_adk/templates/.claude/output-styles/moai/r2d2.md +560 -0
  188. moai_adk/templates/.claude/output-styles/moai/yoda.md +359 -0
  189. moai_adk/templates/.claude/settings.json +78 -50
  190. moai_adk/templates/.claude/skills/moai-ai-nano-banana/SKILL.md +438 -0
  191. moai_adk/templates/.claude/skills/moai-ai-nano-banana/examples.md +431 -0
  192. moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +249 -0
  193. moai_adk/templates/.claude/skills/moai-docs-generation/examples.md +406 -0
  194. moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
  195. moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
  196. moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
  197. moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
  198. moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
  199. moai_adk/templates/.claude/skills/moai-docs-generation/reference.md +328 -0
  200. moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +313 -283
  201. moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +610 -1525
  202. moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +423 -619
  203. moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +295 -95
  204. moai_adk/templates/.claude/skills/moai-domain-database/examples.md +817 -16
  205. moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
  206. moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
  207. moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
  208. moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
  209. moai_adk/templates/.claude/skills/moai-domain-database/reference.md +532 -17
  210. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +470 -97
  211. moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +955 -16
  212. moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +651 -18
  213. moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +455 -0
  214. moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
  215. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
  216. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
  217. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/design-system-tokens.md +405 -0
  218. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
  219. moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
  220. moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
  221. moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +492 -0
  222. moai_adk/templates/.claude/skills/moai-formats-data/examples.md +804 -0
  223. moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
  224. moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
  225. moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
  226. moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
  227. moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
  228. moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
  229. moai_adk/templates/.claude/skills/moai-formats-data/reference.md +585 -0
  230. moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +202 -0
  231. moai_adk/templates/.claude/skills/moai-foundation-claude/examples.md +732 -0
  232. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
  233. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
  234. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
  235. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
  236. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
  237. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
  238. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
  239. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
  240. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
  241. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
  242. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
  243. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
  244. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
  245. moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
  246. moai_adk/templates/.claude/skills/moai-foundation-claude/reference.md +209 -0
  247. moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +441 -0
  248. moai_adk/templates/.claude/skills/moai-foundation-context/examples.md +1048 -0
  249. moai_adk/templates/.claude/skills/moai-foundation-context/reference.md +246 -0
  250. moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +420 -0
  251. moai_adk/templates/.claude/skills/moai-foundation-core/examples.md +358 -0
  252. moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
  253. moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +359 -0
  254. moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
  255. moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
  256. moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
  257. moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
  258. moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
  259. moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
  260. moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
  261. moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
  262. moai_adk/templates/.claude/skills/moai-foundation-core/reference.md +478 -0
  263. moai_adk/templates/.claude/skills/moai-foundation-philosopher/SKILL.md +315 -0
  264. moai_adk/templates/.claude/skills/moai-foundation-philosopher/examples.md +228 -0
  265. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/assumption-matrix.md +80 -0
  266. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/cognitive-bias.md +199 -0
  267. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/first-principles.md +140 -0
  268. moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/trade-off-analysis.md +154 -0
  269. moai_adk/templates/.claude/skills/moai-foundation-philosopher/reference.md +157 -0
  270. moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +364 -0
  271. moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
  272. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
  273. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
  274. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
  275. moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
  276. moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
  277. moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
  278. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
  279. moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
  280. moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +618 -93
  281. moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +446 -91
  282. moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +612 -0
  283. moai_adk/templates/.claude/skills/moai-lang-flutter/SKILL.md +477 -0
  284. moai_adk/templates/.claude/skills/moai-lang-flutter/examples.md +1090 -0
  285. moai_adk/templates/.claude/skills/moai-lang-flutter/reference.md +686 -0
  286. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +346 -94
  287. moai_adk/templates/.claude/skills/moai-lang-go/examples.md +906 -16
  288. moai_adk/templates/.claude/skills/moai-lang-go/reference.md +721 -15
  289. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +352 -91
  290. moai_adk/templates/.claude/skills/moai-lang-java/examples.md +851 -16
  291. moai_adk/templates/.claude/skills/moai-lang-java/reference.md +278 -18
  292. moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +344 -86
  293. moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +993 -16
  294. moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +549 -18
  295. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +617 -96
  296. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +364 -314
  297. moai_adk/templates/.claude/skills/moai-lang-python/examples.md +849 -496
  298. moai_adk/templates/.claude/skills/moai-lang-python/reference.md +731 -243
  299. moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +545 -89
  300. moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +650 -87
  301. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +341 -93
  302. moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +646 -16
  303. moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +491 -18
  304. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +463 -89
  305. moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +620 -16
  306. moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +410 -17
  307. moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +486 -112
  308. moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +905 -16
  309. moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +659 -17
  310. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +333 -92
  311. moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +1076 -16
  312. moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +718 -21
  313. moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +300 -0
  314. moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
  315. moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
  316. moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
  317. moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
  318. moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +319 -0
  319. moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
  320. moai_adk/templates/.claude/skills/moai-library-nextra/examples.md +592 -0
  321. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
  322. moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
  323. moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
  324. moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
  325. moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
  326. moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
  327. moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
  328. moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
  329. moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
  330. moai_adk/templates/.claude/skills/moai-library-nextra/reference.md +379 -0
  331. moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +372 -0
  332. moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
  333. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
  334. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
  335. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
  336. moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
  337. moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
  338. moai_adk/templates/.claude/skills/moai-mcp-figma/SKILL.md +402 -0
  339. moai_adk/templates/.claude/skills/moai-mcp-figma/advanced-patterns.md +607 -0
  340. moai_adk/templates/.claude/skills/moai-mcp-notion/SKILL.md +300 -0
  341. moai_adk/templates/.claude/skills/moai-mcp-notion/advanced-patterns.md +537 -0
  342. moai_adk/templates/.claude/skills/moai-platform-auth0/SKILL.md +290 -0
  343. moai_adk/templates/.claude/skills/moai-platform-clerk/SKILL.md +390 -0
  344. moai_adk/templates/.claude/skills/moai-platform-convex/SKILL.md +398 -0
  345. moai_adk/templates/.claude/skills/moai-platform-firebase-auth/SKILL.md +379 -0
  346. moai_adk/templates/.claude/skills/moai-platform-firestore/SKILL.md +358 -0
  347. moai_adk/templates/.claude/skills/moai-platform-neon/SKILL.md +467 -0
  348. moai_adk/templates/.claude/skills/moai-platform-railway/SKILL.md +377 -0
  349. moai_adk/templates/.claude/skills/moai-platform-supabase/SKILL.md +466 -0
  350. moai_adk/templates/.claude/skills/moai-platform-vercel/SKILL.md +482 -0
  351. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +449 -0
  352. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
  353. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/examples.md +544 -0
  354. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
  355. moai_adk/templates/.claude/skills/moai-workflow-jit-docs/reference.md +307 -0
  356. moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
  357. moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +390 -0
  358. moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
  359. moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
  360. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
  361. moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
  362. moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
  363. moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +175 -0
  364. moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
  365. moai_adk/templates/.claude/skills/moai-workflow-project/examples.md +547 -0
  366. moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
  367. moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
  368. moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
  369. moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
  370. moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
  371. moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
  372. moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
  373. moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
  374. moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
  375. moai_adk/templates/.claude/skills/moai-workflow-project/reference.md +275 -0
  376. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
  377. moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1462 -0
  378. moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
  379. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
  380. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
  381. moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +92 -0
  382. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
  383. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
  384. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
  385. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
  386. moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
  387. moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
  388. moai_adk/templates/.claude/skills/moai-workflow-spec/SKILL.md +534 -0
  389. moai_adk/templates/.claude/skills/moai-workflow-spec/examples.md +900 -0
  390. moai_adk/templates/.claude/skills/moai-workflow-spec/reference.md +704 -0
  391. moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +377 -0
  392. moai_adk/templates/.claude/skills/moai-workflow-templates/examples.md +552 -0
  393. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
  394. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
  395. moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
  396. moai_adk/templates/.claude/skills/moai-workflow-templates/reference.md +346 -0
  397. moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
  398. moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +456 -0
  399. moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
  400. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
  401. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
  402. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
  403. moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
  404. moai_adk/templates/.claude/skills/moai-workflow-testing/examples.md +672 -0
  405. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
  406. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
  407. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
  408. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
  409. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
  410. moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
  411. moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
  412. moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
  413. moai_adk/templates/.claude/skills/moai-workflow-testing/reference.md +440 -0
  414. moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
  415. moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
  416. moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
  417. moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +411 -0
  418. moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
  419. moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
  420. moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
  421. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
  422. moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
  423. moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
  424. moai_adk/templates/.git-hooks/pre-commit +128 -0
  425. moai_adk/templates/.git-hooks/pre-push +365 -0
  426. moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
  427. moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
  428. moai_adk/templates/.github/workflows/spec-issue-sync.yml +206 -36
  429. moai_adk/templates/.gitignore +194 -13
  430. moai_adk/templates/.mcp.json +31 -0
  431. moai_adk/templates/.moai/config/config.yaml +58 -0
  432. moai_adk/templates/.moai/config/questions/_schema.yaml +151 -0
  433. moai_adk/templates/.moai/config/questions/tab0-init.yaml +251 -0
  434. moai_adk/templates/.moai/config/questions/tab1-user.yaml +108 -0
  435. moai_adk/templates/.moai/config/questions/tab2-project.yaml +81 -0
  436. moai_adk/templates/.moai/config/questions/tab3-git.yaml +634 -0
  437. moai_adk/templates/.moai/config/questions/tab4-quality.yaml +170 -0
  438. moai_adk/templates/.moai/config/questions/tab5-system.yaml +87 -0
  439. moai_adk/templates/.moai/config/sections/git-strategy.yaml +116 -0
  440. moai_adk/templates/.moai/config/sections/language.yaml +11 -0
  441. moai_adk/templates/.moai/config/sections/project.yaml +13 -0
  442. moai_adk/templates/.moai/config/sections/quality.yaml +17 -0
  443. moai_adk/templates/.moai/config/sections/system.yaml +14 -0
  444. moai_adk/templates/.moai/config/sections/user.yaml +5 -0
  445. moai_adk/templates/.moai/config/statusline-config.yaml +92 -0
  446. moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
  447. moai_adk/templates/CLAUDE.md +571 -244
  448. moai_adk/utils/__init__.py +24 -2
  449. moai_adk/utils/banner.py +9 -13
  450. moai_adk/utils/common.py +294 -0
  451. moai_adk/utils/link_validator.py +241 -0
  452. moai_adk/utils/logger.py +4 -9
  453. moai_adk/utils/safe_file_reader.py +206 -0
  454. moai_adk/utils/timeout.py +160 -0
  455. moai_adk/utils/toon_utils.py +256 -0
  456. moai_adk/version.py +22 -0
  457. moai_adk-0.34.0.dist-info/METADATA +2999 -0
  458. moai_adk-0.34.0.dist-info/RECORD +463 -0
  459. {moai_adk-0.8.0.dist-info → moai_adk-0.34.0.dist-info}/WHEEL +1 -1
  460. {moai_adk-0.8.0.dist-info → moai_adk-0.34.0.dist-info}/entry_points.txt +1 -0
  461. moai_adk/cli/commands/backup.py +0 -80
  462. moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -293
  463. moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -196
  464. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -207
  465. moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -375
  466. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +0 -343
  467. moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -246
  468. moai_adk/templates/.claude/agents/alfred/quality-gate.md +0 -320
  469. moai_adk/templates/.claude/agents/alfred/skill-factory.md +0 -837
  470. moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -272
  471. moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -265
  472. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +0 -311
  473. moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -352
  474. moai_adk/templates/.claude/commands/alfred/0-project.md +0 -1184
  475. moai_adk/templates/.claude/commands/alfred/1-plan.md +0 -665
  476. moai_adk/templates/.claude/commands/alfred/2-run.md +0 -488
  477. moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -623
  478. moai_adk/templates/.claude/hooks/alfred/HOOK_SCHEMA_VALIDATION.md +0 -313
  479. moai_adk/templates/.claude/hooks/alfred/README.md +0 -230
  480. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -174
  481. moai_adk/templates/.claude/hooks/alfred/core/__init__.py +0 -170
  482. moai_adk/templates/.claude/hooks/alfred/core/context.py +0 -67
  483. moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -416
  484. moai_adk/templates/.claude/hooks/alfred/core/tags.py +0 -198
  485. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -21
  486. moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
  487. moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -161
  488. moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -90
  489. moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -42
  490. moai_adk/templates/.claude/hooks/alfred/test_hook_output.py +0 -175
  491. moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -640
  492. moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -696
  493. moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -474
  494. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/SKILL.md +0 -113
  495. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/examples.md +0 -29
  496. moai_adk/templates/.claude/skills/moai-alfred-ears-authoring/reference.md +0 -28
  497. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/SKILL.md +0 -122
  498. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/examples.md +0 -29
  499. moai_adk/templates/.claude/skills/moai-alfred-git-workflow/reference.md +0 -29
  500. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/SKILL.md +0 -237
  501. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/examples.md +0 -615
  502. moai_adk/templates/.claude/skills/moai-alfred-interactive-questions/reference.md +0 -653
  503. moai_adk/templates/.claude/skills/moai-alfred-language-detection/SKILL.md +0 -113
  504. moai_adk/templates/.claude/skills/moai-alfred-language-detection/examples.md +0 -29
  505. moai_adk/templates/.claude/skills/moai-alfred-language-detection/reference.md +0 -28
  506. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/SKILL.md +0 -113
  507. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/examples.md +0 -29
  508. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-validation/reference.md +0 -28
  509. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/SKILL.md +0 -113
  510. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/examples.md +0 -29
  511. moai_adk/templates/.claude/skills/moai-alfred-tag-scanning/reference.md +0 -28
  512. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/SKILL.md +0 -113
  513. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/examples.md +0 -29
  514. moai_adk/templates/.claude/skills/moai-alfred-trust-validation/reference.md +0 -28
  515. moai_adk/templates/.claude/skills/moai-cc-agents/SKILL.md +0 -269
  516. moai_adk/templates/.claude/skills/moai-cc-agents/templates/agent-template.md +0 -32
  517. moai_adk/templates/.claude/skills/moai-cc-claude-md/SKILL.md +0 -298
  518. moai_adk/templates/.claude/skills/moai-cc-claude-md/templates/CLAUDE-template.md +0 -26
  519. moai_adk/templates/.claude/skills/moai-cc-commands/SKILL.md +0 -307
  520. moai_adk/templates/.claude/skills/moai-cc-commands/templates/command-template.md +0 -21
  521. moai_adk/templates/.claude/skills/moai-cc-hooks/SKILL.md +0 -252
  522. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/pre-bash-check.sh +0 -19
  523. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/preserve-permissions.sh +0 -19
  524. moai_adk/templates/.claude/skills/moai-cc-hooks/scripts/validate-bash-command.py +0 -24
  525. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/SKILL.md +0 -199
  526. moai_adk/templates/.claude/skills/moai-cc-mcp-plugins/templates/settings-mcp-template.json +0 -39
  527. moai_adk/templates/.claude/skills/moai-cc-memory/SKILL.md +0 -316
  528. moai_adk/templates/.claude/skills/moai-cc-memory/templates/session-summary-template.md +0 -18
  529. moai_adk/templates/.claude/skills/moai-cc-settings/SKILL.md +0 -263
  530. moai_adk/templates/.claude/skills/moai-cc-settings/templates/settings-complete-template.json +0 -30
  531. moai_adk/templates/.claude/skills/moai-cc-skills/SKILL.md +0 -291
  532. moai_adk/templates/.claude/skills/moai-cc-skills/templates/SKILL-template.md +0 -15
  533. moai_adk/templates/.claude/skills/moai-domain-cli-tool/SKILL.md +0 -123
  534. moai_adk/templates/.claude/skills/moai-domain-cli-tool/examples.md +0 -29
  535. moai_adk/templates/.claude/skills/moai-domain-cli-tool/reference.md +0 -30
  536. moai_adk/templates/.claude/skills/moai-domain-data-science/SKILL.md +0 -123
  537. moai_adk/templates/.claude/skills/moai-domain-data-science/examples.md +0 -29
  538. moai_adk/templates/.claude/skills/moai-domain-data-science/reference.md +0 -30
  539. moai_adk/templates/.claude/skills/moai-domain-devops/SKILL.md +0 -124
  540. moai_adk/templates/.claude/skills/moai-domain-devops/examples.md +0 -29
  541. moai_adk/templates/.claude/skills/moai-domain-devops/reference.md +0 -31
  542. moai_adk/templates/.claude/skills/moai-domain-ml/SKILL.md +0 -123
  543. moai_adk/templates/.claude/skills/moai-domain-ml/examples.md +0 -29
  544. moai_adk/templates/.claude/skills/moai-domain-ml/reference.md +0 -30
  545. moai_adk/templates/.claude/skills/moai-domain-mobile-app/SKILL.md +0 -123
  546. moai_adk/templates/.claude/skills/moai-domain-mobile-app/examples.md +0 -29
  547. moai_adk/templates/.claude/skills/moai-domain-mobile-app/reference.md +0 -30
  548. moai_adk/templates/.claude/skills/moai-domain-security/SKILL.md +0 -123
  549. moai_adk/templates/.claude/skills/moai-domain-security/examples.md +0 -29
  550. moai_adk/templates/.claude/skills/moai-domain-security/reference.md +0 -30
  551. moai_adk/templates/.claude/skills/moai-domain-web-api/SKILL.md +0 -123
  552. moai_adk/templates/.claude/skills/moai-domain-web-api/examples.md +0 -29
  553. moai_adk/templates/.claude/skills/moai-domain-web-api/reference.md +0 -30
  554. moai_adk/templates/.claude/skills/moai-essentials-debug/SKILL.md +0 -303
  555. moai_adk/templates/.claude/skills/moai-essentials-debug/examples.md +0 -1064
  556. moai_adk/templates/.claude/skills/moai-essentials-debug/reference.md +0 -1047
  557. moai_adk/templates/.claude/skills/moai-essentials-perf/SKILL.md +0 -113
  558. moai_adk/templates/.claude/skills/moai-essentials-perf/examples.md +0 -29
  559. moai_adk/templates/.claude/skills/moai-essentials-perf/reference.md +0 -28
  560. moai_adk/templates/.claude/skills/moai-essentials-refactor/SKILL.md +0 -113
  561. moai_adk/templates/.claude/skills/moai-essentials-refactor/examples.md +0 -29
  562. moai_adk/templates/.claude/skills/moai-essentials-refactor/reference.md +0 -28
  563. moai_adk/templates/.claude/skills/moai-essentials-review/SKILL.md +0 -113
  564. moai_adk/templates/.claude/skills/moai-essentials-review/examples.md +0 -29
  565. moai_adk/templates/.claude/skills/moai-essentials-review/reference.md +0 -28
  566. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +0 -113
  567. moai_adk/templates/.claude/skills/moai-foundation-ears/examples.md +0 -29
  568. moai_adk/templates/.claude/skills/moai-foundation-ears/reference.md +0 -28
  569. moai_adk/templates/.claude/skills/moai-foundation-git/SKILL.md +0 -122
  570. moai_adk/templates/.claude/skills/moai-foundation-git/examples.md +0 -29
  571. moai_adk/templates/.claude/skills/moai-foundation-git/reference.md +0 -29
  572. moai_adk/templates/.claude/skills/moai-foundation-langs/SKILL.md +0 -113
  573. moai_adk/templates/.claude/skills/moai-foundation-langs/examples.md +0 -29
  574. moai_adk/templates/.claude/skills/moai-foundation-langs/reference.md +0 -28
  575. moai_adk/templates/.claude/skills/moai-foundation-specs/SKILL.md +0 -113
  576. moai_adk/templates/.claude/skills/moai-foundation-specs/examples.md +0 -29
  577. moai_adk/templates/.claude/skills/moai-foundation-specs/reference.md +0 -28
  578. moai_adk/templates/.claude/skills/moai-foundation-tags/SKILL.md +0 -113
  579. moai_adk/templates/.claude/skills/moai-foundation-tags/examples.md +0 -29
  580. moai_adk/templates/.claude/skills/moai-foundation-tags/reference.md +0 -28
  581. moai_adk/templates/.claude/skills/moai-foundation-trust/SKILL.md +0 -307
  582. moai_adk/templates/.claude/skills/moai-foundation-trust/examples.md +0 -0
  583. moai_adk/templates/.claude/skills/moai-foundation-trust/reference.md +0 -1099
  584. moai_adk/templates/.claude/skills/moai-lang-c/SKILL.md +0 -124
  585. moai_adk/templates/.claude/skills/moai-lang-c/examples.md +0 -29
  586. moai_adk/templates/.claude/skills/moai-lang-c/reference.md +0 -31
  587. moai_adk/templates/.claude/skills/moai-lang-cpp/examples.md +0 -29
  588. moai_adk/templates/.claude/skills/moai-lang-cpp/reference.md +0 -31
  589. moai_adk/templates/.claude/skills/moai-lang-csharp/examples.md +0 -29
  590. moai_adk/templates/.claude/skills/moai-lang-csharp/reference.md +0 -30
  591. moai_adk/templates/.claude/skills/moai-lang-dart/SKILL.md +0 -123
  592. moai_adk/templates/.claude/skills/moai-lang-dart/examples.md +0 -29
  593. moai_adk/templates/.claude/skills/moai-lang-dart/reference.md +0 -30
  594. moai_adk/templates/.claude/skills/moai-lang-javascript/SKILL.md +0 -125
  595. moai_adk/templates/.claude/skills/moai-lang-javascript/examples.md +0 -29
  596. moai_adk/templates/.claude/skills/moai-lang-javascript/reference.md +0 -32
  597. moai_adk/templates/.claude/skills/moai-lang-php/examples.md +0 -29
  598. moai_adk/templates/.claude/skills/moai-lang-php/reference.md +0 -30
  599. moai_adk/templates/.claude/skills/moai-lang-r/examples.md +0 -29
  600. moai_adk/templates/.claude/skills/moai-lang-r/reference.md +0 -30
  601. moai_adk/templates/.claude/skills/moai-lang-ruby/examples.md +0 -29
  602. moai_adk/templates/.claude/skills/moai-lang-ruby/reference.md +0 -31
  603. moai_adk/templates/.claude/skills/moai-lang-shell/SKILL.md +0 -123
  604. moai_adk/templates/.claude/skills/moai-lang-shell/examples.md +0 -29
  605. moai_adk/templates/.claude/skills/moai-lang-shell/reference.md +0 -30
  606. moai_adk/templates/.claude/skills/moai-lang-sql/SKILL.md +0 -124
  607. moai_adk/templates/.claude/skills/moai-lang-sql/examples.md +0 -29
  608. moai_adk/templates/.claude/skills/moai-lang-sql/reference.md +0 -31
  609. moai_adk/templates/.claude/skills/moai-skill-factory/CHECKLIST.md +0 -482
  610. moai_adk/templates/.claude/skills/moai-skill-factory/EXAMPLES.md +0 -278
  611. moai_adk/templates/.claude/skills/moai-skill-factory/INTERACTIVE-DISCOVERY.md +0 -524
  612. moai_adk/templates/.claude/skills/moai-skill-factory/METADATA.md +0 -477
  613. moai_adk/templates/.claude/skills/moai-skill-factory/PARALLEL-ANALYSIS-REPORT.md +0 -429
  614. moai_adk/templates/.claude/skills/moai-skill-factory/PYTHON-VERSION-MATRIX.md +0 -391
  615. moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-FACTORY-WORKFLOW.md +0 -431
  616. moai_adk/templates/.claude/skills/moai-skill-factory/SKILL-UPDATE-ADVISOR.md +0 -577
  617. moai_adk/templates/.claude/skills/moai-skill-factory/SKILL.md +0 -271
  618. moai_adk/templates/.claude/skills/moai-skill-factory/STEP-BY-STEP-GUIDE.md +0 -466
  619. moai_adk/templates/.claude/skills/moai-skill-factory/STRUCTURE.md +0 -583
  620. moai_adk/templates/.claude/skills/moai-skill-factory/WEB-RESEARCH.md +0 -526
  621. moai_adk/templates/.claude/skills/moai-skill-factory/reference.md +0 -465
  622. moai_adk/templates/.claude/skills/moai-skill-factory/scripts/generate-structure.sh +0 -328
  623. moai_adk/templates/.claude/skills/moai-skill-factory/scripts/validate-skill.sh +0 -312
  624. moai_adk/templates/.claude/skills/moai-skill-factory/templates/SKILL_TEMPLATE.md +0 -245
  625. moai_adk/templates/.claude/skills/moai-skill-factory/templates/examples-template.md +0 -285
  626. moai_adk/templates/.claude/skills/moai-skill-factory/templates/reference-template.md +0 -278
  627. moai_adk/templates/.claude/skills/moai-skill-factory/templates/scripts-template.sh +0 -303
  628. moai_adk/templates/.claude/skills/moai-spec-authoring/README.md +0 -137
  629. moai_adk/templates/.claude/skills/moai-spec-authoring/SKILL.md +0 -218
  630. moai_adk/templates/.claude/skills/moai-spec-authoring/examples/validate-spec.sh +0 -161
  631. moai_adk/templates/.claude/skills/moai-spec-authoring/examples.md +0 -541
  632. moai_adk/templates/.claude/skills/moai-spec-authoring/reference.md +0 -622
  633. moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +0 -176
  634. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
  635. moai_adk/templates/.github/workflows/moai-gitflow.yml +0 -256
  636. moai_adk/templates/.moai/config.json +0 -96
  637. moai_adk/templates/.moai/memory/CLAUDE-AGENTS-GUIDE.md +0 -208
  638. moai_adk/templates/.moai/memory/CLAUDE-PRACTICES.md +0 -369
  639. moai_adk/templates/.moai/memory/CLAUDE-RULES.md +0 -539
  640. moai_adk/templates/.moai/memory/CONFIG-SCHEMA.md +0 -444
  641. moai_adk/templates/.moai/memory/DEVELOPMENT-GUIDE.md +0 -344
  642. moai_adk/templates/.moai/memory/GITFLOW-PROTECTION-POLICY.md +0 -220
  643. moai_adk/templates/.moai/memory/SKILLS-DESCRIPTION-POLICY.md +0 -218
  644. moai_adk/templates/.moai/memory/SPEC-METADATA.md +0 -356
  645. moai_adk/templates/.moai/memory/config-schema.md +0 -444
  646. moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
  647. moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
  648. moai_adk/templates/.moai/project/product.md +0 -161
  649. moai_adk/templates/.moai/project/structure.md +0 -156
  650. moai_adk/templates/.moai/project/tech.md +0 -227
  651. moai_adk/templates/__init__.py +0 -2
  652. moai_adk-0.8.0.dist-info/METADATA +0 -1722
  653. moai_adk-0.8.0.dist-info/RECORD +0 -282
  654. {moai_adk-0.8.0.dist-info → moai_adk-0.34.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,624 +1,977 @@
1
- # Python 3.13 Code Examples
1
+ # Python Production-Ready Code Examples
2
2
 
3
- Production-ready examples for modern Python development with pytest 8.4.2, ruff 0.13.1, mypy 1.8.0, FastAPI 0.115.0, and Python 3.13.1 features.
3
+ ## Complete FastAPI Application
4
4
 
5
- ---
6
-
7
- ## Example 1: pytest 8.4.2 with Fixtures and Async Tests
5
+ ### Project Structure
6
+ ```
7
+ fastapi_app/
8
+ ├── app/
9
+ │ ├── __init__.py
10
+ │ ├── main.py
11
+ │ ├── config.py
12
+ │ ├── database.py
13
+ │ ├── dependencies.py
14
+ │ ├── models/
15
+ │ │ ├── __init__.py
16
+ │ │ └── user.py
17
+ │ ├── schemas/
18
+ │ │ ├── __init__.py
19
+ │ │ └── user.py
20
+ │ ├── repositories/
21
+ │ │ ├── __init__.py
22
+ │ │ └── user_repository.py
23
+ │ ├── services/
24
+ │ │ ├── __init__.py
25
+ │ │ └── user_service.py
26
+ │ └── api/
27
+ │ ├── __init__.py
28
+ │ └── v1/
29
+ │ ├── __init__.py
30
+ │ ├── router.py
31
+ │ └── endpoints/
32
+ │ └── users.py
33
+ ├── tests/
34
+ │ ├── conftest.py
35
+ │ ├── test_users.py
36
+ │ └── test_services.py
37
+ ├── pyproject.toml
38
+ └── Dockerfile
39
+ ```
8
40
 
9
- ### Test File: `tests/test_user_service.py`
41
+ ### Main Application Entry
10
42
 
11
43
  ```python
12
- """
13
- Test suite for UserService with pytest fixtures and async support.
14
- Demonstrates pytest 8.4.2 best practices for Python 3.13.
15
- """
16
- import pytest
17
- from unittest.mock import AsyncMock
18
- from src.services.user_service import UserService
19
- from src.models.user import User
20
-
21
-
22
- @pytest.fixture
23
- def user_service():
24
- """Fixture providing a UserService instance with mocked dependencies."""
25
- return UserService(db_client=AsyncMock())
44
+ # app/main.py
45
+ from contextlib import asynccontextmanager
46
+ from fastapi import FastAPI
47
+ from fastapi.middleware.cors import CORSMiddleware
48
+
49
+ from app.config import get_settings
50
+ from app.database import init_db, close_db
51
+ from app.api.v1.router import api_router
52
+
53
+ settings = get_settings()
54
+
55
+ @asynccontextmanager
56
+ async def lifespan(app: FastAPI):
57
+ # Startup
58
+ await init_db()
59
+ yield
60
+ # Shutdown
61
+ await close_db()
62
+
63
+ app = FastAPI(
64
+ title=settings.app_name,
65
+ version="1.0.0",
66
+ lifespan=lifespan,
67
+ docs_url="/api/docs",
68
+ redoc_url="/api/redoc",
69
+ )
70
+
71
+ # CORS middleware
72
+ app.add_middleware(
73
+ CORSMiddleware,
74
+ allow_origins=settings.cors_origins,
75
+ allow_credentials=True,
76
+ allow_methods=["*"],
77
+ allow_headers=["*"],
78
+ )
79
+
80
+ # Include API router
81
+ app.include_router(api_router, prefix="/api/v1")
82
+
83
+ @app.get("/health")
84
+ async def health_check():
85
+ return {"status": "healthy", "version": "1.0.0"}
86
+ ```
26
87
 
88
+ ### Configuration
27
89
 
28
- @pytest.fixture
29
- def sample_user():
30
- """Fixture providing a sample User instance for tests."""
31
- return User(id=1, name="Alice", email="alice@example.com")
90
+ ```python
91
+ # app/config.py
92
+ from functools import lru_cache
93
+ from pydantic_settings import BaseSettings, SettingsConfigDict
94
+
95
+ class Settings(BaseSettings):
96
+ model_config = SettingsConfigDict(
97
+ env_file=".env",
98
+ env_file_encoding="utf-8",
99
+ case_sensitive=False,
100
+ )
32
101
 
102
+ # Application
103
+ app_name: str = "FastAPI App"
104
+ debug: bool = False
105
+ environment: str = "development"
33
106
 
34
- def test_user_creation(user_service, sample_user):
35
- """Verify user creation with valid data."""
36
- result = user_service.validate_user(sample_user)
37
- assert result is True
38
- assert sample_user.id > 0
107
+ # Database
108
+ database_url: str = "postgresql+asyncpg://user:pass@localhost/db"
109
+ db_pool_size: int = 5
110
+ db_max_overflow: int = 10
111
+ db_pool_timeout: int = 30
39
112
 
113
+ # Security
114
+ secret_key: str
115
+ access_token_expire_minutes: int = 30
116
+ refresh_token_expire_days: int = 7
117
+ algorithm: str = "HS256"
40
118
 
41
- @pytest.mark.asyncio
42
- async def test_fetch_user_async(user_service):
43
- """Test async user fetching with mocked database."""
44
- user_service.db_client.fetch_user.return_value = User(
45
- id=1, name="Bob", email="bob@example.com"
46
- )
119
+ # CORS
120
+ cors_origins: list[str] = ["http://localhost:3000"]
47
121
 
48
- user = await user_service.fetch_user(user_id=1)
122
+ # Redis (optional)
123
+ redis_url: str | None = None
49
124
 
50
- assert user is not None
51
- assert user.name == "Bob"
52
- user_service.db_client.fetch_user.assert_called_once_with(1)
125
+ @lru_cache
126
+ def get_settings() -> Settings:
127
+ return Settings()
128
+ ```
53
129
 
130
+ ### Database Setup
54
131
 
55
- @pytest.mark.parametrize("user_id,expected_name", [
56
- (1, "Alice"),
57
- (2, "Bob"),
58
- (3, "Charlie"),
59
- ])
60
- @pytest.mark.asyncio
61
- async def test_fetch_multiple_users(user_service, user_id, expected_name):
62
- """Parametrized test for fetching multiple users."""
63
- user_service.db_client.fetch_user.return_value = User(
64
- id=user_id, name=expected_name, email=f"{expected_name.lower()}@example.com"
132
+ ```python
133
+ # app/database.py
134
+ from sqlalchemy.ext.asyncio import (
135
+ create_async_engine,
136
+ async_sessionmaker,
137
+ AsyncSession,
138
+ AsyncEngine,
139
+ )
140
+ from sqlalchemy.orm import DeclarativeBase
141
+
142
+ from app.config import get_settings
143
+
144
+ settings = get_settings()
145
+
146
+ class Base(DeclarativeBase):
147
+ pass
148
+
149
+ engine: AsyncEngine | None = None
150
+ async_session_factory: async_sessionmaker[AsyncSession] | None = None
151
+
152
+ async def init_db():
153
+ global engine, async_session_factory
154
+
155
+ engine = create_async_engine(
156
+ settings.database_url,
157
+ pool_size=settings.db_pool_size,
158
+ max_overflow=settings.db_max_overflow,
159
+ pool_timeout=settings.db_pool_timeout,
160
+ pool_pre_ping=True,
161
+ echo=settings.debug,
65
162
  )
66
163
 
67
- user = await user_service.fetch_user(user_id=user_id)
164
+ async_session_factory = async_sessionmaker(
165
+ engine,
166
+ class_=AsyncSession,
167
+ expire_on_commit=False,
168
+ autoflush=False,
169
+ )
68
170
 
69
- assert user.name == expected_name
171
+ # Create tables (for development only)
172
+ if settings.debug:
173
+ async with engine.begin() as conn:
174
+ await conn.run_sync(Base.metadata.create_all)
175
+
176
+ async def close_db():
177
+ global engine
178
+ if engine:
179
+ await engine.dispose()
180
+
181
+ async def get_db() -> AsyncSession:
182
+ if async_session_factory is None:
183
+ raise RuntimeError("Database not initialized")
184
+
185
+ async with async_session_factory() as session:
186
+ try:
187
+ yield session
188
+ await session.commit()
189
+ except Exception:
190
+ await session.rollback()
191
+ raise
70
192
  ```
71
193
 
72
- **Key Features**:
73
- - ✅ Fixtures for dependency injection
74
- - ✅ `@pytest.mark.asyncio` for async tests
75
- - ✅ `@pytest.mark.parametrize` for data-driven tests
76
- - ✅ AsyncMock for mocking async operations
77
- - ✅ One assertion per test (clarity)
78
-
79
- **Run Commands**:
80
- ```bash
81
- pytest tests/test_user_service.py -v
82
- pytest tests/test_user_service.py --cov=src.services --cov-report=term
83
- ```
194
+ ### SQLAlchemy Models
84
195
 
85
- ---
196
+ ```python
197
+ # app/models/user.py
198
+ from datetime import datetime
199
+ from sqlalchemy import String, Boolean, DateTime, func
200
+ from sqlalchemy.orm import Mapped, mapped_column
86
201
 
87
- ## Example 2: ruff 0.13.1 Linting and Formatting Workflow
202
+ from app.database import Base
88
203
 
89
- ### Project Configuration: `pyproject.toml`
204
+ class User(Base):
205
+ __tablename__ = "users"
90
206
 
91
- ```toml
92
- [tool.ruff]
93
- line-length = 100
94
- target-version = "py313"
95
- exclude = [".venv", "build", "dist", "__pycache__"]
207
+ id: Mapped[int] = mapped_column(primary_key=True, index=True)
208
+ email: Mapped[str] = mapped_column(
209
+ String(255), unique=True, index=True, nullable=False
210
+ )
211
+ hashed_password: Mapped[str] = mapped_column(String(255), nullable=False)
212
+ name: Mapped[str] = mapped_column(String(100), nullable=False)
213
+ is_active: Mapped[bool] = mapped_column(Boolean, default=True)
214
+ is_superuser: Mapped[bool] = mapped_column(Boolean, default=False)
215
+ created_at: Mapped[datetime] = mapped_column(
216
+ DateTime(timezone=True), server_default=func.now()
217
+ )
218
+ updated_at: Mapped[datetime] = mapped_column(
219
+ DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
220
+ )
96
221
 
97
- [tool.ruff.lint]
98
- select = [
99
- "E", # pycodestyle errors
100
- "F", # pyflakes
101
- "W", # pycodestyle warnings
102
- "I", # isort (import sorting)
103
- "N", # pep8-naming
104
- "UP", # pyupgrade (use Python 3.13 features)
105
- "B", # flake8-bugbear
106
- "C4", # flake8-comprehensions
107
- ]
108
- ignore = ["E501"] # Line length handled by formatter
109
-
110
- [tool.ruff.lint.per-file-ignores]
111
- "tests/**/*.py" = ["F401", "F811"] # Allow unused imports in tests
112
-
113
- [tool.ruff.format]
114
- quote-style = "double"
115
- indent-style = "space"
222
+ def __repr__(self) -> str:
223
+ return f"<User(id={self.id}, email={self.email})>"
116
224
  ```
117
225
 
118
- ### Example Source File: `src/utils/formatter.py`
226
+ ### Pydantic Schemas
119
227
 
120
228
  ```python
121
- """String formatting utilities using Python 3.13 features."""
122
- from typing import override
123
-
124
-
125
- class Formatter:
126
- """Base formatter class."""
127
-
128
- def format(self, text: str) -> str:
129
- """Format text with default behavior."""
130
- return text.strip()
229
+ # app/schemas/user.py
230
+ from datetime import datetime
231
+ from pydantic import BaseModel, ConfigDict, EmailStr, Field
131
232
 
233
+ class UserBase(BaseModel):
234
+ email: EmailStr
235
+ name: str = Field(min_length=1, max_length=100)
132
236
 
133
- class UppercaseFormatter(Formatter):
134
- """Formatter that converts text to uppercase."""
237
+ class UserCreate(UserBase):
238
+ password: str = Field(min_length=8, max_length=100)
135
239
 
136
- @override # Python 3.13 PEP 698
137
- def format(self, text: str) -> str:
138
- """Format text to uppercase."""
139
- return text.strip().upper()
240
+ class UserUpdate(BaseModel):
241
+ name: str | None = Field(None, min_length=1, max_length=100)
242
+ password: str | None = Field(None, min_length=8, max_length=100)
140
243
 
244
+ class UserResponse(UserBase):
245
+ model_config = ConfigDict(from_attributes=True)
141
246
 
142
- def format_user_info(name: str, age: int, city: str) -> str:
143
- """Format user information with nested f-strings (Python 3.13 PEP 701)."""
144
- # Python 3.13 allows nested f-strings and arbitrary expressions
145
- return f"User: {name}, Details: {f'Age: {age}, City: {city.upper()}'}"
247
+ id: int
248
+ is_active: bool
249
+ created_at: datetime
250
+ updated_at: datetime
251
+
252
+ class UserListResponse(BaseModel):
253
+ users: list[UserResponse]
254
+ total: int
255
+ page: int
256
+ size: int
257
+
258
+ class Token(BaseModel):
259
+ access_token: str
260
+ refresh_token: str
261
+ token_type: str = "bearer"
262
+
263
+ class TokenPayload(BaseModel):
264
+ sub: int
265
+ exp: datetime
266
+ type: str # "access" or "refresh"
146
267
  ```
147
268
 
148
- **Workflow Commands**:
149
- ```bash
150
- # Lint and auto-fix issues
151
- ruff check . --fix
152
-
153
- # Format code (replaces black)
154
- ruff format .
155
-
156
- # Check specific rules
157
- ruff check --select I . # Import sorting only
158
- ruff check --select UP . # Python 3.13 upgrade suggestions
269
+ ### Repository Pattern
159
270
 
160
- # Show what would be fixed (dry-run)
161
- ruff check --show-fixes .
271
+ ```python
272
+ # app/repositories/user_repository.py
273
+ from sqlalchemy import select, func
274
+ from sqlalchemy.ext.asyncio import AsyncSession
275
+
276
+ from app.models.user import User
277
+ from app.schemas.user import UserCreate, UserUpdate
278
+
279
+ class UserRepository:
280
+ def __init__(self, session: AsyncSession):
281
+ self.session = session
282
+
283
+ async def get_by_id(self, user_id: int) -> User | None:
284
+ result = await self.session.execute(
285
+ select(User).where(User.id == user_id)
286
+ )
287
+ return result.scalar_one_or_none()
288
+
289
+ async def get_by_email(self, email: str) -> User | None:
290
+ result = await self.session.execute(
291
+ select(User).where(User.email == email)
292
+ )
293
+ return result.scalar_one_or_none()
294
+
295
+ async def get_multi(
296
+ self,
297
+ skip: int = 0,
298
+ limit: int = 100,
299
+ is_active: bool | None = None,
300
+ ) -> tuple[list[User], int]:
301
+ query = select(User)
302
+ count_query = select(func.count(User.id))
303
+
304
+ if is_active is not None:
305
+ query = query.where(User.is_active == is_active)
306
+ count_query = count_query.where(User.is_active == is_active)
307
+
308
+ # Get total count
309
+ total_result = await self.session.execute(count_query)
310
+ total = total_result.scalar_one()
311
+
312
+ # Get users
313
+ query = query.offset(skip).limit(limit).order_by(User.created_at.desc())
314
+ result = await self.session.execute(query)
315
+ users = result.scalars().all()
316
+
317
+ return list(users), total
318
+
319
+ async def create(self, user_create: UserCreate, hashed_password: str) -> User:
320
+ user = User(
321
+ email=user_create.email,
322
+ name=user_create.name,
323
+ hashed_password=hashed_password,
324
+ )
325
+ self.session.add(user)
326
+ await self.session.flush()
327
+ await self.session.refresh(user)
328
+ return user
329
+
330
+ async def update(self, user: User, user_update: UserUpdate) -> User:
331
+ update_data = user_update.model_dump(exclude_unset=True)
332
+ for field, value in update_data.items():
333
+ setattr(user, field, value)
334
+ await self.session.flush()
335
+ await self.session.refresh(user)
336
+ return user
337
+
338
+ async def delete(self, user: User) -> None:
339
+ await self.session.delete(user)
340
+ await self.session.flush()
341
+
342
+ async def deactivate(self, user: User) -> User:
343
+ user.is_active = False
344
+ await self.session.flush()
345
+ await self.session.refresh(user)
346
+ return user
162
347
  ```
163
348
 
164
- ---
165
-
166
- ## Example 3: mypy 1.8.0 Type Checking with Pydantic 2.7.0
167
-
168
- ### Source File: `src/models/product.py`
349
+ ### Service Layer
169
350
 
170
351
  ```python
171
- """Product models with static (mypy) and runtime (Pydantic) validation."""
172
- from typing import override
173
- from pydantic import BaseModel, Field, field_validator
174
- from decimal import Decimal
175
-
176
-
177
- class Product(BaseModel):
178
- """Product model with runtime validation via Pydantic 2.7.0."""
179
-
180
- id: int = Field(gt=0, description="Product ID must be positive")
181
- name: str = Field(min_length=1, max_length=100)
182
- price: Decimal = Field(gt=0, decimal_places=2)
183
- stock: int = Field(ge=0, description="Stock cannot be negative")
184
-
185
- @field_validator("name")
186
- @classmethod
187
- def name_must_not_contain_special_chars(cls, v: str) -> str:
188
- """Validate that name contains only alphanumeric characters."""
189
- if not v.replace(" ", "").isalnum():
190
- raise ValueError("Product name must be alphanumeric")
191
- return v
192
-
193
- def apply_discount(self, percentage: float) -> Decimal:
194
- """Apply discount percentage to product price."""
195
- if not 0 <= percentage <= 100:
196
- raise ValueError("Discount must be between 0 and 100")
197
- discount_amount = self.price * Decimal(percentage / 100)
198
- return self.price - discount_amount
199
-
200
-
201
- class GenericContainer[T]: # Python 3.13 PEP 695 type parameters
202
- """Generic container using Python 3.13 type parameter syntax."""
203
-
204
- def __init__(self, items: list[T]) -> None:
205
- self.items = items
206
-
207
- def first(self) -> T | None:
208
- """Return first item or None if empty."""
209
- return self.items[0] if self.items else None
352
+ # app/services/user_service.py
353
+ from datetime import datetime, timedelta, timezone
354
+ from jose import jwt
355
+ from passlib.context import CryptContext
356
+
357
+ from app.config import get_settings
358
+ from app.models.user import User
359
+ from app.schemas.user import UserCreate, UserUpdate, Token, TokenPayload
360
+ from app.repositories.user_repository import UserRepository
361
+
362
+ settings = get_settings()
363
+ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
364
+
365
+ class UserService:
366
+ def __init__(self, repository: UserRepository):
367
+ self.repository = repository
368
+
369
+ @staticmethod
370
+ def hash_password(password: str) -> str:
371
+ return pwd_context.hash(password)
372
+
373
+ @staticmethod
374
+ def verify_password(plain_password: str, hashed_password: str) -> bool:
375
+ return pwd_context.verify(plain_password, hashed_password)
376
+
377
+ @staticmethod
378
+ def create_token(user_id: int, token_type: str, expires_delta: timedelta) -> str:
379
+ expire = datetime.now(timezone.utc) + expires_delta
380
+ payload = TokenPayload(
381
+ sub=user_id,
382
+ exp=expire,
383
+ type=token_type,
384
+ )
385
+ return jwt.encode(
386
+ payload.model_dump(),
387
+ settings.secret_key,
388
+ algorithm=settings.algorithm,
389
+ )
390
+
391
+ def create_tokens(self, user: User) -> Token:
392
+ access_token = self.create_token(
393
+ user.id,
394
+ "access",
395
+ timedelta(minutes=settings.access_token_expire_minutes),
396
+ )
397
+ refresh_token = self.create_token(
398
+ user.id,
399
+ "refresh",
400
+ timedelta(days=settings.refresh_token_expire_days),
401
+ )
402
+ return Token(access_token=access_token, refresh_token=refresh_token)
403
+
404
+ async def authenticate(self, email: str, password: str) -> User | None:
405
+ user = await self.repository.get_by_email(email)
406
+ if not user:
407
+ return None
408
+ if not self.verify_password(password, user.hashed_password):
409
+ return None
410
+ if not user.is_active:
411
+ return None
412
+ return user
413
+
414
+ async def register(self, user_create: UserCreate) -> User:
415
+ hashed_password = self.hash_password(user_create.password)
416
+ return await self.repository.create(user_create, hashed_password)
417
+
418
+ async def update(self, user: User, user_update: UserUpdate) -> User:
419
+ if user_update.password:
420
+ user_update.password = self.hash_password(user_update.password)
421
+ return await self.repository.update(user, user_update)
422
+ ```
210
423
 
211
- def add(self, item: T) -> None:
212
- """Add item to container."""
213
- self.items.append(item)
424
+ ### API Endpoints
214
425
 
426
+ ```python
427
+ # app/api/v1/endpoints/users.py
428
+ from fastapi import APIRouter, Depends, HTTPException, status, Query
429
+ from sqlalchemy.ext.asyncio import AsyncSession
430
+
431
+ from app.database import get_db
432
+ from app.dependencies import get_current_user, get_current_active_superuser
433
+ from app.models.user import User
434
+ from app.schemas.user import (
435
+ UserCreate,
436
+ UserUpdate,
437
+ UserResponse,
438
+ UserListResponse,
439
+ Token,
440
+ )
441
+ from app.repositories.user_repository import UserRepository
442
+ from app.services.user_service import UserService
443
+
444
+ router = APIRouter(prefix="/users", tags=["users"])
445
+
446
+ def get_user_service(db: AsyncSession = Depends(get_db)) -> UserService:
447
+ repository = UserRepository(db)
448
+ return UserService(repository)
449
+
450
+ @router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
451
+ async def register(
452
+ user_create: UserCreate,
453
+ service: UserService = Depends(get_user_service),
454
+ ):
455
+ """Register a new user."""
456
+ existing = await service.repository.get_by_email(user_create.email)
457
+ if existing:
458
+ raise HTTPException(
459
+ status_code=status.HTTP_400_BAD_REQUEST,
460
+ detail="Email already registered",
461
+ )
462
+ user = await service.register(user_create)
463
+ return user
464
+
465
+ @router.post("/login", response_model=Token)
466
+ async def login(
467
+ email: str,
468
+ password: str,
469
+ service: UserService = Depends(get_user_service),
470
+ ):
471
+ """Authenticate and get tokens."""
472
+ user = await service.authenticate(email, password)
473
+ if not user:
474
+ raise HTTPException(
475
+ status_code=status.HTTP_401_UNAUTHORIZED,
476
+ detail="Invalid credentials",
477
+ )
478
+ return service.create_tokens(user)
479
+
480
+ @router.get("/me", response_model=UserResponse)
481
+ async def get_current_user_info(
482
+ current_user: User = Depends(get_current_user),
483
+ ):
484
+ """Get current user information."""
485
+ return current_user
486
+
487
+ @router.patch("/me", response_model=UserResponse)
488
+ async def update_current_user(
489
+ user_update: UserUpdate,
490
+ current_user: User = Depends(get_current_user),
491
+ service: UserService = Depends(get_user_service),
492
+ ):
493
+ """Update current user."""
494
+ return await service.update(current_user, user_update)
495
+
496
+ @router.get("", response_model=UserListResponse)
497
+ async def list_users(
498
+ page: int = Query(1, ge=1),
499
+ size: int = Query(20, ge=1, le=100),
500
+ is_active: bool | None = None,
501
+ current_user: User = Depends(get_current_active_superuser),
502
+ service: UserService = Depends(get_user_service),
503
+ ):
504
+ """List all users (admin only)."""
505
+ skip = (page - 1) * size
506
+ users, total = await service.repository.get_multi(
507
+ skip=skip, limit=size, is_active=is_active
508
+ )
509
+ return UserListResponse(users=users, total=total, page=page, size=size)
215
510
 
216
- # Usage example
217
- def process_products(products: GenericContainer[Product]) -> list[str]:
218
- """Process products and return their names."""
219
- return [p.name for p in products.items if p.stock > 0]
511
+ @router.get("/{user_id}", response_model=UserResponse)
512
+ async def get_user(
513
+ user_id: int,
514
+ current_user: User = Depends(get_current_active_superuser),
515
+ service: UserService = Depends(get_user_service),
516
+ ):
517
+ """Get user by ID (admin only)."""
518
+ user = await service.repository.get_by_id(user_id)
519
+ if not user:
520
+ raise HTTPException(
521
+ status_code=status.HTTP_404_NOT_FOUND,
522
+ detail="User not found",
523
+ )
524
+ return user
525
+
526
+ @router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
527
+ async def deactivate_user(
528
+ user_id: int,
529
+ current_user: User = Depends(get_current_active_superuser),
530
+ service: UserService = Depends(get_user_service),
531
+ ):
532
+ """Deactivate user (admin only)."""
533
+ user = await service.repository.get_by_id(user_id)
534
+ if not user:
535
+ raise HTTPException(
536
+ status_code=status.HTTP_404_NOT_FOUND,
537
+ detail="User not found",
538
+ )
539
+ await service.repository.deactivate(user)
220
540
  ```
221
541
 
222
- ### mypy Configuration: `pyproject.toml`
542
+ ### Dependencies
223
543
 
224
- ```toml
225
- [tool.mypy]
226
- python_version = "3.13"
227
- strict = true
228
- warn_return_any = true
229
- warn_unused_configs = true
230
- disallow_untyped_defs = true
231
- disallow_any_generics = true
232
- check_untyped_defs = true
233
- no_implicit_optional = true
234
- warn_redundant_casts = true
235
- warn_unused_ignores = true
236
-
237
- [[tool.mypy.overrides]]
238
- module = "tests.*"
239
- disallow_untyped_defs = false
240
- ```
544
+ ```python
545
+ # app/dependencies.py
546
+ from fastapi import Depends, HTTPException, status
547
+ from fastapi.security import OAuth2PasswordBearer
548
+ from jose import jwt, JWTError
549
+ from sqlalchemy.ext.asyncio import AsyncSession
550
+
551
+ from app.config import get_settings
552
+ from app.database import get_db
553
+ from app.models.user import User
554
+ from app.repositories.user_repository import UserRepository
555
+ from app.schemas.user import TokenPayload
556
+
557
+ settings = get_settings()
558
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/users/login")
559
+
560
+ async def get_current_user(
561
+ token: str = Depends(oauth2_scheme),
562
+ db: AsyncSession = Depends(get_db),
563
+ ) -> User:
564
+ credentials_exception = HTTPException(
565
+ status_code=status.HTTP_401_UNAUTHORIZED,
566
+ detail="Could not validate credentials",
567
+ headers={"WWW-Authenticate": "Bearer"},
568
+ )
241
569
 
242
- **Run Commands**:
243
- ```bash
244
- mypy . # Type check all files
245
- mypy --strict src/ # Strict mode for production code
246
- mypy --show-column-numbers . # Show precise error locations
570
+ try:
571
+ payload = jwt.decode(
572
+ token, settings.secret_key, algorithms=[settings.algorithm]
573
+ )
574
+ token_data = TokenPayload(**payload)
575
+
576
+ if token_data.type != "access":
577
+ raise credentials_exception
578
+
579
+ except JWTError:
580
+ raise credentials_exception
581
+
582
+ repository = UserRepository(db)
583
+ user = await repository.get_by_id(token_data.sub)
584
+
585
+ if user is None:
586
+ raise credentials_exception
587
+
588
+ return user
589
+
590
+ async def get_current_active_user(
591
+ current_user: User = Depends(get_current_user),
592
+ ) -> User:
593
+ if not current_user.is_active:
594
+ raise HTTPException(
595
+ status_code=status.HTTP_403_FORBIDDEN,
596
+ detail="Inactive user",
597
+ )
598
+ return current_user
599
+
600
+ async def get_current_active_superuser(
601
+ current_user: User = Depends(get_current_active_user),
602
+ ) -> User:
603
+ if not current_user.is_superuser:
604
+ raise HTTPException(
605
+ status_code=status.HTTP_403_FORBIDDEN,
606
+ detail="Insufficient permissions",
607
+ )
608
+ return current_user
247
609
  ```
248
610
 
249
611
  ---
250
612
 
251
- ## Example 4: FastAPI 0.115.0 REST API with Async Handlers
252
-
253
- ### API Server: `src/api/main.py`
613
+ ## Complete pytest Test Suite
254
614
 
255
615
  ```python
256
- """FastAPI 0.115.0 application with async handlers and dependency injection."""
257
- from fastapi import FastAPI, HTTPException, Depends
258
- from fastapi.responses import JSONResponse
259
- from pydantic import BaseModel, Field
260
- from typing import Annotated
261
- import asyncio
262
-
263
-
264
- app = FastAPI(title="Product API", version="1.0.0")
265
-
266
-
267
- class ProductCreate(BaseModel):
268
- """Product creation request schema."""
269
- name: str = Field(min_length=1, max_length=100)
270
- price: float = Field(gt=0)
271
- stock: int = Field(ge=0)
272
-
273
-
274
- class ProductResponse(BaseModel):
275
- """Product response schema."""
276
- id: int
277
- name: str
278
- price: float
279
- stock: int
280
-
616
+ # tests/conftest.py
617
+ import pytest
618
+ import pytest_asyncio
619
+ from httpx import AsyncClient, ASGITransport
620
+ from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
621
+ from sqlalchemy.orm import sessionmaker
622
+ from sqlalchemy.pool import StaticPool
623
+
624
+ from app.database import Base, get_db
625
+ from app.main import app
626
+ from app.config import get_settings
627
+
628
+ settings = get_settings()
629
+
630
+ @pytest.fixture(scope="session")
631
+ def event_loop():
632
+ import asyncio
633
+ loop = asyncio.new_event_loop()
634
+ yield loop
635
+ loop.close()
636
+
637
+ @pytest_asyncio.fixture(scope="session")
638
+ async def engine():
639
+ engine = create_async_engine(
640
+ "sqlite+aiosqlite:///:memory:",
641
+ connect_args={"check_same_thread": False},
642
+ poolclass=StaticPool,
643
+ )
644
+ async with engine.begin() as conn:
645
+ await conn.run_sync(Base.metadata.create_all)
646
+ yield engine
647
+ await engine.dispose()
648
+
649
+ @pytest_asyncio.fixture
650
+ async def db_session(engine):
651
+ async_session = sessionmaker(
652
+ engine, class_=AsyncSession, expire_on_commit=False
653
+ )
654
+ async with async_session() as session:
655
+ yield session
656
+ await session.rollback()
281
657
 
282
- # Dependency injection
283
- async def get_db_session():
284
- """Simulated database session (replace with actual DB)."""
285
- # In production: use SQLAlchemy async session
286
- yield {"connection": "active"}
658
+ @pytest_asyncio.fixture
659
+ async def async_client(db_session):
660
+ async def override_get_db():
661
+ yield db_session
287
662
 
663
+ app.dependency_overrides[get_db] = override_get_db
288
664
 
289
- @app.get("/")
290
- async def root():
291
- """Health check endpoint."""
292
- return {"status": "ok", "version": "1.0.0"}
665
+ async with AsyncClient(
666
+ transport=ASGITransport(app=app),
667
+ base_url="http://test",
668
+ ) as client:
669
+ yield client
293
670
 
671
+ app.dependency_overrides.clear()
294
672
 
295
- @app.post("/products", response_model=ProductResponse, status_code=201)
296
- async def create_product(
297
- product: ProductCreate,
298
- db: Annotated[dict, Depends(get_db_session)]
299
- ):
300
- """Create a new product (async handler)."""
301
- # Simulate async database operation
302
- await asyncio.sleep(0.1)
303
-
304
- # In production: insert into database
305
- product_data = {
306
- "id": 1,
307
- "name": product.name,
308
- "price": product.price,
309
- "stock": product.stock,
673
+ @pytest.fixture
674
+ def user_data():
675
+ return {
676
+ "email": "test@example.com",
677
+ "name": "Test User",
678
+ "password": "password123",
310
679
  }
680
+ ```
311
681
 
312
- return ProductResponse(**product_data)
313
-
314
-
315
- @app.get("/products/{product_id}", response_model=ProductResponse)
316
- async def get_product(
317
- product_id: int,
318
- db: Annotated[dict, Depends(get_db_session)]
319
- ):
320
- """Retrieve product by ID (async handler)."""
321
- # Simulate async database lookup
322
- await asyncio.sleep(0.1)
323
-
324
- # In production: query from database
325
- if product_id == 999:
326
- raise HTTPException(status_code=404, detail="Product not found")
327
-
328
- return ProductResponse(id=product_id, name="Sample Product", price=29.99, stock=100)
682
+ ```python
683
+ # tests/test_users.py
684
+ import pytest
685
+ from httpx import AsyncClient
329
686
 
687
+ @pytest.mark.asyncio
688
+ async def test_register_user(async_client: AsyncClient, user_data: dict):
689
+ response = await async_client.post("/api/v1/users/register", json=user_data)
330
690
 
331
- @app.exception_handler(ValueError)
332
- async def value_error_handler(request, exc):
333
- """Global exception handler for ValueError."""
334
- return JSONResponse(
335
- status_code=400,
336
- content={"error": "Validation failed", "detail": str(exc)},
337
- )
338
- ```
691
+ assert response.status_code == 201
692
+ data = response.json()
693
+ assert data["email"] == user_data["email"]
694
+ assert data["name"] == user_data["name"]
695
+ assert "id" in data
696
+ assert "password" not in data
339
697
 
340
- ### Test File: `tests/test_api.py`
698
+ @pytest.mark.asyncio
699
+ async def test_register_duplicate_email(async_client: AsyncClient, user_data: dict):
700
+ # First registration
701
+ await async_client.post("/api/v1/users/register", json=user_data)
341
702
 
342
- ```python
343
- """Tests for FastAPI endpoints using pytest-asyncio."""
344
- import pytest
345
- from httpx import AsyncClient, ASGITransport
346
- from src.api.main import app
703
+ # Second registration with same email
704
+ response = await async_client.post("/api/v1/users/register", json=user_data)
347
705
 
706
+ assert response.status_code == 400
707
+ assert "already registered" in response.json()["detail"]
348
708
 
349
709
  @pytest.mark.asyncio
350
- async def test_root_endpoint():
351
- """Test health check endpoint."""
352
- async with AsyncClient(
353
- transport=ASGITransport(app=app),
354
- base_url="http://test"
355
- ) as client:
356
- response = await client.get("/")
357
- assert response.status_code == 200
358
- assert response.json() == {"status": "ok", "version": "1.0.0"}
710
+ @pytest.mark.parametrize(
711
+ "invalid_data,expected_detail",
712
+ [
713
+ ({"email": "invalid", "name": "Test", "password": "pass123"}, "email"),
714
+ ({"email": "test@example.com", "name": "", "password": "pass123"}, "name"),
715
+ ({"email": "test@example.com", "name": "Test", "password": "short"}, "password"),
716
+ ],
717
+ ids=["invalid_email", "empty_name", "short_password"],
718
+ )
719
+ async def test_register_validation(
720
+ async_client: AsyncClient,
721
+ invalid_data: dict,
722
+ expected_detail: str,
723
+ ):
724
+ response = await async_client.post("/api/v1/users/register", json=invalid_data)
359
725
 
726
+ assert response.status_code == 422
360
727
 
361
728
  @pytest.mark.asyncio
362
- async def test_create_product():
363
- """Test product creation endpoint."""
364
- async with AsyncClient(
365
- transport=ASGITransport(app=app),
366
- base_url="http://test"
367
- ) as client:
368
- response = await client.post("/products", json={
369
- "name": "Test Product",
370
- "price": 19.99,
371
- "stock": 50,
372
- })
373
- assert response.status_code == 201
374
- data = response.json()
375
- assert data["name"] == "Test Product"
376
- assert data["price"] == 19.99
729
+ async def test_login_success(async_client: AsyncClient, user_data: dict):
730
+ # Register user first
731
+ await async_client.post("/api/v1/users/register", json=user_data)
732
+
733
+ # Login
734
+ response = await async_client.post(
735
+ "/api/v1/users/login",
736
+ params={"email": user_data["email"], "password": user_data["password"]},
737
+ )
377
738
 
739
+ assert response.status_code == 200
740
+ data = response.json()
741
+ assert "access_token" in data
742
+ assert "refresh_token" in data
743
+ assert data["token_type"] == "bearer"
378
744
 
379
745
  @pytest.mark.asyncio
380
- async def test_get_product_not_found():
381
- """Test product retrieval with non-existent ID."""
382
- async with AsyncClient(
383
- transport=ASGITransport(app=app),
384
- base_url="http://test"
385
- ) as client:
386
- response = await client.get("/products/999")
387
- assert response.status_code == 404
388
- ```
746
+ async def test_get_current_user(async_client: AsyncClient, user_data: dict):
747
+ # Register and login
748
+ await async_client.post("/api/v1/users/register", json=user_data)
749
+ login_response = await async_client.post(
750
+ "/api/v1/users/login",
751
+ params={"email": user_data["email"], "password": user_data["password"]},
752
+ )
753
+ token = login_response.json()["access_token"]
389
754
 
390
- **Run Commands**:
391
- ```bash
392
- # Start development server
393
- uvicorn src.api.main:app --reload
755
+ # Get current user
756
+ response = await async_client.get(
757
+ "/api/v1/users/me",
758
+ headers={"Authorization": f"Bearer {token}"},
759
+ )
394
760
 
395
- # Run tests
396
- pytest tests/test_api.py -v --cov=src.api
761
+ assert response.status_code == 200
762
+ data = response.json()
763
+ assert data["email"] == user_data["email"]
397
764
  ```
398
765
 
399
766
  ---
400
767
 
401
- ## Example 5: asyncio.TaskGroup Concurrent Pattern (Python 3.13)
768
+ ## Async Patterns Examples
402
769
 
403
- ### Concurrent Operations: `src/services/data_fetcher.py`
770
+ ### Task Groups (Python 3.11+)
404
771
 
405
772
  ```python
406
- """Data fetching service using Python 3.13 asyncio.TaskGroup."""
407
773
  import asyncio
408
774
  from typing import Any
409
- import httpx
410
-
411
-
412
- class DataFetcher:
413
- """Fetch data from multiple sources concurrently using TaskGroup."""
414
-
415
- def __init__(self, base_url: str):
416
- self.base_url = base_url
417
-
418
- async def fetch_user(self, user_id: int) -> dict[str, Any]:
419
- """Fetch user data from API."""
420
- await asyncio.sleep(0.1) # Simulate network delay
421
- return {"id": user_id, "name": f"User{user_id}"}
422
-
423
- async def fetch_posts(self, user_id: int) -> list[dict[str, Any]]:
424
- """Fetch user posts from API."""
425
- await asyncio.sleep(0.15) # Simulate network delay
426
- return [
427
- {"id": 1, "user_id": user_id, "title": "Post 1"},
428
- {"id": 2, "user_id": user_id, "title": "Post 2"},
429
- ]
430
-
431
- async def fetch_comments(self, user_id: int) -> list[dict[str, Any]]:
432
- """Fetch user comments from API."""
433
- await asyncio.sleep(0.12) # Simulate network delay
434
- return [
435
- {"id": 1, "user_id": user_id, "text": "Comment 1"},
436
- ]
437
-
438
- async def fetch_user_profile(self, user_id: int) -> dict[str, Any]:
439
- """
440
- Fetch complete user profile concurrently using TaskGroup.
441
-
442
- TaskGroup advantages over asyncio.gather:
443
- - Automatic exception propagation
444
- - Structured concurrency (cancellation safety)
445
- - Cleaner error handling
446
- """
447
- async with asyncio.TaskGroup() as tg:
448
- user_task = tg.create_task(self.fetch_user(user_id))
449
- posts_task = tg.create_task(self.fetch_posts(user_id))
450
- comments_task = tg.create_task(self.fetch_comments(user_id))
451
- # All tasks run concurrently here
452
- # If any task fails, TaskGroup cancels others and raises
453
-
454
- # After TaskGroup exits, all tasks are complete
455
- return {
456
- "user": user_task.result(),
457
- "posts": posts_task.result(),
458
- "comments": comments_task.result(),
459
- }
460
-
461
- async def fetch_multiple_users(self, user_ids: list[int]) -> list[dict[str, Any]]:
462
- """Fetch multiple user profiles concurrently."""
463
- async with asyncio.TaskGroup() as tg:
464
- tasks = [
465
- tg.create_task(self.fetch_user_profile(user_id))
466
- for user_id in user_ids
467
- ]
468
-
469
- return [task.result() for task in tasks]
470
-
471
-
472
- # Context Variables for request tracking
473
- from contextvars import ContextVar
474
-
475
- request_id_var: ContextVar[str | None] = ContextVar("request_id", default=None)
476
-
477
-
478
- async def process_request(request_id: str) -> dict[str, Any]:
479
- """Process request with context variable tracking."""
480
- # Set context variable (inherited by all spawned tasks)
481
- token = request_id_var.set(request_id)
482
775
 
483
- try:
484
- fetcher = DataFetcher(base_url="https://api.example.com")
485
- result = await fetcher.fetch_user_profile(user_id=1)
776
+ async def fetch_user(user_id: int) -> dict:
777
+ await asyncio.sleep(0.1) # Simulate API call
778
+ return {"id": user_id, "name": f"User {user_id}"}
779
+
780
+ async def fetch_all_users(user_ids: list[int]) -> list[dict]:
781
+ async with asyncio.TaskGroup() as tg:
782
+ tasks = [tg.create_task(fetch_user(uid)) for uid in user_ids]
486
783
 
487
- # Log with request ID (available in all async contexts)
488
- current_request_id = request_id_var.get()
489
- print(f"Request {current_request_id} completed")
784
+ return [task.result() for task in tasks]
490
785
 
491
- return result
492
- finally:
493
- request_id_var.reset(token)
786
+ # Exception handling with TaskGroup
787
+ async def fetch_with_error_handling(user_ids: list[int]) -> tuple[list[dict], list[Exception]]:
788
+ results = []
789
+ errors = []
494
790
 
791
+ async def safe_fetch(user_id: int):
792
+ try:
793
+ result = await fetch_user(user_id)
794
+ results.append(result)
795
+ except Exception as e:
796
+ errors.append(e)
495
797
 
496
- # Main execution
497
- async def main():
498
- """Example usage of DataFetcher with TaskGroup."""
499
- fetcher = DataFetcher(base_url="https://api.example.com")
798
+ async with asyncio.TaskGroup() as tg:
799
+ for uid in user_ids:
800
+ tg.create_task(safe_fetch(uid))
500
801
 
501
- # Fetch single user profile
502
- profile = await fetcher.fetch_user_profile(user_id=1)
503
- print(f"Profile: {profile}")
802
+ return results, errors
803
+ ```
504
804
 
505
- # Fetch multiple users concurrently
506
- profiles = await fetcher.fetch_multiple_users([1, 2, 3])
507
- print(f"Fetched {len(profiles)} profiles")
805
+ ### Semaphore for Rate Limiting
508
806
 
509
- # Process request with context tracking
510
- result = await process_request(request_id="req-12345")
511
- print(f"Result: {result}")
807
+ ```python
808
+ import asyncio
809
+ from contextlib import asynccontextmanager
512
810
 
811
+ class RateLimiter:
812
+ def __init__(self, max_concurrent: int = 10):
813
+ self._semaphore = asyncio.Semaphore(max_concurrent)
513
814
 
514
- if __name__ == "__main__":
515
- asyncio.run(main())
815
+ @asynccontextmanager
816
+ async def acquire(self):
817
+ async with self._semaphore:
818
+ yield
819
+
820
+ rate_limiter = RateLimiter(max_concurrent=5)
821
+
822
+ async def rate_limited_fetch(url: str) -> dict:
823
+ async with rate_limiter.acquire():
824
+ async with httpx.AsyncClient() as client:
825
+ response = await client.get(url)
826
+ return response.json()
516
827
  ```
517
828
 
518
- ### Test File: `tests/test_data_fetcher.py`
829
+ ### Async Generator Streaming
519
830
 
520
831
  ```python
521
- """Tests for DataFetcher using pytest-asyncio."""
522
- import pytest
523
- from src.services.data_fetcher import DataFetcher
832
+ from typing import AsyncGenerator
833
+
834
+ async def stream_large_data(
835
+ db: AsyncSession,
836
+ batch_size: int = 1000,
837
+ ) -> AsyncGenerator[list[User], None]:
838
+ offset = 0
839
+ while True:
840
+ result = await db.execute(
841
+ select(User)
842
+ .offset(offset)
843
+ .limit(batch_size)
844
+ .order_by(User.id)
845
+ )
846
+ users = result.scalars().all()
847
+
848
+ if not users:
849
+ break
850
+
851
+ yield users
852
+ offset += batch_size
853
+
854
+ # Usage
855
+ async def process_all_users(db: AsyncSession):
856
+ async for batch in stream_large_data(db):
857
+ for user in batch:
858
+ await process_user(user)
859
+ ```
524
860
 
861
+ ---
525
862
 
526
- @pytest.mark.asyncio
527
- async def test_fetch_user_profile():
528
- """Test concurrent user profile fetching."""
529
- fetcher = DataFetcher(base_url="https://api.example.com")
530
- profile = await fetcher.fetch_user_profile(user_id=1)
863
+ ## Docker Production Dockerfile
531
864
 
532
- assert "user" in profile
533
- assert "posts" in profile
534
- assert "comments" in profile
535
- assert profile["user"]["id"] == 1
865
+ ```dockerfile
866
+ # Dockerfile
867
+ FROM python:3.13-slim AS builder
536
868
 
869
+ WORKDIR /app
537
870
 
538
- @pytest.mark.asyncio
539
- async def test_fetch_multiple_users():
540
- """Test fetching multiple user profiles concurrently."""
541
- fetcher = DataFetcher(base_url="https://api.example.com")
542
- profiles = await fetcher.fetch_multiple_users([1, 2, 3])
871
+ # Install build dependencies
872
+ RUN apt-get update && apt-get install -y --no-install-recommends \
873
+ build-essential \
874
+ && rm -rf /var/lib/apt/lists/*
543
875
 
544
- assert len(profiles) == 3
545
- assert all("user" in p for p in profiles)
876
+ # Install Python dependencies
877
+ COPY pyproject.toml poetry.lock ./
878
+ RUN pip install poetry && \
879
+ poetry config virtualenvs.create false && \
880
+ poetry install --no-dev --no-interaction --no-ansi
546
881
 
882
+ FROM python:3.13-slim AS runtime
547
883
 
548
- @pytest.mark.asyncio
549
- async def test_taskgroup_error_propagation():
550
- """Test that TaskGroup properly propagates exceptions."""
551
- fetcher = DataFetcher(base_url="https://api.example.com")
884
+ WORKDIR /app
552
885
 
553
- # Override method to raise error
554
- async def failing_fetch(user_id: int):
555
- raise ValueError("Simulated error")
886
+ # Create non-root user
887
+ RUN addgroup --system --gid 1001 appgroup && \
888
+ adduser --system --uid 1001 --gid 1001 appuser
556
889
 
557
- fetcher.fetch_user = failing_fetch
890
+ # Copy dependencies from builder
891
+ COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
892
+ COPY --from=builder /usr/local/bin /usr/local/bin
558
893
 
559
- with pytest.raises(ValueError, match="Simulated error"):
560
- await fetcher.fetch_user_profile(user_id=1)
561
- ```
894
+ # Copy application code
895
+ COPY --chown=appuser:appgroup . .
562
896
 
563
- **Run Commands**:
564
- ```bash
565
- # Run the example
566
- python -m src.services.data_fetcher
897
+ # Switch to non-root user
898
+ USER appuser
567
899
 
568
- # Run tests
569
- pytest tests/test_data_fetcher.py -v --cov=src.services
900
+ # Expose port
901
+ EXPOSE 8000
902
+
903
+ # Health check
904
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
905
+ CMD python -c "import httpx; httpx.get('http://localhost:8000/health')"
906
+
907
+ # Run application
908
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
570
909
  ```
571
910
 
572
911
  ---
573
912
 
574
- ## Quick Reference
913
+ ## pyproject.toml Complete Configuration
575
914
 
576
- ### Setup New Project (uv 0.9.3)
577
-
578
- ```bash
579
- # Create project with Python 3.13
580
- uv venv --python 3.13
581
- source .venv/bin/activate
915
+ ```toml
916
+ [tool.poetry]
917
+ name = "fastapi-app"
918
+ version = "1.0.0"
919
+ description = "Production FastAPI Application"
920
+ authors = ["Developer <dev@example.com>"]
921
+ python = "^3.13"
922
+
923
+ [tool.poetry.dependencies]
924
+ python = "^3.13"
925
+ fastapi = "^0.115.0"
926
+ uvicorn = {extras = ["standard"], version = "^0.32.0"}
927
+ pydantic = "^2.9.0"
928
+ pydantic-settings = "^2.6.0"
929
+ sqlalchemy = {extras = ["asyncio"], version = "^2.0.0"}
930
+ asyncpg = "^0.30.0"
931
+ python-jose = {extras = ["cryptography"], version = "^3.3.0"}
932
+ passlib = {extras = ["bcrypt"], version = "^1.7.4"}
933
+ httpx = "^0.28.0"
934
+
935
+ [tool.poetry.group.dev.dependencies]
936
+ pytest = "^8.3.0"
937
+ pytest-asyncio = "^0.24.0"
938
+ pytest-cov = "^6.0.0"
939
+ aiosqlite = "^0.20.0"
940
+ ruff = "^0.8.0"
941
+ mypy = "^1.13.0"
582
942
 
583
- # Install dependencies
584
- uv add pytest pytest-asyncio ruff mypy fastapi uvicorn httpx pydantic
943
+ [tool.ruff]
944
+ line-length = 100
945
+ target-version = "py313"
585
946
 
586
- # Add development dependencies
587
- uv add --dev pytest-cov pytest-mock
588
- ```
947
+ [tool.ruff.lint]
948
+ select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"]
949
+ ignore = ["E501"]
589
950
 
590
- ### Quality Gate Commands
951
+ [tool.ruff.lint.isort]
952
+ known-first-party = ["app"]
591
953
 
592
- ```bash
593
- # Run all tests with coverage
594
- pytest --cov=src --cov-report=term-missing --cov-report=html
954
+ [tool.pytest.ini_options]
955
+ asyncio_mode = "auto"
956
+ asyncio_default_fixture_loop_scope = "function"
957
+ testpaths = ["tests"]
958
+ addopts = "-v --tb=short --cov=app --cov-report=term-missing"
595
959
 
596
- # Lint and format
597
- ruff check . --fix
598
- ruff format .
960
+ [tool.mypy]
961
+ python_version = "3.13"
962
+ strict = true
963
+ plugins = ["pydantic.mypy"]
599
964
 
600
- # Type check
601
- mypy --strict src/
965
+ [tool.coverage.run]
966
+ source = ["app"]
967
+ omit = ["tests/*"]
602
968
 
603
- # Full quality gate (run before commit)
604
- pytest --cov=src --cov-report=term && ruff check . && mypy .
969
+ [build-system]
970
+ requires = ["poetry-core>=1.0.0"]
971
+ build-backend = "poetry.core.masonry.api"
605
972
  ```
606
973
 
607
- ### Production Dependencies Matrix
608
-
609
- | Package | Version | Purpose |
610
- |---------|---------|---------|
611
- | pytest | 8.4.2 | Testing framework |
612
- | pytest-asyncio | latest | Async test support |
613
- | pytest-cov | latest | Coverage reporting |
614
- | ruff | 0.13.1 | Linting & formatting |
615
- | mypy | 1.8.0 | Static type checking |
616
- | uv | 0.9.3 | Package management |
617
- | FastAPI | 0.115.0 | Web framework |
618
- | Pydantic | 2.7.0 | Data validation |
619
- | httpx | latest | Async HTTP client |
620
- | uvicorn | latest | ASGI server |
621
-
622
974
  ---
623
975
 
624
- All examples are tested against Python 3.13.1 and follow MoAI-ADK TRUST 5 principles.
976
+ Last Updated: 2025-12-07
977
+ Version: 1.0.0