nene2-python 1.8.39__tar.gz → 1.8.40__tar.gz

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 (390) hide show
  1. {nene2_python-1.8.39 → nene2_python-1.8.40}/PKG-INFO +1 -1
  2. nene2_python-1.8.40/docs/field-trials/2026-05-field-trial-169.md +272 -0
  3. {nene2_python-1.8.39 → nene2_python-1.8.40}/pyproject.toml +1 -1
  4. {nene2_python-1.8.39 → nene2_python-1.8.40}/uv.lock +1 -1
  5. {nene2_python-1.8.39 → nene2_python-1.8.40}/.env.example +0 -0
  6. {nene2_python-1.8.39 → nene2_python-1.8.40}/.github/workflows/ci.yml +0 -0
  7. {nene2_python-1.8.39 → nene2_python-1.8.40}/.github/workflows/docs.yml +0 -0
  8. {nene2_python-1.8.39 → nene2_python-1.8.40}/.github/workflows/publish.yml +0 -0
  9. {nene2_python-1.8.39 → nene2_python-1.8.40}/.gitignore +0 -0
  10. {nene2_python-1.8.39 → nene2_python-1.8.40}/.vitepress/config.mts +0 -0
  11. {nene2_python-1.8.39 → nene2_python-1.8.40}/.vitepress/theme/custom.css +0 -0
  12. {nene2_python-1.8.39 → nene2_python-1.8.40}/.vitepress/theme/index.ts +0 -0
  13. {nene2_python-1.8.39 → nene2_python-1.8.40}/AGENTS.md +0 -0
  14. {nene2_python-1.8.39 → nene2_python-1.8.40}/CHANGELOG.md +0 -0
  15. {nene2_python-1.8.39 → nene2_python-1.8.40}/CLAUDE.md +0 -0
  16. {nene2_python-1.8.39 → nene2_python-1.8.40}/Dockerfile +0 -0
  17. {nene2_python-1.8.39 → nene2_python-1.8.40}/LICENSE +0 -0
  18. {nene2_python-1.8.39 → nene2_python-1.8.40}/README.md +0 -0
  19. {nene2_python-1.8.39 → nene2_python-1.8.40}/alembic/README +0 -0
  20. {nene2_python-1.8.39 → nene2_python-1.8.40}/alembic/env.py +0 -0
  21. {nene2_python-1.8.39 → nene2_python-1.8.40}/alembic/script.py.mako +0 -0
  22. {nene2_python-1.8.39 → nene2_python-1.8.40}/alembic/versions/001_create_notes_and_tags_tables.py +0 -0
  23. {nene2_python-1.8.39 → nene2_python-1.8.40}/alembic.ini +0 -0
  24. {nene2_python-1.8.39 → nene2_python-1.8.40}/compose.yaml +0 -0
  25. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0001-toolchain.md +0 -0
  26. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0002-clean-architecture.md +0 -0
  27. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0003-security-first.md +0 -0
  28. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0004-ai-first-design.md +0 -0
  29. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0005-logging.md +0 -0
  30. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0006-rate-limiting.md +0 -0
  31. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0009-mcp-design.md +0 -0
  32. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0010-async-use-case.md +0 -0
  33. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/adr/0011-mcp-as-core-dependency.md +0 -0
  34. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/de/index.md +0 -0
  35. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/de/tutorials/getting-started.md +0 -0
  36. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/explanation/architecture.md +0 -0
  37. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/explanation/design-philosophy.md +0 -0
  38. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-1.md +0 -0
  39. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-10.md +0 -0
  40. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-100.md +0 -0
  41. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-101.md +0 -0
  42. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-102.md +0 -0
  43. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-103.md +0 -0
  44. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-104.md +0 -0
  45. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-105.md +0 -0
  46. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-106.md +0 -0
  47. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-107.md +0 -0
  48. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-108.md +0 -0
  49. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-109.md +0 -0
  50. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-11.md +0 -0
  51. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-110.md +0 -0
  52. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-111.md +0 -0
  53. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-112.md +0 -0
  54. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-113.md +0 -0
  55. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-114.md +0 -0
  56. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-115.md +0 -0
  57. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-116.md +0 -0
  58. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-117.md +0 -0
  59. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-118.md +0 -0
  60. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-119.md +0 -0
  61. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-12.md +0 -0
  62. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-120.md +0 -0
  63. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-121.md +0 -0
  64. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-122.md +0 -0
  65. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-123.md +0 -0
  66. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-124.md +0 -0
  67. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-125.md +0 -0
  68. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-126.md +0 -0
  69. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-127.md +0 -0
  70. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-128.md +0 -0
  71. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-129.md +0 -0
  72. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-13.md +0 -0
  73. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-130.md +0 -0
  74. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-131.md +0 -0
  75. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-132.md +0 -0
  76. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-133.md +0 -0
  77. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-134.md +0 -0
  78. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-135.md +0 -0
  79. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-136.md +0 -0
  80. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-137.md +0 -0
  81. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-138.md +0 -0
  82. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-139.md +0 -0
  83. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-14.md +0 -0
  84. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-140.md +0 -0
  85. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-141.md +0 -0
  86. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-142.md +0 -0
  87. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-143.md +0 -0
  88. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-144.md +0 -0
  89. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-145.md +0 -0
  90. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-146.md +0 -0
  91. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-147.md +0 -0
  92. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-148.md +0 -0
  93. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-149.md +0 -0
  94. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-15.md +0 -0
  95. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-150.md +0 -0
  96. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-151.md +0 -0
  97. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-152.md +0 -0
  98. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-153.md +0 -0
  99. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-154.md +0 -0
  100. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-155.md +0 -0
  101. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-156.md +0 -0
  102. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-157.md +0 -0
  103. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-158.md +0 -0
  104. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-159.md +0 -0
  105. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-16.md +0 -0
  106. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-160.md +0 -0
  107. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-161.md +0 -0
  108. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-162.md +0 -0
  109. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-163.md +0 -0
  110. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-164.md +0 -0
  111. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-165.md +0 -0
  112. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-166.md +0 -0
  113. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-167.md +0 -0
  114. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-168.md +0 -0
  115. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-17.md +0 -0
  116. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-18.md +0 -0
  117. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-19.md +0 -0
  118. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-2.md +0 -0
  119. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-20.md +0 -0
  120. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-21.md +0 -0
  121. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-22.md +0 -0
  122. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-23.md +0 -0
  123. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-24.md +0 -0
  124. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-25.md +0 -0
  125. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-26.md +0 -0
  126. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-27.md +0 -0
  127. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-28.md +0 -0
  128. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-29.md +0 -0
  129. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-3.md +0 -0
  130. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-30.md +0 -0
  131. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-31.md +0 -0
  132. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-32.md +0 -0
  133. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-33.md +0 -0
  134. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-34.md +0 -0
  135. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-35.md +0 -0
  136. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-36.md +0 -0
  137. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-37.md +0 -0
  138. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-38.md +0 -0
  139. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-39.md +0 -0
  140. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-4.md +0 -0
  141. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-40.md +0 -0
  142. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-41.md +0 -0
  143. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-42.md +0 -0
  144. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-43.md +0 -0
  145. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-44.md +0 -0
  146. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-45.md +0 -0
  147. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-46.md +0 -0
  148. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-47.md +0 -0
  149. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-48.md +0 -0
  150. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-49.md +0 -0
  151. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-5.md +0 -0
  152. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-50.md +0 -0
  153. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-51.md +0 -0
  154. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-52.md +0 -0
  155. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-53.md +0 -0
  156. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-54.md +0 -0
  157. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-55.md +0 -0
  158. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-56.md +0 -0
  159. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-57.md +0 -0
  160. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-58.md +0 -0
  161. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-59.md +0 -0
  162. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-6.md +0 -0
  163. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-60.md +0 -0
  164. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-61.md +0 -0
  165. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-62.md +0 -0
  166. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-63.md +0 -0
  167. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-64.md +0 -0
  168. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-65.md +0 -0
  169. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-66.md +0 -0
  170. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-67.md +0 -0
  171. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-68.md +0 -0
  172. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-69.md +0 -0
  173. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-7.md +0 -0
  174. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-70.md +0 -0
  175. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-71.md +0 -0
  176. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-72.md +0 -0
  177. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-73.md +0 -0
  178. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-74.md +0 -0
  179. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-75.md +0 -0
  180. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-76.md +0 -0
  181. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-77.md +0 -0
  182. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-78.md +0 -0
  183. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-79.md +0 -0
  184. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-8.md +0 -0
  185. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-80.md +0 -0
  186. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-81.md +0 -0
  187. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-82.md +0 -0
  188. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-83.md +0 -0
  189. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-84.md +0 -0
  190. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-85.md +0 -0
  191. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-86.md +0 -0
  192. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-87.md +0 -0
  193. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-88.md +0 -0
  194. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-89.md +0 -0
  195. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-9.md +0 -0
  196. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-90.md +0 -0
  197. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-91.md +0 -0
  198. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-92.md +0 -0
  199. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-93.md +0 -0
  200. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-94.md +0 -0
  201. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-95.md +0 -0
  202. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-96.md +0 -0
  203. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-97.md +0 -0
  204. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-98.md +0 -0
  205. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/field-trials/2026-05-field-trial-99.md +0 -0
  206. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/fr/index.md +0 -0
  207. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/fr/tutorials/getting-started.md +0 -0
  208. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/add-new-domain.md +0 -0
  209. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/api-versioning.md +0 -0
  210. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/async-use-case.md +0 -0
  211. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/background-tasks.md +0 -0
  212. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/configure-auth.md +0 -0
  213. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/cors.md +0 -0
  214. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/custom-auth-middleware.md +0 -0
  215. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/dependency-injection.md +0 -0
  216. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/domain-events.md +0 -0
  217. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/file-upload.md +0 -0
  218. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/lifespan-and-app-state.md +0 -0
  219. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/middleware-stack.md +0 -0
  220. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/new-project.md +0 -0
  221. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/problem-details.md +0 -0
  222. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/response-patterns.md +0 -0
  223. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/run-tests.md +0 -0
  224. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/soft-delete.md +0 -0
  225. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/sqlalchemy-repository.md +0 -0
  226. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/streaming.md +0 -0
  227. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/structured-logging.md +0 -0
  228. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/validation.md +0 -0
  229. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/how-to/webhook.md +0 -0
  230. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/howto/mcp-setup.md +0 -0
  231. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/index.md +0 -0
  232. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/explanation/architecture.md +0 -0
  233. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/explanation/design-philosophy.md +0 -0
  234. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/how-to/add-new-domain.md +0 -0
  235. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/how-to/configure-auth.md +0 -0
  236. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/how-to/new-project.md +0 -0
  237. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/how-to/run-tests.md +0 -0
  238. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/how-to/sqlalchemy-repository.md +0 -0
  239. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/howto/mcp-setup.md +0 -0
  240. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/index.md +0 -0
  241. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/reference/api.md +0 -0
  242. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/reference/configuration.md +0 -0
  243. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/reference/framework-modules.md +0 -0
  244. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/tutorials/first-domain.md +0 -0
  245. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/ja/tutorials/getting-started.md +0 -0
  246. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/pt-br/index.md +0 -0
  247. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/pt-br/tutorials/getting-started.md +0 -0
  248. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/reference/api.md +0 -0
  249. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/reference/configuration.md +0 -0
  250. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/reference/framework-modules.md +0 -0
  251. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/roadmap.md +0 -0
  252. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/templates/field-trial-report.md +0 -0
  253. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/todo/current.md +0 -0
  254. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/tutorials/first-domain.md +0 -0
  255. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/tutorials/getting-started.md +0 -0
  256. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/zh/index.md +0 -0
  257. {nene2_python-1.8.39 → nene2_python-1.8.40}/docs/zh/tutorials/getting-started.md +0 -0
  258. {nene2_python-1.8.39 → nene2_python-1.8.40}/package-lock.json +0 -0
  259. {nene2_python-1.8.39 → nene2_python-1.8.40}/package.json +0 -0
  260. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/__init__.py +0 -0
  261. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/__main__.py +0 -0
  262. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/app.py +0 -0
  263. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/comment/__init__.py +0 -0
  264. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/comment/entity.py +0 -0
  265. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/comment/exceptions.py +0 -0
  266. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/comment/handler.py +0 -0
  267. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/comment/repository.py +0 -0
  268. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/comment/sqlalchemy_repository.py +0 -0
  269. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/comment/use_case.py +0 -0
  270. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/mcp.py +0 -0
  271. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/__init__.py +0 -0
  272. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/async_use_case.py +0 -0
  273. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/entity.py +0 -0
  274. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/exceptions.py +0 -0
  275. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/handler.py +0 -0
  276. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/repository.py +0 -0
  277. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/sqlalchemy_repository.py +0 -0
  278. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/note/use_case.py +0 -0
  279. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/schema.py +0 -0
  280. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/tag/__init__.py +0 -0
  281. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/tag/entity.py +0 -0
  282. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/tag/exceptions.py +0 -0
  283. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/tag/handler.py +0 -0
  284. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/tag/repository.py +0 -0
  285. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/tag/sqlalchemy_repository.py +0 -0
  286. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/example/tag/use_case.py +0 -0
  287. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/__init__.py +0 -0
  288. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/auth/__init__.py +0 -0
  289. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/auth/api_key.py +0 -0
  290. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/auth/bearer_token.py +0 -0
  291. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/auth/deps.py +0 -0
  292. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/auth/exceptions.py +0 -0
  293. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/auth/interfaces.py +0 -0
  294. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/auth/local_verifier.py +0 -0
  295. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/cache/__init__.py +0 -0
  296. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/cache/ttl.py +0 -0
  297. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/config/__init__.py +0 -0
  298. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/config/settings.py +0 -0
  299. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/database/__init__.py +0 -0
  300. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/database/exceptions.py +0 -0
  301. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/database/health.py +0 -0
  302. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/database/interfaces.py +0 -0
  303. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/database/sqlalchemy_executor.py +0 -0
  304. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/database/utils.py +0 -0
  305. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/http/__init__.py +0 -0
  306. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/http/etag.py +0 -0
  307. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/http/health.py +0 -0
  308. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/http/pagination.py +0 -0
  309. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/http/problem_details.py +0 -0
  310. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/log/__init__.py +0 -0
  311. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/log/setup.py +0 -0
  312. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/mcp/__init__.py +0 -0
  313. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/mcp/http_client.py +0 -0
  314. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/mcp/server.py +0 -0
  315. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/__init__.py +0 -0
  316. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/domain_exception.py +0 -0
  317. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/error_handler.py +0 -0
  318. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/request_id.py +0 -0
  319. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/request_logging.py +0 -0
  320. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/request_size_limit.py +0 -0
  321. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/security_headers.py +0 -0
  322. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/setup.py +0 -0
  323. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/middleware/throttle.py +0 -0
  324. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/py.typed +0 -0
  325. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/security/__init__.py +0 -0
  326. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/security/webhook.py +0 -0
  327. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/use_case/__init__.py +0 -0
  328. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/use_case/protocols.py +0 -0
  329. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/validation/__init__.py +0 -0
  330. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/nene2/validation/exceptions.py +0 -0
  331. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/scripts/__init__.py +0 -0
  332. {nene2_python-1.8.39 → nene2_python-1.8.40}/src/scripts/export_openapi.py +0 -0
  333. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/__init__.py +0 -0
  334. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/conftest.py +0 -0
  335. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/__init__.py +0 -0
  336. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/comment/__init__.py +0 -0
  337. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/comment/test_comment_http.py +0 -0
  338. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/comment/test_comment_repository.py +0 -0
  339. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/comment/test_comment_use_case.py +0 -0
  340. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/conftest.py +0 -0
  341. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/note/__init__.py +0 -0
  342. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/note/test_async_note_use_case.py +0 -0
  343. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/note/test_list_notes.py +0 -0
  344. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/note/test_note_repository.py +0 -0
  345. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/tag/__init__.py +0 -0
  346. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/tag/test_tag_repository.py +0 -0
  347. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/tag/test_tags.py +0 -0
  348. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/test_cors.py +0 -0
  349. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/example/test_mcp.py +0 -0
  350. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/__init__.py +0 -0
  351. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/auth/__init__.py +0 -0
  352. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/auth/test_api_key.py +0 -0
  353. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/auth/test_bearer_token.py +0 -0
  354. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/auth/test_make_require_auth.py +0 -0
  355. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/auth/test_token_issuer.py +0 -0
  356. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/cache/__init__.py +0 -0
  357. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/cache/test_ttl.py +0 -0
  358. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/config/__init__.py +0 -0
  359. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/config/test_settings.py +0 -0
  360. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/database/__init__.py +0 -0
  361. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/database/test_transaction.py +0 -0
  362. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/database/test_utils.py +0 -0
  363. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/http/__init__.py +0 -0
  364. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/http/test_etag.py +0 -0
  365. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/http/test_health.py +0 -0
  366. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/http/test_pagination.py +0 -0
  367. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/http/test_problem_details.py +0 -0
  368. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/log/__init__.py +0 -0
  369. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/log/test_setup.py +0 -0
  370. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/mcp/__init__.py +0 -0
  371. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/mcp/test_http_client.py +0 -0
  372. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/mcp/test_server.py +0 -0
  373. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/__init__.py +0 -0
  374. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_error_handler.py +0 -0
  375. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_request_id.py +0 -0
  376. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_request_logging.py +0 -0
  377. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_request_size_limit.py +0 -0
  378. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_security_headers.py +0 -0
  379. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_setup_middlewares.py +0 -0
  380. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_simple_domain_handler.py +0 -0
  381. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/middleware/test_throttle.py +0 -0
  382. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/security/__init__.py +0 -0
  383. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/security/test_webhook.py +0 -0
  384. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/use_case/__init__.py +0 -0
  385. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/use_case/test_protocols.py +0 -0
  386. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/use_case/test_run_in_threadpool.py +0 -0
  387. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/validation/__init__.py +0 -0
  388. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/nene2/validation/test_exceptions.py +0 -0
  389. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/scripts/__init__.py +0 -0
  390. {nene2_python-1.8.39 → nene2_python-1.8.40}/tests/scripts/test_export_openapi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nene2-python
3
- Version: 1.8.39
3
+ Version: 1.8.40
4
4
  Summary: NENE2 Python — minimal API framework following NENE2's design philosophy
5
5
  Project-URL: Homepage, https://github.com/hideyukiMORI/nene2-python
6
6
  Project-URL: Repository, https://github.com/hideyukiMORI/nene2-python
@@ -0,0 +1,272 @@
1
+ # FT169: typing モジュール
2
+
3
+ **日付**: 2026-05-21
4
+ **テーマ**: `typing` モジュール — `TypedDict`・`Protocol`・`overload`・`Literal`・`TypeGuard`・`Required`/`NotRequired`
5
+ **セキュリティ診断**: なし(169 % 3 = 2)
6
+
7
+ ---
8
+
9
+ ## 概要
10
+
11
+ Python 標準ライブラリの `typing` モジュール(Python 3.12+ の先進的な機能を含む)を
12
+ nene2-python フレームワーク上で検証した。
13
+ `typing` は nene2 の「strict typing」設計哲学の根幹であり、
14
+ HTTP 境界の型安全性・ドメインモデルの不変性・プロトコルによる構造的サブタイピングを
15
+ 支える重要モジュール。
16
+ CLAUDE.md の型安全ポリシー(`Any` 禁止・`TypedDict`・`Protocol` 活用)に直接対応する。
17
+
18
+ ---
19
+
20
+ ## 実装したサンプルアプリ
21
+
22
+ **場所**: `/home/xi/docker/nene2-python-FT/ft169-typing/`
23
+
24
+ ### 主要機能
25
+
26
+ | 関数/クラス | 概要 |
27
+ |---|---|
28
+ | `NoteDict` (TypedDict) | 構造化辞書の型定義。`id`, `title`, `content` |
29
+ | `NoteCreateDict` (TypedDict) | `NotRequired[str]` でオプショナルフィールドを表現 |
30
+ | `NoteWithMetaDict` (TypedDict 継承) | `total=False` でオプショナル拡張フィールドを追加 |
31
+ | `Serializable` (Protocol) | `@runtime_checkable` で `isinstance()` チェック可能な構造的サブタイプ |
32
+ | `Closeable` (Protocol) | `close()` を持つリソースのプロトコル |
33
+ | `parse_id()` (@overload) | `str` 引数 → `int \| None`、`int` 引数 → `int` の型多態性 |
34
+ | `double()` (@overload) | `int` / `str` / `float` それぞれに異なる戻り値型 |
35
+ | `SortOrder` / `NoteStatus` / `HttpStatusCode` (Literal) | `type` エイリアス + `Literal` で定数列挙 |
36
+ | `is_note_dict()` (TypeGuard) | 実行時の型絞り込み関数 |
37
+ | `build_search_params()` | `Required` / `NotRequired` を持つ `SearchQuery` TypedDict の利用例 |
38
+ | `inspect_hints()` | `get_type_hints()` で実行時にクラスメソッドの型情報を取得 |
39
+
40
+ ### HTTP エンドポイント
41
+
42
+ | メソッド | パス | 概要 |
43
+ |---|---|---|
44
+ | POST | `/typing/notes` | TypedDict でノートを作成 |
45
+ | GET | `/typing/notes` | Literal `SortOrder` でノートをソート |
46
+ | POST | `/typing/notes/tags` | TypedDict 継承でタグを追加 |
47
+ | GET | `/typing/parse-id` | @overload — 文字列 → int 変換 |
48
+ | GET | `/typing/double` | @overload — 型別の倍返し |
49
+ | POST | `/typing/search` | Required/NotRequired を持つ SearchQuery |
50
+ | GET | `/typing/type-guard` | TypeGuard で型絞り込み |
51
+ | GET | `/typing/protocol` | Protocol + is_serializable() |
52
+ | POST | `/typing/close-resources` | Closeable Protocol でリソース管理 |
53
+ | GET | `/typing/hints` | get_type_hints() でクラスのヒント取得 |
54
+ | GET | `/typing/filter-status` | Literal[NoteStatus] でフィルタリング |
55
+ | GET | `/typing/response` | Literal[HttpStatusCode] でレスポンス生成 |
56
+
57
+ ---
58
+
59
+ ## テスト結果
60
+
61
+ **45 passed(摩擦ゼロ)**
62
+
63
+ ```
64
+ 45 passed in 0.86s
65
+ ```
66
+
67
+ ---
68
+
69
+ ## 摩擦ポイント
70
+
71
+ **今回の FT では実装上の摩擦はゼロだった。**
72
+
73
+ ---
74
+
75
+ ## 観察点
76
+
77
+ ### 観察1: `type` エイリアス構文(Python 3.12+)で `Literal` を名前付き型にできる
78
+
79
+ ```python
80
+ type SortOrder = Literal["asc", "desc"]
81
+ type NoteStatus = Literal["draft", "published", "archived"]
82
+ type HttpStatusCode = Literal[200, 201, 204, 400, 401, 403, 404, 422, 500]
83
+ ```
84
+
85
+ Python 3.12 の `type` ステートメントを使うと、`Literal` に意味のある名前がつく。
86
+ `TypeAlias` アノテーション(旧形式)より明示的で mypy --strict に通る。
87
+ 定数の列挙は Enum でなく Literal + type エイリアスが軽量な代替になる。
88
+
89
+ ### 観察2: `TypedDict` + `NotRequired` で HTTP BodyModel の代替が作れる
90
+
91
+ ```python
92
+ class NoteCreateDict(TypedDict):
93
+ title: str
94
+ content: NotRequired[str] # 省略可能
95
+ ```
96
+
97
+ Pydantic BaseModel が必要な HTTP 境界では引き続き Pydantic を使うが、
98
+ UseCase 内部のデータ構造・関数の引数・レポジトリの返り値には
99
+ `TypedDict` が軽量で mypy に完全対応する。
100
+ `total=False` よりも `NotRequired` を使う方が、どのフィールドが省略可能かが明確。
101
+
102
+ ### 観察3: `@runtime_checkable Protocol` で `isinstance()` による構造的型チェックが可能
103
+
104
+ ```python
105
+ @runtime_checkable
106
+ class Serializable(Protocol):
107
+ def to_dict(self) -> dict[str, object]: ...
108
+
109
+ note = InMemoryNote(1, "Test")
110
+ assert isinstance(note, Serializable) # True — クラス継承不要
111
+ ```
112
+
113
+ `InMemoryNote` は `Serializable` を継承していないが、`to_dict()` を持つため
114
+ `isinstance()` が `True` を返す。
115
+ nene2 のリポジトリパターンで「`to_dict()` を持つドメインオブジェクトなら何でも受け付ける」
116
+ 関数を書くときに有効。ただし `@runtime_checkable` はメソッドの「存在」しか確認せず、
117
+ 引数・戻り値型の一致は確認しない。
118
+
119
+ ### 観察4: `@overload` で引数の型による戻り値型の分岐を型安全に表現できる
120
+
121
+ ```python
122
+ @overload
123
+ def parse_id(value: str) -> int | None: ...
124
+ @overload
125
+ def parse_id(value: int) -> int: ...
126
+
127
+ def parse_id(value: str | int) -> int | None:
128
+ ...
129
+ ```
130
+
131
+ `parse_id(42)` のとき mypy は戻り値を `int`(`None` なし)と判断し、
132
+ `parse_id("foo")` のとき `int | None` と判断する。
133
+ `None` チェックを呼び出し側で毎回書く必要がなくなる箇所で効果的。
134
+
135
+ ### 観察5: `TypeGuard` で `Any` 型の辞書を型安全に絞り込める
136
+
137
+ ```python
138
+ def is_note_dict(obj: object) -> TypeGuard[NoteDict]:
139
+ if not isinstance(obj, dict):
140
+ return False
141
+ return (
142
+ isinstance(obj.get("id"), int)
143
+ and isinstance(obj.get("title"), str)
144
+ and isinstance(obj.get("content"), str)
145
+ )
146
+
147
+ def process_unknown(data: Any) -> str:
148
+ if is_note_dict(data):
149
+ return note_summary(data) # mypy はここで data を NoteDict として扱う
150
+ ```
151
+
152
+ 外部 JSON・DB 生クエリ結果など `Any` 型を安全に使う唯一の公式手段。
153
+ `cast()` は「信頼してキャスト」するだけだが、`TypeGuard` は実行時チェックと型絞り込みを両立する。
154
+
155
+ ---
156
+
157
+ ## nene2-python フレームワークとの統合
158
+
159
+ - `TypedDict` は nene2 の UseCase Input/Output DTO の軽量代替として使える(Pydantic より軽い)
160
+ - `Protocol` は `RepositoryInterface` の ABC 代替として `NoteRepositoryProtocol` を定義するのに有効
161
+ - `Literal` は nene2 の `SortOrder` / `DB_ADAPTER` 等の設定値型に直接適用できる
162
+ - `TypeGuard` は `/notes` 一覧取得の外部データを型安全に絞り込む Use Case で使える
163
+ - CLAUDE.md の「`Any` 禁止 / `TypedDict` で Dict 構造を型付け」ポリシーと完全に整合
164
+
165
+ ---
166
+
167
+ ## Developer Experience (DX) Review
168
+
169
+ ### ペルソナ1: 初心者(Python 歴1年・独学中・女性・バックエンド志望)
170
+
171
+ `TypedDict` は `class` で辞書を型定義する概念が新しく、
172
+ 「Pydantic の `BaseModel` と何が違うの?」という混乱が起きる。
173
+
174
+ **ドキュメント理解**: nene2 how-to に「HTTP 境界は Pydantic・UseCase 内部は TypedDict」の
175
+ 使い分けガイドがあれば即解決する。現時点では CLAUDE.md を読み込まないと判断できない。
176
+
177
+ **事故リスク**: 低。`TypedDict` の誤用は実行時エラーにはならず、mypy が検出してくれる。
178
+ ただし mypy なしで開発すると TypedDict の型安全の恩恵がゼロになる。
179
+
180
+ **規約の使いやすさ**: `NoteDict(TypedDict)` のパターンはコピペで書ける。
181
+ `total=False` と `NotRequired` の使い分けは最初は迷う。
182
+
183
+ ### ペルソナ2: ロースキル経験者(Python 歴3-4年・スクリプト系・男性・SES)
184
+
185
+ `Protocol` を「インターフェース」として理解できるが、
186
+ `@runtime_checkable` の「struct subtyping = 継承不要」は最初は驚く。
187
+ 「実行してみたら通った」という体験で理解が定着する。
188
+
189
+ **コピペ可能性**: 高。`@runtime_checkable class Xxx(Protocol)` はテンプレートとして使える。
190
+
191
+ **拡張時の罠**: `@runtime_checkable Protocol` はメソッドの引数・戻り値型を確認しない。
192
+ `to_dict() -> dict[str, object]` を `to_dict() -> str` に変えても `isinstance()` は `True` を返す。
193
+ 実行時の型安全は Protocol の責務ではなく、mypy の責務であることを理解が必要。
194
+
195
+ **セキュリティ的な事故リスク**: 低。typing の誤用がセキュリティインシデントに直結するケースは稀。
196
+
197
+ ### ペルソナ3: フロントエンド寄り経験者(React/TS 歴4年・バックエンド転向中・ノンバイナリ)
198
+
199
+ TypeScript の `interface` / `type` / `as const` との対応関係が作れる。
200
+ - TS の `interface` → Python の `TypedDict`(完全対応)
201
+ - TS の `as const` 配列 → Python の `Literal`(概念的に近い)
202
+ - TS の `function overloads` → Python の `@overload`(ほぼ同じ)
203
+ - TS の `type predicate` (`is`) → Python の `TypeGuard`(同等)
204
+
205
+ **エラーレスポンスの質**: 型ミスマッチは mypy が捕捉し、HTTP 境界では Pydantic が 422 を返す。
206
+ フロントエンド開発者にとって馴染みのある体験。
207
+
208
+ **事故リスク**: 低。TS の型システムの経験が直接活かせる。
209
+
210
+ ### ペルソナ4: バックエンド経験者(Django/FastAPI 歴5-6年・男性・リードエンジニア)
211
+
212
+ Django の `TypedDict` 活用は限定的(Django は dict よりモデルクラスを使う傾向)。
213
+ FastAPI ユーザーにとっては Pydantic v2 が `TypedDict` をスキーマとして受け付けるため、
214
+ 境界が曖昧になりやすい。
215
+
216
+ **他フレームワークとの差異**:
217
+ - Django: ドメインは Model クラスで表現、typing との組み合わせは発展途上
218
+ - nene2: TypedDict(UseCase 内部)+ Pydantic(HTTP 境界)の明確な使い分けが nene2 の差別化
219
+
220
+ **本番投入可能性**: 問題なし。`@overload` / `TypeGuard` は FastAPI ルーターとも問題なく共存する。
221
+
222
+ ### ペルソナ5: シニアエンジニア(設計・コードレビュー担当・女性・10-12年)
223
+
224
+ **コードレビューチェックポイント**:
225
+ - [ ] `TypedDict` フィールドに `NotRequired` を使って省略可能性を明示しているか(`total=False` は非推奨)
226
+ - [ ] `@runtime_checkable Protocol` を型安全の唯一の砦にしていないか(mypy でも確認必須)
227
+ - [ ] `@overload` の実装本体に型注釈が適切についているか(オーバーロードシグネチャのみ書いて本体を忘れるミス)
228
+ - [ ] `TypeGuard` 関数が実行時チェック(isinstance 等)を実施しているか(`return True` のみは危険)
229
+ - [ ] `cast()` には `# reason:` コメントがついているか(CLAUDE.md ポリシー)
230
+
231
+ **チームでの安全なパターン**: `TypedDict` は UseCase I/O の DTO として標準化し、
232
+ HTTP 境界は Pydantic、内部は TypedDict という二層構造を CLAUDE.md に明記する。
233
+
234
+ **ツール追加の必要性**: `mypy --strict` で `TypedDict` の型チェックが網羅されるため追加不要。
235
+
236
+ ### ペルソナ6: 設計者・ポリシー照合(nene2-python 設計ポリシー目線)
237
+
238
+ **ポリシー達成度**: 高
239
+
240
+ **「初心者でも安全な API」達成度**: 高
241
+ - `TypedDict` + mypy の組み合わせで、実行前に型エラーが検出される
242
+ - `TypeGuard` で `Any` 由来のデータを安全に絞り込める
243
+
244
+ **設計上の負債・ドキュメント不足**:
245
+ - CLAUDE.md の「TypedDict で Dict 構造を型付け」ポリシーは記載あるが、Pydantic との使い分けが未記載
246
+ - nene2 の UseCase Input/Output は `dataclass(frozen=True)` で実装されているが、
247
+ `TypedDict` が適切な場面(JSON 応答の直接マッピング等)も存在する
248
+
249
+ **Follow-up Issue 候補**: `docs: TypedDict vs Pydantic vs dataclass の使い分けガイドを how-to に追加`
250
+
251
+ ---
252
+
253
+ ## Follow-up Issues
254
+
255
+ | 優先度 | タイトル | 種別 |
256
+ |---|---|---|
257
+ | 中 | `docs: TypedDict vs Pydantic vs dataclass の使い分けガイドを how-to に追加` | docs |
258
+ | 低 | `feat: NoteRepositoryProtocol を TypedDict + Protocol で再実装するサンプルを追加` | feat |
259
+
260
+ ---
261
+
262
+ ## まとめ
263
+
264
+ `typing` モジュールは nene2-python の型安全設計の根幹をなす機能群。
265
+ 45 テスト全通過、摩擦ゼロ。
266
+
267
+ `TypedDict` + `NotRequired` は UseCase 内部データ構造の軽量 DTO として直接使える。
268
+ `Protocol` + `@runtime_checkable` は nene2 の `RepositoryInterface` の ABC 代替として有効で、
269
+ 継承なしの構造的サブタイピングを実現する。
270
+ `TypeGuard` は `Any` 型データを型安全に絞り込む唯一の公式手段で、外部データ処理に必須。
271
+ Python 3.12 の `type X = Literal[...]` 構文で定数列挙が軽量に書ける。
272
+
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nene2-python"
3
- version = "1.8.39"
3
+ version = "1.8.40"
4
4
  description = "NENE2 Python — minimal API framework following NENE2's design philosophy"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -925,7 +925,7 @@ wheels = [
925
925
 
926
926
  [[package]]
927
927
  name = "nene2-python"
928
- version = "1.8.39"
928
+ version = "1.8.40"
929
929
  source = { editable = "." }
930
930
  dependencies = [
931
931
  { name = "alembic" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes