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.
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/CHANGELOG.md +42 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/PKG-INFO +1 -1
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/coverage.xml +45 -35
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/pyproject.toml +2 -2
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/__init__.py +1 -1
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/url_args_generator.py +28 -4
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_endpoints_emitter.py +3 -3
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_url_args_generator.py +285 -5
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.bandit +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/mcp.json +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/architecture.mdc +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/coding-conventions.mdc +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/project-goal.mdc +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.cursor/rules/testing.mdc +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/BRANCH_PROTECTION.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/CLAUDE_CONFIGURATION.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/CODEOWNERS +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/dependabot.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/ci.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/claude-auto-approve.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/claude-review-trigger.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/claude.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/pr-checks.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/production-release.yml.backup +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/promote-to-staging.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/semantic-release.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/staging-publish.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.github/workflows/testpypi-publish.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.gitignore +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.python-version +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/.vscode/settings.json +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/CONTRIBUTING.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/LICENSE +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/Makefile +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/README.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/README.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/architecture.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/endpoint_visitor.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/helpers.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/ir_models.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/line_writer.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/loader.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/model_visitor.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/release-automation.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/render_context.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/docs/unified_type_resolution.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/business_swagger.json +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/minimal_swagger.json +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/minimal_syntax_test.json +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/input/test_name_collision_spec.json +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/mkdocs.yml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/poetry.lock +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/scripts/sync_version_to_init.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/scripts/validate_version_sync.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/__main__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/cli.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/file_manager.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/import_collector.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/context/render_context.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/auth/base.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/auth/plugins.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/exceptions.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/http_status_codes.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/http_transport.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/loader.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/post_processor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/operations/request_body.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/parameters/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/parameters/parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/responses/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/responses/parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/schemas/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/loader/schemas/extractor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/pagination.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/cyclic_properties.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/direct_cycle.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/existing_schema.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/list_response.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/missing_ref.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/new_schema.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/stripped_suffix.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/resolve_schema_ref.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/common/type_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/context.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/cycle_helpers.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/all_of_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/any_of_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/array_items_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/one_of_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/keywords/properties_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/schema_finalizer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/schema_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/transformers/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/transformers/inline_enum_extractor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/transformers/inline_object_promoter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/parsing/unified_cycle_detection.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/postprocess_manager.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/schemas.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/streaming_helpers.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/telemetry.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/utils.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/warning_collector.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/code_writer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/documentation_writer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/line_writer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core/writers/python_construct_renderer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/core_package_template/README.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emit/models_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/client_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/core_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/docs_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/endpoints_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/exceptions_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/emitters/models_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/generator/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/generator/client_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/endpoint_utils.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_cleaner.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_helper.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/array_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/composition_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/finalizer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/named_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/object_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/primitive_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/type_resolution/resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/helpers/url_utils.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/http_types.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/ir.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/py.typed +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/contracts/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/contracts/protocols.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/contracts/types.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/reference_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/response_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/resolvers/schema_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/services/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/services/type_service.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/strategies/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/types/strategies/response_strategy.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/CLAUDE.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/client_visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/docs_visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/endpoint_visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/docstring_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/overload_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/request_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/response_handler_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/generators/signature_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/processors/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/processors/import_analyzer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/endpoint/processors/parameter_processor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/exception_visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/alias_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/dataclass_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/enum_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/model/model_visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/src/pyopenapi_gen/visit/visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/api/test_programmatic_api.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/auth/auth_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/auth/test_auth_base.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/auth/test_auth_plugins.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/cli_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_backup_diff.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_edge_cases.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_edge_cases_comprehensive.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_cli_internal_utils.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/cli/test_http_pagination_cli.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/context_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_core_import_path.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_file_manager.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_import_collector.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_render_context.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_render_context_imports.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/context/test_render_context_relative_paths.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/core_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/loader/parameters/test_inline_enum_array_params.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/loader/test_extractor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/loader/test_top_level_enum_extraction.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/helpers_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_cyclic_properties.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_direct_cycle.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_existing_schema.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_list_response.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_missing_ref.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_new_schema.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/common/ref_resolution/helpers/test_stripped_suffix.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/keywords_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_all_of_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_any_of_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_array_items_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_one_of_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/keywords/test_properties_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/parsing_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_context.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_cycle_detection.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_cycle_helpers.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_improved_schema_naming.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_inline_enum_extractor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_inline_object_promoter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_logging.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_ref_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_schema_finalizer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_schema_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_schema_parser_list_response.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/parsing/test_type_parser.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_dataclass_serialization.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_detect_circular_imports.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_edge_cases_integration.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_edge_cases_systematic.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_exceptions_module.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_forward_references.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_http_transport.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_import_resolution.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_ir.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_ir_schema.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_extensive.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_invalid_refs.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_malformed.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_loader_media_types.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_pagination.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_parsing_context.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_protocol_defaults.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_schema_parser_specific_case.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_schemas.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_simple_self_ref_check.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_streaming_helpers.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_telemetry.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_telemetry_client.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_utils.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/test_warning_collector.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_code_writer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_documentation_writer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_line_writer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/test_python_construct_renderer_json_wizard.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/core/writers/writers_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/emitters_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_client_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_docs_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_duplicate_operations.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_exceptions_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_list_response_generation.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/emitters/test_models_emitter.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/end_to_end/test_dataclass_serialization_e2e.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/examples/test_developer_experience_demo.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation/generation_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation/test_external_core_package.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/specs/minimal_addmessage_like.json +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_addmessage_like_issues.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_agent_include_parameter_typing.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_message_batch_response_issue.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/generation_issues/test_overload_naming_issues.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/helpers_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_array_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_endpoint_utils.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_endpoint_utils_extended.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_get_endpoint_return_types.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_named_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_named_type_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_object_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_put_endpoint_return_types.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_type_cleaner.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_type_helper.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_url_utils.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/helpers/test_utils_helpers.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integration/test_field_mapping_e2e.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integration/test_generated_code_structure.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/integrations_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_business_swagger_message_type.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_end_to_end_business_swagger.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_end_to_end_petstore.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/integrations/test_name_collisions.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/specs/response_unwrapping_spec.yaml +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/test_analysis_overview.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/test_init.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_business_swagger_integration.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_contracts_types.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_missing_imports_bug.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_reference_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_response_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_response_strategy.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_response_strategy_simplified.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_schema_resolver.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_schema_resolver_enums.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/types/test_type_service.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/generators_analysis.md +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_dataclass_integration.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_docstring_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_endpoint_method_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_match_case_response.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_overload_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_request_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_response_handler_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_response_handler_generator_strategy.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/generators/test_signature_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/test_import_analyzer.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/test_import_analyzer.py.bak +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/processors/test_parameter_processor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/endpoint/test_endpoint_visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/__init__.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_alias_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_dataclass_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_dataclass_generator_json_wizard.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_enum_generator.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_json_value_integration.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/model/test_json_value_wrapper.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/test_client_visitor.py +0 -0
- {pyopenapi_gen-0.21.0 → pyopenapi_gen-0.21.1}/tests/visit/test_model_visitor.py +0 -0
- {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.
|
|
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="
|
|
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.
|
|
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.
|
|
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="
|
|
6701
|
-
<line number="
|
|
6702
|
-
<line number="
|
|
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="
|
|
6704
|
+
<line number="78" hits="1"/>
|
|
6705
|
+
<line number="79" hits="1"/>
|
|
6707
6706
|
<line number="82" hits="1"/>
|
|
6708
|
-
<line number="
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
6751
|
-
<line number="
|
|
6752
|
-
<line number="
|
|
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="
|
|
6757
|
-
<line number="
|
|
6758
|
-
<line number="
|
|
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.
|
|
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.
|
|
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|