aas-http-client 0.1.5__tar.gz → 0.1.6__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 (22) hide show
  1. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/PKG-INFO +5 -4
  2. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/README.md +4 -3
  3. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/__init__.py +3 -1
  4. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/client.py +7 -29
  5. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/utilities/model_builder.py +8 -2
  6. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client.egg-info/PKG-INFO +5 -4
  7. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client.egg-info/SOURCES.txt +2 -1
  8. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/pyproject.toml +1 -1
  9. aas_http_client-0.1.6/tests/test_client_dotnet_server.py +290 -0
  10. aas_http_client-0.1.6/tests/test_client_java_server.py +263 -0
  11. aas_http_client-0.1.5/tests/test_client.py +0 -21
  12. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/LICENSE +0 -0
  13. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/core/encoder.py +0 -0
  14. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/core/version_check.py +0 -0
  15. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/demo/demo_process.py +0 -0
  16. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/demo/logging_handler.py +0 -0
  17. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/utilities/__init__.py +0 -0
  18. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/wrapper/python_sdk_wrapper_tmp.py +0 -0
  19. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client/wrapper/sdk_wrapper.py +0 -0
  20. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client.egg-info/dependency_links.txt +0 -0
  21. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/aas_http_client.egg-info/top_level.txt +0 -0
  22. {aas_http_client-0.1.5 → aas_http_client-0.1.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aas-http-client
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Generic HTTP client for communicating with various types of AAS servers
5
5
  Author-email: Daniel Klein <daniel.klein@em.ag>
6
6
  License: MIT License
@@ -32,20 +32,19 @@ Dynamic: license-file
32
32
 
33
33
  <!-- TODO: Go through the readme and enter the information here -->
34
34
 
35
- # BaSyx Python PoC
35
+ # AAS HTTP Client
36
36
 
37
37
  <div align="center">
38
38
  <!-- change this to your projects logo if you have on.
39
39
  If you don't have one it might be worth trying chatgpt dall-e to create one for you...
40
40
  -->
41
- <img src="docs/assets/fluid_logo.svg" alt="basyx_python_poc" width=500 />
41
+ <img src="docs/assets/fluid_logo.svg" alt="aas_http_client" width=500 />
42
42
  </div>
43
43
 
44
44
  ---
45
45
 
46
46
  [![License: em](https://img.shields.io/badge/license-emSL-%23f8a602?label=License&labelColor=%23992b2e)](LICENSES/LicenseRef-em.txt)
47
47
  [![CI](https://github.com/engineering-methods/basyx_python_poc/actions/workflows/ci.yml/badge.svg?branch=master&cache-bust=1)](https://github.com/engineering-methods/basyx_python_poc/actions)
48
- [![codecov](https://codecov.io/gh/engineering-methods/basyx_python_poc/branch/master/graph/badge.svg)](https://codecov.io/gh/engineering-methods/basyx_python_poc)
49
48
 
50
49
  Proof of concept for a AAS application using the BaSyx Python SDK and Python AAS Server.
51
50
 
@@ -58,3 +57,5 @@ Proof of concept for a AAS application using the BaSyx Python SDK and Python AAS
58
57
  👨‍⚕️ [Troubleshooting](docs/troubleshooting.md)
59
58
 
60
59
  🤖 [Releases](https://github.com/engineering-methods/basyx_python_poc/releases)
60
+
61
+ 📦 [Pypi Packages](https://pypi.org/project/aas-http-client/)
@@ -1,19 +1,18 @@
1
1
  <!-- TODO: Go through the readme and enter the information here -->
2
2
 
3
- # BaSyx Python PoC
3
+ # AAS HTTP Client
4
4
 
5
5
  <div align="center">
6
6
  <!-- change this to your projects logo if you have on.
7
7
  If you don't have one it might be worth trying chatgpt dall-e to create one for you...
8
8
  -->
9
- <img src="docs/assets/fluid_logo.svg" alt="basyx_python_poc" width=500 />
9
+ <img src="docs/assets/fluid_logo.svg" alt="aas_http_client" width=500 />
10
10
  </div>
11
11
 
12
12
  ---
13
13
 
14
14
  [![License: em](https://img.shields.io/badge/license-emSL-%23f8a602?label=License&labelColor=%23992b2e)](LICENSES/LicenseRef-em.txt)
15
15
  [![CI](https://github.com/engineering-methods/basyx_python_poc/actions/workflows/ci.yml/badge.svg?branch=master&cache-bust=1)](https://github.com/engineering-methods/basyx_python_poc/actions)
16
- [![codecov](https://codecov.io/gh/engineering-methods/basyx_python_poc/branch/master/graph/badge.svg)](https://codecov.io/gh/engineering-methods/basyx_python_poc)
17
16
 
18
17
  Proof of concept for a AAS application using the BaSyx Python SDK and Python AAS Server.
19
18
 
@@ -26,3 +25,5 @@ Proof of concept for a AAS application using the BaSyx Python SDK and Python AAS
26
25
  👨‍⚕️ [Troubleshooting](docs/troubleshooting.md)
27
26
 
28
27
  🤖 [Releases](https://github.com/engineering-methods/basyx_python_poc/releases)
28
+
29
+ 📦 [Pypi Packages](https://pypi.org/project/aas-http-client/)
@@ -14,7 +14,9 @@ __package__ = "aas-http-client"
14
14
 
15
15
  from aas_http_client.core.version_check import check_for_update
16
16
  from aas_http_client.client import create_client_by_config, create_client_by_url, AasHttpClient
17
+ from aas_http_client.utilities import model_builder
18
+ from aas_http_client.wrapper.sdk_wrapper import create_wrapper_by_config, create_wrapper_by_url, SdkWrapper
17
19
 
18
20
  check_for_update()
19
21
 
20
- __all__ = ["create_client_by_config", "create_client_by_url", "AasHttpClient"]
22
+ __all__ = ["create_client_by_config", "create_client_by_url", "AasHttpClient", "model_builder", "create_wrapper_by_config", "create_wrapper_by_url", "SdkWrapper"]
@@ -166,7 +166,7 @@ class AasHttpClient(BaseModel):
166
166
 
167
167
  return True
168
168
 
169
- def put_shells_submodels(self, aas_id: str, submodel_id: str, submodel_data: dict) -> bool:
169
+ def put_shells_submodels_by_id(self, aas_id: str, submodel_id: str, submodel_data: dict) -> bool:
170
170
  """Update a submodel by its ID for a specific Asset Administration Shell (AAS).
171
171
 
172
172
  :param aas_id: ID of the AAS to update the submodel for
@@ -257,7 +257,7 @@ class AasHttpClient(BaseModel):
257
257
  ref_dict_string = response.content.decode("utf-8")
258
258
  return json.loads(ref_dict_string, cls=basyx.aas.adapter.json.AASFromJsonDecoder)
259
259
 
260
- def get_shells_submodels(self, aas_id: str, submodel_id: str) -> Submodel | None:
260
+ def get_shells_submodels_by_id(self, aas_id: str, submodel_id: str) -> Submodel | None:
261
261
  """Get a submodel by its ID for a specific Asset Administration Shell (AAS).
262
262
 
263
263
  :param aas_id: ID of the AAS to retrieve the submodel from
@@ -268,6 +268,7 @@ class AasHttpClient(BaseModel):
268
268
  decoded_submodel_id: str = decode_base_64(submodel_id)
269
269
 
270
270
  url = f"{self.base_url}/shells/{decoded_aas_id}/submodels/{decoded_submodel_id}"
271
+ #/shells/{aasIdentifier}/submodels/{submodelIdentifier}
271
272
 
272
273
  try:
273
274
  response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
@@ -307,7 +308,7 @@ class AasHttpClient(BaseModel):
307
308
 
308
309
  return True
309
310
 
310
- def post_submodels(self, submodel_data: dict) -> bool:
311
+ def post_submodels(self, submodel_data: dict) -> dict:
311
312
  """Post a submodel to the REST API.
312
313
 
313
314
  :param submodel_data: Json data of the Submodel to post
@@ -327,9 +328,10 @@ class AasHttpClient(BaseModel):
327
328
  logger.error(f"Error call REST API: {e}")
328
329
  return False
329
330
 
330
- return True
331
+ content = response.content.decode("utf-8")
332
+ return json.loads(content)
331
333
 
332
- def put_submodels(self, identifier: str, submodel_data: dict) -> bool:
334
+ def put_submodels_by_id(self, identifier: str, submodel_data: dict) -> bool:
333
335
  """Update a submodel by its ID in the REST API.
334
336
 
335
337
  :param identifier: Identifier of the submodel to update
@@ -353,30 +355,6 @@ class AasHttpClient(BaseModel):
353
355
 
354
356
  return True
355
357
 
356
- def get_submodel_by_id(self, submodel_id: str) -> dict | None:
357
- """Get a submodel by its ID from the REST API.
358
-
359
- :param submodel_id: ID of the submodel to retrieve
360
- :return: Submodel object or None if an error occurred
361
- """
362
- decoded_submodel_id: str = decode_base_64(submodel_id)
363
- url = f"{self.base_url}/submodels/{decoded_submodel_id}"
364
-
365
- try:
366
- response = self._session.get(url, headers=HEADERS, timeout=self.time_out)
367
- logger.debug(f"Call REST API url '{response.url}'")
368
-
369
- if response.status_code != STATUS_CODE_200:
370
- log_response_errors(response)
371
- return None
372
-
373
- except requests.exceptions.RequestException as e:
374
- logger.error(f"Error call REST API: {e}")
375
- return None
376
-
377
- content = response.content.decode("utf-8")
378
- return json.loads(content)
379
-
380
358
  def get_submodels(self) -> list[dict] | None:
381
359
  """Get all submodels from the REST API.
382
360
 
@@ -34,7 +34,10 @@ def create_base_submodel(id_short: str, namespace: str = "basyx_python_aas_serve
34
34
  :param description: description of the Submodel, defaults to ""
35
35
  :return: Submodel instance
36
36
  """
37
- identifier = f"{namespace}/{id_short}"
37
+ if namespace:
38
+ identifier = f"{namespace}/{id_short}"
39
+ else:
40
+ identifier = id_short
38
41
  sm = Submodel(identifier)
39
42
  sm.id_short = id_short
40
43
 
@@ -101,7 +104,10 @@ def create_base_asset_information(id_short: str, namespace: str = "basyx_python_
101
104
  :param namespace: namespace of the AssetInformation, defaults to "basyx_python_aas_server"
102
105
  :return: AssetInformation instance
103
106
  """
104
- identifier = f"{namespace}/{id_short}"
107
+ if namespace:
108
+ identifier = f"{namespace}/{id_short}"
109
+ else:
110
+ identifier = id_short
105
111
  return AssetInformation(AssetKind.INSTANCE, identifier)
106
112
 
107
113
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aas-http-client
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Generic HTTP client for communicating with various types of AAS servers
5
5
  Author-email: Daniel Klein <daniel.klein@em.ag>
6
6
  License: MIT License
@@ -32,20 +32,19 @@ Dynamic: license-file
32
32
 
33
33
  <!-- TODO: Go through the readme and enter the information here -->
34
34
 
35
- # BaSyx Python PoC
35
+ # AAS HTTP Client
36
36
 
37
37
  <div align="center">
38
38
  <!-- change this to your projects logo if you have on.
39
39
  If you don't have one it might be worth trying chatgpt dall-e to create one for you...
40
40
  -->
41
- <img src="docs/assets/fluid_logo.svg" alt="basyx_python_poc" width=500 />
41
+ <img src="docs/assets/fluid_logo.svg" alt="aas_http_client" width=500 />
42
42
  </div>
43
43
 
44
44
  ---
45
45
 
46
46
  [![License: em](https://img.shields.io/badge/license-emSL-%23f8a602?label=License&labelColor=%23992b2e)](LICENSES/LicenseRef-em.txt)
47
47
  [![CI](https://github.com/engineering-methods/basyx_python_poc/actions/workflows/ci.yml/badge.svg?branch=master&cache-bust=1)](https://github.com/engineering-methods/basyx_python_poc/actions)
48
- [![codecov](https://codecov.io/gh/engineering-methods/basyx_python_poc/branch/master/graph/badge.svg)](https://codecov.io/gh/engineering-methods/basyx_python_poc)
49
48
 
50
49
  Proof of concept for a AAS application using the BaSyx Python SDK and Python AAS Server.
51
50
 
@@ -58,3 +57,5 @@ Proof of concept for a AAS application using the BaSyx Python SDK and Python AAS
58
57
  👨‍⚕️ [Troubleshooting](docs/troubleshooting.md)
59
58
 
60
59
  🤖 [Releases](https://github.com/engineering-methods/basyx_python_poc/releases)
60
+
61
+ 📦 [Pypi Packages](https://pypi.org/project/aas-http-client/)
@@ -15,4 +15,5 @@ aas_http_client/utilities/__init__.py
15
15
  aas_http_client/utilities/model_builder.py
16
16
  aas_http_client/wrapper/python_sdk_wrapper_tmp.py
17
17
  aas_http_client/wrapper/sdk_wrapper.py
18
- tests/test_client.py
18
+ tests/test_client_dotnet_server.py
19
+ tests/test_client_java_server.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aas-http-client"
7
- version = "0.1.5"
7
+ version = "0.1.6"
8
8
  description = "Generic HTTP client for communicating with various types of AAS servers"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -0,0 +1,290 @@
1
+ import pytest
2
+ from pathlib import Path
3
+ from aas_http_client.client import create_client_by_config, AasHttpClient
4
+ from basyx.aas.model import AssetAdministrationShell, Submodel, MultiLanguageTextType
5
+ import aas_http_client.utilities.model_builder as model_builder
6
+ import json
7
+ import basyx.aas.adapter.json
8
+
9
+ @pytest.fixture(scope="module")
10
+ def client() -> AasHttpClient:
11
+ try:
12
+ file = Path("./tests/server_configs/test_dotnet_server_config.json").resolve()
13
+
14
+ if not file.exists():
15
+ raise FileNotFoundError(f"Configuration file {file} does not exist.")
16
+
17
+ client = create_client_by_config(file, password="")
18
+ except Exception as e:
19
+ raise RuntimeError("Unable to connect to server.")
20
+
21
+ shells = client.get_shells()
22
+ if shells is None:
23
+ raise RuntimeError("No shells found on server. Please check the server configuration.")
24
+
25
+ for shell in shells.get("result", []):
26
+ id = shell.get("id", "")
27
+ client.delete_shells_by_id(id)
28
+
29
+ submodels = client.get_submodels()
30
+ if submodels is None:
31
+ raise RuntimeError("No submodels found on server. Please check the server configuration.")
32
+
33
+ for submodel in submodels.get("result", []):
34
+ id = submodel.get("id", "")
35
+ client.delete_submodels_by_id(id)
36
+
37
+ return client
38
+
39
+ @pytest.fixture(scope="module")
40
+ def shared_sm() -> Submodel:
41
+ # create a Submodel
42
+ return model_builder.create_base_submodel("sm_http_client_unit_tests", "")
43
+
44
+ @pytest.fixture(scope="module")
45
+ def shared_aas(client: AasHttpClient, shared_sm: Submodel) -> AssetAdministrationShell:
46
+ # create an AAS
47
+ aas = model_builder.create_base_ass(id_short="aas_http_client_unit_tests", namespace="")
48
+
49
+ # add Submodel to AAS
50
+ model_builder.add_submodel_to_aas(aas, shared_sm)
51
+
52
+ return aas
53
+
54
+ def test_001_connect(client: AasHttpClient):
55
+ assert client is not None
56
+
57
+ def test_002_get_shells(client: AasHttpClient):
58
+ result = client.get_shells()
59
+ assert result is not None
60
+ shells = result.get("result", [])
61
+ assert len(shells) == 0
62
+
63
+ def test_003_post_shells(client: AasHttpClient, shared_aas: AssetAdministrationShell):
64
+ aas_data_string = json.dumps(shared_aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
65
+ aas_data = json.loads(aas_data_string)
66
+ result = client.post_shells(aas_data)
67
+
68
+ assert result is not None
69
+ result_id_short = result.get("idShort", "")
70
+ assert result_id_short == shared_aas.id_short
71
+
72
+ get_result = client.get_shells()
73
+ assert get_result is not None
74
+ shells = get_result.get("result", [])
75
+ assert len(shells) == 1
76
+ assert shells[0].get("idShort", "") == shared_aas.id_short
77
+
78
+ def test_004a_get_shell_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
79
+ result = client.get_shells_by_id(shared_aas.id)
80
+
81
+ assert result is not None
82
+ assert result.get("idShort", "") == shared_aas.id_short
83
+
84
+ def test_004b_get_shell_by_id_not_found(client: AasHttpClient):
85
+ result = client.get_shells_by_id("non_existent_id")
86
+
87
+ assert result is None
88
+
89
+ def test_005a_put_shells(client: AasHttpClient, shared_aas: AssetAdministrationShell):
90
+ aas = AssetAdministrationShell(id_=shared_aas.asset_information.global_asset_id, asset_information=shared_aas.asset_information)
91
+ aas.id_short = shared_aas.id_short
92
+
93
+ description_text = "Put description for unit tests"
94
+ aas.description = MultiLanguageTextType({"en": description_text})
95
+ aas.submodel = shared_aas.submodel # Keep existing submodels
96
+
97
+ aas_data_string = json.dumps(aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
98
+ aas_data = json.loads(aas_data_string)
99
+
100
+ result = client.put_shells(shared_aas.id, aas_data)
101
+
102
+ assert result
103
+
104
+ get_result = client.get_shells_by_id(shared_aas.id)
105
+
106
+ assert get_result is not None
107
+ assert get_result.get("idShort", "") == shared_aas.id_short
108
+ assert get_result.get("id", "") == shared_aas.id
109
+ # description must have changed
110
+ assert get_result.get("description", {})[0].get("text", "") == description_text
111
+ assert get_result.get("description", {})[0].get("text", "") != shared_aas.description.get("en", "")
112
+ # submodels must be retained
113
+ assert len(get_result.get("submodels", [])) == len(shared_aas.submodel)
114
+
115
+ # The display name must be empty
116
+ # currently not working in dotnet
117
+ # assert len(get_result.get("displayName", {})) == 0
118
+
119
+ def test_005b_put_shells_with_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
120
+ # put with other ID
121
+ id_short = "put_short_id"
122
+ asset_info = model_builder.create_base_asset_information(id_short)
123
+ aas = AssetAdministrationShell(id_=asset_info.global_asset_id, asset_information=asset_info)
124
+ aas.id_short = id_short
125
+
126
+ description_text = {"en": "Updated description for unit tests"}
127
+ aas.description = MultiLanguageTextType(description_text)
128
+
129
+ aas_data_string = json.dumps(shared_aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
130
+ aas_data = json.loads(aas_data_string)
131
+
132
+ aas_data["id"] = "updated_id" # Ensure the id is included in the update
133
+
134
+ result = client.put_shells(shared_aas.id, aas_data)
135
+
136
+ assert not result
137
+
138
+ def test_006_get_shells_reference_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
139
+ result = client.get_shells_reference_by_id(shared_aas.id)
140
+
141
+ assert result
142
+ keys = result.get("keys", [])
143
+ assert len(keys) == 1
144
+ assert keys[0].get("value", "") == shared_aas.id
145
+
146
+ def test_007_get_shells_submodels_by_id_not_posted(client: AasHttpClient, shared_aas: AssetAdministrationShell, shared_sm: Submodel):
147
+ result = client.get_shells_submodels_by_id(shared_aas.id, shared_sm.id)
148
+
149
+ assert result is None
150
+
151
+ def test_008_get_submodels(client: AasHttpClient):
152
+ result = client.get_submodels()
153
+ assert result
154
+ submodels = result.get("result", [])
155
+ assert len(submodels) == 0
156
+
157
+ def test_009_post_submodels(client: AasHttpClient, shared_sm: Submodel):
158
+ sm_data_string = json.dumps(shared_sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
159
+ sm_data = json.loads(sm_data_string)
160
+
161
+ result = client.post_submodels(sm_data)
162
+
163
+ assert result is not None
164
+ result_id_short = result.get("idShort", "")
165
+ assert result_id_short == shared_sm.id_short
166
+
167
+ get_result = client.get_submodels()
168
+ assert get_result is not None
169
+ submodels = get_result.get("result", [])
170
+ assert len(submodels) == 1
171
+ assert submodels[0].get("idShort", "") == shared_sm.id_short
172
+
173
+ def test_010_get_shells_submodels_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell, shared_sm: Submodel):
174
+ result = client.get_shells_submodels_by_id(shared_aas.id, shared_sm.id)
175
+
176
+ assert result is not None
177
+ result_id_short = result.get("idShort", "")
178
+ assert result_id_short == shared_sm.id_short
179
+
180
+ def test_011a_get_submodels_by_id(client: AasHttpClient, shared_sm: Submodel):
181
+ result = client.get_submodels_by_id(shared_sm.id)
182
+
183
+ assert result is not None
184
+ result_id_short = result.get("idShort", "")
185
+ assert result_id_short == shared_sm.id_short
186
+
187
+ def test_011b_get_submodels_by_id_not_found(client: AasHttpClient):
188
+ result = client.get_submodels_by_id("non_existent_id")
189
+
190
+ assert result is None
191
+
192
+ def test_012_patch_submodel_by_id(client: AasHttpClient, shared_sm: Submodel):
193
+ sm = Submodel(shared_sm.id_short)
194
+ sm.id_short = shared_sm.id_short
195
+
196
+ description_text = "Patched description for unit tests"
197
+ sm.description = MultiLanguageTextType({"en": description_text})
198
+
199
+ sm_data_string = json.dumps(sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
200
+ sm_data = json.loads(sm_data_string)
201
+
202
+ result = client.patch_submodel_by_id(shared_sm.id, sm_data)
203
+
204
+ assert result
205
+
206
+ get_result = client.get_submodels_by_id(shared_sm.id)
207
+ assert get_result is not None
208
+ assert get_result.get("idShort", "") == shared_sm.id_short
209
+ assert get_result.get("id", "") == shared_sm.id
210
+ # Only the description may change in patch.
211
+ assert get_result.get("description", {})[0].get("text", "") == description_text
212
+ assert get_result.get("description", {})[0].get("text", "") != shared_sm.description.get("en", "")
213
+ # The display name must remain the same.
214
+ assert get_result.get("displayName", {})[0].get("text", "") == shared_sm.display_name.get("en", "")
215
+
216
+ def test_013_put_shells_submodels_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell, shared_sm: Submodel):
217
+ sm = Submodel(shared_sm.id_short)
218
+ sm.id_short = shared_sm.id_short
219
+
220
+ description_text = "Put via shell description for unit tests"
221
+ sm.description = MultiLanguageTextType({"en": description_text})
222
+
223
+ sm_data_string = json.dumps(sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
224
+ sm_data = json.loads(sm_data_string)
225
+
226
+ result = client.put_shells_submodels_by_id(shared_aas.id, shared_sm.id, sm_data)
227
+
228
+ assert result
229
+
230
+ get_result = client.get_shells_submodels_by_id(shared_aas.id, shared_sm.id)
231
+ assert get_result is not None
232
+ assert get_result.get("idShort", "") == shared_sm.id_short
233
+ assert get_result.get("id", "") == shared_sm.id
234
+ # description must have changed
235
+ assert get_result.get("description", {})[0].get("text", "") == description_text
236
+ assert get_result.get("description", {})[0].get("text", "") != shared_sm.description.get("en", "")
237
+ assert len(get_result.get("displayName", {})) == 0
238
+
239
+ # restore to its original state
240
+ sm_data_string = json.dumps(shared_sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
241
+ sm_data = json.loads(sm_data_string)
242
+ client.put_shells_submodels_by_id(shared_aas.id, shared_sm.id, sm_data) # Restore original submodel
243
+
244
+ def test_014_put_submodels_by_id(client: AasHttpClient, shared_sm: Submodel):
245
+ sm = Submodel(shared_sm.id_short)
246
+ sm.id_short = shared_sm.id_short
247
+
248
+ description_text = "Put description for unit tests"
249
+ sm.description = MultiLanguageTextType({"en": description_text})
250
+
251
+ sm_data_string = json.dumps(sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
252
+ sm_data = json.loads(sm_data_string)
253
+
254
+ result = client.put_submodels_by_id(shared_sm.id, sm_data)
255
+
256
+ assert result
257
+
258
+ get_result = client.get_submodels_by_id(shared_sm.id)
259
+ assert get_result is not None
260
+ assert get_result.get("idShort", "") == shared_sm.id_short
261
+ assert get_result.get("id", "") == shared_sm.id
262
+ # description must have changed
263
+ assert get_result.get("description", {})[0].get("text", "") == description_text
264
+ assert get_result.get("description", {})[0].get("text", "") != shared_sm.description.get("en", "")
265
+ assert len(get_result.get("displayName", {})) == 0
266
+
267
+ # restore to its original state
268
+ sm_data_string = json.dumps(shared_sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
269
+ sm_data = json.loads(sm_data_string)
270
+ client.put_submodels_by_id(shared_sm.id, sm_data) # Restore original submodel
271
+
272
+ def test_098_delete_shells_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
273
+ result = client.delete_shells_by_id(shared_aas.id)
274
+
275
+ assert result
276
+
277
+ get_result = client.get_shells()
278
+ assert get_result is not None
279
+ shells = get_result.get("result", [])
280
+ assert len(shells) == 0
281
+
282
+ def test_099_delete_submodel_by_id(client: AasHttpClient, shared_sm: Submodel):
283
+ result = client.delete_submodels_by_id(shared_sm.id)
284
+
285
+ assert result
286
+
287
+ get_result = client.get_submodels()
288
+ assert get_result is not None
289
+ submodels = get_result.get("result", [])
290
+ assert len(submodels) == 0
@@ -0,0 +1,263 @@
1
+ import pytest
2
+ from pathlib import Path
3
+ from aas_http_client.client import create_client_by_config, AasHttpClient
4
+ from basyx.aas.model import AssetAdministrationShell, Submodel, MultiLanguageTextType
5
+ import aas_http_client.utilities.model_builder as model_builder
6
+ import json
7
+ import basyx.aas.adapter.json
8
+
9
+ @pytest.fixture(scope="module")
10
+ def client() -> AasHttpClient:
11
+ try:
12
+ file = Path("./tests/server_configs/test_java_server_config.json").resolve()
13
+
14
+ if not file.exists():
15
+ raise FileNotFoundError(f"Configuration file {file} does not exist.")
16
+
17
+ client = create_client_by_config(file, password="")
18
+ except Exception as e:
19
+ raise RuntimeError("Unable to connect to server.")
20
+
21
+ shells = client.get_shells()
22
+ if shells is None:
23
+ raise RuntimeError("No shells found on server. Please check the server configuration.")
24
+
25
+ for shell in shells.get("result", []):
26
+ id = shell.get("id", "")
27
+ client.delete_shells_by_id(id)
28
+
29
+ submodels = client.get_submodels()
30
+ if submodels is None:
31
+ raise RuntimeError("No submodels found on server. Please check the server configuration.")
32
+
33
+ for submodel in submodels.get("result", []):
34
+ id = submodel.get("id", "")
35
+ client.delete_submodels_by_id(id)
36
+
37
+ return client
38
+
39
+ @pytest.fixture(scope="module")
40
+ def shared_sm() -> Submodel:
41
+ # create a Submodel
42
+ return model_builder.create_base_submodel("sm_http_client_unit_tests", "")
43
+
44
+ @pytest.fixture(scope="module")
45
+ def shared_aas(client: AasHttpClient, shared_sm: Submodel) -> AssetAdministrationShell:
46
+ # create an AAS
47
+ aas = model_builder.create_base_ass(id_short="aas_http_client_unit_tests", namespace="")
48
+
49
+ # add Submodel to AAS
50
+ model_builder.add_submodel_to_aas(aas, shared_sm)
51
+
52
+ return aas
53
+
54
+ def test_001_connect(client: AasHttpClient):
55
+ assert client is not None
56
+
57
+ def test_002_get_shells(client: AasHttpClient):
58
+ result = client.get_shells()
59
+ assert result is not None
60
+ shells = result.get("result", [])
61
+ assert len(shells) == 0
62
+
63
+ def test_003_post_shells(client: AasHttpClient, shared_aas: AssetAdministrationShell):
64
+ aas_data_string = json.dumps(shared_aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
65
+ aas_data = json.loads(aas_data_string)
66
+ result = client.post_shells(aas_data)
67
+
68
+ assert result is not None
69
+ result_id_short = result.get("idShort", "")
70
+ assert result_id_short == shared_aas.id_short
71
+
72
+ get_result = client.get_shells()
73
+ assert get_result is not None
74
+ shells = get_result.get("result", [])
75
+ assert len(shells) == 1
76
+ assert shells[0].get("idShort", "") == shared_aas.id_short
77
+
78
+ def test_004a_get_shell_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
79
+ result = client.get_shells_by_id(shared_aas.id)
80
+
81
+ assert result is not None
82
+ assert result.get("idShort", "") == shared_aas.id_short
83
+
84
+ def test_004b_get_shell_by_id_not_found(client: AasHttpClient):
85
+ result = client.get_shells_by_id("non_existent_id")
86
+
87
+ assert result is None
88
+
89
+ def test_005a_put_shells(client: AasHttpClient, shared_aas: AssetAdministrationShell):
90
+ aas = AssetAdministrationShell(id_=shared_aas.asset_information.global_asset_id, asset_information=shared_aas.asset_information)
91
+ aas.id_short = shared_aas.id_short
92
+
93
+ description_text = "Put description for unit tests"
94
+ aas.description = MultiLanguageTextType({"en": description_text})
95
+ aas.submodel = shared_aas.submodel # Keep existing submodels
96
+
97
+ aas_data_string = json.dumps(aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
98
+ aas_data = json.loads(aas_data_string)
99
+
100
+ result = client.put_shells(shared_aas.id, aas_data)
101
+
102
+ assert result
103
+
104
+ get_result = client.get_shells_by_id(shared_aas.id)
105
+
106
+ assert get_result is not None
107
+ assert get_result.get("idShort", "") == shared_aas.id_short
108
+ assert get_result.get("id", "") == shared_aas.id
109
+ # description must have changed
110
+ assert get_result.get("description", {})[0].get("text", "") == description_text
111
+ assert get_result.get("description", {})[0].get("text", "") != shared_aas.description.get("en", "")
112
+ # submodels must be retained
113
+ assert len(get_result.get("submodels", [])) == len(shared_aas.submodel)
114
+ # The display name must be empty
115
+ assert len(get_result.get("displayName", {})) == 0
116
+
117
+ def test_005b_put_shells_with_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
118
+ # put with other ID
119
+ id_short = "put_short_id"
120
+ asset_info = model_builder.create_base_asset_information(id_short)
121
+ aas = AssetAdministrationShell(id_=asset_info.global_asset_id, asset_information=asset_info)
122
+ aas.id_short = id_short
123
+
124
+ description_text = {"en": "Updated description for unit tests"}
125
+ aas.description = MultiLanguageTextType(description_text)
126
+
127
+ aas_data_string = json.dumps(shared_aas, cls=basyx.aas.adapter.json.AASToJsonEncoder)
128
+ aas_data = json.loads(aas_data_string)
129
+
130
+ aas_data["id"] = "updated_id" # Ensure the id is included in the update
131
+
132
+ result = client.put_shells(shared_aas.id, aas_data)
133
+
134
+ assert not result
135
+
136
+ def test_006_get_shells_reference_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
137
+ result = client.get_shells_reference_by_id(shared_aas.id)
138
+
139
+ # Basyx java server do not provide this endpoint
140
+ assert not result
141
+
142
+ def test_007_get_shells_submodels_by_id_not_posted(client: AasHttpClient, shared_aas: AssetAdministrationShell, shared_sm: Submodel):
143
+ result = client.get_shells_submodels_by_id(shared_aas.id, shared_sm.id)
144
+
145
+ assert result is None
146
+
147
+ def test_008_get_submodels(client: AasHttpClient):
148
+ result = client.get_submodels()
149
+
150
+ assert result
151
+ submodels = result.get("result", [])
152
+ assert len(submodels) == 0
153
+
154
+ def test_009_post_submodels(client: AasHttpClient, shared_sm: Submodel):
155
+ sm_data_string = json.dumps(shared_sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
156
+ sm_data = json.loads(sm_data_string)
157
+
158
+ result = client.post_submodels(sm_data)
159
+
160
+ assert result is not None
161
+ result_id_short = result.get("idShort", "")
162
+ assert result_id_short == shared_sm.id_short
163
+
164
+ get_result = client.get_submodels()
165
+ assert get_result is not None
166
+ submodels = get_result.get("result", [])
167
+ assert len(submodels) == 1
168
+ assert submodels[0].get("idShort", "") == shared_sm.id_short
169
+
170
+ def test_010_get_shells_submodels_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell, shared_sm: Submodel):
171
+ result = client.get_shells_submodels_by_id(shared_aas.id, shared_sm.id)
172
+
173
+ # Basyx java server do not provide this endpoint
174
+ assert result is None
175
+
176
+ def test_011a_get_submodels_by_id(client: AasHttpClient, shared_sm: Submodel):
177
+ result = client.get_submodels_by_id(shared_sm.id)
178
+
179
+ assert result is not None
180
+ result_id_short = result.get("idShort", "")
181
+ assert result_id_short == shared_sm.id_short
182
+
183
+ def test_011b_get_submodels_by_id_not_found(client: AasHttpClient):
184
+ result = client.get_submodels_by_id("non_existent_id")
185
+
186
+ assert result is None
187
+
188
+ def test_012_patch_submodel_by_id(client: AasHttpClient, shared_sm: Submodel):
189
+ sm = Submodel(shared_sm.id_short)
190
+ sm.id_short = shared_sm.id_short
191
+
192
+ description_text = "Patched description for unit tests"
193
+ sm.description = MultiLanguageTextType({"en": description_text})
194
+
195
+ sm_data_string = json.dumps(sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
196
+ sm_data = json.loads(sm_data_string)
197
+
198
+ result = client.patch_submodel_by_id(shared_sm.id, sm_data)
199
+
200
+ # Basyx java server do not provide this endpoint
201
+ assert not result
202
+
203
+ def test_013_put_shells_submodels_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell, shared_sm: Submodel):
204
+ sm = Submodel(shared_sm.id_short)
205
+ sm.id_short = shared_sm.id_short
206
+
207
+ description_text = "Put via shell description for unit tests"
208
+ sm.description = MultiLanguageTextType({"en": description_text})
209
+
210
+ sm_data_string = json.dumps(sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
211
+ sm_data = json.loads(sm_data_string)
212
+
213
+ result = client.put_shells_submodels_by_id(shared_aas.id, shared_sm.id, sm_data)
214
+
215
+ assert not result
216
+
217
+ def test_014_put_submodels_by_id(client: AasHttpClient, shared_sm: Submodel):
218
+ sm = Submodel(shared_sm.id_short)
219
+ sm.id_short = shared_sm.id_short
220
+
221
+ description_text = "Put description for unit tests"
222
+ sm.description = MultiLanguageTextType({"en": description_text})
223
+
224
+ sm_data_string = json.dumps(sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
225
+ sm_data = json.loads(sm_data_string)
226
+
227
+ result = client.put_submodels_by_id(shared_sm.id, sm_data)
228
+
229
+ assert result
230
+
231
+ get_result = client.get_submodels_by_id(shared_sm.id)
232
+ assert get_result is not None
233
+ assert get_result.get("idShort", "") == shared_sm.id_short
234
+ assert get_result.get("id", "") == shared_sm.id
235
+ # description must have changed
236
+ assert get_result.get("description", {})[0].get("text", "") == description_text
237
+ assert get_result.get("description", {})[0].get("text", "") != shared_sm.description.get("en", "")
238
+ assert len(get_result.get("displayName", {})) == 0
239
+
240
+ # restore to its original state
241
+ sm_data_string = json.dumps(shared_sm, cls=basyx.aas.adapter.json.AASToJsonEncoder)
242
+ sm_data = json.loads(sm_data_string)
243
+ client.put_submodels_by_id(shared_sm.id, sm_data) # Restore original submodel
244
+
245
+ def test_098_delete_shells_by_id(client: AasHttpClient, shared_aas: AssetAdministrationShell):
246
+ result = client.delete_shells_by_id(shared_aas.id)
247
+
248
+ assert result
249
+
250
+ get_result = client.get_shells()
251
+ assert get_result is not None
252
+ shells = get_result.get("result", [])
253
+ assert len(shells) == 0
254
+
255
+ def test_099_delete_submodel_by_id(client: AasHttpClient, shared_sm: Submodel):
256
+ result = client.delete_submodels_by_id(shared_sm.id)
257
+
258
+ assert result
259
+
260
+ get_result = client.get_submodels()
261
+ assert get_result is not None
262
+ submodels = get_result.get("result", [])
263
+ assert len(submodels) == 0
@@ -1,21 +0,0 @@
1
- import pytest
2
- from pathlib import Path
3
- from aas_http_client.client import create_client_by_config, AasHttpClient
4
-
5
- @pytest.fixture(scope="module")
6
- def cloud_client() -> AasHttpClient:
7
- try:
8
- file = Path("./tests/test_server_config.json").resolve()
9
-
10
- if not file.exists():
11
- raise FileNotFoundError(f"Configuration file {file} does not exist.")
12
-
13
- client = create_client_by_config(file, password="")
14
- except Exception as e:
15
- raise RuntimeError("Unable to connect to server.")
16
-
17
- return client
18
-
19
- def test_001_connect(cloud_client: AasHttpClient):
20
- print("Testing connection to the server...")
21
- assert cloud_client is not None
File without changes