nene2-python 1.8.55__tar.gz → 1.8.56__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 (407) hide show
  1. {nene2_python-1.8.55 → nene2_python-1.8.56}/PKG-INFO +1 -1
  2. nene2_python-1.8.56/docs/field-trials/2026-05-field-trial-185.md +246 -0
  3. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/INDEX.md +2 -1
  4. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/todo/current.md +6 -5
  5. {nene2_python-1.8.55 → nene2_python-1.8.56}/pyproject.toml +1 -1
  6. {nene2_python-1.8.55 → nene2_python-1.8.56}/.env.example +0 -0
  7. {nene2_python-1.8.55 → nene2_python-1.8.56}/.github/workflows/ci.yml +0 -0
  8. {nene2_python-1.8.55 → nene2_python-1.8.56}/.github/workflows/docs.yml +0 -0
  9. {nene2_python-1.8.55 → nene2_python-1.8.56}/.github/workflows/publish.yml +0 -0
  10. {nene2_python-1.8.55 → nene2_python-1.8.56}/.gitignore +0 -0
  11. {nene2_python-1.8.55 → nene2_python-1.8.56}/.vitepress/config.mts +0 -0
  12. {nene2_python-1.8.55 → nene2_python-1.8.56}/.vitepress/theme/custom.css +0 -0
  13. {nene2_python-1.8.55 → nene2_python-1.8.56}/.vitepress/theme/index.ts +0 -0
  14. {nene2_python-1.8.55 → nene2_python-1.8.56}/AGENTS.md +0 -0
  15. {nene2_python-1.8.55 → nene2_python-1.8.56}/CHANGELOG.md +0 -0
  16. {nene2_python-1.8.55 → nene2_python-1.8.56}/CLAUDE.md +0 -0
  17. {nene2_python-1.8.55 → nene2_python-1.8.56}/Dockerfile +0 -0
  18. {nene2_python-1.8.55 → nene2_python-1.8.56}/LICENSE +0 -0
  19. {nene2_python-1.8.55 → nene2_python-1.8.56}/README.md +0 -0
  20. {nene2_python-1.8.55 → nene2_python-1.8.56}/alembic/README +0 -0
  21. {nene2_python-1.8.55 → nene2_python-1.8.56}/alembic/env.py +0 -0
  22. {nene2_python-1.8.55 → nene2_python-1.8.56}/alembic/script.py.mako +0 -0
  23. {nene2_python-1.8.55 → nene2_python-1.8.56}/alembic/versions/001_create_notes_and_tags_tables.py +0 -0
  24. {nene2_python-1.8.55 → nene2_python-1.8.56}/alembic.ini +0 -0
  25. {nene2_python-1.8.55 → nene2_python-1.8.56}/compose.yaml +0 -0
  26. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0001-toolchain.md +0 -0
  27. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0002-clean-architecture.md +0 -0
  28. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0003-security-first.md +0 -0
  29. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0004-ai-first-design.md +0 -0
  30. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0005-logging.md +0 -0
  31. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0006-rate-limiting.md +0 -0
  32. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0009-mcp-design.md +0 -0
  33. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0010-async-use-case.md +0 -0
  34. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/adr/0011-mcp-as-core-dependency.md +0 -0
  35. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/de/index.md +0 -0
  36. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/de/tutorials/getting-started.md +0 -0
  37. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/explanation/architecture.md +0 -0
  38. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/explanation/design-philosophy.md +0 -0
  39. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-1.md +0 -0
  40. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-10.md +0 -0
  41. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-100.md +0 -0
  42. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-101.md +0 -0
  43. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-102.md +0 -0
  44. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-103.md +0 -0
  45. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-104.md +0 -0
  46. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-105.md +0 -0
  47. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-106.md +0 -0
  48. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-107.md +0 -0
  49. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-108.md +0 -0
  50. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-109.md +0 -0
  51. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-11.md +0 -0
  52. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-110.md +0 -0
  53. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-111.md +0 -0
  54. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-112.md +0 -0
  55. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-113.md +0 -0
  56. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-114.md +0 -0
  57. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-115.md +0 -0
  58. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-116.md +0 -0
  59. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-117.md +0 -0
  60. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-118.md +0 -0
  61. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-119.md +0 -0
  62. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-12.md +0 -0
  63. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-120.md +0 -0
  64. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-121.md +0 -0
  65. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-122.md +0 -0
  66. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-123.md +0 -0
  67. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-124.md +0 -0
  68. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-125.md +0 -0
  69. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-126.md +0 -0
  70. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-127.md +0 -0
  71. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-128.md +0 -0
  72. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-129.md +0 -0
  73. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-13.md +0 -0
  74. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-130.md +0 -0
  75. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-131.md +0 -0
  76. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-132.md +0 -0
  77. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-133.md +0 -0
  78. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-134.md +0 -0
  79. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-135.md +0 -0
  80. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-136.md +0 -0
  81. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-137.md +0 -0
  82. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-138.md +0 -0
  83. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-139.md +0 -0
  84. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-14.md +0 -0
  85. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-140.md +0 -0
  86. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-141.md +0 -0
  87. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-142.md +0 -0
  88. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-143.md +0 -0
  89. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-144.md +0 -0
  90. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-145.md +0 -0
  91. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-146.md +0 -0
  92. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-147.md +0 -0
  93. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-148.md +0 -0
  94. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-149.md +0 -0
  95. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-15.md +0 -0
  96. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-150.md +0 -0
  97. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-151.md +0 -0
  98. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-152.md +0 -0
  99. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-153.md +0 -0
  100. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-154.md +0 -0
  101. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-155.md +0 -0
  102. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-156.md +0 -0
  103. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-157.md +0 -0
  104. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-158.md +0 -0
  105. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-159.md +0 -0
  106. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-16.md +0 -0
  107. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-160.md +0 -0
  108. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-161.md +0 -0
  109. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-162.md +0 -0
  110. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-163.md +0 -0
  111. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-164.md +0 -0
  112. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-165.md +0 -0
  113. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-166.md +0 -0
  114. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-167.md +0 -0
  115. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-168.md +0 -0
  116. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-169.md +0 -0
  117. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-17.md +0 -0
  118. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-170.md +0 -0
  119. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-171.md +0 -0
  120. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-172.md +0 -0
  121. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-173.md +0 -0
  122. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-174.md +0 -0
  123. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-175.md +0 -0
  124. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-176.md +0 -0
  125. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-177.md +0 -0
  126. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-178.md +0 -0
  127. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-179.md +0 -0
  128. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-18.md +0 -0
  129. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-180.md +0 -0
  130. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-181.md +0 -0
  131. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-182.md +0 -0
  132. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-183.md +0 -0
  133. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-184.md +0 -0
  134. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-19.md +0 -0
  135. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-2.md +0 -0
  136. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-20.md +0 -0
  137. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-21.md +0 -0
  138. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-22.md +0 -0
  139. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-23.md +0 -0
  140. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-24.md +0 -0
  141. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-25.md +0 -0
  142. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-26.md +0 -0
  143. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-27.md +0 -0
  144. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-28.md +0 -0
  145. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-29.md +0 -0
  146. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-3.md +0 -0
  147. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-30.md +0 -0
  148. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-31.md +0 -0
  149. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-32.md +0 -0
  150. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-33.md +0 -0
  151. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-34.md +0 -0
  152. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-35.md +0 -0
  153. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-36.md +0 -0
  154. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-37.md +0 -0
  155. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-38.md +0 -0
  156. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-39.md +0 -0
  157. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-4.md +0 -0
  158. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-40.md +0 -0
  159. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-41.md +0 -0
  160. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-42.md +0 -0
  161. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-43.md +0 -0
  162. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-44.md +0 -0
  163. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-45.md +0 -0
  164. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-46.md +0 -0
  165. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-47.md +0 -0
  166. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-48.md +0 -0
  167. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-49.md +0 -0
  168. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-5.md +0 -0
  169. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-50.md +0 -0
  170. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-51.md +0 -0
  171. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-52.md +0 -0
  172. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-53.md +0 -0
  173. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-54.md +0 -0
  174. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-55.md +0 -0
  175. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-56.md +0 -0
  176. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-57.md +0 -0
  177. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-58.md +0 -0
  178. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-59.md +0 -0
  179. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-6.md +0 -0
  180. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-60.md +0 -0
  181. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-61.md +0 -0
  182. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-62.md +0 -0
  183. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-63.md +0 -0
  184. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-64.md +0 -0
  185. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-65.md +0 -0
  186. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-66.md +0 -0
  187. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-67.md +0 -0
  188. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-68.md +0 -0
  189. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-69.md +0 -0
  190. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-7.md +0 -0
  191. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-70.md +0 -0
  192. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-71.md +0 -0
  193. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-72.md +0 -0
  194. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-73.md +0 -0
  195. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-74.md +0 -0
  196. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-75.md +0 -0
  197. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-76.md +0 -0
  198. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-77.md +0 -0
  199. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-78.md +0 -0
  200. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-79.md +0 -0
  201. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-8.md +0 -0
  202. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-80.md +0 -0
  203. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-81.md +0 -0
  204. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-82.md +0 -0
  205. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-83.md +0 -0
  206. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-84.md +0 -0
  207. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-85.md +0 -0
  208. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-86.md +0 -0
  209. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-87.md +0 -0
  210. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-88.md +0 -0
  211. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-89.md +0 -0
  212. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-9.md +0 -0
  213. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-90.md +0 -0
  214. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-91.md +0 -0
  215. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-92.md +0 -0
  216. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-93.md +0 -0
  217. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-94.md +0 -0
  218. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-95.md +0 -0
  219. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-96.md +0 -0
  220. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-97.md +0 -0
  221. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-98.md +0 -0
  222. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/field-trials/2026-05-field-trial-99.md +0 -0
  223. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/fr/index.md +0 -0
  224. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/fr/tutorials/getting-started.md +0 -0
  225. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/add-new-domain.md +0 -0
  226. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/api-versioning.md +0 -0
  227. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/async-use-case.md +0 -0
  228. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/background-tasks.md +0 -0
  229. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/configure-auth.md +0 -0
  230. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/cors.md +0 -0
  231. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/custom-auth-middleware.md +0 -0
  232. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/dependency-injection.md +0 -0
  233. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/domain-events.md +0 -0
  234. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/file-upload.md +0 -0
  235. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/lifespan-and-app-state.md +0 -0
  236. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/middleware-stack.md +0 -0
  237. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/new-project.md +0 -0
  238. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/problem-details.md +0 -0
  239. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/response-patterns.md +0 -0
  240. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/run-tests.md +0 -0
  241. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/soft-delete.md +0 -0
  242. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/sqlalchemy-repository.md +0 -0
  243. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/streaming.md +0 -0
  244. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/structured-logging.md +0 -0
  245. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/validation.md +0 -0
  246. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/how-to/webhook.md +0 -0
  247. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/howto/mcp-setup.md +0 -0
  248. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/index.md +0 -0
  249. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/explanation/architecture.md +0 -0
  250. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/explanation/design-philosophy.md +0 -0
  251. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/how-to/add-new-domain.md +0 -0
  252. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/how-to/configure-auth.md +0 -0
  253. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/how-to/new-project.md +0 -0
  254. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/how-to/run-tests.md +0 -0
  255. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/how-to/sqlalchemy-repository.md +0 -0
  256. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/howto/mcp-setup.md +0 -0
  257. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/index.md +0 -0
  258. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/reference/api.md +0 -0
  259. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/reference/configuration.md +0 -0
  260. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/reference/framework-modules.md +0 -0
  261. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/tutorials/first-domain.md +0 -0
  262. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/ja/tutorials/getting-started.md +0 -0
  263. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/pt-br/index.md +0 -0
  264. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/pt-br/tutorials/getting-started.md +0 -0
  265. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/reference/api.md +0 -0
  266. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/reference/configuration.md +0 -0
  267. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/reference/framework-modules.md +0 -0
  268. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/roadmap.md +0 -0
  269. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/templates/field-trial-report.md +0 -0
  270. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/tutorials/first-domain.md +0 -0
  271. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/tutorials/getting-started.md +0 -0
  272. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/zh/index.md +0 -0
  273. {nene2_python-1.8.55 → nene2_python-1.8.56}/docs/zh/tutorials/getting-started.md +0 -0
  274. {nene2_python-1.8.55 → nene2_python-1.8.56}/package-lock.json +0 -0
  275. {nene2_python-1.8.55 → nene2_python-1.8.56}/package.json +0 -0
  276. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/__init__.py +0 -0
  277. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/__main__.py +0 -0
  278. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/app.py +0 -0
  279. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/comment/__init__.py +0 -0
  280. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/comment/entity.py +0 -0
  281. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/comment/exceptions.py +0 -0
  282. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/comment/handler.py +0 -0
  283. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/comment/repository.py +0 -0
  284. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/comment/sqlalchemy_repository.py +0 -0
  285. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/comment/use_case.py +0 -0
  286. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/mcp.py +0 -0
  287. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/__init__.py +0 -0
  288. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/async_use_case.py +0 -0
  289. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/entity.py +0 -0
  290. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/exceptions.py +0 -0
  291. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/handler.py +0 -0
  292. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/repository.py +0 -0
  293. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/sqlalchemy_repository.py +0 -0
  294. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/note/use_case.py +0 -0
  295. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/schema.py +0 -0
  296. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/tag/__init__.py +0 -0
  297. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/tag/entity.py +0 -0
  298. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/tag/exceptions.py +0 -0
  299. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/tag/handler.py +0 -0
  300. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/tag/repository.py +0 -0
  301. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/tag/sqlalchemy_repository.py +0 -0
  302. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/example/tag/use_case.py +0 -0
  303. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/__init__.py +0 -0
  304. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/auth/__init__.py +0 -0
  305. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/auth/api_key.py +0 -0
  306. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/auth/bearer_token.py +0 -0
  307. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/auth/deps.py +0 -0
  308. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/auth/exceptions.py +0 -0
  309. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/auth/interfaces.py +0 -0
  310. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/auth/local_verifier.py +0 -0
  311. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/cache/__init__.py +0 -0
  312. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/cache/ttl.py +0 -0
  313. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/config/__init__.py +0 -0
  314. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/config/settings.py +0 -0
  315. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/database/__init__.py +0 -0
  316. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/database/exceptions.py +0 -0
  317. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/database/health.py +0 -0
  318. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/database/interfaces.py +0 -0
  319. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/database/sqlalchemy_executor.py +0 -0
  320. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/database/utils.py +0 -0
  321. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/http/__init__.py +0 -0
  322. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/http/etag.py +0 -0
  323. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/http/health.py +0 -0
  324. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/http/pagination.py +0 -0
  325. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/http/problem_details.py +0 -0
  326. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/log/__init__.py +0 -0
  327. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/log/setup.py +0 -0
  328. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/mcp/__init__.py +0 -0
  329. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/mcp/http_client.py +0 -0
  330. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/mcp/server.py +0 -0
  331. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/__init__.py +0 -0
  332. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/domain_exception.py +0 -0
  333. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/error_handler.py +0 -0
  334. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/request_id.py +0 -0
  335. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/request_logging.py +0 -0
  336. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/request_size_limit.py +0 -0
  337. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/security_headers.py +0 -0
  338. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/setup.py +0 -0
  339. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/middleware/throttle.py +0 -0
  340. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/py.typed +0 -0
  341. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/security/__init__.py +0 -0
  342. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/security/webhook.py +0 -0
  343. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/use_case/__init__.py +0 -0
  344. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/use_case/protocols.py +0 -0
  345. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/validation/__init__.py +0 -0
  346. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/nene2/validation/exceptions.py +0 -0
  347. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/scripts/__init__.py +0 -0
  348. {nene2_python-1.8.55 → nene2_python-1.8.56}/src/scripts/export_openapi.py +0 -0
  349. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/__init__.py +0 -0
  350. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/conftest.py +0 -0
  351. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/__init__.py +0 -0
  352. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/comment/__init__.py +0 -0
  353. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/comment/test_comment_http.py +0 -0
  354. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/comment/test_comment_repository.py +0 -0
  355. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/comment/test_comment_use_case.py +0 -0
  356. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/conftest.py +0 -0
  357. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/note/__init__.py +0 -0
  358. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/note/test_async_note_use_case.py +0 -0
  359. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/note/test_list_notes.py +0 -0
  360. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/note/test_note_repository.py +0 -0
  361. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/tag/__init__.py +0 -0
  362. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/tag/test_tag_repository.py +0 -0
  363. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/tag/test_tags.py +0 -0
  364. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/test_cors.py +0 -0
  365. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/example/test_mcp.py +0 -0
  366. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/__init__.py +0 -0
  367. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/auth/__init__.py +0 -0
  368. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/auth/test_api_key.py +0 -0
  369. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/auth/test_bearer_token.py +0 -0
  370. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/auth/test_make_require_auth.py +0 -0
  371. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/auth/test_token_issuer.py +0 -0
  372. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/cache/__init__.py +0 -0
  373. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/cache/test_ttl.py +0 -0
  374. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/config/__init__.py +0 -0
  375. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/config/test_settings.py +0 -0
  376. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/database/__init__.py +0 -0
  377. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/database/test_transaction.py +0 -0
  378. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/database/test_utils.py +0 -0
  379. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/http/__init__.py +0 -0
  380. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/http/test_etag.py +0 -0
  381. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/http/test_health.py +0 -0
  382. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/http/test_pagination.py +0 -0
  383. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/http/test_problem_details.py +0 -0
  384. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/log/__init__.py +0 -0
  385. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/log/test_setup.py +0 -0
  386. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/mcp/__init__.py +0 -0
  387. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/mcp/test_http_client.py +0 -0
  388. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/mcp/test_server.py +0 -0
  389. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/__init__.py +0 -0
  390. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_error_handler.py +0 -0
  391. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_request_id.py +0 -0
  392. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_request_logging.py +0 -0
  393. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_request_size_limit.py +0 -0
  394. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_security_headers.py +0 -0
  395. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_setup_middlewares.py +0 -0
  396. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_simple_domain_handler.py +0 -0
  397. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/middleware/test_throttle.py +0 -0
  398. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/security/__init__.py +0 -0
  399. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/security/test_webhook.py +0 -0
  400. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/use_case/__init__.py +0 -0
  401. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/use_case/test_protocols.py +0 -0
  402. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/use_case/test_run_in_threadpool.py +0 -0
  403. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/validation/__init__.py +0 -0
  404. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/nene2/validation/test_exceptions.py +0 -0
  405. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/scripts/__init__.py +0 -0
  406. {nene2_python-1.8.55 → nene2_python-1.8.56}/tests/scripts/test_export_openapi.py +0 -0
  407. {nene2_python-1.8.55 → nene2_python-1.8.56}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nene2-python
3
- Version: 1.8.55
3
+ Version: 1.8.56
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,246 @@
1
+ # FT185: contextlib
2
+
3
+ **日付**: 2026-05-21
4
+ **テーマ**: contextlib モジュール — コンテキストマネージャー・リソース管理・エラー抑制
5
+ **セキュリティ診断**: なし(185 % 3 = 2)
6
+ **クラッカーペンテスト**: なし(185 % 4 = 1)
7
+
8
+ ---
9
+
10
+ ## 概要
11
+
12
+ Python 標準ライブラリ `contextlib` は、コンテキストマネージャーの作成・合成・利用を支援するユーティリティ集である。
13
+ `@contextmanager` デコレーター、`suppress`、`ExitStack`、`closing`、`nullcontext`、`ContextDecorator`、`chdir`(3.11+)など多岐にわたるツールを検証した。
14
+
15
+ ---
16
+
17
+ ## 実装したサンプルアプリ
18
+
19
+ **場所**: `/home/xi/docker/nene2-python-FT/ft185-contextlib/`
20
+
21
+ ### 主要機能
22
+
23
+ | 関数/クラス | 概要 |
24
+ |---|---|
25
+ | `timer(label)` | `@contextmanager` で経過時間を計測 |
26
+ | `capture_stdout()` | `redirect_stdout` で標準出力をキャプチャ |
27
+ | `temp_attr(obj, attr, value)` | 属性を一時的に変更して復元する |
28
+ | `safe_int(value)` | `suppress(ValueError)` で変換失敗を吸収 |
29
+ | `safe_delete(dict, key)` | `suppress(KeyError)` で削除失敗を吸収 |
30
+ | `query_with_closing(host, sql)` | `closing` で接続を確実にクローズ |
31
+ | `fake_transaction(fail_on)` | ロールバック/コミットを持つトランザクション |
32
+ | `ManagedBuffer` | `ExitStack` で複数バッファのライフサイクルを管理 |
33
+ | `process_data(data, lock)` | `nullcontext` でオプションのロックを抽象化 |
34
+ | `run_and_capture(func)` | `redirect_stdout` / `redirect_stderr` で出力をキャプチャ |
35
+ | `run_pipeline(steps)` | `ExitStack` + コールバックでパイプライン管理 |
36
+ | `RetryContext` | `AbstractContextManager` の具象実装 |
37
+ | `LoggingContext` | `ContextDecorator` でデコレーターとしても使用可 |
38
+ | `batched_writer(items, batch_size)` | アイテムをバッチ分割するコンテキストマネージャー |
39
+ | `read_file_safe(path)` | `suppress(OSError)` でファイル読み込み失敗を吸収 |
40
+ | `get_current_dir_in_context(path)` | `contextlib.chdir` で一時ディレクトリ移動 |
41
+
42
+ ### HTTP エンドポイント
43
+
44
+ | メソッド | パス | 概要 |
45
+ |---|---|---|
46
+ | POST | `/suppress/int` | 文字列→int 変換(失敗時 null)|
47
+ | POST | `/suppress/delete` | 辞書キーを安全に削除 |
48
+ | POST | `/transaction` | フェイクトランザクション(コミット/ロールバック)|
49
+ | POST | `/pipeline` | ExitStack パイプライン実行 |
50
+ | POST | `/buffer` | ManagedBuffer で複数バッファ管理 |
51
+ | POST | `/timer` | 経過時間計測 |
52
+ | POST | `/batch` | バッチ分割 |
53
+ | POST | `/query` | closing 付きクエリ実行 |
54
+
55
+ ---
56
+
57
+ ## テスト結果
58
+
59
+ **50 passed**
60
+
61
+ ```
62
+ 50 passed in 0.31s
63
+ ```
64
+
65
+ mypy --strict: Success
66
+ ruff check: All checks passed
67
+ pip-audit: PYSEC-2025-183 (PyJWT via mcp transitive dep — 許容済み)
68
+
69
+ ---
70
+
71
+ ## 摩擦ポイント
72
+
73
+ ### F-1: `__exit__` の戻り値型に `bool` は不可(mypy --strict)(深刻度: 低)
74
+
75
+ **事象**: `AbstractContextManager` サブクラスの `__exit__` メソッドで戻り値型を `bool` と宣言したところ、mypy --strict が以下のエラーを出力した。
76
+
77
+ ```
78
+ "bool" is invalid as return type for "__exit__" that always returns False
79
+ Use "typing.Literal[False]" as the return type or change it to "None"
80
+ ```
81
+
82
+ **原因**: mypy は `__exit__` が `True` を返すと「例外を抑制する」と解釈する。`bool` 型はその可能性を示すため、常に `False` を返す実装では `Literal[False]` か `None` を使うよう要求される。
83
+
84
+ **対応**: 戻り値型を `Literal[False]` に変更(`from typing import Literal` が必要)。
85
+
86
+ ```python
87
+ from typing import Literal
88
+
89
+ def __exit__(self, exc_type, exc_val, exc_tb) -> Literal[False]:
90
+ return False
91
+ ```
92
+
93
+ ---
94
+
95
+ ## 観察点
96
+
97
+ ### 観察1: `@contextmanager` の yield 前後でのクリーンアップ
98
+
99
+ ```python
100
+ @contextlib.contextmanager
101
+ def timer(label: str) -> Generator[dict[str, float], None, None]:
102
+ result: dict[str, float] = {}
103
+ start = time.perf_counter()
104
+ try:
105
+ yield result
106
+ finally:
107
+ result["elapsed"] = time.perf_counter() - start
108
+ ```
109
+
110
+ `try / finally` パターンによって、`with` ブロック内で例外が発生しても `finally` が確実に実行される。yield した辞書を通じて結果を呼び出し元に渡せる点が特徴的。
111
+
112
+ ### 観察2: `ExitStack.callback` による動的クリーンアップ
113
+
114
+ ```python
115
+ with contextlib.ExitStack() as stack:
116
+ for resource in resources:
117
+ stack.callback(release_resource, resource)
118
+ acquired.append(resource)
119
+ ```
120
+
121
+ コンテキストマネージャーを持たないリソースでも `callback` で後処理を登録できる。登録は LIFO 順で実行されるため、依存関係のあるリソースも安全に解放できる。
122
+
123
+ ### 観察3: `ContextDecorator` で関数デコレーターを兼ねる
124
+
125
+ ```python
126
+ class LoggingContext(contextlib.ContextDecorator):
127
+ def __enter__(self): ...
128
+ def __exit__(self, ...): ...
129
+
130
+ ctx = LoggingContext("fn")
131
+
132
+ # コンテキストマネージャーとして
133
+ with ctx:
134
+ do_something()
135
+
136
+ # デコレーターとして
137
+ @ctx
138
+ def my_func():
139
+ do_something()
140
+ ```
141
+
142
+ `ContextDecorator` を継承するだけで `with` と `@decorator` の両方の文脈で使用できるようになる。テスト・ロギング・タイミングの実装で有用。
143
+
144
+ ### 観察4: `nullcontext` でオプションのロックを統一的に扱う
145
+
146
+ ```python
147
+ def process_data(data, lock=None):
148
+ ctx = lock if lock is not None else contextlib.nullcontext()
149
+ with ctx:
150
+ return sum(data)
151
+ ```
152
+
153
+ 呼び出し元からロックを渡せる場合と不要な場合を、`with` 文を2回書かずに統一できる。シングルスレッドのテストでは `lock=None`、マルチスレッドでは実際のロックを渡すという設計が自然に表現できる。
154
+
155
+ ### 観察5: `contextlib.chdir` (Python 3.11+)
156
+
157
+ ```python
158
+ original = os.getcwd()
159
+ with contextlib.chdir("/tmp"):
160
+ # /tmp が cwd
161
+ pass
162
+ # original に戻っている
163
+ ```
164
+
165
+ `os.chdir()` を手動で `try/finally` でラップする必要がなくなる。Python 3.11 以降でのみ使用可能なため、3.10 以下をサポートする場合は自前実装が必要。
166
+
167
+ ---
168
+
169
+ ## Follow-up Issues
170
+
171
+ 今回の FT では実装上の重大な摩擦はなかった。F-1 は mypy の型精度要求によるものであり、Python 型システムの理解向上につながる知見として記録する。
172
+
173
+ GitHub Issues: なし
174
+
175
+ ---
176
+
177
+ ## DX Review — 6ペルソナ
178
+
179
+ ### 1. 初心者(Python 歴1年・独学中・女性・バックエンド志望)
180
+
181
+ FastAPI でエラーを無視したいとき `try/except pass` を書いていたが、`contextlib.suppress` を知ることで「名前のついた意図表現」に切り替えられる。
182
+
183
+ **ドキュメント理解**: `@contextmanager` の `yield` の意味(「ここで with ブロックに入る」)が直感的でない。`yield result` が値を返すだけでなくコンテキストを区切るという二重の役割は、初見では混乱しやすい。
184
+
185
+ **事故リスク**: 低 — `suppress` の乱用で重要な例外を握りつぶすリスクはあるが、デモコードでは抑制対象の例外を明示しているため、コピペしても事故にはなりにくい。
186
+
187
+ **規約の使いやすさ**: 豊富なサンプルによって「suppress で受ける」「timer で囲む」「ExitStack で登録する」という用法がパターンとして身につく。
188
+
189
+ ### 2. ロースキル経験者(Python 歴3-4年・スクリプト系・男性・SES)
190
+
191
+ `ExitStack` の使い所が「複数のファイルを条件によって開く」といったシナリオで真価を発揮することが理解できれば、実務でのファイル・DB 接続管理が劇的にシンプルになる。
192
+
193
+ **コピペ可能性**: `timer`・`capture_stdout`・`temp_attr` はそのままコピーして使えるユーティリティとして価値がある。
194
+
195
+ **拡張時の罠**: `ManagedBuffer.close_all()` を呼び忘れた場合、バッファはGCまで残る。`__enter__/__exit__` を実装して `with` で使えるようにするほうが安全だが、今回のデモでは意図的に省略した。
196
+
197
+ **事故リスク**: 低
198
+
199
+ ### 3. フロントエンド寄り(React/TS 歴4年・バックエンド転向中・ノンバイナリ)
200
+
201
+ TypeScript の `using` 宣言(TC39 Explicit Resource Management)と概念が近いことを理解すれば、Python の `with` 文の位置付けが掴みやすい。
202
+
203
+ **エラーレスポンスの質**: `/transaction` エンドポイントがロールバックした場合でも HTTP 200 を返し、`rolled_back: true` + `error` フィールドでエラーを示す設計はフロントエンドから見て扱いやすい。
204
+
205
+ **Python 固有概念の学習コスト**: `Generator[dict[str, float], None, None]` という型注釈は TS 経験者には冗長に見える。`@contextmanager` が `Generator` を返す理由を理解するには Python のジェネレーター仕組みへの理解が必要。
206
+
207
+ **事故リスク**: 低
208
+
209
+ ### 4. バックエンド経験者(Django/FastAPI 歴5-6年・男性・リードエンジニア)
210
+
211
+ Django の `transaction.atomic()` や Flask の `g` オブジェクトと比べると、`contextlib` のアプローチはより明示的で汎用的。特に `ExitStack` は Django ORM の接続管理でも応用できる。
212
+
213
+ **他フレームワークとの差異**: `fake_transaction` パターンは Django の `TestCase.databases` によるロールバックと異なり、テスト外のユースケースにも適用できる。
214
+
215
+ **nene2 の薄さへの評価**: `contextlib` 自体は標準ライブラリであり nene2 フレームワークとの結合はない。エンドポイントの薄さ(parse → use-case → response の3ステップ)が維持されており好印象。
216
+
217
+ **事故リスク**: 低
218
+
219
+ ### 5. シニアエンジニア(設計・コードレビュー担当・女性・10-12年)
220
+
221
+ コードレビュー観点で最も重要なのは「suppress の対象を絞ること」。`suppress(Exception)` のように広すぎる例外クラスを指定するコードは必ずレビューで差し戻す。
222
+
223
+ **コードレビューチェックポイント**:
224
+ - `suppress` の引数は具体的な例外クラスか(`Exception` や `BaseException` でないか)
225
+ - `@contextmanager` の `try/finally` が欠落していないか(欠落するとクリーンアップが実行されない)
226
+ - `ExitStack` は使い終わったら必ず `close()` または `with` で囲まれているか
227
+ - `__exit__` の戻り値型が `Literal[False]` か `None` になっているか(mypy で強制されるが目視でも確認)
228
+
229
+ **チームでの安全なパターン**: `LoggingContext(ContextDecorator)` のパターンは横断的関心事(ログ・計測・トレーシング)に応用しやすく、チームで共有できるユーティリティになる。
230
+
231
+ **事故リスク**: 低
232
+
233
+ ### 6. 設計者(nene2-python 設計ポリシー目線)
234
+
235
+ **CLAUDE.md ポリシー整合性**:
236
+ - `dataclass(frozen=True, slots=True)`: `ResourceHandle`・`TransactionResult`・`PipelineResult` で適用済み ✅
237
+ - Pydantic は HTTP 境界のみ: `app.py` の Request/Response モデルのみで使用 ✅
238
+ - `create_app()` はファイル末尾: 全エンドポイント定義後に配置 ✅(FT182 の教訓適用)
239
+ - `max_length` 指定: 全文字列フィールドに設定済み ✅
240
+ - `Literal[False]` 戻り値型: F-1 で修正済み ✅
241
+
242
+ **初心者でも安全な API 達成度**: `suppress` を使う際に抑制対象の例外を明示するパターンを見せることで、「なんでも suppress しない」という習慣を自然に身につけられる構成になっている。`ExitStack` の `callback` で lambda を避けて名前付き関数 `_noop` を使ったことで、mypy の型推論問題も回避できた。
243
+
244
+ ---
245
+
246
+ *バージョン: v1.8.56*
@@ -218,6 +218,7 @@
218
218
  | [FT182](2026-05-field-trial-182.md) | email モジュール — MIME 構築・RFC 2047・パース・アドレス操作 | | |
219
219
  | [FT183](2026-05-field-trial-183.md) | smtplib モジュール — SMTP 送信・STARTTLS・ヘッダーインジェクション防御 | 🔒 | [#513](https://github.com/hideyukiMORI/nene2-python/issues/513) [#514](https://github.com/hideyukiMORI/nene2-python/issues/514) |
220
220
  | [FT184](2026-05-field-trial-184.md) | urllib.request モジュール — URL フェッチ・Basic 認証・SSRF 防御 | 🔍 | [#516](https://github.com/hideyukiMORI/nene2-python/issues/516) [#517](https://github.com/hideyukiMORI/nene2-python/issues/517) |
221
+ | [FT185](2026-05-field-trial-185.md) | contextlib モジュール — コンテキストマネージャー・リソース管理・エラー抑制 | | |
221
222
 
222
223
  ---
223
224
 
@@ -233,4 +234,4 @@ FT172, FT176, FT180, FT184
233
234
 
234
235
  ---
235
236
 
236
- *最終更新: 2026-05-21 (FT184 / v1.8.55)*
237
+ *最終更新: 2026-05-21 (FT185 / v1.8.56)*
@@ -1,14 +1,14 @@
1
1
  # TODO — current
2
2
 
3
3
  最終更新: 2026-05-21
4
- 現状: **v1.8.55 安定版 / フィールドトライアルループ継続中(FT184 完了)**
4
+ 現状: **v1.8.56 安定版 / フィールドトライアルループ継続中(FT185 完了)**
5
5
 
6
6
  ---
7
7
 
8
8
  ## 状態サマリー
9
9
 
10
- v1.8.55 完了済み。FT184urllib.request / URL フェッチ・Basic 認証・SSRF 防御)を含む FT184 件を実施済み。
11
- フィールドトライアルループは FT185 以降も継続中。
10
+ v1.8.56 完了済み。FT185contextlib / コンテキストマネージャー・リソース管理・エラー抑制)を含む FT185 件を実施済み。
11
+ フィールドトライアルループは FT186 以降も継続中。
12
12
 
13
13
  ---
14
14
 
@@ -40,6 +40,7 @@ v1.8.55 完了済み。FT184(urllib.request / URL フェッチ・Basic 認証
40
40
 
41
41
  | バージョン | 主な内容 |
42
42
  |---|---|
43
+ | v1.8.56 | FT185: contextlib — コンテキストマネージャー・リソース管理・エラー抑制 |
43
44
  | v1.8.55 | FT184: urllib.request — URL フェッチ・Basic 認証・SSRF 防御(クラッカーペンテスト実施) |
44
45
  | v1.8.54 | FT183: smtplib — SMTP 送信・STARTTLS・ヘッダーインジェクション防御(診断実施) |
45
46
  | v1.8.53 | FT182: email — MIME 構築・RFC 2047・パース・アドレス操作 |
@@ -58,12 +59,12 @@ v1.8.55 完了済み。FT184(urllib.request / URL フェッチ・Basic 認証
58
59
 
59
60
  ## フィールドトライアル進捗
60
61
 
61
- **実施済み**: FT1〜FT184(全 184 件)
62
+ **実施済み**: FT1〜FT185(全 185 件)
62
63
 
63
64
  索引: [`docs/field-trials/INDEX.md`](../field-trials/INDEX.md)
64
65
 
65
66
  **次のアクション**:
66
- - FT184 以降を継続(FT185185 % 4 = 1 → ペンテストなし、185 % 3 = 2診断なし)
67
+ - FT185 以降を継続(FT186186 % 4 = 2 → ペンテストなし、186 % 3 = 0セキュリティ診断あり)
67
68
 
68
69
  ---
69
70
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nene2-python"
3
- version = "1.8.55"
3
+ version = "1.8.56"
4
4
  description = "NENE2 Python — minimal API framework following NENE2's design philosophy"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes