Skip to content

Commit fa6b88b

Browse files
authored
[Python] Support encode for array of string in serialization and deserialization (#3280)
* Update dependencies * Add changelog .chronus/changes/auto-microsoft-python-array-encode-2025-11-5-10-12-9.md * Update dependencies (2025-12-11 09:22:58) * Regenerate for typespec-python (2025-12-11 09:28:02) * update test case * Update dependencies * Update dependencies (2025-12-12 03:50:10) * Regenerate for typespec-python (2025-12-12 03:55:19) * Update dependencies * Update dependencies (2025-12-12 08:12:07) * Regenerate for typespec-python (2025-12-12 08:17:31) --------- Co-authored-by: AutoPrFromHttpClientPython <AutoPrFromHttpClientPython>
1 parent e183d05 commit fa6b88b

173 files changed

Lines changed: 5056 additions & 17 deletions

File tree

  • .chronus/changes
  • packages
    • autorest.python
    • typespec-python
      • test
        • azure/generated
          • authentication-api-key/authentication/apikey/_utils
          • authentication-http-custom/authentication/http/custom/_utils
          • authentication-oauth2/authentication/oauth2/_utils
          • authentication-union/authentication/union/_utils
          • azure-client-generator-core-access/specs/azure/clientgenerator/core/access/_utils
          • azure-client-generator-core-alternate-type/specs/azure/clientgenerator/core/alternatetype/_utils
          • azure-client-generator-core-api-version-header/client/alternateapiversion/service/header/_utils
          • azure-client-generator-core-api-version-path/client/alternateapiversion/service/path/_utils
          • azure-client-generator-core-api-version-query/client/alternateapiversion/service/query/_utils
          • azure-client-generator-core-client-initialization/specs/azure/clientgenerator/core/clientinitialization/_utils
          • azure-client-generator-core-client-location/specs/azure/clientgenerator/core/clientlocation/_utils
          • azure-client-generator-core-deserialize-empty-string-as-null/specs/azure/clientgenerator/core/emptystring/_utils
          • azure-client-generator-core-flatten-property/specs/azure/clientgenerator/core/flattenproperty/_utils
          • azure-client-generator-core-hierarchy-building/specs/azure/clientgenerator/core/hierarchybuilding/_utils
          • azure-client-generator-core-override/specs/azure/clientgenerator/core/override/_utils
          • azure-client-generator-core-usage/specs/azure/clientgenerator/core/usage/_utils
          • azure-core-basic/specs/azure/core/basic/_utils
          • azure-core-lro-rpc/specs/azure/core/lro/rpc/_utils
          • azure-core-lro-standard/specs/azure/core/lro/standard/_utils
          • azure-core-model/specs/azure/core/model/_utils
          • azure-core-page/specs/azure/core/page/_utils
          • azure-core-scalar/specs/azure/core/scalar/_utils
          • azure-core-traits/specs/azure/core/traits/_utils
          • azure-encode-duration/specs/azure/encode/duration/_utils
          • azure-example-basic/specs/azure/example/basic/_utils
          • azure-payload-pageable/specs/azure/payload/pageable/_utils
          • azure-resource-manager-common-properties/azure/resourcemanager/commonproperties/_utils
          • azure-resource-manager-large-header/azure/resourcemanager/largeheader/_utils
          • azure-resource-manager-method-subscription-id/azure/resourcemanager/methodsubscriptionid/_utils
          • azure-resource-manager-non-resource/azure/resourcemanager/nonresource/_utils
          • azure-resource-manager-operation-templates/azure/resourcemanager/operationtemplates/_utils
          • azure-resource-manager-resources/azure/resourcemanager/resources/_utils
          • azure-special-headers-client-request-id/azure/specialheaders/xmsclientrequestid/_utils
          • azure-versioning-previewversion/specs/azure/versioning/previewversion/_utils
          • client-namespace/client/clientnamespace
          • client-naming-enum-conflict/client/naming/enumconflict/_utils
          • client-naming/client/naming/main/_utils
          • client-overload/client/overload/_utils
          • client-structure-clientoperationgroup/client/structure/clientoperationgroup/_utils
          • client-structure-default/client/structure/service/_utils
          • client-structure-multiclient/client/structure/multiclient/_utils
          • client-structure-renamedoperation/client/structure/renamedoperation/_utils
          • client-structure-twooperationgroup/client/structure/twooperationgroup/_utils
          • encode-array/encode/array
          • encode-bytes/encode/bytes/_utils
          • encode-datetime/encode/datetime/_utils
          • encode-duration/encode/duration/_utils
          • encode-numeric/encode/numeric/_utils
          • generation-subdir/generation/subdir/_generated/_utils
          • headasbooleanfalse/headasbooleanfalse/_utils
          • headasbooleantrue/headasbooleantrue/_utils
          • parameters-basic/parameters/basic/_utils
          • parameters-body-optionality/parameters/bodyoptionality/_utils
          • parameters-collection-format/parameters/collectionformat/_utils
          • parameters-path/parameters/path/_utils
          • parameters-spread/parameters/spread/_utils
          • payload-content-negotiation/payload/contentnegotiation/_utils
          • payload-json-merge-patch/payload/jsonmergepatch/_utils
          • payload-media-type/payload/mediatype/_utils
          • payload-multipart/payload/multipart/_utils
          • payload-pageable/payload/pageable/_utils
          • payload-xml/payload/xml/_utils
          • resiliency-srv-driven1/resiliency/srv/driven1/_utils
          • resiliency-srv-driven2/resiliency/srv/driven2/_utils
          • response-status-code-range/response/statuscoderange/_utils
          • routes/routes/_utils
          • serialization-encoded-name-json/serialization/encodedname/json/_utils
          • server-endpoint-not-defined/server/endpoint/notdefined/_utils
          • server-path-multiple/server/path/multiple/_utils
          • server-path-single/server/path/single/_utils
          • server-versions-not-versioned/server/versions/notversioned/_utils
          • server-versions-versioned/server/versions/versioned/_utils
          • setuppy-authentication-union/setuppy/authentication/union/_utils
          • special-headers-conditional-request/specialheaders/conditionalrequest/_utils
          • special-headers-repeatability/specialheaders/repeatability/_utils
          • special-words/specialwords/_utils
          • specs-documentation/specs/documentation/_utils
          • streaming-jsonl/streaming/jsonl/_utils
          • typetest-array/typetest/array/_utils
          • typetest-dictionary/typetest/dictionary/_utils
          • typetest-enum-extensible/typetest/enum/extensible/_utils
          • typetest-enum-fixed/typetest/enum/fixed/_utils
          • typetest-model-empty/typetest/model/empty/_utils
          • typetest-model-enumdiscriminator/typetest/model/enumdiscriminator/_utils
          • typetest-model-nesteddiscriminator/typetest/model/nesteddiscriminator/_utils
          • typetest-model-notdiscriminated/typetest/model/notdiscriminated/_utils
          • typetest-model-recursive/typetest/model/recursive/_utils
          • typetest-model-singlediscriminator/typetest/model/singlediscriminator/_utils
          • typetest-model-usage/typetest/model/usage/_utils
          • typetest-model-visibility/typetest/model/visibility/_utils
          • typetest-property-additionalproperties/typetest/property/additionalproperties/_utils
          • typetest-property-nullable/typetest/property/nullable/_utils
          • typetest-property-optional/typetest/property/optional/_utils
          • typetest-property-valuetypes/typetest/property/valuetypes/_utils
          • typetest-scalar/typetest/scalar/_utils
          • typetest-union/typetest/union/_utils
          • versioning-added/versioning/added/_utils
          • versioning-madeoptional/versioning/madeoptional/_utils
          • versioning-removed/versioning/removed/_utils
          • versioning-renamedfrom/versioning/renamedfrom/_utils
          • versioning-returntypechangedfrom/versioning/returntypechangedfrom/_utils
          • versioning-typechangedfrom/versioning/typechangedfrom/_utils
        • generic_mock_api_tests
        • unbranded/generated

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
changeKind: feature
3+
packages:
4+
- "@autorest/python"
5+
- "@azure-tools/typespec-python"
6+
---
7+
8+
Support encode for array of string in serialization and deserialization

packages/autorest.python/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
},
3030
"homepage": "https://github.com/Azure/autorest.python/blob/main/README.md",
3131
"dependencies": {
32-
"@typespec/http-client-python": "https://artprodcus3.artifacts.visualstudio.com/A0fb41ef4-5012-48a9-bf39-4ee3de03ee35/29ec6040-b234-4e31-b139-33dc4287b756/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL2F6dXJlLXNkay9wcm9qZWN0SWQvMjllYzYwNDAtYjIzNC00ZTMxLWIxMzktMzNkYzQyODdiNzU2L2J1aWxkSWQvNTY1OTA2NS9hcnRpZmFjdE5hbWUvYnVpbGRfYXJ0aWZhY3RzX3B5dGhvbg2/content?format=file&subPath=%2Fpackages%2Ftypespec-http-client-python-0.22.0.tgz",
32+
"@typespec/http-client-python": "https://artprodcus3.artifacts.visualstudio.com/A0fb41ef4-5012-48a9-bf39-4ee3de03ee35/29ec6040-b234-4e31-b139-33dc4287b756/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL2F6dXJlLXNkay9wcm9qZWN0SWQvMjllYzYwNDAtYjIzNC00ZTMxLWIxMzktMzNkYzQyODdiNzU2L2J1aWxkSWQvNTY2MzY4Mi9hcnRpZmFjdE5hbWUvYnVpbGRfYXJ0aWZhY3RzX3B5dGhvbg2/content?format=file&subPath=%2Fpackages%2Ftypespec-http-client-python-0.22.0.tgz",
3333
"@autorest/system-requirements": "~1.0.2",
3434
"fs-extra": "~11.2.0",
3535
"tsx": "~4.19.1"

packages/typespec-python/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"js-yaml": "~4.1.0",
6868
"semver": "~7.6.2",
6969
"tsx": "~4.19.1",
70-
"@typespec/http-client-python": "https://artprodcus3.artifacts.visualstudio.com/A0fb41ef4-5012-48a9-bf39-4ee3de03ee35/29ec6040-b234-4e31-b139-33dc4287b756/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL2F6dXJlLXNkay9wcm9qZWN0SWQvMjllYzYwNDAtYjIzNC00ZTMxLWIxMzktMzNkYzQyODdiNzU2L2J1aWxkSWQvNTY1OTA2NS9hcnRpZmFjdE5hbWUvYnVpbGRfYXJ0aWZhY3RzX3B5dGhvbg2/content?format=file&subPath=%2Fpackages%2Ftypespec-http-client-python-0.22.0.tgz",
70+
"@typespec/http-client-python": "https://artprodcus3.artifacts.visualstudio.com/A0fb41ef4-5012-48a9-bf39-4ee3de03ee35/29ec6040-b234-4e31-b139-33dc4287b756/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL2F6dXJlLXNkay9wcm9qZWN0SWQvMjllYzYwNDAtYjIzNC00ZTMxLWIxMzktMzNkYzQyODdiNzU2L2J1aWxkSWQvNTY2MzY4Mi9hcnRpZmFjdE5hbWUvYnVpbGRfYXJ0aWZhY3RzX3B5dGhvbg2/content?format=file&subPath=%2Fpackages%2Ftypespec-http-client-python-0.22.0.tgz",
7171
"fs-extra": "~11.2.0"
7272
},
7373
"devDependencies": {

packages/typespec-python/test/azure/generated/authentication-api-key/authentication/apikey/_utils/model_base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ def default(self, o): # pylint: disable=too-many-return-statements
171171
r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
172172
)
173173

174+
_ARRAY_ENCODE_MAPPING = {
175+
"pipeDelimited": "|",
176+
"spaceDelimited": " ",
177+
"commaDelimited": ",",
178+
"newlineDelimited": "\n",
179+
}
180+
181+
182+
def _deserialize_array_encoded(delimit: str, attr):
183+
if isinstance(attr, str):
184+
if attr == "":
185+
return []
186+
return attr.split(delimit)
187+
return attr
188+
174189

175190
def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
176191
"""Deserialize ISO-8601 formatted string into Datetime object.
@@ -315,6 +330,8 @@ def _deserialize_int_as_str(attr):
315330
def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
316331
if annotation is int and rf and rf._format == "str":
317332
return _deserialize_int_as_str
333+
if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
334+
return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
318335
if rf and rf._format:
319336
return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
320337
return _DESERIALIZE_MAPPING.get(annotation) # pyright: ignore
@@ -483,6 +500,8 @@ def _is_model(obj: typing.Any) -> bool:
483500

484501
def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
485502
if isinstance(o, list):
503+
if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
504+
return _ARRAY_ENCODE_MAPPING[format].join(o)
486505
return [_serialize(x, format) for x in o]
487506
if isinstance(o, dict):
488507
return {k: _serialize(v, format) for k, v in o.items()}
@@ -767,6 +786,17 @@ def _deserialize_sequence(
767786
return obj
768787
if isinstance(obj, ET.Element):
769788
obj = list(obj)
789+
try:
790+
if (
791+
isinstance(obj, str)
792+
and isinstance(deserializer, functools.partial)
793+
and isinstance(deserializer.args[0], functools.partial)
794+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
795+
):
796+
# encoded string may be deserialized to sequence
797+
return deserializer(obj)
798+
except: # pylint: disable=bare-except
799+
pass
770800
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
771801

772802

packages/typespec-python/test/azure/generated/authentication-http-custom/authentication/http/custom/_utils/model_base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ def default(self, o): # pylint: disable=too-many-return-statements
171171
r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
172172
)
173173

174+
_ARRAY_ENCODE_MAPPING = {
175+
"pipeDelimited": "|",
176+
"spaceDelimited": " ",
177+
"commaDelimited": ",",
178+
"newlineDelimited": "\n",
179+
}
180+
181+
182+
def _deserialize_array_encoded(delimit: str, attr):
183+
if isinstance(attr, str):
184+
if attr == "":
185+
return []
186+
return attr.split(delimit)
187+
return attr
188+
174189

175190
def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
176191
"""Deserialize ISO-8601 formatted string into Datetime object.
@@ -315,6 +330,8 @@ def _deserialize_int_as_str(attr):
315330
def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
316331
if annotation is int and rf and rf._format == "str":
317332
return _deserialize_int_as_str
333+
if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
334+
return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
318335
if rf and rf._format:
319336
return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
320337
return _DESERIALIZE_MAPPING.get(annotation) # pyright: ignore
@@ -483,6 +500,8 @@ def _is_model(obj: typing.Any) -> bool:
483500

484501
def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
485502
if isinstance(o, list):
503+
if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
504+
return _ARRAY_ENCODE_MAPPING[format].join(o)
486505
return [_serialize(x, format) for x in o]
487506
if isinstance(o, dict):
488507
return {k: _serialize(v, format) for k, v in o.items()}
@@ -767,6 +786,17 @@ def _deserialize_sequence(
767786
return obj
768787
if isinstance(obj, ET.Element):
769788
obj = list(obj)
789+
try:
790+
if (
791+
isinstance(obj, str)
792+
and isinstance(deserializer, functools.partial)
793+
and isinstance(deserializer.args[0], functools.partial)
794+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
795+
):
796+
# encoded string may be deserialized to sequence
797+
return deserializer(obj)
798+
except: # pylint: disable=bare-except
799+
pass
770800
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
771801

772802

packages/typespec-python/test/azure/generated/authentication-oauth2/authentication/oauth2/_utils/model_base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ def default(self, o): # pylint: disable=too-many-return-statements
171171
r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
172172
)
173173

174+
_ARRAY_ENCODE_MAPPING = {
175+
"pipeDelimited": "|",
176+
"spaceDelimited": " ",
177+
"commaDelimited": ",",
178+
"newlineDelimited": "\n",
179+
}
180+
181+
182+
def _deserialize_array_encoded(delimit: str, attr):
183+
if isinstance(attr, str):
184+
if attr == "":
185+
return []
186+
return attr.split(delimit)
187+
return attr
188+
174189

175190
def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
176191
"""Deserialize ISO-8601 formatted string into Datetime object.
@@ -315,6 +330,8 @@ def _deserialize_int_as_str(attr):
315330
def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
316331
if annotation is int and rf and rf._format == "str":
317332
return _deserialize_int_as_str
333+
if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
334+
return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
318335
if rf and rf._format:
319336
return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
320337
return _DESERIALIZE_MAPPING.get(annotation) # pyright: ignore
@@ -483,6 +500,8 @@ def _is_model(obj: typing.Any) -> bool:
483500

484501
def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
485502
if isinstance(o, list):
503+
if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
504+
return _ARRAY_ENCODE_MAPPING[format].join(o)
486505
return [_serialize(x, format) for x in o]
487506
if isinstance(o, dict):
488507
return {k: _serialize(v, format) for k, v in o.items()}
@@ -767,6 +786,17 @@ def _deserialize_sequence(
767786
return obj
768787
if isinstance(obj, ET.Element):
769788
obj = list(obj)
789+
try:
790+
if (
791+
isinstance(obj, str)
792+
and isinstance(deserializer, functools.partial)
793+
and isinstance(deserializer.args[0], functools.partial)
794+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
795+
):
796+
# encoded string may be deserialized to sequence
797+
return deserializer(obj)
798+
except: # pylint: disable=bare-except
799+
pass
770800
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
771801

772802

packages/typespec-python/test/azure/generated/authentication-union/authentication/union/_utils/model_base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ def default(self, o): # pylint: disable=too-many-return-statements
171171
r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
172172
)
173173

174+
_ARRAY_ENCODE_MAPPING = {
175+
"pipeDelimited": "|",
176+
"spaceDelimited": " ",
177+
"commaDelimited": ",",
178+
"newlineDelimited": "\n",
179+
}
180+
181+
182+
def _deserialize_array_encoded(delimit: str, attr):
183+
if isinstance(attr, str):
184+
if attr == "":
185+
return []
186+
return attr.split(delimit)
187+
return attr
188+
174189

175190
def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
176191
"""Deserialize ISO-8601 formatted string into Datetime object.
@@ -315,6 +330,8 @@ def _deserialize_int_as_str(attr):
315330
def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
316331
if annotation is int and rf and rf._format == "str":
317332
return _deserialize_int_as_str
333+
if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
334+
return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
318335
if rf and rf._format:
319336
return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
320337
return _DESERIALIZE_MAPPING.get(annotation) # pyright: ignore
@@ -483,6 +500,8 @@ def _is_model(obj: typing.Any) -> bool:
483500

484501
def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
485502
if isinstance(o, list):
503+
if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
504+
return _ARRAY_ENCODE_MAPPING[format].join(o)
486505
return [_serialize(x, format) for x in o]
487506
if isinstance(o, dict):
488507
return {k: _serialize(v, format) for k, v in o.items()}
@@ -767,6 +786,17 @@ def _deserialize_sequence(
767786
return obj
768787
if isinstance(obj, ET.Element):
769788
obj = list(obj)
789+
try:
790+
if (
791+
isinstance(obj, str)
792+
and isinstance(deserializer, functools.partial)
793+
and isinstance(deserializer.args[0], functools.partial)
794+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
795+
):
796+
# encoded string may be deserialized to sequence
797+
return deserializer(obj)
798+
except: # pylint: disable=bare-except
799+
pass
770800
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
771801

772802

packages/typespec-python/test/azure/generated/azure-client-generator-core-access/specs/azure/clientgenerator/core/access/_utils/model_base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ def default(self, o): # pylint: disable=too-many-return-statements
171171
r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
172172
)
173173

174+
_ARRAY_ENCODE_MAPPING = {
175+
"pipeDelimited": "|",
176+
"spaceDelimited": " ",
177+
"commaDelimited": ",",
178+
"newlineDelimited": "\n",
179+
}
180+
181+
182+
def _deserialize_array_encoded(delimit: str, attr):
183+
if isinstance(attr, str):
184+
if attr == "":
185+
return []
186+
return attr.split(delimit)
187+
return attr
188+
174189

175190
def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
176191
"""Deserialize ISO-8601 formatted string into Datetime object.
@@ -315,6 +330,8 @@ def _deserialize_int_as_str(attr):
315330
def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
316331
if annotation is int and rf and rf._format == "str":
317332
return _deserialize_int_as_str
333+
if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
334+
return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
318335
if rf and rf._format:
319336
return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
320337
return _DESERIALIZE_MAPPING.get(annotation) # pyright: ignore
@@ -483,6 +500,8 @@ def _is_model(obj: typing.Any) -> bool:
483500

484501
def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
485502
if isinstance(o, list):
503+
if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
504+
return _ARRAY_ENCODE_MAPPING[format].join(o)
486505
return [_serialize(x, format) for x in o]
487506
if isinstance(o, dict):
488507
return {k: _serialize(v, format) for k, v in o.items()}
@@ -767,6 +786,17 @@ def _deserialize_sequence(
767786
return obj
768787
if isinstance(obj, ET.Element):
769788
obj = list(obj)
789+
try:
790+
if (
791+
isinstance(obj, str)
792+
and isinstance(deserializer, functools.partial)
793+
and isinstance(deserializer.args[0], functools.partial)
794+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
795+
):
796+
# encoded string may be deserialized to sequence
797+
return deserializer(obj)
798+
except: # pylint: disable=bare-except
799+
pass
770800
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
771801

772802

packages/typespec-python/test/azure/generated/azure-client-generator-core-alternate-type/specs/azure/clientgenerator/core/alternatetype/_utils/model_base.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,21 @@ def default(self, o): # pylint: disable=too-many-return-statements
177177
r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT"
178178
)
179179

180+
_ARRAY_ENCODE_MAPPING = {
181+
"pipeDelimited": "|",
182+
"spaceDelimited": " ",
183+
"commaDelimited": ",",
184+
"newlineDelimited": "\n",
185+
}
186+
187+
188+
def _deserialize_array_encoded(delimit: str, attr):
189+
if isinstance(attr, str):
190+
if attr == "":
191+
return []
192+
return attr.split(delimit)
193+
return attr
194+
180195

181196
def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime:
182197
"""Deserialize ISO-8601 formatted string into Datetime object.
@@ -321,6 +336,8 @@ def _deserialize_int_as_str(attr):
321336
def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None):
322337
if annotation is int and rf and rf._format == "str":
323338
return _deserialize_int_as_str
339+
if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING:
340+
return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format])
324341
if rf and rf._format:
325342
return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format)
326343
if _DESERIALIZE_MAPPING.get(annotation): # pyright: ignore
@@ -491,6 +508,8 @@ def _is_model(obj: typing.Any) -> bool:
491508

492509
def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements
493510
if isinstance(o, list):
511+
if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o):
512+
return _ARRAY_ENCODE_MAPPING[format].join(o)
494513
return [_serialize(x, format) for x in o]
495514
if isinstance(o, dict):
496515
return {k: _serialize(v, format) for k, v in o.items()}
@@ -781,6 +800,17 @@ def _deserialize_sequence(
781800
return obj
782801
if isinstance(obj, ET.Element):
783802
obj = list(obj)
803+
try:
804+
if (
805+
isinstance(obj, str)
806+
and isinstance(deserializer, functools.partial)
807+
and isinstance(deserializer.args[0], functools.partial)
808+
and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable
809+
):
810+
# encoded string may be deserialized to sequence
811+
return deserializer(obj)
812+
except: # pylint: disable=bare-except
813+
pass
784814
return type(obj)(_deserialize(deserializer, entry, module) for entry in obj)
785815

786816

0 commit comments

Comments
 (0)