qase-python-commons 4.1.0__py3-none-any.whl → 4.1.2__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.
Potentially problematic release.
This version of qase-python-commons might be problematic. Click here for more details.
- qase/commons/client/api_v1_client.py +32 -1
- qase/commons/client/base_api_client.py +11 -0
- qase/commons/config.py +8 -0
- qase/commons/models/config/testops.py +5 -0
- qase/commons/models/result.py +2 -2
- qase/commons/models/step.py +3 -2
- qase/commons/reporters/report.py +2 -2
- qase/commons/reporters/testops.py +12 -0
- qase/commons/utils.py +78 -0
- {qase_python_commons-4.1.0.dist-info → qase_python_commons-4.1.2.dist-info}/METADATA +2 -1
- {qase_python_commons-4.1.0.dist-info → qase_python_commons-4.1.2.dist-info}/RECORD +13 -13
- {qase_python_commons-4.1.0.dist-info → qase_python_commons-4.1.2.dist-info}/WHEEL +0 -0
- {qase_python_commons-4.1.0.dist-info → qase_python_commons-4.1.2.dist-info}/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@ from typing import Union
|
|
|
3
3
|
|
|
4
4
|
import certifi
|
|
5
5
|
from qase.api_client_v1 import ApiClient, ProjectsApi, Project, EnvironmentsApi, RunsApi, AttachmentsApi, \
|
|
6
|
-
AttachmentGet, RunCreate, ConfigurationsApi, ConfigurationCreate, ConfigurationGroupCreate
|
|
6
|
+
AttachmentGet, RunCreate, ConfigurationsApi, ConfigurationCreate, ConfigurationGroupCreate, RunPublic
|
|
7
7
|
from qase.api_client_v1.configuration import Configuration
|
|
8
8
|
from .. import Logger
|
|
9
9
|
from .base_api_client import BaseApiClient
|
|
@@ -210,6 +210,37 @@ class ApiV1Client(BaseApiClient):
|
|
|
210
210
|
return True
|
|
211
211
|
return False
|
|
212
212
|
|
|
213
|
+
def enable_public_report(self, project_code: str, run_id: int) -> str:
|
|
214
|
+
"""
|
|
215
|
+
Enable public report for a test run and return the public link
|
|
216
|
+
|
|
217
|
+
:param project_code: project code
|
|
218
|
+
:param run_id: test run id
|
|
219
|
+
:return: public report link or None if failed
|
|
220
|
+
"""
|
|
221
|
+
try:
|
|
222
|
+
self.logger.log_debug(f"Enabling public report for run {run_id}")
|
|
223
|
+
api_runs = RunsApi(self.client)
|
|
224
|
+
|
|
225
|
+
# Create RunPublic object with status=True
|
|
226
|
+
run_public = RunPublic(status=True)
|
|
227
|
+
|
|
228
|
+
# Call the API to enable public report
|
|
229
|
+
response = api_runs.update_run_publicity(project_code, run_id, run_public)
|
|
230
|
+
|
|
231
|
+
# Extract the public URL from response
|
|
232
|
+
if response.result and response.result.url:
|
|
233
|
+
public_url = response.result.url
|
|
234
|
+
self.logger.log_debug(f"Public report enabled for run {run_id}: {public_url}")
|
|
235
|
+
return public_url
|
|
236
|
+
else:
|
|
237
|
+
self.logger.log_debug(f"Public report enabled for run {run_id} but no URL returned")
|
|
238
|
+
return None
|
|
239
|
+
|
|
240
|
+
except Exception as e:
|
|
241
|
+
self.logger.log(f"Error at enabling public report for run {run_id}: {e}", "error")
|
|
242
|
+
return None
|
|
243
|
+
|
|
213
244
|
def update_external_link(self, project_code: str, run_id: int):
|
|
214
245
|
"""Update external link for a test run"""
|
|
215
246
|
try:
|
|
@@ -86,3 +86,14 @@ class BaseApiClient(abc.ABC):
|
|
|
86
86
|
:return: None
|
|
87
87
|
"""
|
|
88
88
|
pass
|
|
89
|
+
|
|
90
|
+
@abc.abstractmethod
|
|
91
|
+
def enable_public_report(self, project_code: str, run_id: int) -> str:
|
|
92
|
+
"""
|
|
93
|
+
Enable public report for a test run and return the public link
|
|
94
|
+
|
|
95
|
+
:param project_code: project code
|
|
96
|
+
:param run_id: test run id
|
|
97
|
+
:return: public report link or None if failed
|
|
98
|
+
"""
|
|
99
|
+
pass
|
qase/commons/config.py
CHANGED
|
@@ -169,6 +169,11 @@ class ConfigManager:
|
|
|
169
169
|
# Parse comma-separated string
|
|
170
170
|
self.config.testops.set_status_filter([s.strip() for s in status_filter.split(',')])
|
|
171
171
|
|
|
172
|
+
if testops.get("showPublicReportLink") is not None:
|
|
173
|
+
self.config.testops.set_show_public_report_link(
|
|
174
|
+
testops.get("showPublicReportLink")
|
|
175
|
+
)
|
|
176
|
+
|
|
172
177
|
if config.get("report"):
|
|
173
178
|
report = config.get("report")
|
|
174
179
|
|
|
@@ -321,6 +326,9 @@ class ConfigManager:
|
|
|
321
326
|
# Parse comma-separated string
|
|
322
327
|
self.config.testops.set_status_filter([s.strip() for s in value.split(',')])
|
|
323
328
|
|
|
329
|
+
if key == 'QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK':
|
|
330
|
+
self.config.testops.set_show_public_report_link(value)
|
|
331
|
+
|
|
324
332
|
if key == 'QASE_REPORT_DRIVER':
|
|
325
333
|
self.config.report.set_driver(value)
|
|
326
334
|
|
|
@@ -49,6 +49,7 @@ class TestopsConfig(BaseModel):
|
|
|
49
49
|
batch: BatchConfig = None
|
|
50
50
|
configurations: ConfigurationsConfig = None
|
|
51
51
|
status_filter: List[str] = None
|
|
52
|
+
show_public_report_link: bool = None
|
|
52
53
|
|
|
53
54
|
def __init__(self):
|
|
54
55
|
self.api = ApiConfig()
|
|
@@ -58,6 +59,7 @@ class TestopsConfig(BaseModel):
|
|
|
58
59
|
self.configurations = ConfigurationsConfig()
|
|
59
60
|
self.defect = False
|
|
60
61
|
self.status_filter = []
|
|
62
|
+
self.show_public_report_link = False
|
|
61
63
|
|
|
62
64
|
def set_project(self, project: str):
|
|
63
65
|
self.project = project
|
|
@@ -67,3 +69,6 @@ class TestopsConfig(BaseModel):
|
|
|
67
69
|
|
|
68
70
|
def set_status_filter(self, status_filter: List[str]):
|
|
69
71
|
self.status_filter = status_filter
|
|
72
|
+
|
|
73
|
+
def set_show_public_report_link(self, show_public_report_link):
|
|
74
|
+
self.show_public_report_link = QaseUtils.parse_bool(show_public_report_link)
|
qase/commons/models/result.py
CHANGED
|
@@ -25,7 +25,7 @@ class Execution(BaseModel):
|
|
|
25
25
|
stacktrace: Optional[str] = None,
|
|
26
26
|
thread: Optional[str] = QaseUtils.get_thread_name()
|
|
27
27
|
):
|
|
28
|
-
self.start_time =
|
|
28
|
+
self.start_time = QaseUtils.get_real_time()
|
|
29
29
|
self.status = status
|
|
30
30
|
self.end_time = end_time
|
|
31
31
|
self.duration = duration
|
|
@@ -48,7 +48,7 @@ class Execution(BaseModel):
|
|
|
48
48
|
return self.status
|
|
49
49
|
|
|
50
50
|
def complete(self):
|
|
51
|
-
self.end_time =
|
|
51
|
+
self.end_time = QaseUtils.get_real_time()
|
|
52
52
|
self.duration = (int)((self.end_time - self.start_time) * 1000)
|
|
53
53
|
|
|
54
54
|
|
qase/commons/models/step.py
CHANGED
|
@@ -5,6 +5,7 @@ from enum import Enum
|
|
|
5
5
|
from typing import Optional, Union, Dict, List, Type
|
|
6
6
|
from .attachment import Attachment
|
|
7
7
|
from .basemodel import BaseModel
|
|
8
|
+
from .. import QaseUtils
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class StepType(Enum):
|
|
@@ -95,7 +96,7 @@ class StepSleepData(BaseModel):
|
|
|
95
96
|
|
|
96
97
|
class StepExecution(BaseModel):
|
|
97
98
|
def __init__(self, status: Optional[str] = 'untested', end_time: int = 0, duration: int = 0):
|
|
98
|
-
self.start_time =
|
|
99
|
+
self.start_time = QaseUtils.get_real_time()
|
|
99
100
|
self.status = status
|
|
100
101
|
self.end_time = end_time
|
|
101
102
|
self.duration = duration
|
|
@@ -108,7 +109,7 @@ class StepExecution(BaseModel):
|
|
|
108
109
|
raise ValueError('Step status must be one of: passed, failed, skipped, blocked, untested, invalid')
|
|
109
110
|
|
|
110
111
|
def complete(self):
|
|
111
|
-
self.end_time =
|
|
112
|
+
self.end_time = QaseUtils.get_real_time()
|
|
112
113
|
self.duration = int((self.end_time - self.start_time) * 1000)
|
|
113
114
|
|
|
114
115
|
def add_attachment(self, attachment: Attachment):
|
qase/commons/reporters/report.py
CHANGED
|
@@ -31,10 +31,10 @@ class QaseReport:
|
|
|
31
31
|
|
|
32
32
|
def start_run(self):
|
|
33
33
|
self._check_report_path()
|
|
34
|
-
self.start_time = str(
|
|
34
|
+
self.start_time = str(QaseUtils.get_real_time())
|
|
35
35
|
|
|
36
36
|
def complete_run(self):
|
|
37
|
-
self.end_time = str(
|
|
37
|
+
self.end_time = str(QaseUtils.get_real_time())
|
|
38
38
|
self._compile_report()
|
|
39
39
|
|
|
40
40
|
def complete_worker(self):
|
|
@@ -144,6 +144,18 @@ class QaseTestOps:
|
|
|
144
144
|
self.logger.log_debug("Completing run")
|
|
145
145
|
self.client.complete_run(self.project_code, self.run_id)
|
|
146
146
|
self.logger.log_debug("Run completed")
|
|
147
|
+
|
|
148
|
+
# Enable public report if configured
|
|
149
|
+
if self.config.testops.show_public_report_link:
|
|
150
|
+
try:
|
|
151
|
+
self.logger.log_debug("Enabling public report")
|
|
152
|
+
public_url = self.client.enable_public_report(self.project_code, self.run_id)
|
|
153
|
+
if public_url:
|
|
154
|
+
self.logger.log(f"Public report link: {public_url}", "info")
|
|
155
|
+
else:
|
|
156
|
+
self.logger.log("Failed to generate public report link", "warning")
|
|
157
|
+
except Exception as e:
|
|
158
|
+
self.logger.log(f"Failed to generate public report link: {e}", "warning")
|
|
147
159
|
|
|
148
160
|
def complete_worker(self) -> None:
|
|
149
161
|
if len(self.results) > 0:
|
qase/commons/utils.py
CHANGED
|
@@ -6,10 +6,88 @@ from typing import Union, List
|
|
|
6
6
|
import pip
|
|
7
7
|
import string
|
|
8
8
|
import uuid
|
|
9
|
+
import time
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class QaseUtils:
|
|
12
13
|
|
|
14
|
+
@staticmethod
|
|
15
|
+
def get_real_time() -> float:
|
|
16
|
+
"""
|
|
17
|
+
Get real system time, bypassing time mocking libraries like freezegun.
|
|
18
|
+
|
|
19
|
+
This is necessary when reporting test results to external systems that validate
|
|
20
|
+
timestamps against current time, even when tests are using time mocking.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
float: Current Unix timestamp in seconds with microsecond precision
|
|
24
|
+
"""
|
|
25
|
+
# Try to get the original time function if it was wrapped by freezegun
|
|
26
|
+
# freezegun stores the original function in __wrapped__ attribute
|
|
27
|
+
if hasattr(time.time, '__wrapped__'):
|
|
28
|
+
return time.time.__wrapped__()
|
|
29
|
+
|
|
30
|
+
# Fallback: use direct system call via ctypes
|
|
31
|
+
# This works on Unix-like systems and Windows
|
|
32
|
+
try:
|
|
33
|
+
import ctypes
|
|
34
|
+
import ctypes.util
|
|
35
|
+
|
|
36
|
+
if sys.platform == 'win32':
|
|
37
|
+
# Windows: use GetSystemTimeAsFileTime
|
|
38
|
+
class FILETIME(ctypes.Structure):
|
|
39
|
+
_fields_ = [("dwLowDateTime", ctypes.c_uint32),
|
|
40
|
+
("dwHighDateTime", ctypes.c_uint32)]
|
|
41
|
+
|
|
42
|
+
kernel32 = ctypes.windll.kernel32
|
|
43
|
+
ft = FILETIME()
|
|
44
|
+
kernel32.GetSystemTimeAsFileTime(ctypes.byref(ft))
|
|
45
|
+
|
|
46
|
+
# Convert FILETIME to Unix timestamp
|
|
47
|
+
# FILETIME is 100-nanosecond intervals since January 1, 1601
|
|
48
|
+
timestamp = (ft.dwHighDateTime << 32) + ft.dwLowDateTime
|
|
49
|
+
# Convert to seconds and adjust epoch (1601 -> 1970)
|
|
50
|
+
return (timestamp / 10000000.0) - 11644473600.0
|
|
51
|
+
else:
|
|
52
|
+
# Unix-like systems: use gettimeofday for microsecond precision
|
|
53
|
+
# Try multiple approaches to find libc
|
|
54
|
+
libc = None
|
|
55
|
+
|
|
56
|
+
# Method 1: Use find_library (works on most systems)
|
|
57
|
+
libc_path = ctypes.util.find_library('c')
|
|
58
|
+
if libc_path:
|
|
59
|
+
try:
|
|
60
|
+
libc = ctypes.CDLL(libc_path)
|
|
61
|
+
except OSError:
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
# Method 2: Try common library names directly (for Alpine Linux, musl libc, etc.)
|
|
65
|
+
if libc is None:
|
|
66
|
+
for lib_name in ['libc.so.6', 'libc.so', 'libc.dylib']:
|
|
67
|
+
try:
|
|
68
|
+
libc = ctypes.CDLL(lib_name)
|
|
69
|
+
break
|
|
70
|
+
except OSError:
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
if libc is None:
|
|
74
|
+
raise OSError("Could not load C library")
|
|
75
|
+
|
|
76
|
+
class timeval(ctypes.Structure):
|
|
77
|
+
_fields_ = [("tv_sec", ctypes.c_long),
|
|
78
|
+
("tv_usec", ctypes.c_long)]
|
|
79
|
+
|
|
80
|
+
tv = timeval()
|
|
81
|
+
libc.gettimeofday(ctypes.byref(tv), None)
|
|
82
|
+
|
|
83
|
+
return float(tv.tv_sec) + (float(tv.tv_usec) / 1000000.0)
|
|
84
|
+
except Exception:
|
|
85
|
+
# Last resort: return the potentially mocked time
|
|
86
|
+
# This will still work in normal cases without freezegun
|
|
87
|
+
# If freezegun is active, the user might see timestamp validation errors
|
|
88
|
+
# but the core functionality will continue to work
|
|
89
|
+
return time.time()
|
|
90
|
+
|
|
13
91
|
@staticmethod
|
|
14
92
|
def build_tree(items):
|
|
15
93
|
nodes = {item.id: item for item in items}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qase-python-commons
|
|
3
|
-
Version: 4.1.
|
|
3
|
+
Version: 4.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
|
|
@@ -31,6 +31,7 @@ Requires-Dist: mock; extra == "testing"
|
|
|
31
31
|
Requires-Dist: more_itertools; extra == "testing"
|
|
32
32
|
Requires-Dist: requests; extra == "testing"
|
|
33
33
|
Requires-Dist: urllib3; extra == "testing"
|
|
34
|
+
Requires-Dist: freezegun; extra == "testing"
|
|
34
35
|
|
|
35
36
|
# Qase Python Commons
|
|
36
37
|
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
qase/__init__.py,sha256=FLefSJnT6MTsTfZSDjMbMImI6674fAoJ5ZT3PNWGcRo,37
|
|
2
2
|
qase/commons/__init__.py,sha256=3HI65PJES4Q6YvtkSuRPh6tZboTETJo8wbdHlNYaePU,323
|
|
3
|
-
qase/commons/config.py,sha256=
|
|
3
|
+
qase/commons/config.py,sha256=SyG1-2RfKQAhQLUbq7szbUUp9ABYvbSiaT8WdQEjMcA,15556
|
|
4
4
|
qase/commons/loader.py,sha256=-MMY4HgSI6q1xq3NaJoq_w4liM73qdFKjYLVCT1E7Pc,1064
|
|
5
5
|
qase/commons/logger.py,sha256=V_QTSDWNnUgd0j58rydYYN1AYOu3wa9T2fWjpOyxyuA,3430
|
|
6
|
-
qase/commons/utils.py,sha256=
|
|
7
|
-
qase/commons/client/api_v1_client.py,sha256=
|
|
6
|
+
qase/commons/utils.py,sha256=0TtpLvyAdh7fLQW4HA_6aQM8kWy4a8VtSD_KdkRVZlw,6775
|
|
7
|
+
qase/commons/client/api_v1_client.py,sha256=BaE9Ix-k5Xc7Wiz8ILKKsWb5G5J3hqgjwaIcrocvCdY,12879
|
|
8
8
|
qase/commons/client/api_v2_client.py,sha256=GsIrXJcBw6GtzvJjbjMYa0tvUIxEEe4pALRN2LBMKPM,9043
|
|
9
|
-
qase/commons/client/base_api_client.py,sha256=
|
|
9
|
+
qase/commons/client/base_api_client.py,sha256=4NtXhUxrxEPOBIzEAE-b50KHMwlhxwnSLGcYx8NMjbY,2961
|
|
10
10
|
qase/commons/exceptions/reporter.py,sha256=dP-Mwcq8HKBOjgu3YqhyULDmDGU09BmT6Fh9HjICaUc,45
|
|
11
11
|
qase/commons/models/__init__.py,sha256=FTt5dYASBX4r6-tQi-_JAUVx4uvJs9GTxROdAZEV6Jo,272
|
|
12
12
|
qase/commons/models/attachment.py,sha256=cGfB0BaTDVfA7euJubKvi2cXXNvlSm_dy5x-ak3H3ec,1625
|
|
13
13
|
qase/commons/models/basemodel.py,sha256=0j8E-LE6hxAKQPYLNM9qThor9s2ZndZys_kibeoLImo,426
|
|
14
14
|
qase/commons/models/external_link.py,sha256=bdXj7pNHHkfb3dcYtXN8sNp-HFxHvZeYz8QIPGcvX0w,1317
|
|
15
15
|
qase/commons/models/relation.py,sha256=HymHeh1uBcoQnTs4Vra7WJ_KFkhryj5o7cShjoGQImI,511
|
|
16
|
-
qase/commons/models/result.py,sha256=
|
|
16
|
+
qase/commons/models/result.py,sha256=53udABcu_Gzm-vvnvvb9mFui8-el-N41vCU2Dsual84,4047
|
|
17
17
|
qase/commons/models/run.py,sha256=ANbljW1mgua4JF1wGZG9S-jnUpI7FC4F15sAQOoNnko,3096
|
|
18
18
|
qase/commons/models/runtime.py,sha256=h0kJcPYRo8dglIQVFyzh-cFpWb3bAaQaIq5wV8VfClM,1508
|
|
19
|
-
qase/commons/models/step.py,sha256=
|
|
19
|
+
qase/commons/models/step.py,sha256=AU7AtNlZBAokWWIlazZ6Gef_ua0g6qDUFD98I6GmDiY,5486
|
|
20
20
|
qase/commons/models/config/api.py,sha256=IyYY2f3ncESUAEGvkE3-meatebBFJdvgo7KNOQnxLE0,288
|
|
21
21
|
qase/commons/models/config/batch.py,sha256=X0H8SVOCCD2pV6LSMqjI-tIjRcLifnrM5MareK2FhQw,321
|
|
22
22
|
qase/commons/models/config/connection.py,sha256=wK2fGjc0G0rMVVhPnjw_t_M1YWZwANlhwl-awmI7XSo,516
|
|
@@ -25,21 +25,21 @@ qase/commons/models/config/plan.py,sha256=JbAY7qfGXYreXOLa32OLxw6z0paeCCf87-2b1m
|
|
|
25
25
|
qase/commons/models/config/qaseconfig.py,sha256=oWc03PKV8-jb3JNgs_tqQP-22wsKZW25eSaAacYl4no,2838
|
|
26
26
|
qase/commons/models/config/report.py,sha256=g3Z2B3Tewaasjc1TMj2mkXxz0Zc1C39sHeTXH0MRM2Y,497
|
|
27
27
|
qase/commons/models/config/run.py,sha256=UGE5PA_EyiFpfIev-TOob1BocxT1vdUdWW3ELMD58zQ,1239
|
|
28
|
-
qase/commons/models/config/testops.py,sha256=
|
|
28
|
+
qase/commons/models/config/testops.py,sha256=LdylcNG1ctxjNHXwrwcerAKY3h0WByKWYIrKOzEV2K8,2133
|
|
29
29
|
qase/commons/profilers/__init__.py,sha256=GhKT5hRbHbhAC4GhdyChA8XoAsGQOnIb8S2Z4-fdS7Q,222
|
|
30
30
|
qase/commons/profilers/db.py,sha256=Am1tvvLgJq4_A8JsuSeBGf47BD2lnSX-5KiMjSgr-Ko,391
|
|
31
31
|
qase/commons/profilers/network.py,sha256=zKNBnTQG4BMg8dn8O--tQzQLpu-qs5ADhHEnqIas0gM,4950
|
|
32
32
|
qase/commons/profilers/sleep.py,sha256=HT6h0R-2XHZAoBYRxS2T_KC8RrnEoVjP7MXusaE4Nec,1624
|
|
33
33
|
qase/commons/reporters/__init__.py,sha256=J0aNLzb_MPPT_zF8BtX_w9nj_U7Ad06RGpyWK5Pxq1o,169
|
|
34
34
|
qase/commons/reporters/core.py,sha256=FJx1kxXkUz9vwkSAXapkNS3vF97Igvlq7Yyjp-4BpeI,9539
|
|
35
|
-
qase/commons/reporters/report.py,sha256=
|
|
36
|
-
qase/commons/reporters/testops.py,sha256=
|
|
35
|
+
qase/commons/reporters/report.py,sha256=2hrpQGhtgEaDphRIiAiVtC1C1YWz3--jy4mw-kvO8lY,4838
|
|
36
|
+
qase/commons/reporters/testops.py,sha256=k3c91l_xuLq6NRLkzfwRqRTLfnpSxEQe38HNH8XMOTk,8161
|
|
37
37
|
qase/commons/status_mapping/__init__.py,sha256=NPsWKDC7rGSCYfVunnGnHxL0_HmKWH7RBaMjWTH_Mtk,322
|
|
38
38
|
qase/commons/status_mapping/status_mapping.py,sha256=kohSLNK6_qbMSP-M8gxHTTmOECgzDE3XvLqOzidPlYI,7213
|
|
39
39
|
qase/commons/util/__init__.py,sha256=0sRRfrMOIPCHpk9tXM94Pj10qrk18B61qEcbLpRjw_I,74
|
|
40
40
|
qase/commons/util/host_data.py,sha256=n8o5PDs8kELCZZ5GR7Jug6LsgZHWJudU7iRmZHRdrlw,5264
|
|
41
41
|
qase/commons/validators/base.py,sha256=wwSn-4YiuXtfGMGnSKgo9Vm5hAKevVmmfd2Ro6Q7MYQ,173
|
|
42
|
-
qase_python_commons-4.1.
|
|
43
|
-
qase_python_commons-4.1.
|
|
44
|
-
qase_python_commons-4.1.
|
|
45
|
-
qase_python_commons-4.1.
|
|
42
|
+
qase_python_commons-4.1.2.dist-info/METADATA,sha256=NISziDSmN_RTWKgMJ2SrdiLkV42IbzDY1VVPdzcPoU8,2027
|
|
43
|
+
qase_python_commons-4.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
44
|
+
qase_python_commons-4.1.2.dist-info/top_level.txt,sha256=Mn5aFk7H7Uia4s1NRDsvebu8vCrFy9nOuRIBfkIY5kQ,5
|
|
45
|
+
qase_python_commons-4.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|