@typespec/http-client-python 0.1.0
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.
- package/README.md +118 -0
- package/dist/emitter/code-model.d.ts +4 -0
- package/dist/emitter/code-model.d.ts.map +1 -0
- package/dist/emitter/code-model.js +195 -0
- package/dist/emitter/code-model.js.map +1 -0
- package/dist/emitter/emitter.d.ts +6 -0
- package/dist/emitter/emitter.d.ts.map +1 -0
- package/dist/emitter/emitter.js +104 -0
- package/dist/emitter/emitter.js.map +1 -0
- package/dist/emitter/external-process.d.ts +20 -0
- package/dist/emitter/external-process.d.ts.map +1 -0
- package/dist/emitter/external-process.js +44 -0
- package/dist/emitter/external-process.js.map +1 -0
- package/dist/emitter/http.d.ts +7 -0
- package/dist/emitter/http.d.ts.map +1 -0
- package/dist/emitter/http.js +268 -0
- package/dist/emitter/http.js.map +1 -0
- package/dist/emitter/index.d.ts +3 -0
- package/dist/emitter/index.d.ts.map +1 -0
- package/dist/emitter/index.js +3 -0
- package/dist/emitter/index.js.map +1 -0
- package/dist/emitter/lib.d.ts +30 -0
- package/dist/emitter/lib.d.ts.map +1 -0
- package/dist/emitter/lib.js +33 -0
- package/dist/emitter/lib.js.map +1 -0
- package/dist/emitter/types.d.ts +36 -0
- package/dist/emitter/types.d.ts.map +1 -0
- package/dist/emitter/types.js +491 -0
- package/dist/emitter/types.js.map +1 -0
- package/dist/emitter/utils.d.ts +26 -0
- package/dist/emitter/utils.d.ts.map +1 -0
- package/dist/emitter/utils.js +155 -0
- package/dist/emitter/utils.js.map +1 -0
- package/emitter/src/code-model.ts +272 -0
- package/emitter/src/emitter.ts +127 -0
- package/emitter/src/external-process.ts +52 -0
- package/emitter/src/http.ts +382 -0
- package/emitter/src/index.ts +2 -0
- package/emitter/src/lib.ts +59 -0
- package/emitter/src/types.ts +573 -0
- package/emitter/src/utils.ts +215 -0
- package/emitter/temp/tsconfig.tsbuildinfo +1 -0
- package/emitter/test/utils.test.ts +22 -0
- package/emitter/tsconfig.build.json +11 -0
- package/emitter/tsconfig.json +7 -0
- package/emitter/vitest.config.ts +4 -0
- package/eng/scripts/Build-Packages.ps1 +86 -0
- package/eng/scripts/Check-GitChanges.ps1 +22 -0
- package/eng/scripts/Functions.ps1 +26 -0
- package/eng/scripts/Generate.ps1 +11 -0
- package/eng/scripts/Generation.psm1 +22 -0
- package/eng/scripts/Initialize-Repository.ps1 +40 -0
- package/eng/scripts/Test-Packages.ps1 +65 -0
- package/eng/scripts/ci/format.ts +3 -0
- package/eng/scripts/ci/lint.ts +39 -0
- package/eng/scripts/ci/mypy.ini +38 -0
- package/eng/scripts/ci/pylintrc +59 -0
- package/eng/scripts/ci/pyproject.toml +18 -0
- package/eng/scripts/ci/pyrightconfig.json +6 -0
- package/eng/scripts/ci/regenerate.ts +299 -0
- package/eng/scripts/ci/run-ci.ts +88 -0
- package/eng/scripts/ci/run_apiview.py +40 -0
- package/eng/scripts/ci/run_mypy.py +49 -0
- package/eng/scripts/ci/run_pylint.py +50 -0
- package/eng/scripts/ci/run_pyright.py +58 -0
- package/eng/scripts/ci/util.py +72 -0
- package/eng/scripts/ci/utils.ts +48 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
- package/eng/scripts/setup/install.py +53 -0
- package/eng/scripts/setup/prepare.py +42 -0
- package/eng/scripts/setup/run-python3.ts +25 -0
- package/eng/scripts/setup/run_tsp.py +42 -0
- package/eng/scripts/setup/system-requirements.ts +261 -0
- package/eng/scripts/setup/venvtools.py +87 -0
- package/generator/LICENSE +21 -0
- package/generator/README.md +1 -0
- package/generator/dev_requirements.txt +13 -0
- package/generator/pygen/__init__.py +107 -0
- package/generator/pygen/_version.py +7 -0
- package/generator/pygen/black.py +71 -0
- package/generator/pygen/codegen/__init__.py +338 -0
- package/generator/pygen/codegen/_utils.py +17 -0
- package/generator/pygen/codegen/models/__init__.py +204 -0
- package/generator/pygen/codegen/models/base.py +186 -0
- package/generator/pygen/codegen/models/base_builder.py +118 -0
- package/generator/pygen/codegen/models/client.py +433 -0
- package/generator/pygen/codegen/models/code_model.py +237 -0
- package/generator/pygen/codegen/models/combined_type.py +149 -0
- package/generator/pygen/codegen/models/constant_type.py +129 -0
- package/generator/pygen/codegen/models/credential_types.py +214 -0
- package/generator/pygen/codegen/models/dictionary_type.py +127 -0
- package/generator/pygen/codegen/models/enum_type.py +238 -0
- package/generator/pygen/codegen/models/imports.py +291 -0
- package/generator/pygen/codegen/models/list_type.py +143 -0
- package/generator/pygen/codegen/models/lro_operation.py +142 -0
- package/generator/pygen/codegen/models/lro_paging_operation.py +32 -0
- package/generator/pygen/codegen/models/model_type.py +359 -0
- package/generator/pygen/codegen/models/operation.py +530 -0
- package/generator/pygen/codegen/models/operation_group.py +184 -0
- package/generator/pygen/codegen/models/paging_operation.py +155 -0
- package/generator/pygen/codegen/models/parameter.py +412 -0
- package/generator/pygen/codegen/models/parameter_list.py +387 -0
- package/generator/pygen/codegen/models/primitive_types.py +659 -0
- package/generator/pygen/codegen/models/property.py +170 -0
- package/generator/pygen/codegen/models/request_builder.py +189 -0
- package/generator/pygen/codegen/models/request_builder_parameter.py +115 -0
- package/generator/pygen/codegen/models/response.py +348 -0
- package/generator/pygen/codegen/models/utils.py +21 -0
- package/generator/pygen/codegen/serializers/__init__.py +574 -0
- package/generator/pygen/codegen/serializers/base_serializer.py +21 -0
- package/generator/pygen/codegen/serializers/builder_serializer.py +1507 -0
- package/generator/pygen/codegen/serializers/client_serializer.py +294 -0
- package/generator/pygen/codegen/serializers/enum_serializer.py +15 -0
- package/generator/pygen/codegen/serializers/general_serializer.py +213 -0
- package/generator/pygen/codegen/serializers/import_serializer.py +126 -0
- package/generator/pygen/codegen/serializers/metadata_serializer.py +198 -0
- package/generator/pygen/codegen/serializers/model_init_serializer.py +33 -0
- package/generator/pygen/codegen/serializers/model_serializer.py +317 -0
- package/generator/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
- package/generator/pygen/codegen/serializers/operations_init_serializer.py +44 -0
- package/generator/pygen/codegen/serializers/parameter_serializer.py +221 -0
- package/generator/pygen/codegen/serializers/patch_serializer.py +19 -0
- package/generator/pygen/codegen/serializers/request_builders_serializer.py +52 -0
- package/generator/pygen/codegen/serializers/sample_serializer.py +168 -0
- package/generator/pygen/codegen/serializers/test_serializer.py +292 -0
- package/generator/pygen/codegen/serializers/types_serializer.py +31 -0
- package/generator/pygen/codegen/serializers/utils.py +68 -0
- package/generator/pygen/codegen/templates/client.py.jinja2 +37 -0
- package/generator/pygen/codegen/templates/client_container.py.jinja2 +12 -0
- package/generator/pygen/codegen/templates/config.py.jinja2 +73 -0
- package/generator/pygen/codegen/templates/config_container.py.jinja2 +16 -0
- package/generator/pygen/codegen/templates/conftest.py.jinja2 +28 -0
- package/generator/pygen/codegen/templates/enum.py.jinja2 +13 -0
- package/generator/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
- package/generator/pygen/codegen/templates/init.py.jinja2 +24 -0
- package/generator/pygen/codegen/templates/keywords.jinja2 +19 -0
- package/generator/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
- package/generator/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
- package/generator/pygen/codegen/templates/macros.jinja2 +12 -0
- package/generator/pygen/codegen/templates/metadata.json.jinja2 +167 -0
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +1157 -0
- package/generator/pygen/codegen/templates/model_container.py.jinja2 +12 -0
- package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +97 -0
- package/generator/pygen/codegen/templates/model_init.py.jinja2 +28 -0
- package/generator/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
- package/generator/pygen/codegen/templates/operation.py.jinja2 +21 -0
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
- package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +19 -0
- package/generator/pygen/codegen/templates/operation_tools.jinja2 +81 -0
- package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
- package/generator/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
- package/generator/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
- package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
- package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
- package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
- package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
- package/generator/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
- package/generator/pygen/codegen/templates/patch.py.jinja2 +19 -0
- package/generator/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
- package/generator/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
- package/generator/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
- package/generator/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
- package/generator/pygen/codegen/templates/sample.py.jinja2 +44 -0
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +2114 -0
- package/generator/pygen/codegen/templates/test.py.jinja2 +50 -0
- package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
- package/generator/pygen/codegen/templates/types.py.jinja2 +7 -0
- package/generator/pygen/codegen/templates/validation.py.jinja2 +38 -0
- package/generator/pygen/codegen/templates/vendor.py.jinja2 +95 -0
- package/generator/pygen/codegen/templates/version.py.jinja2 +4 -0
- package/generator/pygen/m2r.py +65 -0
- package/generator/pygen/postprocess/__init__.py +183 -0
- package/generator/pygen/postprocess/get_all.py +19 -0
- package/generator/pygen/postprocess/venvtools.py +75 -0
- package/generator/pygen/preprocess/__init__.py +515 -0
- package/generator/pygen/preprocess/helpers.py +27 -0
- package/generator/pygen/preprocess/python_mappings.py +224 -0
- package/generator/pygen/utils.py +163 -0
- package/generator/pygen.egg-info/PKG-INFO +25 -0
- package/generator/pygen.egg-info/SOURCES.txt +66 -0
- package/generator/pygen.egg-info/dependency_links.txt +1 -0
- package/generator/pygen.egg-info/requires.txt +4 -0
- package/generator/pygen.egg-info/top_level.txt +1 -0
- package/generator/requirements.txt +12 -0
- package/generator/setup.py +55 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_models_common_types_managed_identity_async.py +63 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_models_resource_async.py +284 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py +101 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +93 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_usage_async.py +31 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_basic_async.py +76 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py +22 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_standard_async.py +39 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_model_async.py +33 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_page_async.py +58 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_scalar_async.py +41 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_traits_async.py +87 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_example_basic_async.py +30 -0
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_special_headers_client_request_id_async.py +30 -0
- package/generator/test/azure/mock_api_tests/conftest.py +150 -0
- package/generator/test/azure/mock_api_tests/test_azure_arm_models_common_types_managed_identity.py +60 -0
- package/generator/test/azure/mock_api_tests/test_azure_arm_models_resource.py +254 -0
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_access.py +92 -0
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +84 -0
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_usage.py +28 -0
- package/generator/test/azure/mock_api_tests/test_azure_core_basic.py +70 -0
- package/generator/test/azure/mock_api_tests/test_azure_core_lro_rpc.py +20 -0
- package/generator/test/azure/mock_api_tests/test_azure_core_lro_standard.py +32 -0
- package/generator/test/azure/mock_api_tests/test_azure_core_model.py +30 -0
- package/generator/test/azure/mock_api_tests/test_azure_core_page.py +51 -0
- package/generator/test/azure/mock_api_tests/test_azure_core_scalar.py +35 -0
- package/generator/test/azure/mock_api_tests/test_azure_core_traits.py +85 -0
- package/generator/test/azure/mock_api_tests/test_azure_example_basic.py +29 -0
- package/generator/test/azure/mock_api_tests/test_azure_special_headers_client_request_id.py +29 -0
- package/generator/test/azure/requirements.txt +89 -0
- package/generator/test/azure/tox.ini +56 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_authentication_async.py +121 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_client_naming_async.py +69 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_client_structure_async.py +62 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py +133 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_datetime_async.py +127 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_duration_async.py +63 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_numeric_async.py +35 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_headasboolean_async.py +35 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_basic_async.py +24 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_body_optionality_async.py +30 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_collection_format_async.py +44 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_spread_async.py +76 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_content_negotiation_async.py +37 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py +98 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_media_type_async.py +27 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_multipart_async.py +153 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py +19 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py +103 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_resiliency_srv_driven_async.py +128 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_routes_async.py +331 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py +24 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_server_endpoint_not_defined_async.py +18 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_server_path_multiple_async.py +25 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_server_path_single_async.py +18 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_server_versions_not_versioned_async.py +28 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_server_versions_versioned_async.py +34 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_special_headers_conditional_request_async.py +38 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_special_headers_repeatability_async.py +19 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_special_words_async.py +42 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_array_async.py +118 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_dictionary_async.py +98 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_extensible_async.py +25 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_fixed_async.py +27 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_empty_async.py +32 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py +70 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py +85 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_not_discriminated_async.py +34 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_recursive_async.py +34 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_single_discriminator_async.py +67 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_usage_async.py +32 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_visibility_async.py +47 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_additionalproperties_async.py +352 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py +110 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_optional_async.py +197 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_valuetypes_async.py +315 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_scalar_async.py +60 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_union_async.py +90 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_added_async.py +36 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_made_optional_async.py +21 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_removed_async.py +21 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_renamed_from_async.py +29 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_return_type_changed_from_async.py +18 -0
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_type_changed_from_async.py +22 -0
- package/generator/test/generic_mock_api_tests/conftest.py +113 -0
- package/generator/test/generic_mock_api_tests/data/image.jpg +0 -0
- package/generator/test/generic_mock_api_tests/data/image.png +0 -0
- package/generator/test/generic_mock_api_tests/test_authentication.py +113 -0
- package/generator/test/generic_mock_api_tests/test_client_naming.py +57 -0
- package/generator/test/generic_mock_api_tests/test_client_structure.py +57 -0
- package/generator/test/generic_mock_api_tests/test_encode_bytes.py +128 -0
- package/generator/test/generic_mock_api_tests/test_encode_datetime.py +123 -0
- package/generator/test/generic_mock_api_tests/test_encode_duration.py +60 -0
- package/generator/test/generic_mock_api_tests/test_encode_numeric.py +31 -0
- package/generator/test/generic_mock_api_tests/test_headasboolean.py +33 -0
- package/generator/test/generic_mock_api_tests/test_parameters_basic.py +22 -0
- package/generator/test/generic_mock_api_tests/test_parameters_body_optionality.py +27 -0
- package/generator/test/generic_mock_api_tests/test_parameters_collection_format.py +37 -0
- package/generator/test/generic_mock_api_tests/test_parameters_spread.py +66 -0
- package/generator/test/generic_mock_api_tests/test_payload_content_negotiation.py +33 -0
- package/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py +93 -0
- package/generator/test/generic_mock_api_tests/test_payload_media_type.py +25 -0
- package/generator/test/generic_mock_api_tests/test_payload_multipart.py +140 -0
- package/generator/test/generic_mock_api_tests/test_payload_pageable.py +18 -0
- package/generator/test/generic_mock_api_tests/test_payload_xml.py +93 -0
- package/generator/test/generic_mock_api_tests/test_resiliency_srv_driven.py +122 -0
- package/generator/test/generic_mock_api_tests/test_routes.py +285 -0
- package/generator/test/generic_mock_api_tests/test_serialization_encoded_name_json.py +21 -0
- package/generator/test/generic_mock_api_tests/test_server_endpoint_not_defined.py +17 -0
- package/generator/test/generic_mock_api_tests/test_server_path_multiple.py +21 -0
- package/generator/test/generic_mock_api_tests/test_server_path_single.py +17 -0
- package/generator/test/generic_mock_api_tests/test_server_versions_not_versioned.py +25 -0
- package/generator/test/generic_mock_api_tests/test_server_versions_versioned.py +30 -0
- package/generator/test/generic_mock_api_tests/test_special_headers_conditional_request.py +34 -0
- package/generator/test/generic_mock_api_tests/test_special_headers_repeatability.py +18 -0
- package/generator/test/generic_mock_api_tests/test_special_words.py +37 -0
- package/generator/test/generic_mock_api_tests/test_typetest_array.py +103 -0
- package/generator/test/generic_mock_api_tests/test_typetest_dictionary.py +86 -0
- package/generator/test/generic_mock_api_tests/test_typetest_enum_extensible.py +23 -0
- package/generator/test/generic_mock_api_tests/test_typetest_enum_fixed.py +25 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_empty.py +29 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_enum_discriminator.py +58 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_nested_discriminator.py +79 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_not_discriminated.py +31 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_recursive.py +32 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_single_discriminator.py +60 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_usage.py +28 -0
- package/generator/test/generic_mock_api_tests/test_typetest_model_visibility.py +40 -0
- package/generator/test/generic_mock_api_tests/test_typetest_property_additionalproperties.py +313 -0
- package/generator/test/generic_mock_api_tests/test_typetest_property_nullable.py +102 -0
- package/generator/test/generic_mock_api_tests/test_typetest_property_optional.py +174 -0
- package/generator/test/generic_mock_api_tests/test_typetest_property_valuetypes.py +286 -0
- package/generator/test/generic_mock_api_tests/test_typetest_scalar.py +53 -0
- package/generator/test/generic_mock_api_tests/test_typetest_union.py +80 -0
- package/generator/test/generic_mock_api_tests/test_versioning_added.py +33 -0
- package/generator/test/generic_mock_api_tests/test_versioning_made_optional.py +20 -0
- package/generator/test/generic_mock_api_tests/test_versioning_removed.py +20 -0
- package/generator/test/generic_mock_api_tests/test_versioning_renamed_from.py +27 -0
- package/generator/test/generic_mock_api_tests/test_versioning_return_type_changed_from.py +17 -0
- package/generator/test/generic_mock_api_tests/test_versioning_type_changed_from.py +21 -0
- package/generator/test/generic_mock_api_tests/unittests/test_model_base_serialization.py +4067 -0
- package/generator/test/generic_mock_api_tests/unittests/test_model_base_xml_serialization.py +1001 -0
- package/generator/test/unbranded/mock_api_tests/asynctests/test_unbranded_async.py +24 -0
- package/generator/test/unbranded/mock_api_tests/cadl-ranch-config.yaml +27 -0
- package/generator/test/unbranded/mock_api_tests/conftest.py +35 -0
- package/generator/test/unbranded/mock_api_tests/test_unbranded.py +57 -0
- package/generator/test/unbranded/requirements.txt +72 -0
- package/generator/test/unbranded/tox.ini +56 -0
- package/package.json +93 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{% set prefix_lower = test.prefix|lower %}
|
|
2
|
+
{% set client_var = "self.client" if code_model.options["azure_arm"] else "client" %}
|
|
3
|
+
{% set async = "async " if test.is_async else "" %}
|
|
4
|
+
{% set async_suffix = "_async" if test.is_async else "" %}
|
|
5
|
+
# coding=utf-8
|
|
6
|
+
{{ code_model.options['license_header'] }}
|
|
7
|
+
import pytest
|
|
8
|
+
{{ imports }}
|
|
9
|
+
|
|
10
|
+
{% if code_model.options["azure_arm"] %}
|
|
11
|
+
AZURE_LOCATION = "eastus"
|
|
12
|
+
{% endif %}
|
|
13
|
+
|
|
14
|
+
@pytest.mark.skip("you may need to update the auto-generated test case before run it")
|
|
15
|
+
class {{ test.test_class_name }}({{ test.base_test_class_name }}):
|
|
16
|
+
{% if code_model.options["azure_arm"] %}
|
|
17
|
+
def setup_method(self, method):
|
|
18
|
+
{% if test.is_async %}
|
|
19
|
+
self.client = self.create_mgmt_client({{ test.client_name }}, is_async=True)
|
|
20
|
+
{% else %}
|
|
21
|
+
self.client = self.create_mgmt_client({{ test.client_name }})
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% endif %}
|
|
24
|
+
{% for testcase in test.testcases %}
|
|
25
|
+
{% if code_model.options["azure_arm"] %}
|
|
26
|
+
@{{ test.preparer_name }}(location=AZURE_LOCATION)
|
|
27
|
+
{% else %}
|
|
28
|
+
@{{ test.preparer_name }}()
|
|
29
|
+
{% endif %}
|
|
30
|
+
@recorded_by_proxy{{ async_suffix }}
|
|
31
|
+
{% if code_model.options["azure_arm"] %}
|
|
32
|
+
{{ async }}def test_{{ testcase.name }}(self, resource_group):
|
|
33
|
+
{% else %}
|
|
34
|
+
{{ async }}def test_{{ testcase.name }}(self, {{ prefix_lower }}_endpoint):
|
|
35
|
+
{{ client_var }} = self.{{ test.create_client_name }}(endpoint={{ prefix_lower }}_endpoint)
|
|
36
|
+
{% endif %}
|
|
37
|
+
{{testcase.response }}{{ client_var }}{{ testcase.operation_group_prefix }}.{{ testcase.operation.name }}(
|
|
38
|
+
{% for key, value in testcase.params.items() %}
|
|
39
|
+
{% if code_model.options["azure_arm"] and key == "resource_group_name" %}
|
|
40
|
+
{{ key }}=resource_group.name,
|
|
41
|
+
{% else %}
|
|
42
|
+
{{ key }}={{ value|indent(12) }},
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% endfor %}
|
|
45
|
+
){{ testcase.operation_suffix }}
|
|
46
|
+
{{ testcase.extra_operation }}
|
|
47
|
+
# please add some check logic here by yourself
|
|
48
|
+
# ...
|
|
49
|
+
|
|
50
|
+
{% endfor %}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
{{ code_model.options['license_header'] }}
|
|
3
|
+
{{ imports }}
|
|
4
|
+
|
|
5
|
+
{% for test_name in test_names %}
|
|
6
|
+
{% set extra_async = ", is_async=True" if test_name.is_async else ""%}
|
|
7
|
+
{% set prefix_lower = test_name.prefix|lower %}
|
|
8
|
+
class {{ test_name.base_test_class_name }}(AzureRecordedTestCase):
|
|
9
|
+
|
|
10
|
+
def {{ test_name.create_client_name }}(self, endpoint):
|
|
11
|
+
credential = self.get_credential({{ test_name.client_name }}{{ extra_async }})
|
|
12
|
+
return self.create_client_from_credential(
|
|
13
|
+
{{ test_name.client_name }},
|
|
14
|
+
credential=credential,
|
|
15
|
+
endpoint=endpoint,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
{% if not test_name.is_async %}
|
|
19
|
+
{{ test_name.preparer_name }} = functools.partial(
|
|
20
|
+
PowerShellPreparer,
|
|
21
|
+
"{{ prefix_lower }}",
|
|
22
|
+
{{ prefix_lower }}_endpoint="https://fake_{{ prefix_lower }}_endpoint.com"
|
|
23
|
+
)
|
|
24
|
+
{% endif %}
|
|
25
|
+
|
|
26
|
+
{% endfor %}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{{ code_model.options['license_header'] }}
|
|
2
|
+
import functools
|
|
3
|
+
|
|
4
|
+
def api_version_validation(**kwargs):
|
|
5
|
+
params_added_on = kwargs.pop("params_added_on", {})
|
|
6
|
+
method_added_on = kwargs.pop("method_added_on", "")
|
|
7
|
+
|
|
8
|
+
def decorator(func):
|
|
9
|
+
@functools.wraps(func)
|
|
10
|
+
def wrapper(*args, **kwargs):
|
|
11
|
+
try:
|
|
12
|
+
# this assumes the client has an _api_version attribute
|
|
13
|
+
client = args[0]
|
|
14
|
+
client_api_version = client._config.api_version # pylint: disable=protected-access
|
|
15
|
+
except AttributeError:
|
|
16
|
+
return func(*args, **kwargs)
|
|
17
|
+
|
|
18
|
+
if method_added_on > client_api_version:
|
|
19
|
+
raise ValueError(
|
|
20
|
+
f"'{func.__name__}' is not available in API version "
|
|
21
|
+
f"{client_api_version}. Pass service API version {method_added_on} or newer to your client."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
unsupported = {
|
|
25
|
+
parameter: api_version
|
|
26
|
+
for api_version, parameters in params_added_on.items()
|
|
27
|
+
for parameter in parameters
|
|
28
|
+
if parameter in kwargs and api_version > client_api_version
|
|
29
|
+
}
|
|
30
|
+
if unsupported:
|
|
31
|
+
raise ValueError("".join([
|
|
32
|
+
f"'{param}' is not available in API version {client_api_version}. "
|
|
33
|
+
f"Use service API version {version} or newer.\n"
|
|
34
|
+
for param, version in unsupported.items()
|
|
35
|
+
]))
|
|
36
|
+
return func(*args, **kwargs)
|
|
37
|
+
return wrapper
|
|
38
|
+
return decorator
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{% import 'keywords.jinja2' as keywords with context %}
|
|
2
|
+
{{ code_model.options['license_header'] }}
|
|
3
|
+
|
|
4
|
+
{{ imports }}
|
|
5
|
+
|
|
6
|
+
{% if code_model.need_mixin_abc %}
|
|
7
|
+
{% for client in clients | selectattr("has_mixin") %}
|
|
8
|
+
class {{ client.name }}MixinABC(
|
|
9
|
+
ABC
|
|
10
|
+
):
|
|
11
|
+
"""DO NOT use this class. It is for internal typing use only."""
|
|
12
|
+
_client: "{{ keywords.async_class }}PipelineClient"
|
|
13
|
+
_config: {{ client.name }}Configuration
|
|
14
|
+
_serialize: "Serializer"
|
|
15
|
+
_deserialize: "Deserializer"
|
|
16
|
+
{% endfor %}
|
|
17
|
+
{% endif %}
|
|
18
|
+
{% if code_model.has_abstract_operations %}
|
|
19
|
+
|
|
20
|
+
def raise_if_not_implemented(cls, abstract_methods):
|
|
21
|
+
not_implemented = [f for f in abstract_methods if not callable(getattr(cls, f, None))]
|
|
22
|
+
if not_implemented:
|
|
23
|
+
raise NotImplementedError("The following methods on operation group '{}' are not implemented: '{}'."
|
|
24
|
+
" Please refer to https://aka.ms/azsdk/python/dpcodegen/python/customize to learn how to customize.".format(
|
|
25
|
+
cls.__name__, '\', \''.join(not_implemented))
|
|
26
|
+
)
|
|
27
|
+
{% endif %}
|
|
28
|
+
|
|
29
|
+
{% if code_model.has_etag %}
|
|
30
|
+
def quote_etag(etag: Optional[str]) -> Optional[str]:
|
|
31
|
+
if not etag or etag == "*":
|
|
32
|
+
return etag
|
|
33
|
+
if etag.startswith("W/"):
|
|
34
|
+
return etag
|
|
35
|
+
if etag.startswith('"') and etag.endswith('"'):
|
|
36
|
+
return etag
|
|
37
|
+
if etag.startswith("'") and etag.endswith("'"):
|
|
38
|
+
return etag
|
|
39
|
+
return '"' + etag + '"'
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def prep_if_match(etag: Optional[str], match_condition: Optional[MatchConditions]) -> Optional[str]:
|
|
43
|
+
if match_condition == MatchConditions.IfNotModified:
|
|
44
|
+
if_match = quote_etag(etag) if etag else None
|
|
45
|
+
return if_match
|
|
46
|
+
if match_condition == MatchConditions.IfPresent:
|
|
47
|
+
return "*"
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def prep_if_none_match(etag: Optional[str], match_condition: Optional[MatchConditions]) -> Optional[str]:
|
|
52
|
+
if match_condition == MatchConditions.IfModified:
|
|
53
|
+
if_none_match = quote_etag(etag) if etag else None
|
|
54
|
+
return if_none_match
|
|
55
|
+
if match_condition == MatchConditions.IfMissing:
|
|
56
|
+
return "*"
|
|
57
|
+
return None
|
|
58
|
+
{% endif %}
|
|
59
|
+
{% if code_model.has_form_data and code_model.options["models_mode"] == "dpg" and not async_mode %}
|
|
60
|
+
# file-like tuple could be `(filename, IO (or bytes))` or `(filename, IO (or bytes), content_type)`
|
|
61
|
+
FileContent = Union[str, bytes, IO[str], IO[bytes]]
|
|
62
|
+
|
|
63
|
+
FileType = Union[
|
|
64
|
+
# file (or bytes)
|
|
65
|
+
FileContent,
|
|
66
|
+
# (filename, file (or bytes))
|
|
67
|
+
Tuple[Optional[str], FileContent],
|
|
68
|
+
# (filename, file (or bytes), content_type)
|
|
69
|
+
Tuple[Optional[str], FileContent, Optional[str]],
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
def serialize_multipart_data_entry(data_entry: Any) -> Any:
|
|
73
|
+
if isinstance(data_entry, (list, tuple, dict, Model)):
|
|
74
|
+
return json.dumps(data_entry, cls=SdkJSONEncoder, exclude_readonly=True)
|
|
75
|
+
return data_entry
|
|
76
|
+
|
|
77
|
+
def prepare_multipart_form_data(
|
|
78
|
+
body: Mapping[str, Any], multipart_fields: List[str], data_fields: List[str]
|
|
79
|
+
) -> Tuple[List[FileType], Dict[str, Any]]:
|
|
80
|
+
files: List[FileType] = []
|
|
81
|
+
data: Dict[str, Any] = {}
|
|
82
|
+
for multipart_field in multipart_fields:
|
|
83
|
+
multipart_entry = body.get(multipart_field)
|
|
84
|
+
if isinstance(multipart_entry, list):
|
|
85
|
+
files.extend([(multipart_field, e) for e in multipart_entry ])
|
|
86
|
+
elif multipart_entry:
|
|
87
|
+
files.append((multipart_field, multipart_entry))
|
|
88
|
+
|
|
89
|
+
for data_field in data_fields:
|
|
90
|
+
data_entry = body.get(data_field)
|
|
91
|
+
if data_entry:
|
|
92
|
+
data[data_field] = serialize_multipart_data_entry(data_entry)
|
|
93
|
+
|
|
94
|
+
return files, data
|
|
95
|
+
{% endif %}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
"""An MD to RST plugin.
|
|
7
|
+
"""
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Any, Dict, Set, Union
|
|
10
|
+
|
|
11
|
+
import m2r2
|
|
12
|
+
|
|
13
|
+
from . import YamlUpdatePlugin
|
|
14
|
+
from .utils import parse_args
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_LOGGER = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class GeneratorRenderer(m2r2.RestRenderer):
|
|
21
|
+
"""Redefine the concept of inline HTML in the renderer, we don't want to define a new format
|
|
22
|
+
in the description/summary.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def inline_html(self, html: str) -> str:
|
|
26
|
+
"""Do not render inline HTML with a role definition."""
|
|
27
|
+
return f":code:`{html}`"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class M2R(YamlUpdatePlugin):
|
|
31
|
+
"""A plugin to convert any description and summary from MD to RST."""
|
|
32
|
+
|
|
33
|
+
def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
|
|
34
|
+
"""Convert in place the YAML str."""
|
|
35
|
+
self._convert_docstring_no_cycles(yaml_data, set())
|
|
36
|
+
|
|
37
|
+
def _convert_docstring_no_cycles(self, yaml_data: Union[Dict[str, Any], str], node_list: Set[int]) -> None:
|
|
38
|
+
"""Walk the YAML tree to convert MD to RST."""
|
|
39
|
+
if id(yaml_data) in node_list:
|
|
40
|
+
return
|
|
41
|
+
node_list.add(id(yaml_data))
|
|
42
|
+
|
|
43
|
+
if isinstance(yaml_data, list):
|
|
44
|
+
for elt in yaml_data:
|
|
45
|
+
self._convert_docstring_no_cycles(elt, node_list)
|
|
46
|
+
elif isinstance(yaml_data, dict):
|
|
47
|
+
for key, value in yaml_data.items():
|
|
48
|
+
if key in ["description", "summary"]:
|
|
49
|
+
yaml_data[key] = self.convert_to_rst(value)
|
|
50
|
+
continue
|
|
51
|
+
self._convert_docstring_no_cycles(value, node_list)
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def convert_to_rst(string_to_convert: str) -> str:
|
|
55
|
+
"""Convert that string from MD to RST."""
|
|
56
|
+
try:
|
|
57
|
+
return m2r2.convert(string_to_convert, renderer=GeneratorRenderer()).strip()
|
|
58
|
+
except Exception: # pylint: disable=broad-except
|
|
59
|
+
return string_to_convert
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
if __name__ == "__main__":
|
|
63
|
+
# CADL pipeline will call this
|
|
64
|
+
args, unknown_args = parse_args()
|
|
65
|
+
M2R(output_folder=args.output_folder, cadl_file=args.cadl_file, **unknown_args).process()
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from typing import Tuple, Any
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import os
|
|
9
|
+
import shutil
|
|
10
|
+
from venv import EnvBuilder
|
|
11
|
+
import black
|
|
12
|
+
from black.report import NothingChanged
|
|
13
|
+
from .venvtools import ExtendedEnvBuilder, python_run
|
|
14
|
+
|
|
15
|
+
from .. import Plugin
|
|
16
|
+
|
|
17
|
+
_BLACK_MODE = black.Mode() # pyright: ignore [reportPrivateImportUsage]
|
|
18
|
+
_BLACK_MODE.line_length = 120
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def format_file(file: Path, file_content: str) -> str:
|
|
22
|
+
if not file.suffix == ".py":
|
|
23
|
+
return file_content
|
|
24
|
+
try:
|
|
25
|
+
file_content = black.format_file_contents(file_content, fast=True, mode=_BLACK_MODE)
|
|
26
|
+
except NothingChanged:
|
|
27
|
+
pass
|
|
28
|
+
return file_content
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PostProcessPlugin(Plugin):
|
|
32
|
+
def __init__(self, **kwargs: Any):
|
|
33
|
+
super().__init__(**kwargs)
|
|
34
|
+
output_folder_uri = self.options["outputFolderUri"]
|
|
35
|
+
if output_folder_uri.startswith("file:"):
|
|
36
|
+
output_folder_uri = output_folder_uri[5:]
|
|
37
|
+
if os.name == "nt" and output_folder_uri.startswith("///"):
|
|
38
|
+
output_folder_uri = output_folder_uri[3:]
|
|
39
|
+
self.output_folder = Path(output_folder_uri) # path to where the setup.py is
|
|
40
|
+
self.setup_venv()
|
|
41
|
+
|
|
42
|
+
# set up the venv
|
|
43
|
+
# base folder is where the code starts, i.e. where we
|
|
44
|
+
self.base_folder, self.namespace = self.get_namespace(self.output_folder, "")
|
|
45
|
+
|
|
46
|
+
def setup_venv(self):
|
|
47
|
+
venv_path = self.output_folder / Path(".temp_folder") / Path("temp_venv")
|
|
48
|
+
|
|
49
|
+
if venv_path.exists():
|
|
50
|
+
env_builder = EnvBuilder(with_pip=True)
|
|
51
|
+
self.venv_context = env_builder.ensure_directories(venv_path)
|
|
52
|
+
else:
|
|
53
|
+
env_builder = ExtendedEnvBuilder(with_pip=True, upgrade_deps=True)
|
|
54
|
+
env_builder.create(venv_path)
|
|
55
|
+
self.venv_context = env_builder.context
|
|
56
|
+
python_run(
|
|
57
|
+
self.venv_context,
|
|
58
|
+
"pip",
|
|
59
|
+
["install", "-e", str(self.output_folder)],
|
|
60
|
+
directory=self.output_folder,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def get_namespace(self, dir: Path, namespace: str) -> Tuple[Path, str]:
|
|
64
|
+
try:
|
|
65
|
+
init_file = next(d for d in dir.iterdir() if d.name == "__init__.py")
|
|
66
|
+
# we don't care about pkgutil inits, we skip over them
|
|
67
|
+
file_content = self.read_file(init_file.relative_to(self.output_folder))
|
|
68
|
+
if "pkgutil" not in file_content:
|
|
69
|
+
return dir, namespace
|
|
70
|
+
except StopIteration:
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
# first, see if we can get a folder that has the same name as the current output folder
|
|
75
|
+
start = self.output_folder.stem.split("-")[0]
|
|
76
|
+
next_dir = next(d for d in dir.iterdir() if d.is_dir() and d.name == start)
|
|
77
|
+
except StopIteration:
|
|
78
|
+
invalid_start_chars = [".", "_"]
|
|
79
|
+
invalid_dirs = [
|
|
80
|
+
"swagger",
|
|
81
|
+
"out",
|
|
82
|
+
"tests",
|
|
83
|
+
"samples",
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
next_dir = next(
|
|
87
|
+
d
|
|
88
|
+
for d in dir.iterdir()
|
|
89
|
+
if d.is_dir()
|
|
90
|
+
and not str(d).endswith("egg-info")
|
|
91
|
+
and d.name[0] not in invalid_start_chars
|
|
92
|
+
and d.name not in invalid_dirs
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
namespace = f"{namespace}.{next_dir.name}" if namespace else next_dir.name
|
|
96
|
+
return self.get_namespace(next_dir, namespace)
|
|
97
|
+
|
|
98
|
+
def process(self) -> bool:
|
|
99
|
+
folders = [f for f in self.base_folder.glob("**/*") if f.is_dir() and not f.stem.startswith("__")]
|
|
100
|
+
# will always have the root
|
|
101
|
+
self.fix_imports_in_init(
|
|
102
|
+
generated_file_name="_client",
|
|
103
|
+
folder_path=self.base_folder,
|
|
104
|
+
namespace=self.namespace,
|
|
105
|
+
)
|
|
106
|
+
try:
|
|
107
|
+
aio_folder = next(f for f in folders if f.stem == "aio")
|
|
108
|
+
self.fix_imports_in_init(
|
|
109
|
+
generated_file_name="_client",
|
|
110
|
+
folder_path=aio_folder,
|
|
111
|
+
namespace=f"{self.namespace}.aio",
|
|
112
|
+
)
|
|
113
|
+
except StopIteration:
|
|
114
|
+
pass
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
models_folder = next(f for f in folders if f.stem == "models")
|
|
118
|
+
self.fix_imports_in_init(
|
|
119
|
+
generated_file_name="_models",
|
|
120
|
+
folder_path=models_folder,
|
|
121
|
+
namespace=f"{self.namespace}.models",
|
|
122
|
+
)
|
|
123
|
+
except StopIteration:
|
|
124
|
+
pass
|
|
125
|
+
operations_folders = [f for f in folders if f.stem in ["operations", "_operations"]]
|
|
126
|
+
for operations_folder in operations_folders:
|
|
127
|
+
sub_namespace = ".".join(str(operations_folder.relative_to(self.base_folder)).split(os.sep))
|
|
128
|
+
self.fix_imports_in_init(
|
|
129
|
+
generated_file_name="_operations",
|
|
130
|
+
folder_path=operations_folder,
|
|
131
|
+
namespace=f"{self.namespace}.{sub_namespace}",
|
|
132
|
+
)
|
|
133
|
+
shutil.rmtree(f"{str(self.output_folder)}/.temp_folder")
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
def fix_imports_in_init(self, generated_file_name: str, folder_path: Path, namespace: str) -> None:
|
|
137
|
+
customized_objects_str = python_run(
|
|
138
|
+
self.venv_context,
|
|
139
|
+
command=[namespace, str(self.output_folder)],
|
|
140
|
+
module="get_all",
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
if not customized_objects_str:
|
|
144
|
+
return
|
|
145
|
+
customized_objects = {k: None for k in customized_objects_str.split(",")}.keys() # filter out duplicates
|
|
146
|
+
file = (folder_path / "__init__.py").relative_to(self.output_folder)
|
|
147
|
+
file_content = self.read_file(file).replace("\r\n", "\n")
|
|
148
|
+
added_objs = []
|
|
149
|
+
for obj in customized_objects:
|
|
150
|
+
if f" import {obj}\n" in file_content:
|
|
151
|
+
# means we're overriding a generated model
|
|
152
|
+
file_content = file_content.replace(
|
|
153
|
+
f"from .{generated_file_name} import {obj}\n",
|
|
154
|
+
f"from ._patch import {obj}\n",
|
|
155
|
+
)
|
|
156
|
+
else:
|
|
157
|
+
added_objs.append(obj)
|
|
158
|
+
file_content = file_content.replace(
|
|
159
|
+
"try:\n from ._patch import __all__ as _patch_all\n "
|
|
160
|
+
"from ._patch import * # pylint: disable=unused-wildcard-import"
|
|
161
|
+
"\nexcept ImportError:\n _patch_all = []",
|
|
162
|
+
"",
|
|
163
|
+
)
|
|
164
|
+
file_content = file_content.replace("from ._patch import __all__ as _patch_all", "")
|
|
165
|
+
file_content = file_content.replace(
|
|
166
|
+
"from ._patch import * # pylint: disable=unused-wildcard-import\n",
|
|
167
|
+
"",
|
|
168
|
+
)
|
|
169
|
+
file_content = file_content.replace("__all__.extend([p for p in _patch_all if p not in __all__])", "")
|
|
170
|
+
if added_objs:
|
|
171
|
+
# add import
|
|
172
|
+
patch_sdk_import = "from ._patch import patch_sdk as _patch_sdk"
|
|
173
|
+
imports = "\n".join([f"from ._patch import {obj}" for obj in added_objs])
|
|
174
|
+
if imports:
|
|
175
|
+
replacement = f"{imports}\n{patch_sdk_import}"
|
|
176
|
+
else:
|
|
177
|
+
replacement = patch_sdk_import
|
|
178
|
+
file_content = file_content.replace(patch_sdk_import, replacement)
|
|
179
|
+
# add to __all__
|
|
180
|
+
added_objs_all = "\n".join([f' "{obj}",' for obj in added_objs]) + "\n"
|
|
181
|
+
file_content = file_content.replace("__all__ = [", f"__all__ = [\n{added_objs_all}", 1)
|
|
182
|
+
formatted_file = format_file(file, file_content)
|
|
183
|
+
self.write_file(file, formatted_file)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
import sys
|
|
7
|
+
import importlib
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main(namespace):
|
|
11
|
+
sdk = importlib.import_module(namespace)
|
|
12
|
+
return sdk._patch.__all__ # pylint: disable=protected-access
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
if __name__ == "__main__":
|
|
16
|
+
patched = ",".join(main(sys.argv[1]))
|
|
17
|
+
output_folder = sys.argv[2]
|
|
18
|
+
with open(f"{output_folder}/.temp_folder/patched.txt", "w", encoding="utf-8-sig") as f:
|
|
19
|
+
f.write(patched)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
|
+
# license information.
|
|
5
|
+
# --------------------------------------------------------------------------
|
|
6
|
+
from typing import Optional
|
|
7
|
+
import subprocess
|
|
8
|
+
import venv
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
_ROOT_DIR = Path(__file__).parent
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ExtendedEnvBuilder(venv.EnvBuilder):
|
|
17
|
+
"""An extended env builder which saves the context, to have access
|
|
18
|
+
easily to bin path and such.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, *args, **kwargs):
|
|
22
|
+
self.context = None
|
|
23
|
+
if sys.version_info < (3, 9, 0):
|
|
24
|
+
# Not supported on Python 3.8, and we don't need it
|
|
25
|
+
kwargs.pop("upgrade_deps", None)
|
|
26
|
+
super().__init__(*args, **kwargs)
|
|
27
|
+
|
|
28
|
+
def ensure_directories(self, env_dir):
|
|
29
|
+
self.context = super(ExtendedEnvBuilder, self).ensure_directories(env_dir)
|
|
30
|
+
return self.context
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def create(
|
|
34
|
+
env_dir,
|
|
35
|
+
system_site_packages=False,
|
|
36
|
+
clear=False,
|
|
37
|
+
symlinks=False,
|
|
38
|
+
with_pip=False,
|
|
39
|
+
prompt=None,
|
|
40
|
+
upgrade_deps=False,
|
|
41
|
+
):
|
|
42
|
+
"""Create a virtual environment in a directory."""
|
|
43
|
+
builder = ExtendedEnvBuilder(
|
|
44
|
+
system_site_packages=system_site_packages,
|
|
45
|
+
clear=clear,
|
|
46
|
+
symlinks=symlinks,
|
|
47
|
+
with_pip=with_pip,
|
|
48
|
+
prompt=prompt,
|
|
49
|
+
upgrade_deps=upgrade_deps,
|
|
50
|
+
)
|
|
51
|
+
builder.create(env_dir)
|
|
52
|
+
return builder.context
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def python_run(venv_context, module, command, directory=_ROOT_DIR) -> Optional[str]:
|
|
56
|
+
try:
|
|
57
|
+
cmd_line = [
|
|
58
|
+
venv_context.env_exe,
|
|
59
|
+
"-m",
|
|
60
|
+
module,
|
|
61
|
+
] + command
|
|
62
|
+
print("Executing: {}".format(" ".join(cmd_line)))
|
|
63
|
+
subprocess.run(
|
|
64
|
+
cmd_line,
|
|
65
|
+
cwd=directory,
|
|
66
|
+
check=True,
|
|
67
|
+
stdout=False,
|
|
68
|
+
)
|
|
69
|
+
if module == "get_all":
|
|
70
|
+
with open(f"{command[1]}/.temp_folder/patched.txt", "r", encoding="utf-8-sig") as f:
|
|
71
|
+
return f.read()
|
|
72
|
+
except subprocess.CalledProcessError as err:
|
|
73
|
+
print(err)
|
|
74
|
+
sys.exit(1)
|
|
75
|
+
return None
|