pyopenapi-gen 0.20.0__tar.gz → 0.20.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.20.0 → pyopenapi_gen-0.20.1}/CHANGELOG.md +47 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/PKG-INFO +1 -1
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/coverage.xml +56 -54
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/pyproject.toml +2 -2
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/__init__.py +1 -1
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py +2 -2
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/overload_generator.py +9 -2
- pyopenapi_gen-0.20.1/tests/generation_issues/test_overload_naming_issues.py +203 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_endpoint_method_generator.py +61 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_overload_generator.py +84 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.bandit +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.cursor/mcp.json +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.cursor/rules/architecture.mdc +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.cursor/rules/coding-conventions.mdc +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.cursor/rules/project-goal.mdc +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.cursor/rules/testing.mdc +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/BRANCH_PROTECTION.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/CLAUDE_CONFIGURATION.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/CODEOWNERS +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/dependabot.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/ci.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/claude-auto-approve.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/claude-review-trigger.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/claude.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/pr-checks.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/production-release.yml.backup +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/promote-to-staging.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/semantic-release.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/staging-publish.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.github/workflows/testpypi-publish.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.gitignore +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.python-version +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/.vscode/settings.json +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/CONTRIBUTING.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/LICENSE +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/Makefile +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/README.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/README.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/architecture.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/endpoint_visitor.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/helpers.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/ir_models.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/line_writer.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/loader.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/model_visitor.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/release-automation.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/render_context.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/docs/unified_type_resolution.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/input/business_swagger.json +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/input/minimal_swagger.json +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/input/minimal_syntax_test.json +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/input/test_name_collision_spec.json +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/mkdocs.yml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/poetry.lock +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/scripts/sync_version_to_init.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/scripts/validate_version_sync.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/__main__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/cli.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/context/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/context/file_manager.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/context/import_collector.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/context/render_context.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/auth/base.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/auth/plugins.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/exceptions.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/http_status_codes.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/http_transport.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/loader.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/operations/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/operations/parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/operations/post_processor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/operations/request_body.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/parameters/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/parameters/parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/responses/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/responses/parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/schemas/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/loader/schemas/extractor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/pagination.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/cyclic_properties.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/direct_cycle.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/existing_schema.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/list_response.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/missing_ref.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/new_schema.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/helpers/stripped_suffix.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/ref_resolution/resolve_schema_ref.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/common/type_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/context.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/cycle_helpers.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/keywords/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/keywords/all_of_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/keywords/any_of_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/keywords/array_items_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/keywords/one_of_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/keywords/properties_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/schema_finalizer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/schema_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/transformers/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/transformers/inline_enum_extractor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/transformers/inline_object_promoter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/parsing/unified_cycle_detection.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/postprocess_manager.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/schemas.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/streaming_helpers.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/telemetry.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/utils.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/warning_collector.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/writers/code_writer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/writers/documentation_writer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/writers/line_writer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core/writers/python_construct_renderer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/core_package_template/README.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emit/models_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emitters/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emitters/client_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emitters/core_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emitters/docs_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emitters/endpoints_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emitters/exceptions_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/emitters/models_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/generator/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/generator/client_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/endpoint_utils.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_cleaner.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_helper.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/array_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/composition_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/finalizer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/named_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/object_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/primitive_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/type_resolution/resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/helpers/url_utils.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/http_types.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/ir.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/py.typed +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/contracts/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/contracts/protocols.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/contracts/types.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/resolvers/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/resolvers/reference_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/resolvers/response_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/resolvers/schema_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/services/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/services/type_service.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/strategies/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/types/strategies/response_strategy.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/CLAUDE.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/client_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/docs_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/endpoint_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/docstring_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/request_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/response_handler_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/signature_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/generators/url_args_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/processors/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/processors/import_analyzer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/endpoint/processors/parameter_processor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/exception_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/model/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/model/alias_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/model/dataclass_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/model/enum_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/model/model_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/src/pyopenapi_gen/visit/visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/api/test_programmatic_api.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/auth/auth_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/auth/test_auth_base.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/auth/test_auth_plugins.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/cli/cli_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/cli/test_cli_backup_diff.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/cli/test_cli_edge_cases.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/cli/test_cli_edge_cases_comprehensive.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/cli/test_cli_internal_utils.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/cli/test_http_pagination_cli.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/context/context_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/context/test_core_import_path.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/context/test_file_manager.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/context/test_import_collector.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/context/test_render_context.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/context/test_render_context_imports.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/context/test_render_context_relative_paths.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/core_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/loader/parameters/test_inline_enum_array_params.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/loader/test_extractor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/loader/test_top_level_enum_extraction.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/helpers_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/test_cyclic_properties.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/test_direct_cycle.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/test_existing_schema.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/test_list_response.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/test_missing_ref.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/test_new_schema.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/common/ref_resolution/helpers/test_stripped_suffix.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/keywords/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/keywords/keywords_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/keywords/test_all_of_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/keywords/test_any_of_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/keywords/test_array_items_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/keywords/test_one_of_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/keywords/test_properties_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/parsing_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_context.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_cycle_detection.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_cycle_helpers.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_improved_schema_naming.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_inline_enum_extractor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_inline_object_promoter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_logging.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_ref_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_schema_finalizer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_schema_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_schema_parser_list_response.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/parsing/test_type_parser.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_dataclass_serialization.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_detect_circular_imports.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_edge_cases_integration.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_edge_cases_systematic.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_exceptions_module.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_forward_references.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_http_transport.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_import_resolution.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_ir.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_ir_schema.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_loader.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_loader_extensive.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_loader_invalid_refs.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_loader_malformed.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_loader_media_types.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_pagination.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_parsing_context.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_protocol_defaults.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_schema_parser_specific_case.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_schemas.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_simple_self_ref_check.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_streaming_helpers.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_telemetry.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_telemetry_client.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_utils.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/test_warning_collector.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/writers/test_code_writer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/writers/test_documentation_writer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/writers/test_line_writer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/writers/test_python_construct_renderer_json_wizard.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/core/writers/writers_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/emitters_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/test_client_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/test_docs_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/test_duplicate_operations.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/test_endpoints_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/test_exceptions_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/test_list_response_generation.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/emitters/test_models_emitter.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/end_to_end/test_dataclass_serialization_e2e.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/examples/test_developer_experience_demo.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/generation/generation_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/generation/test_external_core_package.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/generation_issues/specs/minimal_addmessage_like.json +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/generation_issues/test_addmessage_like_issues.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/generation_issues/test_agent_include_parameter_typing.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/generation_issues/test_message_batch_response_issue.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/helpers_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_array_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_endpoint_utils.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_endpoint_utils_extended.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_get_endpoint_return_types.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_named_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_named_type_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_object_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_put_endpoint_return_types.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_type_cleaner.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_type_helper.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_url_utils.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/helpers/test_utils_helpers.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/integration/test_generated_code_structure.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/integrations/integrations_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/integrations/test_business_swagger_message_type.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/integrations/test_end_to_end_business_swagger.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/integrations/test_end_to_end_petstore.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/integrations/test_name_collisions.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/specs/response_unwrapping_spec.yaml +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/test_analysis_overview.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/test_init.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_business_swagger_integration.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_contracts_types.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_missing_imports_bug.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_reference_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_response_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_response_strategy.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_response_strategy_simplified.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_schema_resolver.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_schema_resolver_enums.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/types/test_type_service.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/generators_analysis.md +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_dataclass_integration.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_docstring_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_match_case_response.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_request_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_response_handler_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_response_handler_generator_strategy.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_signature_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/generators/test_url_args_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/processors/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/processors/test_import_analyzer.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/processors/test_import_analyzer.py.bak +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/processors/test_parameter_processor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/endpoint/test_endpoint_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/model/__init__.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/model/test_alias_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/model/test_dataclass_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/model/test_dataclass_generator_json_wizard.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/model/test_enum_generator.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/model/test_json_value_integration.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/model/test_json_value_wrapper.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/test_client_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/test_model_visitor.py +0 -0
- {pyopenapi_gen-0.20.0 → pyopenapi_gen-0.20.1}/tests/visit/test_visitor.py +0 -0
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.20.1 (2025-10-21)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- **codegen**: Resolve method naming and file handling in overloaded endpoints
|
|
9
|
+
([`190e581`](https://github.com/mindhiveoy/pyopenapi_gen/commit/190e5819e99edf37d14722b075069851d03c4c3b))
|
|
10
|
+
|
|
11
|
+
This commit fixes two critical issues in code generation for operations with multiple content types
|
|
12
|
+
(overloaded methods):
|
|
13
|
+
|
|
14
|
+
1. **Method Naming**: Overloaded methods were using camelCase from OpenAPI operationId instead of
|
|
15
|
+
converting to Python's snake_case convention. - Fixed: Added NameSanitizer.sanitize_method_name()
|
|
16
|
+
in overload_generator.py - Example: updateDocument -> update_document
|
|
17
|
+
|
|
18
|
+
2. **File Upload Handling**: Multipart/form-data file uploads were incorrectly being passed through
|
|
19
|
+
DataclassSerializer.serialize(), which is designed for dataclass-to-dict conversion, not file I/O.
|
|
20
|
+
- Fixed: Pass file dict directly to httpx transport in endpoint_method_generator.py - Rationale:
|
|
21
|
+
httpx expects raw IO objects, not serialized data
|
|
22
|
+
|
|
23
|
+
Both issues only affected operations with multiple content types (JSON + multipart). Standard
|
|
24
|
+
single-content-type operations were unaffected.
|
|
25
|
+
|
|
26
|
+
Changes: - src/pyopenapi_gen/visit/endpoint/generators/overload_generator.py: Added NameSanitizer
|
|
27
|
+
import and method name sanitisation in two locations (overload signatures and implementation
|
|
28
|
+
signatures)
|
|
29
|
+
|
|
30
|
+
- src/pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py: Removed
|
|
31
|
+
DataclassSerializer.serialize() for file parameters in multipart handling, passing files directly
|
|
32
|
+
to transport
|
|
33
|
+
|
|
34
|
+
- tests/visit/endpoint/generators/test_overload_generator.py: Added unit tests for snake_case
|
|
35
|
+
conversion in overload and implementation signatures
|
|
36
|
+
|
|
37
|
+
- tests/visit/endpoint/generators/test_endpoint_method_generator.py: Added test for file handling
|
|
38
|
+
without serialisation
|
|
39
|
+
|
|
40
|
+
- tests/generation_issues/test_overload_naming_issues.py: Added integration tests verifying both
|
|
41
|
+
fixes in full code generation pipeline
|
|
42
|
+
|
|
43
|
+
All tests pass (1348 tests) with full quality checks (format, lint, typecheck, security).
|
|
44
|
+
|
|
45
|
+
### Chores
|
|
46
|
+
|
|
47
|
+
- **release**: Sync __init__.py version [skip ci]
|
|
48
|
+
([`8047e53`](https://github.com/mindhiveoy/pyopenapi_gen/commit/8047e53df11d8985d95f89dbf3b36046af1e6f1a))
|
|
49
|
+
|
|
50
|
+
|
|
4
51
|
## v0.20.0 (2025-10-19)
|
|
5
52
|
|
|
6
53
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyopenapi-gen
|
|
3
|
-
Version: 0.20.
|
|
3
|
+
Version: 0.20.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="1761058806878" lines-valid="6507" lines-covered="5752" line-rate="0.884" 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>
|
|
@@ -6008,7 +6008,7 @@
|
|
|
6008
6008
|
</class>
|
|
6009
6009
|
</classes>
|
|
6010
6010
|
</package>
|
|
6011
|
-
<package name="pyopenapi_gen.visit.endpoint.generators" line-rate="0.
|
|
6011
|
+
<package name="pyopenapi_gen.visit.endpoint.generators" line-rate="0.8884" branch-rate="0" complexity="0">
|
|
6012
6012
|
<classes>
|
|
6013
6013
|
<class name="__init__.py" filename="pyopenapi_gen/visit/endpoint/generators/__init__.py" complexity="0" line-rate="1" branch-rate="0">
|
|
6014
6014
|
<methods/>
|
|
@@ -6085,7 +6085,7 @@
|
|
|
6085
6085
|
<line number="123" hits="1"/>
|
|
6086
6086
|
</lines>
|
|
6087
6087
|
</class>
|
|
6088
|
-
<class name="endpoint_method_generator.py" filename="pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py" complexity="0" line-rate="0.
|
|
6088
|
+
<class name="endpoint_method_generator.py" filename="pyopenapi_gen/visit/endpoint/generators/endpoint_method_generator.py" complexity="0" line-rate="0.9286" branch-rate="0">
|
|
6089
6089
|
<methods/>
|
|
6090
6090
|
<lines>
|
|
6091
6091
|
<line number="1" hits="1"/>
|
|
@@ -6188,7 +6188,6 @@
|
|
|
6188
6188
|
<line number="181" hits="1"/>
|
|
6189
6189
|
<line number="182" hits="1"/>
|
|
6190
6190
|
<line number="183" hits="1"/>
|
|
6191
|
-
<line number="184" hits="1"/>
|
|
6192
6191
|
<line number="185" hits="1"/>
|
|
6193
6192
|
<line number="186" hits="1"/>
|
|
6194
6193
|
<line number="187" hits="1"/>
|
|
@@ -6228,93 +6227,96 @@
|
|
|
6228
6227
|
<line number="10" hits="1"/>
|
|
6229
6228
|
<line number="11" hits="1"/>
|
|
6230
6229
|
<line number="12" hits="1"/>
|
|
6231
|
-
<line number="
|
|
6232
|
-
<line number="
|
|
6233
|
-
<line number="
|
|
6230
|
+
<line number="13" hits="1"/>
|
|
6231
|
+
<line number="15" hits="1"/>
|
|
6232
|
+
<line number="18" hits="1"/>
|
|
6234
6233
|
<line number="27" hits="1"/>
|
|
6235
6234
|
<line number="28" hits="1"/>
|
|
6236
6235
|
<line number="29" hits="1"/>
|
|
6237
6236
|
<line number="30" hits="1"/>
|
|
6238
|
-
<line number="
|
|
6239
|
-
<line number="
|
|
6237
|
+
<line number="31" hits="1"/>
|
|
6238
|
+
<line number="33" hits="1"/>
|
|
6240
6239
|
<line number="43" hits="1"/>
|
|
6241
6240
|
<line number="44" hits="1"/>
|
|
6242
|
-
<line number="
|
|
6243
|
-
<line number="
|
|
6241
|
+
<line number="45" hits="1"/>
|
|
6242
|
+
<line number="47" hits="1"/>
|
|
6244
6243
|
<line number="61" hits="1"/>
|
|
6245
|
-
<line number="
|
|
6244
|
+
<line number="62" hits="1"/>
|
|
6246
6245
|
<line number="65" hits="1"/>
|
|
6247
6246
|
<line number="66" hits="1"/>
|
|
6248
6247
|
<line number="67" hits="1"/>
|
|
6249
|
-
<line number="
|
|
6250
|
-
<line number="
|
|
6251
|
-
<line number="
|
|
6248
|
+
<line number="68" hits="1"/>
|
|
6249
|
+
<line number="70" hits="1"/>
|
|
6250
|
+
<line number="73" hits="1"/>
|
|
6252
6251
|
<line number="77" hits="1"/>
|
|
6253
6252
|
<line number="78" hits="1"/>
|
|
6254
|
-
<line number="
|
|
6255
|
-
<line number="
|
|
6256
|
-
<line number="
|
|
6257
|
-
<line number="
|
|
6258
|
-
<line number="
|
|
6259
|
-
<line number="
|
|
6260
|
-
<line number="
|
|
6253
|
+
<line number="79" hits="1"/>
|
|
6254
|
+
<line number="81" hits="1"/>
|
|
6255
|
+
<line number="83" hits="1"/>
|
|
6256
|
+
<line number="104" hits="1"/>
|
|
6257
|
+
<line number="107" hits="1"/>
|
|
6258
|
+
<line number="110" hits="1"/>
|
|
6259
|
+
<line number="113" hits="1"/>
|
|
6261
6260
|
<line number="116" hits="1"/>
|
|
6262
|
-
<line number="
|
|
6263
|
-
<line number="
|
|
6261
|
+
<line number="117" hits="1"/>
|
|
6262
|
+
<line number="119" hits="1"/>
|
|
6264
6263
|
<line number="121" hits="1"/>
|
|
6265
6264
|
<line number="122" hits="1"/>
|
|
6266
6265
|
<line number="123" hits="1"/>
|
|
6267
|
-
<line number="
|
|
6268
|
-
<line number="
|
|
6269
|
-
<line number="
|
|
6270
|
-
<line number="
|
|
6271
|
-
<line number="
|
|
6266
|
+
<line number="124" hits="1"/>
|
|
6267
|
+
<line number="127" hits="1"/>
|
|
6268
|
+
<line number="130" hits="1"/>
|
|
6269
|
+
<line number="133" hits="1"/>
|
|
6270
|
+
<line number="136" hits="1"/>
|
|
6272
6271
|
<line number="139" hits="1"/>
|
|
6273
|
-
<line number="140" hits="1"/>
|
|
6274
|
-
<line number="141" hits="1"/>
|
|
6275
6272
|
<line number="142" hits="1"/>
|
|
6276
6273
|
<line number="143" hits="1"/>
|
|
6274
|
+
<line number="144" hits="1"/>
|
|
6277
6275
|
<line number="145" hits="1"/>
|
|
6276
|
+
<line number="146" hits="1"/>
|
|
6278
6277
|
<line number="147" hits="1"/>
|
|
6279
|
-
<line number="
|
|
6280
|
-
<line number="
|
|
6281
|
-
<line number="
|
|
6282
|
-
<line number="
|
|
6283
|
-
<line number="
|
|
6284
|
-
<line number="
|
|
6278
|
+
<line number="149" hits="1"/>
|
|
6279
|
+
<line number="151" hits="1"/>
|
|
6280
|
+
<line number="163" hits="1"/>
|
|
6281
|
+
<line number="165" hits="1"/>
|
|
6282
|
+
<line number="168" hits="1"/>
|
|
6283
|
+
<line number="170" hits="1"/>
|
|
6285
6284
|
<line number="171" hits="1"/>
|
|
6286
6285
|
<line number="173" hits="1"/>
|
|
6287
6286
|
<line number="175" hits="1"/>
|
|
6287
|
+
<line number="177" hits="1"/>
|
|
6288
6288
|
<line number="179" hits="1"/>
|
|
6289
|
-
<line number="
|
|
6290
|
-
<line number="
|
|
6291
|
-
<line number="
|
|
6292
|
-
<line number="
|
|
6293
|
-
<line number="203" hits="1"/>
|
|
6289
|
+
<line number="183" hits="1"/>
|
|
6290
|
+
<line number="184" hits="1"/>
|
|
6291
|
+
<line number="186" hits="1"/>
|
|
6292
|
+
<line number="201" hits="1"/>
|
|
6294
6293
|
<line number="204" hits="1"/>
|
|
6295
|
-
<line number="
|
|
6294
|
+
<line number="207" hits="1"/>
|
|
6296
6295
|
<line number="208" hits="1"/>
|
|
6297
|
-
<line number="209" hits="1"/>
|
|
6298
6296
|
<line number="210" hits="1"/>
|
|
6299
|
-
<line number="
|
|
6297
|
+
<line number="212" hits="1"/>
|
|
6298
|
+
<line number="213" hits="1"/>
|
|
6300
6299
|
<line number="214" hits="1"/>
|
|
6301
|
-
<line number="
|
|
6300
|
+
<line number="215" hits="1"/>
|
|
6302
6301
|
<line number="218" hits="1"/>
|
|
6303
|
-
<line number="220" hits="1"/>
|
|
6304
6302
|
<line number="221" hits="1"/>
|
|
6303
|
+
<line number="222" hits="1"/>
|
|
6305
6304
|
<line number="224" hits="1"/>
|
|
6306
6305
|
<line number="225" hits="1"/>
|
|
6307
|
-
<line number="
|
|
6308
|
-
<line number="
|
|
6306
|
+
<line number="228" hits="1"/>
|
|
6307
|
+
<line number="229" hits="1"/>
|
|
6309
6308
|
<line number="230" hits="1"/>
|
|
6310
|
-
<line number="
|
|
6311
|
-
<line number="
|
|
6309
|
+
<line number="231" hits="1"/>
|
|
6310
|
+
<line number="234" hits="1"/>
|
|
6312
6311
|
<line number="237" hits="1"/>
|
|
6313
|
-
<line number="238" hits="1"/>
|
|
6314
|
-
<line number="239" hits="1"/>
|
|
6315
6312
|
<line number="240" hits="1"/>
|
|
6316
|
-
<line number="241" hits="1"/>
|
|
6317
6313
|
<line number="243" hits="1"/>
|
|
6314
|
+
<line number="244" hits="1"/>
|
|
6315
|
+
<line number="245" hits="1"/>
|
|
6316
|
+
<line number="246" hits="1"/>
|
|
6317
|
+
<line number="247" hits="1"/>
|
|
6318
|
+
<line number="248" hits="1"/>
|
|
6319
|
+
<line number="250" hits="1"/>
|
|
6318
6320
|
</lines>
|
|
6319
6321
|
</class>
|
|
6320
6322
|
<class name="request_generator.py" filename="pyopenapi_gen/visit/endpoint/generators/request_generator.py" complexity="0" line-rate="0.9535" branch-rate="0">
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyopenapi-gen"
|
|
7
|
-
version = "0.20.
|
|
7
|
+
version = "0.20.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.20.
|
|
143
|
+
version = "0.20.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.20.
|
|
53
|
+
__version__: str = "0.20.1"
|
|
54
54
|
|
|
55
55
|
# ---------------------------------------------------------------------------
|
|
56
56
|
# Lazy-loading and autocompletion support (This part remains)
|
|
@@ -181,12 +181,12 @@ class EndpointMethodGenerator:
|
|
|
181
181
|
writer.dedent()
|
|
182
182
|
writer.write_line(")")
|
|
183
183
|
elif content_type == "multipart/form-data":
|
|
184
|
-
|
|
184
|
+
# Files dict is already in correct format for httpx - pass directly
|
|
185
185
|
writer.write_line("response = await self._transport.request(")
|
|
186
186
|
writer.indent()
|
|
187
187
|
writer.write_line(f'"{op.method.value.upper()}", url,')
|
|
188
188
|
writer.write_line("params=None,")
|
|
189
|
-
writer.write_line("files=
|
|
189
|
+
writer.write_line(f"files={param_info['name']},")
|
|
190
190
|
writer.write_line("headers=None")
|
|
191
191
|
writer.dedent()
|
|
192
192
|
writer.write_line(")")
|
|
@@ -6,6 +6,7 @@ from typing import Any
|
|
|
6
6
|
from pyopenapi_gen import IROperation
|
|
7
7
|
|
|
8
8
|
from ....context.render_context import RenderContext
|
|
9
|
+
from ....core.utils import NameSanitizer
|
|
9
10
|
from ....core.writers.code_writer import CodeWriter
|
|
10
11
|
from ..processors.parameter_processor import EndpointParameterProcessor
|
|
11
12
|
from .docstring_generator import EndpointDocstringGenerator
|
|
@@ -134,9 +135,12 @@ class OverloadMethodGenerator:
|
|
|
134
135
|
# Get return type from response strategy
|
|
135
136
|
return_type = response_strategy.return_type
|
|
136
137
|
|
|
138
|
+
# Sanitize method name to snake_case
|
|
139
|
+
method_name = NameSanitizer.sanitize_method_name(op.operation_id)
|
|
140
|
+
|
|
137
141
|
# Write signature
|
|
138
142
|
params_str = ",\n ".join(param_parts)
|
|
139
|
-
writer.write_line(f"async def {
|
|
143
|
+
writer.write_line(f"async def {method_name}(")
|
|
140
144
|
writer.indent()
|
|
141
145
|
writer.write_line(params_str)
|
|
142
146
|
writer.dedent()
|
|
@@ -232,9 +236,12 @@ class OverloadMethodGenerator:
|
|
|
232
236
|
# Get return type
|
|
233
237
|
return_type = response_strategy.return_type
|
|
234
238
|
|
|
239
|
+
# Sanitize method name to snake_case
|
|
240
|
+
method_name = NameSanitizer.sanitize_method_name(op.operation_id)
|
|
241
|
+
|
|
235
242
|
# Write signature
|
|
236
243
|
params_str = ",\n ".join(param_parts)
|
|
237
|
-
writer.write_line(f"async def {
|
|
244
|
+
writer.write_line(f"async def {method_name}(")
|
|
238
245
|
writer.indent()
|
|
239
246
|
writer.write_line(params_str)
|
|
240
247
|
writer.dedent()
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Integration tests for overload method naming and file handling issues.
|
|
3
|
+
|
|
4
|
+
These tests verify that:
|
|
5
|
+
1. Methods with camelCase operationIds are converted to snake_case
|
|
6
|
+
2. File uploads don't use incorrect DataclassSerializer.serialize()
|
|
7
|
+
3. Multi-content-type operations generate correct code
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import tempfile
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
16
|
+
from pyopenapi_gen.generator.client_generator import ClientGenerator
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.fixture
|
|
20
|
+
def minimal_spec_with_camelcase_operations() -> dict:
|
|
21
|
+
"""Minimal OpenAPI spec with camelCase operation IDs and multi-content types."""
|
|
22
|
+
return {
|
|
23
|
+
"openapi": "3.0.0",
|
|
24
|
+
"info": {"title": "Test API", "version": "1.0.0"},
|
|
25
|
+
"paths": {
|
|
26
|
+
"/documents/{id}": {
|
|
27
|
+
"put": {
|
|
28
|
+
"operationId": "updateDocument", # camelCase
|
|
29
|
+
"summary": "Update a document",
|
|
30
|
+
"tags": ["documents"],
|
|
31
|
+
"parameters": [{"name": "id", "in": "path", "required": True, "schema": {"type": "string"}}],
|
|
32
|
+
"requestBody": {
|
|
33
|
+
"required": True,
|
|
34
|
+
"content": {
|
|
35
|
+
"application/json": {
|
|
36
|
+
"schema": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"properties": {"title": {"type": "string"}},
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"multipart/form-data": {
|
|
42
|
+
"schema": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"properties": {"file": {"type": "string", "format": "binary"}},
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
"responses": {
|
|
50
|
+
"200": {
|
|
51
|
+
"description": "Success",
|
|
52
|
+
"content": {
|
|
53
|
+
"application/json": {
|
|
54
|
+
"schema": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"properties": {"id": {"type": "string"}},
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"/documents": {
|
|
65
|
+
"post": {
|
|
66
|
+
"operationId": "createDocument", # camelCase
|
|
67
|
+
"summary": "Create a document",
|
|
68
|
+
"tags": ["documents"],
|
|
69
|
+
"requestBody": {
|
|
70
|
+
"required": True,
|
|
71
|
+
"content": {
|
|
72
|
+
"application/json": {
|
|
73
|
+
"schema": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {"title": {"type": "string"}},
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"multipart/form-data": {
|
|
79
|
+
"schema": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"properties": {"file": {"type": "string", "format": "binary"}},
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
"responses": {
|
|
87
|
+
"201": {
|
|
88
|
+
"description": "Created",
|
|
89
|
+
"content": {
|
|
90
|
+
"application/json": {
|
|
91
|
+
"schema": {
|
|
92
|
+
"type": "object",
|
|
93
|
+
"properties": {"id": {"type": "string"}},
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class TestOverloadNamingIntegration:
|
|
106
|
+
"""Integration tests for camelCase to snake_case conversion."""
|
|
107
|
+
|
|
108
|
+
def test_generate_client__camelcase_operations__converts_to_snake_case(
|
|
109
|
+
self, minimal_spec_with_camelcase_operations: dict
|
|
110
|
+
) -> None:
|
|
111
|
+
"""
|
|
112
|
+
Scenario: Generate client from spec with camelCase operationIds
|
|
113
|
+
Expected Outcome: Generated methods should be snake_case
|
|
114
|
+
"""
|
|
115
|
+
# Arrange
|
|
116
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
117
|
+
spec_path = Path(tmpdir) / "spec.json"
|
|
118
|
+
with open(spec_path, "w") as f:
|
|
119
|
+
json.dump(minimal_spec_with_camelcase_operations, f)
|
|
120
|
+
|
|
121
|
+
output_path = Path(tmpdir) / "output"
|
|
122
|
+
output_path.mkdir()
|
|
123
|
+
|
|
124
|
+
generator = ClientGenerator()
|
|
125
|
+
|
|
126
|
+
# Act
|
|
127
|
+
generated_files = generator.generate(
|
|
128
|
+
spec_path=str(spec_path),
|
|
129
|
+
project_root=output_path,
|
|
130
|
+
output_package="testapi",
|
|
131
|
+
force=True,
|
|
132
|
+
no_postprocess=True, # Skip formatting for faster test
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Assert
|
|
136
|
+
# Find the generated endpoint file (exclude __init__.py)
|
|
137
|
+
endpoint_files = [
|
|
138
|
+
f for f in generated_files if "endpoints" in str(f) and not str(f).endswith("__init__.py")
|
|
139
|
+
]
|
|
140
|
+
assert len(endpoint_files) > 0, "No endpoint files generated"
|
|
141
|
+
|
|
142
|
+
# Collect all endpoint code
|
|
143
|
+
all_code = ""
|
|
144
|
+
for endpoint_file in endpoint_files:
|
|
145
|
+
with open(endpoint_file, "r") as f:
|
|
146
|
+
all_code += f.read()
|
|
147
|
+
|
|
148
|
+
# Check method names are snake_case
|
|
149
|
+
assert "async def update_document(" in all_code, "updateDocument should be update_document"
|
|
150
|
+
assert "async def create_document(" in all_code, "createDocument should be create_document"
|
|
151
|
+
|
|
152
|
+
# Check they're NOT camelCase
|
|
153
|
+
assert "async def updateDocument(" not in all_code, "Method name should not be camelCase updateDocument"
|
|
154
|
+
assert "async def createDocument(" not in all_code, "Method name should not be camelCase createDocument"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class TestFileHandlingIntegration:
|
|
158
|
+
"""Integration tests for file upload handling."""
|
|
159
|
+
|
|
160
|
+
def test_generate_client__multipart_files__no_serialization(
|
|
161
|
+
self, minimal_spec_with_camelcase_operations: dict
|
|
162
|
+
) -> None:
|
|
163
|
+
"""
|
|
164
|
+
Scenario: Generate client with multipart/form-data operations
|
|
165
|
+
Expected Outcome: Files should be passed directly, not serialized
|
|
166
|
+
"""
|
|
167
|
+
# Arrange
|
|
168
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
169
|
+
spec_path = Path(tmpdir) / "spec.json"
|
|
170
|
+
with open(spec_path, "w") as f:
|
|
171
|
+
json.dump(minimal_spec_with_camelcase_operations, f)
|
|
172
|
+
|
|
173
|
+
output_path = Path(tmpdir) / "output"
|
|
174
|
+
output_path.mkdir()
|
|
175
|
+
|
|
176
|
+
generator = ClientGenerator()
|
|
177
|
+
|
|
178
|
+
# Act
|
|
179
|
+
generated_files = generator.generate(
|
|
180
|
+
spec_path=str(spec_path),
|
|
181
|
+
project_root=output_path,
|
|
182
|
+
output_package="testapi",
|
|
183
|
+
force=True,
|
|
184
|
+
no_postprocess=True,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Assert
|
|
188
|
+
endpoint_files = [f for f in generated_files if "endpoints" in str(f)]
|
|
189
|
+
assert len(endpoint_files) > 0
|
|
190
|
+
|
|
191
|
+
for endpoint_file in endpoint_files:
|
|
192
|
+
with open(endpoint_file, "r") as f:
|
|
193
|
+
code = f.read()
|
|
194
|
+
|
|
195
|
+
# Files should be passed directly
|
|
196
|
+
if "multipart/form-data" in code:
|
|
197
|
+
# Should NOT serialize files
|
|
198
|
+
assert (
|
|
199
|
+
"files_data = DataclassSerializer.serialize(files)" not in code
|
|
200
|
+
), "Files should not be serialized"
|
|
201
|
+
|
|
202
|
+
# Should pass files directly
|
|
203
|
+
assert "files=files," in code or "files = files" in code, "Files should be passed directly"
|
|
@@ -241,3 +241,64 @@ class TestEndpointMethodGenerator:
|
|
|
241
241
|
result_code
|
|
242
242
|
== "def test_op():\n # Docstring here\n # Only comments or whitespace added by helpers\n pass"
|
|
243
243
|
)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class TestGenerateImplementationMethod:
|
|
247
|
+
"""Tests for _generate_implementation_method."""
|
|
248
|
+
|
|
249
|
+
def test_generate_implementation_method__multipart_files__no_serialization(
|
|
250
|
+
self, mock_render_context: RenderContext
|
|
251
|
+
) -> None:
|
|
252
|
+
"""
|
|
253
|
+
Scenario: Generating implementation method for multipart/form-data with files
|
|
254
|
+
Expected Outcome: Files parameter should be passed directly without DataclassSerializer
|
|
255
|
+
"""
|
|
256
|
+
# Arrange
|
|
257
|
+
from pyopenapi_gen import IRRequestBody, IRResponse
|
|
258
|
+
from pyopenapi_gen.ir import IRSchema
|
|
259
|
+
from pyopenapi_gen.types.strategies.response_strategy import ResponseStrategy
|
|
260
|
+
|
|
261
|
+
op = IROperation(
|
|
262
|
+
path="/upload",
|
|
263
|
+
method=HTTPMethod.POST,
|
|
264
|
+
operation_id="uploadFile",
|
|
265
|
+
summary="Upload file",
|
|
266
|
+
description="Upload operation",
|
|
267
|
+
parameters=[],
|
|
268
|
+
request_body=IRRequestBody(
|
|
269
|
+
description="File upload",
|
|
270
|
+
required=True,
|
|
271
|
+
content={
|
|
272
|
+
"application/json": IRSchema(type="object", name="UploadRequest"),
|
|
273
|
+
"multipart/form-data": IRSchema(type="object", name="FileUpload"),
|
|
274
|
+
},
|
|
275
|
+
),
|
|
276
|
+
responses=[
|
|
277
|
+
IRResponse(
|
|
278
|
+
status_code="201", description="Created", content={"application/json": IRSchema(type="object")}
|
|
279
|
+
)
|
|
280
|
+
],
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
response_ir = IRResponse(
|
|
284
|
+
status_code="201", description="Created", content={"application/json": IRSchema(type="object")}
|
|
285
|
+
)
|
|
286
|
+
response_strategy = ResponseStrategy(
|
|
287
|
+
return_type="UploadResponse",
|
|
288
|
+
response_schema=IRSchema(type="object", name="UploadResponse"),
|
|
289
|
+
is_streaming=False,
|
|
290
|
+
response_ir=response_ir,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
generator = EndpointMethodGenerator(schemas={})
|
|
294
|
+
|
|
295
|
+
# Act
|
|
296
|
+
result = generator._generate_implementation_method(op, mock_render_context, response_strategy)
|
|
297
|
+
|
|
298
|
+
# Assert - Files should be passed directly, NOT serialized
|
|
299
|
+
# The implementation should contain: files=files (not files_data=DataclassSerializer.serialize(files))
|
|
300
|
+
assert "files=files," in result or "files={param_info['name']}" in result
|
|
301
|
+
# Should NOT contain serialization of files
|
|
302
|
+
assert "DataclassSerializer.serialize(files)" not in result
|
|
303
|
+
# The variable assignment should be for json_body, not files_data
|
|
304
|
+
assert "files_data" not in result or "files_data = files" in result
|