@typespec/http-client-python 0.17.0 → 0.18.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 (33) hide show
  1. package/dist/emitter/emitter.js +1 -1
  2. package/dist/emitter/emitter.js.map +1 -1
  3. package/dist/emitter/http.d.ts.map +1 -1
  4. package/dist/emitter/http.js +1 -0
  5. package/dist/emitter/http.js.map +1 -1
  6. package/emitter/src/emitter.ts +1 -1
  7. package/emitter/src/http.ts +2 -0
  8. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  9. package/eng/scripts/ci/dev_requirements.txt +2 -2
  10. package/eng/scripts/setup/__pycache__/package_manager.cpython-39.pyc +0 -0
  11. package/eng/scripts/setup/__pycache__/venvtools.cpython-39.pyc +0 -0
  12. package/eng/scripts/setup/install.py +1 -2
  13. package/eng/scripts/setup/package_manager.py +5 -2
  14. package/eng/scripts/setup/prepare.py +1 -1
  15. package/generator/build/lib/pygen/codegen/models/paging_operation.py +4 -0
  16. package/generator/build/lib/pygen/codegen/models/parameter.py +1 -1
  17. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +7 -0
  18. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +1 -1
  19. package/generator/build/lib/pygen/preprocess/__init__.py +13 -3
  20. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  21. package/generator/pygen/codegen/models/paging_operation.py +4 -0
  22. package/generator/pygen/codegen/models/parameter.py +1 -1
  23. package/generator/pygen/codegen/serializers/builder_serializer.py +7 -0
  24. package/generator/pygen/codegen/templates/serialization.py.jinja2 +1 -1
  25. package/generator/pygen/preprocess/__init__.py +13 -3
  26. package/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_method_subscription_id_async.py +248 -0
  27. package/generator/test/azure/mock_api_tests/test_azure_resource_manager_method_subscription_id.py +235 -0
  28. package/generator/test/azure/requirements.txt +1 -0
  29. package/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py +40 -0
  30. package/generator/test/generic_mock_api_tests/asynctests/test_typetest_array_async.py +9 -0
  31. package/generator/test/generic_mock_api_tests/test_payload_pageable.py +29 -0
  32. package/generator/test/generic_mock_api_tests/test_typetest_array.py +8 -0
  33. package/package.json +3 -3
@@ -51,8 +51,7 @@ def main():
51
51
  venv_context = create_venv_with_package_manager(venv_path)
52
52
 
53
53
  # Install required packages - install_packages handles package manager logic
54
- install_packages(["-U", "black"], venv_context)
55
- install_packages([f"{_ROOT_DIR}/generator"], venv_context)
54
+ install_packages([f"{_ROOT_DIR}/generator"], venv_context, cwd=_ROOT_DIR)
56
55
  except Exception as e:
57
56
  # Since Python and package manager are available, any failure here should fail the npm install
58
57
  print(f"Error: Installation failed despite Python and package manager being available: {e}")
@@ -85,7 +85,7 @@ def get_install_command(package_manager: str, venv_context=None) -> list:
85
85
  raise ValueError(f"Unknown package manager: {package_manager}")
86
86
 
87
87
 
88
- def install_packages(packages: list, venv_context=None, package_manager: str = None) -> None:
88
+ def install_packages(packages: list, venv_context=None, package_manager: str = None, cwd: Path = None) -> None:
89
89
  """Install packages using the available package manager.
90
90
 
91
91
  Args:
@@ -99,7 +99,10 @@ def install_packages(packages: list, venv_context=None, package_manager: str = N
99
99
  install_cmd = get_install_command(package_manager, venv_context)
100
100
 
101
101
  try:
102
- subprocess.check_call(install_cmd + packages)
102
+ if cwd:
103
+ subprocess.check_call(install_cmd + packages, cwd=cwd)
104
+ else:
105
+ subprocess.check_call(install_cmd + packages)
103
106
  except subprocess.CalledProcessError as e:
104
107
  raise RuntimeError(f"Failed to install packages with {package_manager}: {e}")
105
108
 
@@ -27,7 +27,7 @@ def main():
27
27
  venv_context = create_venv_with_package_manager(venv_path)
28
28
 
29
29
  try:
30
- install_packages(["-r", f"{_ROOT_DIR}/generator/dev_requirements.txt"], venv_context)
30
+ install_packages(["-r", f"{_ROOT_DIR}/generator/dev_requirements.txt"], venv_context, cwd=_ROOT_DIR)
31
31
  except FileNotFoundError as e:
32
32
  raise ValueError(e.filename)
33
33
 
@@ -96,6 +96,10 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
96
96
  return self._get_attr_name(wire_name)
97
97
  return wire_name
98
98
 
99
+ @property
100
+ def next_link_is_nested(self) -> bool:
101
+ return self.yaml_data.get("nextLinkIsNested", False)
102
+
99
103
  @property
100
104
  def item_name(self) -> str:
101
105
  wire_name = self.yaml_data["itemName"]
@@ -63,7 +63,7 @@ class _ParameterBase(BaseModel, abc.ABC): # pylint: disable=too-many-instance-a
63
63
  self.wire_name: str = yaml_data.get("wireName", "")
64
64
  self.client_name: str = self.yaml_data["clientName"]
65
65
  self.optional: bool = self.yaml_data["optional"]
66
- self.implementation: str = yaml_data.get("implementation", None)
66
+ self.implementation: Optional[str] = yaml_data.get("implementation", None)
67
67
  self.location: ParameterLocation = self.yaml_data["location"]
68
68
  self.client_default_value = self.yaml_data.get("clientDefaultValue", None)
69
69
  self.in_docstring = self.yaml_data.get("inDocstring", True)
@@ -1383,6 +1383,13 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
1383
1383
  cont_token_property = "None"
1384
1384
  elif self.code_model.options["models-mode"] == "msrest":
1385
1385
  cont_token_property = f"deserialized.{next_link_name} or None"
1386
+ elif builder.next_link_is_nested:
1387
+ next_link_name_array = next_link_name.split(".")
1388
+ access = (
1389
+ "".join([f'.get("{i}", {{}})' for i in next_link_name_array[:-1]])
1390
+ + f'.get("{next_link_name_array[-1]}")'
1391
+ )
1392
+ cont_token_property = f"deserialized{access} or None"
1386
1393
  else:
1387
1394
  cont_token_property = f'deserialized.get("{next_link_name}") or None'
1388
1395
  list_type = "AsyncList" if self.async_mode else "iter"
@@ -783,7 +783,7 @@ class Serializer: # pylint: disable=too-many-public-methods
783
783
 
784
784
  # If dependencies is empty, try with current data class
785
785
  # It has to be a subclass of Enum anyway
786
- enum_type = self.dependencies.get(data_type, data.__class__)
786
+ enum_type = self.dependencies.get(data_type, cast(type, data.__class__))
787
787
  if issubclass(enum_type, Enum):
788
788
  return Serializer.serialize_enum(data, enum_obj=enum_type)
789
789
 
@@ -213,7 +213,10 @@ class PreProcessPlugin(YamlUpdatePlugin):
213
213
  and not any(t for t in ["flattened", "groupedBy"] if body_parameter.get(t))
214
214
  ):
215
215
  origin_type = body_parameter["type"]["type"]
216
- is_dpg_model = body_parameter["type"].get("base") == "dpg"
216
+ model_type = (
217
+ body_parameter["type"] if origin_type == "model" else body_parameter["type"].get("elementType", {})
218
+ )
219
+ is_dpg_model = model_type.get("base") == "dpg"
217
220
  body_parameter["type"] = {
218
221
  "type": "combined",
219
222
  "types": [body_parameter["type"]],
@@ -222,8 +225,15 @@ class PreProcessPlugin(YamlUpdatePlugin):
222
225
  if not (self.is_tsp and has_multi_part_content_type(body_parameter)):
223
226
  body_parameter["type"]["types"].append(KNOWN_TYPES["binary"])
224
227
 
225
- if origin_type == "model" and is_dpg_model and self.options["models-mode"] == "dpg":
226
- body_parameter["type"]["types"].insert(1, KNOWN_TYPES["any-object"])
228
+ if self.options["models-mode"] == "dpg" and is_dpg_model:
229
+ if origin_type == "model":
230
+ body_parameter["type"]["types"].insert(1, KNOWN_TYPES["any-object"])
231
+ else:
232
+ # dict or list
233
+ # copy the original dict / list type
234
+ any_obj_list_or_dict = copy.deepcopy(body_parameter["type"]["types"][0])
235
+ any_obj_list_or_dict["elementType"] = KNOWN_TYPES["any-object"]
236
+ body_parameter["type"]["types"].insert(1, any_obj_list_or_dict)
227
237
  code_model["types"].append(body_parameter["type"])
228
238
 
229
239
  def pad_reserved_words(self, name: str, pad_type: PadType):
@@ -96,6 +96,10 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
96
96
  return self._get_attr_name(wire_name)
97
97
  return wire_name
98
98
 
99
+ @property
100
+ def next_link_is_nested(self) -> bool:
101
+ return self.yaml_data.get("nextLinkIsNested", False)
102
+
99
103
  @property
100
104
  def item_name(self) -> str:
101
105
  wire_name = self.yaml_data["itemName"]
@@ -63,7 +63,7 @@ class _ParameterBase(BaseModel, abc.ABC): # pylint: disable=too-many-instance-a
63
63
  self.wire_name: str = yaml_data.get("wireName", "")
64
64
  self.client_name: str = self.yaml_data["clientName"]
65
65
  self.optional: bool = self.yaml_data["optional"]
66
- self.implementation: str = yaml_data.get("implementation", None)
66
+ self.implementation: Optional[str] = yaml_data.get("implementation", None)
67
67
  self.location: ParameterLocation = self.yaml_data["location"]
68
68
  self.client_default_value = self.yaml_data.get("clientDefaultValue", None)
69
69
  self.in_docstring = self.yaml_data.get("inDocstring", True)
@@ -1383,6 +1383,13 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
1383
1383
  cont_token_property = "None"
1384
1384
  elif self.code_model.options["models-mode"] == "msrest":
1385
1385
  cont_token_property = f"deserialized.{next_link_name} or None"
1386
+ elif builder.next_link_is_nested:
1387
+ next_link_name_array = next_link_name.split(".")
1388
+ access = (
1389
+ "".join([f'.get("{i}", {{}})' for i in next_link_name_array[:-1]])
1390
+ + f'.get("{next_link_name_array[-1]}")'
1391
+ )
1392
+ cont_token_property = f"deserialized{access} or None"
1386
1393
  else:
1387
1394
  cont_token_property = f'deserialized.get("{next_link_name}") or None'
1388
1395
  list_type = "AsyncList" if self.async_mode else "iter"
@@ -783,7 +783,7 @@ class Serializer: # pylint: disable=too-many-public-methods
783
783
 
784
784
  # If dependencies is empty, try with current data class
785
785
  # It has to be a subclass of Enum anyway
786
- enum_type = self.dependencies.get(data_type, data.__class__)
786
+ enum_type = self.dependencies.get(data_type, cast(type, data.__class__))
787
787
  if issubclass(enum_type, Enum):
788
788
  return Serializer.serialize_enum(data, enum_obj=enum_type)
789
789
 
@@ -213,7 +213,10 @@ class PreProcessPlugin(YamlUpdatePlugin):
213
213
  and not any(t for t in ["flattened", "groupedBy"] if body_parameter.get(t))
214
214
  ):
215
215
  origin_type = body_parameter["type"]["type"]
216
- is_dpg_model = body_parameter["type"].get("base") == "dpg"
216
+ model_type = (
217
+ body_parameter["type"] if origin_type == "model" else body_parameter["type"].get("elementType", {})
218
+ )
219
+ is_dpg_model = model_type.get("base") == "dpg"
217
220
  body_parameter["type"] = {
218
221
  "type": "combined",
219
222
  "types": [body_parameter["type"]],
@@ -222,8 +225,15 @@ class PreProcessPlugin(YamlUpdatePlugin):
222
225
  if not (self.is_tsp and has_multi_part_content_type(body_parameter)):
223
226
  body_parameter["type"]["types"].append(KNOWN_TYPES["binary"])
224
227
 
225
- if origin_type == "model" and is_dpg_model and self.options["models-mode"] == "dpg":
226
- body_parameter["type"]["types"].insert(1, KNOWN_TYPES["any-object"])
228
+ if self.options["models-mode"] == "dpg" and is_dpg_model:
229
+ if origin_type == "model":
230
+ body_parameter["type"]["types"].insert(1, KNOWN_TYPES["any-object"])
231
+ else:
232
+ # dict or list
233
+ # copy the original dict / list type
234
+ any_obj_list_or_dict = copy.deepcopy(body_parameter["type"]["types"][0])
235
+ any_obj_list_or_dict["elementType"] = KNOWN_TYPES["any-object"]
236
+ body_parameter["type"]["types"].insert(1, any_obj_list_or_dict)
227
237
  code_model["types"].append(body_parameter["type"])
228
238
 
229
239
  def pad_reserved_words(self, name: str, pad_type: PadType):
@@ -0,0 +1,248 @@
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 pytest
7
+ from azure.resourcemanager.methodsubscriptionid.aio import MethodSubscriptionIdClient
8
+ from azure.resourcemanager.methodsubscriptionid import models
9
+
10
+ SUBSCRIPTION_ID = "00000000-0000-0000-0000-000000000000"
11
+ RESOURCE_GROUP_NAME = "test-rg"
12
+
13
+
14
+ @pytest.fixture
15
+ async def client(credential, authentication_policy):
16
+ async with MethodSubscriptionIdClient(
17
+ credential,
18
+ SUBSCRIPTION_ID,
19
+ "http://localhost:3000",
20
+ authentication_policy=authentication_policy,
21
+ ) as client:
22
+ yield client
23
+
24
+
25
+ @pytest.mark.asyncio
26
+ async def test_operations_list(client):
27
+ """Test Operations.list() endpoint."""
28
+ operations = client.operations.list()
29
+ operations_list = [op async for op in operations]
30
+ assert len(operations_list) > 0
31
+
32
+ operation = operations_list[0]
33
+ assert operation.name == "Azure.ResourceManager.MethodSubscriptionId/services/read"
34
+ assert operation.is_data_action is False
35
+ assert operation.display.provider == "Azure.ResourceManager.MethodSubscriptionId"
36
+ assert operation.display.resource == "services"
37
+ assert operation.display.operation == "Lists services"
38
+ assert operation.display.description == "Lists registered services"
39
+
40
+
41
+ @pytest.mark.asyncio
42
+ async def test_two_subscription_resources_method_level_subscription_resource1_operations_get(client):
43
+ """Test get operation for SubscriptionResource1 with method-level subscription ID."""
44
+ result = await client.two_subscription_resources_method_level.subscription_resource1_operations.get(
45
+ subscription_id=SUBSCRIPTION_ID,
46
+ subscription_resource1_name="sub-resource-1",
47
+ )
48
+
49
+ assert (
50
+ result.id
51
+ == f"/subscriptions/{SUBSCRIPTION_ID}/providers/Azure.ResourceManager.MethodSubscriptionId/subscriptionResource1s/sub-resource-1"
52
+ )
53
+ assert result.name == "sub-resource-1"
54
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/subscriptionResource1s"
55
+ assert result.properties.description == "Valid subscription resource 1"
56
+ assert result.properties.provisioning_state == "Succeeded"
57
+ assert result.system_data.created_by == "AzureSDK"
58
+
59
+
60
+ @pytest.mark.asyncio
61
+ async def test_two_subscription_resources_method_level_subscription_resource1_operations_put(client):
62
+ """Test put operation for SubscriptionResource1 with method-level subscription ID."""
63
+ resource = models.SubscriptionResource1(
64
+ properties=models.SubscriptionResource1Properties(description="Valid subscription resource 1")
65
+ )
66
+
67
+ result = await client.two_subscription_resources_method_level.subscription_resource1_operations.put(
68
+ subscription_id=SUBSCRIPTION_ID,
69
+ subscription_resource1_name="sub-resource-1",
70
+ resource=resource,
71
+ )
72
+
73
+ assert (
74
+ result.id
75
+ == f"/subscriptions/{SUBSCRIPTION_ID}/providers/Azure.ResourceManager.MethodSubscriptionId/subscriptionResource1s/sub-resource-1"
76
+ )
77
+ assert result.name == "sub-resource-1"
78
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/subscriptionResource1s"
79
+ assert result.properties.description == "Valid subscription resource 1"
80
+ assert result.properties.provisioning_state == "Succeeded"
81
+ assert result.system_data.created_by == "AzureSDK"
82
+
83
+
84
+ @pytest.mark.asyncio
85
+ async def test_two_subscription_resources_method_level_subscription_resource1_operations_delete(client):
86
+ """Test delete operation for SubscriptionResource1 with method-level subscription ID."""
87
+ await client.two_subscription_resources_method_level.subscription_resource1_operations.delete(
88
+ subscription_id=SUBSCRIPTION_ID,
89
+ subscription_resource1_name="sub-resource-1",
90
+ )
91
+
92
+
93
+ @pytest.mark.asyncio
94
+ async def test_two_subscription_resources_method_level_subscription_resource2_operations_get(client):
95
+ """Test get operation for SubscriptionResource2 with method-level subscription ID."""
96
+ result = await client.two_subscription_resources_method_level.subscription_resource2_operations.get(
97
+ subscription_id=SUBSCRIPTION_ID,
98
+ subscription_resource2_name="sub-resource-2",
99
+ )
100
+
101
+ assert (
102
+ result.id
103
+ == f"/subscriptions/{SUBSCRIPTION_ID}/providers/Azure.ResourceManager.MethodSubscriptionId/subscriptionResource2s/sub-resource-2"
104
+ )
105
+ assert result.name == "sub-resource-2"
106
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/subscriptionResource2s"
107
+ assert result.properties.config_value == "test-config"
108
+ assert result.properties.provisioning_state == "Succeeded"
109
+ assert result.system_data.created_by == "AzureSDK"
110
+
111
+
112
+ @pytest.mark.asyncio
113
+ async def test_two_subscription_resources_method_level_subscription_resource2_operations_put(client):
114
+ """Test put operation for SubscriptionResource2 with method-level subscription ID."""
115
+ resource = models.SubscriptionResource2(
116
+ properties=models.SubscriptionResource2Properties(config_value="test-config")
117
+ )
118
+
119
+ result = await client.two_subscription_resources_method_level.subscription_resource2_operations.put(
120
+ subscription_id=SUBSCRIPTION_ID,
121
+ subscription_resource2_name="sub-resource-2",
122
+ resource=resource,
123
+ )
124
+
125
+ assert (
126
+ result.id
127
+ == f"/subscriptions/{SUBSCRIPTION_ID}/providers/Azure.ResourceManager.MethodSubscriptionId/subscriptionResource2s/sub-resource-2"
128
+ )
129
+ assert result.name == "sub-resource-2"
130
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/subscriptionResource2s"
131
+ assert result.properties.config_value == "test-config"
132
+ assert result.properties.provisioning_state == "Succeeded"
133
+ assert result.system_data.created_by == "AzureSDK"
134
+
135
+
136
+ @pytest.mark.asyncio
137
+ async def test_two_subscription_resources_method_level_subscription_resource2_operations_delete(client):
138
+ """Test delete operation for SubscriptionResource2 with method-level subscription ID."""
139
+ await client.two_subscription_resources_method_level.subscription_resource2_operations.delete(
140
+ subscription_id=SUBSCRIPTION_ID,
141
+ subscription_resource2_name="sub-resource-2",
142
+ )
143
+
144
+
145
+ @pytest.mark.asyncio
146
+ async def test_mixed_subscription_placement_subscription_resource_operations_get(client):
147
+ """Test get operation for SubscriptionResource in mixed placement scenario."""
148
+ result = await client.mixed_subscription_placement.subscription_resource_operations.get(
149
+ subscription_id=SUBSCRIPTION_ID,
150
+ subscription_resource_name="sub-resource",
151
+ )
152
+
153
+ assert (
154
+ result.id
155
+ == f"/subscriptions/{SUBSCRIPTION_ID}/providers/Azure.ResourceManager.MethodSubscriptionId/subscriptionResources/sub-resource"
156
+ )
157
+ assert result.name == "sub-resource"
158
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/subscriptionResources"
159
+ assert result.properties.subscription_setting == "test-sub-setting"
160
+ assert result.properties.provisioning_state == "Succeeded"
161
+ assert result.system_data.created_by == "AzureSDK"
162
+
163
+
164
+ @pytest.mark.asyncio
165
+ async def test_mixed_subscription_placement_subscription_resource_operations_put(client):
166
+ """Test put operation for SubscriptionResource in mixed placement scenario."""
167
+ resource = models.SubscriptionResource(
168
+ properties=models.SubscriptionResourceProperties(subscription_setting="test-sub-setting")
169
+ )
170
+
171
+ result = await client.mixed_subscription_placement.subscription_resource_operations.put(
172
+ subscription_id=SUBSCRIPTION_ID,
173
+ subscription_resource_name="sub-resource",
174
+ resource=resource,
175
+ )
176
+
177
+ assert (
178
+ result.id
179
+ == f"/subscriptions/{SUBSCRIPTION_ID}/providers/Azure.ResourceManager.MethodSubscriptionId/subscriptionResources/sub-resource"
180
+ )
181
+ assert result.name == "sub-resource"
182
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/subscriptionResources"
183
+ assert result.properties.subscription_setting == "test-sub-setting"
184
+ assert result.properties.provisioning_state == "Succeeded"
185
+ assert result.system_data.created_by == "AzureSDK"
186
+
187
+
188
+ @pytest.mark.asyncio
189
+ async def test_mixed_subscription_placement_subscription_resource_operations_delete(client):
190
+ """Test delete operation for SubscriptionResource in mixed placement scenario."""
191
+ await client.mixed_subscription_placement.subscription_resource_operations.delete(
192
+ subscription_id=SUBSCRIPTION_ID,
193
+ subscription_resource_name="sub-resource",
194
+ )
195
+
196
+
197
+ @pytest.mark.asyncio
198
+ async def test_mixed_subscription_placement_resource_group_resource_operations_get(client):
199
+ """Test get operation for ResourceGroupResource with client-level subscription ID."""
200
+ result = await client.mixed_subscription_placement.resource_group_resource_operations.get(
201
+ resource_group_name=RESOURCE_GROUP_NAME,
202
+ resource_group_resource_name="rg-resource",
203
+ )
204
+
205
+ assert (
206
+ result.id
207
+ == f"/subscriptions/{SUBSCRIPTION_ID}/resourceGroups/{RESOURCE_GROUP_NAME}/providers/Azure.ResourceManager.MethodSubscriptionId/resourceGroupResources/rg-resource"
208
+ )
209
+ assert result.name == "rg-resource"
210
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/resourceGroupResources"
211
+ assert result.location == "eastus"
212
+ assert result.properties.resource_group_setting == "test-setting"
213
+ assert result.properties.provisioning_state == "Succeeded"
214
+ assert result.system_data.created_by == "AzureSDK"
215
+
216
+
217
+ @pytest.mark.asyncio
218
+ async def test_mixed_subscription_placement_resource_group_resource_operations_put(client):
219
+ """Test put operation for ResourceGroupResource with client-level subscription ID."""
220
+ resource = models.ResourceGroupResource(
221
+ location="eastus", properties=models.ResourceGroupResourceProperties(resource_group_setting="test-setting")
222
+ )
223
+
224
+ result = await client.mixed_subscription_placement.resource_group_resource_operations.put(
225
+ resource_group_name=RESOURCE_GROUP_NAME,
226
+ resource_group_resource_name="rg-resource",
227
+ resource=resource,
228
+ )
229
+
230
+ assert (
231
+ result.id
232
+ == f"/subscriptions/{SUBSCRIPTION_ID}/resourceGroups/{RESOURCE_GROUP_NAME}/providers/Azure.ResourceManager.MethodSubscriptionId/resourceGroupResources/rg-resource"
233
+ )
234
+ assert result.name == "rg-resource"
235
+ assert result.type == "Azure.ResourceManager.MethodSubscriptionId/resourceGroupResources"
236
+ assert result.location == "eastus"
237
+ assert result.properties.resource_group_setting == "test-setting"
238
+ assert result.properties.provisioning_state == "Succeeded"
239
+ assert result.system_data.created_by == "AzureSDK"
240
+
241
+
242
+ @pytest.mark.asyncio
243
+ async def test_mixed_subscription_placement_resource_group_resource_operations_delete(client):
244
+ """Test delete operation for ResourceGroupResource with client-level subscription ID."""
245
+ await client.mixed_subscription_placement.resource_group_resource_operations.delete(
246
+ resource_group_name=RESOURCE_GROUP_NAME,
247
+ resource_group_resource_name="rg-resource",
248
+ )