deepdoc 0.6.0__tar.gz → 0.6.2__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 (238) hide show
  1. {deepdoc-0.6.0 → deepdoc-0.6.2}/PKG-INFO +21 -2
  2. {deepdoc-0.6.0 → deepdoc-0.6.2}/README.md +20 -1
  3. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/__init__.py +1 -1
  4. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/config.py +1 -1
  5. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/generator/generation.py +6 -4
  6. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/llm/client.py +11 -5
  7. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/openapi.py +43 -32
  8. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc.egg-info/PKG-INFO +21 -2
  9. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc.egg-info/SOURCES.txt +1 -0
  10. {deepdoc-0.6.0 → deepdoc-0.6.2}/pyproject.toml +1 -1
  11. deepdoc-0.6.2/tests/test_openapi_null_values.py +62 -0
  12. {deepdoc-0.6.0 → deepdoc-0.6.2}/LICENSE +0 -0
  13. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/__main__.py +0 -0
  14. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/benchmark_v2.py +0 -0
  15. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/__init__.py +0 -0
  16. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/extractor.py +0 -0
  17. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/go_extractor.py +0 -0
  18. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/graph_builder.py +0 -0
  19. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/java_extractor.py +0 -0
  20. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/js_ts_extractor.py +0 -0
  21. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/php_extractor.py +0 -0
  22. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/call_graph/python_extractor.py +0 -0
  23. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/changelog_writer.py +0 -0
  24. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/__init__.py +0 -0
  25. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/answer_mixin.py +0 -0
  26. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/chunker.py +0 -0
  27. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/constants.py +0 -0
  28. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/deep_research.py +0 -0
  29. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/docs_summary.py +0 -0
  30. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/embedding_capabilities.py +0 -0
  31. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/embeddings.py +0 -0
  32. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/indexer.py +0 -0
  33. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/linking.py +0 -0
  34. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/live_fallback_mixin.py +0 -0
  35. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/persistence.py +0 -0
  36. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/providers.py +0 -0
  37. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/retrieval_mixin.py +0 -0
  38. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/routes.py +0 -0
  39. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/scaffold.py +0 -0
  40. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/service.py +0 -0
  41. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/settings.py +0 -0
  42. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/source_archive.py +0 -0
  43. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/symbol_index.py +0 -0
  44. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/chatbot/types.py +0 -0
  45. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/cli.py +0 -0
  46. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/content_store.py +0 -0
  47. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/docs_system.py +0 -0
  48. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/generator/__init__.py +0 -0
  49. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/generator/claims.py +0 -0
  50. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/generator/consistency.py +0 -0
  51. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/generator/evidence.py +0 -0
  52. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/generator/post_processors.py +0 -0
  53. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/generator/validation.py +0 -0
  54. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/language_support.py +0 -0
  55. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/llm/__init__.py +0 -0
  56. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/llm/json_utils.py +0 -0
  57. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/llm/litellm_compat.py +0 -0
  58. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/llm/rate_limit.py +0 -0
  59. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/llm/retry.py +0 -0
  60. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/llm/token_budget.py +0 -0
  61. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/manifest.py +0 -0
  62. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/output_safety.py +0 -0
  63. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/__init__.py +0 -0
  64. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/api_detector.py +0 -0
  65. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/base.py +0 -0
  66. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/go_parser.py +0 -0
  67. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/java_parser.py +0 -0
  68. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/js_ts_parser.py +0 -0
  69. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/php_parser.py +0 -0
  70. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/python_parser.py +0 -0
  71. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/registry.py +0 -0
  72. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/__init__.py +0 -0
  73. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/base.py +0 -0
  74. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/common.py +0 -0
  75. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/detector.py +0 -0
  76. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/django.py +0 -0
  77. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/express.py +0 -0
  78. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/falcon.py +0 -0
  79. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/fastapi.py +0 -0
  80. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/fastify.py +0 -0
  81. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/go.py +0 -0
  82. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/js_shared.py +0 -0
  83. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/laravel.py +0 -0
  84. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/nestjs.py +0 -0
  85. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/python_shared.py +0 -0
  86. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/registry.py +0 -0
  87. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/routes/repo_resolver.py +0 -0
  88. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/rust_parser.py +0 -0
  89. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/parser/vue_parser.py +0 -0
  90. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/persistence_v2.py +0 -0
  91. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/persistent_index.py +0 -0
  92. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/pipeline_v2.py +0 -0
  93. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/plan_contract.py +0 -0
  94. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/__init__.py +0 -0
  95. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/bucket_injection.py +0 -0
  96. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/bucket_refinement.py +0 -0
  97. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/common.py +0 -0
  98. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/endpoint_refs.py +0 -0
  99. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/engine.py +0 -0
  100. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/flow_candidates.py +0 -0
  101. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/heuristics.py +0 -0
  102. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/merge.py +0 -0
  103. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/nav_shaping.py +0 -0
  104. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/partitioning.py +0 -0
  105. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/specializations.py +0 -0
  106. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/topology.py +0 -0
  107. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/unit_boundaries.py +0 -0
  108. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/planner/utils.py +0 -0
  109. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/prompts/__init__.py +0 -0
  110. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/prompts/bucket_types.py +0 -0
  111. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/prompts/page_types.py +0 -0
  112. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/prompts/selectors.py +0 -0
  113. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/prompts/system.py +0 -0
  114. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/prompts/update.py +0 -0
  115. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/py.typed +0 -0
  116. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/repo_model.py +0 -0
  117. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scale_utils.py +0 -0
  118. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/__init__.py +0 -0
  119. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/artifacts.py +0 -0
  120. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/clustering.py +0 -0
  121. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/common.py +0 -0
  122. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/database.py +0 -0
  123. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/endpoints.py +0 -0
  124. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/integrations.py +0 -0
  125. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/runtime.py +0 -0
  126. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/scanner/utils.py +0 -0
  127. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/__init__.py +0 -0
  128. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/__init__.py +0 -0
  129. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/common.py +0 -0
  130. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/mdx_utils.py +0 -0
  131. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_builder.py +0 -0
  132. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/.gitignore +0 -0
  133. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/(main)/[[...slug]]/page.tsx +0 -0
  134. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/(main)/layout.tsx +0 -0
  135. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/api/search/route.ts +0 -0
  136. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/ask/layout.tsx +0 -0
  137. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/ask/page.tsx +0 -0
  138. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/components/mermaid-runner.tsx +0 -0
  139. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/globals.css +0 -0
  140. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/app/layout.tsx +0 -0
  141. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/components/chatbot.tsx +0 -0
  142. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/deepdoc.config.json +0 -0
  143. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/lib/config.ts +0 -0
  144. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/lib/docs.ts +0 -0
  145. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/lib/nav.ts +0 -0
  146. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/next.config.mjs +0 -0
  147. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/package.json +0 -0
  148. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/postcss.config.mjs +0 -0
  149. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/next_template/tsconfig.json +0 -0
  150. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/presets.py +0 -0
  151. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/vendor/highlight.min.js +0 -0
  152. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/vendor/hljs-theme.css +0 -0
  153. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/site/builder/vendor/markdown-it.min.js +0 -0
  154. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/smart_update_v2.py +0 -0
  155. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/source_metadata.py +0 -0
  156. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/telemetry.py +0 -0
  157. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/updater_v2.py +0 -0
  158. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc/v2_models.py +0 -0
  159. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc.egg-info/dependency_links.txt +0 -0
  160. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc.egg-info/entry_points.txt +0 -0
  161. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc.egg-info/requires.txt +0 -0
  162. {deepdoc-0.6.0 → deepdoc-0.6.2}/deepdoc.egg-info/top_level.txt +0 -0
  163. {deepdoc-0.6.0 → deepdoc-0.6.2}/setup.cfg +0 -0
  164. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_benchmark_scorecard.py +0 -0
  165. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_call_graph.py +0 -0
  166. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_changelog.py +0 -0
  167. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_config.py +0 -0
  168. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_embeddings.py +0 -0
  169. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_eval.py +0 -0
  170. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_index.py +0 -0
  171. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_persistence.py +0 -0
  172. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_providers.py +0 -0
  173. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_query.py +0 -0
  174. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_relationship.py +0 -0
  175. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_scaffold.py +0 -0
  176. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_chatbot_source_archive.py +0 -0
  177. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_citations.py +0 -0
  178. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_claim_validation.py +0 -0
  179. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_classify.py +0 -0
  180. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_cli_generate.py +0 -0
  181. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_cli_serve.py +0 -0
  182. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_cli_update.py +0 -0
  183. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_config_defaults.py +0 -0
  184. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_consistency_pass.py +0 -0
  185. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_coverage_report.py +0 -0
  186. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_docs_system.py +0 -0
  187. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_embedding_capabilities.py +0 -0
  188. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_empty_repo_guard.py +0 -0
  189. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_endpoint_priority_dedupe.py +0 -0
  190. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_fastapi_phantom_endpoints.py +0 -0
  191. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_fastapi_product_gate.py +0 -0
  192. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_flow_candidates.py +0 -0
  193. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_framework_fixtures.py +0 -0
  194. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_framework_support.py +0 -0
  195. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_generation_evidence.py +0 -0
  196. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_hosted_upload.py +0 -0
  197. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_internal_docs_metadata.py +0 -0
  198. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_language_support.py +0 -0
  199. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_litellm_compat.py +0 -0
  200. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_llm_json_utils.py +0 -0
  201. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_llm_retry.py +0 -0
  202. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_manifest_performance.py +0 -0
  203. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_nav_shaping.py +0 -0
  204. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_next_builder.py +0 -0
  205. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_output_safety.py +0 -0
  206. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_parallel_pipeline.py +0 -0
  207. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_parallel_scan.py +0 -0
  208. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_parser_ranges.py +0 -0
  209. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_persistent_index.py +0 -0
  210. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_phase1_perf.py +0 -0
  211. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_plan_contract.py +0 -0
  212. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_planner_assignment_partition.py +0 -0
  213. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_planner_consolidation.py +0 -0
  214. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_planner_granularity.py +0 -0
  215. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_planner_merge.py +0 -0
  216. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_planner_partitioning.py +0 -0
  217. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_planner_unit_boundaries.py +0 -0
  218. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_planner_unit_orchestration.py +0 -0
  219. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_rate_limit.py +0 -0
  220. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_repo_model.py +0 -0
  221. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_route_composition.py +0 -0
  222. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_route_registry.py +0 -0
  223. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_runtime_evidence_regressions.py +0 -0
  224. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_runtime_scan.py +0 -0
  225. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_scale.py +0 -0
  226. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_scan_guards.py +0 -0
  227. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_scan_telemetry.py +0 -0
  228. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_scanner_llm_bounds.py +0 -0
  229. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_serve_resync.py +0 -0
  230. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_site_config_schema.py +0 -0
  231. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_slug_dedup.py +0 -0
  232. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_smart_update.py +0 -0
  233. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_stale.py +0 -0
  234. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_state.py +0 -0
  235. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_telemetry.py +0 -0
  236. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_token_budget.py +0 -0
  237. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_unknown_language_coverage.py +0 -0
  238. {deepdoc-0.6.0 → deepdoc-0.6.2}/tests/test_word_count.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepdoc
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Auto-generate beautiful docs from any codebase
5
5
  Author: Pranav Kumar
6
6
  License: MIT
@@ -420,6 +420,7 @@ Generated Markdown pages include provenance frontmatter such as `deepdoc_generat
420
420
  | `--since` | last synced commit | Git ref to diff against |
421
421
  | `--replan` | off | Force a full replan even if the change set looks incremental |
422
422
  | `--deploy` | off | Deploy after a fully successful update |
423
+ | `--strict-quality` | off | Exit non-zero when any page fails validation — use this in CI |
423
424
 
424
425
  ### `deepdoc status`
425
426
 
@@ -484,6 +485,24 @@ deepdoc config set llm.api_key_env AZURE_API_KEY # Change API key env var
484
485
  deepdoc config set compatibility.deprecated_version_warning.enabled false
485
486
  ```
486
487
 
488
+ ### `deepdoc clean`
489
+
490
+ Reset the repository to a pre-DeepDoc state. Removes `.deepdoc.yaml`, the
491
+ DeepDoc-owned docs and site output, and saved state under `.deepdoc/`.
492
+
493
+ ```bash
494
+ deepdoc clean # prompts before deleting
495
+ deepdoc clean --yes # no prompt, for scripts
496
+ ```
497
+
498
+ Only files DeepDoc created are removed — deletion is tracked against its own
499
+ manifest, so hand-written pages you added to the output directory survive.
500
+ `chatbot_backend/` is preserved as well, since it may contain your changes.
501
+
502
+ | Flag | Default | Description |
503
+ |------|---------|-------------|
504
+ | `--yes` | off | Skip the confirmation prompt |
505
+
487
506
  ### `deepdoc benchmark`
488
507
 
489
508
  Run planner benchmark cases and optionally generate a combined docs+chatbot quality scorecard.
@@ -493,7 +512,7 @@ deepdoc benchmark --catalog benchmarks/catalog.json
493
512
  deepdoc benchmark --repo /path/to/repo --gold benchmarks/gold.json
494
513
  deepdoc benchmark --catalog benchmarks/catalog.json --chatbot-eval benchmarks/chatbot_eval.json
495
514
  deepdoc benchmark --catalog benchmarks/catalog.json --chatbot-eval benchmarks/chatbot_eval.json --scorecard-out .deepdoc/quality_scorecard.json --strict-scorecard
496
- deepdoc benchmark --generated-root /Users/apple/autodoc/docs --scorecard-out /Users/apple/autodoc/docs/_scorecards/latest.json
515
+ deepdoc benchmark --generated-root ./deepdoc-docs --scorecard-out .deepdoc/scorecards/latest.json
497
516
  ```
498
517
 
499
518
  Use `--strict-scorecard` to fail the command when completeness gates are not met.
@@ -379,6 +379,7 @@ Generated Markdown pages include provenance frontmatter such as `deepdoc_generat
379
379
  | `--since` | last synced commit | Git ref to diff against |
380
380
  | `--replan` | off | Force a full replan even if the change set looks incremental |
381
381
  | `--deploy` | off | Deploy after a fully successful update |
382
+ | `--strict-quality` | off | Exit non-zero when any page fails validation — use this in CI |
382
383
 
383
384
  ### `deepdoc status`
384
385
 
@@ -443,6 +444,24 @@ deepdoc config set llm.api_key_env AZURE_API_KEY # Change API key env var
443
444
  deepdoc config set compatibility.deprecated_version_warning.enabled false
444
445
  ```
445
446
 
447
+ ### `deepdoc clean`
448
+
449
+ Reset the repository to a pre-DeepDoc state. Removes `.deepdoc.yaml`, the
450
+ DeepDoc-owned docs and site output, and saved state under `.deepdoc/`.
451
+
452
+ ```bash
453
+ deepdoc clean # prompts before deleting
454
+ deepdoc clean --yes # no prompt, for scripts
455
+ ```
456
+
457
+ Only files DeepDoc created are removed — deletion is tracked against its own
458
+ manifest, so hand-written pages you added to the output directory survive.
459
+ `chatbot_backend/` is preserved as well, since it may contain your changes.
460
+
461
+ | Flag | Default | Description |
462
+ |------|---------|-------------|
463
+ | `--yes` | off | Skip the confirmation prompt |
464
+
446
465
  ### `deepdoc benchmark`
447
466
 
448
467
  Run planner benchmark cases and optionally generate a combined docs+chatbot quality scorecard.
@@ -452,7 +471,7 @@ deepdoc benchmark --catalog benchmarks/catalog.json
452
471
  deepdoc benchmark --repo /path/to/repo --gold benchmarks/gold.json
453
472
  deepdoc benchmark --catalog benchmarks/catalog.json --chatbot-eval benchmarks/chatbot_eval.json
454
473
  deepdoc benchmark --catalog benchmarks/catalog.json --chatbot-eval benchmarks/chatbot_eval.json --scorecard-out .deepdoc/quality_scorecard.json --strict-scorecard
455
- deepdoc benchmark --generated-root /Users/apple/autodoc/docs --scorecard-out /Users/apple/autodoc/docs/_scorecards/latest.json
474
+ deepdoc benchmark --generated-root ./deepdoc-docs --scorecard-out .deepdoc/scorecards/latest.json
456
475
  ```
457
476
 
458
477
  Use `--strict-scorecard` to fail the command when completeness gates are not met.
@@ -1,3 +1,3 @@
1
1
  """DeepDoc — Auto-generate beautiful docs from any codebase."""
2
2
 
3
- __version__ = "0.6.0"
3
+ __version__ = "0.6.2"
@@ -196,7 +196,7 @@ DEFAULT_CONFIG: dict[str, Any] = {
196
196
  },
197
197
  "theme": {
198
198
  # One of the built-in palettes, or "" for DeepDoc's own.
199
- # neutral | black | vitepress | ocean | catppuccin | dusk | purple | solar | shadcn
199
+ # neutral | black | vitepress | ocean | catppuccin | dusk | purple
200
200
  "preset": "",
201
201
  # Raw Fumadocs design-token overrides — the final word, and the
202
202
  # escape hatch for anything the named keys above don't cover.
@@ -473,10 +473,12 @@ class BucketGenerationEngine:
473
473
  for spec_path in self.scan.openapi_paths:
474
474
  spec = parse_openapi_spec(self.repo_root / spec_path)
475
475
  if spec:
476
- chunk = (
477
- f"\n## OpenAPI Spec ({spec_path}):\n"
478
- f"{spec_to_context_string(spec)[:per_spec_limit]}"
479
- )
476
+ # Supplemental context only: a malformed spec must not abort the run.
477
+ try:
478
+ rendered = spec_to_context_string(spec)[:per_spec_limit]
479
+ except Exception:
480
+ continue
481
+ chunk = f"\n## OpenAPI Spec ({spec_path}):\n{rendered}"
480
482
  parts.append(chunk)
481
483
  total += len(chunk)
482
484
  if total >= 6000:
@@ -202,11 +202,13 @@ class LLMClient:
202
202
  self._raise_if_truncated(response)
203
203
  return response.choices[0].message.content or ""
204
204
 
205
- except ImportError:
205
+ except ImportError as e:
206
206
  error_type = "ImportError"
207
207
  raise RuntimeError(
208
- "litellm not installed. Run: pip install litellm"
209
- )
208
+ f"litellm import failed ({e}). If `pip show litellm` finds it, "
209
+ "this is a broken dependency in litellm's import chain, not a "
210
+ "missing package — reinstalling litellm alone won't fix it."
211
+ ) from e
210
212
  except LLMOutputTruncatedError:
211
213
  error_type = "LLMOutputTruncatedError"
212
214
  raise
@@ -261,9 +263,13 @@ class LLMClient:
261
263
  yield delta.content
262
264
  self._raise_if_truncated(final_chunk)
263
265
 
264
- except ImportError:
266
+ except ImportError as e:
265
267
  error_type = "ImportError"
266
- raise RuntimeError("litellm not installed. Run: pip install litellm")
268
+ raise RuntimeError(
269
+ f"litellm import failed ({e}). If `pip show litellm` finds it, "
270
+ "this is a broken dependency in litellm's import chain, not a "
271
+ "missing package — reinstalling litellm alone won't fix it."
272
+ ) from e
267
273
  except LLMOutputTruncatedError:
268
274
  error_type = "LLMOutputTruncatedError"
269
275
  raise
@@ -12,6 +12,16 @@ from typing import Any
12
12
  from urllib.parse import urlparse
13
13
 
14
14
 
15
+ def _d(value: Any) -> dict:
16
+ """Coerce to a dict. YAML ``key:`` with no value parses to None, and
17
+ ``.get(key, default)`` returns that None instead of the default."""
18
+ return value if isinstance(value, dict) else {}
19
+
20
+
21
+ def _l(value: Any) -> list:
22
+ return value if isinstance(value, list) else []
23
+
24
+
15
25
  def find_openapi_specs(repo_root: Path) -> list[Path]:
16
26
  """Find all OpenAPI/Swagger spec files in the repo."""
17
27
  candidates = [
@@ -35,16 +45,17 @@ def parse_openapi_spec(spec_path: Path) -> dict[str, Any] | None:
35
45
  try:
36
46
  content = spec_path.read_text(encoding="utf-8")
37
47
  if spec_path.suffix == ".json":
38
- return json.loads(content)
48
+ parsed = json.loads(content)
39
49
  else:
40
50
  try:
41
51
  import yaml
42
- return yaml.safe_load(content)
52
+ parsed = yaml.safe_load(content)
43
53
  except ImportError:
44
54
  # Try JSON anyway
45
- return json.loads(content)
55
+ parsed = json.loads(content)
46
56
  except Exception:
47
57
  return None
58
+ return parsed if isinstance(parsed, dict) else None
48
59
 
49
60
 
50
61
  def extract_endpoints_from_spec(spec: dict[str, Any]) -> list[dict[str, Any]]:
@@ -55,9 +66,9 @@ def extract_endpoints_from_spec(spec: dict[str, Any]) -> list[dict[str, Any]]:
55
66
 
56
67
  # OpenAPI 3.x
57
68
  if "openapi" in spec:
58
- servers = spec.get("servers", [])
69
+ servers = _l(spec.get("servers"))
59
70
  if servers:
60
- server_url = str(servers[0].get("url", "") or "").strip()
71
+ server_url = str(_d(servers[0]).get("url", "") or "").strip()
61
72
  if server_url:
62
73
  parsed = urlparse(server_url)
63
74
  if parsed.scheme or parsed.netloc:
@@ -67,26 +78,27 @@ def extract_endpoints_from_spec(spec: dict[str, Any]) -> list[dict[str, Any]]:
67
78
 
68
79
  # Swagger 2.x
69
80
  elif "swagger" in spec:
70
- base_path = spec.get("basePath", "")
81
+ base_path = str(spec.get("basePath") or "")
71
82
 
72
- paths = spec.get("paths", {})
73
- for path, methods in paths.items():
83
+ for path, methods in _d(spec.get("paths")).items():
84
+ path = str(path)
74
85
  full_path = base_path + path if not path.startswith("http") else path
75
86
 
76
- for method, details in methods.items():
77
- if method.lower() in ("get", "post", "put", "patch", "delete", "head", "options"):
87
+ for method, details in _d(methods).items():
88
+ details = _d(details)
89
+ if str(method).lower() in ("get", "post", "put", "patch", "delete", "head", "options"):
78
90
  endpoint = {
79
91
  "method": method.upper(),
80
92
  "path": full_path,
81
- "summary": details.get("summary", ""),
82
- "description": details.get("description", ""),
83
- "operation_id": details.get("operationId", ""),
84
- "tags": details.get("tags", []),
93
+ "summary": str(details.get("summary") or ""),
94
+ "description": str(details.get("description") or ""),
95
+ "operation_id": str(details.get("operationId") or ""),
96
+ "tags": _l(details.get("tags")),
85
97
  "parameters": _extract_parameters(details, spec),
86
98
  "request_body": _extract_request_body(details, spec),
87
99
  "responses": _extract_responses(details, spec),
88
- "security": details.get("security", spec.get("security", [])),
89
- "deprecated": details.get("deprecated", False),
100
+ "security": _l(details.get("security", spec.get("security"))),
101
+ "deprecated": bool(details.get("deprecated", False)),
90
102
  }
91
103
  endpoints.append(endpoint)
92
104
 
@@ -96,10 +108,10 @@ def extract_endpoints_from_spec(spec: dict[str, Any]) -> list[dict[str, Any]]:
96
108
  def spec_to_context_string(spec: dict[str, Any]) -> str:
97
109
  """Convert an OpenAPI spec into a compact string for LLM context."""
98
110
  lines = []
99
- info = spec.get("info", {})
100
- lines.append(f"API: {info.get('title', 'Unknown')} v{info.get('version', '?')}")
111
+ info = _d(spec.get("info"))
112
+ lines.append(f"API: {info.get('title') or 'Unknown'} v{info.get('version') or '?'}")
101
113
  if info.get("description"):
102
- lines.append(f"Description: {info['description'][:200]}")
114
+ lines.append(f"Description: {str(info['description'])[:200]}")
103
115
 
104
116
  endpoints = extract_endpoints_from_spec(spec)
105
117
  lines.append(f"\nEndpoints ({len(endpoints)}):")
@@ -131,8 +143,8 @@ def spec_to_context_string(spec: dict[str, Any]) -> str:
131
143
 
132
144
  def _extract_parameters(details: dict, spec: dict) -> list[dict]:
133
145
  params = []
134
- for p in details.get("parameters", []):
135
- p = _resolve_ref(p, spec)
146
+ for p in _l(details.get("parameters")):
147
+ p = _d(_resolve_ref(p, spec))
136
148
  params.append({
137
149
  "name": p.get("name", "?"),
138
150
  "in": p.get("in", "?"),
@@ -144,26 +156,25 @@ def _extract_parameters(details: dict, spec: dict) -> list[dict]:
144
156
 
145
157
 
146
158
  def _extract_request_body(details: dict, spec: dict) -> str:
147
- rb = details.get("requestBody", {})
159
+ rb = details.get("requestBody")
148
160
  if not rb:
149
161
  return ""
150
- rb = _resolve_ref(rb, spec)
151
- content = rb.get("content", {})
152
- for _media_type, schema_info in content.items():
153
- schema = _resolve_ref(schema_info.get("schema", {}), spec)
162
+ rb = _d(_resolve_ref(rb, spec))
163
+ for _media_type, schema_info in _d(rb.get("content")).items():
164
+ schema = _resolve_ref(_d(schema_info).get("schema", {}), spec)
154
165
  return json.dumps(schema, indent=2)[:500]
155
166
  return ""
156
167
 
157
168
 
158
169
  def _extract_responses(details: dict, spec: dict) -> dict[str, str]:
159
170
  responses = {}
160
- for status, resp in details.get("responses", {}).items():
161
- resp = _resolve_ref(resp, spec)
162
- desc = resp.get("description", "")
163
- content = resp.get("content", {})
171
+ for status, resp in _d(details.get("responses")).items():
172
+ resp = _d(_resolve_ref(resp, spec))
173
+ desc = str(resp.get("description") or "")
174
+ content = _d(resp.get("content"))
164
175
  if content:
165
176
  for _media_type, schema_info in content.items():
166
- schema = _resolve_ref(schema_info.get("schema", {}), spec)
177
+ schema = _resolve_ref(_d(schema_info).get("schema", {}), spec)
167
178
  desc += f" | schema: {json.dumps(schema)[:200]}"
168
179
  break
169
180
  responses[str(status)] = desc[:300]
@@ -180,7 +191,7 @@ def _resolve_ref(obj: dict, spec: dict) -> dict:
180
191
  parts = ref.lstrip("#/").split("/")
181
192
  resolved = spec
182
193
  for part in parts:
183
- resolved = resolved.get(part, {})
194
+ resolved = _d(resolved).get(part, {})
184
195
  return resolved if isinstance(resolved, dict) else obj
185
196
 
186
197
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepdoc
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Auto-generate beautiful docs from any codebase
5
5
  Author: Pranav Kumar
6
6
  License: MIT
@@ -420,6 +420,7 @@ Generated Markdown pages include provenance frontmatter such as `deepdoc_generat
420
420
  | `--since` | last synced commit | Git ref to diff against |
421
421
  | `--replan` | off | Force a full replan even if the change set looks incremental |
422
422
  | `--deploy` | off | Deploy after a fully successful update |
423
+ | `--strict-quality` | off | Exit non-zero when any page fails validation — use this in CI |
423
424
 
424
425
  ### `deepdoc status`
425
426
 
@@ -484,6 +485,24 @@ deepdoc config set llm.api_key_env AZURE_API_KEY # Change API key env var
484
485
  deepdoc config set compatibility.deprecated_version_warning.enabled false
485
486
  ```
486
487
 
488
+ ### `deepdoc clean`
489
+
490
+ Reset the repository to a pre-DeepDoc state. Removes `.deepdoc.yaml`, the
491
+ DeepDoc-owned docs and site output, and saved state under `.deepdoc/`.
492
+
493
+ ```bash
494
+ deepdoc clean # prompts before deleting
495
+ deepdoc clean --yes # no prompt, for scripts
496
+ ```
497
+
498
+ Only files DeepDoc created are removed — deletion is tracked against its own
499
+ manifest, so hand-written pages you added to the output directory survive.
500
+ `chatbot_backend/` is preserved as well, since it may contain your changes.
501
+
502
+ | Flag | Default | Description |
503
+ |------|---------|-------------|
504
+ | `--yes` | off | Skip the confirmation prompt |
505
+
487
506
  ### `deepdoc benchmark`
488
507
 
489
508
  Run planner benchmark cases and optionally generate a combined docs+chatbot quality scorecard.
@@ -493,7 +512,7 @@ deepdoc benchmark --catalog benchmarks/catalog.json
493
512
  deepdoc benchmark --repo /path/to/repo --gold benchmarks/gold.json
494
513
  deepdoc benchmark --catalog benchmarks/catalog.json --chatbot-eval benchmarks/chatbot_eval.json
495
514
  deepdoc benchmark --catalog benchmarks/catalog.json --chatbot-eval benchmarks/chatbot_eval.json --scorecard-out .deepdoc/quality_scorecard.json --strict-scorecard
496
- deepdoc benchmark --generated-root /Users/apple/autodoc/docs --scorecard-out /Users/apple/autodoc/docs/_scorecards/latest.json
515
+ deepdoc benchmark --generated-root ./deepdoc-docs --scorecard-out .deepdoc/scorecards/latest.json
497
516
  ```
498
517
 
499
518
  Use `--strict-scorecard` to fail the command when completeness gates are not met.
@@ -199,6 +199,7 @@ tests/test_llm_retry.py
199
199
  tests/test_manifest_performance.py
200
200
  tests/test_nav_shaping.py
201
201
  tests/test_next_builder.py
202
+ tests/test_openapi_null_values.py
202
203
  tests/test_output_safety.py
203
204
  tests/test_parallel_pipeline.py
204
205
  tests/test_parallel_scan.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deepdoc"
7
- version = "0.6.0"
7
+ version = "0.6.2"
8
8
  description = "Auto-generate beautiful docs from any codebase"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -0,0 +1,62 @@
1
+ """Specs with empty YAML values (``info:`` with nothing under it) parse to None.
2
+
3
+ ``dict.get(key, default)`` returns that None, so a sloppy-but-loadable spec used
4
+ to crash ``spec_to_context_string`` and abort the whole generation run.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ from deepdoc.openapi import (
9
+ extract_endpoints_from_spec,
10
+ parse_openapi_spec,
11
+ spec_to_context_string,
12
+ )
13
+
14
+ SLOPPY_YAML = """\
15
+ openapi: 3.0.0
16
+ info:
17
+ servers:
18
+ paths:
19
+ /things:
20
+ get:
21
+ summary:
22
+ tags:
23
+ parameters:
24
+ requestBody:
25
+ responses:
26
+ "200":
27
+ description:
28
+ content:
29
+ post:
30
+ /empty:
31
+ """
32
+
33
+
34
+ def test_null_valued_spec_renders_context(tmp_path):
35
+ path = tmp_path / "openapi.yaml"
36
+ path.write_text(SLOPPY_YAML, encoding="utf-8")
37
+ spec = parse_openapi_spec(path)
38
+ assert spec is not None
39
+
40
+ text = spec_to_context_string(spec)
41
+
42
+ assert "API: Unknown v?" in text
43
+ assert "GET /things" in text
44
+ assert "POST /things" in text
45
+
46
+
47
+ def test_null_valued_spec_extracts_endpoints(tmp_path):
48
+ path = tmp_path / "openapi.yaml"
49
+ path.write_text(SLOPPY_YAML, encoding="utf-8")
50
+ endpoints = extract_endpoints_from_spec(parse_openapi_spec(path))
51
+
52
+ assert {(e["method"], e["path"]) for e in endpoints} == {
53
+ ("GET", "/things"),
54
+ ("POST", "/things"),
55
+ }
56
+ assert all(isinstance(e["tags"], list) for e in endpoints)
57
+
58
+
59
+ def test_non_mapping_spec_is_rejected(tmp_path):
60
+ path = tmp_path / "openapi.yaml"
61
+ path.write_text("- just\n- a list\n", encoding="utf-8")
62
+ assert parse_openapi_spec(path) is None
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes