@autorest/python 6.22.0 → 6.24.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 (41) hide show
  1. package/generator/dev_requirements.txt +10 -2
  2. package/generator/pygen/black.py +2 -0
  3. package/generator/pygen/codegen/_utils.py +1 -0
  4. package/generator/pygen/codegen/models/base_builder.py +1 -2
  5. package/generator/pygen/codegen/models/client.py +11 -6
  6. package/generator/pygen/codegen/models/imports.py +2 -2
  7. package/generator/pygen/codegen/models/lro_operation.py +1 -1
  8. package/generator/pygen/codegen/models/model_type.py +2 -5
  9. package/generator/pygen/codegen/models/operation.py +13 -13
  10. package/generator/pygen/codegen/models/operation_group.py +2 -2
  11. package/generator/pygen/codegen/models/parameter.py +9 -9
  12. package/generator/pygen/codegen/models/property.py +0 -1
  13. package/generator/pygen/codegen/models/request_builder.py +3 -3
  14. package/generator/pygen/codegen/models/request_builder_parameter.py +1 -1
  15. package/generator/pygen/codegen/models/response.py +3 -3
  16. package/generator/pygen/codegen/models/utils.py +0 -2
  17. package/generator/pygen/codegen/serializers/builder_serializer.py +37 -43
  18. package/generator/pygen/codegen/serializers/client_serializer.py +1 -2
  19. package/generator/pygen/codegen/serializers/import_serializer.py +2 -3
  20. package/generator/pygen/codegen/serializers/model_serializer.py +21 -4
  21. package/generator/pygen/codegen/serializers/parameter_serializer.py +3 -3
  22. package/generator/pygen/codegen/serializers/test_serializer.py +0 -1
  23. package/generator/pygen/codegen/templates/client.py.jinja2 +1 -1
  24. package/generator/pygen/codegen/templates/config.py.jinja2 +1 -1
  25. package/generator/pygen/codegen/templates/conftest.py.jinja2 +1 -1
  26. package/generator/pygen/codegen/templates/macros.jinja2 +2 -2
  27. package/generator/pygen/codegen/templates/model_base.py.jinja2 +2 -3
  28. package/generator/pygen/codegen/templates/model_container.py.jinja2 +0 -1
  29. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +2 -3
  30. package/generator/pygen/codegen/templates/operation_group.py.jinja2 +7 -7
  31. package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +0 -1
  32. package/generator/pygen/codegen/templates/serialization.py.jinja2 +0 -1
  33. package/generator/pygen/codegen/templates/types.py.jinja2 +0 -1
  34. package/generator/pygen/preprocess/__init__.py +9 -3
  35. package/generator/pygen/preprocess/python_mappings.py +1 -1
  36. package/generator/pygen/utils.py +3 -0
  37. package/package.json +4 -4
  38. package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
  39. package/scripts/copy-generator.ts +7 -7
  40. package/scripts/eng/lint.ts +1 -1
  41. package/scripts/eng/pylintrc +2 -1
@@ -1,5 +1,13 @@
1
1
  -e ./generator
2
- -r ../../../eng/requirements.txt
3
- -r ../../../eng/dev_requirements.txt
2
+ pyright==1.1.375
3
+ pylint==3.2.6
4
+ tox==4.16.0
5
+ mypy==1.10.1
6
+ azure-pylint-guidelines-checker==0.0.8
7
+ colorama==0.4.6
8
+ debugpy==1.8.2
9
+ pytest==8.3.2
10
+ coverage==7.6.1
11
+ black==24.8.0
4
12
  ptvsd==4.3.2
5
13
  types-PyYAML==6.0.12.8
@@ -60,6 +60,8 @@ class BlackScriptPlugin(Plugin):
60
60
  _LOGGER.error("Error: failed to format %s", file)
61
61
  raise
62
62
  else:
63
+ if len(file_content.splitlines()) > 1000:
64
+ file_content = "# pylint: disable=too-many-lines\n" + file_content
63
65
  self.write_file(file, file_content)
64
66
 
65
67
 
@@ -14,3 +14,4 @@ DEFAULT_HEADER_TEXT = (
14
14
  SWAGGER_PACKAGE_MODE = ["mgmtplane", "dataplane"] # for backward compatibility
15
15
  TYPESPEC_PACKAGE_MODE = ["azure-mgmt", "azure-dataplane", "generic"]
16
16
  VALID_PACKAGE_MODE = SWAGGER_PACKAGE_MODE + TYPESPEC_PACKAGE_MODE
17
+ NAME_LENGTH_LIMIT = 40
@@ -91,8 +91,7 @@ class BaseBuilder(
91
91
  return None
92
92
  return self._summary
93
93
 
94
- @property
95
- def pylint_disable(self) -> str:
94
+ def pylint_disable(self, async_mode: bool) -> str: # pylint: disable=unused-argument
96
95
  return ""
97
96
 
98
97
  @abstractmethod
@@ -8,7 +8,7 @@ from typing import Any, Dict, TYPE_CHECKING, TypeVar, Generic, Union, List, Opti
8
8
  from .base import BaseModel
9
9
  from .parameter_list import ClientGlobalParameterList, ConfigGlobalParameterList
10
10
  from .imports import FileImport, ImportType, TypingSection, MsrestImportType
11
- from .utils import add_to_pylint_disable, NAME_LENGTH_LIMIT
11
+ from .utils import add_to_pylint_disable
12
12
  from .operation_group import OperationGroup
13
13
  from .request_builder import (
14
14
  RequestBuilder,
@@ -18,7 +18,7 @@ from .request_builder import (
18
18
  from .parameter import Parameter, ParameterMethodLocation
19
19
  from .lro_operation import LROOperation
20
20
  from .lro_paging_operation import LROPagingOperation
21
- from ...utils import extract_original_name
21
+ from ...utils import extract_original_name, NAME_LENGTH_LIMIT
22
22
 
23
23
  ParameterListType = TypeVar(
24
24
  "ParameterListType",
@@ -145,9 +145,15 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
145
145
  """Whether the base url is parameterized or not"""
146
146
  return not any(p for p in self.parameters if p.is_host)
147
147
 
148
- @property
149
148
  def pylint_disable(self) -> str:
150
- retval = add_to_pylint_disable("", "client-accepts-api-version-keyword")
149
+ retval = ""
150
+ if not any(
151
+ p
152
+ for p in self.parameters.parameters
153
+ if p.is_api_version
154
+ and p.method_location in [ParameterMethodLocation.KEYWORD_ONLY, ParameterMethodLocation.KWARG]
155
+ ):
156
+ retval = add_to_pylint_disable(retval, "client-accepts-api-version-keyword")
151
157
  if len(self.operation_groups) > 6:
152
158
  retval = add_to_pylint_disable(retval, "too-many-instance-attributes")
153
159
  if len(self.name) > NAME_LENGTH_LIMIT:
@@ -347,10 +353,9 @@ class Client(_ClientConfigBase[ClientGlobalParameterList]):
347
353
  class Config(_ClientConfigBase[ConfigGlobalParameterList]):
348
354
  """Model representing our Config type."""
349
355
 
350
- @property
351
356
  def pylint_disable(self) -> str:
352
357
  retval = add_to_pylint_disable("", "too-many-instance-attributes")
353
- if len(self.name) + len("Configuration") > NAME_LENGTH_LIMIT:
358
+ if len(self.name) > NAME_LENGTH_LIMIT:
354
359
  retval = add_to_pylint_disable(retval, "name-too-long")
355
360
  return retval
356
361
 
@@ -19,7 +19,7 @@ class ImportType(str, Enum):
19
19
  THIRDPARTY = "thirdparty"
20
20
  SDKCORE = "sdkcore"
21
21
  LOCAL = "local"
22
- BYVERSION = "by_version"
22
+ BY_VERSION = "by_version"
23
23
 
24
24
 
25
25
  class TypingSection(str, Enum):
@@ -171,7 +171,7 @@ class FileImport:
171
171
  self.add_submodule_import(
172
172
  "typing",
173
173
  "MutableMapping",
174
- ImportType.BYVERSION,
174
+ ImportType.BY_VERSION,
175
175
  TypingSection.REGULAR,
176
176
  None,
177
177
  (((3, 9), "collections.abc", None),),
@@ -93,7 +93,7 @@ class LROOperationBase(OperationBase[LROResponseType]):
93
93
  return "None"
94
94
 
95
95
  def cls_type_annotation(self, *, async_mode: bool) -> str:
96
- """We don't want the poller to show up in ClsType, so we call super() on resposne type annotation"""
96
+ """We don't want the poller to show up in ClsType, so we call super() on response type annotation"""
97
97
  return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]"
98
98
 
99
99
  def get_poller_with_response_type(self, async_mode: bool) -> str:
@@ -7,14 +7,12 @@ from enum import Enum
7
7
  from collections import OrderedDict
8
8
  from typing import Any, Dict, List, Optional, TYPE_CHECKING, cast
9
9
  import sys
10
- from .utils import (
11
- add_to_pylint_disable,
12
- NAME_LENGTH_LIMIT,
13
- )
10
+ from .utils import add_to_pylint_disable
14
11
  from .base import BaseType
15
12
  from .constant_type import ConstantType
16
13
  from .property import Property
17
14
  from .imports import FileImport, ImportType, TypingSection
15
+ from ...utils import NAME_LENGTH_LIMIT
18
16
 
19
17
  if sys.version_info >= (3, 8):
20
18
  from typing import Literal
@@ -236,7 +234,6 @@ class ModelType(BaseType): # pylint: disable=too-many-instance-attributes, too-
236
234
  except StopIteration:
237
235
  return None
238
236
 
239
- @property
240
237
  def pylint_disable(self) -> str:
241
238
  retval: str = ""
242
239
  if len(self.properties) > 10:
@@ -19,7 +19,7 @@ from typing import (
19
19
 
20
20
  from .request_builder_parameter import RequestBuilderParameter
21
21
 
22
- from .utils import OrderedSet, add_to_pylint_disable, NAME_LENGTH_LIMIT
22
+ from .utils import OrderedSet, add_to_pylint_disable
23
23
  from .base_builder import BaseBuilder
24
24
  from .imports import FileImport, ImportType, TypingSection
25
25
  from .response import (
@@ -38,7 +38,7 @@ from .parameter_list import ParameterList
38
38
  from .model_type import ModelType
39
39
  from .base import BaseType
40
40
  from .request_builder import OverloadedRequestBuilder, RequestBuilder
41
- from ...utils import xml_serializable, json_serializable
41
+ from ...utils import xml_serializable, json_serializable, NAME_LENGTH_LIMIT
42
42
 
43
43
  if TYPE_CHECKING:
44
44
  from .code_model import CodeModel
@@ -137,10 +137,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
137
137
  return self.responses[0].type_annotation(**kwargs)
138
138
  return "None"
139
139
 
140
- @property
141
- def pylint_disable(self) -> str:
140
+ def pylint_disable(self, async_mode: bool) -> str:
142
141
  retval: str = ""
143
- if self.response_type_annotation(async_mode=False) == "None":
142
+ if not async_mode and not self.is_overload and self.response_type_annotation(async_mode=False) == "None":
144
143
  # doesn't matter if it's async or not
145
144
  retval = add_to_pylint_disable(retval, "inconsistent-return-statements")
146
145
  try:
@@ -204,9 +203,9 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
204
203
  default_exceptions = [e for e in self.exceptions if "default" in e.status_codes and e.type]
205
204
  if not default_exceptions:
206
205
  return None
207
- excep_schema = default_exceptions[0].type
208
- if isinstance(excep_schema, ModelType):
209
- return excep_schema.type_annotation(skip_quote=True)
206
+ exception_schema = default_exceptions[0].type
207
+ if isinstance(exception_schema, ModelType):
208
+ return exception_schema.type_annotation(skip_quote=True)
210
209
  # in this case, it's just an AnyType
211
210
  return "'object'"
212
211
 
@@ -350,11 +349,12 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
350
349
  file_import.add_submodule_import("exceptions", error, ImportType.SDKCORE)
351
350
  if self.code_model.options["azure_arm"]:
352
351
  file_import.add_submodule_import("azure.mgmt.core.exceptions", "ARMErrorFormat", ImportType.SDKCORE)
353
- file_import.add_submodule_import(
354
- "typing",
355
- "Type",
356
- ImportType.STDLIB,
357
- )
352
+ if self.non_default_errors:
353
+ file_import.add_submodule_import(
354
+ "typing",
355
+ "Type",
356
+ ImportType.STDLIB,
357
+ )
358
358
  file_import.add_mutable_mapping_import()
359
359
  if self.non_default_error_status_codes:
360
360
  file_import.add_submodule_import(
@@ -10,9 +10,10 @@ from .utils import OrderedSet
10
10
  from .base import BaseModel
11
11
  from .operation import get_operation
12
12
  from .imports import FileImport, ImportType, TypingSection
13
- from .utils import add_to_pylint_disable, NAME_LENGTH_LIMIT
13
+ from .utils import add_to_pylint_disable
14
14
  from .lro_operation import LROOperation
15
15
  from .lro_paging_operation import LROPagingOperation
16
+ from ...utils import NAME_LENGTH_LIMIT
16
17
 
17
18
  if TYPE_CHECKING:
18
19
  from .code_model import CodeModel
@@ -76,7 +77,6 @@ class OperationGroup(BaseModel):
76
77
  file_import.add_submodule_import(relative_path, "models", ImportType.LOCAL, alias="_models")
77
78
  return file_import
78
79
 
79
- @property
80
80
  def pylint_disable(self) -> str:
81
81
  retval: str = ""
82
82
  if self.has_abstract_operations:
@@ -142,12 +142,12 @@ class _ParameterBase(BaseModel, abc.ABC): # pylint: disable=too-many-instance-a
142
142
  kwargs["is_operation_file"] = True
143
143
  # special logic for api-version parameter
144
144
  if self.is_api_version:
145
- type_annot = "str"
145
+ type_annotation = "str"
146
146
  else:
147
- type_annot = self.type.type_annotation(**kwargs)
147
+ type_annotation = self.type.type_annotation(**kwargs)
148
148
  if self.optional and self.client_default_value is None:
149
- return f"Optional[{type_annot}]"
150
- return type_annot
149
+ return f"Optional[{type_annotation}]"
150
+ return type_annotation
151
151
 
152
152
  def docstring_text(self, **kwargs: Any) -> str:
153
153
  return self.type.docstring_text(**kwargs)
@@ -213,12 +213,12 @@ class _ParameterBase(BaseModel, abc.ABC): # pylint: disable=too-many-instance-a
213
213
  def in_method_signature(self) -> bool: ...
214
214
 
215
215
  def method_signature(self, async_mode: bool) -> str:
216
- type_annot = self.type_annotation(async_mode=async_mode)
216
+ type_annotation = self.type_annotation(async_mode=async_mode)
217
217
  if self.client_default_value is not None or self.optional:
218
- return f"{self.client_name}: {type_annot} = {self.client_default_value_declaration},"
218
+ return f"{self.client_name}: {type_annotation} = {self.client_default_value_declaration},"
219
219
  if self.default_to_unset_sentinel:
220
- return f"{self.client_name}: {type_annot} = _Unset,"
221
- return f"{self.client_name}: {type_annot},"
220
+ return f"{self.client_name}: {type_annotation} = _Unset,"
221
+ return f"{self.client_name}: {type_annotation},"
222
222
 
223
223
 
224
224
  class BodyParameter(_ParameterBase):
@@ -306,7 +306,7 @@ class Parameter(_ParameterBase):
306
306
 
307
307
  self.skip_url_encoding: bool = self.yaml_data.get("skipUrlEncoding", False)
308
308
  self.explode: bool = self.yaml_data.get("explode", False)
309
- self.in_overriden: bool = self.yaml_data.get("inOverriden", False)
309
+ self.in_overridden: bool = self.yaml_data.get("inOverridden", False)
310
310
  self.delimiter: Optional[ParameterDelimeter] = self.yaml_data.get("delimiter")
311
311
  self._default_to_unset_sentinel: bool = False
312
312
 
@@ -40,7 +40,6 @@ class Property(BaseModel): # pylint: disable=too-many-instance-attributes
40
40
  self.is_multipart_file_input: bool = yaml_data.get("isMultipartFileInput", False)
41
41
  self.flatten = self.yaml_data.get("flatten", False) and not getattr(self.type, "flattened_property", False)
42
42
 
43
- @property
44
43
  def pylint_disable(self) -> str:
45
44
  retval: str = ""
46
45
  if self.yaml_data.get("pylintDisable"):
@@ -16,12 +16,13 @@ from typing import (
16
16
  from abc import abstractmethod
17
17
 
18
18
  from .base_builder import BaseBuilder
19
- from .utils import add_to_pylint_disable, NAME_LENGTH_LIMIT
19
+ from .utils import add_to_pylint_disable
20
20
  from .parameter_list import (
21
21
  RequestBuilderParameterList,
22
22
  OverloadedRequestBuilderParameterList,
23
23
  )
24
24
  from .imports import FileImport, ImportType, TypingSection, MsrestImportType
25
+ from ...utils import NAME_LENGTH_LIMIT
25
26
 
26
27
  if TYPE_CHECKING:
27
28
  from .code_model import CodeModel
@@ -65,8 +66,7 @@ class RequestBuilderBase(BaseBuilder[ParameterListType, List["RequestBuilder"]])
65
66
  def is_lro(self) -> bool:
66
67
  return self.yaml_data.get("discriminator") in ("lro", "lropaging")
67
68
 
68
- @property
69
- def pylint_disable(self) -> str:
69
+ def pylint_disable(self, async_mode: bool) -> str:
70
70
  if len(self.name) > NAME_LENGTH_LIMIT:
71
71
  return add_to_pylint_disable("", "name-too-long")
72
72
  return ""
@@ -100,7 +100,7 @@ class RequestBuilderParameter(Parameter):
100
100
  super_method_location = super().method_location
101
101
  if super_method_location == ParameterMethodLocation.KWARG:
102
102
  return super_method_location
103
- if self.in_overriden and super_method_location == ParameterMethodLocation.KEYWORD_ONLY:
103
+ if self.in_overridden and super_method_location == ParameterMethodLocation.KEYWORD_ONLY:
104
104
  return ParameterMethodLocation.KWARG
105
105
  if self.location != ParameterLocation.PATH:
106
106
  return ParameterMethodLocation.KEYWORD_ONLY
@@ -97,10 +97,10 @@ class Response(BaseModel):
97
97
  def type_annotation(self, **kwargs: Any) -> str:
98
98
  if self.type:
99
99
  kwargs["is_operation_file"] = True
100
- type_annot = self.type.type_annotation(**kwargs)
100
+ type_annotation = self.type.type_annotation(**kwargs)
101
101
  if self.nullable:
102
- return f"Optional[{type_annot}]"
103
- return type_annot
102
+ return f"Optional[{type_annotation}]"
103
+ return type_annotation
104
104
  return "None"
105
105
 
106
106
  def docstring_text(self, **kwargs: Any) -> str:
@@ -8,8 +8,6 @@ from typing import TypeVar, Dict
8
8
  T = TypeVar("T")
9
9
  OrderedSet = Dict[T, None]
10
10
 
11
- NAME_LENGTH_LIMIT = 40
12
-
13
11
 
14
12
  def add_to_description(description: str, entry: str) -> str:
15
13
  if description:
@@ -62,8 +62,8 @@ def _all_same(data: List[List[str]]) -> bool:
62
62
 
63
63
 
64
64
  def _need_type_ignore(builder: OperationType) -> bool:
65
- for excep in builder.non_default_errors:
66
- for status_code in excep.status_codes:
65
+ for e in builder.non_default_errors:
66
+ for status_code in e.status_codes:
67
67
  if status_code in (401, 404, 409, 304):
68
68
  return True
69
69
  return False
@@ -187,24 +187,6 @@ def _get_json_response_template_to_status_codes(
187
187
  return retval
188
188
 
189
189
 
190
- def _api_version_validation(builder: OperationType) -> str:
191
- if builder.is_overload:
192
- return ""
193
- retval: List[str] = []
194
- if builder.added_on:
195
- retval.append(f' method_added_on="{builder.added_on}",')
196
- params_added_on = defaultdict(list)
197
- for parameter in builder.parameters:
198
- if parameter.added_on:
199
- params_added_on[parameter.added_on].append(parameter.client_name)
200
- if params_added_on:
201
- retval.append(f" params_added_on={dict(params_added_on)},")
202
- if retval:
203
- retval_str = "\n".join(retval)
204
- return f"@api_version_validation(\n{retval_str}\n){builder.pylint_disable}"
205
- return ""
206
-
207
-
208
190
  def is_json_model_type(parameters: ParameterListType) -> bool:
209
191
  return (
210
192
  parameters.has_body
@@ -257,7 +239,7 @@ class _BuilderBaseSerializer(Generic[BuilderType]):
257
239
  method_name=builder.name,
258
240
  need_self_param=self._need_self_param,
259
241
  method_param_signatures=builder.method_signature(self.async_mode),
260
- pylint_disable=builder.pylint_disable,
242
+ pylint_disable=builder.pylint_disable(self.async_mode),
261
243
  )
262
244
 
263
245
  def method_signature_and_response_type_annotation(
@@ -599,10 +581,27 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
599
581
  def decorators(self, builder: OperationType) -> List[str]:
600
582
  """Decorators for the method"""
601
583
  retval = super().decorators(builder)
602
- if _api_version_validation(builder):
603
- retval.append(_api_version_validation(builder))
584
+ if self._api_version_validation(builder):
585
+ retval.append(self._api_version_validation(builder))
604
586
  return retval
605
587
 
588
+ def _api_version_validation(self, builder: OperationType) -> str:
589
+ if builder.is_overload:
590
+ return ""
591
+ retval: List[str] = []
592
+ if builder.added_on:
593
+ retval.append(f' method_added_on="{builder.added_on}",')
594
+ params_added_on = defaultdict(list)
595
+ for parameter in builder.parameters:
596
+ if parameter.added_on:
597
+ params_added_on[parameter.added_on].append(parameter.client_name)
598
+ if params_added_on:
599
+ retval.append(f" params_added_on={dict(params_added_on)},")
600
+ if retval:
601
+ retval_str = "\n".join(retval)
602
+ return f"@api_version_validation(\n{retval_str}\n){builder.pylint_disable(self.async_mode)}"
603
+ return ""
604
+
606
605
  def pop_kwargs_from_signature(self, builder: OperationType) -> List[str]:
607
606
  kwargs_to_pop = builder.parameters.kwargs_to_pop
608
607
  kwargs = self.parameter_serializer.pop_kwargs_from_signature(
@@ -625,10 +624,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
625
624
  if p.hide_in_operation_signature:
626
625
  kwargs.append(f'{p.client_name} = kwargs.pop("{p.client_name}", None)')
627
626
  cls_annotation = builder.cls_type_annotation(async_mode=self.async_mode)
628
- pylint_disable = ""
629
- if any(x.startswith("_") for x in cls_annotation.split(".")):
630
- pylint_disable = " # pylint: disable=protected-access"
631
- kwargs.append(f"cls: {cls_annotation} = kwargs.pop({pylint_disable}\n 'cls', None\n)")
627
+ kwargs.append(f"cls: {cls_annotation} = kwargs.pop(\n 'cls', None\n)")
632
628
  return kwargs
633
629
 
634
630
  def response_docstring(self, builder: OperationType) -> List[str]:
@@ -883,7 +879,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
883
879
  # request builders don't allow grouped parameters, so we group them before making the call
884
880
  retval.extend(_serialize_grouped_body(builder))
885
881
  if builder.parameters.has_body and builder.parameters.body_parameter.flattened:
886
- # unflatten before passing to request builder as well
882
+ # serialize flattened body before passing to request builder as well
887
883
  retval.extend(_serialize_flattened_body(builder.parameters.body_parameter))
888
884
  if is_json_model_type(builder.parameters):
889
885
  retval.extend(_serialize_json_model_body(builder.parameters.body_parameter, builder.parameters.parameters))
@@ -1089,9 +1085,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
1089
1085
  return retval
1090
1086
 
1091
1087
  def error_map(self, builder: OperationType) -> List[str]:
1092
- retval = [
1093
- "error_map: MutableMapping[int, Type[HttpResponseError]] = { # pylint: disable=unsubscriptable-object"
1094
- ]
1088
+ retval = ["error_map: MutableMapping = {"]
1095
1089
  if builder.non_default_errors:
1096
1090
  if not 401 in builder.non_default_error_status_codes:
1097
1091
  retval.append(" 401: ClientAuthenticationError,")
@@ -1101,17 +1095,17 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
1101
1095
  retval.append(" 409: ResourceExistsError,")
1102
1096
  if not 304 in builder.non_default_error_status_codes:
1103
1097
  retval.append(" 304: ResourceNotModifiedError,")
1104
- for excep in builder.non_default_errors:
1098
+ for e in builder.non_default_errors:
1105
1099
  error_model_str = ""
1106
- if isinstance(excep.type, ModelType):
1100
+ if isinstance(e.type, ModelType):
1107
1101
  if self.code_model.options["models_mode"] == "msrest":
1108
1102
  error_model_str = (
1109
- f", model=self._deserialize(" f"_models.{excep.type.serialization_type}, response)"
1103
+ f", model=self._deserialize(" f"_models.{e.type.serialization_type}, response)"
1110
1104
  )
1111
1105
  elif self.code_model.options["models_mode"] == "dpg":
1112
- error_model_str = f", model=_deserialize(_models.{excep.type.name}, response.json())"
1106
+ error_model_str = f", model=_deserialize(_models.{e.type.name}, response.json())"
1113
1107
  error_format_str = ", error_format=ARMErrorFormat" if self.code_model.options["azure_arm"] else ""
1114
- for status_code in excep.status_codes:
1108
+ for status_code in e.status_codes:
1115
1109
  if status_code == 401:
1116
1110
  retval.append(
1117
1111
  " 401: cast(Type[HttpResponseError], "
@@ -1196,8 +1190,8 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
1196
1190
  return ["@overload"]
1197
1191
  if self.code_model.options["tracing"] and builder.want_tracing:
1198
1192
  retval.append("@distributed_trace")
1199
- if _api_version_validation(builder):
1200
- retval.append(_api_version_validation(builder))
1193
+ if self._api_version_validation(builder):
1194
+ retval.append(self._api_version_validation(builder))
1201
1195
  return retval
1202
1196
 
1203
1197
  def call_next_link_request_builder(self, builder: PagingOperationType) -> List[str]:
@@ -1498,16 +1492,16 @@ def get_operation_serializer(
1498
1492
  LROOperationSerializer,
1499
1493
  LROPagingOperationSerializer,
1500
1494
  ]:
1501
- retcls: Union[
1495
+ ret_cls: Union[
1502
1496
  Type[OperationSerializer],
1503
1497
  Type[PagingOperationSerializer],
1504
1498
  Type[LROOperationSerializer],
1505
1499
  Type[LROPagingOperationSerializer],
1506
1500
  ] = OperationSerializer
1507
1501
  if builder.operation_type == "lropaging":
1508
- retcls = LROPagingOperationSerializer
1502
+ ret_cls = LROPagingOperationSerializer
1509
1503
  elif builder.operation_type == "lro":
1510
- retcls = LROOperationSerializer
1504
+ ret_cls = LROOperationSerializer
1511
1505
  elif builder.operation_type == "paging":
1512
- retcls = PagingOperationSerializer
1513
- return retcls(code_model, async_mode)
1506
+ ret_cls = PagingOperationSerializer
1507
+ return ret_cls(code_model, async_mode)
@@ -43,13 +43,12 @@ class ClientSerializer:
43
43
  pop_params_kwarg=PopKwargType.NO,
44
44
  )
45
45
 
46
- @property
47
46
  def class_definition(self) -> str:
48
47
  class_name = self.client.name
49
48
  base_class = ""
50
49
  if self.client.has_mixin:
51
50
  base_class = f"{class_name}OperationsMixin"
52
- pylint_disable = self.client.pylint_disable
51
+ pylint_disable = self.client.pylint_disable()
53
52
  if base_class:
54
53
  return f"class {class_name}({base_class}):{pylint_disable}"
55
54
  return f"class {class_name}:{pylint_disable}"
@@ -42,8 +42,7 @@ def _serialize_versioned_package(i: ImportModel, delimiter: str) -> str:
42
42
  )
43
43
  buffer.append("else:")
44
44
  buffer.append(
45
- f" from {i.module_name} import {i.submodule_name}{f' as {i.alias}' if i.alias else ''}"
46
- " # type: ignore # pylint: disable=ungrouped-imports"
45
+ f" from {i.module_name} import {i.submodule_name}{f' as {i.alias}' if i.alias else ''}" " # type: ignore"
47
46
  )
48
47
  return delimiter.join(buffer)
49
48
 
@@ -122,6 +121,6 @@ class FileImportSerializer:
122
121
  add_conditional_typing=False,
123
122
  )
124
123
  if typing_imports_list:
125
- typing_imports += "\n\nif TYPE_CHECKING:\n # pylint: disable=unused-import,ungrouped-imports\n "
124
+ typing_imports += "\n\nif TYPE_CHECKING:\n "
126
125
  typing_imports += "\n\n ".join(_get_import_clauses(typing_imports_list, "\n "))
127
126
  return regular_imports + typing_imports + self.get_typing_definitions()
@@ -66,10 +66,10 @@ class _ModelSerializer(BaseSerializer, ABC):
66
66
  @staticmethod
67
67
  def initialize_standard_property(prop: Property):
68
68
  if not (prop.optional or prop.client_default_value is not None):
69
- return f"{prop.client_name}: {prop.type_annotation()},{prop.pylint_disable}"
69
+ return f"{prop.client_name}: {prop.type_annotation()},{prop.pylint_disable()}"
70
70
  return (
71
71
  f"{prop.client_name}: {prop.type_annotation()} = "
72
- f"{prop.client_default_value_declaration},{prop.pylint_disable}"
72
+ f"{prop.client_default_value_declaration},{prop.pylint_disable()}"
73
73
  )
74
74
 
75
75
  @staticmethod
@@ -104,6 +104,23 @@ class _ModelSerializer(BaseSerializer, ABC):
104
104
  properties_to_pass_to_super.append("**kwargs")
105
105
  return ", ".join(properties_to_pass_to_super)
106
106
 
107
+ @abstractmethod
108
+ def initialize_properties(self, model: ModelType) -> List[str]: ...
109
+
110
+ def need_init(self, model: ModelType) -> bool:
111
+ return (not model.internal) and bool(self.init_line(model) or model.discriminator)
112
+
113
+ def pylint_disable(self, model: ModelType) -> str:
114
+ if model.flattened_property or self.initialize_properties(model):
115
+ return ""
116
+ if any(p for p in model.properties if p.is_discriminator and model.discriminator_value):
117
+ return ""
118
+ if model.parents and any(
119
+ "=" in prop for parent in model.parents for prop in self.init_line(parent) if self.need_init(parent)
120
+ ):
121
+ return ""
122
+ return " # pylint: disable=useless-super-delegation"
123
+
107
124
 
108
125
  class MsrestModelSerializer(_ModelSerializer):
109
126
  def imports(self) -> FileImport:
@@ -128,7 +145,7 @@ class MsrestModelSerializer(_ModelSerializer):
128
145
  )
129
146
  if model.parents:
130
147
  basename = ", ".join([m.name for m in model.parents])
131
- return f"class {model.name}({basename}):{model.pylint_disable}"
148
+ return f"class {model.name}({basename}):{model.pylint_disable()}"
132
149
 
133
150
  @staticmethod
134
151
  def get_properties_to_initialize(model: ModelType) -> List[Property]:
@@ -213,7 +230,7 @@ class DpgModelSerializer(_ModelSerializer):
213
230
  basename = ", ".join([m.name for m in model.parents])
214
231
  if model.discriminator_value:
215
232
  basename += f", discriminator='{model.discriminator_value}'"
216
- return f"class {model.name}({basename}):{model.pylint_disable}"
233
+ return f"class {model.name}({basename}):{model.pylint_disable()}"
217
234
 
218
235
  @staticmethod
219
236
  def get_properties_to_declare(model: ModelType) -> List[Property]:
@@ -179,7 +179,7 @@ class ParameterSerializer:
179
179
  if pop_headers_kwarg != PopKwargType.NO or pop_params_kwarg != PopKwargType.NO:
180
180
  retval.append("")
181
181
  for kwarg in parameters:
182
- type_annot = kwarg.type_annotation()
182
+ type_annotation = kwarg.type_annotation()
183
183
  if kwarg.client_default_value is not None or kwarg.optional:
184
184
  if check_client_input and kwarg.check_client_input:
185
185
  default_value = f"self._config.{kwarg.client_name}"
@@ -196,10 +196,10 @@ class ParameterSerializer:
196
196
  default_value = f"_{kwarg_dict}.pop('{kwarg.wire_name}', {default_value})"
197
197
 
198
198
  retval.append(
199
- f"{kwarg.client_name}: {type_annot} = kwargs.pop('{kwarg.client_name}', " + f"{default_value})"
199
+ f"{kwarg.client_name}: {type_annotation} = kwargs.pop('{kwarg.client_name}', " + f"{default_value})"
200
200
  )
201
201
  else:
202
- retval.append(f"{kwarg.client_name}: {type_annot} = kwargs.pop('{kwarg.client_name}')")
202
+ retval.append(f"{kwarg.client_name}: {type_annotation} = kwargs.pop('{kwarg.client_name}')")
203
203
  return retval
204
204
 
205
205
  @staticmethod
@@ -1,4 +1,3 @@
1
- # pylint: disable=too-many-lines
2
1
  # -------------------------------------------------------------------------
3
2
  # Copyright (c) Microsoft Corporation. All rights reserved.
4
3
  # Licensed under the MIT License. See License.txt in the project root for
@@ -1,4 +1,4 @@
1
- {{ serializer.class_definition }}
1
+ {{ serializer.class_definition() }}
2
2
  """{{ op_tools.wrap_string(client.description, "\n") | indent }}
3
3
 
4
4
  {{ op_tools.serialize_with_wrap(serializer.property_descriptions(async_mode), "\n ") | indent }}
@@ -1,4 +1,4 @@
1
- class {{ client.name }}Configuration: {{ client.config.pylint_disable }}
1
+ class {{ client.name }}Configuration: {{ client.config.pylint_disable() }}
2
2
  """Configuration for {{ client.name }}.
3
3
 
4
4
  Note that all parameters used to create this instance are saved as instance
@@ -7,7 +7,7 @@ from devtools_testutils import test_proxy, add_general_regex_sanitizer, add_body
7
7
 
8
8
  load_dotenv()
9
9
 
10
- # aovid record sensitive identity information in recordings
10
+ # For security, please avoid record sensitive identity information in recordings
11
11
  @pytest.fixture(scope="session", autouse=True)
12
12
  def add_sanitizers(test_proxy):
13
13
  {% for test_name in test_names %}
@@ -1,6 +1,6 @@
1
1
  {% macro wrap_model_string(doc_string, wrap_string, suffix_string="") %}
2
- {% set orignal_result = doc_string | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) %}
3
- {% set list_result = orignal_result.split('\n') %}
2
+ {% set original_result = doc_string | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrap_string) %}
3
+ {% set list_result = original_result.split('\n') %}
4
4
  {% for line in list_result %}
5
5
  {% set suffix = suffix_string if list_result | length == loop.index %}
6
6
  {% if line | length > 120 %}
@@ -636,7 +636,7 @@ class Model(_MyMutableMapping):
636
636
  return mapped_cls._deserialize(data, exist_discriminators)
637
637
 
638
638
  def as_dict(self, *, exclude_readonly: bool = False) -> typing.Dict[str, typing.Any]:
639
- """Return a dict that can be JSONify using json.dump.
639
+ """Return a dict that can be turned into json using json.dump.
640
640
 
641
641
  :keyword bool exclude_readonly: Whether to remove the readonly properties.
642
642
  :returns: A dict JSON compatible object
@@ -732,8 +732,7 @@ def _sorted_annotations(types: typing.List[typing.Any]) -> typing.List[typing.An
732
732
  key=lambda x: hasattr(x, "__name__") and x.__name__.lower() in ("str", "float", "int", "bool"),
733
733
  )
734
734
 
735
-
736
- def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915, R0912
735
+ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-return-statements, too-many-branches
737
736
  annotation: typing.Any,
738
737
  module: typing.Optional[str],
739
738
  rf: typing.Optional["_RestField"] = None,
@@ -1,6 +1,5 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools %}
2
2
  # coding=utf-8
3
- # pylint: disable=too-many-lines
4
3
  {{ code_model.options['license_header'] }}
5
4
 
6
5
  {{ imports }}
@@ -50,8 +50,7 @@
50
50
  {% endif %}
51
51
 
52
52
 
53
- {% set need_init = (not model.internal) and (serializer.init_line(model) or model.discriminator)%}
54
- {% if need_init %}
53
+ {% if serializer.need_init(model) %}
55
54
  @overload
56
55
  def __init__({{ model.init_pylint_disable }}
57
56
  self,
@@ -70,7 +69,7 @@
70
69
 
71
70
  {% endif %}
72
71
  {% set initialize_properties = serializer.initialize_properties(model) %}
73
- {% if need_init or initialize_properties %}
72
+ {% if serializer.need_init(model) or initialize_properties %}
74
73
  def __init__(self, *args: Any, **kwargs: Any) -> None:{{ '# pylint: disable=useless-super-delegation' if not initialize_properties else '' }}
75
74
  {% for line in serializer.super_call(model) %}
76
75
  {{ line }}
@@ -9,11 +9,11 @@
9
9
  {% endif %}
10
10
  {% endmacro %}
11
11
  {% if operation_group.base_class %}
12
- class {{ operation_group.class_name }}( {{ operation_group.pylint_disable }}
12
+ class {{ operation_group.class_name }}( {{ operation_group.pylint_disable() }}
13
13
  {{ operation_group.base_class }}
14
14
  ):
15
15
  {% else %}
16
- class {{ operation_group.class_name }}: {{ operation_group.pylint_disable }}
16
+ class {{ operation_group.class_name }}: {{ operation_group.pylint_disable() }}
17
17
  {% endif %}
18
18
  {% if not operation_group.is_mixin %}
19
19
  """
@@ -63,13 +63,13 @@ class {{ operation_group.class_name }}: {{ operation_group.pylint_disable }}
63
63
  {% set request_builder = operation.request_builder %}
64
64
  {% set operation_serializer = get_operation_serializer(operation) %}
65
65
  {% if operation.operation_type == "lropaging" %}
66
- {%- macro someop() %}{% include "lro_paging_operation.py.jinja2" %}{% endmacro %}
66
+ {%- macro some_op() %}{% include "lro_paging_operation.py.jinja2" %}{% endmacro %}
67
67
  {% elif operation.operation_type == "lro" %}
68
- {%- macro someop() %}{% include "lro_operation.py.jinja2" %}{% endmacro %}
68
+ {%- macro some_op() %}{% include "lro_operation.py.jinja2" %}{% endmacro %}
69
69
  {% elif operation.operation_type == "paging" %}
70
- {% macro someop() %}{% include "paging_operation.py.jinja2" %}{% endmacro %}
70
+ {% macro some_op() %}{% include "paging_operation.py.jinja2" %}{% endmacro %}
71
71
  {% else %}
72
- {% macro someop() %}{% include "operation.py.jinja2" %}{% endmacro %}
72
+ {% macro some_op() %}{% include "operation.py.jinja2" %}{% endmacro %}
73
73
  {% endif %}
74
- {{ someop()|indent }}
74
+ {{ some_op()|indent }}
75
75
  {% endfor %}
@@ -1,7 +1,6 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools %}
2
2
  {% set operations_description = "async operations" if async_mode else "operations" %}
3
3
  {% set return_none_type_annotation = " -> None" if async_mode else "" %}
4
- # pylint: disable=too-many-lines,too-many-statements
5
4
  # coding=utf-8
6
5
  {{ code_model.options['license_header'] }}
7
6
  {{ imports }}
@@ -1,4 +1,3 @@
1
- # pylint: disable=too-many-lines
2
1
  # --------------------------------------------------------------------------
3
2
  #
4
3
  # Copyright (c) {{ code_model.options["company_name"] }} Corporation. All rights reserved.
@@ -1,5 +1,4 @@
1
1
  # coding=utf-8
2
- # pylint: disable=too-many-lines
3
2
  {{ code_model.options['license_header'] }}
4
3
 
5
4
  {{ imports }}
@@ -17,7 +17,13 @@ from .helpers import (
17
17
  from .python_mappings import CADL_RESERVED_WORDS, RESERVED_WORDS, PadType
18
18
 
19
19
  from .. import YamlUpdatePlugin
20
- from ..utils import parse_args, get_body_type_for_description, JSON_REGEXP, KNOWN_TYPES, update_enum_value
20
+ from ..utils import (
21
+ parse_args,
22
+ get_body_type_for_description,
23
+ JSON_REGEXP,
24
+ KNOWN_TYPES,
25
+ update_enum_value,
26
+ )
21
27
 
22
28
 
23
29
  def update_overload_section(
@@ -91,10 +97,10 @@ def add_overloads_for_body_param(yaml_data: Dict[str, Any]) -> None:
91
97
  yaml_data["overloads"].append(add_overload(yaml_data, body_type, for_flatten_params=True))
92
98
  content_type_param = next(p for p in yaml_data["parameters"] if p["wireName"].lower() == "content-type")
93
99
  content_type_param["inOverload"] = False
94
- content_type_param["inOverriden"] = True
100
+ content_type_param["inOverridden"] = True
95
101
  content_type_param["inDocstring"] = True
96
102
  content_type_param["clientDefaultValue"] = (
97
- None # make it none bc it will be overriden, we depend on default of overloads
103
+ None # make it none bc it will be overridden, we depend on default of overloads
98
104
  )
99
105
  content_type_param["optional"] = True
100
106
 
@@ -126,7 +126,7 @@ RESERVED_WORDS = {
126
126
  "connection_cert",
127
127
  "connection_data_block_size",
128
128
  "use_env_settings",
129
- # the following aren't in the readme, but Xiang said these are also transport kwargs
129
+ # the following aren't in the readme, but @xiangyan99 said these are also transport kwargs
130
130
  "read_timeout",
131
131
  "proxies",
132
132
  "cookies",
@@ -158,3 +158,6 @@ def json_serializable(content_type: str) -> bool:
158
158
 
159
159
  def xml_serializable(content_type: str) -> bool:
160
160
  return bool(XML_REGEXP.match(content_type.split(";")[0].strip().lower()))
161
+
162
+
163
+ NAME_LENGTH_LIMIT = 40
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorest/python",
3
- "version": "6.22.0",
3
+ "version": "6.24.0",
4
4
  "description": "The Python extension for generators in AutoRest.",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -24,10 +24,10 @@
24
24
  "tsx": "4.17.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@microsoft.azure/autorest.testserver": "^3.3.46",
28
- "typescript": "~5.1.3",
27
+ "@microsoft.azure/autorest.testserver": "^3.3.50",
28
+ "@typespec/http-client-python": "0.2.0",
29
29
  "chalk": "5.3.0",
30
- "@azure-tools/typespec-python": "^0.32.0"
30
+ "typescript": "~5.1.6"
31
31
  },
32
32
  "files": [
33
33
  "autorest/**/*.py",
@@ -1,6 +1,5 @@
1
- import { copyFileSync, readdirSync } from "fs";
2
1
  import { existsSync, removeSync, copySync } from "fs-extra";
3
- import { join } from "path";
2
+ import { join, win32, posix } from "path";
4
3
 
5
4
  const force: boolean = process.argv[2] === "--force";
6
5
 
@@ -12,13 +11,14 @@ function copyAndCreateDir(sourceDir: string, destDir: string) {
12
11
  }
13
12
 
14
13
  // Copy the source directory to the destination directory
15
- copySync(sourceDir, destDir);
14
+ copySync(sourceDir, destDir, {
15
+ filter: (src: string) => {
16
+ return !src.replaceAll(win32.sep, posix.sep).includes("/test/");
17
+ },
18
+ });
16
19
  }
17
20
 
18
- const typespecModulePath: string = join(__dirname, "..", "node_modules", "@azure-tools", "typespec-python");
21
+ const typespecModulePath: string = join(__dirname, "..", "node_modules", "@typespec", "http-client-python");
19
22
 
20
23
  // Copy the generator directory
21
24
  copyAndCreateDir(join(typespecModulePath, "generator"), join(__dirname, "..", "generator"));
22
-
23
- // Copy the scripts directory
24
- copyAndCreateDir(join(typespecModulePath, "scripts", "eng"), join(__dirname, "..", "scripts", "eng"));
@@ -52,7 +52,7 @@ export function pyright() {
52
52
  export function eslint() {
53
53
  // const checkWarning = argv.skipWarning ? "" : "--max-warnings=0";
54
54
  const checkWarning = "";
55
- executeCommand(`npx eslint . --ext .ts ${checkWarning} `, "eslint");
55
+ executeCommand(`npx eslint . ${checkWarning} `, "eslint");
56
56
  }
57
57
 
58
58
  if (argv.command === "pylint") {
@@ -15,8 +15,9 @@ enable=useless-suppression
15
15
  # locally-disabled: Warning locally suppressed using disable-msg
16
16
  # cyclic-import: because of https://github.com/PyCQA/pylint/issues/850
17
17
  # too-many-arguments: Due to the nature of the CLI many commands have large arguments set which reflect in large arguments set in corresponding methods.
18
+ # too-many-lines: Due to code generation many files end up with too many lines.
18
19
  # Let's black deal with bad-continuation
19
- disable=useless-object-inheritance,missing-docstring,locally-disabled,fixme,cyclic-import,too-many-arguments,invalid-name,duplicate-code,too-few-public-methods,consider-using-f-string,super-with-arguments,redefined-builtin,import-outside-toplevel,client-suffix-needed,unnecessary-dunder-call,unnecessary-ellipsis,disallowed-name,consider-using-max-builtin
20
+ disable=useless-object-inheritance,missing-docstring,locally-disabled,fixme,cyclic-import,too-many-arguments,invalid-name,duplicate-code,too-few-public-methods,consider-using-f-string,super-with-arguments,redefined-builtin,import-outside-toplevel,client-suffix-needed,unnecessary-dunder-call,unnecessary-ellipsis,disallowed-name,consider-using-max-builtin,too-many-lines,parse-error,useless-suppression,unknown-option-value
20
21
 
21
22
  [FORMAT]
22
23
  max-line-length=120