@autorest/python 6.7.7 → 6.8.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.
@@ -13,7 +13,7 @@ from .. import Plugin, PluginAutorest
13
13
  from .._utils import parse_args
14
14
  from .models.code_model import CodeModel
15
15
  from .serializers import JinjaSerializer, JinjaSerializerAutorest
16
- from ._utils import DEFAULT_HEADER_TEXT
16
+ from ._utils import DEFAULT_HEADER_TEXT, VALID_PACKAGE_MODE, TYPESPEC_PACKAGE_MODE
17
17
 
18
18
 
19
19
  def _default_pprint(package_name: str) -> str:
@@ -55,11 +55,17 @@ def _validate_code_model_options(options: Dict[str, Any]) -> None:
55
55
 
56
56
  if options["package_mode"]:
57
57
  if (
58
- options["package_mode"] not in ("mgmtplane", "dataplane")
59
- and not Path(options["package_mode"]).exists()
60
- ):
58
+ (
59
+ options["package_mode"] not in TYPESPEC_PACKAGE_MODE
60
+ and options["from_typespec"]
61
+ )
62
+ or (
63
+ options["package_mode"] not in VALID_PACKAGE_MODE
64
+ and not options["from_typespec"]
65
+ )
66
+ ) and not Path(options["package_mode"]).exists():
61
67
  raise ValueError(
62
- "--package-mode can only be 'mgmtplane' or 'dataplane' or directory which contains template files"
68
+ f"--package-mode can only be {' or '.join(TYPESPEC_PACKAGE_MODE)} or directory which contains template files" # pylint: disable=line-too-long
63
69
  )
64
70
 
65
71
  if options["multiapi"] and options["version_tolerant"]:
@@ -170,6 +176,7 @@ class CodeGenerator(Plugin):
170
176
  ),
171
177
  "generate_sample": self.options.get("generate-sample", False),
172
178
  "default_api_version": self.options.get("default-api-version"),
179
+ "from_typespec": self.options.get("from-typespec", False),
173
180
  }
174
181
 
175
182
  if options["builders_visibility"] is None:
@@ -10,3 +10,7 @@ DEFAULT_HEADER_TEXT = (
10
10
  "Code generated by Microsoft (R) Python Code Generator.\n"
11
11
  "Changes may cause incorrect behavior and will be lost if the code is regenerated."
12
12
  )
13
+
14
+ SWAGGER_PACKAGE_MODE = ["mgmtplane", "dataplane"] # for backward compatibility
15
+ TYPESPEC_PACKAGE_MODE = ["azure-mgmt", "azure-dataplane", "generic"]
16
+ VALID_PACKAGE_MODE = SWAGGER_PACKAGE_MODE + TYPESPEC_PACKAGE_MODE
@@ -31,8 +31,8 @@ class DictionaryType(BaseType):
31
31
  self.element_type = element_type
32
32
 
33
33
  @property
34
- def format(self) -> Optional[str]:
35
- return self.element_type.format if hasattr(self.element_type, "format") else None # type: ignore
34
+ def encode(self) -> Optional[str]:
35
+ return self.element_type.encode if hasattr(self.element_type, "encode") else None # type: ignore
36
36
 
37
37
  @property
38
38
  def serialization_type(self) -> str:
@@ -26,8 +26,8 @@ class ListType(BaseType):
26
26
  self.unique_items: bool = yaml_data.get("uniqueItems", False)
27
27
 
28
28
  @property
29
- def format(self) -> Optional[str]:
30
- return self.element_type.format if hasattr(self.element_type, "format") else None # type: ignore
29
+ def encode(self) -> Optional[str]:
30
+ return self.element_type.encode if hasattr(self.element_type, "encode") else None # type: ignore
31
31
 
32
32
  @property
33
33
  def serialization_type(self) -> str:
@@ -92,6 +92,10 @@ class _ParameterBase(
92
92
  )
93
93
  self.hide_in_method: bool = self.yaml_data.get("hideInMethod", False)
94
94
 
95
+ @property
96
+ def hide_in_operation_signature(self) -> bool:
97
+ return False
98
+
95
99
  @property
96
100
  def constant(self) -> bool:
97
101
  """Returns whether a parameter is a constant or not.
@@ -341,6 +345,15 @@ class Parameter(_ParameterBase):
341
345
  self.delimiter: Optional[ParameterDelimeter] = self.yaml_data.get("delimiter")
342
346
  self._default_to_unset_sentinel: bool = False
343
347
 
348
+ @property
349
+ def hide_in_operation_signature(self) -> bool:
350
+ if (
351
+ self.code_model.options["version_tolerant"]
352
+ and self.client_name == "maxpagesize"
353
+ ):
354
+ return True
355
+ return False
356
+
344
357
  @property
345
358
  def in_method_signature(self) -> bool:
346
359
  return not (self.wire_name == "Accept" or self.grouped_by or self.flattened)
@@ -248,11 +248,12 @@ class _ParameterListBase(
248
248
 
249
249
  def method_signature_keyword_only(self, async_mode: bool) -> List[str]:
250
250
  """Signature for keyword only parameters"""
251
- if not self.keyword_only:
252
- return []
253
- return ["*,"] + [
254
- parameter.method_signature(async_mode) for parameter in self.keyword_only
251
+ result = [
252
+ parameter.method_signature(async_mode)
253
+ for parameter in self.keyword_only
254
+ if not parameter.hide_in_operation_signature
255
255
  ]
256
+ return ["*,"] + result if result else []
256
257
 
257
258
  @property
258
259
  def method_signature_kwargs(self) -> List[str]:
@@ -409,16 +410,6 @@ class RequestBuilderParameterList(_RequestBuilderParameterList):
409
410
  class OverloadedRequestBuilderParameterList(_RequestBuilderParameterList):
410
411
  """Parameter list for OverloadedRequestBuilder"""
411
412
 
412
- def method_signature_keyword_only(self, async_mode: bool) -> List[str]:
413
- """Signature for keyword only parameters"""
414
- if not self.keyword_only:
415
- return []
416
- return ["*,"] + [
417
- parameter.method_signature(async_mode)
418
- for parameter in self.keyword_only
419
- if parameter.location != ParameterLocation.BODY
420
- ]
421
-
422
413
 
423
414
  class _ClientGlobalParameterList( # pylint: disable=abstract-method
424
415
  _ParameterListBase[ParameterType, BodyParameter]
@@ -355,10 +355,10 @@ class StringType(PrimitiveType):
355
355
  class DatetimeType(PrimitiveType):
356
356
  def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
357
357
  super().__init__(yaml_data=yaml_data, code_model=code_model)
358
- self.format = (
358
+ self.encode = (
359
359
  "rfc3339"
360
- if yaml_data.get("format", "date-time") == "date-time"
361
- or yaml_data.get("format", "date-time") == "rfc3339"
360
+ if yaml_data.get("encode", "date-time") == "date-time"
361
+ or yaml_data.get("encode", "date-time") == "rfc3339"
362
362
  else "rfc7231"
363
363
  )
364
364
 
@@ -368,7 +368,7 @@ class DatetimeType(PrimitiveType):
368
368
  "rfc3339": "iso-8601",
369
369
  "rfc7231": "rfc-1123",
370
370
  }
371
- return formats_to_attribute_type[self.format]
371
+ return formats_to_attribute_type[self.encode]
372
372
 
373
373
  def docstring_type(self, **kwargs: Any) -> str:
374
374
  return "~" + self.type_annotation()
@@ -455,7 +455,7 @@ class TimeType(PrimitiveType):
455
455
 
456
456
  class UnixTimeType(PrimitiveType):
457
457
  @property
458
- def format(self) -> str:
458
+ def encode(self) -> str:
459
459
  return "unix-timestamp"
460
460
 
461
461
  @property
@@ -592,11 +592,11 @@ class DurationType(PrimitiveType):
592
592
  class ByteArraySchema(PrimitiveType):
593
593
  def __init__(self, yaml_data: Dict[str, Any], code_model: "CodeModel") -> None:
594
594
  super().__init__(yaml_data=yaml_data, code_model=code_model)
595
- self.format = yaml_data.get("format", "base64")
595
+ self.encode = yaml_data.get("encode", "base64")
596
596
 
597
597
  @property
598
598
  def serialization_type(self) -> str:
599
- if self.format == "base64url":
599
+ if self.encode == "base64url":
600
600
  return "base64"
601
601
  return "bytearray"
602
602
 
@@ -110,6 +110,10 @@ class RequestBuilderParameter(Parameter):
110
110
  # we don't want hidden parameters for grouped by in request builders
111
111
  self.client_name = self.client_name[1:]
112
112
 
113
+ @property
114
+ def hide_in_operation_signature(self) -> bool:
115
+ return False
116
+
113
117
  @property
114
118
  def in_method_signature(self) -> bool:
115
119
  if self.grouped_by and not self.in_flattened_body:
@@ -29,6 +29,7 @@ from .patch_serializer import PatchSerializer
29
29
  from .sample_serializer import SampleSerializer
30
30
  from .types_serializer import TypesSerializer
31
31
  from ..._utils import to_snake_case
32
+ from .._utils import VALID_PACKAGE_MODE
32
33
  from .utils import (
33
34
  extract_sample_name,
34
35
  get_namespace_from_package_name,
@@ -216,7 +217,7 @@ class JinjaSerializer(ReaderAndWriter): # pylint: disable=abstract-method
216
217
 
217
218
  def _serialize_and_write_package_files(self, namespace_path: Path) -> None:
218
219
  root_of_sdk = self._package_root_folder(namespace_path)
219
- if self.code_model.options["package_mode"] in ("dataplane", "mgmtplane"):
220
+ if self.code_model.options["package_mode"] in VALID_PACKAGE_MODE:
220
221
  env = Environment(
221
222
  loader=PackageLoader(
222
223
  "autorest.codegen", "templates/packaging_templates"
@@ -32,6 +32,7 @@ from ..models import (
32
32
  RequestBuilderType,
33
33
  CombinedType,
34
34
  ParameterListType,
35
+ ByteArraySchema,
35
36
  )
36
37
  from .parameter_serializer import ParameterSerializer, PopKwargType
37
38
  from ..models.parameter_list import ParameterType
@@ -332,7 +333,7 @@ class _BuilderBaseSerializer(Generic[BuilderType]): # pylint: disable=abstract-
332
333
  def param_description(self, builder: BuilderType) -> List[str]:
333
334
  description_list: List[str] = []
334
335
  for param in builder.parameters.method:
335
- if not param.in_docstring:
336
+ if not param.in_docstring or param.hide_in_operation_signature:
336
337
  continue
337
338
  description_list.extend(
338
339
  f":{param.description_keyword} {param.client_name}: {param.description}".replace(
@@ -700,6 +701,9 @@ class _OperationSerializer(
700
701
  check_client_input=not self.code_model.options["multiapi"],
701
702
  operation_name=f"('{builder.name}')" if builder.group_name == "" else "",
702
703
  )
704
+ for p in builder.parameters.parameters:
705
+ if p.hide_in_operation_signature:
706
+ kwargs.append(f'{p.client_name} = kwargs.pop("{p.client_name}", None)')
703
707
  cls_annotation = builder.cls_type_annotation(async_mode=self.async_mode)
704
708
  pylint_disable = ""
705
709
  if any(x.startswith("_") for x in cls_annotation.split(".")):
@@ -749,10 +753,17 @@ class _OperationSerializer(
749
753
  f"'{body_param.type.serialization_type}'{is_xml_cmd}{serialization_ctxt_cmd})"
750
754
  )
751
755
  elif self.code_model.options["models_mode"] == "dpg":
752
- create_body_call = (
753
- f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
754
- "cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore"
755
- )
756
+ if hasattr(body_param.type, "encode") and body_param.type.encode: # type: ignore
757
+ create_body_call = (
758
+ f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
759
+ "cls=AzureJSONEncoder, exclude_readonly=True, "
760
+ f"format='{body_param.type.encode}') # type: ignore" # type: ignore
761
+ )
762
+ else:
763
+ create_body_call = (
764
+ f"_{body_kwarg_name} = json.dumps({body_param.client_name}, "
765
+ "cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore"
766
+ )
756
767
  else:
757
768
  create_body_call = f"_{body_kwarg_name} = {body_param.client_name}"
758
769
  if body_param.optional:
@@ -774,7 +785,11 @@ class _OperationSerializer(
774
785
  if hasattr(body_param, "entries"):
775
786
  return _serialize_multipart_body(builder)
776
787
  body_kwarg_name = builder.request_builder.parameters.body_parameter.client_name
777
- if isinstance(body_param.type, BinaryType):
788
+ body_param_type = body_param.type
789
+ if isinstance(body_param_type, BinaryType) or (
790
+ isinstance(body_param.type, ByteArraySchema)
791
+ and body_param.default_content_type != "application/json"
792
+ ):
778
793
  retval.append(f"_{body_kwarg_name} = {body_param.client_name}")
779
794
  if (
780
795
  not body_param.default_content_type
@@ -260,8 +260,8 @@ class DpgModelSerializer(_ModelSerializer):
260
260
  args.append(f"visibility=[{v_list}]")
261
261
  if prop.client_default_value is not None:
262
262
  args.append(f"default={prop.client_default_value_declaration}")
263
- if hasattr(prop.type, "format") and prop.type.format: # type: ignore
264
- args.append(f'format="{prop.type.format}"') # type: ignore
263
+ if hasattr(prop.type, "encode") and prop.type.encode: # type: ignore
264
+ args.append(f'format="{prop.type.encode}"') # type: ignore
265
265
 
266
266
  field = "rest_discriminator" if prop.is_discriminator else "rest_field"
267
267
  type_ignore = (
@@ -128,9 +128,10 @@ def _is_readonly(p):
128
128
  class AzureJSONEncoder(JSONEncoder):
129
129
  """A JSON encoder that's capable of serializing datetime objects and bytes."""
130
130
 
131
- def __init__(self, *args, exclude_readonly: bool = False, **kwargs):
131
+ def __init__(self, *args, exclude_readonly: bool = False, format: typing.Optional[str] = None, **kwargs):
132
132
  super().__init__(*args, **kwargs)
133
133
  self.exclude_readonly = exclude_readonly
134
+ self.format = format
134
135
 
135
136
  def default(self, o): # pylint: disable=too-many-return-statements
136
137
  if _is_model(o):
@@ -138,18 +139,16 @@ class AzureJSONEncoder(JSONEncoder):
138
139
  readonly_props = [p._rest_name for p in o._attr_to_rest_field.values() if _is_readonly(p)]
139
140
  return {k: v for k, v in o.items() if k not in readonly_props}
140
141
  return dict(o.items())
141
- if isinstance(o, (bytes, bytearray)):
142
- return base64.b64encode(o).decode()
143
- if isinstance(o, _Null):
144
- return None
145
142
  try:
146
143
  return super(AzureJSONEncoder, self).default(o)
147
144
  except TypeError:
145
+ if isinstance(o, _Null):
146
+ return None
148
147
  if isinstance(o, (bytes, bytearray)):
149
- return _serialize_bytes(o)
148
+ return _serialize_bytes(o, self.format)
150
149
  try:
151
150
  # First try datetime.datetime
152
- return _serialize_datetime(o)
151
+ return _serialize_datetime(o, self.format)
153
152
  except AttributeError:
154
153
  pass
155
154
  # Last, try datetime.timedelta
@@ -232,11 +232,11 @@ def update_primitive( # pylint: disable=too-many-return-statements
232
232
  return KNOWN_TYPES["binary"]
233
233
  if type_group == "date-time":
234
234
  base = _update_type_base("datetime", yaml_data)
235
- base["format"] = yaml_data["format"]
235
+ base["encode"] = yaml_data["format"]
236
236
  return base
237
237
  if type_group == "byte-array":
238
238
  base = _update_type_base("bytes", yaml_data)
239
- base["format"] = yaml_data["format"]
239
+ base["encode"] = yaml_data["format"]
240
240
  return base
241
241
  return _update_type_base(type_group, yaml_data)
242
242
 
@@ -137,16 +137,6 @@ def add_overloads_for_body_param(yaml_data: Dict[str, Any]) -> None:
137
137
  content_type_param["optional"] = True
138
138
 
139
139
 
140
- def _remove_paging_maxpagesize(yaml_data: Dict[str, Any]) -> None:
141
- # we don't expose maxpagesize for version tolerant generation
142
- # users should be passing this into `by_page`
143
- yaml_data["parameters"] = [
144
- p
145
- for p in yaml_data.get("parameters", [])
146
- if p["wireName"].lower() not in ["maxpagesize", "$maxpagesize"]
147
- ]
148
-
149
-
150
140
  def update_description(
151
141
  description: Optional[str], default_description: str = ""
152
142
  ) -> str:
@@ -494,13 +484,8 @@ class PreProcessPlugin(YamlUpdatePlugin): # pylint: disable=abstract-method
494
484
  yaml_data["pagerSync"] = "azure.core.paging.ItemPaged"
495
485
  if not yaml_data.get("pagerAsync"):
496
486
  yaml_data["pagerAsync"] = "azure.core.async_paging.AsyncItemPaged"
497
- if self.version_tolerant:
498
- # if we're in version tolerant, hide the paging model
499
- _remove_paging_maxpagesize(yaml_data)
500
487
  item_type = item_type or yaml_data["itemType"]["elementType"]
501
488
  if yaml_data.get("nextOperation"):
502
- if self.version_tolerant:
503
- _remove_paging_maxpagesize(yaml_data["nextOperation"])
504
489
  yaml_data["nextOperation"]["groupName"] = self.pad_reserved_words(
505
490
  yaml_data["nextOperation"]["groupName"], PadType.OPERATION_GROUP
506
491
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.7.7",
3
+ "version": "6.8.0",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {