@typespec/http-client-python 0.4.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/emitter/emitter.d.ts.map +1 -1
  2. package/dist/emitter/emitter.js +110 -24
  3. package/dist/emitter/emitter.js.map +1 -1
  4. package/dist/emitter/http.js +1 -1
  5. package/dist/emitter/http.js.map +1 -1
  6. package/dist/emitter/lib.d.ts +1 -0
  7. package/dist/emitter/lib.d.ts.map +1 -1
  8. package/dist/emitter/lib.js +1 -0
  9. package/dist/emitter/lib.js.map +1 -1
  10. package/dist/emitter/run-python3.d.ts +2 -0
  11. package/dist/emitter/run-python3.d.ts.map +1 -0
  12. package/dist/emitter/run-python3.js +19 -0
  13. package/dist/emitter/run-python3.js.map +1 -0
  14. package/dist/emitter/system-requirements.d.ts +17 -0
  15. package/dist/emitter/system-requirements.d.ts.map +1 -0
  16. package/dist/emitter/system-requirements.js +167 -0
  17. package/dist/emitter/system-requirements.js.map +1 -0
  18. package/emitter/src/emitter.ts +111 -23
  19. package/emitter/src/http.ts +1 -1
  20. package/emitter/src/lib.ts +2 -0
  21. package/emitter/src/run-python3.ts +20 -0
  22. package/emitter/src/system-requirements.ts +261 -0
  23. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  24. package/eng/scripts/Test-Packages.ps1 +1 -1
  25. package/eng/scripts/ci/regenerate.ts +20 -8
  26. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  27. package/eng/scripts/setup/build.ts +16 -0
  28. package/eng/scripts/setup/build_pygen_wheel.py +40 -0
  29. package/eng/scripts/setup/install.py +9 -8
  30. package/eng/scripts/setup/install.ts +12 -0
  31. package/eng/scripts/setup/prepare.py +3 -1
  32. package/eng/scripts/setup/prepare.ts +11 -0
  33. package/eng/scripts/setup/run-python3.ts +1 -6
  34. package/generator/build/lib/pygen/__init__.py +107 -0
  35. package/generator/build/lib/pygen/_version.py +7 -0
  36. package/generator/build/lib/pygen/black.py +71 -0
  37. package/generator/build/lib/pygen/codegen/__init__.py +357 -0
  38. package/generator/build/lib/pygen/codegen/_utils.py +17 -0
  39. package/generator/build/lib/pygen/codegen/models/__init__.py +204 -0
  40. package/generator/build/lib/pygen/codegen/models/base.py +186 -0
  41. package/generator/build/lib/pygen/codegen/models/base_builder.py +118 -0
  42. package/generator/build/lib/pygen/codegen/models/client.py +435 -0
  43. package/generator/build/lib/pygen/codegen/models/code_model.py +237 -0
  44. package/generator/build/lib/pygen/codegen/models/combined_type.py +149 -0
  45. package/generator/build/lib/pygen/codegen/models/constant_type.py +129 -0
  46. package/generator/build/lib/pygen/codegen/models/credential_types.py +214 -0
  47. package/generator/build/lib/pygen/codegen/models/dictionary_type.py +127 -0
  48. package/generator/build/lib/pygen/codegen/models/enum_type.py +238 -0
  49. package/generator/build/lib/pygen/codegen/models/imports.py +291 -0
  50. package/generator/build/lib/pygen/codegen/models/list_type.py +143 -0
  51. package/generator/build/lib/pygen/codegen/models/lro_operation.py +142 -0
  52. package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +32 -0
  53. package/generator/build/lib/pygen/codegen/models/model_type.py +357 -0
  54. package/generator/build/lib/pygen/codegen/models/operation.py +509 -0
  55. package/generator/build/lib/pygen/codegen/models/operation_group.py +184 -0
  56. package/generator/build/lib/pygen/codegen/models/paging_operation.py +155 -0
  57. package/generator/build/lib/pygen/codegen/models/parameter.py +412 -0
  58. package/generator/build/lib/pygen/codegen/models/parameter_list.py +387 -0
  59. package/generator/build/lib/pygen/codegen/models/primitive_types.py +659 -0
  60. package/generator/build/lib/pygen/codegen/models/property.py +170 -0
  61. package/generator/build/lib/pygen/codegen/models/request_builder.py +189 -0
  62. package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +115 -0
  63. package/generator/build/lib/pygen/codegen/models/response.py +348 -0
  64. package/generator/build/lib/pygen/codegen/models/utils.py +21 -0
  65. package/generator/build/lib/pygen/codegen/serializers/__init__.py +574 -0
  66. package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +21 -0
  67. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +1533 -0
  68. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +294 -0
  69. package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +15 -0
  70. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +213 -0
  71. package/generator/build/lib/pygen/codegen/serializers/import_serializer.py +126 -0
  72. package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +198 -0
  73. package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +33 -0
  74. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +335 -0
  75. package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +89 -0
  76. package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +44 -0
  77. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +221 -0
  78. package/generator/build/lib/pygen/codegen/serializers/patch_serializer.py +19 -0
  79. package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +52 -0
  80. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +168 -0
  81. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +292 -0
  82. package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +31 -0
  83. package/generator/build/lib/pygen/codegen/serializers/utils.py +68 -0
  84. package/generator/build/lib/pygen/codegen/templates/client.py.jinja2 +37 -0
  85. package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +12 -0
  86. package/generator/build/lib/pygen/codegen/templates/config.py.jinja2 +73 -0
  87. package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +16 -0
  88. package/generator/build/lib/pygen/codegen/templates/conftest.py.jinja2 +28 -0
  89. package/generator/build/lib/pygen/codegen/templates/enum.py.jinja2 +13 -0
  90. package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +10 -0
  91. package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +24 -0
  92. package/generator/build/lib/pygen/codegen/templates/keywords.jinja2 +27 -0
  93. package/generator/build/lib/pygen/codegen/templates/lro_operation.py.jinja2 +16 -0
  94. package/generator/build/lib/pygen/codegen/templates/lro_paging_operation.py.jinja2 +18 -0
  95. package/generator/build/lib/pygen/codegen/templates/macros.jinja2 +12 -0
  96. package/generator/build/lib/pygen/codegen/templates/metadata.json.jinja2 +167 -0
  97. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +1174 -0
  98. package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +15 -0
  99. package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +97 -0
  100. package/generator/build/lib/pygen/codegen/templates/model_init.py.jinja2 +33 -0
  101. package/generator/build/lib/pygen/codegen/templates/model_msrest.py.jinja2 +92 -0
  102. package/generator/build/lib/pygen/codegen/templates/operation.py.jinja2 +21 -0
  103. package/generator/build/lib/pygen/codegen/templates/operation_group.py.jinja2 +75 -0
  104. package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +19 -0
  105. package/generator/build/lib/pygen/codegen/templates/operation_tools.jinja2 +81 -0
  106. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +17 -0
  107. package/generator/build/lib/pygen/codegen/templates/packaging_templates/CHANGELOG.md.jinja2 +6 -0
  108. package/generator/build/lib/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +21 -0
  109. package/generator/build/lib/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +8 -0
  110. package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +107 -0
  111. package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +9 -0
  112. package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +108 -0
  113. package/generator/build/lib/pygen/codegen/templates/paging_operation.py.jinja2 +21 -0
  114. package/generator/build/lib/pygen/codegen/templates/patch.py.jinja2 +19 -0
  115. package/generator/build/lib/pygen/codegen/templates/pkgutil_init.py.jinja2 +1 -0
  116. package/generator/build/lib/pygen/codegen/templates/request_builder.py.jinja2 +28 -0
  117. package/generator/build/lib/pygen/codegen/templates/request_builders.py.jinja2 +10 -0
  118. package/generator/build/lib/pygen/codegen/templates/rest_init.py.jinja2 +12 -0
  119. package/generator/build/lib/pygen/codegen/templates/sample.py.jinja2 +44 -0
  120. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +2117 -0
  121. package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +50 -0
  122. package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +26 -0
  123. package/generator/build/lib/pygen/codegen/templates/types.py.jinja2 +7 -0
  124. package/generator/build/lib/pygen/codegen/templates/validation.py.jinja2 +38 -0
  125. package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +96 -0
  126. package/generator/build/lib/pygen/codegen/templates/version.py.jinja2 +4 -0
  127. package/generator/build/lib/pygen/m2r.py +65 -0
  128. package/generator/build/lib/pygen/preprocess/__init__.py +515 -0
  129. package/generator/build/lib/pygen/preprocess/helpers.py +27 -0
  130. package/generator/build/lib/pygen/preprocess/python_mappings.py +226 -0
  131. package/generator/build/lib/pygen/utils.py +163 -0
  132. package/generator/component-detection-pip-report.json +134 -0
  133. package/generator/dev_requirements.txt +0 -1
  134. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  135. package/generator/pygen/codegen/__init__.py +4 -4
  136. package/generator/pygen.egg-info/PKG-INFO +7 -4
  137. package/generator/pygen.egg-info/requires.txt +7 -4
  138. package/generator/setup.py +7 -4
  139. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +1 -1
  140. package/generator/test/{generic_mock_api_tests/asynctests/test_payload_pageable_async.py → azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py} +1 -1
  141. package/generator/test/azure/mock_api_tests/conftest.py +5 -4
  142. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +1 -1
  143. package/generator/test/{generic_mock_api_tests/test_payload_pageable.py → azure/mock_api_tests/test_azure_payload_pageable.py} +1 -1
  144. package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_resiliency_srv_driven.py +4 -2
  145. package/generator/test/{generic_mock_api_tests/asynctests → azure/mock_api_tests}/test_resiliency_srv_driven_async.py +3 -2
  146. package/generator/test/azure/requirements.txt +9 -8
  147. package/generator/test/generic_mock_api_tests/conftest.py +9 -4
  148. package/generator/test/unbranded/mock_api_tests/conftest.py +4 -4
  149. package/generator/test/unbranded/mock_api_tests/test_unbranded.py +1 -1
  150. package/generator/test/unbranded/requirements.txt +1 -8
  151. package/package.json +10 -10
  152. package/generator/requirements.txt +0 -12
  153. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_naming_async.py +0 -0
  154. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_structure_async.py +0 -0
  155. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_naming.py +0 -0
  156. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_structure.py +0 -0
@@ -0,0 +1,155 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ from typing import Dict, List, Any, Optional, Union, TYPE_CHECKING, cast, TypeVar
7
+
8
+ from .operation import Operation, OperationBase
9
+ from .response import PagingResponse, LROPagingResponse, Response
10
+ from .request_builder import (
11
+ OverloadedRequestBuilder,
12
+ RequestBuilder,
13
+ get_request_builder,
14
+ )
15
+ from .imports import ImportType, FileImport, TypingSection
16
+ from .parameter_list import ParameterList
17
+ from .model_type import ModelType
18
+ from .list_type import ListType
19
+
20
+ if TYPE_CHECKING:
21
+ from .code_model import CodeModel
22
+ from .client import Client
23
+
24
+ PagingResponseType = TypeVar("PagingResponseType", bound=Union[PagingResponse, LROPagingResponse])
25
+
26
+
27
+ class PagingOperationBase(OperationBase[PagingResponseType]):
28
+ def __init__(
29
+ self,
30
+ yaml_data: Dict[str, Any],
31
+ code_model: "CodeModel",
32
+ client: "Client",
33
+ name: str,
34
+ request_builder: RequestBuilder,
35
+ parameters: ParameterList,
36
+ responses: List[PagingResponseType],
37
+ exceptions: List[Response],
38
+ *,
39
+ overloads: Optional[List[Operation]] = None,
40
+ override_success_response_to_200: bool = False,
41
+ ) -> None:
42
+ super().__init__(
43
+ code_model=code_model,
44
+ client=client,
45
+ yaml_data=yaml_data,
46
+ name=name,
47
+ request_builder=request_builder,
48
+ parameters=parameters,
49
+ responses=responses,
50
+ exceptions=exceptions,
51
+ overloads=overloads,
52
+ )
53
+ self.next_request_builder: Optional[Union[RequestBuilder, OverloadedRequestBuilder]] = (
54
+ get_request_builder(self.yaml_data["nextOperation"], code_model, client)
55
+ if self.yaml_data.get("nextOperation")
56
+ else None
57
+ )
58
+ self.override_success_response_to_200 = override_success_response_to_200
59
+ self.pager_sync: str = yaml_data.get("pagerSync") or f"{self.code_model.core_library}.paging.ItemPaged"
60
+ self.pager_async: str = yaml_data.get("pagerAsync") or f"{self.code_model.core_library}.paging.AsyncItemPaged"
61
+
62
+ def _get_attr_name(self, wire_name: str) -> str:
63
+ response_type = self.responses[0].type
64
+ if not response_type:
65
+ raise ValueError(f"Can't find a matching property in response for {wire_name}")
66
+ if response_type.type == "list":
67
+ response_type = cast(ListType, response_type).element_type
68
+ try:
69
+ return next(p.client_name for p in cast(ModelType, response_type).properties if p.wire_name == wire_name)
70
+ except StopIteration as exc:
71
+ raise ValueError(f"Can't find a matching property in response for {wire_name}") from exc
72
+
73
+ def get_pager(self, async_mode: bool) -> str:
74
+ return self.responses[0].get_pager(async_mode)
75
+
76
+ @property
77
+ def continuation_token_name(self) -> Optional[str]:
78
+ wire_name = self.yaml_data.get("continuationTokenName")
79
+ if not wire_name:
80
+ # That's an ok scenario, it just means no next page possible
81
+ return None
82
+ if self.code_model.options["models_mode"] == "msrest":
83
+ return self._get_attr_name(wire_name)
84
+ return wire_name
85
+
86
+ @property
87
+ def item_name(self) -> str:
88
+ wire_name = self.yaml_data["itemName"]
89
+ if self.code_model.options["models_mode"] == "msrest":
90
+ # we don't use the paging model for dpg
91
+ return self._get_attr_name(wire_name)
92
+ return wire_name
93
+
94
+ @property
95
+ def item_type(self) -> ModelType:
96
+ try:
97
+ item_type_yaml = self.yaml_data["itemType"]
98
+ except KeyError as e:
99
+ raise ValueError("Only call this for DPG paging model deserialization") from e
100
+ return cast(ModelType, self.code_model.types_map[id(item_type_yaml)])
101
+
102
+ @property
103
+ def operation_type(self) -> str:
104
+ return "paging"
105
+
106
+ def cls_type_annotation(self, *, async_mode: bool) -> str:
107
+ return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]"
108
+
109
+ def _imports_shared(self, async_mode: bool, **kwargs: Any) -> FileImport:
110
+ file_import = super()._imports_shared(async_mode, **kwargs)
111
+ if async_mode:
112
+ file_import.add_submodule_import("typing", "AsyncIterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
113
+ else:
114
+ file_import.add_submodule_import("typing", "Iterable", ImportType.STDLIB, TypingSection.CONDITIONAL)
115
+ if (
116
+ self.next_request_builder
117
+ and self.code_model.options["builders_visibility"] == "embedded"
118
+ and not async_mode
119
+ ):
120
+ file_import.merge(self.next_request_builder.imports())
121
+ return file_import
122
+
123
+ @property
124
+ def has_optional_return_type(self) -> bool:
125
+ return False
126
+
127
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
128
+ if self.abstract:
129
+ return FileImport(self.code_model)
130
+ file_import = self._imports_shared(async_mode, **kwargs)
131
+ file_import.merge(super().imports(async_mode, **kwargs))
132
+ if self.code_model.options["tracing"] and self.want_tracing:
133
+ file_import.add_submodule_import(
134
+ "azure.core.tracing.decorator",
135
+ "distributed_trace",
136
+ ImportType.SDKCORE,
137
+ )
138
+ if self.next_request_builder:
139
+ file_import.merge(self.get_request_builder_import(self.next_request_builder, async_mode))
140
+ elif any(p.is_api_version for p in self.client.parameters):
141
+ file_import.add_import("urllib.parse", ImportType.STDLIB)
142
+ file_import.add_submodule_import(
143
+ "utils",
144
+ "case_insensitive_dict",
145
+ ImportType.SDKCORE,
146
+ )
147
+ if self.code_model.options["models_mode"] == "dpg":
148
+ relative_path = "..." if async_mode else ".."
149
+ file_import.merge(self.item_type.imports(**kwargs))
150
+ if self.default_error_deserialization or any(r.type for r in self.responses):
151
+ file_import.add_submodule_import(f"{relative_path}_model_base", "_deserialize", ImportType.LOCAL)
152
+ return file_import
153
+
154
+
155
+ class PagingOperation(PagingOperationBase[PagingResponse]): ...
@@ -0,0 +1,412 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License.txt in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ import abc
7
+ from enum import Enum
8
+
9
+ from typing import (
10
+ Dict,
11
+ Any,
12
+ TYPE_CHECKING,
13
+ List,
14
+ Optional,
15
+ TypeVar,
16
+ Union,
17
+ )
18
+
19
+ from .imports import FileImport, ImportType, TypingSection
20
+ from .base import BaseModel
21
+ from .base import BaseType
22
+ from .constant_type import ConstantType
23
+ from .utils import add_to_description
24
+ from .combined_type import CombinedType
25
+ from .model_type import JSONModelType
26
+
27
+ if TYPE_CHECKING:
28
+ from .code_model import CodeModel
29
+ from .request_builder_parameter import RequestBuilderBodyParameter
30
+
31
+
32
+ class ParameterLocation(str, Enum):
33
+ HEADER = "header"
34
+ PATH = "path"
35
+ ENDPOINT_PATH = "endpointPath"
36
+ QUERY = "query"
37
+ BODY = "body"
38
+ OTHER = "other"
39
+
40
+
41
+ class ParameterMethodLocation(str, Enum):
42
+ POSITIONAL = "positional"
43
+ KEYWORD_ONLY = "keywordOnly"
44
+ KWARG = "kwarg"
45
+
46
+
47
+ class ParameterDelimeter(str, Enum):
48
+ SPACE = "space"
49
+ PIPE = "pipe"
50
+ TAB = "tab"
51
+ COMMA = "comma"
52
+
53
+
54
+ class _ParameterBase(BaseModel, abc.ABC): # pylint: disable=too-many-instance-attributes
55
+ """Base class for all parameters"""
56
+
57
+ def __init__(
58
+ self,
59
+ yaml_data: Dict[str, Any],
60
+ code_model: "CodeModel",
61
+ type: BaseType,
62
+ ) -> None:
63
+ super().__init__(yaml_data, code_model)
64
+ self.wire_name: str = yaml_data.get("wireName", "")
65
+ self.client_name: str = self.yaml_data["clientName"]
66
+ self.optional: bool = self.yaml_data["optional"]
67
+ self.implementation: str = yaml_data.get("implementation", None)
68
+ self.location: ParameterLocation = self.yaml_data["location"]
69
+ self.client_default_value = self.yaml_data.get("clientDefaultValue", None)
70
+ self.in_docstring = self.yaml_data.get("inDocstring", True)
71
+ self.type = type
72
+ if self.client_default_value is None:
73
+ self.client_default_value = self.type.client_default_value
74
+ # name of grouper if it is grouped by another parameter
75
+ self.grouped_by: Optional[str] = self.yaml_data.get("groupedBy")
76
+ # property matching property name to parameter name for grouping params
77
+ # and flattened body params
78
+ self.property_to_parameter_name: Optional[Dict[str, str]] = self.yaml_data.get("propertyToParameterName")
79
+ self.flattened: bool = self.yaml_data.get("flattened", False)
80
+ self.in_flattened_body: bool = self.yaml_data.get("inFlattenedBody", False)
81
+ self.grouper: bool = self.yaml_data.get("grouper", False)
82
+ self.check_client_input: bool = self.yaml_data.get("checkClientInput", False)
83
+ self.added_on: Optional[str] = self.yaml_data.get("addedOn")
84
+ self.is_api_version: bool = self.yaml_data.get("isApiVersion", False)
85
+ self.in_overload: bool = self.yaml_data.get("inOverload", False)
86
+ self.default_to_unset_sentinel: bool = self.yaml_data.get("defaultToUnsetSentinel", False)
87
+ self.hide_in_method: bool = self.yaml_data.get("hideInMethod", False)
88
+
89
+ def get_declaration(self, value: Any = None) -> Any:
90
+ return self.type.get_declaration(value)
91
+
92
+ @property
93
+ def hide_in_operation_signature(self) -> bool:
94
+ return False
95
+
96
+ @property
97
+ def constant(self) -> bool:
98
+ """Returns whether a parameter is a constant or not.
99
+ Checking to see if it's required, because if not, we don't consider it
100
+ a constant because it can have a value of None.
101
+ """
102
+ return (not self.optional or self.is_api_version) and isinstance(self.type, ConstantType)
103
+
104
+ @property
105
+ def description(self) -> str:
106
+ base_description = self.yaml_data["description"]
107
+ type_description = self.type.description(is_operation_file=True)
108
+ if type_description:
109
+ base_description = add_to_description(base_description, type_description)
110
+ if self.optional and isinstance(self.type, ConstantType):
111
+ base_description = add_to_description(
112
+ base_description,
113
+ f"Known values are {self.get_declaration()} and None.",
114
+ )
115
+ if not (self.optional or self.client_default_value):
116
+ base_description = add_to_description(base_description, "Required.")
117
+ if self.client_default_value is not None:
118
+ base_description = add_to_description(
119
+ base_description,
120
+ f"Default value is {self.client_default_value_declaration}.",
121
+ )
122
+ if self.optional and self.client_default_value is None:
123
+ base_description = add_to_description(
124
+ base_description,
125
+ f"Default value is {self.client_default_value_declaration}.",
126
+ )
127
+ if self.constant:
128
+ base_description = add_to_description(
129
+ base_description,
130
+ "Note that overriding this default value may result in unsupported behavior.",
131
+ )
132
+ return base_description
133
+
134
+ @property
135
+ def client_default_value_declaration(self):
136
+ """Declaration of parameter's client default value"""
137
+ if self.client_default_value is None:
138
+ return None
139
+ return self.get_declaration(self.client_default_value)
140
+
141
+ def type_annotation(self, **kwargs: Any) -> str:
142
+ kwargs["is_operation_file"] = True
143
+ # special logic for api-version parameter
144
+ if self.is_api_version:
145
+ type_annotation = "str"
146
+ else:
147
+ type_annotation = self.type.type_annotation(**kwargs)
148
+ if self.optional and self.client_default_value is None:
149
+ return f"Optional[{type_annotation}]"
150
+ return type_annotation
151
+
152
+ def docstring_text(self, **kwargs: Any) -> str:
153
+ return self.type.docstring_text(**kwargs)
154
+
155
+ def docstring_type(self, **kwargs: Any) -> str:
156
+ return self.type.docstring_type(**kwargs)
157
+
158
+ @property
159
+ def serialization_type(self) -> str:
160
+ return self.type.serialization_type
161
+
162
+ def _imports_shared(self, async_mode: bool, **_: Any) -> FileImport:
163
+ file_import = FileImport(self.code_model)
164
+ if self.optional and self.client_default_value is None:
165
+ file_import.add_submodule_import("typing", "Optional", ImportType.STDLIB)
166
+ if self.added_on and self.implementation != "Client":
167
+ file_import.add_submodule_import(
168
+ f"{'.' if async_mode else ''}.._validation",
169
+ "api_version_validation",
170
+ ImportType.LOCAL,
171
+ )
172
+ if isinstance(self.type, CombinedType) and self.type.name:
173
+ file_import.add_submodule_import(
174
+ "..." if async_mode else "..",
175
+ "_types",
176
+ ImportType.LOCAL,
177
+ TypingSection.TYPING,
178
+ )
179
+ return file_import
180
+
181
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
182
+ file_import = self._imports_shared(async_mode, **kwargs)
183
+ # special logic for api-version parameter
184
+ if not self.is_api_version:
185
+ file_import.merge(self.type.imports(async_mode=async_mode, **kwargs))
186
+ if self.default_to_unset_sentinel:
187
+ file_import.add_submodule_import("typing", "Any", ImportType.STDLIB)
188
+ file_import.define_mypy_type(
189
+ "_Unset: Any",
190
+ "object()",
191
+ )
192
+ return file_import
193
+
194
+ def imports_for_multiapi(self, async_mode: bool, **kwargs: Any) -> FileImport:
195
+ file_import = self._imports_shared(async_mode, **kwargs)
196
+ file_import.merge(self.type.imports_for_multiapi(async_mode=async_mode, **kwargs))
197
+ return file_import
198
+
199
+ @property
200
+ def method_location(self) -> ParameterMethodLocation:
201
+ raise NotImplementedError("Please implement in children")
202
+
203
+ @property
204
+ def description_keyword(self) -> str:
205
+ return "param" if self.method_location == ParameterMethodLocation.POSITIONAL else "keyword"
206
+
207
+ @property
208
+ def docstring_type_keyword(self) -> str:
209
+ return "type" if self.method_location == ParameterMethodLocation.POSITIONAL else "paramtype"
210
+
211
+ @property
212
+ @abc.abstractmethod
213
+ def in_method_signature(self) -> bool: ...
214
+
215
+ def method_signature(self, async_mode: bool) -> str:
216
+ type_annotation = self.type_annotation(async_mode=async_mode)
217
+ if self.client_default_value is not None or self.optional:
218
+ return f"{self.client_name}: {type_annotation} = {self.client_default_value_declaration},"
219
+ if self.default_to_unset_sentinel:
220
+ return f"{self.client_name}: {type_annotation} = _Unset,"
221
+ return f"{self.client_name}: {type_annotation},"
222
+
223
+
224
+ class BodyParameter(_ParameterBase):
225
+ """Body parameter."""
226
+
227
+ @property
228
+ def entries(self) -> List["BodyParameter"]:
229
+ return [BodyParameter.from_yaml(e, self.code_model) for e in self.yaml_data.get("entries", [])]
230
+
231
+ @property
232
+ def is_form_data(self) -> bool:
233
+ # hacky, but rn in legacy, there is no formdata model type, it's just a dict
234
+ # with all of the entries splatted out
235
+ return (
236
+ self.type.is_form_data
237
+ or bool(self.entries)
238
+ or ("multipart/form-data" in self.content_types and self.code_model.options["from_typespec"])
239
+ )
240
+
241
+ @property
242
+ def is_partial_body(self) -> bool:
243
+ """Whether it's part of a bigger body parameter, i.e. a MultipartBodyParameter"""
244
+ return self.yaml_data.get("isPartialBody", False)
245
+
246
+ @property
247
+ def method_location(self) -> ParameterMethodLocation:
248
+ return ParameterMethodLocation.KWARG if self.constant else ParameterMethodLocation.POSITIONAL
249
+
250
+ @property
251
+ def in_method_signature(self) -> bool:
252
+ if self.yaml_data.get("entries"):
253
+ # Right now, only legacy generates with multipart bodies and entries
254
+ # and legacy generates with the multipart body arguments splatted out
255
+ return False
256
+ return not (self.flattened or self.grouped_by)
257
+
258
+ @property
259
+ def content_types(self) -> List[str]:
260
+ return self.yaml_data["contentTypes"]
261
+
262
+ @property
263
+ def default_content_type(self) -> str:
264
+ return self.yaml_data["defaultContentType"]
265
+
266
+ @property
267
+ def has_json_model_type(self) -> bool:
268
+ if isinstance(self.type, CombinedType):
269
+ return self.type.target_model_subtype((JSONModelType,)) is not None
270
+ return isinstance(self.type, JSONModelType)
271
+
272
+ def imports(self, async_mode: bool, **kwargs: Any) -> FileImport:
273
+ file_import = super().imports(async_mode, **kwargs)
274
+ if self.is_form_data:
275
+ relative_path = "..." if async_mode else ".."
276
+ file_import.add_submodule_import(
277
+ f"{relative_path}_vendor",
278
+ "prepare_multipart_form_data",
279
+ ImportType.LOCAL,
280
+ )
281
+ file_import.add_submodule_import("typing", "List", ImportType.STDLIB)
282
+ return file_import
283
+
284
+ @classmethod
285
+ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel") -> "BodyParameter":
286
+ return cls(
287
+ yaml_data=yaml_data,
288
+ code_model=code_model,
289
+ type=code_model.lookup_type(id(yaml_data["type"])),
290
+ )
291
+
292
+
293
+ EntryBodyParameterType = TypeVar("EntryBodyParameterType", bound=Union[BodyParameter, "RequestBuilderBodyParameter"])
294
+
295
+
296
+ class Parameter(_ParameterBase):
297
+ """Basic Parameter class"""
298
+
299
+ def __init__(
300
+ self,
301
+ yaml_data: Dict[str, Any],
302
+ code_model: "CodeModel",
303
+ type: BaseType,
304
+ ) -> None:
305
+ super().__init__(yaml_data, code_model, type=type)
306
+
307
+ self.skip_url_encoding: bool = self.yaml_data.get("skipUrlEncoding", False)
308
+ self.explode: bool = self.yaml_data.get("explode", False)
309
+ self.in_overridden: bool = self.yaml_data.get("inOverridden", False)
310
+ self.delimiter: Optional[ParameterDelimeter] = self.yaml_data.get("delimiter")
311
+ self._default_to_unset_sentinel: bool = False
312
+
313
+ @property
314
+ def hide_in_operation_signature(self) -> bool:
315
+ if self.code_model.options["version_tolerant"] and self.client_name == "maxpagesize":
316
+ return True
317
+ return False
318
+
319
+ @property
320
+ def in_method_signature(self) -> bool:
321
+ return not (self.wire_name == "Accept" or self.grouped_by or self.flattened)
322
+
323
+ @property
324
+ def full_client_name(self) -> str:
325
+ if self.implementation == "Client":
326
+ return f"self._config.{self.client_name}"
327
+ return self.client_name
328
+
329
+ @property
330
+ def xml_serialization_ctxt(self) -> str:
331
+ return self.type.xml_serialization_ctxt or ""
332
+
333
+ @property
334
+ def is_content_type(self) -> bool:
335
+ return bool(self.wire_name) and self.wire_name.lower() == "content-type"
336
+
337
+ @property
338
+ def method_location( # pylint: disable=too-many-return-statements
339
+ self,
340
+ ) -> ParameterMethodLocation:
341
+ if not self.in_method_signature:
342
+ raise ValueError(f"Parameter '{self.client_name}' is not in the method.")
343
+ if self.code_model.options["models_mode"] == "dpg" and self.in_flattened_body:
344
+ return ParameterMethodLocation.KEYWORD_ONLY
345
+ if self.grouper:
346
+ return ParameterMethodLocation.POSITIONAL
347
+ if self.constant and self.wire_name != "Content-Type":
348
+ return ParameterMethodLocation.KWARG
349
+ if self.is_content_type:
350
+ if self.in_overload:
351
+ return ParameterMethodLocation.KEYWORD_ONLY
352
+ return ParameterMethodLocation.KWARG
353
+ query_or_header = self.location in (
354
+ ParameterLocation.HEADER,
355
+ ParameterLocation.QUERY,
356
+ )
357
+ if self.code_model.options["only_path_and_body_params_positional"] and query_or_header:
358
+ return ParameterMethodLocation.KEYWORD_ONLY
359
+ return ParameterMethodLocation.POSITIONAL
360
+
361
+ @classmethod
362
+ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"):
363
+ return cls(
364
+ yaml_data=yaml_data,
365
+ code_model=code_model,
366
+ type=code_model.lookup_type(id(yaml_data["type"])),
367
+ )
368
+
369
+
370
+ class ClientParameter(Parameter):
371
+ """Client parameter"""
372
+
373
+ @property
374
+ def is_host(self) -> bool:
375
+ return self.wire_name == "$host"
376
+
377
+ @property
378
+ def method_location(self) -> ParameterMethodLocation:
379
+ if self.constant:
380
+ return ParameterMethodLocation.KWARG
381
+ if (
382
+ self.is_host
383
+ and (self.code_model.options["version_tolerant"] or self.code_model.options["low_level_client"])
384
+ and not self.code_model.options["azure_arm"]
385
+ ):
386
+ # this means i am the base url
387
+ return ParameterMethodLocation.KEYWORD_ONLY
388
+ if (
389
+ self.client_default_value is not None
390
+ and self.code_model.options["from_typespec"]
391
+ and not self.code_model.options["azure_arm"]
392
+ ):
393
+ return ParameterMethodLocation.KEYWORD_ONLY
394
+ return ParameterMethodLocation.POSITIONAL
395
+
396
+
397
+ class ConfigParameter(Parameter):
398
+ """Config Parameter"""
399
+
400
+ @property
401
+ def in_method_signature(self) -> bool:
402
+ return not self.is_host
403
+
404
+ @property
405
+ def is_host(self) -> bool:
406
+ return self.wire_name == "$host"
407
+
408
+ @property
409
+ def method_location(self) -> ParameterMethodLocation:
410
+ if self.constant:
411
+ return ParameterMethodLocation.KWARG
412
+ return ParameterMethodLocation.POSITIONAL