testit-python-commons 5.1.0__py3-none-any.whl → 5.1.1__py3-none-any.whl

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.
@@ -30,6 +30,9 @@ from api_client_adapters.models import (
30
30
  from testit_python_commons.client.client_configuration import ClientConfiguration
31
31
  from testit_python_commons.client.converter import Converter
32
32
  from testit_python_commons.client.helpers.bulk_autotest_helper import BulkAutotestHelper
33
+ from typing import List
34
+
35
+ from testit_python_commons.models.link import Link
33
36
  from testit_python_commons.models.test_result import TestResult
34
37
  from testit_python_commons.services.logger import adapter_logger
35
38
  from testit_python_commons.services.retry import (
@@ -38,7 +41,6 @@ from testit_python_commons.services.retry import (
38
41
  retry,
39
42
  retry_on_connection_error,
40
43
  )
41
- from typing import List
42
44
 
43
45
 
44
46
  class ApiClientWorker:
@@ -80,14 +82,25 @@ class ApiClientWorker:
80
82
 
81
83
  @adapter_logger
82
84
  @retry
83
- def create_test_run(self, test_run_name: str = None) -> str:
85
+ def create_test_run(
86
+ self,
87
+ test_run_name: str = None,
88
+ tags: List[str] = None,
89
+ links: List[Link] = None) -> str:
84
90
  test_run_name = f'TestRun_{datetime.today().strftime("%Y-%m-%dT%H:%M:%S")}' if \
85
91
  not test_run_name else test_run_name
86
92
  model = Converter.test_run_to_test_run_short_model(
87
93
  self.__config.get_project_id(),
88
- test_run_name
94
+ test_run_name,
95
+ tags=tags,
96
+ links=links,
89
97
  )
90
98
 
99
+ logging.info(
100
+ 'Creating test run with tags=%s, links=%s',
101
+ tags or [],
102
+ [link.get_url() for link in (links or [])],
103
+ )
91
104
  response = self.__test_run_api.adapters_test_runs_post(
92
105
  adapters_test_runs_post_request=model)
93
106
 
@@ -107,15 +120,55 @@ class ApiClientWorker:
107
120
  raise Exception(f"Test run by id {test_run_id} not found!")
108
121
 
109
122
  @retry
110
- def update_test_run(self, test_run: TestRunApiResult) -> None:
123
+ def update_test_run(
124
+ self,
125
+ test_run: TestRunApiResult,
126
+ tags: List[str] = None,
127
+ links: List[Link] = None) -> None:
111
128
  """Function updates test run."""
112
- model = Converter.build_update_empty_request(test_run)
129
+ model = Converter.build_update_empty_request(test_run, tags=tags, links=links)
113
130
  logging.debug(f"Updating test run with model: {model}")
114
131
 
115
132
  self.__test_run_api.adapters_test_runs_put(adapters_test_runs_put_request=model)
116
133
 
117
134
  logging.debug(f'Updated testrun (ID: {test_run.id})')
118
135
 
136
+ @adapter_logger
137
+ def apply_test_run_tags_and_links(
138
+ self,
139
+ test_run_id: str,
140
+ tags: List[str] = None,
141
+ links: List[Link] = None,
142
+ test_run_name: str = None) -> None:
143
+ tags = tags or []
144
+ links = links or []
145
+ if not tags and not links and not test_run_name:
146
+ return
147
+
148
+ try:
149
+ test_run = self.get_test_run(test_run_id)
150
+ name_changed = bool(test_run_name and test_run_name != test_run.name)
151
+ if name_changed:
152
+ test_run.name = test_run_name
153
+
154
+ if not tags and not links and not name_changed:
155
+ return
156
+
157
+ logging.info(
158
+ 'Applying test run metadata to %s: tags=%s, links=%s, name=%s',
159
+ test_run_id,
160
+ tags,
161
+ [link.get_url() for link in links],
162
+ test_run_name,
163
+ )
164
+ self.update_test_run(test_run, tags=tags, links=links)
165
+ except Exception as exc:
166
+ logging.error(
167
+ 'Cannot apply tags/links to test run %s: %s',
168
+ test_run_id,
169
+ exc,
170
+ )
171
+
119
172
  @adapter_logger
120
173
  def set_test_run_id(self, test_run_id: str) -> None:
121
174
  self.__config.set_test_run_id(test_run_id)
@@ -48,11 +48,22 @@ from testit_python_commons.services.logger import adapter_logger
48
48
  class Converter:
49
49
  @staticmethod
50
50
  @adapter_logger
51
- def test_run_to_test_run_short_model(project_id: str, name: str) -> AdaptersTestRunsPostRequest:
52
- return AdaptersTestRunsPostRequest(
53
- project_id=project_id,
54
- name=name
55
- )
51
+ def test_run_to_test_run_short_model(
52
+ project_id: str,
53
+ name: str,
54
+ tags: List[str] = None,
55
+ links: List[Link] = None) -> AdaptersTestRunsPostRequest:
56
+ kwargs = {
57
+ 'project_id': project_id,
58
+ 'name': name,
59
+ }
60
+ if tags:
61
+ kwargs['tags'] = tags
62
+ if links:
63
+ kwargs['links'] = [
64
+ Converter.link_to_create_link_api_model(link) for link in links
65
+ ]
66
+ return AdaptersTestRunsPostRequest(**kwargs)
56
67
 
57
68
  @staticmethod
58
69
  @adapter_logger
@@ -61,14 +72,51 @@ class Converter:
61
72
 
62
73
  @classmethod
63
74
  @adapter_logger
64
- def build_update_empty_request(cls, test_run: TestRunApiResult) -> AdaptersTestRunsPutRequest:
75
+ def build_update_empty_request(
76
+ cls,
77
+ test_run: TestRunApiResult,
78
+ tags: List[str] = None,
79
+ links: List[Link] = None) -> AdaptersTestRunsPutRequest:
80
+ merged_tags = list(test_run.tags or [])
81
+ for tag in tags or []:
82
+ if tag not in merged_tags:
83
+ merged_tags.append(tag)
84
+
85
+ update_links = list(map(cls.build_update_link_api_model, test_run.links or []))
86
+ existing_urls = {link.url for link in (test_run.links or [])}
87
+ for link in links or []:
88
+ if link.get_url() not in existing_urls:
89
+ update_links.append(cls.link_to_update_link_api_model(link))
90
+ existing_urls.add(link.get_url())
91
+
65
92
  return AdaptersTestRunsPutRequest(
66
93
  id=test_run.id,
67
94
  name=test_run.name,
68
95
  description=test_run.description,
69
96
  launch_source=test_run.launch_source,
70
- attachments=list(map(cls.build_assign_attachment_api_model, test_run.attachments)),
71
- links=list(map(cls.build_update_link_api_model, test_run.links))
97
+ attachments=list(map(cls.build_assign_attachment_api_model, test_run.attachments or [])),
98
+ links=update_links,
99
+ tags=merged_tags,
100
+ )
101
+
102
+ @staticmethod
103
+ @adapter_logger
104
+ def link_to_create_link_api_model(link: Link) -> CreateLinkApiModel:
105
+ return CreateLinkApiModel(
106
+ url=link.get_url(),
107
+ title=link.get_title(),
108
+ type=LinkType(link.get_link_type() or "Related"),
109
+ description=link.get_description(),
110
+ )
111
+
112
+ @staticmethod
113
+ @adapter_logger
114
+ def link_to_update_link_api_model(link: Link) -> UpdateLinkApiModel:
115
+ return UpdateLinkApiModel(
116
+ url=link.get_url(),
117
+ title=link.get_title(),
118
+ type=LinkType(link.get_link_type() or "Related"),
119
+ description=link.get_description(),
72
120
  )
73
121
 
74
122
  @staticmethod
@@ -7,6 +7,8 @@ class PropertiesNames:
7
7
  CONFIGURATION_ID = 'configurationid'
8
8
  TEST_RUN_ID = 'testrunid'
9
9
  TEST_RUN_NAME = 'testrunname'
10
+ TEST_RUN_TAGS = 'testruntags'
11
+ TEST_RUN_LINKS = 'testrunlinks'
10
12
  TMS_PROXY = 'tmsproxy'
11
13
  ADAPTER_MODE = 'adaptermode'
12
14
  CERT_VALIDATION = 'certvalidation'
@@ -23,6 +25,8 @@ ENV_TO_PROPERTY = {
23
25
  'TMS_CONFIGURATION_ID': PropertiesNames.CONFIGURATION_ID,
24
26
  'TMS_TEST_RUN_ID': PropertiesNames.TEST_RUN_ID,
25
27
  'TMS_TEST_RUN_NAME': PropertiesNames.TEST_RUN_NAME,
28
+ 'TMS_TEST_RUN_TAGS': PropertiesNames.TEST_RUN_TAGS,
29
+ 'TMS_TEST_RUN_LINKS': PropertiesNames.TEST_RUN_LINKS,
26
30
  'TMS_PROXY': PropertiesNames.TMS_PROXY,
27
31
  'TMS_ADAPTER_MODE': PropertiesNames.ADAPTER_MODE,
28
32
  'TMS_CERT_VALIDATION': PropertiesNames.CERT_VALIDATION,
@@ -40,6 +44,8 @@ OPTION_TO_PROPERTY = {
40
44
  'set_configuration_id': PropertiesNames.CONFIGURATION_ID,
41
45
  'set_test_run_id': PropertiesNames.TEST_RUN_ID,
42
46
  'set_test_run_name': PropertiesNames.TEST_RUN_NAME,
47
+ 'set_test_run_tags': PropertiesNames.TEST_RUN_TAGS,
48
+ 'set_test_run_links': PropertiesNames.TEST_RUN_LINKS,
43
49
  'set_tms_proxy': PropertiesNames.TMS_PROXY,
44
50
  'set_adapter_mode': PropertiesNames.ADAPTER_MODE,
45
51
  'set_cert_validation': PropertiesNames.CERT_VALIDATION,
@@ -34,6 +34,7 @@ class AdapterManager:
34
34
  self.__fixture_manager = fixture_manager
35
35
  self.__test_result_map = {}
36
36
  self.__test_results = []
37
+ self.__test_run_metadata_applied = False
37
38
 
38
39
  # Sync Storage integration
39
40
  self.__sync_storage_runner = None
@@ -106,33 +107,35 @@ class AdapterManager:
106
107
  test_run_id = self.__config.get_test_run_id()
107
108
 
108
109
  if test_run_id:
109
- self.__update_test_run_name(test_run_id)
110
+ self.__apply_test_run_metadata_early(test_run_id)
110
111
 
111
112
  return test_run_id or ""
112
113
 
113
114
  result = self.__config.get_test_run_id()
114
115
  if result is not None:
116
+ self.__apply_test_run_metadata_early(result)
115
117
  return result
116
118
 
117
119
  # create if not exists
118
120
  test_run_name = self.__config.get_test_run_name()
119
- return self.__api_client.create_test_run(test_run_name if test_run_name else "")
121
+ return self.__api_client.create_test_run(
122
+ test_run_name if test_run_name else "",
123
+ tags=self.__config.get_test_run_tags(),
124
+ links=self.__config.get_test_run_links(),
125
+ )
120
126
 
121
127
  @adapter_logger
122
- def __update_test_run_name(self, test_run_id: str) -> None:
123
- test_run_name = self.__config.get_test_run_name()
124
-
125
- if not test_run_name:
126
- return
127
-
128
- test_run = self.__api_client.get_test_run(test_run_id)
129
-
130
- if test_run_name == test_run.name:
128
+ def __apply_test_run_metadata_early(self, test_run_id: str) -> None:
129
+ if self.__test_run_metadata_applied:
131
130
  return
132
131
 
133
- test_run.name = test_run_name
134
-
135
- self.__api_client.update_test_run(test_run)
132
+ self.__test_run_metadata_applied = True
133
+ self.__api_client.apply_test_run_tags_and_links(
134
+ test_run_id,
135
+ tags=self.__config.get_test_run_tags(),
136
+ links=self.__config.get_test_run_links(),
137
+ test_run_name=self.__config.get_test_run_name(),
138
+ )
136
139
 
137
140
  @adapter_logger
138
141
  def get_autotests_for_launch(self):
@@ -1,8 +1,13 @@
1
+ from typing import List
2
+
1
3
  from testit_python_commons.models.adapter_mode import AdapterMode
4
+ from testit_python_commons.models.link import Link
2
5
  from testit_python_commons.services.logger import adapter_logger
6
+ from testit_python_commons.services.test_run_metadata import parse_test_run_links, parse_test_run_tags
3
7
  from testit_python_commons.services.utils import Utils
4
8
  from testit_python_commons.configurations.properties_names import PropertiesNames
5
9
 
10
+
6
11
  class AdapterManagerConfiguration:
7
12
  __test_run_id = None
8
13
 
@@ -14,8 +19,11 @@ class AdapterManagerConfiguration:
14
19
  self.__automatic_creation_test_cases = Utils.convert_value_str_to_bool(
15
20
  app_properties.get(PropertiesNames.AUTOMATIC_CREATION_TEST_CASES).lower())
16
21
 
17
- self.__import_realtime = Utils.convert_value_str_to_bool(app_properties.get(PropertiesNames.IMPORT_REALTIME).lower())
22
+ self.__import_realtime = Utils.convert_value_str_to_bool(
23
+ app_properties.get(PropertiesNames.IMPORT_REALTIME).lower())
18
24
  self.__test_run_name = app_properties.get(PropertiesNames.TEST_RUN_NAME)
25
+ self.__test_run_tags = parse_test_run_tags(app_properties.get(PropertiesNames.TEST_RUN_TAGS))
26
+ self.__test_run_links = parse_test_run_links(app_properties.get(PropertiesNames.TEST_RUN_LINKS))
19
27
 
20
28
  @adapter_logger
21
29
  def get_test_run_id(self):
@@ -29,6 +37,14 @@ class AdapterManagerConfiguration:
29
37
  def get_test_run_name(self):
30
38
  return self.__test_run_name
31
39
 
40
+ @adapter_logger
41
+ def get_test_run_tags(self) -> List[str]:
42
+ return self.__test_run_tags
43
+
44
+ @adapter_logger
45
+ def get_test_run_links(self) -> List[Link]:
46
+ return self.__test_run_links
47
+
32
48
  @adapter_logger
33
49
  def get_mode(self):
34
50
  return self.__adapter_mode
@@ -0,0 +1,50 @@
1
+ import json
2
+ import logging
3
+ from typing import List, Optional
4
+
5
+ from testit_python_commons.models.link import Link
6
+ from testit_python_commons.services.utils import Utils
7
+
8
+
9
+ def parse_test_run_tags(raw: Optional[str]) -> List[str]:
10
+ if not raw or not str(raw).strip():
11
+ return []
12
+
13
+ value = str(raw).strip()
14
+ if value.startswith('['):
15
+ try:
16
+ parsed = json.loads(value)
17
+ except json.JSONDecodeError:
18
+ logging.warning('Invalid test run tags JSON: %s', value)
19
+ return []
20
+ if not isinstance(parsed, list):
21
+ logging.warning('Test run tags JSON must be an array: %s', value)
22
+ return []
23
+ return [str(tag).strip() for tag in parsed if str(tag).strip()]
24
+
25
+ return [tag.strip() for tag in value.split(',') if tag.strip()]
26
+
27
+
28
+ def parse_test_run_links(raw: Optional[str]) -> List[Link]:
29
+ if not raw or not str(raw).strip():
30
+ return []
31
+
32
+ value = str(raw).strip()
33
+ try:
34
+ parsed = json.loads(value)
35
+ except json.JSONDecodeError:
36
+ logging.warning('Invalid test run links JSON: %s', value)
37
+ return []
38
+
39
+ if not isinstance(parsed, list):
40
+ logging.warning('Test run links JSON must be an array: %s', value)
41
+ return []
42
+
43
+ links = []
44
+ for item in parsed:
45
+ if not isinstance(item, dict) or not item.get('url'):
46
+ logging.warning('Skipping invalid test run link (url is required): %s', item)
47
+ continue
48
+ links.append(Utils.convert_link_dict_to_link_model(item))
49
+
50
+ return links
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: testit-python-commons
3
- Version: 5.1.0
3
+ Version: 5.1.1
4
4
  Summary: Python commons for Test IT
5
5
  Home-page: https://github.com/testit-tms/adapters-python/
6
6
  Author: Integration team
@@ -211,9 +211,9 @@ testit_python_commons/decorators.py,sha256=QI8qMjDincTRZmcZByP5y5wHsf_Fwd1oc67Wu
211
211
  testit_python_commons/dynamic_methods.py,sha256=WKHHA6Uj61tWXI3DphALYOi2BV6TnQKvQy0-Vt2JR2I,8816
212
212
  testit_python_commons/step.py,sha256=CYUs_S8opmRg1tsTY1dVJOPzzt-HYR3_uLTBpYtHSfQ,3244
213
213
  testit_python_commons/client/__init__.py,sha256=zSJhxDHzWWTFHJ0s8bqCaBtM5FK2GcPgZxaKdI8zf-o,165
214
- testit_python_commons/client/api_client.py,sha256=MQIqTE4VyBTugkpAP7wb3Kr27_2KfSHAIr9th4lcSTs,26025
214
+ testit_python_commons/client/api_client.py,sha256=izH0bRWjC37aubt5hhREzCRc7SPe6DfFlcpkj0M3YXA,27693
215
215
  testit_python_commons/client/client_configuration.py,sha256=1M-OrROU3Xj0YGsUX4venG-l6Ewr43LNvUcyFfY57ys,2776
216
- testit_python_commons/client/converter.py,sha256=rVleh2OC2rKd3iR-BVO1-StP9kVqRSsNcp_HcPoNr2E,24653
216
+ testit_python_commons/client/converter.py,sha256=pjnCHtaQNGTot-YWYb6IJ9gX9XlEos708Vi98oJBxws,26272
217
217
  testit_python_commons/client/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
218
  testit_python_commons/client/helpers/bulk_autotest_helper.py,sha256=L480JYYA3zphCciJOzefCOg1upWeRgdJWd6qWEKM45k,10920
219
219
  testit_python_commons/client/helpers/threads_manager.py,sha256=Ix8NJm3Yp9_7jxGTtojsAWqfuNvtYHEia9CiHFW9b3k,3509
@@ -221,7 +221,7 @@ testit_python_commons/client/models/__init__.py,sha256=4c3yNkadtebFF1eEZw7JmfwcL
221
221
  testit_python_commons/client/models/threads_for_create_and_result.py,sha256=qOEZDIhCX0r6uUndzc2SiDcykcMVuv5XTDEvBQGGslY,1458
222
222
  testit_python_commons/client/models/threads_for_update_and_result.py,sha256=QedFC8CnG5hcku4RkqA157o-azktpZhp6cpwdcBqxFA,2129
223
223
  testit_python_commons/configurations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
224
- testit_python_commons/configurations/properties_names.py,sha256=DcMkFmJuyvRXylLjP3HgJTjiaXsNSJ0ZmQjKYgM1v00,2364
224
+ testit_python_commons/configurations/properties_names.py,sha256=st-M0werA0w9fCcuELm0h3D7-nCEVn9vJmj4RCMPuaA,2662
225
225
  testit_python_commons/models/__init__.py,sha256=qtwpjoKOOaTCiRHiG0TlOWWQ26AFw7dumt4yV-u0LcE,90
226
226
  testit_python_commons/models/adapter_mode.py,sha256=4U3IlRvjoDCe6WJ6AS4HaiP2nS9ntXIMOUmKGKcblWE,87
227
227
  testit_python_commons/models/fixture.py,sha256=_KO-sWKHloHY1MFowp1anE3Dp5-ebdUeO8AAsLMNids,661
@@ -233,8 +233,8 @@ testit_python_commons/models/step_result.py,sha256=T9BbcPB6BCz3ZkrWXy2Z2Guj2wecv
233
233
  testit_python_commons/models/test_result.py,sha256=z6OB3V_whCQDJvr4jQdgVanoJSoeKh8ZXgPAACkNrdw,7515
234
234
  testit_python_commons/models/test_result_with_all_fixture_step_results_model.py,sha256=aI5nfJ_4EAhzZg7eIV1JhSf9i3EENiRiuQuqJvSUs3M,866
235
235
  testit_python_commons/services/__init__.py,sha256=yVVmiCgMyike_8OoNPiHLNoMqKhCDlWYhvmGW0IRHJM,1197
236
- testit_python_commons/services/adapter_manager.py,sha256=CtzPoTjGHKKCrjMWk_HEpF26Ww56OI6mwcsRXrTpx2Q,11541
237
- testit_python_commons/services/adapter_manager_configuration.py,sha256=KyLhB_iNUQaVEurfLQ0RANIZfhJPB19c_WUkGpqf0xo,1619
236
+ testit_python_commons/services/adapter_manager.py,sha256=HiPxT5Ikbpdqe41EO-mmiUXvmDPms6ZRnsTCVdnybuE,11839
237
+ testit_python_commons/services/adapter_manager_configuration.py,sha256=ZPgSRUskSh8sJNAtlpOSAXqGWWTdYNsDb3jaiuTFEc8,2228
238
238
  testit_python_commons/services/fixture_manager.py,sha256=PCSLBEPa3yJVbCPsMt_Y5badWLAhKrJsZTaUesq7oNI,2006
239
239
  testit_python_commons/services/fixture_storage.py,sha256=nAIW0p9lVvVWtiVdFNqaD7-gCBislY8DLrfdlh8OqFw,1205
240
240
  testit_python_commons/services/logger.py,sha256=E4LmykJeEHPIzuRjJShAuo2WvObfBBwOgBjYnaQi4C4,810
@@ -242,12 +242,13 @@ testit_python_commons/services/plugin_manager.py,sha256=IIPJZSCJrOKQWfm0kmL9jWG9
242
242
  testit_python_commons/services/retry.py,sha256=CD_ou5xcz9gjxYUfctGJTAFMmTcv8hMNqOt42VTxS2I,2476
243
243
  testit_python_commons/services/step_manager.py,sha256=pKTtEgpwOS_KJV_9kcBmKA8WRJkWvvdye_Y0ot0AKw0,1103
244
244
  testit_python_commons/services/step_result_storage.py,sha256=4axfi2dnP3LABlEql9k6lydftOgDFV3c2cXN-1uEvXU,633
245
+ testit_python_commons/services/test_run_metadata.py,sha256=F3Ig8p6AwEkalZ4S93okzGIrP_2AYVybrT6LLc9_1cY,1547
245
246
  testit_python_commons/services/utils.py,sha256=5LBymIxEC1AKtGQz-S1-ipo3OYR-JzRUAC4WWFQylHc,4060
246
247
  testit_python_commons/services/sync_storage/__init__.py,sha256=Qmjs6Xk5l-i5FFItk0-XPrlVK_HkDuX6FD8FID1iKu0,154
247
248
  testit_python_commons/services/sync_storage/sync_storage_runner.py,sha256=9FCbMxzGa84I79X7QOjYO_oSiUUu43LhJqPDs_JEEb0,20549
248
249
  testit_python_commons/utils/__init__.py,sha256=CUHziylwvFAuKyUM1tCp13ik5Z2Mw-VK8n7c92aVy-I,78
249
250
  testit_python_commons/utils/html_escape_utils.py,sha256=wx20lAVrMvhNiQ7bEu_f-SGqDBp85D-EBL2sgTmnJPY,8135
250
- testit_python_commons-5.1.0.dist-info/METADATA,sha256=xxhtb3Ug-X3Xfu-CjyZ2EwK7_uOkpSwXXWFcN2uJcUI,1675
251
- testit_python_commons-5.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
252
- testit_python_commons-5.1.0.dist-info/top_level.txt,sha256=Jme7mbm0CtX-96d3cUiEonamIeb7kAo3Je4bSlxBndI,72
253
- testit_python_commons-5.1.0.dist-info/RECORD,,
251
+ testit_python_commons-5.1.1.dist-info/METADATA,sha256=xtmhARbQoOwie5KNvJOusxkUTxDrv0yXCep2ZBqqYTQ,1675
252
+ testit_python_commons-5.1.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
253
+ testit_python_commons-5.1.1.dist-info/top_level.txt,sha256=Jme7mbm0CtX-96d3cUiEonamIeb7kAo3Je4bSlxBndI,72
254
+ testit_python_commons-5.1.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (83.0.0)
2
+ Generator: setuptools (84.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5