@typespec/http-client-python 0.22.0 → 0.23.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 (25) hide show
  1. package/dist/emitter/types.d.ts.map +1 -1
  2. package/dist/emitter/types.js +1 -0
  3. package/dist/emitter/types.js.map +1 -1
  4. package/emitter/src/types.ts +1 -0
  5. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  6. package/eng/scripts/ci/regenerate.ts +5 -1
  7. package/eng/scripts/setup/__pycache__/package_manager.cpython-311.pyc +0 -0
  8. package/eng/scripts/setup/__pycache__/venvtools.cpython-311.pyc +0 -0
  9. package/generator/build/lib/pygen/codegen/models/property.py +1 -0
  10. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +2 -0
  11. package/generator/build/lib/pygen/codegen/templates/macros.jinja2 +12 -5
  12. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +28 -0
  13. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  14. package/generator/pygen/codegen/models/property.py +1 -0
  15. package/generator/pygen/codegen/serializers/model_serializer.py +2 -0
  16. package/generator/pygen/codegen/templates/macros.jinja2 +12 -5
  17. package/generator/pygen/codegen/templates/model_base.py.jinja2 +28 -0
  18. package/generator/test/azure/requirements.txt +1 -0
  19. package/generator/test/generic_mock_api_tests/asynctests/test_encode_array_async.py +43 -0
  20. package/generator/test/generic_mock_api_tests/asynctests/test_specs_documentation_async.py +60 -0
  21. package/generator/test/generic_mock_api_tests/test_encode_array.py +38 -0
  22. package/generator/test/generic_mock_api_tests/test_specs_documentation.py +52 -0
  23. package/generator/test/unbranded/requirements.txt +1 -0
  24. package/generator/test/unittests/test_model_base_serialization.py +264 -0
  25. package/package.json +1 -1
@@ -4108,3 +4108,267 @@ def test_multi_layer_discriminator():
4108
4108
 
4109
4109
  assert AnotherPet(name="Buddy", trained=True) == model_pet
4110
4110
  assert AnotherDog(name="Rex", trained=True, breed="German Shepherd") == model_dog
4111
+
4112
+
4113
+ def test_array_encode_comma_delimited():
4114
+ """Test commaDelimited format for array of strings"""
4115
+
4116
+ class CommaDelimitedModel(Model):
4117
+ colors: list[str] = rest_field(format="commaDelimited")
4118
+
4119
+ @overload
4120
+ def __init__(self, *, colors: list[str]): ...
4121
+
4122
+ @overload
4123
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4124
+
4125
+ def __init__(self, *args, **kwargs):
4126
+ super().__init__(*args, **kwargs)
4127
+
4128
+ # Test serialization: list[str] -> comma-delimited string
4129
+ model = CommaDelimitedModel(colors=["blue", "red", "green"])
4130
+ assert model.colors == ["blue", "red", "green"]
4131
+ assert model["colors"] == "blue,red,green"
4132
+
4133
+ # Test deserialization: comma-delimited string -> list[str]
4134
+ model = CommaDelimitedModel({"colors": "blue,red,green"})
4135
+ assert model.colors == ["blue", "red", "green"]
4136
+ assert model["colors"] == "blue,red,green"
4137
+
4138
+ # Test with empty list
4139
+ model = CommaDelimitedModel(colors=[])
4140
+ assert model.colors == []
4141
+ assert model["colors"] == ""
4142
+
4143
+ # Test with single item
4144
+ model = CommaDelimitedModel(colors=["blue"])
4145
+ assert model.colors == ["blue"]
4146
+ assert model["colors"] == "blue"
4147
+
4148
+
4149
+ def test_array_encode_pipe_delimited():
4150
+ """Test pipeDelimited format for array of strings"""
4151
+
4152
+ class PipeDelimitedModel(Model):
4153
+ colors: list[str] = rest_field(format="pipeDelimited")
4154
+
4155
+ @overload
4156
+ def __init__(self, *, colors: list[str]): ...
4157
+
4158
+ @overload
4159
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4160
+
4161
+ def __init__(self, *args, **kwargs):
4162
+ super().__init__(*args, **kwargs)
4163
+
4164
+ # Test serialization: list[str] -> pipe-delimited string
4165
+ model = PipeDelimitedModel(colors=["blue", "red", "green"])
4166
+ assert model.colors == ["blue", "red", "green"]
4167
+ assert model["colors"] == "blue|red|green"
4168
+
4169
+ # Test deserialization: pipe-delimited string -> list[str]
4170
+ model = PipeDelimitedModel({"colors": "blue|red|green"})
4171
+ assert model.colors == ["blue", "red", "green"]
4172
+ assert model["colors"] == "blue|red|green"
4173
+
4174
+ # Test with empty list
4175
+ model = PipeDelimitedModel(colors=[])
4176
+ assert model.colors == []
4177
+ assert model["colors"] == ""
4178
+
4179
+
4180
+ def test_array_encode_space_delimited():
4181
+ """Test spaceDelimited format for array of strings"""
4182
+
4183
+ class SpaceDelimitedModel(Model):
4184
+ colors: list[str] = rest_field(format="spaceDelimited")
4185
+
4186
+ @overload
4187
+ def __init__(self, *, colors: list[str]): ...
4188
+
4189
+ @overload
4190
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4191
+
4192
+ def __init__(self, *args, **kwargs):
4193
+ super().__init__(*args, **kwargs)
4194
+
4195
+ # Test serialization: list[str] -> space-delimited string
4196
+ model = SpaceDelimitedModel(colors=["blue", "red", "green"])
4197
+ assert model.colors == ["blue", "red", "green"]
4198
+ assert model["colors"] == "blue red green"
4199
+
4200
+ # Test deserialization: space-delimited string -> list[str]
4201
+ model = SpaceDelimitedModel({"colors": "blue red green"})
4202
+ assert model.colors == ["blue", "red", "green"]
4203
+ assert model["colors"] == "blue red green"
4204
+
4205
+ # Test with empty list
4206
+ model = SpaceDelimitedModel(colors=[])
4207
+ assert model.colors == []
4208
+ assert model["colors"] == ""
4209
+
4210
+
4211
+ def test_array_encode_newline_delimited():
4212
+ """Test newlineDelimited format for array of strings"""
4213
+
4214
+ class NewlineDelimitedModel(Model):
4215
+ colors: list[str] = rest_field(format="newlineDelimited")
4216
+
4217
+ @overload
4218
+ def __init__(self, *, colors: list[str]): ...
4219
+
4220
+ @overload
4221
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4222
+
4223
+ def __init__(self, *args, **kwargs):
4224
+ super().__init__(*args, **kwargs)
4225
+
4226
+ # Test serialization: list[str] -> newline-delimited string
4227
+ model = NewlineDelimitedModel(colors=["blue", "red", "green"])
4228
+ assert model.colors == ["blue", "red", "green"]
4229
+ assert model["colors"] == "blue\nred\ngreen"
4230
+
4231
+ # Test deserialization: newline-delimited string -> list[str]
4232
+ model = NewlineDelimitedModel({"colors": "blue\nred\ngreen"})
4233
+ assert model.colors == ["blue", "red", "green"]
4234
+ assert model["colors"] == "blue\nred\ngreen"
4235
+
4236
+ # Test with empty list
4237
+ model = NewlineDelimitedModel(colors=[])
4238
+ assert model.colors == []
4239
+ assert model["colors"] == ""
4240
+
4241
+
4242
+ def test_array_encode_optional():
4243
+ """Test array encoding with optional fields"""
4244
+
4245
+ class OptionalEncodedModel(Model):
4246
+ colors: Optional[list[str]] = rest_field(default=None, format="commaDelimited")
4247
+
4248
+ @overload
4249
+ def __init__(self, *, colors: Optional[list[str]] = None): ...
4250
+
4251
+ @overload
4252
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4253
+
4254
+ def __init__(self, *args, **kwargs):
4255
+ super().__init__(*args, **kwargs)
4256
+
4257
+ # Test with None
4258
+ model = OptionalEncodedModel(colors=None)
4259
+ assert model.colors is None
4260
+ assert model["colors"] is None
4261
+
4262
+ # Test with value
4263
+ model = OptionalEncodedModel(colors=["blue", "red"])
4264
+ assert model.colors == ["blue", "red"]
4265
+ assert model["colors"] == "blue,red"
4266
+
4267
+ # Test deserialization with None
4268
+ model = OptionalEncodedModel({"colors": None})
4269
+ assert model.colors is None
4270
+
4271
+
4272
+ def test_array_encode_modification():
4273
+ """Test modifying array-encoded fields"""
4274
+
4275
+ class ModifiableModel(Model):
4276
+ colors: list[str] = rest_field(format="commaDelimited")
4277
+
4278
+ @overload
4279
+ def __init__(self, *, colors: list[str]): ...
4280
+
4281
+ @overload
4282
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4283
+
4284
+ def __init__(self, *args, **kwargs):
4285
+ super().__init__(*args, **kwargs)
4286
+
4287
+ model = ModifiableModel(colors=["blue", "red"])
4288
+ assert model.colors == ["blue", "red"]
4289
+ assert model["colors"] == "blue,red"
4290
+
4291
+ # Modify through property
4292
+ model.colors = ["green", "yellow", "purple"]
4293
+ assert model.colors == ["green", "yellow", "purple"]
4294
+ assert model["colors"] == "green,yellow,purple"
4295
+
4296
+ # Modify through dict access
4297
+ model["colors"] = "orange,pink"
4298
+ assert model.colors == ["orange", "pink"]
4299
+ assert model["colors"] == "orange,pink"
4300
+
4301
+
4302
+ def test_array_encode_json_roundtrip():
4303
+ """Test JSON serialization and deserialization with array encoding"""
4304
+
4305
+ class JsonModel(Model):
4306
+ pipe_colors: list[str] = rest_field(name="pipeColors", format="pipeDelimited")
4307
+ comma_colors: list[str] = rest_field(name="commaColors", format="commaDelimited")
4308
+
4309
+ @overload
4310
+ def __init__(
4311
+ self,
4312
+ *,
4313
+ pipe_colors: list[str],
4314
+ comma_colors: list[str],
4315
+ ): ...
4316
+
4317
+ @overload
4318
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4319
+
4320
+ def __init__(self, *args, **kwargs):
4321
+ super().__init__(*args, **kwargs)
4322
+
4323
+ model = JsonModel(
4324
+ pipe_colors=["blue", "red", "green"],
4325
+ comma_colors=["small", "medium", "large"],
4326
+ )
4327
+
4328
+ # Serialize to JSON
4329
+ json_str = json.dumps(dict(model), cls=SdkJSONEncoder)
4330
+ assert json.loads(json_str) == {
4331
+ "pipeColors": "blue|red|green",
4332
+ "commaColors": "small,medium,large",
4333
+ }
4334
+
4335
+ # Deserialize from JSON
4336
+ deserialized = JsonModel(json.loads(json_str))
4337
+ assert deserialized.pipe_colors == ["blue", "red", "green"]
4338
+ assert deserialized.comma_colors == ["small", "medium", "large"]
4339
+
4340
+
4341
+ def test_array_encode_with_special_characters():
4342
+ """Test array encoding with strings containing special characters"""
4343
+
4344
+ class SpecialCharsModel(Model):
4345
+ comma_values: list[str] = rest_field(name="commaValues", format="commaDelimited")
4346
+ pipe_values: list[str] = rest_field(name="pipeValues", format="pipeDelimited")
4347
+
4348
+ @overload
4349
+ def __init__(
4350
+ self,
4351
+ *,
4352
+ comma_values: list[str],
4353
+ pipe_values: list[str],
4354
+ ): ...
4355
+
4356
+ @overload
4357
+ def __init__(self, mapping: Mapping[str, Any], /): ...
4358
+
4359
+ def __init__(self, *args, **kwargs):
4360
+ super().__init__(*args, **kwargs)
4361
+
4362
+ # Test with strings that might contain delimiters
4363
+ # Note: In real usage, the strings should not contain the delimiter character
4364
+ # This test documents current behavior
4365
+ model = SpecialCharsModel(
4366
+ comma_values=["value with spaces", "another-value", "value_3"],
4367
+ pipe_values=["path/to/file", "another-path", "final.path"],
4368
+ )
4369
+
4370
+ assert model.comma_values == ["value with spaces", "another-value", "value_3"]
4371
+ assert model["commaValues"] == "value with spaces,another-value,value_3"
4372
+
4373
+ assert model.pipe_values == ["path/to/file", "another-path", "final.path"]
4374
+ assert model["pipeValues"] == "path/to/file|another-path|final.path"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http-client-python",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec emitter for Python SDKs",
6
6
  "homepage": "https://typespec.io",