@typespec/http-client-python 0.23.1 → 0.24.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 (75) hide show
  1. package/dist/emitter/code-model.d.ts.map +1 -1
  2. package/dist/emitter/code-model.js +35 -25
  3. package/dist/emitter/code-model.js.map +1 -1
  4. package/dist/emitter/http.d.ts +4 -4
  5. package/dist/emitter/http.d.ts.map +1 -1
  6. package/dist/emitter/http.js +41 -35
  7. package/dist/emitter/http.js.map +1 -1
  8. package/dist/emitter/types.d.ts +1 -1
  9. package/dist/emitter/types.d.ts.map +1 -1
  10. package/dist/emitter/types.js +2 -2
  11. package/dist/emitter/types.js.map +1 -1
  12. package/dist/emitter/utils.d.ts +2 -2
  13. package/dist/emitter/utils.d.ts.map +1 -1
  14. package/dist/emitter/utils.js +7 -6
  15. package/dist/emitter/utils.js.map +1 -1
  16. package/emitter/src/code-model.ts +61 -18
  17. package/emitter/src/http.ts +107 -22
  18. package/emitter/src/types.ts +2 -1
  19. package/emitter/src/utils.ts +11 -9
  20. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  21. package/eng/scripts/ci/dev_requirements.txt +3 -3
  22. package/eng/scripts/ci/pylintrc +1 -1
  23. package/eng/scripts/ci/regenerate.ts +8 -1
  24. package/eng/scripts/setup/__pycache__/package_manager.cpython-311.pyc +0 -0
  25. package/eng/scripts/setup/__pycache__/venvtools.cpython-311.pyc +0 -0
  26. package/generator/build/lib/pygen/codegen/models/code_model.py +4 -0
  27. package/generator/build/lib/pygen/codegen/models/enum_type.py +8 -1
  28. package/generator/build/lib/pygen/codegen/models/list_type.py +6 -2
  29. package/generator/build/lib/pygen/codegen/models/model_type.py +2 -2
  30. package/generator/build/lib/pygen/codegen/models/operation.py +10 -1
  31. package/generator/build/lib/pygen/codegen/models/operation_group.py +3 -1
  32. package/generator/build/lib/pygen/codegen/models/request_builder.py +20 -3
  33. package/generator/build/lib/pygen/codegen/models/response.py +2 -2
  34. package/generator/build/lib/pygen/codegen/models/utils.py +7 -0
  35. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +20 -11
  36. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +1 -2
  37. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +1 -1
  38. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +3 -0
  39. package/generator/build/lib/pygen/codegen/templates/enum.py.jinja2 +3 -1
  40. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +10 -7
  41. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  42. package/generator/pygen/codegen/models/code_model.py +4 -0
  43. package/generator/pygen/codegen/models/enum_type.py +8 -1
  44. package/generator/pygen/codegen/models/list_type.py +6 -2
  45. package/generator/pygen/codegen/models/model_type.py +2 -2
  46. package/generator/pygen/codegen/models/operation.py +10 -1
  47. package/generator/pygen/codegen/models/operation_group.py +3 -1
  48. package/generator/pygen/codegen/models/request_builder.py +20 -3
  49. package/generator/pygen/codegen/models/response.py +2 -2
  50. package/generator/pygen/codegen/models/utils.py +7 -0
  51. package/generator/pygen/codegen/serializers/builder_serializer.py +20 -11
  52. package/generator/pygen/codegen/serializers/client_serializer.py +1 -2
  53. package/generator/pygen/codegen/serializers/general_serializer.py +1 -1
  54. package/generator/pygen/codegen/serializers/model_serializer.py +3 -0
  55. package/generator/pygen/codegen/templates/enum.py.jinja2 +3 -1
  56. package/generator/pygen/codegen/templates/model_base.py.jinja2 +10 -7
  57. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_default_value_async.py +46 -0
  58. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_location_async.py +48 -21
  59. package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_async.py +110 -0
  60. package/generator/test/azure/mock_api_tests/asynctests/test_service_multi_service_async.py +31 -0
  61. package/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py +18 -0
  62. package/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py +16 -0
  63. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_default_value.py +42 -0
  64. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_location.py +44 -19
  65. package/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service.py +104 -0
  66. package/generator/test/azure/mock_api_tests/test_service_multi_service.py +29 -0
  67. package/generator/test/azure/mock_api_tests/test_special_words.py +17 -0
  68. package/generator/test/azure/requirements.txt +9 -1
  69. package/generator/test/generic_mock_api_tests/asynctests/test_parameters_query_async.py +18 -0
  70. package/generator/test/generic_mock_api_tests/test_parameters_query.py +17 -0
  71. package/generator/test/generic_mock_api_tests/test_typetest_scalar.py +0 -5
  72. package/generator/test/generic_mock_api_tests/test_typetest_union_discriminated.py +290 -0
  73. package/generator/test/unbranded/requirements.txt +2 -0
  74. package/generator/test/unittests/test_model_base_serialization.py +66 -0
  75. package/package.json +5 -5
@@ -0,0 +1,104 @@
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 azure.core.exceptions import HttpResponseError
8
+ from azure.resourcemanager.multiservice.combined import CombinedClient
9
+ from azure.resourcemanager.multiservice.combined.models import VirtualMachine, Disk
10
+
11
+
12
+ @pytest.fixture
13
+ def client(credential, authentication_policy):
14
+ """Create a Combined client for testing."""
15
+ return CombinedClient(
16
+ credential=credential, # Will use mock server, no real auth needed
17
+ subscription_id="00000000-0000-0000-0000-000000000000",
18
+ base_url="http://localhost:3000",
19
+ authentication_policy=authentication_policy,
20
+ polling_interval=0.1, # Speed up tests by reducing polling interval
21
+ )
22
+
23
+
24
+ def test_virtual_machines_get(client):
25
+ resource_group_name = "test-rg"
26
+ vm_name = "vm1"
27
+
28
+ with pytest.raises(HttpResponseError):
29
+ client.virtual_machines.get(
30
+ resource_group_name=resource_group_name,
31
+ vm_name=vm_name,
32
+ api_version="av1", # invalid api version shall raise error
33
+ )
34
+
35
+ result = client.virtual_machines.get(resource_group_name=resource_group_name, vm_name=vm_name)
36
+
37
+ assert result is not None
38
+ assert isinstance(result, VirtualMachine)
39
+ assert result.name == vm_name
40
+
41
+
42
+ def test_virtual_machines_create_or_update(client):
43
+ resource_group_name = "test-rg"
44
+ vm_name = "vm1"
45
+
46
+ vm_resource = VirtualMachine(location="eastus", properties={})
47
+
48
+ with pytest.raises(HttpResponseError):
49
+ client.virtual_machines.begin_create_or_update(
50
+ resource_group_name=resource_group_name,
51
+ vm_name=vm_name,
52
+ resource=vm_resource,
53
+ api_version="av1", # invalid api version shall raise error
54
+ ).result()
55
+
56
+ poller = client.virtual_machines.begin_create_or_update(
57
+ resource_group_name=resource_group_name, vm_name=vm_name, resource=vm_resource
58
+ )
59
+
60
+ result = poller.result()
61
+ assert result is not None
62
+ assert isinstance(result, VirtualMachine)
63
+ assert result.location == "eastus"
64
+
65
+
66
+ def test_disks_get(client):
67
+ resource_group_name = "test-rg"
68
+ disk_name = "disk1"
69
+ with pytest.raises(HttpResponseError):
70
+ client.disks.get(
71
+ resource_group_name=resource_group_name,
72
+ disk_name=disk_name,
73
+ api_version="av1", # invalid api version shall raise error
74
+ )
75
+
76
+ result = client.disks.get(resource_group_name=resource_group_name, disk_name=disk_name)
77
+
78
+ assert result is not None
79
+ assert isinstance(result, Disk)
80
+ assert result.name == disk_name
81
+
82
+
83
+ def test_disks_create_or_update(client):
84
+ resource_group_name = "test-rg"
85
+ disk_name = "disk1"
86
+
87
+ disk_resource = Disk(location="eastus", properties={})
88
+
89
+ with pytest.raises(HttpResponseError):
90
+ client.disks.begin_create_or_update(
91
+ resource_group_name=resource_group_name,
92
+ disk_name=disk_name,
93
+ resource=disk_resource,
94
+ api_version="av1", # invalid api version shall raise error
95
+ ).result()
96
+
97
+ poller = client.disks.begin_create_or_update(
98
+ resource_group_name=resource_group_name, disk_name=disk_name, resource=disk_resource
99
+ )
100
+
101
+ result = poller.result()
102
+ assert result is not None
103
+ assert isinstance(result, Disk)
104
+ assert result.location == "eastus"
@@ -0,0 +1,29 @@
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 azure.core.exceptions import HttpResponseError
8
+ from service.multiservice import CombinedClient
9
+ from service.multiservice.models import VersionsA, VersionsB
10
+
11
+
12
+ @pytest.fixture
13
+ def client():
14
+ """Fixture that creates a CombinedClient for testing."""
15
+ return CombinedClient(endpoint="http://localhost:3000")
16
+
17
+
18
+ def test_service_multi_service_foo(client):
19
+ with pytest.raises(HttpResponseError):
20
+ client.foo.test(api_version=VersionsA.AV1)
21
+
22
+ client.foo.test()
23
+
24
+
25
+ def test_service_multi_service_bar(client):
26
+ with pytest.raises(HttpResponseError):
27
+ client.bar.test(api_version=VersionsB.BV1)
28
+
29
+ client.bar.test()
@@ -35,3 +35,20 @@ def test_model(client: SpecialWordsClient, special_words):
35
35
 
36
36
  def test_model_properties(client: SpecialWordsClient):
37
37
  client.model_properties.same_as_model(models.SameAsModel(same_as_model="ok"))
38
+
39
+
40
+ def test_model_properties_dict_methods(client: SpecialWordsClient):
41
+ client.model_properties.dict_methods(
42
+ body=models.DictMethods(
43
+ keys_property="ok",
44
+ items_property="ok",
45
+ values_property="ok",
46
+ popitem_property="ok",
47
+ clear_property="ok",
48
+ update_property="ok",
49
+ setdefault_property="ok",
50
+ pop_property="ok",
51
+ get_property="ok",
52
+ copy_property="ok",
53
+ )
54
+ )
@@ -13,7 +13,11 @@ azure-mgmt-core==1.6.0
13
13
  -e ./generated/azure-client-generator-core-hierarchy-building
14
14
  -e ./generated/azure-client-generator-core-usage
15
15
  -e ./generated/azure-client-generator-core-override
16
- -e ./generated/azure-client-generator-core-client-location
16
+ -e ./generated/azure-client-generator-core-client-location-move-method-parameter-to-client
17
+ -e ./generated/azure-client-generator-core-client-location-move-to-existing-sub-client
18
+ -e ./generated/azure-client-generator-core-client-location-move-to-new-sub-client
19
+ -e ./generated/azure-client-generator-core-client-location-move-to-root-client
20
+ -e ./generated/azure-client-generator-core-client-default-value
17
21
  -e ./generated/azure-client-generator-core-alternate-type
18
22
  -e ./generated/azure-client-generator-core-next-link-verb
19
23
  -e ./generated/azure-core-basic
@@ -32,6 +36,7 @@ azure-mgmt-core==1.6.0
32
36
  -e ./generated/azure-resource-manager-operation-templates
33
37
  -e ./generated/azure-resource-manager-resources
34
38
  -e ./generated/azure-resource-manager-method-subscription-id
39
+ -e ./generated/azure-resource-manager-multi-service
35
40
  -e ./generated/azure-versioning-previewversion
36
41
  -e ./generated/client-namespace
37
42
  -e ./generated/azure-payload-pageable
@@ -45,6 +50,7 @@ azure-mgmt-core==1.6.0
45
50
  -e ./generated/client-structure-twooperationgroup
46
51
  -e ./generated/resiliency-srv-driven1
47
52
  -e ./generated/resiliency-srv-driven2
53
+ -e ./generated/service-multi-service
48
54
 
49
55
  # common test case
50
56
  -e ./generated/authentication-api-key
@@ -59,6 +65,7 @@ azure-mgmt-core==1.6.0
59
65
  -e ./generated/parameters-basic
60
66
  -e ./generated/parameters-collection-format
61
67
  -e ./generated/parameters-path
68
+ -e ./generated/parameters-query
62
69
  -e ./generated/parameters-spread
63
70
  -e ./generated/serialization-encoded-name-json
64
71
  -e ./generated/server-endpoint-not-defined
@@ -85,6 +92,7 @@ azure-mgmt-core==1.6.0
85
92
  -e ./generated/typetest-property-additionalproperties
86
93
  -e ./generated/typetest-scalar
87
94
  -e ./generated/typetest-union
95
+ -e ./generated/typetest-discriminatedunion
88
96
  -e ./generated/typetest-model-empty
89
97
  -e ./generated/headasbooleantrue
90
98
  -e ./generated/headasbooleanfalse
@@ -0,0 +1,18 @@
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.query.aio import QueryClient
8
+
9
+
10
+ @pytest.fixture
11
+ async def client():
12
+ async with QueryClient() as client:
13
+ yield client
14
+
15
+
16
+ @pytest.mark.asyncio
17
+ async def test_constant(client: QueryClient):
18
+ await client.constant.post()
@@ -0,0 +1,17 @@
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.query import QueryClient
8
+
9
+
10
+ @pytest.fixture
11
+ def client():
12
+ with QueryClient() as client:
13
+ yield client
14
+
15
+
16
+ def test_constant(client: QueryClient):
17
+ client.constant.post()
@@ -51,8 +51,3 @@ def test_decimal128_verify(client: ScalarClient):
51
51
  def test_decimal_verify(client: ScalarClient):
52
52
  prepare = client.decimal_verify.prepare_verify()
53
53
  client.decimal_verify.verify(reduce(lambda x, y: x + y, prepare))
54
-
55
-
56
- # open this test case after adopt new version of http-specs for https://github.com/microsoft/typespec/pull/8807
57
- # def test_constant_query(client: ScalarClient):
58
- # client.constant_query.post()
@@ -0,0 +1,290 @@
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 typetest.discriminatedunion import DiscriminatedClient
8
+ from typetest.discriminatedunion import models
9
+
10
+
11
+ @pytest.fixture
12
+ def client():
13
+ with DiscriminatedClient() as client:
14
+ yield client
15
+
16
+
17
+ @pytest.fixture
18
+ def cat_body():
19
+ """Cat model for testing."""
20
+ return models.Cat(name="Whiskers", meow=True)
21
+
22
+
23
+ @pytest.fixture
24
+ def dog_body():
25
+ """Dog model for testing."""
26
+ return models.Dog(name="Rex", bark=False)
27
+
28
+
29
+ # Tests for No Envelope / Default (inline discriminator with "kind")
30
+ @pytest.mark.skip(reason="After completely support discriminated unions, enable these tests")
31
+ class TestNoEnvelopeDefault:
32
+ """Test discriminated union with inline discriminator (no envelope)."""
33
+
34
+ def test_get_default_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
35
+ """Test getting cat with default (no query param or kind=cat).
36
+
37
+ Expected response:
38
+ {
39
+ "kind": "cat",
40
+ "name": "Whiskers",
41
+ "meow": true
42
+ }
43
+ """
44
+ result = client.no_envelope.default.get()
45
+ assert result == cat_body
46
+ assert isinstance(result, models.Cat)
47
+
48
+ def test_get_with_kind_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
49
+ """Test getting cat with kind=cat query parameter.
50
+
51
+ Expected response:
52
+ {
53
+ "kind": "cat",
54
+ "name": "Whiskers",
55
+ "meow": true
56
+ }
57
+ """
58
+ result = client.no_envelope.default.get(kind="cat")
59
+ assert result == cat_body
60
+ assert isinstance(result, models.Cat)
61
+
62
+ def test_get_with_kind_dog(self, client: DiscriminatedClient, dog_body: models.Dog):
63
+ """Test getting dog with kind=dog query parameter.
64
+
65
+ Expected response:
66
+ {
67
+ "kind": "dog",
68
+ "name": "Rex",
69
+ "bark": false
70
+ }
71
+ """
72
+ result = client.no_envelope.default.get(kind="dog")
73
+ assert result == dog_body
74
+ assert isinstance(result, models.Dog)
75
+
76
+ def test_put_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
77
+ """Test sending cat with inline discriminator.
78
+
79
+ Expected request:
80
+ {
81
+ "kind": "cat",
82
+ "name": "Whiskers",
83
+ "meow": true
84
+ }
85
+ """
86
+ result = client.no_envelope.default.put(cat_body)
87
+ assert result == cat_body
88
+ assert isinstance(result, models.Cat)
89
+
90
+
91
+ # Tests for No Envelope / Custom Discriminator (inline with custom "type" property)
92
+ @pytest.mark.skip(reason="After completely support discriminated unions, enable these tests")
93
+ class TestNoEnvelopeCustomDiscriminator:
94
+ """Test discriminated union with inline discriminator and custom discriminator property name."""
95
+
96
+ def test_get_default_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
97
+ """Test getting cat with default (no query param or type=cat).
98
+
99
+ Expected response:
100
+ {
101
+ "type": "cat",
102
+ "name": "Whiskers",
103
+ "meow": true
104
+ }
105
+ """
106
+ result = client.no_envelope.custom_discriminator.get()
107
+ assert result == cat_body
108
+ assert isinstance(result, models.Cat)
109
+
110
+ def test_get_with_type_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
111
+ """Test getting cat with type=cat query parameter.
112
+
113
+ Expected response:
114
+ {
115
+ "type": "cat",
116
+ "name": "Whiskers",
117
+ "meow": true
118
+ }
119
+ """
120
+ result = client.no_envelope.custom_discriminator.get(type="cat")
121
+ assert result == cat_body
122
+ assert isinstance(result, models.Cat)
123
+
124
+ def test_get_with_type_dog(self, client: DiscriminatedClient, dog_body: models.Dog):
125
+ """Test getting dog with type=dog query parameter.
126
+
127
+ Expected response:
128
+ {
129
+ "type": "dog",
130
+ "name": "Rex",
131
+ "bark": false
132
+ }
133
+ """
134
+ result = client.no_envelope.custom_discriminator.get(type="dog")
135
+ assert result == dog_body
136
+ assert isinstance(result, models.Dog)
137
+
138
+ def test_put_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
139
+ """Test sending cat with inline custom discriminator.
140
+
141
+ Expected request:
142
+ {
143
+ "type": "cat",
144
+ "name": "Whiskers",
145
+ "meow": true
146
+ }
147
+ """
148
+ result = client.no_envelope.custom_discriminator.put(cat_body)
149
+ assert result == cat_body
150
+ assert isinstance(result, models.Cat)
151
+
152
+
153
+ # Tests for Envelope / Object / Default (envelope with "kind" and "value")
154
+ @pytest.mark.skip(reason="After completely support discriminated unions, enable these tests")
155
+ class TestEnvelopeObjectDefault:
156
+ """Test discriminated union with default envelope serialization."""
157
+
158
+ def test_get_default_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
159
+ """Test getting cat with default (no query param or kind=cat).
160
+
161
+ Expected response:
162
+ {
163
+ "kind": "cat",
164
+ "value": {
165
+ "name": "Whiskers",
166
+ "meow": true
167
+ }
168
+ }
169
+ """
170
+ result = client.envelope.object.default.get()
171
+ assert result == cat_body
172
+ assert isinstance(result, models.Cat)
173
+
174
+ def test_get_with_kind_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
175
+ """Test getting cat with kind=cat query parameter.
176
+
177
+ Expected response:
178
+ {
179
+ "kind": "cat",
180
+ "value": {
181
+ "name": "Whiskers",
182
+ "meow": true
183
+ }
184
+ }
185
+ """
186
+ result = client.envelope.object.default.get(kind="cat")
187
+ assert result == cat_body
188
+ assert isinstance(result, models.Cat)
189
+
190
+ def test_get_with_kind_dog(self, client: DiscriminatedClient, dog_body: models.Dog):
191
+ """Test getting dog with kind=dog query parameter.
192
+
193
+ Expected response:
194
+ {
195
+ "kind": "dog",
196
+ "value": {
197
+ "name": "Rex",
198
+ "bark": false
199
+ }
200
+ }
201
+ """
202
+ result = client.envelope.object.default.get(kind="dog")
203
+ assert result == dog_body
204
+ assert isinstance(result, models.Dog)
205
+
206
+ def test_put_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
207
+ """Test sending cat with envelope serialization.
208
+
209
+ Expected request:
210
+ {
211
+ "kind": "cat",
212
+ "value": {
213
+ "name": "Whiskers",
214
+ "meow": true
215
+ }
216
+ }
217
+ """
218
+ result = client.envelope.object.default.put(cat_body)
219
+ assert result == cat_body
220
+ assert isinstance(result, models.Cat)
221
+
222
+
223
+ # Tests for Envelope / Object / Custom Properties (envelope with custom "petType" and "petData")
224
+ @pytest.mark.skip(reason="After completely support discriminated unions, enable these tests")
225
+ class TestEnvelopeObjectCustomProperties:
226
+ """Test discriminated union with custom property names in envelope."""
227
+
228
+ def test_get_default_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
229
+ """Test getting cat with default (no query param or petType=cat).
230
+
231
+ Expected response:
232
+ {
233
+ "petType": "cat",
234
+ "petData": {
235
+ "name": "Whiskers",
236
+ "meow": true
237
+ }
238
+ }
239
+ """
240
+ result = client.envelope.object.custom_properties.get()
241
+ assert result == cat_body
242
+ assert isinstance(result, models.Cat)
243
+
244
+ def test_get_with_pet_type_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
245
+ """Test getting cat with petType=cat query parameter.
246
+
247
+ Expected response:
248
+ {
249
+ "petType": "cat",
250
+ "petData": {
251
+ "name": "Whiskers",
252
+ "meow": true
253
+ }
254
+ }
255
+ """
256
+ result = client.envelope.object.custom_properties.get(pet_type="cat")
257
+ assert result == cat_body
258
+ assert isinstance(result, models.Cat)
259
+
260
+ def test_get_with_pet_type_dog(self, client: DiscriminatedClient, dog_body: models.Dog):
261
+ """Test getting dog with petType=dog query parameter.
262
+
263
+ Expected response:
264
+ {
265
+ "petType": "dog",
266
+ "petData": {
267
+ "name": "Rex",
268
+ "bark": false
269
+ }
270
+ }
271
+ """
272
+ result = client.envelope.object.custom_properties.get(pet_type="dog")
273
+ assert result == dog_body
274
+ assert isinstance(result, models.Dog)
275
+
276
+ def test_put_cat(self, client: DiscriminatedClient, cat_body: models.Cat):
277
+ """Test sending cat with custom property names in envelope.
278
+
279
+ Expected request:
280
+ {
281
+ "petType": "cat",
282
+ "petData": {
283
+ "name": "Whiskers",
284
+ "meow": true
285
+ }
286
+ }
287
+ """
288
+ result = client.envelope.object.custom_properties.put(cat_body)
289
+ assert result == cat_body
290
+ assert isinstance(result, models.Cat)
@@ -14,6 +14,7 @@
14
14
  -e ./generated/parameters-basic
15
15
  -e ./generated/parameters-collection-format
16
16
  -e ./generated/parameters-path
17
+ -e ./generated/parameters-query
17
18
  -e ./generated/parameters-spread
18
19
  -e ./generated/serialization-encoded-name-json
19
20
  -e ./generated/server-endpoint-not-defined
@@ -40,6 +41,7 @@
40
41
  -e ./generated/typetest-property-additionalproperties
41
42
  -e ./generated/typetest-scalar
42
43
  -e ./generated/typetest-union
44
+ -e ./generated/typetest-discriminatedunion
43
45
  -e ./generated/typetest-model-empty
44
46
  -e ./generated/headasbooleantrue
45
47
  -e ./generated/headasbooleanfalse
@@ -332,6 +332,72 @@ def test_property_is_a_type():
332
332
  assert fishery.fish.species == fishery.fish["species"] == fishery["fish"]["species"] == "Salmon"
333
333
 
334
334
 
335
+ def test_model_initialization():
336
+ class DatetimeModel(Model):
337
+ datetime_value: datetime.datetime = rest_field(name="datetimeValue")
338
+
339
+ @overload
340
+ def __init__(self, *, datetime_value: datetime.datetime): ...
341
+
342
+ @overload
343
+ def __init__(self, mapping: Mapping[str, Any], /): ...
344
+
345
+ def __init__(self, *args, **kwargs):
346
+ super().__init__(*args, **kwargs)
347
+
348
+ val_str = "9999-12-31T23:59:59.999000Z"
349
+ val = isodate.parse_datetime(val_str)
350
+
351
+ # when initialize model with dict, the dict value is shall be serialized value
352
+ model1 = DatetimeModel({"datetimeValue": val_str})
353
+ assert model1["datetimeValue"] == val_str
354
+ assert model1.datetime_value == val
355
+
356
+ # when initialize model with keyword args, the value is deserialized value
357
+ model2 = DatetimeModel(datetime_value=val)
358
+ assert model2["datetimeValue"] == val_str
359
+ assert model2.datetime_value == val
360
+
361
+ # what if we initialize with dict but the dict has deserialized value? this case show what happens.
362
+ # Since we always serialize the value before initializing the model from dict, we could still get correct result
363
+ model3 = DatetimeModel({"datetimeValue": val})
364
+ assert model3["datetimeValue"] == val_str
365
+ assert model3.datetime_value == val
366
+
367
+
368
+ def test_model_dict_prop_initialization():
369
+ class DatetimeModel(Model):
370
+ dict_prop: dict[str, datetime.datetime] = rest_field(name="dictProp")
371
+
372
+ @overload
373
+ def __init__(self, *, dict_prop: dict[str, datetime.datetime]): ...
374
+
375
+ @overload
376
+ def __init__(self, mapping: Mapping[str, Any], /): ...
377
+
378
+ def __init__(self, *args, **kwargs):
379
+ super().__init__(*args, **kwargs)
380
+
381
+ val_str = "9999-12-31T23:59:59.999000Z"
382
+ val = isodate.parse_datetime(val_str)
383
+
384
+ # when initialize model with dict, the dict value is shall be serialized value
385
+ model1 = DatetimeModel({"dictProp": {"key1": val_str}})
386
+ assert model1["dictProp"] == {"key1": val_str}
387
+ assert model1.dict_prop == {"key1": val}
388
+
389
+ # when initialize model with keyword args, the value is deserialized value
390
+ model2 = DatetimeModel(dict_prop={"key1": val})
391
+ assert model2["dictProp"] == {"key1": val_str}
392
+ assert model2.dict_prop == {"key1": val}
393
+
394
+ # what if we initialize with dict but the dict has deserialized value? this case show what happens.
395
+ # Since we always serialize the value before initializing the model from dict, we could still get correct result
396
+ model3 = DatetimeModel({"dictProp": {"key1": val}})
397
+ assert model3["dictProp"] == {"key1": val_str}
398
+ assert model3.dict_prop == {"key1": val}
399
+
400
+
335
401
  def test_datetime_deserialization():
336
402
  class DatetimeModel(Model):
337
403
  datetime_value: datetime.datetime = rest_field(name="datetimeValue")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http-client-python",
3
- "version": "0.23.1",
3
+ "version": "0.24.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.63.0 <1.0.0",
59
59
  "@azure-tools/typespec-azure-resource-manager": ">=0.63.0 <1.0.0",
60
60
  "@azure-tools/typespec-azure-rulesets": ">=0.63.0 <1.0.0",
61
- "@azure-tools/typespec-client-generator-core": ">=0.63.0 <1.0.0",
61
+ "@azure-tools/typespec-client-generator-core": ">=0.63.4 <1.0.0",
62
62
  "@typespec/compiler": "^1.7.0",
63
63
  "@typespec/http": "^1.7.0",
64
64
  "@typespec/openapi": "^1.7.0",
@@ -81,8 +81,8 @@
81
81
  "@azure-tools/typespec-azure-core": "~0.63.0",
82
82
  "@azure-tools/typespec-azure-resource-manager": "~0.63.0",
83
83
  "@azure-tools/typespec-azure-rulesets": "~0.63.0",
84
- "@azure-tools/typespec-client-generator-core": "~0.63.0",
85
- "@azure-tools/azure-http-specs": "0.1.0-alpha.33",
84
+ "@azure-tools/typespec-client-generator-core": "~0.63.4",
85
+ "@azure-tools/azure-http-specs": "0.1.0-alpha.35-dev.8",
86
86
  "@typespec/compiler": "^1.7.0",
87
87
  "@typespec/http": "^1.7.0",
88
88
  "@typespec/openapi": "^1.7.0",
@@ -94,7 +94,7 @@
94
94
  "@typespec/sse": "~0.77.0",
95
95
  "@typespec/streams": "~0.77.0",
96
96
  "@typespec/xml": "~0.77.0",
97
- "@typespec/http-specs": "0.1.0-alpha.29",
97
+ "@typespec/http-specs": "0.1.0-alpha.30-dev.1",
98
98
  "@types/js-yaml": "~4.0.5",
99
99
  "@types/node": "~24.1.0",
100
100
  "@types/semver": "7.5.8",