aas-http-client 0.2.61__tar.gz → 0.3.1__tar.gz

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.

Potentially problematic release.


This version of aas-http-client might be problematic. Click here for more details.

Files changed (21) hide show
  1. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/PKG-INFO +5 -1
  2. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/client.py +52 -1
  3. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/wrapper/sdk_wrapper.py +10 -0
  4. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client.egg-info/PKG-INFO +5 -1
  5. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client.egg-info/SOURCES.txt +1 -0
  6. aas_http_client-0.3.1/aas_http_client.egg-info/requires.txt +4 -0
  7. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/pyproject.toml +7 -3
  8. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/tests/test_client.py +72 -13
  9. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/tests/test_wrapper.py +52 -12
  10. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/LICENSE +0 -0
  11. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/README.md +0 -0
  12. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/__init__.py +0 -0
  13. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/core/encoder.py +0 -0
  14. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/core/version_check.py +0 -0
  15. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/demo/demo_process.py +0 -0
  16. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/demo/logging_handler.py +0 -0
  17. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/utilities/__init__.py +0 -0
  18. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client/utilities/model_builder.py +0 -0
  19. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client.egg-info/dependency_links.txt +0 -0
  20. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/aas_http_client.egg-info/top_level.txt +0 -0
  21. {aas_http_client-0.2.61 → aas_http_client-0.3.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aas-http-client
3
- Version: 0.2.61
3
+ Version: 0.3.1
4
4
  Summary: Generic python HTTP client for communication with various types of AAS servers
5
5
  Author-email: Daniel Klein <daniel.klein@em.ag>
6
6
  License: # :em engineering methods AG Software License
@@ -108,6 +108,10 @@ License: # :em engineering methods AG Software License
108
108
  Project-URL: Homepage, https://github.com/fluid40/aas-http-client
109
109
  Description-Content-Type: text/markdown
110
110
  License-File: LICENSE
111
+ Requires-Dist: typing>=3.7.4.3
112
+ Requires-Dist: pydantic>=2.11.5
113
+ Requires-Dist: requests>=2.32.3
114
+ Requires-Dist: basyx-python-sdk>=1.2.1
111
115
  Dynamic: license-file
112
116
 
113
117
  <!-- TODO: Go through the readme and enter the information here -->
@@ -109,7 +109,7 @@ class AasHttpClient(BaseModel):
109
109
  url = f"{self.base_url}/shells"
110
110
 
111
111
  try:
112
- response = self._session.get(url, headers=HEADERS, timeout=2)
112
+ response = self._session.get(url, headers=HEADERS, timeout=10)
113
113
  logger.debug(f"Call REST API url '{response.url}'")
114
114
 
115
115
  if response.status_code != STATUS_CODE_200:
@@ -510,6 +510,57 @@ class AasHttpClient(BaseModel):
510
510
  content = response.content.decode("utf-8")
511
511
  return json.loads(content)
512
512
 
513
+ def get_submodel_element_by_path_submodel_repo(self, submodel_id: str, submodel_element_path: str) -> dict | None:
514
+ """Returns a specific submodel element from the Submodel at a specified path.
515
+
516
+ :param submodel_id: Encoded ID of the Submodel to retrieve element from
517
+ :param submodel_element_path: Path of the Submodel element to retrieve
518
+ :return: Submodel element data or None if an error occurred
519
+ """
520
+ decoded_submodel_id: str = decode_base_64(submodel_id)
521
+
522
+ url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements/{submodel_element_path}"
523
+
524
+ try:
525
+ response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
526
+ logger.debug(f"Call REST API url '{response.url}'")
527
+
528
+ if response.status_code != STATUS_CODE_200:
529
+ log_response_errors(response)
530
+ return None
531
+
532
+ except requests.exceptions.RequestException as e:
533
+ logger.error(f"Error call REST API: {e}")
534
+ return None
535
+
536
+ content = response.content.decode("utf-8")
537
+ return json.loads(content)
538
+
539
+ def delete_submodel_element_by_path_submodel_repo(self, submodel_id: str, submodel_element_path: str):
540
+ """Deletes a submodel element at a specified path within the submodel elements hierarchy.
541
+
542
+ :param submodel_id: Encoded ID of the Submodel to delete submodel element from
543
+ :param submodel_element_path: Path of the Submodel element to delete
544
+ :return: True if the deletion was successful, False otherwise
545
+ """
546
+ decoded_submodel_id: str = decode_base_64(submodel_id)
547
+
548
+ url = f"{self.base_url}/submodels/{decoded_submodel_id}/submodel-elements/{submodel_element_path}"
549
+
550
+ try:
551
+ response = self._session.delete(url, headers=HEADERS, timeout=self.time_out)
552
+ logger.debug(f"Call REST API url '{response.url}'")
553
+
554
+ if response.status_code != STATUS_CODE_204:
555
+ log_response_errors(response)
556
+ return False
557
+
558
+ except requests.exceptions.RequestException as e:
559
+ logger.error(f"Error call REST API: {e}")
560
+ return False
561
+
562
+ return True
563
+
513
564
 
514
565
  # endregion
515
566
 
@@ -253,6 +253,16 @@ class SdkWrapper:
253
253
  content: dict = self._client.post_submodel_element_submodel_repo(submodel_id, sme_data)
254
254
  return _to_object(content)
255
255
 
256
+ def get_submodel_element_by_path_submodel_repo(self, submodel_id: str, submodel_element_path: str) -> model.SubmodelElement | None:
257
+ """Returns a specific submodel element from the Submodel at a specified path.
258
+
259
+ :param submodel_id: Encoded ID of the Submodel to retrieve element from
260
+ :param submodel_element_path: Path of the Submodel element to retrieve
261
+ :return: Submodel element object or None if an error occurred
262
+ """
263
+ content: dict = self._client.get_submodel_element_by_path_submodel_repo(submodel_id, submodel_element_path)
264
+ return _to_object(content)
265
+
256
266
 
257
267
  # endregion
258
268
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aas-http-client
3
- Version: 0.2.61
3
+ Version: 0.3.1
4
4
  Summary: Generic python HTTP client for communication with various types of AAS servers
5
5
  Author-email: Daniel Klein <daniel.klein@em.ag>
6
6
  License: # :em engineering methods AG Software License
@@ -108,6 +108,10 @@ License: # :em engineering methods AG Software License
108
108
  Project-URL: Homepage, https://github.com/fluid40/aas-http-client
109
109
  Description-Content-Type: text/markdown
110
110
  License-File: LICENSE
111
+ Requires-Dist: typing>=3.7.4.3
112
+ Requires-Dist: pydantic>=2.11.5
113
+ Requires-Dist: requests>=2.32.3
114
+ Requires-Dist: basyx-python-sdk>=1.2.1
111
115
  Dynamic: license-file
112
116
 
113
117
  <!-- TODO: Go through the readme and enter the information here -->
@@ -6,6 +6,7 @@ aas_http_client/client.py
6
6
  aas_http_client.egg-info/PKG-INFO
7
7
  aas_http_client.egg-info/SOURCES.txt
8
8
  aas_http_client.egg-info/dependency_links.txt
9
+ aas_http_client.egg-info/requires.txt
9
10
  aas_http_client.egg-info/top_level.txt
10
11
  aas_http_client/core/encoder.py
11
12
  aas_http_client/core/version_check.py
@@ -0,0 +1,4 @@
1
+ typing>=3.7.4.3
2
+ pydantic>=2.11.5
3
+ requests>=2.32.3
4
+ basyx-python-sdk>=1.2.1
@@ -4,13 +4,17 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aas-http-client"
7
- version = "0.2.61"
7
+ version = "0.3.1"
8
8
  description = "Generic python HTTP client for communication with various types of AAS servers"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
11
11
  authors = [{ name = "Daniel Klein", email = "daniel.klein@em.ag" }]
12
- dependencies = []
13
-
12
+ dependencies = [
13
+ "typing>=3.7.4.3",
14
+ "pydantic>=2.11.5",
15
+ "requests>=2.32.3",
16
+ "basyx-python-sdk>=1.2.1",
17
+ ]
14
18
  [project.urls]
15
19
  Homepage = "https://github.com/fluid40/aas-http-client"
16
20
 
@@ -5,12 +5,15 @@ from basyx.aas import model
5
5
  import aas_http_client.utilities.model_builder as model_builder
6
6
  import json
7
7
  import basyx.aas.adapter.json
8
+ from urllib.parse import urlparse
8
9
 
9
- JAVA_SERVER_PORT = "8075"
10
+ JAVA_SERVER_PORTS = [8075]
11
+ PYTHON_SERVER_PORTS = [8080, 80]
10
12
 
11
13
  CONFIG_FILES = [
12
14
  "./tests/server_configs/test_dotnet_server_config.json",
13
15
  "./tests/server_configs/test_java_server_config.json",
16
+ "./tests/server_configs/test_python_server_config.json",
14
17
  ]
15
18
 
16
19
  @pytest.fixture(params=CONFIG_FILES, scope="module")
@@ -51,9 +54,39 @@ def shared_aas(shared_sm: model.Submodel) -> model.AssetAdministrationShell:
51
54
 
52
55
  return aas
53
56
 
54
- def test_001_connect(client: AasHttpClient):
57
+ def test_001a_connect(client: AasHttpClient):
55
58
  assert client is not None
56
59
 
60
+ def test_001b_delete_all_asset_administration_shells(client: AasHttpClient):
61
+ result = client.get_all_asset_administration_shells()
62
+ assert result is not None
63
+ shells = result.get("result", [])
64
+
65
+ for shell in shells:
66
+ shell_id = shell.get("id", "")
67
+ if shell_id:
68
+ delete_result = client.delete_asset_administration_shell_by_id(shell_id)
69
+ assert delete_result
70
+
71
+ shells_result = client.get_all_asset_administration_shells()
72
+ shells = shells_result.get("result", [])
73
+ assert len(shells) == 0
74
+
75
+ def test_001c_delete_all_submodels(client: AasHttpClient):
76
+ result = client.get_all_submodels()
77
+ assert result is not None
78
+ submodels = result.get("result", [])
79
+
80
+ for submodel in submodels:
81
+ submodel_id = submodel.get("id", "")
82
+ if submodel_id:
83
+ delete_result = client.delete_submodel_by_id(submodel_id)
84
+ assert delete_result
85
+
86
+ submodels_result = client.get_all_submodels()
87
+ submodels = submodels_result.get("result", [])
88
+ assert len(submodels) == 0
89
+
57
90
  def test_002_get_all_asset_administration_shells(client: AasHttpClient):
58
91
  result = client.get_all_asset_administration_shells()
59
92
  assert result is not None
@@ -113,9 +146,14 @@ def test_005a_put_asset_administration_shell_by_id(client: AasHttpClient, shared
113
146
  assert len(get_result.get("submodels", [])) == len(shared_aas.submodel)
114
147
 
115
148
  # The display name must be empty
116
- # currently not working in dotnet
149
+ # NOTE: currently not working in dotnet
117
150
  # assert len(get_result.get("displayName", {})) == 0
118
151
 
152
+ # restore to its original state
153
+ sm_data_string = json.dumps(shared_aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
154
+ sm_data = json.loads(sm_data_string)
155
+ client.put_asset_administration_shell_by_id(shared_aas.id, sm_data) # Restore original submodel
156
+
119
157
  def test_005b_put_asset_administration_shell_by_id(client: AasHttpClient, shared_aas: model.AssetAdministrationShell):
120
158
  # put with other ID
121
159
  id_short = "put_short_id"
@@ -129,15 +167,26 @@ def test_005b_put_asset_administration_shell_by_id(client: AasHttpClient, shared
129
167
  aas_data_string = json.dumps(aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
130
168
  aas_data = json.loads(aas_data_string)
131
169
 
132
- result = client.put_asset_administration_shell_by_id(shared_aas.id, aas_data)
170
+ parsed = urlparse(client.base_url)
171
+ if int(parsed.port) in PYTHON_SERVER_PORTS:
172
+ # NOTE: Python server crashes by this test
173
+ result = False
174
+ else:
175
+ result = client.put_asset_administration_shell_by_id(shared_aas.id, aas_data)
133
176
 
134
177
  assert not result
135
178
 
179
+ get_result = client.get_asset_administration_shell_by_id(shared_aas.id)
180
+
181
+ assert get_result.get("description", {})[0].get("text", "") != description_text
182
+ assert get_result.get("description", {})[0].get("text", "") == shared_aas.description.get("en", "")
183
+
136
184
  def test_006_get_asset_administration_shell_by_id_reference_aas_repository(client: AasHttpClient, shared_aas: model.AssetAdministrationShell):
137
185
  result = client.get_asset_administration_shell_by_id_reference_aas_repository(shared_aas.id)
138
186
 
139
- if JAVA_SERVER_PORT in client.base_url:
140
- # Basyx java server do not provide this endpoint
187
+ parsed = urlparse(client.base_url)
188
+ if int(parsed.port) in JAVA_SERVER_PORTS:
189
+ # NOTE: Basyx java server do not provide this endpoint
141
190
  assert result is None
142
191
  else:
143
192
  assert result is not None
@@ -175,8 +224,9 @@ def test_009_post_submodel(client: AasHttpClient, shared_sm: model.Submodel):
175
224
  def test_010_get_submodel_by_id_aas_repository(client: AasHttpClient, shared_aas: model.AssetAdministrationShell, shared_sm: model.Submodel):
176
225
  result = client.get_submodel_by_id_aas_repository(shared_aas.id, shared_sm.id)
177
226
 
178
- if JAVA_SERVER_PORT in client.base_url:
179
- # Basyx java server do not provide this endpoint
227
+ parsed = urlparse(client.base_url)
228
+ if int(parsed.port) in JAVA_SERVER_PORTS:
229
+ # NOTE: Basyx java server do not provide this endpoint
180
230
  assert result is None
181
231
  else:
182
232
  assert result is not None
@@ -207,8 +257,9 @@ def test_012_patch_submodel_by_id(client: AasHttpClient, shared_sm: model.Submod
207
257
 
208
258
  result = client.patch_submodel_by_id(shared_sm.id, sm_data)
209
259
 
210
- if JAVA_SERVER_PORT in client.base_url:
211
- # Basyx java server do not provide this endpoint
260
+ parsed = urlparse(client.base_url)
261
+ if int(parsed.port) in JAVA_SERVER_PORTS or int(parsed.port) in PYTHON_SERVER_PORTS:
262
+ # NOTE: Basyx java and python server do not provide this endpoint
212
263
  assert not result
213
264
  else:
214
265
  assert result
@@ -235,8 +286,9 @@ def test_013_put_submodel_by_id_aas_repository(client: AasHttpClient, shared_aas
235
286
 
236
287
  result = client.put_submodel_by_id_aas_repository(shared_aas.id, shared_sm.id, sm_data)
237
288
 
238
- if JAVA_SERVER_PORT in client.base_url:
239
- # Basyx java server do not provide this endpoint
289
+ parsed = urlparse(client.base_url)
290
+ if int(parsed.port) in JAVA_SERVER_PORTS:
291
+ # NOTE: Basyx java server do not provide this endpoint
240
292
  assert not result
241
293
  else:
242
294
  assert result
@@ -302,9 +354,16 @@ def test_016_post_submodel_element_submodel_repo(client: AasHttpClient, shared_s
302
354
 
303
355
  get_result = client.get_all_submodel_elements_submodel_repository(shared_sm.id)
304
356
 
305
- assert get_result is not None
306
357
  assert len(get_result.get("result", [])) == 1
307
358
 
359
+ def test_017_get_submodel_element_by_path_submodel_repo(client: AasHttpClient, shared_sm: model.Submodel, shared_sme: model.Property):
360
+ result = client.get_submodel_element_by_path_submodel_repo(shared_sm.id, shared_sme.id_short)
361
+
362
+ assert result is not None
363
+ assert result.get("idShort", "") == shared_sme.id_short
364
+ assert result.get("description", {})[0].get("text", "") == shared_sme.description.get("en", "")
365
+ assert result.get("displayName", {})[0].get("text", "") == shared_sme.display_name.get("en", "")
366
+
308
367
  def test_098_delete_asset_administration_shell_by_id(client: AasHttpClient, shared_aas: model.AssetAdministrationShell):
309
368
  result = client.delete_asset_administration_shell_by_id(shared_aas.id)
310
369
 
@@ -3,12 +3,16 @@ from pathlib import Path
3
3
  from aas_http_client.wrapper.sdk_wrapper import create_wrapper_by_config, SdkWrapper
4
4
  from basyx.aas import model
5
5
  import aas_http_client.utilities.model_builder as model_builder
6
+ from urllib.parse import urlparse
6
7
 
7
- JAVA_SERVER_PORT = "8075"
8
+ JAVA_SERVER_PORTS = [8075]
9
+ PYTHON_SERVER_PORTS = [8080, 80]
10
+ DOTNET_SERVER_PORTS = [5043]
8
11
 
9
12
  CONFIG_FILES = [
10
13
  "./tests/server_configs/test_dotnet_server_config.json",
11
- "./tests/server_configs/test_java_server_config.json"
14
+ "./tests/server_configs/test_java_server_config.json",
15
+ "./tests/server_configs/test_python_server_config.json"
12
16
  ]
13
17
 
14
18
  @pytest.fixture(params=CONFIG_FILES, scope="module")
@@ -111,6 +115,9 @@ def test_005a_put_asset_administration_shell_by_id(wrapper: SdkWrapper, shared_a
111
115
  # currently not working in dotnet
112
116
  # assert len(get_result.get("displayName", {})) == 0
113
117
 
118
+ # # restore to its original state
119
+ wrapper.put_asset_administration_shell_by_id(shared_aas.id, shared_aas) # Restore original submodel
120
+
114
121
  def test_005b_put_asset_administration_shell_by_id(wrapper: SdkWrapper, shared_aas: model.AssetAdministrationShell):
115
122
  # put with other ID
116
123
  id_short = "put_short_id"
@@ -121,10 +128,22 @@ def test_005b_put_asset_administration_shell_by_id(wrapper: SdkWrapper, shared_a
121
128
  description_text = {"en": "Updated description for unit tests"}
122
129
  aas.description = model.MultiLanguageTextType(description_text)
123
130
 
124
- result = wrapper.put_asset_administration_shell_by_id(shared_aas.id, aas)
131
+ parsed = urlparse(wrapper.base_url)
132
+ if int(parsed.port) in PYTHON_SERVER_PORTS:
133
+ # NOTE: Python server crashes by this test
134
+ result = False
135
+ else:
136
+ result = wrapper.put_asset_administration_shell_by_id(shared_aas.id, aas)
125
137
 
126
138
  assert not result
127
139
 
140
+ assert not result
141
+
142
+ shell = wrapper.get_asset_administration_shell_by_id(shared_aas.id)
143
+
144
+ assert shell.description.get("en", "") != description_text
145
+ assert shell.description.get("en", "") == shared_aas.description.get("en", "")
146
+
128
147
  def test_006_get_asset_administration_shell_by_id_reference_aas_repository(wrapper: SdkWrapper, shared_aas: model.AssetAdministrationShell):
129
148
  reference = wrapper.get_asset_administration_shell_by_id_reference_aas_repository(shared_aas.id)
130
149
 
@@ -158,7 +177,8 @@ def test_009_post_submodel(wrapper: SdkWrapper, shared_sm: model.Submodel):
158
177
  def test_010_get_submodel_by_id_aas_repository(wrapper: SdkWrapper, shared_aas: model.AssetAdministrationShell, shared_sm: model.Submodel):
159
178
  submodel = wrapper.get_submodel_by_id_aas_repository(shared_aas.id, shared_sm.id)
160
179
 
161
- if JAVA_SERVER_PORT in wrapper.base_url:
180
+ parsed = urlparse(wrapper.base_url)
181
+ if int(parsed.port) in JAVA_SERVER_PORTS:
162
182
  # Basyx java server do not provide this endpoint
163
183
  assert submodel is None
164
184
  else:
@@ -187,7 +207,8 @@ def test_012_patch_submodel_by_id(wrapper: SdkWrapper, shared_sm: model.Submodel
187
207
 
188
208
  result = wrapper.patch_submodel_by_id(shared_sm.id, sm)
189
209
 
190
- if JAVA_SERVER_PORT in wrapper.base_url:
210
+ parsed = urlparse(wrapper.base_url)
211
+ if int(parsed.port) in JAVA_SERVER_PORTS or int(parsed.port) in PYTHON_SERVER_PORTS:
191
212
  # Basyx java server do not provide this endpoint
192
213
  assert not result
193
214
  else:
@@ -214,7 +235,8 @@ def test_013_put_submodel_by_id_aas_repository(wrapper: SdkWrapper, shared_aas:
214
235
 
215
236
  result = wrapper.put_submodel_by_id_aas_repository(shared_aas.id, shared_sm.id, sm)
216
237
 
217
- if JAVA_SERVER_PORT in wrapper.base_url:
238
+ parsed = urlparse(wrapper.base_url)
239
+ if int(parsed.port) in JAVA_SERVER_PORTS:
218
240
  # Basyx java server do not provide this endpoint
219
241
  assert not result
220
242
  else:
@@ -275,20 +297,38 @@ def test_016_post_submodel_element_submodel_repo(wrapper: SdkWrapper, shared_sm:
275
297
 
276
298
  assert submodel_element is not None
277
299
 
278
- # currently only dict is returned
300
+ parsed = urlparse(wrapper.base_url)
301
+ if int(parsed.port) in DOTNET_SERVER_PORTS:
302
+ # NOTE: dotNet server provides a wrong representation of submodel elements
303
+ return
279
304
 
280
- # property: model.Property = submodel_element
305
+ assert isinstance(submodel_element, model.Property)
281
306
 
282
- # assert property.id_short == shared_sme.id_short
283
- # assert property.description.get("em", "") == shared_sme.description.get("en", "")
284
- # assert property.display_name.get("em", "") == shared_sme.display_name.get("en", "")
285
- # assert property.value == shared_sme.value
307
+ assert submodel_element.id_short == shared_sme.id_short
308
+ assert submodel_element.description.get("en", "") == shared_sme.description.get("en", "")
309
+ assert submodel_element.display_name.get("en", "") == shared_sme.display_name.get("en", "")
286
310
 
287
311
  submodel_elements = wrapper.get_all_submodel_elements_submodel_repository(shared_sm.id)
288
312
 
289
313
  assert submodel_elements is not None
290
314
  assert len(submodel_elements) == 1
291
315
 
316
+ def test_017_get_submodel_element_by_path_submodel_repo(wrapper: SdkWrapper, shared_sm: model.Submodel, shared_sme: model.Property):
317
+ submodel_element = wrapper.get_submodel_element_by_path_submodel_repo(shared_sm.id, shared_sme.id_short)
318
+
319
+ assert submodel_element is not None
320
+
321
+ parsed = urlparse(wrapper.base_url)
322
+ if int(parsed.port) in DOTNET_SERVER_PORTS:
323
+ # NOTE: dotNet server provides a wrong representation of submodel elements
324
+ return
325
+
326
+ assert isinstance(submodel_element, model.Property)
327
+
328
+ assert submodel_element.id_short == shared_sme.id_short
329
+ assert submodel_element.description.get("en", "") == shared_sme.description.get("en", "")
330
+ assert submodel_element.display_name.get("en", "") == shared_sme.display_name.get("en", "")
331
+
292
332
  def test_098_delete_asset_administration_shell_by_id(wrapper: SdkWrapper, shared_aas: model.AssetAdministrationShell):
293
333
  result = wrapper.delete_asset_administration_shell_by_id(shared_aas.id)
294
334