@typespec/http-client-python 0.28.2 → 0.29.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/dist/emitter/code-model.d.ts.map +1 -1
- package/dist/emitter/code-model.js +7 -6
- package/dist/emitter/code-model.js.map +1 -1
- package/dist/emitter/constants.d.ts +6 -0
- package/dist/emitter/constants.d.ts.map +1 -0
- package/dist/emitter/constants.js +27 -0
- package/dist/emitter/constants.js.map +1 -0
- package/dist/emitter/emitter.d.ts.map +1 -1
- package/dist/emitter/emitter.js +193 -119
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/http.d.ts.map +1 -1
- package/dist/emitter/http.js +33 -1
- package/dist/emitter/http.js.map +1 -1
- package/dist/emitter/lib.d.ts +37 -3
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +17 -0
- package/dist/emitter/lib.js.map +1 -1
- package/dist/emitter/run-python3.js +1 -1
- package/dist/emitter/run-python3.js.map +1 -1
- package/dist/emitter/system-requirements.js +6 -4
- package/dist/emitter/system-requirements.js.map +1 -1
- package/dist/emitter/types.d.ts +2 -5
- package/dist/emitter/types.d.ts.map +1 -1
- package/dist/emitter/types.js +86 -63
- package/dist/emitter/types.js.map +1 -1
- package/dist/emitter/utils.d.ts.map +1 -1
- package/dist/emitter/utils.js +16 -17
- package/dist/emitter/utils.js.map +1 -1
- package/emitter/src/code-model.ts +7 -13
- package/emitter/src/constants.ts +27 -0
- package/emitter/src/emitter.ts +241 -123
- package/emitter/src/http.ts +29 -1
- package/emitter/src/lib.ts +24 -0
- package/emitter/src/run-python3.ts +1 -1
- package/emitter/src/system-requirements.ts +4 -4
- package/emitter/src/types.ts +102 -62
- package/emitter/src/utils.ts +16 -18
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/emitter/test/utils.test.ts +3 -0
- package/emitter/tsconfig.build.json +2 -1
- package/emitter/tsconfig.json +2 -1
- package/eng/scripts/Build-Packages.ps1 +62 -37
- package/eng/scripts/Check-GitChanges.ps1 +30 -3
- package/eng/scripts/Functions.ps1 +54 -15
- package/eng/scripts/Generate.ps1 +42 -8
- package/eng/scripts/Generation.psm1 +44 -15
- package/eng/scripts/Initialize-Repository.ps1 +29 -11
- package/eng/scripts/Test-Packages.ps1 +47 -31
- package/eng/scripts/ci/config/eslint-ci.config.mjs +64 -0
- package/eng/scripts/ci/{mypy.ini → config/mypy.ini} +1 -1
- package/eng/scripts/ci/{pylintrc → config/pylintrc} +1 -1
- package/eng/scripts/ci/{pyrightconfig.json → config/pyrightconfig.json} +1 -1
- package/eng/scripts/ci/dev_requirements.txt +2 -1
- package/eng/scripts/ci/format.ts +232 -2
- package/eng/scripts/ci/lint.ts +223 -20
- package/eng/scripts/ci/regenerate-common.ts +411 -136
- package/eng/scripts/ci/regenerate.ts +247 -101
- package/eng/scripts/ci/run-tests.ts +507 -0
- package/eng/scripts/ci/run_apiview.py +22 -16
- package/eng/scripts/ci/run_mypy.py +34 -23
- package/eng/scripts/ci/run_pylint.py +27 -19
- package/eng/scripts/ci/run_pyright.py +9 -5
- package/eng/scripts/ci/run_sphinx_build.py +24 -9
- package/eng/scripts/ci/typecheck.ts +225 -0
- package/eng/scripts/ci/util.py +61 -25
- package/eng/scripts/ci/utils.ts +5 -5
- package/eng/scripts/setup/__pycache__/package_manager.cpython-311.pyc +0 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-311.pyc +0 -0
- package/eng/scripts/setup/build.ts +1 -1
- package/eng/scripts/setup/build_pygen_wheel.py +4 -3
- package/eng/scripts/setup/install.py +4 -3
- package/eng/scripts/setup/install.ts +1 -1
- package/eng/scripts/setup/prepare.py +3 -2
- package/eng/scripts/setup/prepare.ts +1 -1
- package/eng/scripts/setup/run-python3.ts +1 -1
- package/eng/scripts/setup/run_batch.py +197 -0
- package/eng/scripts/setup/run_tsp.py +3 -3
- package/eng/scripts/setup/system-requirements.ts +8 -4
- package/eng/scripts/setup/venvtools.py +1 -1
- package/generator/build/lib/pygen/__init__.py +1 -3
- package/generator/build/lib/pygen/codegen/__init__.py +0 -1
- package/generator/build/lib/pygen/codegen/models/base.py +0 -1
- package/generator/build/lib/pygen/codegen/models/client.py +2 -1
- package/generator/build/lib/pygen/codegen/models/code_model.py +1 -0
- package/generator/build/lib/pygen/codegen/models/enum_type.py +0 -1
- package/generator/build/lib/pygen/codegen/models/model_type.py +1 -7
- package/generator/build/lib/pygen/codegen/models/parameter.py +16 -14
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +27 -12
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +12 -3
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +6 -2
- package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +17 -4
- package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +17 -11
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +176 -71
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +11 -3
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +5 -1
- package/generator/build/lib/pygen/preprocess/__init__.py +37 -30
- package/generator/component-detection-pip-report.json +7 -7
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/__init__.py +1 -3
- package/generator/pygen/codegen/__init__.py +0 -1
- package/generator/pygen/codegen/models/base.py +0 -1
- package/generator/pygen/codegen/models/client.py +2 -1
- package/generator/pygen/codegen/models/code_model.py +1 -0
- package/generator/pygen/codegen/models/enum_type.py +0 -1
- package/generator/pygen/codegen/models/model_type.py +1 -7
- package/generator/pygen/codegen/models/parameter.py +16 -14
- package/generator/pygen/codegen/serializers/__init__.py +27 -12
- package/generator/pygen/codegen/serializers/builder_serializer.py +12 -3
- package/generator/pygen/codegen/serializers/general_serializer.py +6 -2
- package/generator/pygen/codegen/serializers/import_serializer.py +17 -4
- package/generator/pygen/codegen/serializers/parameter_serializer.py +17 -11
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +176 -71
- package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +11 -3
- package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +1 -1
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +5 -1
- package/generator/pygen/preprocess/__init__.py +37 -30
- package/generator/pygen.egg-info/PKG-INFO +1 -2
- package/generator/pygen.egg-info/requires.txt +1 -1
- package/generator/setup.py +1 -2
- package/package.json +63 -42
- package/eng/scripts/ci/run-ci.ts +0 -89
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_commonproperties_async.py +0 -94
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_largeheader_async.py +0 -30
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_nonresource_async.py +0 -36
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py +0 -205
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_resource_async.py +0 -478
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py +0 -101
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_header_async.py +0 -18
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_path_async.py +0 -18
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_query_async.py +0 -18
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_default_value_async.py +0 -46
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_initialization_async.py +0 -58
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_location_async.py +0 -82
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py +0 -20
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +0 -115
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py +0 -53
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_next_link_verb_async.py +0 -28
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_override_async.py +0 -106
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_usage_async.py +0 -38
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_basic_async.py +0 -76
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py +0 -22
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_standard_async.py +0 -39
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_model_async.py +0 -33
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_page_async.py +0 -80
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_scalar_async.py +0 -41
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_traits_async.py +0 -87
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_encode_duration_async.py +0 -19
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_example_basic_async.py +0 -30
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py +0 -19
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_method_subscription_id_async.py +0 -248
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_async.py +0 -110
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py +0 -132
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_special_headers_client_request_id_async.py +0 -30
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_versioning_previewversion_async.py +0 -53
- package/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +0 -34
- package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_async.py +0 -69
- package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py +0 -37
- package/generator/test/azure/mock_api_tests/asynctests/test_client_overload_async.py +0 -27
- package/generator/test/azure/mock_api_tests/asynctests/test_client_structure_async.py +0 -64
- package/generator/test/azure/mock_api_tests/asynctests/test_client_structure_clientoperationgroup_async.py +0 -31
- package/generator/test/azure/mock_api_tests/asynctests/test_encode_duration_async.py +0 -63
- package/generator/test/azure/mock_api_tests/asynctests/test_encode_numeric_async.py +0 -35
- package/generator/test/azure/mock_api_tests/asynctests/test_parameters_basic_async.py +0 -24
- package/generator/test/azure/mock_api_tests/asynctests/test_parameters_spread_async.py +0 -76
- package/generator/test/azure/mock_api_tests/asynctests/test_payload_content_negotiation_async.py +0 -37
- package/generator/test/azure/mock_api_tests/asynctests/test_payload_multipart_async.py +0 -216
- package/generator/test/azure/mock_api_tests/asynctests/test_resiliency_srv_driven_async.py +0 -130
- package/generator/test/azure/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py +0 -24
- package/generator/test/azure/mock_api_tests/asynctests/test_service_multi_service_async.py +0 -31
- package/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py +0 -71
- package/generator/test/azure/mock_api_tests/conftest.py +0 -207
- package/generator/test/azure/mock_api_tests/data/image.jpg +0 -0
- package/generator/test/azure/mock_api_tests/data/image.png +0 -0
- package/generator/test/azure/mock_api_tests/test_azure_arm_commonproperties.py +0 -89
- package/generator/test/azure/mock_api_tests/test_azure_arm_largeheader.py +0 -27
- package/generator/test/azure/mock_api_tests/test_azure_arm_nonresource.py +0 -34
- package/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py +0 -180
- package/generator/test/azure/mock_api_tests/test_azure_arm_resource.py +0 -436
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_access.py +0 -92
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_header.py +0 -17
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_path.py +0 -17
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_query.py +0 -17
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_default_value.py +0 -42
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_initialization.py +0 -51
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_location.py +0 -70
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_deserialize_empty_string_as_null.py +0 -19
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +0 -104
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_hierrarchy_building.py +0 -45
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_next_link_verb.py +0 -27
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_override.py +0 -102
- package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_usage.py +0 -32
- package/generator/test/azure/mock_api_tests/test_azure_core_basic.py +0 -70
- package/generator/test/azure/mock_api_tests/test_azure_core_lro_rpc.py +0 -20
- package/generator/test/azure/mock_api_tests/test_azure_core_lro_standard.py +0 -32
- package/generator/test/azure/mock_api_tests/test_azure_core_model.py +0 -30
- package/generator/test/azure/mock_api_tests/test_azure_core_page.py +0 -71
- package/generator/test/azure/mock_api_tests/test_azure_core_scalar.py +0 -35
- package/generator/test/azure/mock_api_tests/test_azure_core_traits.py +0 -85
- package/generator/test/azure/mock_api_tests/test_azure_encode_duration.py +0 -18
- package/generator/test/azure/mock_api_tests/test_azure_example_basic.py +0 -29
- package/generator/test/azure/mock_api_tests/test_azure_payload_pageable.py +0 -18
- package/generator/test/azure/mock_api_tests/test_azure_resource_manager_method_subscription_id.py +0 -235
- package/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service.py +0 -104
- package/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service_shared_models.py +0 -128
- package/generator/test/azure/mock_api_tests/test_azure_special_headers_client_request_id.py +0 -29
- package/generator/test/azure/mock_api_tests/test_azure_versioning_previewversion.py +0 -50
- package/generator/test/azure/mock_api_tests/test_clear_output_folder.py +0 -23
- package/generator/test/azure/mock_api_tests/test_client_namespace.py +0 -32
- package/generator/test/azure/mock_api_tests/test_client_naming.py +0 -57
- package/generator/test/azure/mock_api_tests/test_client_naming_enum_conflict.py +0 -35
- package/generator/test/azure/mock_api_tests/test_client_overload.py +0 -25
- package/generator/test/azure/mock_api_tests/test_client_structure.py +0 -60
- package/generator/test/azure/mock_api_tests/test_client_structure_clientoperationgroup.py +0 -29
- package/generator/test/azure/mock_api_tests/test_encode_duration.py +0 -60
- package/generator/test/azure/mock_api_tests/test_encode_numeric.py +0 -31
- package/generator/test/azure/mock_api_tests/test_model_base_flatten_compatibility.py +0 -251
- package/generator/test/azure/mock_api_tests/test_parameters_basic.py +0 -22
- package/generator/test/azure/mock_api_tests/test_parameters_spread.py +0 -66
- package/generator/test/azure/mock_api_tests/test_payload_content_negotiation.py +0 -33
- package/generator/test/azure/mock_api_tests/test_payload_multipart.py +0 -198
- package/generator/test/azure/mock_api_tests/test_resiliency_srv_driven.py +0 -124
- package/generator/test/azure/mock_api_tests/test_serialization_encoded_name_json.py +0 -21
- package/generator/test/azure/mock_api_tests/test_service_multi_service.py +0 -29
- package/generator/test/azure/mock_api_tests/test_special_words.py +0 -63
- package/generator/test/azure/requirements.txt +0 -125
- package/generator/test/azure/tox.ini +0 -64
- package/generator/test/data/image.jpg +0 -0
- package/generator/test/data/image.png +0 -0
- package/generator/test/dev_requirements.txt +0 -8
- package/generator/test/generic_mock_api_tests/asynctests/test_authentication_async.py +0 -140
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_array_async.py +0 -139
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py +0 -132
- package/generator/test/generic_mock_api_tests/asynctests/test_encode_datetime_async.py +0 -127
- package/generator/test/generic_mock_api_tests/asynctests/test_headasboolean_async.py +0 -35
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_body_optionality_async.py +0 -30
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_collection_format_async.py +0 -38
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py +0 -24
- package/generator/test/generic_mock_api_tests/asynctests/test_parameters_query_async.py +0 -18
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py +0 -98
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_media_type_async.py +0 -27
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py +0 -134
- package/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py +0 -150
- package/generator/test/generic_mock_api_tests/asynctests/test_response_status_code_range_async.py +0 -38
- package/generator/test/generic_mock_api_tests/asynctests/test_routes_async.py +0 -331
- package/generator/test/generic_mock_api_tests/asynctests/test_server_endpoint_not_defined_async.py +0 -18
- package/generator/test/generic_mock_api_tests/asynctests/test_server_path_multiple_async.py +0 -25
- package/generator/test/generic_mock_api_tests/asynctests/test_server_path_single_async.py +0 -18
- package/generator/test/generic_mock_api_tests/asynctests/test_server_versions_not_versioned_async.py +0 -28
- package/generator/test/generic_mock_api_tests/asynctests/test_server_versions_versioned_async.py +0 -34
- package/generator/test/generic_mock_api_tests/asynctests/test_special_headers_conditional_request_async.py +0 -38
- package/generator/test/generic_mock_api_tests/asynctests/test_special_headers_repeatability_async.py +0 -19
- package/generator/test/generic_mock_api_tests/asynctests/test_specs_documentation_async.py +0 -59
- package/generator/test/generic_mock_api_tests/asynctests/test_streaming_jsonl_async.py +0 -27
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_array_async.py +0 -127
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_dictionary_async.py +0 -98
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_extensible_async.py +0 -25
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_fixed_async.py +0 -27
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_file_async.py +0 -59
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_empty_async.py +0 -32
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py +0 -70
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py +0 -85
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_not_discriminated_async.py +0 -34
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_recursive_async.py +0 -34
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_single_discriminator_async.py +0 -67
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_usage_async.py +0 -32
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_visibility_async.py +0 -47
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_additionalproperties_async.py +0 -353
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py +0 -110
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_optional_async.py +0 -197
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_valuetypes_async.py +0 -315
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_scalar_async.py +0 -60
- package/generator/test/generic_mock_api_tests/asynctests/test_typetest_union_async.py +0 -90
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_added_async.py +0 -36
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_made_optional_async.py +0 -21
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_removed_async.py +0 -39
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_renamed_from_async.py +0 -29
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_return_type_changed_from_async.py +0 -18
- package/generator/test/generic_mock_api_tests/asynctests/test_versioning_type_changed_from_async.py +0 -22
- package/generator/test/generic_mock_api_tests/conftest.py +0 -75
- 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 +0 -130
- package/generator/test/generic_mock_api_tests/test_encode_array.py +0 -126
- package/generator/test/generic_mock_api_tests/test_encode_bytes.py +0 -128
- package/generator/test/generic_mock_api_tests/test_encode_datetime.py +0 -123
- package/generator/test/generic_mock_api_tests/test_headasboolean.py +0 -33
- package/generator/test/generic_mock_api_tests/test_parameters_body_optionality.py +0 -27
- package/generator/test/generic_mock_api_tests/test_parameters_collection_format.py +0 -33
- package/generator/test/generic_mock_api_tests/test_parameters_path.py +0 -22
- package/generator/test/generic_mock_api_tests/test_parameters_query.py +0 -17
- package/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py +0 -93
- package/generator/test/generic_mock_api_tests/test_payload_media_type.py +0 -25
- package/generator/test/generic_mock_api_tests/test_payload_pageable.py +0 -99
- package/generator/test/generic_mock_api_tests/test_payload_xml.py +0 -135
- package/generator/test/generic_mock_api_tests/test_response_status_code_range.py +0 -36
- package/generator/test/generic_mock_api_tests/test_routes.py +0 -285
- package/generator/test/generic_mock_api_tests/test_server_endpoint_not_defined.py +0 -17
- package/generator/test/generic_mock_api_tests/test_server_path_multiple.py +0 -21
- package/generator/test/generic_mock_api_tests/test_server_path_single.py +0 -17
- package/generator/test/generic_mock_api_tests/test_server_versions_not_versioned.py +0 -25
- package/generator/test/generic_mock_api_tests/test_server_versions_versioned.py +0 -30
- package/generator/test/generic_mock_api_tests/test_special_headers_conditional_request.py +0 -34
- package/generator/test/generic_mock_api_tests/test_special_headers_repeatability.py +0 -18
- package/generator/test/generic_mock_api_tests/test_specs_documentation.py +0 -51
- package/generator/test/generic_mock_api_tests/test_streaming_jsonl.py +0 -25
- package/generator/test/generic_mock_api_tests/test_typetest_array.py +0 -111
- package/generator/test/generic_mock_api_tests/test_typetest_dictionary.py +0 -86
- package/generator/test/generic_mock_api_tests/test_typetest_enum_extensible.py +0 -23
- package/generator/test/generic_mock_api_tests/test_typetest_enum_fixed.py +0 -25
- package/generator/test/generic_mock_api_tests/test_typetest_file.py +0 -52
- package/generator/test/generic_mock_api_tests/test_typetest_model_empty.py +0 -29
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_enum_discriminator.py +0 -58
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_nested_discriminator.py +0 -79
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_not_discriminated.py +0 -31
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_recursive.py +0 -32
- package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_single_discriminator.py +0 -60
- package/generator/test/generic_mock_api_tests/test_typetest_model_usage.py +0 -28
- package/generator/test/generic_mock_api_tests/test_typetest_model_visibility.py +0 -40
- package/generator/test/generic_mock_api_tests/test_typetest_property_additionalproperties.py +0 -314
- package/generator/test/generic_mock_api_tests/test_typetest_property_nullable.py +0 -102
- package/generator/test/generic_mock_api_tests/test_typetest_property_optional.py +0 -174
- package/generator/test/generic_mock_api_tests/test_typetest_property_valuetypes.py +0 -286
- package/generator/test/generic_mock_api_tests/test_typetest_scalar.py +0 -53
- package/generator/test/generic_mock_api_tests/test_typetest_union.py +0 -80
- package/generator/test/generic_mock_api_tests/test_typetest_union_discriminated.py +0 -290
- package/generator/test/generic_mock_api_tests/test_versioning_added.py +0 -33
- package/generator/test/generic_mock_api_tests/test_versioning_made_optional.py +0 -20
- package/generator/test/generic_mock_api_tests/test_versioning_removed.py +0 -37
- package/generator/test/generic_mock_api_tests/test_versioning_renamed_from.py +0 -27
- package/generator/test/generic_mock_api_tests/test_versioning_return_type_changed_from.py +0 -17
- package/generator/test/generic_mock_api_tests/test_versioning_type_changed_from.py +0 -21
- package/generator/test/unbranded/mock_api_tests/asynctests/test_auth_flow_async.py +0 -19
- package/generator/test/unbranded/mock_api_tests/asynctests/test_encode_duration_async.py +0 -63
- package/generator/test/unbranded/mock_api_tests/asynctests/test_encode_numeric_async.py +0 -35
- package/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_basic_async.py +0 -24
- package/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_spread_async.py +0 -76
- package/generator/test/unbranded/mock_api_tests/asynctests/test_payload_content_negotiation_async.py +0 -37
- package/generator/test/unbranded/mock_api_tests/asynctests/test_payload_multipart_async.py +0 -218
- package/generator/test/unbranded/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py +0 -24
- package/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py +0 -73
- package/generator/test/unbranded/mock_api_tests/asynctests/test_unbranded_async.py +0 -24
- package/generator/test/unbranded/mock_api_tests/conftest.py +0 -91
- package/generator/test/unbranded/mock_api_tests/data/image.jpg +0 -0
- package/generator/test/unbranded/mock_api_tests/data/image.png +0 -0
- package/generator/test/unbranded/mock_api_tests/test_auth_flow.py +0 -17
- package/generator/test/unbranded/mock_api_tests/test_encode_duration.py +0 -60
- package/generator/test/unbranded/mock_api_tests/test_encode_numeric.py +0 -32
- package/generator/test/unbranded/mock_api_tests/test_parameters_basic.py +0 -22
- package/generator/test/unbranded/mock_api_tests/test_parameters_spread.py +0 -66
- package/generator/test/unbranded/mock_api_tests/test_payload_content_negotiation.py +0 -33
- package/generator/test/unbranded/mock_api_tests/test_payload_multipart.py +0 -200
- package/generator/test/unbranded/mock_api_tests/test_serialization_encoded_name_json.py +0 -22
- package/generator/test/unbranded/mock_api_tests/test_special_words.py +0 -66
- package/generator/test/unbranded/mock_api_tests/test_unbranded.py +0 -65
- package/generator/test/unbranded/requirements.txt +0 -69
- package/generator/test/unbranded/tox.ini +0 -64
- package/generator/test/unittests/conftest.py +0 -15
- package/generator/test/unittests/requirements.txt +0 -3
- package/generator/test/unittests/test_enums.py +0 -89
- package/generator/test/unittests/test_model_base_serialization.py +0 -4906
- package/generator/test/unittests/test_model_base_xml_serialization.py +0 -1239
- package/generator/test/unittests/test_name_converter.py +0 -35
- package/generator/test/unittests/test_optional_return_type.py +0 -268
- package/generator/test/unittests/test_parameter_ordering.py +0 -104
- package/generator/test/unittests/test_sort_schema.py +0 -93
- package/generator/test/unittests/tox.ini +0 -5
- /package/eng/scripts/ci/{pyproject.toml → config/pyproject.toml} +0 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { ChildProcess, spawn } from "child_process";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import { cpus } from "os";
|
|
5
|
+
import { dirname, join } from "path";
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import { parseArgs } from "util";
|
|
9
|
+
|
|
10
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), "../../../");
|
|
11
|
+
const monorepoRoot = join(root, "../../");
|
|
12
|
+
const testsDir = join(root, "tests");
|
|
13
|
+
|
|
14
|
+
const argv = parseArgs({
|
|
15
|
+
args: process.argv.slice(2),
|
|
16
|
+
options: {
|
|
17
|
+
emitter: { type: "boolean", short: "e" },
|
|
18
|
+
generator: { type: "boolean", short: "g" },
|
|
19
|
+
flavor: { type: "string", short: "f", default: "all" },
|
|
20
|
+
env: { type: "string" },
|
|
21
|
+
jobs: { type: "string", short: "j" },
|
|
22
|
+
name: { type: "string", short: "n" },
|
|
23
|
+
quiet: { type: "boolean", short: "q", default: false },
|
|
24
|
+
help: { type: "boolean", short: "h", default: false },
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (argv.values.help) {
|
|
29
|
+
console.log(`
|
|
30
|
+
Usage: run-tests.ts [options]
|
|
31
|
+
|
|
32
|
+
Options:
|
|
33
|
+
-e, --emitter Run TypeScript emitter tests (vitest)
|
|
34
|
+
-g, --generator Run Python generator tests (tox)
|
|
35
|
+
-f, --flavor <azure|unbranded> SDK flavor to test (only applies to --generator)
|
|
36
|
+
If not specified, tests both flavors
|
|
37
|
+
--env <env1,env2,...> Specific tox environments to run
|
|
38
|
+
Available: test, lint, mypy, pyright, apiview, sphinx, docs, ci, unittest
|
|
39
|
+
-j, --jobs <n> Number of parallel jobs (default: CPU cores - 2)
|
|
40
|
+
-n, --name <pattern> Filter tests by name pattern
|
|
41
|
+
-q, --quiet Suppress test output (only show pass/fail summary)
|
|
42
|
+
-h, --help Show this help message
|
|
43
|
+
|
|
44
|
+
Environments (for --generator):
|
|
45
|
+
test Run pytest tests for generated packages
|
|
46
|
+
lint Run pylint on generated packages
|
|
47
|
+
mypy Run mypy type checking on generated packages
|
|
48
|
+
pyright Run pyright type checking on generated packages
|
|
49
|
+
apiview Run apiview validation on generated packages
|
|
50
|
+
sphinx Run sphinx docstring validation on generated packages
|
|
51
|
+
docs Run apiview + sphinx (split into parallel envs)
|
|
52
|
+
ci Run all checks (test + lint + mypy + pyright + apiview + sphinx)
|
|
53
|
+
unittest Run unit tests for pygen internals
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
run-tests.ts # Run all tests (emitter + generator)
|
|
57
|
+
run-tests.ts --emitter # Run only emitter tests
|
|
58
|
+
run-tests.ts --generator # Run generator tests for all flavors
|
|
59
|
+
run-tests.ts --generator --flavor=azure # Run generator tests for azure only
|
|
60
|
+
run-tests.ts -g -f azure --env=test # Run pytest for azure only
|
|
61
|
+
run-tests.ts -g --env=lint # Run pylint for all flavors
|
|
62
|
+
run-tests.ts -g -f unbranded --env=mypy # Run mypy for unbranded only
|
|
63
|
+
`);
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Get Python venv path
|
|
68
|
+
function getVenvPython(): string {
|
|
69
|
+
const venvPath = join(root, "venv");
|
|
70
|
+
if (fs.existsSync(join(venvPath, "bin"))) {
|
|
71
|
+
return join(venvPath, "bin", "python");
|
|
72
|
+
} else if (fs.existsSync(join(venvPath, "Scripts"))) {
|
|
73
|
+
return join(venvPath, "Scripts", "python.exe");
|
|
74
|
+
}
|
|
75
|
+
throw new Error("Virtual environment not found. Run 'npm run install' first.");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface ToxResult {
|
|
79
|
+
env: string;
|
|
80
|
+
success: boolean;
|
|
81
|
+
duration: number;
|
|
82
|
+
error?: string;
|
|
83
|
+
failedTests?: string[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface RunningTask {
|
|
87
|
+
env: string;
|
|
88
|
+
proc: ChildProcess;
|
|
89
|
+
promise: Promise<ToxResult>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function extractFailedTests(output: string): string[] {
|
|
93
|
+
const lines = output.split("\n");
|
|
94
|
+
const failedTests: string[] = [];
|
|
95
|
+
let inSummary = false;
|
|
96
|
+
|
|
97
|
+
for (const line of lines) {
|
|
98
|
+
if (line.includes("short test summary info")) {
|
|
99
|
+
inSummary = true;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (inSummary) {
|
|
103
|
+
const match = line.match(/^FAILED\s+(.+)/);
|
|
104
|
+
if (match) {
|
|
105
|
+
failedTests.push(match[1].trim());
|
|
106
|
+
} else if (line.match(/^={3,}/) || line.match(/^\d+ failed/)) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return failedTests;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function startToxEnv(env: string, pythonPath: string, name?: string): RunningTask {
|
|
116
|
+
const startTime = Date.now();
|
|
117
|
+
const toxIniPath = join(testsDir, "tox.ini");
|
|
118
|
+
|
|
119
|
+
// Build command
|
|
120
|
+
const args = ["-m", "tox", "-c", toxIniPath, "-e", env];
|
|
121
|
+
if (name) {
|
|
122
|
+
args.push("--", "-k", name);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
console.log(`${pc.blue("[START]")} ${env}`);
|
|
126
|
+
|
|
127
|
+
const proc: ChildProcess = spawn(pythonPath, args, {
|
|
128
|
+
cwd: testsDir,
|
|
129
|
+
stdio: "pipe",
|
|
130
|
+
env: { ...process.env, FOLDER: env.split("-")[1] || "azure" },
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
let stderr = "";
|
|
134
|
+
let stdout = "";
|
|
135
|
+
if (proc.stdout) {
|
|
136
|
+
proc.stdout.on("data", (data) => {
|
|
137
|
+
const chunk = data.toString();
|
|
138
|
+
stdout += chunk;
|
|
139
|
+
if (!argv.values.quiet) {
|
|
140
|
+
process.stdout.write(chunk);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (proc.stderr) {
|
|
145
|
+
proc.stderr.on("data", (data) => {
|
|
146
|
+
const chunk = data.toString();
|
|
147
|
+
stderr += chunk;
|
|
148
|
+
if (!argv.values.quiet) {
|
|
149
|
+
process.stderr.write(chunk);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const promise = new Promise<ToxResult>((resolve) => {
|
|
155
|
+
proc.on("close", (code) => {
|
|
156
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
157
|
+
const success = code === 0;
|
|
158
|
+
|
|
159
|
+
if (success) {
|
|
160
|
+
console.log(`${pc.green("[PASS]")} ${env} (${duration.toFixed(1)}s)`);
|
|
161
|
+
} else {
|
|
162
|
+
console.log(`${pc.red("[FAIL]")} ${env} (${duration.toFixed(1)}s)`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const failedTests = extractFailedTests(stdout);
|
|
166
|
+
|
|
167
|
+
resolve({
|
|
168
|
+
env,
|
|
169
|
+
success,
|
|
170
|
+
duration,
|
|
171
|
+
error: success ? undefined : stderr || `Exit code: ${code}`,
|
|
172
|
+
failedTests: failedTests.length > 0 ? failedTests : undefined,
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
proc.on("error", (err) => {
|
|
177
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
178
|
+
console.log(`${pc.red("[ERROR]")} ${env}: ${err.message}`);
|
|
179
|
+
resolve({
|
|
180
|
+
env,
|
|
181
|
+
success: false,
|
|
182
|
+
duration,
|
|
183
|
+
error: err.message,
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return { env, proc, promise };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function killTask(task: RunningTask): void {
|
|
192
|
+
try {
|
|
193
|
+
task.proc.kill("SIGTERM");
|
|
194
|
+
} catch {
|
|
195
|
+
// Process may have already exited
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function runParallel(
|
|
200
|
+
envs: string[],
|
|
201
|
+
pythonPath: string,
|
|
202
|
+
maxJobs: number,
|
|
203
|
+
name?: string,
|
|
204
|
+
): Promise<ToxResult[]> {
|
|
205
|
+
const results: ToxResult[] = [];
|
|
206
|
+
const running: Map<string, RunningTask> = new Map();
|
|
207
|
+
|
|
208
|
+
for (const env of envs) {
|
|
209
|
+
// Wait if we're at max capacity
|
|
210
|
+
while (running.size >= maxJobs) {
|
|
211
|
+
const promises = Array.from(running.values()).map((t) => t.promise);
|
|
212
|
+
const completed = await Promise.race(promises);
|
|
213
|
+
results.push(completed);
|
|
214
|
+
running.delete(completed.env);
|
|
215
|
+
|
|
216
|
+
// Fail-fast: kill all running tasks and exit
|
|
217
|
+
if (!completed.success) {
|
|
218
|
+
console.log(pc.red(`\n[FAIL-FAST] ${completed.env} failed, killing remaining tasks...`));
|
|
219
|
+
for (const task of running.values()) {
|
|
220
|
+
killTask(task);
|
|
221
|
+
}
|
|
222
|
+
// Wait briefly for processes to terminate
|
|
223
|
+
await Promise.all(Array.from(running.values()).map((t) => t.promise));
|
|
224
|
+
return results;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Start new task
|
|
229
|
+
const task = startToxEnv(env, pythonPath, name);
|
|
230
|
+
running.set(env, task);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Wait for remaining tasks, checking for failures
|
|
234
|
+
while (running.size > 0) {
|
|
235
|
+
const promises = Array.from(running.values()).map((t) => t.promise);
|
|
236
|
+
const completed = await Promise.race(promises);
|
|
237
|
+
results.push(completed);
|
|
238
|
+
running.delete(completed.env);
|
|
239
|
+
|
|
240
|
+
// Fail-fast: kill all running tasks and exit
|
|
241
|
+
if (!completed.success) {
|
|
242
|
+
console.log(pc.red(`\n[FAIL-FAST] ${completed.env} failed, killing remaining tasks...`));
|
|
243
|
+
for (const task of running.values()) {
|
|
244
|
+
killTask(task);
|
|
245
|
+
}
|
|
246
|
+
// Wait briefly for processes to terminate
|
|
247
|
+
await Promise.all(Array.from(running.values()).map((t) => t.promise));
|
|
248
|
+
return results;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return results;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function _runSequential(
|
|
256
|
+
envs: string[],
|
|
257
|
+
pythonPath: string,
|
|
258
|
+
name?: string,
|
|
259
|
+
): Promise<ToxResult[]> {
|
|
260
|
+
const results: ToxResult[] = [];
|
|
261
|
+
for (const env of envs) {
|
|
262
|
+
const task = startToxEnv(env, pythonPath, name);
|
|
263
|
+
const result = await task.promise;
|
|
264
|
+
results.push(result);
|
|
265
|
+
}
|
|
266
|
+
return results;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function printSummary(results: ToxResult[]): void {
|
|
270
|
+
console.log("\n" + pc.bold("═".repeat(60)));
|
|
271
|
+
console.log(pc.bold(" Test Results Summary"));
|
|
272
|
+
console.log(pc.bold("═".repeat(60)) + "\n");
|
|
273
|
+
|
|
274
|
+
const passed = results.filter((r) => r.success);
|
|
275
|
+
const failed = results.filter((r) => !r.success);
|
|
276
|
+
const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
|
|
277
|
+
|
|
278
|
+
for (const result of results) {
|
|
279
|
+
const status = result.success ? pc.green("PASS") : pc.red("FAIL");
|
|
280
|
+
console.log(` ${status} ${result.env} (${result.duration.toFixed(1)}s)`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
console.log("\n" + "─".repeat(60));
|
|
284
|
+
console.log(
|
|
285
|
+
` ${pc.green(`Passed: ${passed.length}`)} ` +
|
|
286
|
+
`${pc.red(`Failed: ${failed.length}`)} ` +
|
|
287
|
+
`Total: ${results.length} ` +
|
|
288
|
+
`Duration: ${totalDuration.toFixed(1)}s`,
|
|
289
|
+
);
|
|
290
|
+
console.log("─".repeat(60) + "\n");
|
|
291
|
+
|
|
292
|
+
if (failed.length > 0) {
|
|
293
|
+
console.log(pc.red("Failed environments:"));
|
|
294
|
+
for (const result of failed) {
|
|
295
|
+
console.log(` - ${result.env}`);
|
|
296
|
+
if (result.failedTests && result.failedTests.length > 0) {
|
|
297
|
+
for (const test of result.failedTests) {
|
|
298
|
+
console.log(` ${pc.red("FAILED")} ${test}`);
|
|
299
|
+
}
|
|
300
|
+
} else if (result.error && !argv.values.quiet) {
|
|
301
|
+
console.log(` ${result.error.split("\n").slice(0, 5).join("\n ")}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
console.log();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function runEmitterTests(): Promise<ToxResult> {
|
|
309
|
+
const startTime = Date.now();
|
|
310
|
+
console.log(`${pc.blue("[START]")} emitter (vitest)`);
|
|
311
|
+
|
|
312
|
+
// Add node_modules/.bin directories to PATH so vitest can be found
|
|
313
|
+
const pathSep = process.platform === "win32" ? ";" : ":";
|
|
314
|
+
const binPaths = [
|
|
315
|
+
join(root, "node_modules", ".bin"),
|
|
316
|
+
join(monorepoRoot, "node_modules", ".bin"),
|
|
317
|
+
].join(pathSep);
|
|
318
|
+
const env = {
|
|
319
|
+
...process.env,
|
|
320
|
+
PATH: `${binPaths}${pathSep}${process.env.PATH}`,
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
return new Promise((resolve) => {
|
|
324
|
+
const proc: ChildProcess = spawn("vitest", ["run", "-c", "./emitter/vitest.config.ts"], {
|
|
325
|
+
cwd: root,
|
|
326
|
+
stdio: !argv.values.quiet ? "inherit" : "pipe",
|
|
327
|
+
shell: true,
|
|
328
|
+
env,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
let stderr = "";
|
|
332
|
+
if (argv.values.quiet && proc.stderr) {
|
|
333
|
+
proc.stderr.on("data", (data) => {
|
|
334
|
+
stderr += data.toString();
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
proc.on("close", (code) => {
|
|
339
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
340
|
+
const success = code === 0;
|
|
341
|
+
|
|
342
|
+
if (success) {
|
|
343
|
+
console.log(`${pc.green("[PASS]")} emitter (vitest) (${duration.toFixed(1)}s)`);
|
|
344
|
+
} else {
|
|
345
|
+
console.log(`${pc.red("[FAIL]")} emitter (vitest) (${duration.toFixed(1)}s)`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
resolve({
|
|
349
|
+
env: "emitter (vitest)",
|
|
350
|
+
success,
|
|
351
|
+
duration,
|
|
352
|
+
error: success ? undefined : stderr || `Exit code: ${code}`,
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
proc.on("error", (err) => {
|
|
357
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
358
|
+
console.log(`${pc.red("[ERROR]")} emitter (vitest): ${err.message}`);
|
|
359
|
+
resolve({
|
|
360
|
+
env: "emitter (vitest)",
|
|
361
|
+
success: false,
|
|
362
|
+
duration,
|
|
363
|
+
error: err.message,
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async function main(): Promise<void> {
|
|
370
|
+
const startTime = Date.now();
|
|
371
|
+
|
|
372
|
+
const runEmitter = argv.values.emitter;
|
|
373
|
+
const runGenerator = argv.values.generator;
|
|
374
|
+
const runBoth = !runEmitter && !runGenerator;
|
|
375
|
+
|
|
376
|
+
const allResults: ToxResult[] = [];
|
|
377
|
+
|
|
378
|
+
// Header
|
|
379
|
+
console.log(pc.cyan("\n╔══════════════════════════════════════════════════════════╗"));
|
|
380
|
+
console.log(
|
|
381
|
+
pc.cyan("║") +
|
|
382
|
+
pc.bold(" TypeSpec Python SDK Generator Tests ") +
|
|
383
|
+
pc.cyan("║"),
|
|
384
|
+
);
|
|
385
|
+
console.log(pc.cyan("╚══════════════════════════════════════════════════════════╝") + "\n");
|
|
386
|
+
|
|
387
|
+
// Run emitter tests if requested
|
|
388
|
+
if (runEmitter || runBoth) {
|
|
389
|
+
console.log(`${pc.bold("=== Emitter Tests (TypeScript) ===")}\n`);
|
|
390
|
+
const emitterResult = await runEmitterTests();
|
|
391
|
+
allResults.push(emitterResult);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Run generator tests if requested
|
|
395
|
+
if (runGenerator || runBoth) {
|
|
396
|
+
console.log(`\n${pc.bold("=== Generator Tests (Python) ===")}\n`);
|
|
397
|
+
|
|
398
|
+
// Determine flavors
|
|
399
|
+
const flavors = argv.values.flavor === "all" ? ["azure", "unbranded"] : [argv.values.flavor!];
|
|
400
|
+
|
|
401
|
+
// Determine environments
|
|
402
|
+
let baseEnvs: string[];
|
|
403
|
+
if (argv.values.env) {
|
|
404
|
+
baseEnvs = argv.values.env.split(",").map((e) => e.trim());
|
|
405
|
+
} else {
|
|
406
|
+
// Default: run test environments
|
|
407
|
+
baseEnvs = ["test"];
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Expand 'ci' and 'docs' into component environments for parallel execution
|
|
411
|
+
const expandedEnvs: string[] = [];
|
|
412
|
+
for (const env of baseEnvs) {
|
|
413
|
+
if (env === "ci") {
|
|
414
|
+
// All envs run in parallel — pre-built wheels make installs cheap
|
|
415
|
+
expandedEnvs.push("test", "lint", "mypy", "pyright", "apiview", "sphinx");
|
|
416
|
+
} else if (env === "docs") {
|
|
417
|
+
// Split docs into apiview + sphinx for parallelism
|
|
418
|
+
expandedEnvs.push("apiview", "sphinx");
|
|
419
|
+
} else {
|
|
420
|
+
expandedEnvs.push(env);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Build full environment list
|
|
425
|
+
const envs: string[] = [];
|
|
426
|
+
for (const env of expandedEnvs) {
|
|
427
|
+
if (env === "unittest") {
|
|
428
|
+
envs.push("unittest");
|
|
429
|
+
} else {
|
|
430
|
+
for (const flavor of flavors) {
|
|
431
|
+
envs.push(`${env}-${flavor}`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Get Python path
|
|
437
|
+
let pythonPath: string;
|
|
438
|
+
try {
|
|
439
|
+
pythonPath = getVenvPython();
|
|
440
|
+
} catch (error) {
|
|
441
|
+
console.error(pc.red((error as Error).message));
|
|
442
|
+
process.exit(1);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const maxJobs = argv.values.jobs
|
|
446
|
+
? parseInt(argv.values.jobs, 10)
|
|
447
|
+
: Math.max(2, cpus().length - 2);
|
|
448
|
+
|
|
449
|
+
console.log(` Flavors: ${flavors.join(", ")}`);
|
|
450
|
+
console.log(` Environments: ${envs.join(", ")}`);
|
|
451
|
+
console.log(` Jobs: ${maxJobs}`);
|
|
452
|
+
if (argv.values.name) {
|
|
453
|
+
console.log(` Filter: ${argv.values.name}`);
|
|
454
|
+
}
|
|
455
|
+
console.log();
|
|
456
|
+
|
|
457
|
+
// Pre-build wheels for each flavor so tox envs install from pre-built
|
|
458
|
+
// wheels instead of rebuilding from source (~2min build once vs ~2min × N envs)
|
|
459
|
+
console.log(pc.cyan("Pre-building wheels for all flavors..."));
|
|
460
|
+
const installScript = join(testsDir, "install_packages.py");
|
|
461
|
+
for (const flavor of flavors) {
|
|
462
|
+
const startTime = Date.now();
|
|
463
|
+
const proc = spawn(pythonPath, [installScript, "build", flavor, testsDir], {
|
|
464
|
+
cwd: testsDir,
|
|
465
|
+
stdio: "inherit",
|
|
466
|
+
});
|
|
467
|
+
await new Promise<void>((resolve) => {
|
|
468
|
+
proc.on("close", (code) => {
|
|
469
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
470
|
+
if (code === 0) {
|
|
471
|
+
console.log(`${pc.green("[PASS]")} wheel build ${flavor} (${duration}s)`);
|
|
472
|
+
} else {
|
|
473
|
+
console.log(
|
|
474
|
+
`${pc.yellow("[WARN]")} wheel build ${flavor} failed (${duration}s), tox envs will build from source`,
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
resolve();
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
console.log();
|
|
482
|
+
|
|
483
|
+
// Run all environments in parallel
|
|
484
|
+
// The mock server serves both azure and unbranded specs, so all tests can run together
|
|
485
|
+
console.log(pc.cyan("Running all environments in parallel..."));
|
|
486
|
+
const results = await runParallel(envs, pythonPath, maxJobs, argv.values.name);
|
|
487
|
+
|
|
488
|
+
allResults.push(...results);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Print summary
|
|
492
|
+
printSummary(allResults);
|
|
493
|
+
|
|
494
|
+
const totalDuration = (Date.now() - startTime) / 1000;
|
|
495
|
+
console.log(`Total execution time: ${totalDuration.toFixed(1)}s\n`);
|
|
496
|
+
|
|
497
|
+
// Exit with appropriate code
|
|
498
|
+
const failed = allResults.filter((r) => !r.success);
|
|
499
|
+
if (failed.length > 0) {
|
|
500
|
+
process.exit(1);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
main().catch((error) => {
|
|
505
|
+
console.error(`${pc.red("Unexpected error:")}`, error);
|
|
506
|
+
process.exit(1);
|
|
507
|
+
});
|
|
@@ -10,32 +10,38 @@
|
|
|
10
10
|
|
|
11
11
|
import os
|
|
12
12
|
import sys
|
|
13
|
-
from subprocess import
|
|
13
|
+
from subprocess import run, TimeoutExpired
|
|
14
14
|
import logging
|
|
15
15
|
from util import run_check
|
|
16
16
|
|
|
17
17
|
logging.getLogger().setLevel(logging.INFO)
|
|
18
18
|
|
|
19
|
+
# Timeout for each apiview generation (seconds)
|
|
20
|
+
APIVIEW_TIMEOUT = 30
|
|
21
|
+
|
|
19
22
|
|
|
20
23
|
def _single_dir_apiview(mod):
|
|
21
|
-
|
|
22
|
-
while True:
|
|
24
|
+
for attempt in range(2):
|
|
23
25
|
try:
|
|
24
|
-
|
|
25
|
-
[
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
str(mod.absolute()),
|
|
29
|
-
]
|
|
26
|
+
result = run(
|
|
27
|
+
["apistubgen", "--pkg-path", str(mod.absolute())],
|
|
28
|
+
capture_output=True,
|
|
29
|
+
timeout=APIVIEW_TIMEOUT,
|
|
30
30
|
)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
if result.returncode == 0:
|
|
32
|
+
return True
|
|
33
|
+
if attempt == 1:
|
|
34
|
+
logging.error(f"{mod.stem} failed: {result.stderr.decode()[:200]}")
|
|
35
|
+
return False
|
|
36
|
+
except TimeoutExpired:
|
|
37
|
+
if attempt == 1:
|
|
38
|
+
logging.error(f"{mod.stem} timed out after {APIVIEW_TIMEOUT}s")
|
|
39
|
+
return False
|
|
40
|
+
except Exception as e:
|
|
41
|
+
if attempt == 1:
|
|
42
|
+
logging.error(f"{mod.stem} error: {e}")
|
|
34
43
|
return False
|
|
35
|
-
|
|
36
|
-
loop += 1
|
|
37
|
-
continue
|
|
38
|
-
return True
|
|
44
|
+
return False
|
|
39
45
|
|
|
40
46
|
|
|
41
47
|
if __name__ == "__main__":
|
|
@@ -12,37 +12,48 @@ from subprocess import check_call, CalledProcessError
|
|
|
12
12
|
import os
|
|
13
13
|
import logging
|
|
14
14
|
import sys
|
|
15
|
-
from util import run_check
|
|
15
|
+
from util import run_check, get_package_namespace_dir
|
|
16
16
|
|
|
17
17
|
logging.getLogger().setLevel(logging.INFO)
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def get_config_file_location():
|
|
21
|
-
|
|
21
|
+
# When running from tests/ directory via tox
|
|
22
|
+
mypy_ini_path = os.path.join(os.getcwd(), "../eng/scripts/ci/config/mypy.ini")
|
|
22
23
|
if os.path.exists(mypy_ini_path):
|
|
23
24
|
return mypy_ini_path
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def _single_dir_mypy(mod):
|
|
29
|
-
inner_class =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
[
|
|
33
|
-
sys.executable,
|
|
34
|
-
"-m",
|
|
35
|
-
"mypy",
|
|
36
|
-
"--config-file",
|
|
37
|
-
get_config_file_location(),
|
|
38
|
-
"--ignore-missing",
|
|
39
|
-
str(inner_class.absolute()),
|
|
40
|
-
]
|
|
41
|
-
)
|
|
25
|
+
# Fallback for running from different directories
|
|
26
|
+
return os.path.join(os.path.dirname(__file__), "config/mypy.ini")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _single_dir_mypy(mod, retries=2):
|
|
30
|
+
inner_class = get_package_namespace_dir(mod)
|
|
31
|
+
if not inner_class:
|
|
32
|
+
logging.info(f"No package directory found in {mod}, skipping")
|
|
42
33
|
return True
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
for attempt in range(1, retries + 2):
|
|
35
|
+
try:
|
|
36
|
+
check_call(
|
|
37
|
+
[
|
|
38
|
+
sys.executable,
|
|
39
|
+
"-m",
|
|
40
|
+
"mypy",
|
|
41
|
+
"--config-file",
|
|
42
|
+
get_config_file_location(),
|
|
43
|
+
"--ignore-missing",
|
|
44
|
+
str(inner_class.absolute()),
|
|
45
|
+
]
|
|
46
|
+
)
|
|
47
|
+
return True
|
|
48
|
+
except CalledProcessError as e:
|
|
49
|
+
if attempt <= retries:
|
|
50
|
+
logging.warning(
|
|
51
|
+
"{} mypy attempt {} failed (exit {}), retrying...".format(inner_class.stem, attempt, e.returncode)
|
|
52
|
+
)
|
|
53
|
+
else:
|
|
54
|
+
logging.error("{} exited with mypy error {}".format(inner_class.stem, e.returncode))
|
|
55
|
+
return False
|
|
56
|
+
return False
|
|
46
57
|
|
|
47
58
|
|
|
48
59
|
if __name__ == "__main__":
|
|
@@ -12,36 +12,44 @@ from subprocess import check_call, CalledProcessError
|
|
|
12
12
|
import os
|
|
13
13
|
import logging
|
|
14
14
|
import sys
|
|
15
|
-
from util import run_check
|
|
15
|
+
from util import run_check, get_package_namespace_dir
|
|
16
16
|
|
|
17
17
|
logging.getLogger().setLevel(logging.INFO)
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def get_rfc_file_location():
|
|
21
|
-
|
|
21
|
+
# When running from tests/ directory via tox
|
|
22
|
+
rfc_file_location = os.path.join(os.getcwd(), "../eng/scripts/ci/config/pylintrc")
|
|
22
23
|
if os.path.exists(rfc_file_location):
|
|
23
24
|
return rfc_file_location
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
# Fallback for running from different directories
|
|
26
|
+
return os.path.join(os.path.dirname(__file__), "config/pylintrc")
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
def _single_dir_pylint(mod):
|
|
29
|
-
inner_class =
|
|
30
|
+
inner_class = get_package_namespace_dir(mod)
|
|
31
|
+
if not inner_class:
|
|
32
|
+
logging.info(f"No package directory found in {mod}, skipping")
|
|
33
|
+
return True
|
|
34
|
+
# Only load the Azure pylint guidelines checker plugin for azure packages.
|
|
35
|
+
# The plugin (azure-pylint-guidelines-checker) is only installed in the
|
|
36
|
+
# lint-azure tox environment and is not available for unbranded packages.
|
|
37
|
+
is_azure = "azure" in mod.parts
|
|
38
|
+
pylint_args = [
|
|
39
|
+
sys.executable,
|
|
40
|
+
"-m",
|
|
41
|
+
"pylint",
|
|
42
|
+
"--rcfile={}".format(get_rfc_file_location()),
|
|
43
|
+
"--evaluation=(max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention + info)/ statement) * 10)))",
|
|
44
|
+
"--output-format=parseable",
|
|
45
|
+
"--recursive=y",
|
|
46
|
+
"--py-version=3.10",
|
|
47
|
+
]
|
|
48
|
+
if is_azure:
|
|
49
|
+
pylint_args.append("--load-plugins=pylint_guidelines_checker")
|
|
50
|
+
pylint_args.append(str(inner_class.absolute()))
|
|
30
51
|
try:
|
|
31
|
-
check_call(
|
|
32
|
-
[
|
|
33
|
-
sys.executable,
|
|
34
|
-
"-m",
|
|
35
|
-
"pylint",
|
|
36
|
-
"--rcfile={}".format(get_rfc_file_location()),
|
|
37
|
-
"--evaluation=(max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention + info)/ statement) * 10)))",
|
|
38
|
-
"--load-plugins=pylint_guidelines_checker",
|
|
39
|
-
"--output-format=parseable",
|
|
40
|
-
"--recursive=y",
|
|
41
|
-
"--py-version=3.9",
|
|
42
|
-
str(inner_class.absolute()),
|
|
43
|
-
]
|
|
44
|
-
)
|
|
52
|
+
check_call(pylint_args)
|
|
45
53
|
return True
|
|
46
54
|
except CalledProcessError as e:
|
|
47
55
|
logging.error("{} exited with linting error {}".format(str(inner_class.absolute()), e.returncode))
|