@autorest/python 6.6.0 → 6.7.1

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 (26) hide show
  1. package/autorest/codegen/models/__init__.py +2 -0
  2. package/autorest/codegen/models/client.py +4 -7
  3. package/autorest/codegen/models/code_model.py +7 -9
  4. package/autorest/codegen/models/dictionary_type.py +4 -0
  5. package/autorest/codegen/models/list_type.py +4 -0
  6. package/autorest/codegen/models/lro_operation.py +12 -0
  7. package/autorest/codegen/models/model_type.py +4 -1
  8. package/autorest/codegen/models/operation.py +35 -9
  9. package/autorest/codegen/models/parameter.py +1 -7
  10. package/autorest/codegen/models/parameter_list.py +1 -1
  11. package/autorest/codegen/models/primitive_types.py +37 -9
  12. package/autorest/codegen/models/property.py +1 -0
  13. package/autorest/codegen/models/request_builder.py +0 -4
  14. package/autorest/codegen/serializers/__init__.py +1 -0
  15. package/autorest/codegen/serializers/builder_serializer.py +31 -42
  16. package/autorest/codegen/serializers/client_serializer.py +8 -2
  17. package/autorest/codegen/serializers/general_serializer.py +7 -4
  18. package/autorest/codegen/serializers/model_serializer.py +13 -2
  19. package/autorest/codegen/serializers/parameter_serializer.py +59 -4
  20. package/autorest/codegen/templates/model_base.py.jinja2 +246 -172
  21. package/autorest/codegen/templates/packaging_templates/setup.py.jinja2 +1 -1
  22. package/autorest/codegen/templates/request_builder.py.jinja2 +1 -1
  23. package/autorest/codegen/templates/serialization.py.jinja2 +22 -8
  24. package/autorest/codegen/templates/vendor.py.jinja2 +29 -15
  25. package/autorest/preprocess/__init__.py +63 -0
  26. package/package.json +2 -2
@@ -664,8 +664,9 @@ class Serializer(object):
664
664
  _serialized.update(_new_attr) # type: ignore
665
665
  _new_attr = _new_attr[k] # type: ignore
666
666
  _serialized = _serialized[k]
667
- except ValueError:
668
- continue
667
+ except ValueError as err:
668
+ if isinstance(err, SerializationError):
669
+ raise
669
670
 
670
671
  except (AttributeError, KeyError, TypeError) as err:
671
672
  msg = "Attribute {} in object {} cannot be serialized.\n{}".format(attr_name, class_name, str(target_obj))
@@ -743,6 +744,8 @@ class Serializer(object):
743
744
 
744
745
  :param data: The data to be serialized.
745
746
  :param str data_type: The type to be serialized from.
747
+ :keyword bool skip_quote: Whether to skip quote the serialized result.
748
+ Defaults to False.
746
749
  :rtype: str
747
750
  :raises: TypeError if serialization fails.
748
751
  :raises: ValueError if data is None
@@ -751,10 +754,8 @@ class Serializer(object):
751
754
  # Treat the list aside, since we don't want to encode the div separator
752
755
  if data_type.startswith("["):
753
756
  internal_data_type = data_type[1:-1]
754
- data = [self.serialize_data(d, internal_data_type, **kwargs) if d is not None else "" for d in data]
755
- if not kwargs.get("skip_quote", False):
756
- data = [quote(str(d), safe="") for d in data]
757
- return str(self.serialize_iter(data, internal_data_type, **kwargs))
757
+ do_quote = not kwargs.get('skip_quote', False)
758
+ return str(self.serialize_iter(data, internal_data_type, do_quote=do_quote, **kwargs))
758
759
 
759
760
  # Not a list, regular serialization
760
761
  output = self.serialize_data(data, data_type, **kwargs)
@@ -893,6 +894,8 @@ class Serializer(object):
893
894
  not be None or empty.
894
895
  :param str div: If set, this str will be used to combine the elements
895
896
  in the iterable into a combined string. Default is 'None'.
897
+ :keyword bool do_quote: Whether to quote the serialized result of each iterable element.
898
+ Defaults to False.
896
899
  :rtype: list, str
897
900
  """
898
901
  if isinstance(data, str):
@@ -905,9 +908,18 @@ class Serializer(object):
905
908
  for d in data:
906
909
  try:
907
910
  serialized.append(self.serialize_data(d, iter_type, **kwargs))
908
- except ValueError:
911
+ except ValueError as err:
912
+ if isinstance(err, SerializationError):
913
+ raise
909
914
  serialized.append(None)
910
915
 
916
+ if kwargs.get('do_quote', False):
917
+ serialized = [
918
+ '' if s is None else quote(str(s), safe='')
919
+ for s
920
+ in serialized
921
+ ]
922
+
911
923
  if div:
912
924
  serialized = ["" if s is None else str(s) for s in serialized]
913
925
  serialized = div.join(serialized)
@@ -952,7 +964,9 @@ class Serializer(object):
952
964
  for key, value in attr.items():
953
965
  try:
954
966
  serialized[self.serialize_unicode(key)] = self.serialize_data(value, dict_type, **kwargs)
955
- except ValueError:
967
+ except ValueError as err:
968
+ if isinstance(err, SerializationError):
969
+ raise
956
970
  serialized[self.serialize_unicode(key)] = None
957
971
 
958
972
  if "xml" in serialization_ctxt:
@@ -11,21 +11,6 @@ def _convert_request(request, files=None):
11
11
  request.set_formdata_body(files)
12
12
  return request
13
13
  {% endif %}
14
- {% if code_model.need_format_url and not async_mode %}
15
-
16
- def _format_url_section(template, **kwargs):
17
- components = template.split("/")
18
- while components:
19
- try:
20
- return template.format(**kwargs)
21
- except KeyError as key:
22
- # Need the cast, as for some reasons "split" is typed as list[str | Any]
23
- formatted_components = cast(List[str], template.split("/"))
24
- components = [
25
- c for c in formatted_components if "{{{}}}".format(key.args[0]) not in c
26
- ]
27
- template = "/".join(components)
28
- {% endif %}
29
14
  {% if code_model.need_mixin_abc %}
30
15
  {% for client in clients | selectattr("has_mixin") %}
31
16
 
@@ -47,3 +32,32 @@ def raise_if_not_implemented(cls, abstract_methods):
47
32
  cls.__name__, '\', \''.join(not_implemented))
48
33
  )
49
34
  {% endif %}
35
+
36
+ {% if code_model.has_etag %}
37
+ def quote_etag(etag: Optional[str]) -> Optional[str]:
38
+ if not etag or etag == "*":
39
+ return etag
40
+ if etag.startswith('"') and etag.endswith('"'):
41
+ return etag
42
+ if etag.startswith("'") and etag.endswith("'"):
43
+ return etag
44
+ return '"' + etag + '"'
45
+
46
+
47
+ def prep_if_match(etag: Optional[str], match_condition: Optional[MatchConditions]) -> Optional[str]:
48
+ if match_condition == MatchConditions.IfNotModified:
49
+ if_match = quote_etag(etag) if etag else None
50
+ return if_match
51
+ if match_condition == MatchConditions.IfPresent:
52
+ return "*"
53
+ return None
54
+
55
+
56
+ def prep_if_none_match(etag: Optional[str], match_condition: Optional[MatchConditions]) -> Optional[str]:
57
+ if match_condition == MatchConditions.IfModified:
58
+ if_none_match = quote_etag(etag) if etag else None
59
+ return if_none_match
60
+ if match_condition == MatchConditions.IfMissing:
61
+ return "*"
62
+ return None
63
+ {% endif %}
@@ -176,6 +176,37 @@ def update_paging_response(yaml_data: Dict[str, Any]) -> None:
176
176
  )
177
177
 
178
178
 
179
+ HEADERS_HIDE_IN_METHOD = (
180
+ "repeatability-request-id",
181
+ "repeatability-first-sent",
182
+ "x-ms-client-request-id",
183
+ "client-request-id",
184
+ "return-client-request-id",
185
+ )
186
+ HEADERS_CONVERT_IN_METHOD = {
187
+ "if-match": {
188
+ "clientName": "etag",
189
+ "wireName": "etag",
190
+ "description": "check if resource is changed. Set None to skip checking etag.",
191
+ },
192
+ "if-none-match": {
193
+ "clientName": "match_condition",
194
+ "wireName": "match-condition",
195
+ "description": "The match condition to use upon the etag.",
196
+ "type": {
197
+ "type": "azurecore",
198
+ "name": "MatchConditions",
199
+ },
200
+ },
201
+ }
202
+
203
+
204
+ def headers_convert(yaml_data: Dict[str, Any], replace_data: Any) -> None:
205
+ if isinstance(replace_data, dict):
206
+ for k, v in replace_data.items():
207
+ yaml_data[k] = v
208
+
209
+
179
210
  class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
180
211
  """Add Python naming information."""
181
212
 
@@ -242,6 +273,11 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
242
273
  )
243
274
  type["values"].extend(values_to_add)
244
275
 
276
+ # add type for reference
277
+ for v in HEADERS_CONVERT_IN_METHOD.values():
278
+ if isinstance(v, dict) and "type" in v:
279
+ yaml_data.append(v["type"])
280
+
245
281
  def update_client(self, yaml_data: Dict[str, Any]) -> None:
246
282
  yaml_data["description"] = update_description(
247
283
  yaml_data["description"], default_description=yaml_data["name"]
@@ -253,6 +289,21 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
253
289
  if prop_name.endswith("Client"):
254
290
  prop_name = prop_name[: len(prop_name) - len("Client")]
255
291
  yaml_data["builderPadName"] = to_snake_case(prop_name)
292
+ for og in yaml_data["operationGroups"]:
293
+ for o in og["operations"]:
294
+ for p in o["parameters"]:
295
+ if (
296
+ p["location"] == "header"
297
+ and p["wireName"] == "client-request-id"
298
+ ):
299
+ yaml_data["requestIdHeaderName"] = p["wireName"]
300
+ if (
301
+ self.version_tolerant
302
+ and p["location"] == "header"
303
+ and p["clientName"] in ("if_match", "if_none_match")
304
+ ):
305
+ o["hasEtag"] = True
306
+ yaml_data["hasEtag"] = True
256
307
 
257
308
  def get_operation_updater(
258
309
  self, yaml_data: Dict[str, Any]
@@ -282,6 +333,18 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
282
333
  .lower()
283
334
  for prop, param_name in yaml_data["propertyToParameterName"].items()
284
335
  }
336
+ wire_name_lower = (yaml_data.get("wireName") or "").lower()
337
+ if (
338
+ yaml_data["location"] == "header"
339
+ and wire_name_lower in HEADERS_HIDE_IN_METHOD
340
+ ):
341
+ yaml_data["hideInMethod"] = True
342
+ if (
343
+ self.version_tolerant
344
+ and yaml_data["location"] == "header"
345
+ and wire_name_lower in HEADERS_CONVERT_IN_METHOD
346
+ ):
347
+ headers_convert(yaml_data, HEADERS_CONVERT_IN_METHOD[wire_name_lower])
285
348
 
286
349
  def update_operation(
287
350
  self,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.6.0",
3
+ "version": "6.7.1",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@microsoft.azure/autorest.testserver": "^3.3.46",
26
- "typescript": "^5.0.4"
26
+ "typescript": "~5.1.3"
27
27
  },
28
28
  "files": [
29
29
  "autorest/**/*.py",