@autorest/python 6.28.0 → 6.28.2
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.
- package/autorest/codegen.py +2 -2
- package/autorest/jsonrpc/__init__.py +2 -2
- package/autorest/m4reformatter/__init__.py +13 -13
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +1 -1
- package/generator/build/lib/pygen/codegen/models/code_model.py +5 -1
- package/generator/build/lib/pygen/codegen/models/combined_type.py +4 -3
- package/generator/build/lib/pygen/codegen/models/credential_types.py +4 -0
- package/generator/build/lib/pygen/codegen/models/operation.py +9 -3
- package/generator/build/lib/pygen/codegen/models/operation_group.py +26 -1
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +1 -1
- package/generator/build/lib/pygen/codegen/models/property.py +2 -2
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +22 -7
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +14 -3
- package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +2 -1
- package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +1 -0
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +61 -0
- package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +4 -4
- package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +2 -0
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +39 -107
- package/generator/build/lib/pygen/preprocess/__init__.py +1 -1
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/models/code_model.py +5 -1
- package/generator/pygen/codegen/models/combined_type.py +4 -3
- package/generator/pygen/codegen/models/credential_types.py +4 -0
- package/generator/pygen/codegen/models/operation.py +9 -3
- package/generator/pygen/codegen/models/operation_group.py +26 -1
- package/generator/pygen/codegen/models/paging_operation.py +1 -1
- package/generator/pygen/codegen/models/property.py +2 -2
- package/generator/pygen/codegen/serializers/__init__.py +22 -7
- package/generator/pygen/codegen/serializers/builder_serializer.py +14 -3
- package/generator/pygen/codegen/serializers/model_serializer.py +2 -1
- package/generator/pygen/codegen/serializers/operation_groups_serializer.py +1 -0
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +61 -0
- package/generator/pygen/codegen/templates/operation_group.py.jinja2 +4 -4
- package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +2 -0
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +39 -107
- package/generator/pygen/preprocess/__init__.py +1 -1
- package/package.json +2 -2
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
- package/scripts/eng/mypy.ini +1 -1
- package/scripts/mypy.ini +1 -1
- package/scripts/prepare.py +2 -2
- package/scripts/start.py +2 -2
- package/scripts/venvtools.py +2 -2
|
@@ -47,9 +47,7 @@ from typing import (
|
|
|
47
47
|
IO,
|
|
48
48
|
Mapping,
|
|
49
49
|
Callable,
|
|
50
|
-
TypeVar,
|
|
51
50
|
MutableMapping,
|
|
52
|
-
Type,
|
|
53
51
|
List,
|
|
54
52
|
)
|
|
55
53
|
|
|
@@ -60,13 +58,13 @@ except ImportError:
|
|
|
60
58
|
import xml.etree.ElementTree as ET
|
|
61
59
|
|
|
62
60
|
import isodate # type: ignore
|
|
61
|
+
from typing_extensions import Self
|
|
63
62
|
|
|
64
63
|
from {{ code_model.core_library }}.exceptions import DeserializationError, SerializationError
|
|
65
64
|
from {{ code_model.core_library }}.serialization import NULL as CoreNull
|
|
66
65
|
|
|
67
66
|
_BOM = codecs.BOM_UTF8.decode(encoding="utf-8")
|
|
68
67
|
|
|
69
|
-
ModelType = TypeVar("ModelType", bound="Model")
|
|
70
68
|
JSON = MutableMapping[str, Any]
|
|
71
69
|
|
|
72
70
|
|
|
@@ -184,73 +182,7 @@ try:
|
|
|
184
182
|
except NameError:
|
|
185
183
|
_long_type = int
|
|
186
184
|
|
|
187
|
-
|
|
188
|
-
class UTC(datetime.tzinfo):
|
|
189
|
-
"""Time Zone info for handling UTC"""
|
|
190
|
-
|
|
191
|
-
def utcoffset(self, dt):
|
|
192
|
-
"""UTF offset for UTC is 0.
|
|
193
|
-
|
|
194
|
-
:param datetime.datetime dt: The datetime
|
|
195
|
-
:returns: The offset
|
|
196
|
-
:rtype: datetime.timedelta
|
|
197
|
-
"""
|
|
198
|
-
return datetime.timedelta(0)
|
|
199
|
-
|
|
200
|
-
def tzname(self, dt):
|
|
201
|
-
"""Timestamp representation.
|
|
202
|
-
|
|
203
|
-
:param datetime.datetime dt: The datetime
|
|
204
|
-
:returns: The timestamp representation
|
|
205
|
-
:rtype: str
|
|
206
|
-
"""
|
|
207
|
-
return "Z"
|
|
208
|
-
|
|
209
|
-
def dst(self, dt):
|
|
210
|
-
"""No daylight saving for UTC.
|
|
211
|
-
|
|
212
|
-
:param datetime.datetime dt: The datetime
|
|
213
|
-
:returns: The daylight saving time
|
|
214
|
-
:rtype: datetime.timedelta
|
|
215
|
-
"""
|
|
216
|
-
return datetime.timedelta(hours=1)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
try:
|
|
220
|
-
from datetime import timezone as _FixedOffset # type: ignore
|
|
221
|
-
except ImportError: # Python 2.7
|
|
222
|
-
|
|
223
|
-
class _FixedOffset(datetime.tzinfo): # type: ignore
|
|
224
|
-
"""Fixed offset in minutes east from UTC.
|
|
225
|
-
Copy/pasted from Python doc
|
|
226
|
-
:param datetime.timedelta offset: offset in timedelta format
|
|
227
|
-
"""
|
|
228
|
-
|
|
229
|
-
def __init__(self, offset) -> None:
|
|
230
|
-
self.__offset = offset
|
|
231
|
-
|
|
232
|
-
def utcoffset(self, dt):
|
|
233
|
-
return self.__offset
|
|
234
|
-
|
|
235
|
-
def tzname(self, dt):
|
|
236
|
-
return str(self.__offset.total_seconds() / 3600)
|
|
237
|
-
|
|
238
|
-
def __repr__(self):
|
|
239
|
-
return "<FixedOffset {}>".format(self.tzname(None))
|
|
240
|
-
|
|
241
|
-
def dst(self, dt):
|
|
242
|
-
return datetime.timedelta(0)
|
|
243
|
-
|
|
244
|
-
def __getinitargs__(self):
|
|
245
|
-
return (self.__offset,)
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
try:
|
|
249
|
-
from datetime import timezone
|
|
250
|
-
|
|
251
|
-
TZ_UTC = timezone.utc
|
|
252
|
-
except ImportError:
|
|
253
|
-
TZ_UTC = UTC() # type: ignore
|
|
185
|
+
TZ_UTC = datetime.timezone.utc
|
|
254
186
|
|
|
255
187
|
_FLATTEN = re.compile(r"(?<!\\)\.")
|
|
256
188
|
|
|
@@ -449,25 +381,25 @@ class Model:
|
|
|
449
381
|
return client_models
|
|
450
382
|
|
|
451
383
|
@classmethod
|
|
452
|
-
def deserialize(cls
|
|
384
|
+
def deserialize(cls, data: Any, content_type: Optional[str] = None) -> Self:
|
|
453
385
|
"""Parse a str using the RestAPI syntax and return a model.
|
|
454
386
|
|
|
455
387
|
:param str data: A str using RestAPI structure. JSON by default.
|
|
456
388
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
457
389
|
:returns: An instance of this model
|
|
458
|
-
:raises
|
|
459
|
-
:rtype:
|
|
390
|
+
:raises DeserializationError: if something went wrong
|
|
391
|
+
:rtype: Self
|
|
460
392
|
"""
|
|
461
393
|
deserializer = Deserializer(cls._infer_class_models())
|
|
462
394
|
return deserializer(cls.__name__, data, content_type=content_type) # type: ignore
|
|
463
395
|
|
|
464
396
|
@classmethod
|
|
465
397
|
def from_dict(
|
|
466
|
-
cls
|
|
398
|
+
cls,
|
|
467
399
|
data: Any,
|
|
468
400
|
key_extractors: Optional[Callable[[str, Dict[str, Any], Any], Any]] = None,
|
|
469
401
|
content_type: Optional[str] = None,
|
|
470
|
-
) ->
|
|
402
|
+
) -> Self:
|
|
471
403
|
"""Parse a dict using given key extractor return a model.
|
|
472
404
|
|
|
473
405
|
By default consider key
|
|
@@ -479,7 +411,7 @@ class Model:
|
|
|
479
411
|
:param str content_type: JSON by default, set application/xml if XML.
|
|
480
412
|
:returns: An instance of this model
|
|
481
413
|
:raises: DeserializationError if something went wrong
|
|
482
|
-
:rtype:
|
|
414
|
+
:rtype: Self
|
|
483
415
|
"""
|
|
484
416
|
deserializer = Deserializer(cls._infer_class_models())
|
|
485
417
|
deserializer.key_extractors = ( # type: ignore
|
|
@@ -625,7 +557,7 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
625
557
|
:param object target_obj: The data to be serialized.
|
|
626
558
|
:param str data_type: The type to be serialized from.
|
|
627
559
|
:rtype: str, dict
|
|
628
|
-
:raises
|
|
560
|
+
:raises SerializationError: if serialization fails.
|
|
629
561
|
:returns: The serialized data.
|
|
630
562
|
"""
|
|
631
563
|
key_transformer = kwargs.get("key_transformer", self.key_transformer)
|
|
@@ -735,8 +667,8 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
735
667
|
:param object data: The data to be serialized.
|
|
736
668
|
:param str data_type: The type to be serialized from.
|
|
737
669
|
:rtype: dict
|
|
738
|
-
:raises
|
|
739
|
-
:raises
|
|
670
|
+
:raises SerializationError: if serialization fails.
|
|
671
|
+
:raises ValueError: if data is None
|
|
740
672
|
:returns: The serialized request body
|
|
741
673
|
"""
|
|
742
674
|
|
|
@@ -780,8 +712,8 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
780
712
|
:param str data_type: The type to be serialized from.
|
|
781
713
|
:rtype: str
|
|
782
714
|
:returns: The serialized URL path
|
|
783
|
-
:raises
|
|
784
|
-
:raises
|
|
715
|
+
:raises TypeError: if serialization fails.
|
|
716
|
+
:raises ValueError: if data is None
|
|
785
717
|
"""
|
|
786
718
|
try:
|
|
787
719
|
output = self.serialize_data(data, data_type, **kwargs)
|
|
@@ -804,8 +736,8 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
804
736
|
:param object data: The data to be serialized.
|
|
805
737
|
:param str data_type: The type to be serialized from.
|
|
806
738
|
:rtype: str, list
|
|
807
|
-
:raises
|
|
808
|
-
:raises
|
|
739
|
+
:raises TypeError: if serialization fails.
|
|
740
|
+
:raises ValueError: if data is None
|
|
809
741
|
:returns: The serialized query parameter
|
|
810
742
|
"""
|
|
811
743
|
try:
|
|
@@ -834,8 +766,8 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
834
766
|
:param object data: The data to be serialized.
|
|
835
767
|
:param str data_type: The type to be serialized from.
|
|
836
768
|
:rtype: str
|
|
837
|
-
:raises
|
|
838
|
-
:raises
|
|
769
|
+
:raises TypeError: if serialization fails.
|
|
770
|
+
:raises ValueError: if data is None
|
|
839
771
|
:returns: The serialized header
|
|
840
772
|
"""
|
|
841
773
|
try:
|
|
@@ -854,9 +786,9 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
854
786
|
|
|
855
787
|
:param object data: The data to be serialized.
|
|
856
788
|
:param str data_type: The type to be serialized from.
|
|
857
|
-
:raises
|
|
858
|
-
:raises
|
|
859
|
-
:raises
|
|
789
|
+
:raises AttributeError: if required data is None.
|
|
790
|
+
:raises ValueError: if data is None
|
|
791
|
+
:raises SerializationError: if serialization fails.
|
|
860
792
|
:returns: The serialized data.
|
|
861
793
|
:rtype: str, int, float, bool, dict, list
|
|
862
794
|
"""
|
|
@@ -1191,7 +1123,7 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
1191
1123
|
|
|
1192
1124
|
:param Datetime attr: Object to be serialized.
|
|
1193
1125
|
:rtype: str
|
|
1194
|
-
:raises
|
|
1126
|
+
:raises TypeError: if format invalid.
|
|
1195
1127
|
:return: serialized rfc
|
|
1196
1128
|
"""
|
|
1197
1129
|
try:
|
|
@@ -1217,7 +1149,7 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
1217
1149
|
|
|
1218
1150
|
:param Datetime attr: Object to be serialized.
|
|
1219
1151
|
:rtype: str
|
|
1220
|
-
:raises
|
|
1152
|
+
:raises SerializationError: if format invalid.
|
|
1221
1153
|
:return: serialized iso
|
|
1222
1154
|
"""
|
|
1223
1155
|
if isinstance(attr, str):
|
|
@@ -1250,7 +1182,7 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
1250
1182
|
|
|
1251
1183
|
:param Datetime attr: Object to be serialized.
|
|
1252
1184
|
:rtype: int
|
|
1253
|
-
:raises
|
|
1185
|
+
:raises SerializationError: if format invalid
|
|
1254
1186
|
:return: serialied unix
|
|
1255
1187
|
"""
|
|
1256
1188
|
if isinstance(attr, int):
|
|
@@ -1487,7 +1419,7 @@ class Deserializer:
|
|
|
1487
1419
|
:param str target_obj: Target data type to deserialize to.
|
|
1488
1420
|
:param requests.Response response_data: REST response object.
|
|
1489
1421
|
:param str content_type: Swagger "produces" if available.
|
|
1490
|
-
:raises
|
|
1422
|
+
:raises DeserializationError: if deserialization fails.
|
|
1491
1423
|
:return: Deserialized object.
|
|
1492
1424
|
:rtype: object
|
|
1493
1425
|
"""
|
|
@@ -1501,7 +1433,7 @@ class Deserializer:
|
|
|
1501
1433
|
|
|
1502
1434
|
:param str target_obj: Target data type to deserialize to.
|
|
1503
1435
|
:param object data: Object to deserialize.
|
|
1504
|
-
:raises
|
|
1436
|
+
:raises DeserializationError: if deserialization fails.
|
|
1505
1437
|
:return: Deserialized object.
|
|
1506
1438
|
:rtype: object
|
|
1507
1439
|
"""
|
|
@@ -1716,7 +1648,7 @@ class Deserializer:
|
|
|
1716
1648
|
|
|
1717
1649
|
:param str data: The response string to be deserialized.
|
|
1718
1650
|
:param str data_type: The type to deserialize to.
|
|
1719
|
-
:raises
|
|
1651
|
+
:raises DeserializationError: if deserialization fails.
|
|
1720
1652
|
:return: Deserialized object.
|
|
1721
1653
|
:rtype: object
|
|
1722
1654
|
"""
|
|
@@ -1798,7 +1730,7 @@ class Deserializer:
|
|
|
1798
1730
|
:param dict attr: Dictionary to be deserialized.
|
|
1799
1731
|
:return: Deserialized object.
|
|
1800
1732
|
:rtype: dict
|
|
1801
|
-
:raises
|
|
1733
|
+
:raises TypeError: if non-builtin datatype encountered.
|
|
1802
1734
|
"""
|
|
1803
1735
|
if attr is None:
|
|
1804
1736
|
return None
|
|
@@ -1844,7 +1776,7 @@ class Deserializer:
|
|
|
1844
1776
|
:param str data_type: deserialization data type.
|
|
1845
1777
|
:return: Deserialized basic type.
|
|
1846
1778
|
:rtype: str, int, float or bool
|
|
1847
|
-
:raises
|
|
1779
|
+
:raises TypeError: if string format is not valid.
|
|
1848
1780
|
"""
|
|
1849
1781
|
# If we're here, data is supposed to be a basic type.
|
|
1850
1782
|
# If it's still an XML node, take the text
|
|
@@ -1935,7 +1867,7 @@ class Deserializer:
|
|
|
1935
1867
|
:param str attr: response string to be deserialized.
|
|
1936
1868
|
:return: Deserialized bytearray
|
|
1937
1869
|
:rtype: bytearray
|
|
1938
|
-
:raises
|
|
1870
|
+
:raises TypeError: if string format invalid.
|
|
1939
1871
|
"""
|
|
1940
1872
|
if isinstance(attr, ET.Element):
|
|
1941
1873
|
attr = attr.text
|
|
@@ -1948,7 +1880,7 @@ class Deserializer:
|
|
|
1948
1880
|
:param str attr: response string to be deserialized.
|
|
1949
1881
|
:return: Deserialized base64 string
|
|
1950
1882
|
:rtype: bytearray
|
|
1951
|
-
:raises
|
|
1883
|
+
:raises TypeError: if string format invalid.
|
|
1952
1884
|
"""
|
|
1953
1885
|
if isinstance(attr, ET.Element):
|
|
1954
1886
|
attr = attr.text
|
|
@@ -1963,7 +1895,7 @@ class Deserializer:
|
|
|
1963
1895
|
|
|
1964
1896
|
:param str attr: response string to be deserialized.
|
|
1965
1897
|
:return: Deserialized decimal
|
|
1966
|
-
:raises
|
|
1898
|
+
:raises DeserializationError: if string format invalid.
|
|
1967
1899
|
:rtype: decimal
|
|
1968
1900
|
"""
|
|
1969
1901
|
if isinstance(attr, ET.Element):
|
|
@@ -1981,7 +1913,7 @@ class Deserializer:
|
|
|
1981
1913
|
:param str attr: response string to be deserialized.
|
|
1982
1914
|
:return: Deserialized int
|
|
1983
1915
|
:rtype: long or int
|
|
1984
|
-
:raises
|
|
1916
|
+
:raises ValueError: if string format invalid.
|
|
1985
1917
|
"""
|
|
1986
1918
|
if isinstance(attr, ET.Element):
|
|
1987
1919
|
attr = attr.text
|
|
@@ -1994,7 +1926,7 @@ class Deserializer:
|
|
|
1994
1926
|
:param str attr: response string to be deserialized.
|
|
1995
1927
|
:return: Deserialized duration
|
|
1996
1928
|
:rtype: TimeDelta
|
|
1997
|
-
:raises
|
|
1929
|
+
:raises DeserializationError: if string format invalid.
|
|
1998
1930
|
"""
|
|
1999
1931
|
if isinstance(attr, ET.Element):
|
|
2000
1932
|
attr = attr.text
|
|
@@ -2012,7 +1944,7 @@ class Deserializer:
|
|
|
2012
1944
|
:param str attr: response string to be deserialized.
|
|
2013
1945
|
:return: Deserialized date
|
|
2014
1946
|
:rtype: Date
|
|
2015
|
-
:raises
|
|
1947
|
+
:raises DeserializationError: if string format invalid.
|
|
2016
1948
|
"""
|
|
2017
1949
|
if isinstance(attr, ET.Element):
|
|
2018
1950
|
attr = attr.text
|
|
@@ -2028,7 +1960,7 @@ class Deserializer:
|
|
|
2028
1960
|
:param str attr: response string to be deserialized.
|
|
2029
1961
|
:return: Deserialized time
|
|
2030
1962
|
:rtype: datetime.time
|
|
2031
|
-
:raises
|
|
1963
|
+
:raises DeserializationError: if string format invalid.
|
|
2032
1964
|
"""
|
|
2033
1965
|
if isinstance(attr, ET.Element):
|
|
2034
1966
|
attr = attr.text
|
|
@@ -2043,14 +1975,14 @@ class Deserializer:
|
|
|
2043
1975
|
:param str attr: response string to be deserialized.
|
|
2044
1976
|
:return: Deserialized RFC datetime
|
|
2045
1977
|
:rtype: Datetime
|
|
2046
|
-
:raises
|
|
1978
|
+
:raises DeserializationError: if string format invalid.
|
|
2047
1979
|
"""
|
|
2048
1980
|
if isinstance(attr, ET.Element):
|
|
2049
1981
|
attr = attr.text
|
|
2050
1982
|
try:
|
|
2051
1983
|
parsed_date = email.utils.parsedate_tz(attr) # type: ignore
|
|
2052
1984
|
date_obj = datetime.datetime(
|
|
2053
|
-
*parsed_date[:6], tzinfo=
|
|
1985
|
+
*parsed_date[:6], tzinfo=datetime.timezone(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60))
|
|
2054
1986
|
)
|
|
2055
1987
|
if not date_obj.tzinfo:
|
|
2056
1988
|
date_obj = date_obj.astimezone(tz=TZ_UTC)
|
|
@@ -2066,7 +1998,7 @@ class Deserializer:
|
|
|
2066
1998
|
:param str attr: response string to be deserialized.
|
|
2067
1999
|
:return: Deserialized ISO datetime
|
|
2068
2000
|
:rtype: Datetime
|
|
2069
|
-
:raises
|
|
2001
|
+
:raises DeserializationError: if string format invalid.
|
|
2070
2002
|
"""
|
|
2071
2003
|
if isinstance(attr, ET.Element):
|
|
2072
2004
|
attr = attr.text
|
|
@@ -2104,7 +2036,7 @@ class Deserializer:
|
|
|
2104
2036
|
:param int attr: Object to be serialized.
|
|
2105
2037
|
:return: Deserialized datetime
|
|
2106
2038
|
:rtype: Datetime
|
|
2107
|
-
:raises
|
|
2039
|
+
:raises DeserializationError: if format invalid
|
|
2108
2040
|
"""
|
|
2109
2041
|
if isinstance(attr, ET.Element):
|
|
2110
2042
|
attr = int(attr.text) # type: ignore
|
|
@@ -92,9 +92,9 @@ def add_overloads_for_body_param(yaml_data: Dict[str, Any]) -> None:
|
|
|
92
92
|
for body_type in body_parameter["type"]["types"]:
|
|
93
93
|
if any(o for o in yaml_data["overloads"] if id(o["bodyParameter"]["type"]) == id(body_type)):
|
|
94
94
|
continue
|
|
95
|
-
yaml_data["overloads"].append(add_overload(yaml_data, body_type))
|
|
96
95
|
if body_type.get("type") == "model" and body_type.get("base") == "json":
|
|
97
96
|
yaml_data["overloads"].append(add_overload(yaml_data, body_type, for_flatten_params=True))
|
|
97
|
+
yaml_data["overloads"].append(add_overload(yaml_data, body_type))
|
|
98
98
|
content_type_param = next(p for p in yaml_data["parameters"] if p["wireName"].lower() == "content-type")
|
|
99
99
|
content_type_param["inOverload"] = False
|
|
100
100
|
content_type_param["inOverridden"] = True
|
|
Binary file
|
|
@@ -313,7 +313,7 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
313
313
|
:param int schema_id: The yaml id of the schema
|
|
314
314
|
:return: If created, we return the created schema, otherwise, we throw.
|
|
315
315
|
:rtype: ~autorest.models.BaseType
|
|
316
|
-
:raises
|
|
316
|
+
:raises KeyError: if schema is not found
|
|
317
317
|
"""
|
|
318
318
|
try:
|
|
319
319
|
return next(type for id, type in self.types_map.items() if id == schema_id)
|
|
@@ -402,3 +402,7 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
402
402
|
@property
|
|
403
403
|
def is_legacy(self) -> bool:
|
|
404
404
|
return _is_legacy(self.options)
|
|
405
|
+
|
|
406
|
+
@staticmethod
|
|
407
|
+
def has_non_json_models(models: List[ModelType]) -> bool:
|
|
408
|
+
return any(m for m in models if m.base != "json")
|
|
@@ -53,9 +53,10 @@ class CombinedType(BaseType):
|
|
|
53
53
|
return self.yaml_data.get("clientDefaultValue")
|
|
54
54
|
|
|
55
55
|
def description(self, *, is_operation_file: bool) -> str:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
type_descriptions = list({t.type_description: None for t in self.types}.keys())
|
|
57
|
+
if len(type_descriptions) == 2:
|
|
58
|
+
return f"Is either a {type_descriptions[0]} type or a {type_descriptions[1]} type."
|
|
59
|
+
return f"Is one of the following types: {', '.join(t for t in type_descriptions)}"
|
|
59
60
|
|
|
60
61
|
def docstring_text(self, **kwargs: Any) -> str:
|
|
61
62
|
return " or ".join(t.docstring_text(**kwargs) for t in self.types)
|
|
@@ -198,6 +198,10 @@ class KeyCredentialType(CredentialType[KeyCredentialPolicyType]):
|
|
|
198
198
|
def type_annotation(self, **kwargs: Any) -> str:
|
|
199
199
|
return self.policy.credential_name
|
|
200
200
|
|
|
201
|
+
@property
|
|
202
|
+
def type_description(self) -> str:
|
|
203
|
+
return "key credential"
|
|
204
|
+
|
|
201
205
|
@property
|
|
202
206
|
def instance_check_template(self) -> str:
|
|
203
207
|
return "isinstance({}, " + f"{self.policy.credential_name})"
|
|
@@ -35,6 +35,7 @@ from .parameter import (
|
|
|
35
35
|
)
|
|
36
36
|
from .parameter_list import ParameterList
|
|
37
37
|
from .model_type import ModelType
|
|
38
|
+
from .primitive_types import BinaryIteratorType, BinaryType
|
|
38
39
|
from .base import BaseType
|
|
39
40
|
from .combined_type import CombinedType
|
|
40
41
|
from .request_builder import OverloadedRequestBuilder, RequestBuilder
|
|
@@ -313,6 +314,10 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
313
314
|
)
|
|
314
315
|
return file_import
|
|
315
316
|
|
|
317
|
+
@property
|
|
318
|
+
def need_deserialize(self) -> bool:
|
|
319
|
+
return any(r.type and not isinstance(r.type, BinaryIteratorType) for r in self.responses)
|
|
320
|
+
|
|
316
321
|
def imports( # pylint: disable=too-many-branches, disable=too-many-statements
|
|
317
322
|
self, async_mode: bool, **kwargs: Any
|
|
318
323
|
) -> FileImport:
|
|
@@ -432,7 +437,8 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
432
437
|
file_import.add_submodule_import("typing", "overload", ImportType.STDLIB)
|
|
433
438
|
if self.code_model.options["models_mode"] == "dpg":
|
|
434
439
|
relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
|
|
435
|
-
if self.parameters.has_body
|
|
440
|
+
body_param = self.parameters.body_parameter if self.parameters.has_body else None
|
|
441
|
+
if body_param and not isinstance(body_param.type, BinaryType):
|
|
436
442
|
if self.has_form_data_body:
|
|
437
443
|
file_import.add_submodule_import(
|
|
438
444
|
self.code_model.get_relative_import_path(serialize_namespace), "_model_base", ImportType.LOCAL
|
|
@@ -450,9 +456,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
450
456
|
ImportType.LOCAL,
|
|
451
457
|
)
|
|
452
458
|
file_import.add_import("json", ImportType.STDLIB)
|
|
453
|
-
if any(xml_serializable(str(r.default_content_type)) for r in self.responses):
|
|
459
|
+
if any(xml_serializable(str(r.default_content_type)) for r in self.responses + self.exceptions):
|
|
454
460
|
file_import.add_submodule_import(relative_path, "_deserialize_xml", ImportType.LOCAL)
|
|
455
|
-
elif
|
|
461
|
+
elif self.need_deserialize:
|
|
456
462
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
457
463
|
if self.default_error_deserialization or self.non_default_errors:
|
|
458
464
|
file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL)
|
|
@@ -9,7 +9,7 @@ from .utils import OrderedSet
|
|
|
9
9
|
|
|
10
10
|
from .base import BaseModel
|
|
11
11
|
from .operation import get_operation
|
|
12
|
-
from .imports import FileImport, ImportType, TypingSection
|
|
12
|
+
from .imports import FileImport, ImportType, TypingSection, MsrestImportType
|
|
13
13
|
from .utils import add_to_pylint_disable, NamespaceType
|
|
14
14
|
from .lro_operation import LROOperation
|
|
15
15
|
from .lro_paging_operation import LROPagingOperation
|
|
@@ -152,6 +152,31 @@ class OperationGroup(BaseModel):
|
|
|
152
152
|
f"{self.client.name}MixinABC",
|
|
153
153
|
ImportType.LOCAL,
|
|
154
154
|
)
|
|
155
|
+
else:
|
|
156
|
+
file_import.add_submodule_import(
|
|
157
|
+
"" if self.code_model.is_azure_flavor else "runtime",
|
|
158
|
+
f"{'Async' if async_mode else ''}PipelineClient",
|
|
159
|
+
ImportType.SDKCORE,
|
|
160
|
+
)
|
|
161
|
+
file_import.add_submodule_import(
|
|
162
|
+
self.code_model.get_relative_import_path(
|
|
163
|
+
serialize_namespace,
|
|
164
|
+
self.code_model.get_imported_namespace_for_client(self.client.client_namespace, async_mode),
|
|
165
|
+
module_name="_configuration",
|
|
166
|
+
),
|
|
167
|
+
f"{self.client.name}Configuration",
|
|
168
|
+
ImportType.LOCAL,
|
|
169
|
+
)
|
|
170
|
+
file_import.add_msrest_import(
|
|
171
|
+
serialize_namespace=kwargs.get("serialize_namespace", self.code_model.namespace),
|
|
172
|
+
msrest_import_type=MsrestImportType.Serializer,
|
|
173
|
+
typing_section=TypingSection.REGULAR,
|
|
174
|
+
)
|
|
175
|
+
file_import.add_msrest_import(
|
|
176
|
+
serialize_namespace=kwargs.get("serialize_namespace", self.code_model.namespace),
|
|
177
|
+
msrest_import_type=MsrestImportType.SerializerDeserializer,
|
|
178
|
+
typing_section=TypingSection.REGULAR,
|
|
179
|
+
)
|
|
155
180
|
if self.has_abstract_operations:
|
|
156
181
|
file_import.add_submodule_import(
|
|
157
182
|
# raise_if_not_implemented is always defined in _vendor of top namespace
|
|
@@ -150,7 +150,7 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
150
150
|
if self.code_model.options["models_mode"] == "dpg":
|
|
151
151
|
relative_path = self.code_model.get_relative_import_path(serialize_namespace, module_name="_model_base")
|
|
152
152
|
file_import.merge(self.item_type.imports(**kwargs))
|
|
153
|
-
if self.default_error_deserialization or
|
|
153
|
+
if self.default_error_deserialization or self.need_deserialize:
|
|
154
154
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
155
155
|
return file_import
|
|
156
156
|
|
|
@@ -102,7 +102,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
102
102
|
if self.is_base_discriminator:
|
|
103
103
|
return "str"
|
|
104
104
|
types_type_annotation = self.type.type_annotation(is_operation_file=is_operation_file, **kwargs)
|
|
105
|
-
if self.optional and self.client_default_value is None:
|
|
105
|
+
if (self.optional and self.client_default_value is None) or self.readonly:
|
|
106
106
|
return f"Optional[{types_type_annotation}]"
|
|
107
107
|
return types_type_annotation
|
|
108
108
|
|
|
@@ -144,7 +144,7 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
|
|
|
144
144
|
if self.is_discriminator and isinstance(self.type, EnumType):
|
|
145
145
|
return file_import
|
|
146
146
|
file_import.merge(self.type.imports(**kwargs))
|
|
147
|
-
if self.optional and self.client_default_value is None:
|
|
147
|
+
if (self.optional and self.client_default_value is None) or self.readonly:
|
|
148
148
|
file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
|
|
149
149
|
if self.code_model.options["models_mode"] == "dpg":
|
|
150
150
|
serialize_namespace = kwargs.get("serialize_namespace", self.code_model.namespace)
|
|
@@ -130,10 +130,10 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
130
130
|
if self.code_model.options["package_mode"]:
|
|
131
131
|
self._serialize_and_write_package_files(client_namespace)
|
|
132
132
|
|
|
133
|
-
# write
|
|
133
|
+
# write apiview-properties.json
|
|
134
134
|
if self.code_model.options.get("emit_cross_language_definition_file"):
|
|
135
135
|
self.write_file(
|
|
136
|
-
exec_path / Path("
|
|
136
|
+
exec_path / Path("apiview-properties.json"),
|
|
137
137
|
general_serializer.serialize_cross_language_definition_file(),
|
|
138
138
|
)
|
|
139
139
|
|
|
@@ -159,7 +159,9 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
159
159
|
self._serialize_and_write_top_level_folder(env=env, namespace=client_namespace)
|
|
160
160
|
|
|
161
161
|
# add models folder if there are models in this namespace
|
|
162
|
-
if (
|
|
162
|
+
if (
|
|
163
|
+
self.code_model.has_non_json_models(client_namespace_type.models) or client_namespace_type.enums
|
|
164
|
+
) and self.code_model.options["models_mode"]:
|
|
163
165
|
self._serialize_and_write_models_folder(
|
|
164
166
|
env=env,
|
|
165
167
|
namespace=client_namespace,
|
|
@@ -181,6 +183,14 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
181
183
|
if self.code_model.options["multiapi"]:
|
|
182
184
|
self._serialize_and_write_metadata(env=env, namespace=client_namespace)
|
|
183
185
|
|
|
186
|
+
# if there are only operations under this namespace, we need to add general __init__.py into `aio` folder
|
|
187
|
+
# to make sure all generated files could be packed into .zip/.whl/.tgz package
|
|
188
|
+
if not client_namespace_type.clients and client_namespace_type.operation_groups and self.has_aio_folder:
|
|
189
|
+
self.write_file(
|
|
190
|
+
exec_path / Path("aio/__init__.py"),
|
|
191
|
+
general_serializer.serialize_pkgutil_init_file(),
|
|
192
|
+
)
|
|
193
|
+
|
|
184
194
|
def _serialize_and_write_package_files(self, client_namespace: str) -> None:
|
|
185
195
|
root_of_sdk = self.exec_path(client_namespace)
|
|
186
196
|
if self.code_model.options["package_mode"] in VALID_PACKAGE_MODE:
|
|
@@ -228,9 +238,9 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
228
238
|
self, env: Environment, namespace: str, models: List[ModelType], enums: List[EnumType]
|
|
229
239
|
) -> None:
|
|
230
240
|
# Write the models folder
|
|
231
|
-
models_path = self.exec_path(namespace
|
|
241
|
+
models_path = self.exec_path(namespace) / "models"
|
|
232
242
|
serializer = DpgModelSerializer if self.code_model.options["models_mode"] == "dpg" else MsrestModelSerializer
|
|
233
|
-
if models:
|
|
243
|
+
if self.code_model.has_non_json_models(models):
|
|
234
244
|
self.write_file(
|
|
235
245
|
models_path / Path(f"{self.code_model.models_filename}.py"),
|
|
236
246
|
serializer(code_model=self.code_model, env=env, client_namespace=namespace, models=models).serialize(),
|
|
@@ -469,7 +479,12 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
469
479
|
else Path(".")
|
|
470
480
|
)
|
|
471
481
|
|
|
482
|
+
def exec_path_for_test_sample(self, namespace: str) -> Path:
|
|
483
|
+
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
484
|
+
|
|
472
485
|
def exec_path(self, namespace: str) -> Path:
|
|
486
|
+
if self.code_model.options["no_namespace_folders"] and not self.code_model.options["multiapi"]:
|
|
487
|
+
return Path(".")
|
|
473
488
|
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
474
489
|
|
|
475
490
|
@property
|
|
@@ -482,7 +497,7 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
482
497
|
return Path("")
|
|
483
498
|
|
|
484
499
|
def _serialize_and_write_sample(self, env: Environment, namespace: str):
|
|
485
|
-
out_path = self.
|
|
500
|
+
out_path = self.exec_path_for_test_sample(namespace) / Path("generated_samples")
|
|
486
501
|
for client in self.code_model.clients:
|
|
487
502
|
for op_group in client.operation_groups:
|
|
488
503
|
for operation in op_group.operations:
|
|
@@ -516,7 +531,7 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
516
531
|
|
|
517
532
|
def _serialize_and_write_test(self, env: Environment, namespace: str):
|
|
518
533
|
self.code_model.for_test = True
|
|
519
|
-
out_path = self.
|
|
534
|
+
out_path = self.exec_path_for_test_sample(namespace) / Path("generated_tests")
|
|
520
535
|
general_serializer = TestGeneralSerializer(code_model=self.code_model, env=env)
|
|
521
536
|
self.write_file(out_path / "conftest.py", general_serializer.serialize_conftest())
|
|
522
537
|
if not self.code_model.options["azure_arm"]:
|
|
@@ -498,7 +498,11 @@ class RequestBuilderSerializer(_BuilderBaseSerializer[RequestBuilderType]):
|
|
|
498
498
|
url_value = _escape_str(builder.url)
|
|
499
499
|
else:
|
|
500
500
|
url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
|
|
501
|
-
|
|
501
|
+
result = "_url = " + url_value
|
|
502
|
+
# there will be always 4 spaces before the url
|
|
503
|
+
if len(result) + 4 > 120:
|
|
504
|
+
return result + " # pylint: disable=line-too-long"
|
|
505
|
+
return result
|
|
502
506
|
|
|
503
507
|
|
|
504
508
|
############################## NORMAL OPERATIONS ##############################
|
|
@@ -1001,7 +1005,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1001
1005
|
retval.extend(deserialize_code)
|
|
1002
1006
|
return retval
|
|
1003
1007
|
|
|
1004
|
-
def handle_error_response(self, builder: OperationType) -> List[str]:
|
|
1008
|
+
def handle_error_response(self, builder: OperationType) -> List[str]: # pylint: disable=too-many-statements, too-many-branches
|
|
1005
1009
|
async_await = "await " if self.async_mode else ""
|
|
1006
1010
|
retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
|
|
1007
1011
|
response_read = [
|
|
@@ -1075,7 +1079,14 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1075
1079
|
is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
|
|
1076
1080
|
)
|
|
1077
1081
|
if self.code_model.options["models_mode"] == "dpg":
|
|
1078
|
-
|
|
1082
|
+
if xml_serializable(str(e.default_content_type)):
|
|
1083
|
+
retval.append(
|
|
1084
|
+
f" error = _failsafe_deserialize_xml({type_annotation}, response.text())"
|
|
1085
|
+
)
|
|
1086
|
+
else:
|
|
1087
|
+
retval.append(
|
|
1088
|
+
f" error = _failsafe_deserialize({type_annotation}, response.json())"
|
|
1089
|
+
)
|
|
1079
1090
|
else:
|
|
1080
1091
|
retval.append(
|
|
1081
1092
|
f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
|