pyopenapi-gen 0.21.0__tar.gz → 0.21.1__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.

Potentially problematic release.


This version of pyopenapi-gen might be problematic. Click here for more details.

Files changed (342) hide show
  1. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/CHANGELOG.md +42 -0
  2. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/PKG-INFO +1 -1
  3. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/coverage.xml +45 -35
  4. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/pyproject.toml +2 -2
  5. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/__init__.py +1 -1
  6. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/url_args_generator.py +28 -4
  7. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_endpoints_emitter.py +3 -3
  8. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_url_args_generator.py +285 -5
  9. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.bandit +0 -0
  10. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/mcp.json +0 -0
  11. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/architecture.mdc +0 -0
  12. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/coding-conventions.mdc +0 -0
  13. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/project-goal.mdc +0 -0
  14. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/testing.mdc +0 -0
  15. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/BRANCH_PROTECTION.md +0 -0
  16. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/CLAUDE_CONFIGURATION.md +0 -0
  17. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/CODEOWNERS +0 -0
  18. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  19. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  20. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/dependabot.yml +0 -0
  21. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/ci.yml +0 -0
  22. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/claude-auto-approve.yml +0 -0
  23. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/claude-review-trigger.yml +0 -0
  24. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/claude.yml +0 -0
  25. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/pr-checks.yml +0 -0
  26. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/production-release.yml.backup +0 -0
  27. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/promote-to-staging.yml +0 -0
  28. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/semantic-release.yml +0 -0
  29. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/staging-publish.yml +0 -0
  30. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/testpypi-publish.yml +0 -0
  31. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.gitignore +0 -0
  32. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.python-version +0 -0
  33. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.vscode/settings.json +0 -0
  34. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/CLAUDE.md +0 -0
  35. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/CONTRIBUTING.md +0 -0
  36. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/LICENSE +0 -0
  37. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/Makefile +0 -0
  38. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/README.md +0 -0
  39. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/README.md +0 -0
  40. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/architecture.md +0 -0
  41. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/endpoint_visitor.md +0 -0
  42. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/helpers.md +0 -0
  43. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/ir_models.md +0 -0
  44. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/line_writer.md +0 -0
  45. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/loader.md +0 -0
  46. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/model_visitor.md +0 -0
  47. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/release-automation.md +0 -0
  48. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/render_context.md +0 -0
  49. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/unified_type_resolution.md +0 -0
  50. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/business_swagger.json +0 -0
  51. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/minimal_swagger.json +0 -0
  52. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/minimal_syntax_test.json +0 -0
  53. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/test_name_collision_spec.json +0 -0
  54. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/mkdocs.yml +0 -0
  55. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/poetry.lock +0 -0
  56. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/scripts/sync_version_to_init.py +0 -0
  57. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/scripts/validate_version_sync.py +0 -0
  58. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/__main__.py +0 -0
  59. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/cli.py +0 -0
  60. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/CLAUDE.md +0 -0
  61. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/file_manager.py +0 -0
  62. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/import_collector.py +0 -0
  63. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/render_context.py +0 -0
  64. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/CLAUDE.md +0 -0
  65. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/__init__.py +0 -0
  66. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/auth/base.py +0 -0
  67. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/auth/plugins.py +0 -0
  68. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/exceptions.py +0 -0
  69. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/http_status_codes.py +0 -0
  70. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/http_transport.py +0 -0
  71. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/__init__.py +0 -0
  72. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/loader.py +0 -0
  73. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/__init__.py +0 -0
  74. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/parser.py +0 -0
  75. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/post_processor.py +0 -0
  76. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/request_body.py +0 -0
  77. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/parameters/__init__.py +0 -0
  78. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/parameters/parser.py +0 -0
  79. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/responses/__init__.py +0 -0
  80. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/responses/parser.py +0 -0
  81. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/schemas/__init__.py +0 -0
  82. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/schemas/extractor.py +0 -0
  83. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/pagination.py +0 -0
  84. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/__init__.py +0 -0
  85. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/__init__.py +0 -0
  86. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/__init__.py +0 -0
  87. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/__init__.py +0 -0
  88. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/cyclic_properties.py +0 -0
  89. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/direct_cycle.py +0 -0
  90. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/existing_schema.py +0 -0
  91. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/list_response.py +0 -0
  92. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/missing_ref.py +0 -0
  93. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/new_schema.py +0 -0
  94. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/stripped_suffix.py +0 -0
  95. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/resolve_schema_ref.py +0 -0
  96. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/type_parser.py +0 -0
  97. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/context.py +0 -0
  98. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/cycle_helpers.py +0 -0
  99. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/__init__.py +0 -0
  100. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/all_of_parser.py +0 -0
  101. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/any_of_parser.py +0 -0
  102. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/array_items_parser.py +0 -0
  103. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/one_of_parser.py +0 -0
  104. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/properties_parser.py +0 -0
  105. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/schema_finalizer.py +0 -0
  106. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/schema_parser.py +0 -0
  107. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/transformers/__init__.py +0 -0
  108. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/transformers/inline_enum_extractor.py +0 -0
  109. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/transformers/inline_object_promoter.py +0 -0
  110. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/unified_cycle_detection.py +0 -0
  111. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/postprocess_manager.py +0 -0
  112. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/schemas.py +0 -0
  113. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/streaming_helpers.py +0 -0
  114. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/telemetry.py +0 -0
  115. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/utils.py +0 -0
  116. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/warning_collector.py +0 -0
  117. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/code_writer.py +0 -0
  118. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/documentation_writer.py +0 -0
  119. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/line_writer.py +0 -0
  120. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/python_construct_renderer.py +0 -0
  121. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core_package_template/README.md +0 -0
  122. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emit/models_emitter.py +0 -0
  123. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/CLAUDE.md +0 -0
  124. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/client_emitter.py +0 -0
  125. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/core_emitter.py +0 -0
  126. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/docs_emitter.py +0 -0
  127. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/endpoints_emitter.py +0 -0
  128. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/exceptions_emitter.py +0 -0
  129. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/models_emitter.py +0 -0
  130. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/generator/CLAUDE.md +0 -0
  131. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/generator/client_generator.py +0 -0
  132. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/CLAUDE.md +0 -0
  133. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/__init__.py +0 -0
  134. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/endpoint_utils.py +0 -0
  135. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_cleaner.py +0 -0
  136. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_helper.py +0 -0
  137. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/__init__.py +0 -0
  138. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/array_resolver.py +0 -0
  139. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/composition_resolver.py +0 -0
  140. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/finalizer.py +0 -0
  141. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/named_resolver.py +0 -0
  142. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/object_resolver.py +0 -0
  143. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/primitive_resolver.py +0 -0
  144. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/resolver.py +0 -0
  145. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/url_utils.py +0 -0
  146. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/http_types.py +0 -0
  147. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/ir.py +0 -0
  148. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/py.typed +0 -0
  149. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/CLAUDE.md +0 -0
  150. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/__init__.py +0 -0
  151. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/contracts/__init__.py +0 -0
  152. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/contracts/protocols.py +0 -0
  153. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/contracts/types.py +0 -0
  154. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/__init__.py +0 -0
  155. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/reference_resolver.py +0 -0
  156. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/response_resolver.py +0 -0
  157. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/schema_resolver.py +0 -0
  158. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/services/__init__.py +0 -0
  159. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/services/type_service.py +0 -0
  160. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/strategies/__init__.py +0 -0
  161. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/strategies/response_strategy.py +0 -0
  162. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/CLAUDE.md +0 -0
  163. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/client_visitor.py +0 -0
  164. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/docs_visitor.py +0 -0
  165. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/__init__.py +0 -0
  166. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/endpoint_visitor.py +0 -0
  167. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/__init__.py +0 -0
  168. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/docstring_generator.py +0 -0
  169. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py +0 -0
  170. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/overload_generator.py +0 -0
  171. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/request_generator.py +0 -0
  172. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/response_handler_generator.py +0 -0
  173. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/signature_generator.py +0 -0
  174. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/processors/__init__.py +0 -0
  175. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/processors/import_analyzer.py +0 -0
  176. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/processors/parameter_processor.py +0 -0
  177. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/exception_visitor.py +0 -0
  178. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/__init__.py +0 -0
  179. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/alias_generator.py +0 -0
  180. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/dataclass_generator.py +0 -0
  181. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/enum_generator.py +0 -0
  182. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/model_visitor.py +0 -0
  183. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/visitor.py +0 -0
  184. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/__init__.py +0 -0
  185. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/api/test_programmatic_api.py +0 -0
  186. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/auth/auth_analysis.md +0 -0
  187. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/auth/test_auth_base.py +0 -0
  188. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/auth/test_auth_plugins.py +0 -0
  189. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/cli_analysis.md +0 -0
  190. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_backup_diff.py +0 -0
  191. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_edge_cases.py +0 -0
  192. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_edge_cases_comprehensive.py +0 -0
  193. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_internal_utils.py +0 -0
  194. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_http_pagination_cli.py +0 -0
  195. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/context_analysis.md +0 -0
  196. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_core_import_path.py +0 -0
  197. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_file_manager.py +0 -0
  198. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_import_collector.py +0 -0
  199. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_render_context.py +0 -0
  200. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_render_context_imports.py +0 -0
  201. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_render_context_relative_paths.py +0 -0
  202. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/core_analysis.md +0 -0
  203. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/loader/parameters/test_inline_enum_array_params.py +0 -0
  204. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/loader/test_extractor.py +0 -0
  205. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/loader/test_top_level_enum_extraction.py +0 -0
  206. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/helpers_analysis.md +0 -0
  207. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_cyclic_properties.py +0 -0
  208. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_direct_cycle.py +0 -0
  209. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_existing_schema.py +0 -0
  210. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_list_response.py +0 -0
  211. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_missing_ref.py +0 -0
  212. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_new_schema.py +0 -0
  213. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_stripped_suffix.py +0 -0
  214. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/__init__.py +0 -0
  215. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/keywords_analysis.md +0 -0
  216. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_all_of_parser.py +0 -0
  217. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_any_of_parser.py +0 -0
  218. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_array_items_parser.py +0 -0
  219. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_one_of_parser.py +0 -0
  220. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_properties_parser.py +0 -0
  221. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/parsing_analysis.md +0 -0
  222. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_context.py +0 -0
  223. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_cycle_detection.py +0 -0
  224. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_cycle_helpers.py +0 -0
  225. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_improved_schema_naming.py +0 -0
  226. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_inline_enum_extractor.py +0 -0
  227. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_inline_object_promoter.py +0 -0
  228. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_logging.py +0 -0
  229. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_ref_resolver.py +0 -0
  230. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_schema_finalizer.py +0 -0
  231. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_schema_parser.py +0 -0
  232. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_schema_parser_list_response.py +0 -0
  233. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_type_parser.py +0 -0
  234. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_dataclass_serialization.py +0 -0
  235. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_detect_circular_imports.py +0 -0
  236. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_edge_cases_integration.py +0 -0
  237. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_edge_cases_systematic.py +0 -0
  238. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_exceptions_module.py +0 -0
  239. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_forward_references.py +0 -0
  240. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_http_transport.py +0 -0
  241. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_import_resolution.py +0 -0
  242. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_ir.py +0 -0
  243. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_ir_schema.py +0 -0
  244. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader.py +0 -0
  245. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_extensive.py +0 -0
  246. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_invalid_refs.py +0 -0
  247. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_malformed.py +0 -0
  248. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_media_types.py +0 -0
  249. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_pagination.py +0 -0
  250. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_parsing_context.py +0 -0
  251. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_protocol_defaults.py +0 -0
  252. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_schema_parser_specific_case.py +0 -0
  253. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_schemas.py +0 -0
  254. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_simple_self_ref_check.py +0 -0
  255. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_streaming_helpers.py +0 -0
  256. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_telemetry.py +0 -0
  257. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_telemetry_client.py +0 -0
  258. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_utils.py +0 -0
  259. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_warning_collector.py +0 -0
  260. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_code_writer.py +0 -0
  261. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_documentation_writer.py +0 -0
  262. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_line_writer.py +0 -0
  263. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_python_construct_renderer_json_wizard.py +0 -0
  264. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/writers_analysis.md +0 -0
  265. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/emitters_analysis.md +0 -0
  266. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_client_emitter.py +0 -0
  267. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_docs_emitter.py +0 -0
  268. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_duplicate_operations.py +0 -0
  269. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_exceptions_emitter.py +0 -0
  270. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_list_response_generation.py +0 -0
  271. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_models_emitter.py +0 -0
  272. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/end_to_end/test_dataclass_serialization_e2e.py +0 -0
  273. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/examples/test_developer_experience_demo.py +0 -0
  274. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation/generation_analysis.md +0 -0
  275. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation/test_external_core_package.py +0 -0
  276. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/specs/minimal_addmessage_like.json +0 -0
  277. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_addmessage_like_issues.py +0 -0
  278. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_agent_include_parameter_typing.py +0 -0
  279. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_message_batch_response_issue.py +0 -0
  280. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_overload_naming_issues.py +0 -0
  281. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/helpers_analysis.md +0 -0
  282. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_array_resolver.py +0 -0
  283. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_endpoint_utils.py +0 -0
  284. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_endpoint_utils_extended.py +0 -0
  285. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_get_endpoint_return_types.py +0 -0
  286. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_named_resolver.py +0 -0
  287. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_named_type_resolver.py +0 -0
  288. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_object_resolver.py +0 -0
  289. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_put_endpoint_return_types.py +0 -0
  290. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_type_cleaner.py +0 -0
  291. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_type_helper.py +0 -0
  292. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_url_utils.py +0 -0
  293. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_utils_helpers.py +0 -0
  294. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integration/test_field_mapping_e2e.py +0 -0
  295. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integration/test_generated_code_structure.py +0 -0
  296. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/integrations_analysis.md +0 -0
  297. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_business_swagger_message_type.py +0 -0
  298. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_end_to_end_business_swagger.py +0 -0
  299. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_end_to_end_petstore.py +0 -0
  300. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_name_collisions.py +0 -0
  301. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/specs/response_unwrapping_spec.yaml +0 -0
  302. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/test_analysis_overview.md +0 -0
  303. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/test_init.py +0 -0
  304. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/__init__.py +0 -0
  305. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_business_swagger_integration.py +0 -0
  306. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_contracts_types.py +0 -0
  307. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_missing_imports_bug.py +0 -0
  308. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_reference_resolver.py +0 -0
  309. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_response_resolver.py +0 -0
  310. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_response_strategy.py +0 -0
  311. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_response_strategy_simplified.py +0 -0
  312. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_schema_resolver.py +0 -0
  313. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_schema_resolver_enums.py +0 -0
  314. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_type_service.py +0 -0
  315. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/__init__.py +0 -0
  316. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/__init__.py +0 -0
  317. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/__init__.py +0 -0
  318. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/generators_analysis.md +0 -0
  319. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_dataclass_integration.py +0 -0
  320. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_docstring_generator.py +0 -0
  321. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_endpoint_method_generator.py +0 -0
  322. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_match_case_response.py +0 -0
  323. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_overload_generator.py +0 -0
  324. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_request_generator.py +0 -0
  325. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_response_handler_generator.py +0 -0
  326. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_response_handler_generator_strategy.py +0 -0
  327. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_signature_generator.py +0 -0
  328. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/__init__.py +0 -0
  329. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/test_import_analyzer.py +0 -0
  330. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/test_import_analyzer.py.bak +0 -0
  331. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/test_parameter_processor.py +0 -0
  332. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/test_endpoint_visitor.py +0 -0
  333. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/__init__.py +0 -0
  334. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_alias_generator.py +0 -0
  335. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_dataclass_generator.py +0 -0
  336. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_dataclass_generator_json_wizard.py +0 -0
  337. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_enum_generator.py +0 -0
  338. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_json_value_integration.py +0 -0
  339. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_json_value_wrapper.py +0 -0
  340. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/test_client_visitor.py +0 -0
  341. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/test_model_visitor.py +0 -0
  342. {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/test_visitor.py +0 -0
@@ -1,6 +1,48 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## v0.21.1 (2025-10-24)
5
+
6
+ ### Bug Fixes
7
+
8
+ - **codegen**: Fix enum parameter serialization in query, header, and path parameters
9
+ ([`be5391f`](https://github.com/mindhiveoy/pyopenapi_gen/commit/be5391ff9fde14a1826aa217c077b06a0f832f8c))
10
+
11
+ Implement consistent parameter serialization using DataclassSerializer.serialize() for query,
12
+ header, and path parameters to handle enum-to-string conversion correctly.
13
+
14
+ Technical changes: - _write_query_params() now wraps all parameter values in
15
+ DataclassSerializer.serialize() - _write_header_params() now wraps all parameter values in
16
+ DataclassSerializer.serialize() - generate_url_and_args() serializes path params before f-string
17
+ interpolation - Added context.add_import() calls to ensure DataclassSerializer is imported in
18
+ generated code
19
+
20
+ Implementation approach: Query/header parameters use DataclassSerializer.serialize() in dict
21
+ construction: Required: "{param}": DataclassSerializer.serialize(param_var)
22
+
23
+ Optional: **{{"{param}": DataclassSerializer.serialize(param_var)} if param_var is not None else {}}
24
+
25
+ Path parameters are serialized before URL construction to prevent enum objects in f-strings (would
26
+ produce "EnumType.VALUE" instead of "value"): param_var = DataclassSerializer.serialize(param_var)
27
+
28
+ Breaking changes: None API changes: None (generated code behavior corrected to match intended
29
+ design)
30
+
31
+ Test coverage: - 5 new TDD tests validate enum serialization for all parameter types - All 1360
32
+ tests passing with 88.43% coverage - Integration tests confirm correct mypy validation and runtime
33
+ behavior
34
+
35
+ Fixes issue where enum parameters (e.g., DocumentStatus.INDEXED) were passed directly to httpx
36
+ instead of being converted to their string values ("indexed"), causing incorrect API calls.
37
+
38
+ Related: business_swagger.json list_documents endpoint with status parameter
39
+
40
+ ### Chores
41
+
42
+ - **release**: Sync __init__.py version [skip ci]
43
+ ([`823dc4e`](https://github.com/mindhiveoy/pyopenapi_gen/commit/823dc4e7083f17df7323aeebd9a400fd9d7aca5d))
44
+
45
+
4
46
  ## v0.21.0 (2025-10-23)
5
47
 
6
48
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyopenapi-gen
3
- Version: 0.21.0
3
+ Version: 0.21.1
4
4
  Summary: Modern, async-first Python client generator for OpenAPI specifications with advanced cycle detection and unified type resolution
5
5
  Project-URL: Homepage, https://github.com/your-org/pyopenapi-gen
6
6
  Project-URL: Documentation, https://github.com/your-org/pyopenapi-gen/blob/main/README.md
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" ?>
2
- <coverage version="7.10.7" timestamp="1761233680435" lines-valid="6518" lines-covered="5763" line-rate="0.8842" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
2
+ <coverage version="7.10.7" timestamp="1761323025794" lines-valid="6528" lines-covered="5773" line-rate="0.8843" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
3
3
  <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.10.7 -->
4
4
  <!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
5
5
  <sources>
@@ -6019,7 +6019,7 @@
6019
6019
  </class>
6020
6020
  </classes>
6021
6021
  </package>
6022
- <package name="pyopenapi_gen.visit.endpoint.generators" line-rate="0.8884" branch-rate="0" complexity="0">
6022
+ <package name="pyopenapi_gen.visit.endpoint.generators" line-rate="0.89" branch-rate="0" complexity="0">
6023
6023
  <classes>
6024
6024
  <class name="__init__.py" filename="pyopenapi_gen/visit/endpoint/generators/__init__.py" complexity="0" line-rate="1" branch-rate="0">
6025
6025
  <methods/>
@@ -6669,7 +6669,7 @@
6669
6669
  <line number="83" hits="1"/>
6670
6670
  </lines>
6671
6671
  </class>
6672
- <class name="url_args_generator.py" filename="pyopenapi_gen/visit/endpoint/generators/url_args_generator.py" complexity="0" line-rate="0.9882" branch-rate="0">
6672
+ <class name="url_args_generator.py" filename="pyopenapi_gen/visit/endpoint/generators/url_args_generator.py" complexity="0" line-rate="0.9895" branch-rate="0">
6673
6673
  <methods/>
6674
6674
  <lines>
6675
6675
  <line number="5" hits="1"/>
@@ -6689,74 +6689,84 @@
6689
6689
  <line number="41" hits="1"/>
6690
6690
  <line number="42" hits="1"/>
6691
6691
  <line number="44" hits="0"/>
6692
- <line number="46" hits="1"/>
6693
6692
  <line number="47" hits="1"/>
6694
- <line number="48" hits="1"/>
6695
6693
  <line number="49" hits="1"/>
6694
+ <line number="50" hits="1"/>
6696
6695
  <line number="51" hits="1"/>
6697
6696
  <line number="52" hits="1"/>
6697
+ <line number="54" hits="1"/>
6698
6698
  <line number="55" hits="1"/>
6699
6699
  <line number="60" hits="1"/>
6700
- <line number="67" hits="1"/>
6701
- <line number="69" hits="1"/>
6702
- <line number="70" hits="1"/>
6703
- <line number="73" hits="1"/>
6704
- <line number="74" hits="1"/>
6700
+ <line number="65" hits="1"/>
6701
+ <line number="72" hits="1"/>
6702
+ <line number="75" hits="1"/>
6705
6703
  <line number="76" hits="1"/>
6706
- <line number="77" hits="1"/>
6704
+ <line number="78" hits="1"/>
6705
+ <line number="79" hits="1"/>
6707
6706
  <line number="82" hits="1"/>
6708
- <line number="87" hits="1"/>
6707
+ <line number="83" hits="1"/>
6708
+ <line number="85" hits="1"/>
6709
+ <line number="86" hits="1"/>
6710
+ <line number="93" hits="1"/>
6709
6711
  <line number="98" hits="1"/>
6710
- <line number="99" hits="1"/>
6711
- <line number="100" hits="1"/>
6712
- <line number="104" hits="1"/>
6713
- <line number="105" hits="1"/>
6714
- <line number="106" hits="1"/>
6715
- <line number="107" hits="1"/>
6716
- <line number="108" hits="1"/>
6717
- <line number="110" hits="1"/>
6718
- <line number="112" hits="1"/>
6719
6712
  <line number="113" hits="1"/>
6713
+ <line number="114" hits="1"/>
6720
6714
  <line number="116" hits="1"/>
6721
6715
  <line number="117" hits="1"/>
6722
6716
  <line number="118" hits="1"/>
6723
6717
  <line number="119" hits="1"/>
6724
6718
  <line number="120" hits="1"/>
6725
6719
  <line number="122" hits="1"/>
6720
+ <line number="123" hits="1"/>
6726
6721
  <line number="124" hits="1"/>
6727
- <line number="125" hits="1"/>
6722
+ <line number="128" hits="1"/>
6728
6723
  <line number="129" hits="1"/>
6724
+ <line number="130" hits="1"/>
6729
6725
  <line number="131" hits="1"/>
6730
- <line number="133" hits="1"/>
6726
+ <line number="132" hits="1"/>
6731
6727
  <line number="134" hits="1"/>
6732
- <line number="135" hits="1"/>
6733
6728
  <line number="136" hits="1"/>
6734
6729
  <line number="137" hits="1"/>
6735
- <line number="138" hits="1"/>
6730
+ <line number="140" hits="1"/>
6731
+ <line number="141" hits="1"/>
6736
6732
  <line number="142" hits="1"/>
6733
+ <line number="143" hits="1"/>
6734
+ <line number="144" hits="1"/>
6737
6735
  <line number="146" hits="1"/>
6738
- <line number="147" hits="1"/>
6739
6736
  <line number="148" hits="1"/>
6740
6737
  <line number="149" hits="1"/>
6741
- <line number="150" hits="1"/>
6742
- <line number="151" hits="1"/>
6743
- <line number="152" hits="1"/>
6744
6738
  <line number="153" hits="1"/>
6745
6739
  <line number="155" hits="1"/>
6740
+ <line number="157" hits="1"/>
6741
+ <line number="158" hits="1"/>
6746
6742
  <line number="159" hits="1"/>
6747
6743
  <line number="160" hits="1"/>
6748
6744
  <line number="161" hits="1"/>
6749
6745
  <line number="162" hits="1"/>
6750
- <line number="165" hits="1"/>
6751
- <line number="168" hits="1"/>
6752
- <line number="169" hits="1"/>
6746
+ <line number="166" hits="1"/>
6747
+ <line number="170" hits="1"/>
6748
+ <line number="171" hits="1"/>
6749
+ <line number="172" hits="1"/>
6753
6750
  <line number="173" hits="1"/>
6754
6751
  <line number="174" hits="1"/>
6755
6752
  <line number="175" hits="1"/>
6756
- <line number="178" hits="1"/>
6757
- <line number="180" hits="1"/>
6758
- <line number="181" hits="1"/>
6753
+ <line number="176" hits="1"/>
6754
+ <line number="177" hits="1"/>
6755
+ <line number="179" hits="1"/>
6759
6756
  <line number="183" hits="1"/>
6757
+ <line number="184" hits="1"/>
6758
+ <line number="185" hits="1"/>
6759
+ <line number="186" hits="1"/>
6760
+ <line number="189" hits="1"/>
6761
+ <line number="192" hits="1"/>
6762
+ <line number="193" hits="1"/>
6763
+ <line number="197" hits="1"/>
6764
+ <line number="198" hits="1"/>
6765
+ <line number="199" hits="1"/>
6766
+ <line number="202" hits="1"/>
6767
+ <line number="204" hits="1"/>
6768
+ <line number="205" hits="1"/>
6769
+ <line number="207" hits="1"/>
6760
6770
  </lines>
6761
6771
  </class>
6762
6772
  </classes>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pyopenapi-gen"
7
- version = "0.21.0"
7
+ version = "0.21.1"
8
8
  description = "Modern, async-first Python client generator for OpenAPI specifications with advanced cycle detection and unified type resolution"
9
9
  authors = [{ name = "Mindhive Oy", email = "contact@mindhive.fi" }]
10
10
  maintainers = [{ name = "Ville Venäläinen | Mindhive Oy", email = "ville@mindhive.fi" }]
@@ -140,7 +140,7 @@ pyopenapi-gen = "pyopenapi_gen.cli:app"
140
140
 
141
141
  [tool.commitizen]
142
142
  name = "cz_conventional_commits"
143
- version = "0.21.0"
143
+ version = "0.21.1"
144
144
  version_files = [
145
145
  "pyproject.toml:version",
146
146
  "src/pyopenapi_gen/__init__.py:__version__"
@@ -50,7 +50,7 @@ __all__ = [
50
50
  ]
51
51
 
52
52
  # Semantic version of the generator core – automatically managed by semantic-release.
53
- __version__: str = "0.21.0"
53
+ __version__: str = "0.21.1"
54
54
 
55
55
  # ---------------------------------------------------------------------------
56
56
  # Lazy-loading and autocompletion support (This part remains)
@@ -43,17 +43,22 @@ class EndpointUrlArgsGenerator:
43
43
  # writer.write_line("# No query parameters to write") # Optional: for clarity during debugging
44
44
  return
45
45
 
46
+ # Import DataclassSerializer since we use it for parameter serialization
47
+ context.add_import(f"{context.core_package_name}.utils", "DataclassSerializer")
48
+
46
49
  for i, p in enumerate(query_params_to_write):
47
50
  param_var_name = NameSanitizer.sanitize_method_name(p["name"]) # Ensure name is sanitized
48
51
  original_param_name = p["original_name"]
49
52
  line_end = "," # Always add comma, let formatter handle final one if needed
50
53
 
51
54
  if p.get("required", False):
52
- writer.write_line(f' "{original_param_name}": {param_var_name}{line_end}')
55
+ writer.write_line(
56
+ f' "{original_param_name}": DataclassSerializer.serialize({param_var_name}){line_end}'
57
+ )
53
58
  else:
54
59
  # Using dict unpacking for conditional parameters
55
60
  writer.write_line(
56
- f' **({{"{original_param_name}": {param_var_name}}} '
61
+ f' **({{"{original_param_name}": DataclassSerializer.serialize({param_var_name})}} '
57
62
  f"if {param_var_name} is not None else {{}}){line_end}"
58
63
  )
59
64
 
@@ -66,6 +71,10 @@ class EndpointUrlArgsGenerator:
66
71
  # if ordered_params is the sole source of truth for method params.
67
72
  header_params_to_write = [p for p in ordered_params if p.get("param_in") == "header"]
68
73
 
74
+ # Import DataclassSerializer since we use it for parameter serialization
75
+ if header_params_to_write:
76
+ context.add_import(f"{context.core_package_name}.utils", "DataclassSerializer")
77
+
69
78
  for p_info in header_params_to_write:
70
79
  param_var_name = NameSanitizer.sanitize_method_name(
71
80
  p_info["name"]
@@ -74,13 +83,15 @@ class EndpointUrlArgsGenerator:
74
83
  line_end = ","
75
84
 
76
85
  if p_info.get("required", False):
77
- writer.write_line(f' "{original_header_name}": {param_var_name}{line_end}')
86
+ writer.write_line(
87
+ f' "{original_header_name}": DataclassSerializer.serialize({param_var_name}){line_end}'
88
+ )
78
89
  else:
79
90
  # Conditional inclusion for optional headers
80
91
  # This assumes that if an optional header parameter is None, it should not be sent.
81
92
  # If specific behavior (e.g. empty string) is needed for None, logic would adjust.
82
93
  writer.write_line(
83
- f' **({{"{original_header_name}": {param_var_name}}} '
94
+ f' **({{"{original_header_name}": DataclassSerializer.serialize({param_var_name})}} '
84
95
  f"if {param_var_name} is not None else {{}}){line_end}"
85
96
  )
86
97
 
@@ -95,6 +106,19 @@ class EndpointUrlArgsGenerator:
95
106
  ) -> bool:
96
107
  """Writes URL, query, and header parameters. Returns True if header params were written."""
97
108
  # Main logic from EndpointMethodGenerator._write_url_and_args
109
+
110
+ # Serialize path parameters before URL construction
111
+ # This ensures enums, dates, and other complex types are converted to strings
112
+ # before f-string interpolation in the URL
113
+ path_params = [p for p in ordered_params if p.get("param_in") == "path"]
114
+ if path_params:
115
+ # Import DataclassSerializer since we use it for parameter serialization
116
+ context.add_import(f"{context.core_package_name}.utils", "DataclassSerializer")
117
+ for p in path_params:
118
+ param_var_name = NameSanitizer.sanitize_method_name(p["name"])
119
+ writer.write_line(f"{param_var_name} = DataclassSerializer.serialize({param_var_name})")
120
+ writer.write_line("") # Blank line after path param serialization
121
+
98
122
  url_expr = self._build_url_with_path_vars(op.path)
99
123
  writer.write_line(f"url = {url_expr}")
100
124
  writer.write_line("") # Add a blank line for readability
@@ -804,9 +804,9 @@ def test_endpoints_emitter__query_params_included_in_params_dict(
804
804
  # Read the generated code
805
805
  with open(os.path.join(out_dir, "endpoints", "tenants.py")) as f:
806
806
  content = f.read()
807
- # Assert that all query params are included in the params dict
808
- assert '"start_date": start_date' in content
809
- assert '"end_date": end_date' in content
807
+ # Assert that all query params are included in the params dict with serialization
808
+ assert '"start_date": DataclassSerializer.serialize(start_date)' in content
809
+ assert '"end_date": DataclassSerializer.serialize(end_date)' in content
810
810
  # Also check that tenant_id is not in params (it's a path param)
811
811
  assert '"tenant_id": tenant_id' not in content
812
812
 
@@ -157,7 +157,7 @@ class TestEndpointUrlArgsGenerator:
157
157
  code_writer_mock.write_line.assert_any_call(f'url = f"{{self.base_url}}/items"')
158
158
  code_writer_mock.write_line.assert_any_call("params: dict[str, Any] = {")
159
159
  code_writer_mock.write_line.assert_any_call(
160
- ' **({"filterBy": filter_by} if filter_by is not None else {}),'
160
+ ' **({"filterBy": DataclassSerializer.serialize(filter_by)} if filter_by is not None else {}),'
161
161
  )
162
162
  mock_sanitize_query.assert_any_call("filter_by")
163
163
  render_context_mock.add_import.assert_any_call("typing", "Any")
@@ -227,9 +227,9 @@ class TestEndpointUrlArgsGenerator:
227
227
 
228
228
  code_writer_mock.write_line.assert_any_call(f'url = f"{{self.base_url}}/items_with_headers"')
229
229
  code_writer_mock.write_line.assert_any_call("headers: dict[str, Any] = {")
230
- code_writer_mock.write_line.assert_any_call(' "X-Request-ID": x_request_id,')
230
+ code_writer_mock.write_line.assert_any_call(' "X-Request-ID": DataclassSerializer.serialize(x_request_id),')
231
231
  code_writer_mock.write_line.assert_any_call(
232
- ' **({"X-Client-Version": x_client_version} if x_client_version is not None else {}),'
232
+ ' **({"X-Client-Version": DataclassSerializer.serialize(x_client_version)} if x_client_version is not None else {}),'
233
233
  )
234
234
  code_writer_mock.write_line.assert_any_call("}") # Closing brace for headers dict
235
235
 
@@ -371,7 +371,7 @@ class TestEndpointUrlArgsGenerator:
371
371
  # Query params assertions
372
372
  code_writer_mock.write_line.assert_any_call("params: dict[str, Any] = {")
373
373
  code_writer_mock.write_line.assert_any_call(
374
- ' **({"verboseOutput": verbose_output_sanitized} if verbose_output_sanitized is not None else {}),'
374
+ ' **({"verboseOutput": DataclassSerializer.serialize(verbose_output_sanitized)} if verbose_output_sanitized is not None else {}),'
375
375
  )
376
376
  # _write_query_params calls sanitize_method_name on p["name"]
377
377
  mock_sanitize_method_name.assert_any_call(
@@ -382,7 +382,9 @@ class TestEndpointUrlArgsGenerator:
382
382
  code_writer_mock.write_line.assert_any_call("headers: dict[str, Any] = {")
383
383
  # Content-Type is NOT added by this generator to the headers dict
384
384
  # self.code_writer_mock.write_line.assert_any_call(f' "Content-Type": "{primary_content_type}",')
385
- code_writer_mock.write_line.assert_any_call(' "X-Correlation-ID": x_correlation_id_sanitized,')
385
+ code_writer_mock.write_line.assert_any_call(
386
+ ' "X-Correlation-ID": DataclassSerializer.serialize(x_correlation_id_sanitized),'
387
+ )
386
388
 
387
389
  # _write_header_params calls sanitize_method_name on p_info["name"]
388
390
  mock_sanitize_method_name.assert_any_call(
@@ -601,3 +603,281 @@ class TestEndpointUrlArgsGenerator:
601
603
 
602
604
  code_writer_mock.write_line.assert_any_call(f"bytes_body: bytes = bytes_content")
603
605
  # No specific imports added by this path in the generator
606
+
607
+ # ========== ENUM SERIALIZATION TESTS (TDD - RED PHASE) ==========
608
+
609
+ def test_write_query_params__required_enum_parameter__serializes_value(
610
+ self, url_args_generator: EndpointUrlArgsGenerator, render_context_mock: MagicMock
611
+ ) -> None:
612
+ """
613
+ Scenario: Required query parameter is an enum type
614
+ Expected Outcome: Generated code calls DataclassSerializer.serialize() to convert enum to string value
615
+
616
+ This test follows TDD principles:
617
+ - RED: Test will fail because current code doesn't call serialize()
618
+ - GREEN: Will pass after implementing the fix
619
+ - REFACTOR: Cleanup if needed
620
+ """
621
+ # Arrange
622
+ writer = CodeWriter()
623
+ operation = IROperation(
624
+ operation_id="list_documents",
625
+ summary="List documents",
626
+ description="List documents with status filter",
627
+ method=HTTPMethod.GET,
628
+ path="/documents",
629
+ tags=["documents"],
630
+ parameters=[
631
+ IRParameter(
632
+ name="status",
633
+ param_in="query",
634
+ required=True,
635
+ schema=IRSchema(type="string", is_nullable=False),
636
+ description="Document status filter",
637
+ )
638
+ ],
639
+ request_body=None,
640
+ responses=[],
641
+ )
642
+ ordered_params = [
643
+ {
644
+ "name": "status",
645
+ "original_name": "status",
646
+ "param_in": "query",
647
+ "required": True,
648
+ }
649
+ ]
650
+
651
+ # Act
652
+ url_args_generator._write_query_params(writer, operation, ordered_params, render_context_mock)
653
+ generated_code = writer.get_code()
654
+
655
+ # Assert
656
+ assert "DataclassSerializer.serialize(status)" in generated_code, (
657
+ "Required query parameter should be serialized with DataclassSerializer.serialize() "
658
+ "to handle enum→string conversion"
659
+ )
660
+ assert '"status": DataclassSerializer.serialize(status)' in generated_code
661
+
662
+ def test_write_query_params__optional_enum_parameter__serializes_value(
663
+ self, url_args_generator: EndpointUrlArgsGenerator, render_context_mock: MagicMock
664
+ ) -> None:
665
+ """
666
+ Scenario: Optional query parameter is an enum type
667
+ Expected Outcome: Generated code calls DataclassSerializer.serialize() within None check
668
+
669
+ This ensures enums are converted to string values before being passed to httpx,
670
+ preventing enum objects from appearing in query strings.
671
+ """
672
+ # Arrange
673
+ writer = CodeWriter()
674
+ operation = IROperation(
675
+ operation_id="list_documents",
676
+ summary="List documents",
677
+ description="List documents with optional status filter",
678
+ method=HTTPMethod.GET,
679
+ path="/documents",
680
+ tags=["documents"],
681
+ parameters=[
682
+ IRParameter(
683
+ name="status",
684
+ param_in="query",
685
+ required=False,
686
+ schema=IRSchema(type="string", is_nullable=True),
687
+ description="Optional document status filter",
688
+ )
689
+ ],
690
+ request_body=None,
691
+ responses=[],
692
+ )
693
+ ordered_params = [
694
+ {
695
+ "name": "status",
696
+ "original_name": "status",
697
+ "param_in": "query",
698
+ "required": False,
699
+ }
700
+ ]
701
+
702
+ # Act
703
+ url_args_generator._write_query_params(writer, operation, ordered_params, render_context_mock)
704
+ generated_code = writer.get_code()
705
+
706
+ # Assert
707
+ assert "DataclassSerializer.serialize(status)" in generated_code, (
708
+ "Optional query parameter should be serialized with DataclassSerializer.serialize() "
709
+ "to handle enum→string conversion"
710
+ )
711
+ assert "if status is not None" in generated_code, "Optional parameter should have None check"
712
+ # Verify serialization happens inside the conditional
713
+ assert '{"status": DataclassSerializer.serialize(status)}' in generated_code
714
+
715
+ def test_write_header_params__required_enum_parameter__serializes_value(
716
+ self, url_args_generator: EndpointUrlArgsGenerator, render_context_mock: MagicMock
717
+ ) -> None:
718
+ """
719
+ Scenario: Required header parameter is an enum type
720
+ Expected Outcome: Generated code calls DataclassSerializer.serialize() to convert enum to string value
721
+
722
+ Headers must be strings. This test ensures enums are properly converted.
723
+ """
724
+ # Arrange
725
+ writer = CodeWriter()
726
+ operation = IROperation(
727
+ operation_id="get_data",
728
+ summary="Get data",
729
+ description="Get data with API version header",
730
+ method=HTTPMethod.GET,
731
+ path="/data",
732
+ tags=["data"],
733
+ parameters=[
734
+ IRParameter(
735
+ name="X-API-Version",
736
+ param_in="header",
737
+ required=True,
738
+ schema=IRSchema(type="string", is_nullable=False),
739
+ description="API version",
740
+ )
741
+ ],
742
+ request_body=None,
743
+ responses=[],
744
+ )
745
+ ordered_params = [
746
+ {
747
+ "name": "x_api_version",
748
+ "original_name": "X-API-Version",
749
+ "param_in": "header",
750
+ "required": True,
751
+ }
752
+ ]
753
+
754
+ # Act
755
+ url_args_generator._write_header_params(writer, operation, ordered_params, render_context_mock)
756
+ generated_code = writer.get_code()
757
+
758
+ # Assert
759
+ assert "DataclassSerializer.serialize(x_api_version)" in generated_code, (
760
+ "Required header parameter should be serialized with DataclassSerializer.serialize() "
761
+ "to handle enum→string conversion"
762
+ )
763
+ assert '"X-API-Version": DataclassSerializer.serialize(x_api_version)' in generated_code
764
+
765
+ def test_write_header_params__optional_enum_parameter__serializes_value(
766
+ self, url_args_generator: EndpointUrlArgsGenerator, render_context_mock: MagicMock
767
+ ) -> None:
768
+ """
769
+ Scenario: Optional header parameter is an enum type
770
+ Expected Outcome: Generated code calls DataclassSerializer.serialize() within None check
771
+
772
+ Ensures enum headers are properly converted to strings before being sent to httpx.
773
+ """
774
+ # Arrange
775
+ writer = CodeWriter()
776
+ operation = IROperation(
777
+ operation_id="get_data",
778
+ summary="Get data",
779
+ description="Get data with optional API version header",
780
+ method=HTTPMethod.GET,
781
+ path="/data",
782
+ tags=["data"],
783
+ parameters=[
784
+ IRParameter(
785
+ name="X-API-Version",
786
+ param_in="header",
787
+ required=False,
788
+ schema=IRSchema(type="string", is_nullable=True),
789
+ description="Optional API version",
790
+ )
791
+ ],
792
+ request_body=None,
793
+ responses=[],
794
+ )
795
+ ordered_params = [
796
+ {
797
+ "name": "x_api_version",
798
+ "original_name": "X-API-Version",
799
+ "param_in": "header",
800
+ "required": False,
801
+ }
802
+ ]
803
+
804
+ # Act
805
+ url_args_generator._write_header_params(writer, operation, ordered_params, render_context_mock)
806
+ generated_code = writer.get_code()
807
+
808
+ # Assert
809
+ assert "DataclassSerializer.serialize(x_api_version)" in generated_code, (
810
+ "Optional header parameter should be serialized with DataclassSerializer.serialize() "
811
+ "to handle enum→string conversion"
812
+ )
813
+ assert "if x_api_version is not None" in generated_code, "Optional parameter should have None check"
814
+ assert '{"X-API-Version": DataclassSerializer.serialize(x_api_version)}' in generated_code
815
+
816
+ def test_generate_url_and_args__path_enum_parameter__serializes_before_url(
817
+ self, url_args_generator: EndpointUrlArgsGenerator, code_writer_mock: MagicMock, render_context_mock: MagicMock
818
+ ) -> None:
819
+ """
820
+ Scenario: Path parameter is an enum type
821
+ Expected Outcome: Generated code serializes path variable before URL construction
822
+
823
+ Path parameters are interpolated into f-strings. Enums must be converted to strings
824
+ first, otherwise f-string will produce "DocumentStatus.INDEXED" instead of "indexed".
825
+ """
826
+ # Arrange
827
+ operation = IROperation(
828
+ operation_id="get_document_by_status",
829
+ summary="Get document by status",
830
+ description="Get document using status path parameter",
831
+ method=HTTPMethod.GET,
832
+ path="/documents/{status}",
833
+ tags=["documents"],
834
+ parameters=[
835
+ IRParameter(
836
+ name="status",
837
+ param_in="path",
838
+ required=True,
839
+ schema=IRSchema(type="string", is_nullable=False),
840
+ description="Document status",
841
+ )
842
+ ],
843
+ request_body=None,
844
+ responses=[],
845
+ )
846
+ ordered_params = [
847
+ {
848
+ "name": "status",
849
+ "original_name": "status",
850
+ "param_in": "path",
851
+ "required": True,
852
+ }
853
+ ]
854
+
855
+ # Act
856
+ url_args_generator.generate_url_and_args(
857
+ code_writer_mock, operation, render_context_mock, ordered_params, None, None
858
+ )
859
+
860
+ # Assert
861
+ # Get all write_line calls
862
+ calls = [c[0][0] for c in code_writer_mock.write_line.call_args_list]
863
+
864
+ # Find serialization and URL lines
865
+ serialize_line_idx = None
866
+ url_line_idx = None
867
+
868
+ for i, line in enumerate(calls):
869
+ if "DataclassSerializer.serialize(status)" in line and "status = " in line:
870
+ serialize_line_idx = i
871
+ if 'url = f"{self.base_url}' in line:
872
+ url_line_idx = i
873
+
874
+ # Assert serialization happens before URL construction
875
+ assert serialize_line_idx is not None, (
876
+ "Path parameter must be serialized using DataclassSerializer.serialize() "
877
+ "to convert enum to string before f-string interpolation"
878
+ )
879
+ assert url_line_idx is not None, "URL construction line should exist"
880
+ assert serialize_line_idx < url_line_idx, (
881
+ "Path parameter serialization must occur before URL construction "
882
+ "to ensure f-string receives string value, not enum object"
883
+ )
File without changes