@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.
Files changed (368) hide show
  1. package/dist/emitter/code-model.d.ts.map +1 -1
  2. package/dist/emitter/code-model.js +7 -6
  3. package/dist/emitter/code-model.js.map +1 -1
  4. package/dist/emitter/constants.d.ts +6 -0
  5. package/dist/emitter/constants.d.ts.map +1 -0
  6. package/dist/emitter/constants.js +27 -0
  7. package/dist/emitter/constants.js.map +1 -0
  8. package/dist/emitter/emitter.d.ts.map +1 -1
  9. package/dist/emitter/emitter.js +193 -119
  10. package/dist/emitter/emitter.js.map +1 -1
  11. package/dist/emitter/http.d.ts.map +1 -1
  12. package/dist/emitter/http.js +33 -1
  13. package/dist/emitter/http.js.map +1 -1
  14. package/dist/emitter/lib.d.ts +37 -3
  15. package/dist/emitter/lib.d.ts.map +1 -1
  16. package/dist/emitter/lib.js +17 -0
  17. package/dist/emitter/lib.js.map +1 -1
  18. package/dist/emitter/run-python3.js +1 -1
  19. package/dist/emitter/run-python3.js.map +1 -1
  20. package/dist/emitter/system-requirements.js +6 -4
  21. package/dist/emitter/system-requirements.js.map +1 -1
  22. package/dist/emitter/types.d.ts +2 -5
  23. package/dist/emitter/types.d.ts.map +1 -1
  24. package/dist/emitter/types.js +86 -63
  25. package/dist/emitter/types.js.map +1 -1
  26. package/dist/emitter/utils.d.ts.map +1 -1
  27. package/dist/emitter/utils.js +16 -17
  28. package/dist/emitter/utils.js.map +1 -1
  29. package/emitter/src/code-model.ts +7 -13
  30. package/emitter/src/constants.ts +27 -0
  31. package/emitter/src/emitter.ts +241 -123
  32. package/emitter/src/http.ts +29 -1
  33. package/emitter/src/lib.ts +24 -0
  34. package/emitter/src/run-python3.ts +1 -1
  35. package/emitter/src/system-requirements.ts +4 -4
  36. package/emitter/src/types.ts +102 -62
  37. package/emitter/src/utils.ts +16 -18
  38. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  39. package/emitter/test/utils.test.ts +3 -0
  40. package/emitter/tsconfig.build.json +2 -1
  41. package/emitter/tsconfig.json +2 -1
  42. package/eng/scripts/Build-Packages.ps1 +62 -37
  43. package/eng/scripts/Check-GitChanges.ps1 +30 -3
  44. package/eng/scripts/Functions.ps1 +54 -15
  45. package/eng/scripts/Generate.ps1 +42 -8
  46. package/eng/scripts/Generation.psm1 +44 -15
  47. package/eng/scripts/Initialize-Repository.ps1 +29 -11
  48. package/eng/scripts/Test-Packages.ps1 +47 -31
  49. package/eng/scripts/ci/config/eslint-ci.config.mjs +64 -0
  50. package/eng/scripts/ci/{mypy.ini → config/mypy.ini} +1 -1
  51. package/eng/scripts/ci/{pylintrc → config/pylintrc} +1 -1
  52. package/eng/scripts/ci/{pyrightconfig.json → config/pyrightconfig.json} +1 -1
  53. package/eng/scripts/ci/dev_requirements.txt +2 -1
  54. package/eng/scripts/ci/format.ts +232 -2
  55. package/eng/scripts/ci/lint.ts +223 -20
  56. package/eng/scripts/ci/regenerate-common.ts +411 -136
  57. package/eng/scripts/ci/regenerate.ts +247 -101
  58. package/eng/scripts/ci/run-tests.ts +507 -0
  59. package/eng/scripts/ci/run_apiview.py +22 -16
  60. package/eng/scripts/ci/run_mypy.py +34 -23
  61. package/eng/scripts/ci/run_pylint.py +27 -19
  62. package/eng/scripts/ci/run_pyright.py +9 -5
  63. package/eng/scripts/ci/run_sphinx_build.py +24 -9
  64. package/eng/scripts/ci/typecheck.ts +225 -0
  65. package/eng/scripts/ci/util.py +61 -25
  66. package/eng/scripts/ci/utils.ts +5 -5
  67. package/eng/scripts/setup/__pycache__/package_manager.cpython-311.pyc +0 -0
  68. package/eng/scripts/setup/__pycache__/venvtools.cpython-311.pyc +0 -0
  69. package/eng/scripts/setup/build.ts +1 -1
  70. package/eng/scripts/setup/build_pygen_wheel.py +4 -3
  71. package/eng/scripts/setup/install.py +4 -3
  72. package/eng/scripts/setup/install.ts +1 -1
  73. package/eng/scripts/setup/prepare.py +3 -2
  74. package/eng/scripts/setup/prepare.ts +1 -1
  75. package/eng/scripts/setup/run-python3.ts +1 -1
  76. package/eng/scripts/setup/run_batch.py +197 -0
  77. package/eng/scripts/setup/run_tsp.py +3 -3
  78. package/eng/scripts/setup/system-requirements.ts +8 -4
  79. package/eng/scripts/setup/venvtools.py +1 -1
  80. package/generator/build/lib/pygen/__init__.py +1 -3
  81. package/generator/build/lib/pygen/codegen/__init__.py +0 -1
  82. package/generator/build/lib/pygen/codegen/models/base.py +0 -1
  83. package/generator/build/lib/pygen/codegen/models/client.py +2 -1
  84. package/generator/build/lib/pygen/codegen/models/code_model.py +1 -0
  85. package/generator/build/lib/pygen/codegen/models/enum_type.py +0 -1
  86. package/generator/build/lib/pygen/codegen/models/model_type.py +1 -7
  87. package/generator/build/lib/pygen/codegen/models/parameter.py +16 -14
  88. package/generator/build/lib/pygen/codegen/serializers/__init__.py +27 -12
  89. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +12 -3
  90. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +6 -2
  91. package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +17 -4
  92. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +17 -11
  93. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +176 -71
  94. package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +11 -3
  95. package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +1 -1
  96. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +5 -1
  97. package/generator/build/lib/pygen/preprocess/__init__.py +37 -30
  98. package/generator/component-detection-pip-report.json +7 -7
  99. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  100. package/generator/pygen/__init__.py +1 -3
  101. package/generator/pygen/codegen/__init__.py +0 -1
  102. package/generator/pygen/codegen/models/base.py +0 -1
  103. package/generator/pygen/codegen/models/client.py +2 -1
  104. package/generator/pygen/codegen/models/code_model.py +1 -0
  105. package/generator/pygen/codegen/models/enum_type.py +0 -1
  106. package/generator/pygen/codegen/models/model_type.py +1 -7
  107. package/generator/pygen/codegen/models/parameter.py +16 -14
  108. package/generator/pygen/codegen/serializers/__init__.py +27 -12
  109. package/generator/pygen/codegen/serializers/builder_serializer.py +12 -3
  110. package/generator/pygen/codegen/serializers/general_serializer.py +6 -2
  111. package/generator/pygen/codegen/serializers/import_serializer.py +17 -4
  112. package/generator/pygen/codegen/serializers/parameter_serializer.py +17 -11
  113. package/generator/pygen/codegen/templates/model_base.py.jinja2 +176 -71
  114. package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +11 -3
  115. package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +1 -1
  116. package/generator/pygen/codegen/templates/serialization.py.jinja2 +5 -1
  117. package/generator/pygen/preprocess/__init__.py +37 -30
  118. package/generator/pygen.egg-info/PKG-INFO +1 -2
  119. package/generator/pygen.egg-info/requires.txt +1 -1
  120. package/generator/setup.py +1 -2
  121. package/package.json +63 -42
  122. package/eng/scripts/ci/run-ci.ts +0 -89
  123. package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_commonproperties_async.py +0 -94
  124. package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_largeheader_async.py +0 -30
  125. package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_nonresource_async.py +0 -36
  126. package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py +0 -205
  127. package/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_resource_async.py +0 -478
  128. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py +0 -101
  129. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_header_async.py +0 -18
  130. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_path_async.py +0 -18
  131. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_query_async.py +0 -18
  132. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_default_value_async.py +0 -46
  133. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_initialization_async.py +0 -58
  134. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_location_async.py +0 -82
  135. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py +0 -20
  136. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +0 -115
  137. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py +0 -53
  138. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_next_link_verb_async.py +0 -28
  139. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_override_async.py +0 -106
  140. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_usage_async.py +0 -38
  141. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_basic_async.py +0 -76
  142. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py +0 -22
  143. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_standard_async.py +0 -39
  144. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_model_async.py +0 -33
  145. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_page_async.py +0 -80
  146. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_scalar_async.py +0 -41
  147. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_traits_async.py +0 -87
  148. package/generator/test/azure/mock_api_tests/asynctests/test_azure_encode_duration_async.py +0 -19
  149. package/generator/test/azure/mock_api_tests/asynctests/test_azure_example_basic_async.py +0 -30
  150. package/generator/test/azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py +0 -19
  151. package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_method_subscription_id_async.py +0 -248
  152. package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_async.py +0 -110
  153. package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py +0 -132
  154. package/generator/test/azure/mock_api_tests/asynctests/test_azure_special_headers_client_request_id_async.py +0 -30
  155. package/generator/test/azure/mock_api_tests/asynctests/test_azure_versioning_previewversion_async.py +0 -53
  156. package/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +0 -34
  157. package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_async.py +0 -69
  158. package/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py +0 -37
  159. package/generator/test/azure/mock_api_tests/asynctests/test_client_overload_async.py +0 -27
  160. package/generator/test/azure/mock_api_tests/asynctests/test_client_structure_async.py +0 -64
  161. package/generator/test/azure/mock_api_tests/asynctests/test_client_structure_clientoperationgroup_async.py +0 -31
  162. package/generator/test/azure/mock_api_tests/asynctests/test_encode_duration_async.py +0 -63
  163. package/generator/test/azure/mock_api_tests/asynctests/test_encode_numeric_async.py +0 -35
  164. package/generator/test/azure/mock_api_tests/asynctests/test_parameters_basic_async.py +0 -24
  165. package/generator/test/azure/mock_api_tests/asynctests/test_parameters_spread_async.py +0 -76
  166. package/generator/test/azure/mock_api_tests/asynctests/test_payload_content_negotiation_async.py +0 -37
  167. package/generator/test/azure/mock_api_tests/asynctests/test_payload_multipart_async.py +0 -216
  168. package/generator/test/azure/mock_api_tests/asynctests/test_resiliency_srv_driven_async.py +0 -130
  169. package/generator/test/azure/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py +0 -24
  170. package/generator/test/azure/mock_api_tests/asynctests/test_service_multi_service_async.py +0 -31
  171. package/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py +0 -71
  172. package/generator/test/azure/mock_api_tests/conftest.py +0 -207
  173. package/generator/test/azure/mock_api_tests/data/image.jpg +0 -0
  174. package/generator/test/azure/mock_api_tests/data/image.png +0 -0
  175. package/generator/test/azure/mock_api_tests/test_azure_arm_commonproperties.py +0 -89
  176. package/generator/test/azure/mock_api_tests/test_azure_arm_largeheader.py +0 -27
  177. package/generator/test/azure/mock_api_tests/test_azure_arm_nonresource.py +0 -34
  178. package/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py +0 -180
  179. package/generator/test/azure/mock_api_tests/test_azure_arm_resource.py +0 -436
  180. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_access.py +0 -92
  181. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_header.py +0 -17
  182. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_path.py +0 -17
  183. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_query.py +0 -17
  184. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_default_value.py +0 -42
  185. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_initialization.py +0 -51
  186. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_location.py +0 -70
  187. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_deserialize_empty_string_as_null.py +0 -19
  188. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +0 -104
  189. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_hierrarchy_building.py +0 -45
  190. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_next_link_verb.py +0 -27
  191. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_override.py +0 -102
  192. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_usage.py +0 -32
  193. package/generator/test/azure/mock_api_tests/test_azure_core_basic.py +0 -70
  194. package/generator/test/azure/mock_api_tests/test_azure_core_lro_rpc.py +0 -20
  195. package/generator/test/azure/mock_api_tests/test_azure_core_lro_standard.py +0 -32
  196. package/generator/test/azure/mock_api_tests/test_azure_core_model.py +0 -30
  197. package/generator/test/azure/mock_api_tests/test_azure_core_page.py +0 -71
  198. package/generator/test/azure/mock_api_tests/test_azure_core_scalar.py +0 -35
  199. package/generator/test/azure/mock_api_tests/test_azure_core_traits.py +0 -85
  200. package/generator/test/azure/mock_api_tests/test_azure_encode_duration.py +0 -18
  201. package/generator/test/azure/mock_api_tests/test_azure_example_basic.py +0 -29
  202. package/generator/test/azure/mock_api_tests/test_azure_payload_pageable.py +0 -18
  203. package/generator/test/azure/mock_api_tests/test_azure_resource_manager_method_subscription_id.py +0 -235
  204. package/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service.py +0 -104
  205. package/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service_shared_models.py +0 -128
  206. package/generator/test/azure/mock_api_tests/test_azure_special_headers_client_request_id.py +0 -29
  207. package/generator/test/azure/mock_api_tests/test_azure_versioning_previewversion.py +0 -50
  208. package/generator/test/azure/mock_api_tests/test_clear_output_folder.py +0 -23
  209. package/generator/test/azure/mock_api_tests/test_client_namespace.py +0 -32
  210. package/generator/test/azure/mock_api_tests/test_client_naming.py +0 -57
  211. package/generator/test/azure/mock_api_tests/test_client_naming_enum_conflict.py +0 -35
  212. package/generator/test/azure/mock_api_tests/test_client_overload.py +0 -25
  213. package/generator/test/azure/mock_api_tests/test_client_structure.py +0 -60
  214. package/generator/test/azure/mock_api_tests/test_client_structure_clientoperationgroup.py +0 -29
  215. package/generator/test/azure/mock_api_tests/test_encode_duration.py +0 -60
  216. package/generator/test/azure/mock_api_tests/test_encode_numeric.py +0 -31
  217. package/generator/test/azure/mock_api_tests/test_model_base_flatten_compatibility.py +0 -251
  218. package/generator/test/azure/mock_api_tests/test_parameters_basic.py +0 -22
  219. package/generator/test/azure/mock_api_tests/test_parameters_spread.py +0 -66
  220. package/generator/test/azure/mock_api_tests/test_payload_content_negotiation.py +0 -33
  221. package/generator/test/azure/mock_api_tests/test_payload_multipart.py +0 -198
  222. package/generator/test/azure/mock_api_tests/test_resiliency_srv_driven.py +0 -124
  223. package/generator/test/azure/mock_api_tests/test_serialization_encoded_name_json.py +0 -21
  224. package/generator/test/azure/mock_api_tests/test_service_multi_service.py +0 -29
  225. package/generator/test/azure/mock_api_tests/test_special_words.py +0 -63
  226. package/generator/test/azure/requirements.txt +0 -125
  227. package/generator/test/azure/tox.ini +0 -64
  228. package/generator/test/data/image.jpg +0 -0
  229. package/generator/test/data/image.png +0 -0
  230. package/generator/test/dev_requirements.txt +0 -8
  231. package/generator/test/generic_mock_api_tests/asynctests/test_authentication_async.py +0 -140
  232. package/generator/test/generic_mock_api_tests/asynctests/test_encode_array_async.py +0 -139
  233. package/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py +0 -132
  234. package/generator/test/generic_mock_api_tests/asynctests/test_encode_datetime_async.py +0 -127
  235. package/generator/test/generic_mock_api_tests/asynctests/test_headasboolean_async.py +0 -35
  236. package/generator/test/generic_mock_api_tests/asynctests/test_parameters_body_optionality_async.py +0 -30
  237. package/generator/test/generic_mock_api_tests/asynctests/test_parameters_collection_format_async.py +0 -38
  238. package/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py +0 -24
  239. package/generator/test/generic_mock_api_tests/asynctests/test_parameters_query_async.py +0 -18
  240. package/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py +0 -98
  241. package/generator/test/generic_mock_api_tests/asynctests/test_payload_media_type_async.py +0 -27
  242. package/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py +0 -134
  243. package/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py +0 -150
  244. package/generator/test/generic_mock_api_tests/asynctests/test_response_status_code_range_async.py +0 -38
  245. package/generator/test/generic_mock_api_tests/asynctests/test_routes_async.py +0 -331
  246. package/generator/test/generic_mock_api_tests/asynctests/test_server_endpoint_not_defined_async.py +0 -18
  247. package/generator/test/generic_mock_api_tests/asynctests/test_server_path_multiple_async.py +0 -25
  248. package/generator/test/generic_mock_api_tests/asynctests/test_server_path_single_async.py +0 -18
  249. package/generator/test/generic_mock_api_tests/asynctests/test_server_versions_not_versioned_async.py +0 -28
  250. package/generator/test/generic_mock_api_tests/asynctests/test_server_versions_versioned_async.py +0 -34
  251. package/generator/test/generic_mock_api_tests/asynctests/test_special_headers_conditional_request_async.py +0 -38
  252. package/generator/test/generic_mock_api_tests/asynctests/test_special_headers_repeatability_async.py +0 -19
  253. package/generator/test/generic_mock_api_tests/asynctests/test_specs_documentation_async.py +0 -59
  254. package/generator/test/generic_mock_api_tests/asynctests/test_streaming_jsonl_async.py +0 -27
  255. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_array_async.py +0 -127
  256. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_dictionary_async.py +0 -98
  257. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_extensible_async.py +0 -25
  258. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_fixed_async.py +0 -27
  259. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_file_async.py +0 -59
  260. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_empty_async.py +0 -32
  261. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py +0 -70
  262. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py +0 -85
  263. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_not_discriminated_async.py +0 -34
  264. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_recursive_async.py +0 -34
  265. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_single_discriminator_async.py +0 -67
  266. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_usage_async.py +0 -32
  267. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_visibility_async.py +0 -47
  268. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_additionalproperties_async.py +0 -353
  269. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py +0 -110
  270. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_optional_async.py +0 -197
  271. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_valuetypes_async.py +0 -315
  272. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_scalar_async.py +0 -60
  273. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_union_async.py +0 -90
  274. package/generator/test/generic_mock_api_tests/asynctests/test_versioning_added_async.py +0 -36
  275. package/generator/test/generic_mock_api_tests/asynctests/test_versioning_made_optional_async.py +0 -21
  276. package/generator/test/generic_mock_api_tests/asynctests/test_versioning_removed_async.py +0 -39
  277. package/generator/test/generic_mock_api_tests/asynctests/test_versioning_renamed_from_async.py +0 -29
  278. package/generator/test/generic_mock_api_tests/asynctests/test_versioning_return_type_changed_from_async.py +0 -18
  279. package/generator/test/generic_mock_api_tests/asynctests/test_versioning_type_changed_from_async.py +0 -22
  280. package/generator/test/generic_mock_api_tests/conftest.py +0 -75
  281. package/generator/test/generic_mock_api_tests/data/image.jpg +0 -0
  282. package/generator/test/generic_mock_api_tests/data/image.png +0 -0
  283. package/generator/test/generic_mock_api_tests/test_authentication.py +0 -130
  284. package/generator/test/generic_mock_api_tests/test_encode_array.py +0 -126
  285. package/generator/test/generic_mock_api_tests/test_encode_bytes.py +0 -128
  286. package/generator/test/generic_mock_api_tests/test_encode_datetime.py +0 -123
  287. package/generator/test/generic_mock_api_tests/test_headasboolean.py +0 -33
  288. package/generator/test/generic_mock_api_tests/test_parameters_body_optionality.py +0 -27
  289. package/generator/test/generic_mock_api_tests/test_parameters_collection_format.py +0 -33
  290. package/generator/test/generic_mock_api_tests/test_parameters_path.py +0 -22
  291. package/generator/test/generic_mock_api_tests/test_parameters_query.py +0 -17
  292. package/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py +0 -93
  293. package/generator/test/generic_mock_api_tests/test_payload_media_type.py +0 -25
  294. package/generator/test/generic_mock_api_tests/test_payload_pageable.py +0 -99
  295. package/generator/test/generic_mock_api_tests/test_payload_xml.py +0 -135
  296. package/generator/test/generic_mock_api_tests/test_response_status_code_range.py +0 -36
  297. package/generator/test/generic_mock_api_tests/test_routes.py +0 -285
  298. package/generator/test/generic_mock_api_tests/test_server_endpoint_not_defined.py +0 -17
  299. package/generator/test/generic_mock_api_tests/test_server_path_multiple.py +0 -21
  300. package/generator/test/generic_mock_api_tests/test_server_path_single.py +0 -17
  301. package/generator/test/generic_mock_api_tests/test_server_versions_not_versioned.py +0 -25
  302. package/generator/test/generic_mock_api_tests/test_server_versions_versioned.py +0 -30
  303. package/generator/test/generic_mock_api_tests/test_special_headers_conditional_request.py +0 -34
  304. package/generator/test/generic_mock_api_tests/test_special_headers_repeatability.py +0 -18
  305. package/generator/test/generic_mock_api_tests/test_specs_documentation.py +0 -51
  306. package/generator/test/generic_mock_api_tests/test_streaming_jsonl.py +0 -25
  307. package/generator/test/generic_mock_api_tests/test_typetest_array.py +0 -111
  308. package/generator/test/generic_mock_api_tests/test_typetest_dictionary.py +0 -86
  309. package/generator/test/generic_mock_api_tests/test_typetest_enum_extensible.py +0 -23
  310. package/generator/test/generic_mock_api_tests/test_typetest_enum_fixed.py +0 -25
  311. package/generator/test/generic_mock_api_tests/test_typetest_file.py +0 -52
  312. package/generator/test/generic_mock_api_tests/test_typetest_model_empty.py +0 -29
  313. package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_enum_discriminator.py +0 -58
  314. package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_nested_discriminator.py +0 -79
  315. package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_not_discriminated.py +0 -31
  316. package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_recursive.py +0 -32
  317. package/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_single_discriminator.py +0 -60
  318. package/generator/test/generic_mock_api_tests/test_typetest_model_usage.py +0 -28
  319. package/generator/test/generic_mock_api_tests/test_typetest_model_visibility.py +0 -40
  320. package/generator/test/generic_mock_api_tests/test_typetest_property_additionalproperties.py +0 -314
  321. package/generator/test/generic_mock_api_tests/test_typetest_property_nullable.py +0 -102
  322. package/generator/test/generic_mock_api_tests/test_typetest_property_optional.py +0 -174
  323. package/generator/test/generic_mock_api_tests/test_typetest_property_valuetypes.py +0 -286
  324. package/generator/test/generic_mock_api_tests/test_typetest_scalar.py +0 -53
  325. package/generator/test/generic_mock_api_tests/test_typetest_union.py +0 -80
  326. package/generator/test/generic_mock_api_tests/test_typetest_union_discriminated.py +0 -290
  327. package/generator/test/generic_mock_api_tests/test_versioning_added.py +0 -33
  328. package/generator/test/generic_mock_api_tests/test_versioning_made_optional.py +0 -20
  329. package/generator/test/generic_mock_api_tests/test_versioning_removed.py +0 -37
  330. package/generator/test/generic_mock_api_tests/test_versioning_renamed_from.py +0 -27
  331. package/generator/test/generic_mock_api_tests/test_versioning_return_type_changed_from.py +0 -17
  332. package/generator/test/generic_mock_api_tests/test_versioning_type_changed_from.py +0 -21
  333. package/generator/test/unbranded/mock_api_tests/asynctests/test_auth_flow_async.py +0 -19
  334. package/generator/test/unbranded/mock_api_tests/asynctests/test_encode_duration_async.py +0 -63
  335. package/generator/test/unbranded/mock_api_tests/asynctests/test_encode_numeric_async.py +0 -35
  336. package/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_basic_async.py +0 -24
  337. package/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_spread_async.py +0 -76
  338. package/generator/test/unbranded/mock_api_tests/asynctests/test_payload_content_negotiation_async.py +0 -37
  339. package/generator/test/unbranded/mock_api_tests/asynctests/test_payload_multipart_async.py +0 -218
  340. package/generator/test/unbranded/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py +0 -24
  341. package/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py +0 -73
  342. package/generator/test/unbranded/mock_api_tests/asynctests/test_unbranded_async.py +0 -24
  343. package/generator/test/unbranded/mock_api_tests/conftest.py +0 -91
  344. package/generator/test/unbranded/mock_api_tests/data/image.jpg +0 -0
  345. package/generator/test/unbranded/mock_api_tests/data/image.png +0 -0
  346. package/generator/test/unbranded/mock_api_tests/test_auth_flow.py +0 -17
  347. package/generator/test/unbranded/mock_api_tests/test_encode_duration.py +0 -60
  348. package/generator/test/unbranded/mock_api_tests/test_encode_numeric.py +0 -32
  349. package/generator/test/unbranded/mock_api_tests/test_parameters_basic.py +0 -22
  350. package/generator/test/unbranded/mock_api_tests/test_parameters_spread.py +0 -66
  351. package/generator/test/unbranded/mock_api_tests/test_payload_content_negotiation.py +0 -33
  352. package/generator/test/unbranded/mock_api_tests/test_payload_multipart.py +0 -200
  353. package/generator/test/unbranded/mock_api_tests/test_serialization_encoded_name_json.py +0 -22
  354. package/generator/test/unbranded/mock_api_tests/test_special_words.py +0 -66
  355. package/generator/test/unbranded/mock_api_tests/test_unbranded.py +0 -65
  356. package/generator/test/unbranded/requirements.txt +0 -69
  357. package/generator/test/unbranded/tox.ini +0 -64
  358. package/generator/test/unittests/conftest.py +0 -15
  359. package/generator/test/unittests/requirements.txt +0 -3
  360. package/generator/test/unittests/test_enums.py +0 -89
  361. package/generator/test/unittests/test_model_base_serialization.py +0 -4906
  362. package/generator/test/unittests/test_model_base_xml_serialization.py +0 -1239
  363. package/generator/test/unittests/test_name_converter.py +0 -35
  364. package/generator/test/unittests/test_optional_return_type.py +0 -268
  365. package/generator/test/unittests/test_parameter_ordering.py +0 -104
  366. package/generator/test/unittests/test_sort_schema.py +0 -93
  367. package/generator/test/unittests/tox.ini +0 -5
  368. /package/eng/scripts/ci/{pyproject.toml → config/pyproject.toml} +0 -0
@@ -1,9 +1,80 @@
1
- import { promises } from "fs";
1
+ /* eslint-disable no-console */
2
+ /**
3
+ * Shared helpers, types, constants, and data tables used by `regenerate.ts`.
4
+ *
5
+ * This file is meant to be **byte-identical** between this package and the
6
+ * upstream `@typespec/http-client-python`. typespec-python syncs it from
7
+ * <repo-root>/core/packages/http-client-python/eng/scripts/ci/regenerate-common.ts
8
+ * via `pnpm sync`.
9
+ *
10
+ * Per-repo divergence (paths, emitter name, single-phase vs two-phase
11
+ * orchestration, argv/help text) lives in each repo's own `regenerate.ts`,
12
+ * which builds a `RegenerateContext` and feeds it into the helpers exported
13
+ * from this module.
14
+ */
15
+
16
+ import { compile, NodeHost } from "@typespec/compiler";
17
+ import { execSync } from "child_process";
18
+ import { existsSync, rmSync } from "fs";
19
+ import { access, cp, mkdir, mkdtemp, readdir, writeFile } from "fs/promises";
20
+ import { tmpdir } from "os";
2
21
  import { dirname, join, relative, resolve } from "path";
22
+ import pc from "picocolors";
3
23
 
4
- // ---- Shared constants ----
24
+ // ---- Public types ----
5
25
 
6
- export const SKIP_SPECS: string[] = ["type/file"];
26
+ export interface RegenerateFlags {
27
+ flavor: string;
28
+ debug: boolean;
29
+ name?: string;
30
+ }
31
+
32
+ export interface CompileTask {
33
+ spec: string;
34
+ outputDir: string;
35
+ options: Record<string, unknown>;
36
+ }
37
+
38
+ // Group of tasks for the same spec that must run sequentially
39
+ export interface TaskGroup {
40
+ spec: string;
41
+ tasks: CompileTask[];
42
+ }
43
+
44
+ /**
45
+ * Per-repo context injected into the helpers below. Every value is repo
46
+ * specific and must be supplied by the caller's `regenerate.ts`.
47
+ */
48
+ export interface RegenerateContext {
49
+ /** Absolute path to the package root (the dir containing `package.json`). */
50
+ pluginDir: string;
51
+ /** Absolute path to the azure-http-specs `specs/` dir. */
52
+ azureHttpSpecs: string;
53
+ /** Absolute path to the http-specs `specs/` dir. */
54
+ httpSpecs: string;
55
+ /** Absolute path to where generated SDKs should go (e.g. `<plugin>/generator`). */
56
+ generatedFolder: string;
57
+ /** Emitter name to invoke (e.g. `@azure-tools/typespec-python`). */
58
+ emitterName: string;
59
+ }
60
+
61
+ /**
62
+ * Optional knobs for `buildTaskGroups`. Kept here so the call site in each
63
+ * repo's `regenerate.ts` can opt into the upstream two-phase pipeline
64
+ * (`emitYamlOnly: true`) or the single-phase pipeline (default).
65
+ */
66
+ export interface BuildTaskGroupsOptions {
67
+ /** If true, ask the emitter to write YAML only and skip Python codegen. */
68
+ emitYamlOnly?: boolean;
69
+ }
70
+
71
+ // ---- Public constants ----
72
+
73
+ export const SKIP_SPECS: string[] = [
74
+ "type/file",
75
+ "service/multiple-services",
76
+ "azure/client-generator-core/response-as-bool",
77
+ ];
7
78
 
8
79
  export const SpecialFlags: Record<string, Record<string, any>> = {
9
80
  azure: {
@@ -12,9 +83,9 @@ export const SpecialFlags: Record<string, Record<string, any>> = {
12
83
  },
13
84
  };
14
85
 
15
- // ---- Base emitter options (shared across repos) ----
86
+ // ---- Spec-specific emitter option overrides ----
16
87
 
17
- export const BASE_AZURE_EMITTER_OPTIONS: Record<
88
+ export const AZURE_EMITTER_OPTIONS: Record<
18
89
  string,
19
90
  Record<string, string> | Record<string, string>[]
20
91
  > = {
@@ -48,6 +119,9 @@ export const BASE_AZURE_EMITTER_OPTIONS: Record<
48
119
  "azure/client-generator-core/usage": {
49
120
  namespace: "specs.azure.clientgenerator.core.usage",
50
121
  },
122
+ "azure/client-generator-core/client-doc": {
123
+ namespace: "specs.azure.clientgenerator.core.clientdoc",
124
+ },
51
125
  "azure/client-generator-core/override": {
52
126
  namespace: "specs.azure.clientgenerator.core.override",
53
127
  },
@@ -135,12 +209,13 @@ export const BASE_AZURE_EMITTER_OPTIONS: Record<
135
209
  "service/multi-service": {
136
210
  namespace: "service.multiservice",
137
211
  },
212
+ "client/structure/client-operation-group": {
213
+ "package-name": "client-structure-clientoperationgroup",
214
+ namespace: "client.structure.clientoperationgroup",
215
+ },
138
216
  };
139
217
 
140
- export const BASE_EMITTER_OPTIONS: Record<
141
- string,
142
- Record<string, string> | Record<string, string>[]
143
- > = {
218
+ export const EMITTER_OPTIONS: Record<string, Record<string, string> | Record<string, string>[]> = {
144
219
  "resiliency/srv-driven/old.tsp": {
145
220
  "package-name": "resiliency-srv-driven1",
146
221
  namespace: "resiliency.srv.driven1",
@@ -208,10 +283,19 @@ export const BASE_EMITTER_OPTIONS: Record<
208
283
  "package-name": "typetest-model-singlediscriminator",
209
284
  namespace: "typetest.model.singlediscriminator",
210
285
  },
211
- "type/model/inheritance/recursive": {
212
- "package-name": "typetest-model-recursive",
213
- namespace: "typetest.model.recursive",
214
- },
286
+ "type/model/inheritance/recursive": [
287
+ {
288
+ "package-name": "typetest-model-recursive",
289
+ namespace: "typetest.model.recursive",
290
+ },
291
+ {
292
+ "package-name": "generation-subdir",
293
+ namespace: "generation.subdir",
294
+ "generation-subdir": "_generated",
295
+ "generate-test": "false",
296
+ "clear-output-folder": "true",
297
+ },
298
+ ],
215
299
  "type/model/usage": {
216
300
  "package-name": "typetest-model-usage",
217
301
  namespace: "typetest.model.usage",
@@ -268,65 +352,63 @@ export const BASE_EMITTER_OPTIONS: Record<
268
352
  "package-name": "specs-documentation",
269
353
  namespace: "specs.documentation",
270
354
  },
355
+ "versioning/added": [
356
+ {
357
+ "package-name": "versioning-added",
358
+ namespace: "versioning.added",
359
+ },
360
+ {
361
+ "package-name": "generation-subdir2",
362
+ namespace: "generation.subdir2",
363
+ "generate-test": "false",
364
+ "generation-subdir": "_generated",
365
+ },
366
+ ],
271
367
  };
272
368
 
273
- // ---- Shared interfaces ----
274
-
275
- export interface TspCommand {
276
- outputDir: string;
277
- command: string | string[];
278
- }
279
-
280
- export interface RegenerateFlagsInput {
281
- flavor?: string;
282
- debug?: boolean;
283
- name?: string;
284
- pyodide?: boolean;
285
- }
286
-
287
- export interface RegenerateFlags {
288
- flavor: string;
289
- debug: boolean;
290
- name?: string;
291
- pyodide?: boolean;
292
- }
369
+ // ---- Public helpers ----
293
370
 
294
- export interface ProcessedEmitterOption {
295
- options: Record<string, string>;
296
- outputDir: string;
371
+ export function toPosix(p: string): string {
372
+ return p.replace(/\\/g, "/");
297
373
  }
298
374
 
299
- export interface RegenerateConfig {
300
- azureHttpSpecs: string;
301
- httpSpecs: string;
302
- emitterOptions: Record<string, Record<string, string> | Record<string, string>[]>;
303
- azureEmitterOptions: Record<string, Record<string, string> | Record<string, string>[]>;
304
- preprocess: (flags: RegenerateFlagsInput) => Promise<void>;
305
- getCmdList: (spec: string, flags: RegenerateFlags) => TspCommand[];
306
- executeCommand: (cmd: TspCommand) => Promise<void>;
375
+ /**
376
+ * Whether a spec path belongs to azure-http-specs (vs standard http-specs).
377
+ * Uses the `azure-http-specs` substring rather than `azure` to avoid false
378
+ * positives when the working-dir path itself contains "azure" (e.g.
379
+ * azure-sdk-for-python).
380
+ */
381
+ export function isAzureSpec(spec: string): boolean {
382
+ return spec.includes("azure-http-specs");
307
383
  }
308
384
 
309
- // ---- Shared utility functions ----
310
-
311
- export function toPosix(dir: string): string {
312
- return dir.replace(/\\/g, "/");
385
+ export function defaultPackageName(spec: string, ctx: RegenerateContext): string {
386
+ const specDir = isAzureSpec(spec) ? ctx.azureHttpSpecs : ctx.httpSpecs;
387
+ return toPosix(relative(specDir, dirname(spec)))
388
+ .replace(/\//g, "-")
389
+ .toLowerCase();
313
390
  }
314
391
 
315
- export function getEmitterOption(
392
+ export function getEmitterOptions(
316
393
  spec: string,
317
394
  flavor: string,
318
- config: RegenerateConfig,
395
+ ctx: RegenerateContext,
319
396
  ): Record<string, string>[] {
320
- const specDir = spec.includes("azure") ? config.azureHttpSpecs : config.httpSpecs;
397
+ const specDir = isAzureSpec(spec) ? ctx.azureHttpSpecs : ctx.httpSpecs;
321
398
  const relativeSpec = toPosix(relative(specDir, spec));
322
399
  const key = relativeSpec.includes("resiliency/srv-driven/old.tsp")
323
400
  ? relativeSpec
324
401
  : dirname(relativeSpec);
325
- const emitter_options = config.emitterOptions[key] ||
326
- (flavor === "azure" ? config.azureEmitterOptions[key] : [{}]) || [{}];
327
- return Array.isArray(emitter_options) ? emitter_options : [emitter_options];
402
+ const emitterOpts = EMITTER_OPTIONS[key] ||
403
+ (flavor === "azure" ? AZURE_EMITTER_OPTIONS[key] : [{}]) || [{}];
404
+ return Array.isArray(emitterOpts) ? emitterOpts : [emitterOpts];
328
405
  }
329
406
 
407
+ /**
408
+ * Walk `baseDir` and collect every TypeSpec entry-point file that the
409
+ * regenerator should compile (handles `client.tsp`, `main.tsp`, and the
410
+ * special `resiliency/srv-driven/old.tsp` case).
411
+ */
330
412
  export async function getSubdirectories(
331
413
  baseDir: string,
332
414
  flags: RegenerateFlags,
@@ -334,7 +416,7 @@ export async function getSubdirectories(
334
416
  const subdirectories: string[] = [];
335
417
 
336
418
  async function searchDir(currentDir: string) {
337
- const items = await promises.readdir(currentDir, { withFileTypes: true });
419
+ const items = await readdir(currentDir, { withFileTypes: true });
338
420
 
339
421
  const promisesArray = items.map(async (item) => {
340
422
  const subDirPath = join(currentDir, item.name);
@@ -346,12 +428,10 @@ export async function getSubdirectories(
346
428
 
347
429
  if (SKIP_SPECS.some((skipSpec) => mainTspRelativePath.includes(skipSpec))) return;
348
430
 
349
- const hasMainTsp = await promises
350
- .access(mainTspPath)
431
+ const hasMainTsp = await access(mainTspPath)
351
432
  .then(() => true)
352
433
  .catch(() => false);
353
- const hasClientTsp = await promises
354
- .access(clientTspPath)
434
+ const hasClientTsp = await access(clientTspPath)
355
435
  .then(() => true)
356
436
  .catch(() => false);
357
437
 
@@ -366,7 +446,6 @@ export async function getSubdirectories(
366
446
  }
367
447
  }
368
448
 
369
- // Recursively search in the subdirectory
370
449
  await searchDir(subDirPath);
371
450
  }
372
451
  });
@@ -378,95 +457,291 @@ export async function getSubdirectories(
378
457
  return subdirectories;
379
458
  }
380
459
 
381
- export function defaultPackageName(spec: string, config: RegenerateConfig): string {
382
- const specDir = spec.includes("azure") ? config.azureHttpSpecs : config.httpSpecs;
383
- return toPosix(relative(specDir, dirname(spec)))
384
- .replace(/\//g, "-")
385
- .toLowerCase();
460
+ export function buildTaskGroups(
461
+ specs: string[],
462
+ flags: RegenerateFlags,
463
+ ctx: RegenerateContext,
464
+ options: BuildTaskGroupsOptions = {},
465
+ ): TaskGroup[] {
466
+ const groups: TaskGroup[] = [];
467
+
468
+ for (const spec of specs) {
469
+ const tasks: CompileTask[] = [];
470
+
471
+ for (const emitterConfig of getEmitterOptions(spec, flags.flavor, ctx)) {
472
+ // Apply flavor defaults first, then per-spec options so they can override
473
+ // (e.g. "generate-test": "false")
474
+ const opts: Record<string, unknown> = {};
475
+ for (const [k, v] of Object.entries(SpecialFlags[flags.flavor] ?? {})) {
476
+ opts[k] = v;
477
+ }
478
+ Object.assign(opts, emitterConfig);
479
+
480
+ opts["flavor"] = flags.flavor;
481
+
482
+ // Set output directory - tests/generated/<flavor>/<package> structure.
483
+ // Always anchored at <generatedFolder>/../tests/generated regardless of
484
+ // pluginDir, so generator-only checkouts work too.
485
+ const packageName = (opts["package-name"] as string) || defaultPackageName(spec, ctx);
486
+ const outputDir =
487
+ (opts["emitter-output-dir"] as string) ||
488
+ toPosix(`${ctx.generatedFolder}/../tests/generated/${flags.flavor}/${packageName}`);
489
+ opts["emitter-output-dir"] = outputDir;
490
+
491
+ if (flags.debug) {
492
+ opts["debug"] = true;
493
+ }
494
+
495
+ opts["examples-dir"] = toPosix(join(dirname(spec), "examples"));
496
+
497
+ if (options.emitYamlOnly) {
498
+ // Emit YAML only - Python processing is batched after all specs compile.
499
+ opts["emit-yaml-only"] = true;
500
+ }
501
+
502
+ tasks.push({ spec, outputDir, options: opts });
503
+ }
504
+
505
+ groups.push({ spec, tasks });
506
+ }
507
+
508
+ return groups;
386
509
  }
387
510
 
388
- export function buildOptions(
389
- spec: string,
390
- generatedFolder: string,
391
- flags: RegenerateFlags,
392
- config: RegenerateConfig,
393
- ): ProcessedEmitterOption[] {
394
- const results: ProcessedEmitterOption[] = [];
395
- for (const emitterConfig of getEmitterOption(spec, flags.flavor, config)) {
396
- const options: Record<string, string> = { ...emitterConfig };
397
- if (flags.pyodide) {
398
- options["use-pyodide"] = "true";
511
+ export async function compileSpec(
512
+ task: CompileTask,
513
+ ctx: RegenerateContext,
514
+ ): Promise<{ success: boolean; error?: string }> {
515
+ const { spec, outputDir, options } = task;
516
+
517
+ try {
518
+ const compilerOptions = {
519
+ emit: [ctx.pluginDir],
520
+ options: {
521
+ [ctx.emitterName]: options,
522
+ },
523
+ };
524
+
525
+ const program = await compile(NodeHost, spec, compilerOptions);
526
+
527
+ if (program.hasError()) {
528
+ const errors = program.diagnostics
529
+ .filter((d) => d.severity === "error")
530
+ .map((d) => d.message)
531
+ .join("\n");
532
+ return { success: false, error: errors };
399
533
  }
400
- options["flavor"] = flags.flavor;
401
- for (const [k, v] of Object.entries(SpecialFlags[flags.flavor] ?? {})) {
402
- options[k] = v;
534
+
535
+ return { success: true };
536
+ } catch (err) {
537
+ rmSync(outputDir, { recursive: true, force: true });
538
+ return { success: false, error: String(err) };
539
+ }
540
+ }
541
+
542
+ export function renderProgressBar(
543
+ completed: number,
544
+ failed: number,
545
+ total: number,
546
+ width: number = 40,
547
+ ): string {
548
+ const successCount = completed - failed;
549
+ const successWidth = Math.round((successCount / total) * width);
550
+ const failWidth = Math.round((failed / total) * width);
551
+ const emptyWidth = width - successWidth - failWidth;
552
+
553
+ const successBar = pc.bgGreen(" ".repeat(successWidth));
554
+ const failBar = failed > 0 ? pc.bgRed(" ".repeat(failWidth)) : "";
555
+ const emptyBar = pc.dim("░".repeat(Math.max(0, emptyWidth)));
556
+
557
+ const percent = Math.round((completed / total) * 100);
558
+ return `${successBar}${failBar}${emptyBar} ${pc.cyan(`${percent}%`)} (${completed}/${total})`;
559
+ }
560
+
561
+ export async function runParallel(
562
+ groups: TaskGroup[],
563
+ maxJobs: number,
564
+ ctx: RegenerateContext,
565
+ ): Promise<Map<string, boolean>> {
566
+ const results = new Map<string, boolean>();
567
+ const executing: Set<Promise<void>> = new Set();
568
+
569
+ const totalTasks = groups.reduce((sum, g) => sum + g.tasks.length, 0);
570
+ let completed = 0;
571
+ let failed = 0;
572
+ const failedSpecs: string[] = [];
573
+
574
+ const isTTY = process.stdout.isTTY;
575
+
576
+ const updateProgress = () => {
577
+ if (isTTY) {
578
+ process.stdout.write(`\r${renderProgressBar(completed, failed, totalTasks)}`);
403
579
  }
404
- if (options["emitter-output-dir"] === undefined) {
405
- const packageName = options["package-name"] || defaultPackageName(spec, config);
406
- options["emitter-output-dir"] = toPosix(
407
- `${generatedFolder}/test/${flags.flavor}/generated/${packageName}`,
408
- );
580
+ };
581
+
582
+ updateProgress();
583
+
584
+ for (const group of groups) {
585
+ // Each group runs as a unit - tasks within a group run sequentially
586
+ // to avoid state pollution. Different groups run in parallel.
587
+ const runGroup = async () => {
588
+ const specDir = isAzureSpec(group.spec) ? ctx.azureHttpSpecs : ctx.httpSpecs;
589
+ const shortName = toPosix(relative(specDir, dirname(group.spec)));
590
+
591
+ let groupSuccess = true;
592
+ for (const task of group.tasks) {
593
+ const packageName = (task.options["package-name"] as string) || shortName;
594
+
595
+ const result = await compileSpec(task, ctx);
596
+ completed++;
597
+
598
+ if (!result.success) {
599
+ failed++;
600
+ failedSpecs.push(`${packageName}: ${result.error}`);
601
+ groupSuccess = false;
602
+ }
603
+
604
+ updateProgress();
605
+ }
606
+
607
+ results.set(group.spec, groupSuccess);
608
+ };
609
+
610
+ const p = runGroup().finally(() => executing.delete(p));
611
+ executing.add(p);
612
+
613
+ if (executing.size >= maxJobs) {
614
+ await Promise.race(executing);
409
615
  }
410
- if (flags.debug) {
411
- options["debug"] = "true";
616
+ }
617
+
618
+ await Promise.all(executing);
619
+
620
+ if (isTTY) {
621
+ process.stdout.write("\r" + " ".repeat(60) + "\r");
622
+ }
623
+
624
+ if (failedSpecs.length > 0) {
625
+ console.log(pc.red(`\nFailed specs:`));
626
+ for (const spec of failedSpecs) {
627
+ console.log(pc.red(` • ${spec}`));
412
628
  }
413
- options["examples-dir"] = toPosix(join(dirname(spec), "examples"));
414
- results.push({
415
- options,
416
- outputDir: options["emitter-output-dir"],
417
- });
418
629
  }
630
+
419
631
  return results;
420
632
  }
421
633
 
422
- export async function runTaskPool(
423
- tasks: Array<() => Promise<void>>,
424
- poolLimit: number,
425
- ): Promise<void> {
426
- async function worker(start: number, end: number) {
427
- while (start < end) {
428
- await tasks[start]();
429
- start++;
430
- }
431
- }
634
+ /**
635
+ * Pre-create the marker files that the test harness expects to find before
636
+ * regeneration so it can verify they're cleared/preserved correctly.
637
+ */
638
+ export async function preprocess(flavor: string, generatedFolder: string): Promise<void> {
639
+ if (flavor !== "azure") return;
432
640
 
433
- const workers = [];
434
- let start = 0;
435
- while (start < tasks.length) {
436
- const end = Math.min(start + poolLimit, tasks.length);
437
- workers.push((async () => await worker(start, end))());
438
- start = end;
439
- }
440
- await Promise.all(workers);
641
+ const testsGeneratedDir = resolve(generatedFolder, "../tests/generated/azure");
642
+
643
+ const DELETE_CONTENT = "# This file is to be deleted after regeneration";
644
+ const KEEP_CONTENT = "# This file is to be kept after regeneration";
645
+ const DELETE_FILE = "to_be_deleted.py";
646
+ const entries: { folder: string[]; file: string; content: string }[] = [
647
+ {
648
+ folder: ["authentication-api-key", "authentication", "apikey", "_operations"],
649
+ file: DELETE_FILE,
650
+ content: DELETE_CONTENT,
651
+ },
652
+ {
653
+ folder: ["generation-subdir", "generation", "subdir", "_generated"],
654
+ file: DELETE_FILE,
655
+ content: DELETE_CONTENT,
656
+ },
657
+ {
658
+ folder: ["generation-subdir", "generated_tests"],
659
+ file: DELETE_FILE,
660
+ content: DELETE_CONTENT,
661
+ },
662
+ {
663
+ folder: ["generation-subdir", "generation", "subdir"],
664
+ file: "to_be_kept.py",
665
+ content: KEEP_CONTENT,
666
+ },
667
+ ];
668
+
669
+ await Promise.all(
670
+ entries.map(async ({ folder, file, content }) => {
671
+ const targetFolder = join(testsGeneratedDir, ...folder);
672
+ await mkdir(targetFolder, { recursive: true });
673
+ await writeFile(join(targetFolder, file), content);
674
+ }),
675
+ );
441
676
  }
442
677
 
443
- export async function regenerate(
444
- flags: RegenerateFlagsInput,
445
- config: RegenerateConfig,
446
- ): Promise<void> {
447
- if (flags.flavor === undefined) {
448
- await regenerate({ flavor: "azure", ...flags }, config);
449
- await regenerate({ flavor: "unbranded", ...flags }, config);
450
- } else {
451
- await config.preprocess(flags);
452
-
453
- const flagsResolved: RegenerateFlags = { debug: false, flavor: flags.flavor, ...flags };
454
- const subdirectoriesForAzure = await getSubdirectories(config.azureHttpSpecs, flagsResolved);
455
- const subdirectoriesForNonAzure = await getSubdirectories(config.httpSpecs, flagsResolved);
456
- const subdirectories =
457
- flags.flavor === "azure"
458
- ? [...subdirectoriesForAzure, ...subdirectoriesForNonAzure]
459
- : subdirectoriesForNonAzure;
460
- const cmdList: TspCommand[] = subdirectories.flatMap((subdirectory) =>
461
- config.getCmdList(subdirectory, flagsResolved),
462
- );
463
-
464
- // Create tasks as functions for the pool
465
- const tasks: Array<() => Promise<void>> = cmdList.map((tspCommand) => {
466
- return () => config.executeCommand(tspCommand);
467
- });
678
+ /**
679
+ * Resets the `tests/generated/{azure,unbranded}` baseline by sparse-checking-out
680
+ * `eng/tools/emitter/gen` from the Azure/azure-sdk-for-python repo, then
681
+ * deleting a couple of fully-generated package folders so regeneration has to
682
+ * recreate them from scratch (smoke test of full-emit path).
683
+ *
684
+ * `generatedFolder` is the per-repo `generator/` directory; baseline lands at
685
+ * `<generatedFolder>/../tests/generated`.
686
+ */
687
+ export async function prepareBaselineOfGeneratedCode(generatedFolder: string): Promise<void> {
688
+ const repoUrl = "https://github.com/Azure/azure-sdk-for-python.git";
689
+ const branch = "main";
690
+ const sourceSubdir = "eng/tools/emitter/gen";
691
+ const testsGeneratedDir = resolve(generatedFolder, "../tests/generated");
692
+
693
+ console.log(pc.cyan(`\n${"=".repeat(60)}`));
694
+ console.log(pc.cyan(`Resetting baseline from ${repoUrl} (${branch}/${sourceSubdir})`));
695
+ console.log(pc.cyan(`${"=".repeat(60)}\n`));
696
+
697
+ // Wipe tests/generated
698
+ if (existsSync(testsGeneratedDir)) {
699
+ console.log(pc.dim(`Removing ${testsGeneratedDir}`));
700
+ rmSync(testsGeneratedDir, { recursive: true, force: true });
701
+ }
702
+
703
+ // Sparse-checkout the baseline folder into a temp directory
704
+ const tempDir = await mkdtemp(join(tmpdir(), "azsdk-baseline-"));
705
+ try {
706
+ console.log(pc.dim(`Cloning into ${tempDir}`));
707
+ const run = (cmd: string) =>
708
+ execSync(cmd, { cwd: tempDir, stdio: ["ignore", "ignore", "inherit"] });
709
+
710
+ run(`git init`);
711
+ run(`git remote add origin ${repoUrl}`);
712
+ run(`git config core.sparseCheckout true`);
713
+ run(`git sparse-checkout init --cone`);
714
+ run(`git sparse-checkout set ${sourceSubdir}`);
715
+ run(`git fetch --depth 1 origin ${branch}`);
716
+ run(`git checkout FETCH_HEAD`);
717
+
718
+ const sourceRoot = join(tempDir, ...sourceSubdir.split("/"));
719
+ for (const flavor of ["azure", "unbranded"]) {
720
+ const src = join(sourceRoot, flavor);
721
+ const dest = join(testsGeneratedDir, flavor);
722
+ if (!existsSync(src)) {
723
+ console.warn(pc.yellow(`Baseline folder not found: ${src}`));
724
+ continue;
725
+ }
726
+ console.log(pc.dim(`Copying ${flavor}/ -> ${dest}`));
727
+ await cp(src, dest, { recursive: true });
728
+ }
468
729
 
469
- // Run tasks with a concurrency limit
470
- await runTaskPool(tasks, 30);
730
+ console.log(pc.green(`Baseline reset complete.\n`));
731
+ } finally {
732
+ rmSync(tempDir, { recursive: true, force: true });
733
+ }
734
+
735
+ // Delete a couple of fully-generated package folders so regeneration has to
736
+ // recreate them from scratch (smoke test of full-emit path).
737
+ const targetsToDelete = [
738
+ join(testsGeneratedDir, "azure", "authentication-http-custom"),
739
+ join(testsGeneratedDir, "unbranded", "encode-array"),
740
+ ];
741
+ for (const target of targetsToDelete) {
742
+ if (existsSync(target)) {
743
+ console.log(pc.dim(`Deleting ${target}`));
744
+ rmSync(target, { recursive: true, force: true });
745
+ }
471
746
  }
472
747
  }