@typespec/http-client-python 0.10.0 → 0.11.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 (32) hide show
  1. package/README.md +19 -36
  2. package/dist/emitter/emitter.js +40 -0
  3. package/dist/emitter/emitter.js.map +1 -1
  4. package/dist/emitter/http.js +5 -2
  5. package/dist/emitter/http.js.map +1 -1
  6. package/dist/emitter/utils.d.ts.map +1 -1
  7. package/dist/emitter/utils.js +9 -1
  8. package/dist/emitter/utils.js.map +1 -1
  9. package/emitter/src/emitter.ts +46 -0
  10. package/emitter/src/http.ts +12 -2
  11. package/emitter/src/utils.ts +11 -1
  12. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  13. package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
  14. package/eng/scripts/setup/install.py +1 -0
  15. package/eng/scripts/setup/run_tsp.py +2 -3
  16. package/generator/build/lib/pygen/codegen/models/parameter.py +3 -0
  17. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +27 -13
  18. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +6 -1
  19. package/generator/component-detection-pip-report.json +4 -5
  20. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  21. package/generator/pygen/codegen/models/parameter.py +3 -0
  22. package/generator/pygen/codegen/serializers/general_serializer.py +27 -13
  23. package/generator/pygen/codegen/serializers/parameter_serializer.py +6 -1
  24. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_initialization_async.py +50 -0
  25. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_initialization.py +44 -0
  26. package/generator/test/azure/requirements.txt +3 -1
  27. package/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py +24 -0
  28. package/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py +1 -1
  29. package/generator/test/generic_mock_api_tests/test_parameters_path.py +22 -0
  30. package/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py +1 -1
  31. package/generator/test/unbranded/requirements.txt +1 -0
  32. package/package.json +5 -5
@@ -357,6 +357,9 @@ class Parameter(_ParameterBase):
357
357
  )
358
358
  if self.code_model.options["only_path_and_body_params_positional"] and query_or_header:
359
359
  return ParameterMethodLocation.KEYWORD_ONLY
360
+ # for optional path parameter, we need to use keyword only
361
+ if self.location == ParameterLocation.PATH and self.optional:
362
+ return ParameterMethodLocation.KEYWORD_ONLY
360
363
  return ParameterMethodLocation.POSITIONAL
361
364
 
362
365
  @classmethod
@@ -225,19 +225,33 @@ class GeneralSerializer(BaseSerializer):
225
225
  if not enum.internal
226
226
  }
227
227
  )
228
- cross_langauge_def_dict.update(
229
- {
230
- (
231
- f"{self.code_model.namespace}.{client.name}."
232
- + ("" if operation_group.is_mixin else f"{operation_group.property_name}.")
233
- + f"{operation.name}"
234
- ): operation.cross_language_definition_id
235
- for client in self.code_model.clients
236
- for operation_group in client.operation_groups
237
- for operation in operation_group.operations
238
- if not operation.name.startswith("_")
239
- }
240
- )
228
+ for client in self.code_model.clients:
229
+ for operation_group in client.operation_groups:
230
+ for operation in operation_group.operations:
231
+ if operation.name.startswith("_"):
232
+ continue
233
+ cross_langauge_def_dict.update(
234
+ {
235
+ f"{self.code_model.namespace}."
236
+ + (
237
+ f"{client.name}."
238
+ if operation_group.is_mixin
239
+ else f"operations.{operation_group.class_name}."
240
+ )
241
+ + f"{operation.name}": operation.cross_language_definition_id
242
+ }
243
+ )
244
+ cross_langauge_def_dict.update(
245
+ {
246
+ f"{self.code_model.namespace}.aio."
247
+ + (
248
+ f"{client.name}."
249
+ if operation_group.is_mixin
250
+ else f"operations.{operation_group.class_name}."
251
+ )
252
+ + f"{operation.name}": operation.cross_language_definition_id
253
+ }
254
+ )
241
255
  return json.dumps(
242
256
  {
243
257
  "CrossLanguagePackageId": self.code_model.cross_language_package_id,
@@ -109,6 +109,7 @@ class ParameterSerializer:
109
109
  return f"[{serialize_line} if q is not None else '' for q in {origin_name}]"
110
110
  return serialize_line
111
111
 
112
+ # pylint: disable=line-too-long
112
113
  def serialize_path(
113
114
  self,
114
115
  parameters: Union[
@@ -124,7 +125,11 @@ class ParameterSerializer:
124
125
  [
125
126
  ' "{}": {},'.format(
126
127
  path_parameter.wire_name,
127
- self.serialize_parameter(path_parameter, serializer_name),
128
+ (
129
+ f'"" if {path_parameter.full_client_name} is None else "/" + {self.serialize_parameter(path_parameter, serializer_name)}'
130
+ if path_parameter.optional and isinstance(path_parameter, RequestBuilderParameter)
131
+ else self.serialize_parameter(path_parameter, serializer_name)
132
+ ),
128
133
  )
129
134
  for path_parameter in parameters
130
135
  ]
@@ -4,11 +4,11 @@
4
4
  "install": [
5
5
  {
6
6
  "download_info": {
7
- "url": "https://files.pythonhosted.org/packages/54/21/f43f0a1fa8b06b32812e0975981f4677d28e0f3271601dc88ac5a5b83220/setuptools-78.1.0-py3-none-any.whl",
7
+ "url": "https://files.pythonhosted.org/packages/cc/ea/d53f2f8897c46a36df085964d07761ea4c2d1f2cf92019693b6742b7aabb/setuptools-79.0.0-py3-none-any.whl",
8
8
  "archive_info": {
9
- "hash": "sha256=3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8",
9
+ "hash": "sha256=b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a",
10
10
  "hashes": {
11
- "sha256": "3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8"
11
+ "sha256": "b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a"
12
12
  }
13
13
  }
14
14
  },
@@ -18,7 +18,7 @@
18
18
  "metadata": {
19
19
  "metadata_version": "2.4",
20
20
  "name": "setuptools",
21
- "version": "78.1.0",
21
+ "version": "79.0.0",
22
22
  "dynamic": [
23
23
  "license-file"
24
24
  ],
@@ -39,7 +39,6 @@
39
39
  "classifier": [
40
40
  "Development Status :: 5 - Production/Stable",
41
41
  "Intended Audience :: Developers",
42
- "License :: OSI Approved :: MIT License",
43
42
  "Programming Language :: Python :: 3",
44
43
  "Programming Language :: Python :: 3 :: Only",
45
44
  "Topic :: Software Development :: Libraries :: Python Modules",
@@ -357,6 +357,9 @@ class Parameter(_ParameterBase):
357
357
  )
358
358
  if self.code_model.options["only_path_and_body_params_positional"] and query_or_header:
359
359
  return ParameterMethodLocation.KEYWORD_ONLY
360
+ # for optional path parameter, we need to use keyword only
361
+ if self.location == ParameterLocation.PATH and self.optional:
362
+ return ParameterMethodLocation.KEYWORD_ONLY
360
363
  return ParameterMethodLocation.POSITIONAL
361
364
 
362
365
  @classmethod
@@ -225,19 +225,33 @@ class GeneralSerializer(BaseSerializer):
225
225
  if not enum.internal
226
226
  }
227
227
  )
228
- cross_langauge_def_dict.update(
229
- {
230
- (
231
- f"{self.code_model.namespace}.{client.name}."
232
- + ("" if operation_group.is_mixin else f"{operation_group.property_name}.")
233
- + f"{operation.name}"
234
- ): operation.cross_language_definition_id
235
- for client in self.code_model.clients
236
- for operation_group in client.operation_groups
237
- for operation in operation_group.operations
238
- if not operation.name.startswith("_")
239
- }
240
- )
228
+ for client in self.code_model.clients:
229
+ for operation_group in client.operation_groups:
230
+ for operation in operation_group.operations:
231
+ if operation.name.startswith("_"):
232
+ continue
233
+ cross_langauge_def_dict.update(
234
+ {
235
+ f"{self.code_model.namespace}."
236
+ + (
237
+ f"{client.name}."
238
+ if operation_group.is_mixin
239
+ else f"operations.{operation_group.class_name}."
240
+ )
241
+ + f"{operation.name}": operation.cross_language_definition_id
242
+ }
243
+ )
244
+ cross_langauge_def_dict.update(
245
+ {
246
+ f"{self.code_model.namespace}.aio."
247
+ + (
248
+ f"{client.name}."
249
+ if operation_group.is_mixin
250
+ else f"operations.{operation_group.class_name}."
251
+ )
252
+ + f"{operation.name}": operation.cross_language_definition_id
253
+ }
254
+ )
241
255
  return json.dumps(
242
256
  {
243
257
  "CrossLanguagePackageId": self.code_model.cross_language_package_id,
@@ -109,6 +109,7 @@ class ParameterSerializer:
109
109
  return f"[{serialize_line} if q is not None else '' for q in {origin_name}]"
110
110
  return serialize_line
111
111
 
112
+ # pylint: disable=line-too-long
112
113
  def serialize_path(
113
114
  self,
114
115
  parameters: Union[
@@ -124,7 +125,11 @@ class ParameterSerializer:
124
125
  [
125
126
  ' "{}": {},'.format(
126
127
  path_parameter.wire_name,
127
- self.serialize_parameter(path_parameter, serializer_name),
128
+ (
129
+ f'"" if {path_parameter.full_client_name} is None else "/" + {self.serialize_parameter(path_parameter, serializer_name)}'
130
+ if path_parameter.optional and isinstance(path_parameter, RequestBuilderParameter)
131
+ else self.serialize_parameter(path_parameter, serializer_name)
132
+ ),
128
133
  )
129
134
  for path_parameter in parameters
130
135
  ]
@@ -0,0 +1,50 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ import pytest
7
+ from specs.azure.clientgenerator.core.clientinitialization.aio import (
8
+ HeaderParamClient,
9
+ MultipleParamsClient,
10
+ MixedParamsClient,
11
+ PathParamClient,
12
+ ParamAliasClient,
13
+ )
14
+ from specs.azure.clientgenerator.core.clientinitialization.models import Input
15
+
16
+
17
+ @pytest.mark.asyncio
18
+ async def test_header_param_client():
19
+ async with HeaderParamClient("test-name-value") as client:
20
+ await client.with_query(id="test-id")
21
+ await client.with_body(Input(name="test-name"))
22
+
23
+
24
+ @pytest.mark.asyncio
25
+ async def test_multiple_params_client():
26
+ async with MultipleParamsClient("test-name-value", "us-west") as client:
27
+ await client.with_query(id="test-id")
28
+ await client.with_body(Input(name="test-name"))
29
+
30
+
31
+ @pytest.mark.asyncio
32
+ async def test_mixed_params_client():
33
+ async with MixedParamsClient("test-name-value") as client:
34
+ await client.with_query(region="us-west", id="test-id")
35
+ await client.with_body(Input(name="test-name"), region="us-west")
36
+
37
+
38
+ @pytest.mark.asyncio
39
+ async def test_path_param_client():
40
+ async with PathParamClient("sample-blob") as client:
41
+ await client.with_query(format="text")
42
+ await client.get_standalone()
43
+ await client.delete_standalone()
44
+
45
+
46
+ @pytest.mark.asyncio
47
+ async def test_param_alias_client():
48
+ async with ParamAliasClient("sample-blob") as client:
49
+ await client.with_aliased_name()
50
+ await client.with_original_name()
@@ -0,0 +1,44 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ from specs.azure.clientgenerator.core.clientinitialization import (
7
+ HeaderParamClient,
8
+ MultipleParamsClient,
9
+ MixedParamsClient,
10
+ PathParamClient,
11
+ ParamAliasClient,
12
+ )
13
+ from specs.azure.clientgenerator.core.clientinitialization.models import Input
14
+
15
+
16
+ def test_header_param_client():
17
+ with HeaderParamClient("test-name-value") as client:
18
+ client.with_query(id="test-id")
19
+ client.with_body(Input(name="test-name"))
20
+
21
+
22
+ def test_multiple_params_client():
23
+ with MultipleParamsClient("test-name-value", "us-west") as client:
24
+ client.with_query(id="test-id")
25
+ client.with_body(Input(name="test-name"))
26
+
27
+
28
+ def test_mixed_params_client():
29
+ with MixedParamsClient("test-name-value") as client:
30
+ client.with_query(region="us-west", id="test-id")
31
+ client.with_body(Input(name="test-name"), region="us-west")
32
+
33
+
34
+ def test_path_param_client():
35
+ with PathParamClient("sample-blob") as client:
36
+ client.with_query(format="text")
37
+ client.get_standalone()
38
+ client.delete_standalone()
39
+
40
+
41
+ def test_param_alias_client():
42
+ with ParamAliasClient("sample-blob") as client:
43
+ client.with_aliased_name()
44
+ client.with_original_name()
@@ -4,8 +4,9 @@ azure-mgmt-core==1.5.0
4
4
 
5
5
  # only for azure
6
6
  -e ./generated/azure-client-generator-core-access
7
- -e ./generated/azure-client-generator-core-usage
7
+ -e ./generated/azure-client-generator-core-client-initialization
8
8
  -e ./generated/azure-client-generator-core-flatten-property
9
+ -e ./generated/azure-client-generator-core-usage
9
10
  -e ./generated/azure-core-basic
10
11
  -e ./generated/azure-core-scalar
11
12
  -e ./generated/azure-core-lro-rpc
@@ -37,6 +38,7 @@ azure-mgmt-core==1.5.0
37
38
  -e ./generated/encode-numeric
38
39
  -e ./generated/parameters-basic
39
40
  -e ./generated/parameters-collection-format
41
+ -e ./generated/parameters-path
40
42
  -e ./generated/parameters-spread
41
43
  -e ./generated/serialization-encoded-name-json
42
44
  -e ./generated/server-endpoint-not-defined
@@ -0,0 +1,24 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ import pytest
7
+ from parameters.path.aio import PathClient
8
+
9
+
10
+ @pytest.fixture
11
+ async def client():
12
+ async with PathClient() as client:
13
+ yield client
14
+
15
+
16
+ @pytest.mark.asyncio
17
+ async def test_normal(client: PathClient):
18
+ await client.normal("foo")
19
+
20
+
21
+ @pytest.mark.asyncio
22
+ async def test_optional(client: PathClient):
23
+ await client.optional()
24
+ await client.optional(name="foo")
@@ -28,7 +28,7 @@ async def test_create_resource(client: JsonMergePatchClient):
28
28
  map={"key": inner_madge},
29
29
  array=[inner_madge],
30
30
  int_value=1,
31
- float_value=1.1,
31
+ float_value=1.25,
32
32
  inner_model=inner_madge,
33
33
  int_array=[1, 2, 3],
34
34
  )
@@ -0,0 +1,22 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ import pytest
7
+ from parameters.path import PathClient
8
+
9
+
10
+ @pytest.fixture
11
+ def client():
12
+ with PathClient() as client:
13
+ yield client
14
+
15
+
16
+ def test_normal(client: PathClient):
17
+ client.normal("foo")
18
+
19
+
20
+ def test_optional(client: PathClient):
21
+ client.optional()
22
+ client.optional(name="foo")
@@ -27,7 +27,7 @@ def test_create_resource(client: JsonMergePatchClient):
27
27
  map={"key": inner_madge},
28
28
  array=[inner_madge],
29
29
  int_value=1,
30
- float_value=1.1,
30
+ float_value=1.25,
31
31
  inner_model=inner_madge,
32
32
  int_array=[1, 2, 3],
33
33
  )
@@ -10,6 +10,7 @@
10
10
  -e ./generated/encode-numeric
11
11
  -e ./generated/parameters-basic
12
12
  -e ./generated/parameters-collection-format
13
+ -e ./generated/parameters-path
13
14
  -e ./generated/parameters-spread
14
15
  -e ./generated/serialization-encoded-name-json
15
16
  -e ./generated/server-endpoint-not-defined
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http-client-python",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec emitter for Python SDKs",
6
6
  "homepage": "https://typespec.io",
@@ -58,7 +58,7 @@
58
58
  "@azure-tools/typespec-azure-core": ">=0.54.0 <1.0.0",
59
59
  "@azure-tools/typespec-azure-resource-manager": ">=0.54.0 <1.0.0",
60
60
  "@azure-tools/typespec-azure-rulesets": ">=0.54.0 <1.0.0",
61
- "@azure-tools/typespec-client-generator-core": ">=0.54.0 <1.0.0",
61
+ "@azure-tools/typespec-client-generator-core": ">=0.54.2 <1.0.0",
62
62
  "@typespec/compiler": "^1.0.0-0",
63
63
  "@typespec/http": "^1.0.0-0",
64
64
  "@typespec/openapi": "^1.0.0-0",
@@ -81,8 +81,8 @@
81
81
  "@azure-tools/typespec-azure-core": "~0.54.0",
82
82
  "@azure-tools/typespec-azure-resource-manager": "~0.54.0",
83
83
  "@azure-tools/typespec-azure-rulesets": "~0.54.0",
84
- "@azure-tools/typespec-client-generator-core": "~0.54.0",
85
- "@azure-tools/azure-http-specs": "0.1.0-alpha.13",
84
+ "@azure-tools/typespec-client-generator-core": "~0.54.2",
85
+ "@azure-tools/azure-http-specs": "0.1.0-alpha.14",
86
86
  "@typespec/compiler": "^1.0.0-0",
87
87
  "@typespec/http": "^1.0.0-0",
88
88
  "@typespec/openapi": "^1.0.0-0",
@@ -92,7 +92,7 @@
92
92
  "@typespec/sse": "~0.68.0",
93
93
  "@typespec/streams": "~0.68.0",
94
94
  "@typespec/xml": "~0.68.0",
95
- "@typespec/http-specs": "0.1.0-alpha.17",
95
+ "@typespec/http-specs": "0.1.0-alpha.19",
96
96
  "@types/js-yaml": "~4.0.5",
97
97
  "@types/node": "~22.13.14",
98
98
  "@types/semver": "7.5.8",