qase-python-commons 5.1.0__tar.gz → 5.1.2__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.
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/PKG-INFO +1 -1
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/pyproject.toml +1 -1
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/client/api_v2_client.py +0 -7
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/result.py +8 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/core.py +9 -3
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/testops_multi.py +12 -0
- qase_python_commons-5.1.2/src/qase/commons/util/token_masker.py +46 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase_python_commons.egg-info/PKG-INFO +1 -1
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase_python_commons.egg-info/SOURCES.txt +1 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/README.md +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/setup.cfg +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/__init__.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/__init__.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/client/api_v1_client.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/client/base_api_client.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/config.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/exceptions/reporter.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/loader.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/logger.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/__init__.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/attachment.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/basemodel.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/api.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/batch.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/connection.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/framework.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/plan.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/qaseconfig.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/report.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/run.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/testops.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/external_link.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/relation.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/run.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/runtime.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/step.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/profilers/__init__.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/profilers/db.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/profilers/network.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/profilers/sleep.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/__init__.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/report.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/testops.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/status_mapping/__init__.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/status_mapping/status_mapping.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/util/__init__.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/util/host_data.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/utils.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/validators/base.py +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase_python_commons.egg-info/dependency_links.txt +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase_python_commons.egg-info/requires.txt +0 -0
- {qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase_python_commons.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qase-python-commons
|
|
3
|
-
Version: 5.1.
|
|
3
|
+
Version: 5.1.2
|
|
4
4
|
Summary: A library for Qase TestOps and Qase Report
|
|
5
5
|
Author-email: Qase Team <support@qase.io>
|
|
6
6
|
Project-URL: Homepage, https://github.com/qase-tms/qase-python/tree/main/qase-python-commons
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qase-python-commons"
|
|
7
|
-
version = "5.1.
|
|
7
|
+
version = "5.1.2"
|
|
8
8
|
description = "A library for Qase TestOps and Qase Report"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{name = "Qase Team", email = "support@qase.io"}]
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/client/api_v2_client.py
RENAMED
|
@@ -157,13 +157,6 @@ class ApiV2Client(ApiV1Client):
|
|
|
157
157
|
if param == "":
|
|
158
158
|
result.params[key] = "empty"
|
|
159
159
|
|
|
160
|
-
# Merge result.tags into fields["tags"] for API
|
|
161
|
-
if result.tags:
|
|
162
|
-
existing_str = result.fields.get("tags", "")
|
|
163
|
-
existing = [t.strip() for t in existing_str.split(",") if t.strip()] if existing_str else []
|
|
164
|
-
all_tags = list(dict.fromkeys(existing + result.tags))
|
|
165
|
-
result.fields["tags"] = ",".join(all_tags)
|
|
166
|
-
|
|
167
160
|
result_model_v2 = ResultCreate(
|
|
168
161
|
title=result.get_title(),
|
|
169
162
|
signature=result.signature,
|
|
@@ -98,6 +98,14 @@ class Result(BaseModel):
|
|
|
98
98
|
def add_tags(self, tags: List[str]) -> None:
|
|
99
99
|
for tag in tags:
|
|
100
100
|
self.add_tag(tag)
|
|
101
|
+
self._sync_tags_to_fields()
|
|
102
|
+
|
|
103
|
+
def _sync_tags_to_fields(self) -> None:
|
|
104
|
+
if self.tags:
|
|
105
|
+
existing_str = self.fields.get("tags", "")
|
|
106
|
+
existing = [t.strip() for t in existing_str.split(",") if t.strip()] if existing_str else []
|
|
107
|
+
all_tags = list(dict.fromkeys(existing + self.tags))
|
|
108
|
+
self.fields["tags"] = ",".join(all_tags)
|
|
101
109
|
|
|
102
110
|
def get_tags(self) -> List[str]:
|
|
103
111
|
return self.tags
|
|
@@ -12,6 +12,7 @@ from ..models.config.qaseconfig import Mode
|
|
|
12
12
|
from typing import Union, List, Dict
|
|
13
13
|
|
|
14
14
|
from ..util import get_host_info
|
|
15
|
+
from ..util.token_masker import sanitize_config_for_log
|
|
15
16
|
from ..status_mapping.status_mapping import StatusMapping
|
|
16
17
|
from ..exceptions.reporter import ReporterException
|
|
17
18
|
|
|
@@ -68,7 +69,7 @@ class QaseCoreReporter:
|
|
|
68
69
|
|
|
69
70
|
self.fallback = self._fallback_setup()
|
|
70
71
|
|
|
71
|
-
self.logger.log_debug(f"Config: {self.config}")
|
|
72
|
+
self.logger.log_debug(f"Config: {sanitize_config_for_log(self.config)}")
|
|
72
73
|
|
|
73
74
|
host_data = get_host_info(framework, reporter_name)
|
|
74
75
|
self.logger.log_debug(f"Host data: {host_data}")
|
|
@@ -260,10 +261,15 @@ class QaseCoreReporter:
|
|
|
260
261
|
for profiler in self.profilers:
|
|
261
262
|
profiler.disable()
|
|
262
263
|
|
|
263
|
-
def set_run_id(self, run_id
|
|
264
|
+
def set_run_id(self, run_id) -> None:
|
|
264
265
|
if self.reporter:
|
|
265
266
|
try:
|
|
266
|
-
|
|
267
|
+
# Multi-project mode: run_id is a dict of project -> run_id.
|
|
268
|
+
# Dispatch to set_run_ids so each project gets seeded.
|
|
269
|
+
if isinstance(run_id, dict) and hasattr(self.reporter, 'set_run_ids'):
|
|
270
|
+
self.reporter.set_run_ids(run_id)
|
|
271
|
+
else:
|
|
272
|
+
self.reporter.set_run_id(run_id)
|
|
267
273
|
except Exception as e:
|
|
268
274
|
# Log error and run fallback
|
|
269
275
|
self.logger.log('Failed to set run id', 'info')
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/testops_multi.py
RENAMED
|
@@ -166,6 +166,18 @@ class QaseTestOpsMulti:
|
|
|
166
166
|
else:
|
|
167
167
|
self.logger.log(f"Unknown project code: {project_code}", "warning")
|
|
168
168
|
|
|
169
|
+
def set_run_ids(self, run_ids: Dict[str, Union[str, int]]) -> None:
|
|
170
|
+
"""Set run_ids for multiple projects at once.
|
|
171
|
+
|
|
172
|
+
Used by xdist workers to seed run ids produced by the controller.
|
|
173
|
+
Unknown project codes are skipped with a warning but do not raise.
|
|
174
|
+
"""
|
|
175
|
+
for project_code, run_id in run_ids.items():
|
|
176
|
+
if project_code in self.project_configs:
|
|
177
|
+
self.project_runs[project_code] = int(run_id) if isinstance(run_id, str) else run_id
|
|
178
|
+
else:
|
|
179
|
+
self.logger.log(f"Unknown project code: {project_code}", "warning")
|
|
180
|
+
|
|
169
181
|
def start_run(self) -> Dict[str, int]:
|
|
170
182
|
"""
|
|
171
183
|
Create or verify test runs for all projects.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Token masking utilities for safe config logging.
|
|
2
|
+
|
|
3
|
+
Mirrors the qase-javascript-commons `token-masker.ts` contract so leaked
|
|
4
|
+
debug logs cannot expose customer API tokens. The only secret we currently
|
|
5
|
+
need to mask sits at ``config.testops.api.token``.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def mask_token(token: str) -> str:
|
|
13
|
+
"""Return a masked representation of an API token.
|
|
14
|
+
|
|
15
|
+
Tokens of 7 chars or fewer are fully replaced with asterisks.
|
|
16
|
+
Longer tokens keep the first 3 and last 4 characters: ``abc****wxyz``.
|
|
17
|
+
"""
|
|
18
|
+
if not isinstance(token, str):
|
|
19
|
+
return token
|
|
20
|
+
if len(token) <= 7:
|
|
21
|
+
return "*" * len(token)
|
|
22
|
+
return f"{token[:3]}****{token[-4:]}"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def sanitize_config_for_log(config: Any) -> str:
|
|
26
|
+
"""Return a JSON string of ``config`` with the API token masked.
|
|
27
|
+
|
|
28
|
+
Accepts any object with a JSON-serialisable ``__str__`` (e.g. ``BaseModel``)
|
|
29
|
+
or a dict. Falls back to ``str(config)`` if the serialised form cannot be
|
|
30
|
+
parsed as JSON, so callers never lose log output to a masking bug.
|
|
31
|
+
"""
|
|
32
|
+
try:
|
|
33
|
+
raw = config if isinstance(config, str) else str(config)
|
|
34
|
+
parsed = json.loads(raw)
|
|
35
|
+
except (TypeError, ValueError):
|
|
36
|
+
return str(config)
|
|
37
|
+
|
|
38
|
+
token = (
|
|
39
|
+
parsed.get("testops", {}).get("api", {}).get("token")
|
|
40
|
+
if isinstance(parsed, dict)
|
|
41
|
+
else None
|
|
42
|
+
)
|
|
43
|
+
if token:
|
|
44
|
+
parsed["testops"]["api"]["token"] = mask_token(token)
|
|
45
|
+
|
|
46
|
+
return json.dumps(parsed, indent=4, sort_keys=True)
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase_python_commons.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qase-python-commons
|
|
3
|
-
Version: 5.1.
|
|
3
|
+
Version: 5.1.2
|
|
4
4
|
Summary: A library for Qase TestOps and Qase Report
|
|
5
5
|
Author-email: Qase Team <support@qase.io>
|
|
6
6
|
Project-URL: Homepage, https://github.com/qase-tms/qase-python/tree/main/qase-python-commons
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase_python_commons.egg-info/SOURCES.txt
RENAMED
|
@@ -41,6 +41,7 @@ src/qase/commons/status_mapping/__init__.py
|
|
|
41
41
|
src/qase/commons/status_mapping/status_mapping.py
|
|
42
42
|
src/qase/commons/util/__init__.py
|
|
43
43
|
src/qase/commons/util/host_data.py
|
|
44
|
+
src/qase/commons/util/token_masker.py
|
|
44
45
|
src/qase/commons/validators/base.py
|
|
45
46
|
src/qase_python_commons.egg-info/PKG-INFO
|
|
46
47
|
src/qase_python_commons.egg-info/SOURCES.txt
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/client/api_v1_client.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/client/base_api_client.py
RENAMED
|
File without changes
|
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/exceptions/reporter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/attachment.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/basemodel.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/api.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/batch.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/connection.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/framework.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/plan.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/qaseconfig.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/report.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/run.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/config/testops.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/models/external_link.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/profilers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/profilers/network.py
RENAMED
|
File without changes
|
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/__init__.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/report.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/reporters/testops.py
RENAMED
|
File without changes
|
{qase_python_commons-5.1.0 → qase_python_commons-5.1.2}/src/qase/commons/status_mapping/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|