@autorest/python 5.12.5 → 5.14.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/ChangeLog.md +185 -118
  2. package/autorest/black/__init__.py +3 -0
  3. package/autorest/codegen/__init__.py +34 -2
  4. package/autorest/codegen/models/__init__.py +2 -1
  5. package/autorest/codegen/models/client.py +6 -5
  6. package/autorest/codegen/models/code_model.py +3 -0
  7. package/autorest/codegen/models/constant_schema.py +0 -4
  8. package/autorest/codegen/models/lro_operation.py +6 -2
  9. package/autorest/codegen/models/operation.py +20 -11
  10. package/autorest/codegen/models/operation_group.py +0 -9
  11. package/autorest/codegen/models/paging_operation.py +3 -3
  12. package/autorest/codegen/models/parameter.py +35 -9
  13. package/autorest/codegen/models/parameter_list.py +11 -4
  14. package/autorest/codegen/models/request_builder.py +3 -2
  15. package/autorest/codegen/models/request_builder_parameter.py +5 -0
  16. package/autorest/codegen/models/request_builder_parameter_list.py +1 -0
  17. package/autorest/codegen/serializers/__init__.py +147 -74
  18. package/autorest/codegen/serializers/builder_serializer.py +68 -37
  19. package/autorest/codegen/serializers/client_serializer.py +14 -3
  20. package/autorest/codegen/serializers/general_serializer.py +4 -1
  21. package/autorest/codegen/serializers/utils.py +5 -1
  22. package/autorest/codegen/templates/CHANGELOG.md.jinja2 +6 -0
  23. package/autorest/codegen/templates/LICENSE.jinja2 +21 -0
  24. package/autorest/codegen/templates/MANIFEST.in.jinja2 +7 -0
  25. package/autorest/codegen/templates/README.md.jinja2 +105 -0
  26. package/autorest/codegen/templates/config.py.jinja2 +2 -7
  27. package/autorest/codegen/templates/dev_requirements.txt.jinja2 +10 -0
  28. package/autorest/codegen/templates/lro_operation.py.jinja2 +3 -1
  29. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +2 -0
  30. package/autorest/codegen/templates/operation.py.jinja2 +6 -2
  31. package/autorest/codegen/templates/operation_group.py.jinja2 +15 -18
  32. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -0
  33. package/autorest/codegen/templates/operation_tools.jinja2 +3 -2
  34. package/autorest/codegen/templates/paging_operation.py.jinja2 +2 -2
  35. package/autorest/codegen/templates/request_builder.py.jinja2 +2 -7
  36. package/autorest/codegen/templates/service_client.py.jinja2 +1 -1
  37. package/autorest/codegen/templates/setup.py.jinja2 +79 -20
  38. package/autorest/namer/name_converter.py +1 -1
  39. package/package.json +2 -2
  40. package/run-python3.js +1 -7
  41. package/venvtools.py +2 -2
@@ -27,12 +27,16 @@ from ..models import (
27
27
  SchemaResponse,
28
28
  IOSchema,
29
29
  ParameterStyle,
30
+ ParameterLocation
30
31
  )
31
32
  from . import utils
32
33
 
33
34
  T = TypeVar("T")
34
35
  OrderedSet = Dict[T, None]
35
36
 
37
+ def _escape_str(input_str: str) -> str:
38
+ replace = input_str.replace("'", "\\'")
39
+ return f'"{replace}"'
36
40
 
37
41
  def _improve_json_string(template_representation: str) -> Any:
38
42
  origin = template_representation.split('\n')
@@ -110,7 +114,7 @@ def _pop_parameters_kwarg(
110
114
  function_name: str,
111
115
  kwarg_name: str,
112
116
  ) -> str:
113
- return f'{function_name}_parameters = kwargs.pop("{kwarg_name}", {{}}) # type: Dict[str, Any]'
117
+ return f'_{function_name}_parameters = kwargs.pop("{kwarg_name}", {{}}) # type: Dict[str, Any]'
114
118
 
115
119
  def _serialize_grouped_body(builder) -> List[str]:
116
120
  retval: List[str] = []
@@ -149,12 +153,21 @@ def _serialize_flattened_body(builder) -> List[str]:
149
153
  return retval
150
154
 
151
155
  def _content_type_docstring(builder) -> str:
152
- content_type_str = (
153
- ":keyword str content_type: Media type of the body sent to the API. " +
154
- f'Default value is "{builder.parameters.default_content_type}". ' +
155
- 'Allowed values are: "{}."'.format('", "'.join(builder.parameters.content_types))
156
+ content_types = [f'"{c}"' for c in builder.parameters.content_types]
157
+ if len(content_types) == 2:
158
+ possible_values_str = " or ".join(content_types)
159
+ else:
160
+ possible_values_str = ", ".join(
161
+ content_types[: len(content_types) - 1]
162
+ ) + f", and {content_types[-1]}"
163
+ default_value = next(
164
+ p for p in builder.parameters.method if p.rest_api_name == "Content-Type"
165
+ ).default_value_declaration
166
+ return (
167
+ ":keyword content_type: Media type of the body sent to the API. " +
168
+ f"Possible values are: {possible_values_str}. " +
169
+ f"Default value is {default_value}."
156
170
  )
157
- return content_type_str
158
171
 
159
172
  class _BuilderSerializerProtocol(ABC):
160
173
  @property
@@ -180,11 +193,6 @@ class _BuilderSerializerProtocol(ABC):
180
193
  """Whether you want inline type hints. If false, your type hints will be commented'"""
181
194
  ...
182
195
 
183
- @abstractmethod
184
- def _method_signature(self, builder) -> str:
185
- """Signature of the builder. Does not include return type annotation"""
186
- ...
187
-
188
196
  @abstractmethod
189
197
  def _response_type_annotation(self, builder, modify_if_head_as_boolean: bool = True) -> str:
190
198
  """The mypy type annotation for the response"""
@@ -266,20 +274,22 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
266
274
  def _cls_docstring_rtype(self) -> str:
267
275
  return "" if self.code_model.options["version_tolerant"] else " or the result of cls(response)"
268
276
 
269
- def _method_signature(self, builder) -> str:
277
+ def _method_signature(self, builder: Operation, response_type_annotation: str) -> str:
270
278
  return utils.serialize_method(
271
279
  function_def=self._function_definition,
272
280
  method_name=builder.name,
273
281
  is_in_class=self._is_in_class,
274
282
  method_param_signatures=builder.parameters.method_signature(self._want_inline_type_hints),
283
+ ignore_inconsistent_return_statements=(response_type_annotation == "None")
275
284
  )
276
285
 
277
286
  def _response_type_annotation_wrapper(self, builder) -> List[str]:
278
287
  return []
279
288
 
280
289
  def method_signature_and_response_type_annotation(self, builder) -> str:
281
- method_signature = self._method_signature(builder)
282
290
  response_type_annotation = self._response_type_annotation(builder)
291
+ # want pre-wrapped response type. As long as it's None, pylint will get mad about inconsistent return types
292
+ method_signature = self._method_signature(builder, response_type_annotation)
283
293
  for wrapper in self._response_type_annotation_wrapper(builder)[::-1]:
284
294
  response_type_annotation = f"{wrapper}[{response_type_annotation}]"
285
295
  return self._method_signature_and_response_type_annotation_template(method_signature, response_type_annotation)
@@ -304,13 +314,14 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
304
314
  description_list.append(
305
315
  f":{param.docstring_type_keyword} { param.serialized_name }: { param.docstring_type }"
306
316
  )
307
- try:
308
- request_builder: RequestBuilder = cast(Operation, builder).request_builder
309
- except AttributeError:
310
- request_builder = cast(RequestBuilder, builder)
311
317
 
312
- if len(request_builder.schema_requests) > 1:
313
- description_list.append(_content_type_docstring(builder))
318
+ if len(builder.parameters.content_types) > 1:
319
+ description_list = [
320
+ _content_type_docstring(builder) if l.startswith(":keyword content_type:") else l
321
+ for l in description_list
322
+ ]
323
+ if not any(l for l in description_list if l.startswith(":keyword content_type:")):
324
+ description_list.append(_content_type_docstring(builder))
314
325
  return description_list
315
326
 
316
327
  def param_description_and_response_docstring(self, builder) -> List[str]:
@@ -402,7 +413,7 @@ class _BuilderBaseSerializer(_BuilderSerializerProtocol): # pylint: disable=abs
402
413
  def _serialize_parameter(
403
414
  self, param: Parameter, function_name: str
404
415
  ) -> List[str]:
405
- set_parameter = "{}_parameters['{}'] = {}".format(
416
+ set_parameter = "_{}_parameters['{}'] = {}".format(
406
417
  function_name,
407
418
  param.rest_api_name,
408
419
  utils.build_serialize_data_call(param, function_name, self.serializer_name)
@@ -499,11 +510,11 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
499
510
  def create_http_request(self, builder) -> List[str]:
500
511
  retval = ["return HttpRequest("]
501
512
  retval.append(f' method="{builder.method}",')
502
- retval.append(" url=url,")
513
+ retval.append(" url=_url,")
503
514
  if builder.parameters.query:
504
- retval.append(" params=query_parameters,")
515
+ retval.append(" params=_query_parameters,")
505
516
  if builder.parameters.headers:
506
- retval.append(" headers=header_parameters,")
517
+ retval.append(" headers=_header_parameters,")
507
518
  if builder.parameters.has_body:
508
519
  retval.extend([
509
520
  f" {body_kwarg}={body_kwarg},"
@@ -533,6 +544,13 @@ class _RequestBuilderBaseSerializer(_BuilderBaseSerializer): # pylint: disable=
533
544
  ))
534
545
  return retval
535
546
 
547
+ def construct_url(self, builder) -> str:
548
+ if any(o for o in ["low_level_client", "version_tolerant"] if self.code_model.options.get(o)):
549
+ url_value = _escape_str(builder.url)
550
+ else:
551
+ url_value = f'kwargs.pop("template_url", {_escape_str(builder.url)})'
552
+ return f"_url = {url_value}{' # pylint: disable=line-too-long' if len(url_value) > 114 else ''}"
553
+
536
554
  class RequestBuilderGenericSerializer(_RequestBuilderBaseSerializer):
537
555
  @property
538
556
  def _want_inline_type_hints(self) -> bool:
@@ -711,7 +729,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
711
729
  )
712
730
  ser_ctxt_name = "serialization_ctxt"
713
731
  ser_ctxt = builder.parameters.body[0].xml_serialization_ctxt if send_xml else None
714
- if ser_ctxt:
732
+ if ser_ctxt and self.code_model.options["models_mode"]:
715
733
  retval.append(f'{ser_ctxt_name} = {{"xml": {{{ser_ctxt}}}}}')
716
734
  serialize_body_call = self._serialize_body_call(
717
735
  builder,
@@ -781,6 +799,7 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
781
799
  builder,
782
800
  request_builder: RequestBuilder,
783
801
  template_url: Optional[str] = None,
802
+ is_next_request: bool = False,
784
803
  ) -> List[str]:
785
804
  retval = []
786
805
  if len(builder.body_kwargs_to_pass_to_request_builder) > 1:
@@ -820,6 +839,16 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
820
839
  parameter.serialized_name not in builder.body_kwargs_to_pass_to_request_builder
821
840
  ):
822
841
  continue
842
+ if (
843
+ is_next_request and
844
+ not bool(builder.next_request_builder) and
845
+ not self.code_model.options["reformat_next_link"] and
846
+ parameter.location == ParameterLocation.Query
847
+ ):
848
+ # if we don't want to reformat query parameters for next link calls
849
+ # in paging operations with a single swagger operation defintion,
850
+ # we skip passing query params when building the next request
851
+ continue
823
852
  high_level_name = cast(RequestBuilderParameter, parameter).name_in_high_level_operation
824
853
  retval.append(f" {parameter.serialized_name}={high_level_name},")
825
854
  if not self.code_model.options["version_tolerant"]:
@@ -986,7 +1015,8 @@ class _OperationBaseSerializer(_BuilderBaseSerializer): # pylint: disable=abstr
986
1015
 
987
1016
  @staticmethod
988
1017
  def get_metadata_url(builder) -> str:
989
- return f"{builder.python_name}.metadata = {{'url': '{ builder.request_builder.url }'}} # type: ignore"
1018
+ url = _escape_str(builder.request_builder.url)
1019
+ return f"{builder.python_name}.metadata = {{'url': { url }}} # type: ignore"
990
1020
 
991
1021
  class _SyncOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=abstract-method
992
1022
  @property
@@ -1065,11 +1095,13 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
1065
1095
  else:
1066
1096
  request_builder = builder.request_builder
1067
1097
  template_url = "next_link"
1098
+
1068
1099
  request_builder = builder.next_request_builder or builder.request_builder
1069
1100
  return self._call_request_builder_helper(
1070
1101
  builder,
1071
1102
  request_builder,
1072
1103
  template_url=template_url,
1104
+ is_next_request=True
1073
1105
  )
1074
1106
 
1075
1107
  def _prepare_request_callback(self, builder) -> List[str]:
@@ -1114,7 +1146,7 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
1114
1146
  deserialized = (
1115
1147
  f'self._deserialize("{response.serialization_type}", pipeline_response)'
1116
1148
  if self.code_model.options["models_mode"] else
1117
- "_loads(pipeline_response.http_response.body())"
1149
+ "pipeline_response.http_response.json()"
1118
1150
  )
1119
1151
  retval.append(f" deserialized = {deserialized}")
1120
1152
  item_name = builder.item_name(self.code_model)
@@ -1137,10 +1169,11 @@ class _PagingOperationBaseSerializer(_OperationBaseSerializer): # pylint: disab
1137
1169
  retval = [f"{self._def} get_next(next_link=None):"]
1138
1170
  retval.append(" request = prepare_request(next_link)")
1139
1171
  retval.append("")
1140
- retval.append(
1141
- f" pipeline_response = {self._call_method}self._client._pipeline.run(request, "
1142
- f"stream={builder.is_stream_response}, **kwargs)"
1143
- )
1172
+ retval.append(f" pipeline_response = {self._call_method}self._client._pipeline.run( # pylint: disable=protected-access")
1173
+ retval.append(" request,")
1174
+ retval.append(f" stream={builder.is_stream_response},")
1175
+ retval.append(" **kwargs")
1176
+ retval.append(" )")
1144
1177
  retval.append(" response = pipeline_response.http_response")
1145
1178
  retval.append("")
1146
1179
  retval.extend([
@@ -1234,7 +1267,7 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
1234
1267
  "Pass in False for this operation to not poll, or pass in your own initialized polling object for a"
1235
1268
  " personal polling strategy."
1236
1269
  )
1237
- retval.append(f":paramtype polling: bool or ~{self._polling_method_type}")
1270
+ retval.append(f":paramtype polling: bool or ~azure.core.polling.{self._polling_method_type}")
1238
1271
  retval.append(
1239
1272
  ":keyword int polling_interval: Default waiting time between two polls for LRO operations "
1240
1273
  "if no Retry-After header is present."
@@ -1287,9 +1320,8 @@ class _LROOperationBaseSerializer(_OperationBaseSerializer): # pylint: disable=
1287
1320
  retval.append(" client=self._client,")
1288
1321
  retval.append(" deserialization_callback=get_long_running_output")
1289
1322
  retval.append(" )")
1290
- retval.append("else:")
1291
1323
  retval.append(
1292
- f" return {self._poller(builder)}"
1324
+ f"return {self._poller(builder)}"
1293
1325
  "(self._client, raw_result, get_long_running_output, polling_method)"
1294
1326
  )
1295
1327
  return retval
@@ -1335,7 +1367,7 @@ class _SyncLROOperationBaseSerializer(_LROOperationBaseSerializer, _SyncOperatio
1335
1367
 
1336
1368
  @property
1337
1369
  def _polling_method_type(self):
1338
- return "azure.core.polling.PollingMethod"
1370
+ return "PollingMethod"
1339
1371
 
1340
1372
  def _poller(self, builder) -> str:
1341
1373
  return builder.get_poller(async_mode=False)
@@ -1368,7 +1400,7 @@ class AsyncLROOperationSerializer(_LROOperationBaseSerializer, AsyncOperationSer
1368
1400
 
1369
1401
  @property
1370
1402
  def _polling_method_type(self):
1371
- return "azure.core.polling.AsyncPollingMethod"
1403
+ return "AsyncPollingMethod"
1372
1404
 
1373
1405
  def _poller(self, builder) -> str:
1374
1406
  return builder.get_poller(async_mode=True)
@@ -1383,8 +1415,7 @@ class _LROPagingOperationBaseSerializer(_LROOperationBaseSerializer, _PagingOper
1383
1415
  retval.append(f" {self._def} internal_get_next(next_link=None):")
1384
1416
  retval.append(" if next_link is None:")
1385
1417
  retval.append(" return pipeline_response")
1386
- retval.append(" else:")
1387
- retval.append(f" return {self._call_method}get_next(next_link)")
1418
+ retval.append(f" return {self._call_method}get_next(next_link)")
1388
1419
  retval.append("")
1389
1420
  retval.append(f" return {self._pager(builder)}(")
1390
1421
  retval.append(" internal_get_next, extract_data")
@@ -44,9 +44,12 @@ class ClientSerializer:
44
44
  base_class = f"{class_name}OperationsMixin"
45
45
  elif not (async_mode or self.is_python3_file):
46
46
  base_class = "object"
47
+ disable = ""
48
+ if len(self.code_model.operation_groups) > 6:
49
+ disable = " # pylint: disable=too-many-instance-attributes"
47
50
  if base_class:
48
- return f"class {class_name}({base_class}):"
49
- return f"class {class_name}:"
51
+ return f"class {class_name}({base_class}):{disable}"
52
+ return f"class {class_name}:{disable}"
50
53
 
51
54
  def property_descriptions(self, async_mode: bool) -> List[str]:
52
55
  retval: List[str] = []
@@ -113,7 +116,7 @@ class ClientSerializer:
113
116
  method_name=self.code_model.send_request_name,
114
117
  is_in_class=True,
115
118
  method_param_signatures=self.code_model.service_client.send_request_signature(
116
- async_mode, async_mode or self.is_python3_file
119
+ async_mode or self.is_python3_file
117
120
  ),
118
121
  )
119
122
 
@@ -227,3 +230,11 @@ class ConfigSerializer:
227
230
  for p in self.code_model.global_parameters.config_method
228
231
  if p.required and not p.constant
229
232
  ]
233
+
234
+ def property_descriptions(self) -> List[str]:
235
+ retval: List[str] = []
236
+ for p in self.code_model.global_parameters.config_method:
237
+ retval.append(f":{p.description_keyword} {p.serialized_name}: {p.description}")
238
+ retval.append(f":{p.docstring_type_keyword} {p.serialized_name}: {p.docstring_type}")
239
+ retval.append('"""')
240
+ return retval
@@ -119,4 +119,7 @@ class GeneralSerializer:
119
119
 
120
120
  def serialize_setup_file(self) -> str:
121
121
  template = self.env.get_template("setup.py.jinja2")
122
- return template.render(code_model=self.code_model)
122
+ params = {}
123
+ params.update(self.code_model.options)
124
+ params.update(self.code_model.package_dependency)
125
+ return template.render(code_model=self.code_model, **params)
@@ -13,9 +13,13 @@ def serialize_method(
13
13
  method_name: str,
14
14
  is_in_class: bool,
15
15
  method_param_signatures: List[str],
16
+ ignore_inconsistent_return_statements: bool = False,
16
17
  ):
17
18
  lines: List[str] = []
18
- lines.append(f"{function_def} {method_name}(")
19
+ first_line = f"{function_def} {method_name}("
20
+ if ignore_inconsistent_return_statements:
21
+ first_line += " # pylint: disable=inconsistent-return-statements"
22
+ lines.append(first_line)
19
23
  if is_in_class:
20
24
  lines.append(" self,")
21
25
  lines.extend([
@@ -0,0 +1,6 @@
1
+ # Release History
2
+
3
+ ## 1.0.0b1 (1970-01-01)
4
+
5
+ - Initial version
6
+
@@ -0,0 +1,21 @@
1
+ Copyright (c) Microsoft Corporation.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ include *.md
2
+ include LICENSE
3
+ recursive-include tests *.py
4
+ recursive-include samples *.py *.md
5
+ {%- for init_name in init_names %}
6
+ include {{ init_name }}
7
+ {%- endfor %}
@@ -0,0 +1,105 @@
1
+ {% if package_mode == "mgmtplane" -%}
2
+ # Microsoft Azure SDK for Python
3
+
4
+ This is the Microsoft {{package_pprint_name}} Client Library.
5
+ This package has been tested with Python 3.6+.
6
+ For a more complete view of Azure libraries, see the [azure sdk python release](https://aka.ms/azsdk/python/all).
7
+
8
+ # Usage
9
+
10
+ To learn how to use this package, see the [quickstart guide](https://aka.ms/azsdk/python/mgmt)
11
+
12
+ For docs and references, see [Python SDK References](https://docs.microsoft.com/python/api/overview/azure)
13
+ Code samples for this package can be found at [{{package_pprint_name}}](https://docs.microsoft.com/samples/browse/?languages=python&term=Getting%20started%20-%20Managing&terms=Getting%20started%20-%20Managing) on docs.microsoft.com.
14
+ Additional code samples for different Azure services are available at [Samples Repo](https://aka.ms/azsdk/python/mgmt/samples)
15
+
16
+ # Provide Feedback
17
+
18
+ If you encounter any bugs or have suggestions, please file an issue in the
19
+ [Issues](https://github.com/Azure/azure-sdk-for-python/issues)
20
+ section of the project.
21
+
22
+
23
+ ![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-python%2F{{package_name}}%2FREADME.png)
24
+ {% else %}
25
+ # {{ package_pprint_name }} client library for Python
26
+ <!-- write necessary description of service -->
27
+
28
+ ## Getting started
29
+
30
+ ### Installating the package
31
+
32
+ ```bash
33
+ python -m pip install {{ package_name }}
34
+ ```
35
+
36
+ #### Prequisites
37
+
38
+ - Python 3.6 or later is required to use this package.
39
+ - You need an [Azure subscription][azure_sub] to use this package.
40
+ - An existing {{ package_pprint_name }} instance.
41
+
42
+ {%- if token_credential %}
43
+ #### Create with an Azure Active Directory Credential
44
+ To use an [Azure Active Directory (AAD) token credential][authenticate_with_token],
45
+ provide an instance of the desired credential type obtained from the
46
+ [azure-identity][azure_identity_credentials] library.
47
+
48
+ To authenticate with AAD, you must first [pip][pip] install [`azure-identity`][azure_identity_pip]
49
+
50
+ After setup, you can choose which type of [credential][azure_identity_credentials] from azure.identity to use.
51
+ As an example, [DefaultAzureCredential][default_azure_credential] can be used to authenticate the client:
52
+
53
+ Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables:
54
+ `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`
55
+
56
+ Use the returned token credential to authenticate the client:
57
+
58
+ ```python
59
+ >>> from {{ namespace }} import {{ client_name }}
60
+ >>> from azure.identity import DefaultAzureCredential
61
+ >>> client = {{ client_name }}(endpoint='<endpoint>', credential=DefaultAzureCredential())
62
+ ```
63
+
64
+ ## Examples
65
+
66
+ ```python
67
+ >>> from {{ namespace }} import {{ client_name }}
68
+ >>> from azure.identity import DefaultAzureCredential
69
+ >>> from azure.core.exceptions import HttpResponseError
70
+
71
+ >>> client = {{ client_name }}(endpoint='<endpoint>', credential=DefaultAzureCredential())
72
+ >>> try:
73
+ <!-- write test code here -->
74
+ except HttpResponseError as e:
75
+ print('service responds error: {}'.format(e.response.json()))
76
+
77
+ ```
78
+ {%- endif %}
79
+
80
+ ## Contributing
81
+
82
+ This project welcomes contributions and suggestions. Most contributions require
83
+ you to agree to a Contributor License Agreement (CLA) declaring that you have
84
+ the right to, and actually do, grant us the rights to use your contribution.
85
+ For details, visit https://cla.microsoft.com.
86
+
87
+ When you submit a pull request, a CLA-bot will automatically determine whether
88
+ you need to provide a CLA and decorate the PR appropriately (e.g., label,
89
+ comment). Simply follow the instructions provided by the bot. You will only
90
+ need to do this once across all repos using our CLA.
91
+
92
+ This project has adopted the
93
+ [Microsoft Open Source Code of Conduct][code_of_conduct]. For more information,
94
+ see the Code of Conduct FAQ or contact opencode@microsoft.com with any
95
+ additional questions or comments.
96
+
97
+ <!-- LINKS -->
98
+ [code_of_conduct]: https://opensource.microsoft.com/codeofconduct/
99
+ [authenticate_with_token]: https://docs.microsoft.com/azure/cognitive-services/authentication?tabs=powershell#authenticate-with-an-authentication-token
100
+ [azure_identity_credentials]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#credentials
101
+ [azure_identity_pip]: https://pypi.org/project/azure-identity/
102
+ [default_azure_credential]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#defaultazurecredential
103
+ [pip]: https://pypi.org/project/pip/
104
+ [azure_sub]: https://azure.microsoft.com/free/
105
+ {% endif %}
@@ -11,7 +11,7 @@
11
11
  VERSION = "unknown"
12
12
  {% endif %}
13
13
 
14
- class {{ code_model.class_name }}Configuration(Configuration):
14
+ class {{ code_model.class_name }}Configuration(Configuration): # pylint: disable=too-many-instance-attributes
15
15
  """Configuration for {{ code_model.class_name }}.
16
16
 
17
17
  Note that all parameters used to create this instance are saved as instance
@@ -19,12 +19,7 @@ class {{ code_model.class_name }}Configuration(Configuration):
19
19
  {% if code_model.global_parameters.config_method | first %}
20
20
 
21
21
  {% endif %}
22
- {% for parameter in code_model.global_parameters.config_method %}
23
- :{{ parameter.description_keyword }} {{ parameter.serialized_name }}: {{ parameter.description }}
24
- :{{ parameter.docstring_type_keyword }} {{ parameter.serialized_name }}: {{ parameter.docstring_type }}
25
- {% endfor %}
26
- """
27
-
22
+ {{ op_tools.serialize_with_wrap(serializer.property_descriptions(), "\n ") | indent }}
28
23
  {{ serializer.init_signature_and_response_type_annotation(async_mode) | indent }}
29
24
  super({{ code_model.class_name }}Configuration, self).__init__(**kwargs)
30
25
  {% if code_model.service_client.parameters.config_kwargs_to_pop(async_mode) %}
@@ -0,0 +1,10 @@
1
+ -e ../../../tools/azure-devtools
2
+ -e ../../../tools/azure-sdk-tools
3
+ ../../core/azure-core
4
+ {% if token_credential -%}
5
+ ../../identity/azure-identity
6
+ {% endif -%}
7
+ {% if azure_arm -%}
8
+ ../../core/azure-mgmt-core
9
+ {% endif -%}
10
+ aiohttp
@@ -13,4 +13,6 @@
13
13
  {{ op_tools.serialize(operation_serializer.get_long_running_output(operation)) | indent }}
14
14
 
15
15
  {{ op_tools.serialize(operation_serializer.return_lro_poller(operation)) | indent }}
16
- {{ operation_serializer.get_metadata_url(operation) }}
16
+ {% if not code_model.options["version_tolerant"] %}
17
+ {{ operation_serializer.get_metadata_url(operation) -}}
18
+ {% endif %}
@@ -15,4 +15,6 @@
15
15
  {{ op_tools.serialize(operation_serializer.initial_call(operation)) | indent }}
16
16
  {{ op_tools.serialize(operation_serializer.get_long_running_output(operation)) | indent }}
17
17
  {{ op_tools.serialize(operation_serializer.return_lro_poller(operation)) | indent }}
18
+ {% if not code_model.options["version_tolerant"] %}
18
19
  {{ operation_serializer.get_metadata_url(operation) }}
20
+ {% endif %}
@@ -18,8 +18,12 @@
18
18
  {{ op_tools.serialize(operation_serializer.pop_kwargs_from_signature(operation)) | indent }}
19
19
  {% endif %}
20
20
  {{ op_tools.serialize(operation_serializer.call_request_builder(operation)) | indent }}
21
- pipeline_response = {{ keywords.await }}self._client._pipeline.run(request, {{ stream_request_parameter }}, **kwargs)
21
+ pipeline_response = {{ keywords.await }}self._client._pipeline.run( # pylint: disable=protected-access
22
+ request,
23
+ {{ stream_request_parameter }},
24
+ **kwargs
25
+ )
22
26
  {{ op_tools.serialize(operation_serializer.handle_response(operation)) | indent }}
23
27
  {% if not code_model.options["version_tolerant"] %}
24
- {{ operation.python_name }}.metadata = {'url': {{ keywords.escape_str(request_builder.url) }}} # type: ignore
28
+ {{ operation_serializer.get_metadata_url(operation) }}
25
29
  {% endif %}
@@ -1,29 +1,26 @@
1
- class {{ operation_group.class_name }}{{ object_base_class }}:
1
+ {% set disable = " # pylint: disable=too-many-public-methods" if operation_group.operations | length > 20 else "" %}
2
+ class {{ operation_group.class_name }}{{ object_base_class }}:{{ disable }}
2
3
  {% if not operation_group.is_empty_operation_group %}
3
- """{{ operation_group.class_name }} {{ operations_description }}.
4
-
5
- You should not instantiate this class directly. Instead, you should create a Client instance that
6
- instantiates it for you and attaches it as an attribute.
4
+ """
5
+ .. warning::
6
+ **DO NOT** instantiate this class directly.
7
7
 
8
- {% if code_model.schemas and code_model.options["models_mode"] %}
9
- :ivar models: Alias to model classes used in this operation group.
10
- :type models: ~{{ code_model.namespace }}.models
11
- {% endif %}
12
- :param client: Client for service requests.
13
- :param config: Configuration of service client.
14
- :param serializer: An object model serializer.
15
- :param deserializer: An object model deserializer.
8
+ Instead, you should access the following operations through
9
+ :class:`{{ "~" + code_model.namespace + (".aio." if async_mode else ".") + code_model.class_name }}`'s
10
+ :attr:`{{ operation_group.name }}` attribute.
16
11
  """
17
12
 
18
13
  {% if code_model.schemas and code_model.options["models_mode"] %}
19
14
  models = _models
20
15
 
21
16
  {% endif %}
22
- def __init__(self, client, config, serializer, deserializer){{ return_none_type_annotation }}:
23
- self._client = client
24
- self._serialize = serializer
25
- self._deserialize = deserializer
26
- self._config = config
17
+ def __init__(self, *args, **kwargs){{ return_none_type_annotation }}:
18
+ args = list(args)
19
+ self._client = args.pop(0) if args else kwargs.pop("client")
20
+ self._config = args.pop(0) if args else kwargs.pop("config")
21
+ self._serialize = args.pop(0) if args else kwargs.pop("serializer")
22
+ self._deserialize = args.pop(0) if args else kwargs.pop("deserializer")
23
+
27
24
  {% endif %}
28
25
  {% for operation in operation_group.operations %}
29
26
 
@@ -2,6 +2,7 @@
2
2
  {% set object_base_class = "" if async_mode else "(object)" %}
3
3
  {% set operations_description = "async operations" if async_mode else "operations" %}
4
4
  {% set return_none_type_annotation = " -> None" if async_mode else "" %}
5
+ # pylint: disable=too-many-lines
5
6
  # coding=utf-8
6
7
  {{ code_model.options['license_header'] }}
7
8
  {{ imports }}
@@ -1,4 +1,4 @@
1
- {% macro wrap_string(string, wrapstring) %}{{ string | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring=wrapstring)}}{% endmacro %}
1
+ {% macro wrap_string(string, wrapstring, width=95) %}{{ string | wordwrap(width=width, break_long_words=False, break_on_hyphens=False, wrapstring=wrapstring)}}{% endmacro %}
2
2
 
3
3
  {% macro description(builder, serializer) %}
4
4
  {% for description in serializer.description_and_summary(builder) %}
@@ -22,7 +22,8 @@ Example:
22
22
  .. code-block:: python
23
23
  {% for template_line in serializer.get_example_template(builder) %}
24
24
  {% if template_line %}
25
- {{ template_line }}
25
+ {% set wrap_amount = (template_line | length) - (template_line.lstrip() | length) + 10 %}
26
+ {{ wrap_string(template_line, wrapstring='\n' + " " * wrap_amount, width=(95 - wrap_amount)) }}
26
27
  {% else %}
27
28
 
28
29
  {% endif %}
@@ -17,6 +17,6 @@
17
17
  return {{ operation.get_pager(async_mode) }}(
18
18
  get_next, extract_data
19
19
  )
20
- {% if not code_model.options["metadata"] %}
21
- {{ operation.python_name }}.metadata = {'url': '{{ request_builder.url|replace("'", "\\'") }}'} # type: ignore
20
+ {% if not code_model.options["version_tolerant"] %}
21
+ {{ operation_serializer.get_metadata_url(operation) -}}
22
22
  {% endif %}
@@ -13,15 +13,10 @@
13
13
  {% endfor %}
14
14
  {% endif %}
15
15
  # Construct URL
16
- {% if code_model.options["version_tolerant"] or code_model.options["low_level_client"] %}
17
- {% set url_value = keywords.escape_str(request_builder.url) %}
18
- {% else %}
19
- {% set url_value = 'kwargs.pop("template_url", ' + keywords.escape_str(request_builder.url) + ')' %}
20
- {% endif %}
21
- url = {{ url_value }}
16
+ {{ request_builder_serializer.construct_url(request_builder) }}
22
17
  {% if request_builder.parameters.path %}
23
18
  {{ op_tools.serialize(request_builder_serializer.serialize_path(request_builder)) | indent }}
24
- url = _format_url_section(url, **path_format_arguments)
19
+ _url = _format_url_section(_url, **path_format_arguments)
25
20
  {% endif %}
26
21
 
27
22
  {% if request_builder.parameters.query %}