qase-python-commons 3.1.8__py3-none-any.whl → 3.2.0__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.

@@ -8,6 +8,7 @@ from .. import Logger
8
8
  from .base_api_client import BaseApiClient
9
9
  from ..exceptions.reporter import ReporterException
10
10
  from ..models import Attachment, Result, Step
11
+ from ..models.config.framework import Video, Trace
11
12
  from ..models.config.qaseconfig import QaseConfig
12
13
  from ..models.step import StepType
13
14
 
@@ -137,6 +138,8 @@ class ApiV1Client(BaseApiClient):
137
138
  attached = []
138
139
  if result.attachments:
139
140
  for attachment in result.attachments:
141
+ if self.__should_skip_attachment(attachment, result):
142
+ continue
140
143
  attach_id = self._upload_attachment(project_code, attachment)
141
144
  if attach_id:
142
145
  attached.extend(attach_id)
@@ -168,8 +171,14 @@ class ApiV1Client(BaseApiClient):
168
171
  case_data["layer"] = result.get_field('layer')
169
172
 
170
173
  suite = None
171
- if result.get_suite_title():
172
- suite = "\t".join(result.get_suite_title().split("."))
174
+ if result.relations is not None and result.relations.suite is not None and len(
175
+ result.relations.suite.data) != 0:
176
+ suites = []
177
+
178
+ for raw in result.relations.suite.data:
179
+ suites.append(raw.title)
180
+
181
+ suite = "\t".join(suites)
173
182
 
174
183
  if result.get_field('suite'):
175
184
  suite = result.get_field('suite')
@@ -278,3 +287,14 @@ class ApiV1Client(BaseApiClient):
278
287
  self.__authors[author] = authors.result.entities[0].author_id
279
288
 
280
289
  return authors.result.entities[0].author_id
290
+
291
+ def __should_skip_attachment(self, attachment, result):
292
+ if (self.config.framework.playwright.video == Video.failed and
293
+ result.execution.status != 'failed' and
294
+ attachment.file_name == 'video.webm'):
295
+ return True
296
+ if (self.config.framework.playwright.trace == Trace.failed and
297
+ result.execution.status != 'failed' and
298
+ attachment.file_name == 'trace.zip'):
299
+ return True
300
+ return False
@@ -1,7 +1,7 @@
1
1
  from typing import Dict
2
2
 
3
3
  import certifi
4
- from qase.api_client_v2 import ResultsApi
4
+ from qase.api_client_v2 import ResultsApi, ResultCreateFields
5
5
  from qase.api_client_v2.api_client import ApiClient
6
6
  from qase.api_client_v2.configuration import Configuration
7
7
  from qase.api_client_v2.models.create_results_request_v2 import CreateResultsRequestV2
@@ -75,23 +75,25 @@ class ApiV2Client(ApiV1Client):
75
75
  execution=ResultExecution(start_time=result.execution.start_time, end_time=result.execution.end_time,
76
76
  status=result.execution.status, duration=result.execution.duration,
77
77
  stacktrace=result.execution.stacktrace, thread=result.execution.thread),
78
- fields=result.fields,
78
+ fields=ResultCreateFields.from_dict(result.fields),
79
79
  attachments=[attach.hash for attach in attached],
80
80
  steps=steps,
81
- step_type=ResultStepsType.CLASSIC,
81
+ steps_type=ResultStepsType.CLASSIC,
82
82
  params=result.params,
83
+ param_groups=result.param_groups,
83
84
  muted=False,
84
85
  message=result.message,
85
86
  )
86
87
 
87
- if result.get_suite_title():
88
+ if result.relations is not None and result.relations.suite is not None and len(
89
+ result.relations.suite.data) != 0:
88
90
  data = []
89
91
  root_suite = self.config.root_suite
90
92
  if root_suite:
91
93
  data.append(RelationSuiteItem(title=root_suite))
92
94
 
93
- for suite in result.get_suite_title().split("."):
94
- data.append(RelationSuiteItem(title=suite))
95
+ for raw in result.relations.suite.data:
96
+ data.append(RelationSuiteItem(title=raw.title))
95
97
 
96
98
  result_model_v2.relations = ResultRelations(suite=RelationSuite(data=data))
97
99
 
@@ -1,7 +1,6 @@
1
1
  from .result import Result, Field
2
2
  from .run import Run
3
3
  from .attachment import Attachment
4
- from .suite import Suite
5
4
  from .relation import Relation
6
5
  from .step import Step
7
6
  from .runtime import Runtime
@@ -10,7 +9,6 @@ __all__ = [
10
9
  Result,
11
10
  Run,
12
11
  Attachment,
13
- Suite,
14
12
  Relation,
15
13
  Step,
16
14
  Runtime,
@@ -1,7 +1,22 @@
1
+ from enum import Enum
2
+ from typing import Type, Union
3
+
1
4
  from ..basemodel import BaseModel
2
5
  from ... import QaseUtils
3
6
 
4
7
 
8
+ class Video(Enum):
9
+ off = "off"
10
+ on = "on"
11
+ failed = "retain-on-failure"
12
+
13
+
14
+ class Trace(Enum):
15
+ off = "off"
16
+ on = "on"
17
+ failed = "retain-on-failure"
18
+
19
+
5
20
  class PytestConfig(BaseModel):
6
21
  capture_logs: bool = None
7
22
 
@@ -12,8 +27,37 @@ class PytestConfig(BaseModel):
12
27
  self.capture_logs = QaseUtils.parse_bool(capture_logs)
13
28
 
14
29
 
30
+ class PlaywrightConfig(BaseModel):
31
+ output_dir: str = None
32
+ video: Video = None
33
+ trace: Trace = None
34
+
35
+ def __init__(self):
36
+ self.output_dir = "test-results"
37
+ self.video = Video.off
38
+ self.trace = Trace.off
39
+
40
+ def set_output_dir(self, output_dir: str):
41
+ self.output_dir = output_dir
42
+
43
+ def set_video(self, value: str):
44
+ self.video = self.__set_mode(Video, value)
45
+
46
+ def set_trace(self, value: str):
47
+ self.trace = self.__set_mode(Trace, value)
48
+
49
+ @staticmethod
50
+ def __set_mode(enum_class: Type[Union[Video, Trace]], value: str):
51
+ for mode in enum_class:
52
+ if mode.value == value:
53
+ return mode
54
+ return None
55
+
56
+
15
57
  class Framework(BaseModel):
16
58
  pytest: PytestConfig = None
59
+ playwright: PlaywrightConfig = None
17
60
 
18
61
  def __init__(self):
19
62
  self.pytest = PytestConfig()
63
+ self.playwright = PlaywrightConfig()
@@ -1,13 +1,23 @@
1
1
  from .basemodel import BaseModel
2
2
 
3
3
 
4
- class RelationSuite(BaseModel):
5
- def __init__(self, suite_id: int, title: str) -> None:
6
- self.suite_id = suite_id
4
+ class SuiteData(BaseModel):
5
+ def __init__(self, title: str) -> None:
6
+ self.public_id = None
7
7
  self.title = title
8
8
 
9
9
 
10
+ class RelationSuite(BaseModel):
11
+ def __init__(self) -> None:
12
+ self.data = []
13
+
14
+ def add_data(self, data: SuiteData) -> None:
15
+ self.data.append(data)
16
+
17
+
10
18
  class Relation(BaseModel):
11
- def __init__(self, type: str, data: RelationSuite):
12
- self.type = type
13
- self.data = data
19
+ def __init__(self):
20
+ self.suite = RelationSuite()
21
+
22
+ def add_suite(self, suite: SuiteData) -> None:
23
+ self.suite.add_data(suite)
@@ -4,7 +4,6 @@ import uuid
4
4
  from typing import Type, Optional, Union, Dict, List
5
5
  from .basemodel import BaseModel
6
6
  from .step import Step
7
- from .suite import Suite
8
7
  from .attachment import Attachment
9
8
  from .relation import Relation
10
9
  from .. import QaseUtils
@@ -79,10 +78,9 @@ class Result(BaseModel):
79
78
  self.params: Optional[dict] = {}
80
79
  self.param_groups: Optional[List[List[str]]] = []
81
80
  self.author: Optional[str] = None
82
- self.relations: List[Type[Relation]] = []
81
+ self.relations: Type[Relation] = None
83
82
  self.muted: bool = False
84
83
  self.message: Optional[str] = None
85
- self.suite: Optional[Type[Suite]] = None
86
84
  QaseUtils.get_host_data()
87
85
 
88
86
  def add_message(self, message: str) -> None:
@@ -97,20 +95,14 @@ class Result(BaseModel):
97
95
  def add_attachment(self, attachment: Attachment) -> None:
98
96
  self.attachments.append(attachment)
99
97
 
100
- def add_relation(self, relation: Type[Relation]) -> None:
101
- self.relations.append(relation)
102
-
103
98
  def add_param(self, key: str, value: str) -> None:
104
99
  self.params[key] = value
105
100
 
106
101
  def add_param_groups(self, values: List[str]) -> None:
107
102
  self.param_groups.append(values)
108
103
 
109
- def add_relation(self, relation: Type[Relation]) -> None:
110
- self.relations.append(relation)
111
-
112
- def add_suite(self, suite: Type[Suite]) -> None:
113
- self.suite = suite
104
+ def set_relation(self, relation: Relation) -> None:
105
+ self.relations = relation
114
106
 
115
107
  def get_status(self) -> Optional[str]:
116
108
  return self.execution.status
@@ -127,17 +119,10 @@ class Result(BaseModel):
127
119
  return None
128
120
 
129
121
  def get_testops_id(self) -> Optional[int]:
130
- if self.testops_id is None:
131
- # Hack for old API
132
- return 0
133
122
  return self.testops_id
134
123
 
135
124
  def get_duration(self) -> int:
136
125
  return self.execution.duration
137
126
 
138
- def get_suite_title(self) -> Optional[str]:
139
- if self.suite:
140
- return self.suite.title
141
-
142
127
  def set_run_id(self, run_id: str) -> None:
143
128
  self.run_id = run_id
@@ -68,13 +68,19 @@ class QaseReport:
68
68
  mode = "w"
69
69
  if isinstance(attachment.content, bytes):
70
70
  mode = "wb"
71
- with open(f"{self.report_path}/attachments/{attachment.id}-{attachment.file_name}", mode) as f:
71
+
72
+ file_path = f"{self.report_path}/attachments/{attachment.id}-{attachment.file_name}"
73
+ with open(file_path, mode) as f:
72
74
  f.write(attachment.content)
73
75
  # Clear content to save memory and avoid double writing
74
76
  attachment.content = None
77
+ attachment.file_path = file_path
78
+
75
79
  elif attachment.file_path:
80
+ file_path = f"{self.report_path}/attachments/{attachment.id}-{attachment.file_name}"
76
81
  shutil.copy2(os.path.abspath(attachment.file_path),
77
82
  f"{self.report_path}/attachments/{attachment.id}-{attachment.file_name}")
83
+ attachment.file_path = file_path
78
84
 
79
85
  def _persist_attachments_in_steps(self, steps: list):
80
86
  for step in steps:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qase-python-commons
3
- Version: 3.1.8
3
+ Version: 3.2.0
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/master/qase-python-commons
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
23
23
  Requires-Dist: certifi>=2024.2.2
24
24
  Requires-Dist: attrs>=23.2.0
25
25
  Requires-Dist: qase-api-client~=1.1.1
26
- Requires-Dist: qase-api-v2-client~=1.0.0
26
+ Requires-Dist: qase-api-v2-client~=1.1.0
27
27
  Requires-Dist: more-itertools
28
28
  Provides-Extra: testing
29
29
  Requires-Dist: pytest; extra == "testing"
@@ -3,23 +3,22 @@ qase/commons/config.py,sha256=meRRgDrsA9qQ9fZR4fnP0VdngrKiGcHF9nnJkf3eJpg,8320
3
3
  qase/commons/loader.py,sha256=-MMY4HgSI6q1xq3NaJoq_w4liM73qdFKjYLVCT1E7Pc,1064
4
4
  qase/commons/logger.py,sha256=ka5chQYBXLUB5pM4YHDBo3QCZfBTGMtC3H33tI4NbPQ,1027
5
5
  qase/commons/utils.py,sha256=OOr6kQ5hPZEyHXwbwiTOTkonRxmmtkyZPPGqXQKp5vY,2799
6
- qase/commons/client/api_v1_client.py,sha256=t93-wqb9Rxgsvsk49toRZPeaTtBUVWsDk-UQ8gpy9pU,11880
7
- qase/commons/client/api_v2_client.py,sha256=F3wU_2EKe6eUjNRahvnDmpbx99PwZB6Lxc4VPRj7w58,7247
6
+ qase/commons/client/api_v1_client.py,sha256=YIaRWu9txJoIljcvPJ-4MECqgw72oae-o6z0Bl9t-Jo,12715
7
+ qase/commons/client/api_v2_client.py,sha256=sh748gx9jjqBm42IrSeOduBWs6jKzz5QqCWSKcURDOA,7440
8
8
  qase/commons/client/base_api_client.py,sha256=H8JnjqSrBFNfghDd3T3zxYOyKYHYe9QiJQXol1JqdQk,2613
9
9
  qase/commons/exceptions/reporter.py,sha256=dP-Mwcq8HKBOjgu3YqhyULDmDGU09BmT6Fh9HjICaUc,45
10
- qase/commons/models/__init__.py,sha256=66rxcTqtfbx_zPshJW3f5JxtC4aoaDSCC0izyY_9GGI,308
10
+ qase/commons/models/__init__.py,sha256=FTt5dYASBX4r6-tQi-_JAUVx4uvJs9GTxROdAZEV6Jo,272
11
11
  qase/commons/models/attachment.py,sha256=Rjq1mAP11uk7TN2RrtImntw6DUMV7U0R-44TYj8O5j0,1432
12
12
  qase/commons/models/basemodel.py,sha256=nyDSXhpQUecKdzhB-eWqujmso20oXB9p_42qpOsGVuQ,213
13
- qase/commons/models/relation.py,sha256=Hscui14vuSdKVdPPej4V1-SF4XHvJ2Tqg0KH8d49dH0,321
14
- qase/commons/models/result.py,sha256=im6L5F44yXAyD6HQy8kP9fncjrKn-7HN30ZnezSdi_Q,4423
13
+ qase/commons/models/relation.py,sha256=HymHeh1uBcoQnTs4Vra7WJ_KFkhryj5o7cShjoGQImI,511
14
+ qase/commons/models/result.py,sha256=RWryOX85T-_T3AngrGuREtwmPq6FyOPvM77H949vm1I,3953
15
15
  qase/commons/models/run.py,sha256=KkplvlHJNvVLORzVkdz5mHsLFBTUAdtuEYCqCy_RcvU,2469
16
16
  qase/commons/models/runtime.py,sha256=mfK-mOViD1orXOx-jP6nIgtnN0tUmRYY1aMH0qFDmXA,1287
17
17
  qase/commons/models/step.py,sha256=M-btRYZ4febYavDhwFqmKcCdLAgrhtuv7E_M3TKZdfg,4281
18
- qase/commons/models/suite.py,sha256=Z2tlxdeIsuzjIoPnuyVq23pt59Yt6LVmofcew5Njk_s,348
19
18
  qase/commons/models/config/api.py,sha256=IyYY2f3ncESUAEGvkE3-meatebBFJdvgo7KNOQnxLE0,288
20
19
  qase/commons/models/config/batch.py,sha256=X0H8SVOCCD2pV6LSMqjI-tIjRcLifnrM5MareK2FhQw,321
21
20
  qase/commons/models/config/connection.py,sha256=wK2fGjc0G0rMVVhPnjw_t_M1YWZwANlhwl-awmI7XSo,516
22
- qase/commons/models/config/framework.py,sha256=upGHFwmJ-i-VA_OLPgJiwgJRjB7vusuk-dhJMhgdYDM,416
21
+ qase/commons/models/config/framework.py,sha256=N4vSS1EAu8LEzYSbpy3Z4rNY2DbpWQ4Mh1mknRfMDRM,1432
23
22
  qase/commons/models/config/plan.py,sha256=JbAY7qfGXYreXOLa32OLxw6z0paeCCf87-2b1m8xkks,137
24
23
  qase/commons/models/config/qaseconfig.py,sha256=-tuTsd6s4YSAkSca7vvNaFZbqhbWkxuw-mjeqhwmjlc,1722
25
24
  qase/commons/models/config/report.py,sha256=g3Z2B3Tewaasjc1TMj2mkXxz0Zc1C39sHeTXH0MRM2Y,497
@@ -31,10 +30,10 @@ qase/commons/profilers/network.py,sha256=zKNBnTQG4BMg8dn8O--tQzQLpu-qs5ADhHEnqIa
31
30
  qase/commons/profilers/sleep.py,sha256=HT6h0R-2XHZAoBYRxS2T_KC8RrnEoVjP7MXusaE4Nec,1624
32
31
  qase/commons/reporters/__init__.py,sha256=J0aNLzb_MPPT_zF8BtX_w9nj_U7Ad06RGpyWK5Pxq1o,169
33
32
  qase/commons/reporters/core.py,sha256=0x5G-KVfEOWyXiXaX5__7JBIr3Rxy8vhy0cByUSZUc0,8021
34
- qase/commons/reporters/report.py,sha256=MPsFv3k2l4652NyXEGFiSmwsSpwZT3Is-lLRXvsniz4,4606
33
+ qase/commons/reporters/report.py,sha256=zyGeUOcJCOEoGtsewCOf3kypbPttJH7EM-LmZ_Y5huY,4829
35
34
  qase/commons/reporters/testops.py,sha256=f5BcorFwIK5BSeA4Rv4IKDddkWrAXL_w-Y5Xn--NdYs,6264
36
35
  qase/commons/validators/base.py,sha256=wwSn-4YiuXtfGMGnSKgo9Vm5hAKevVmmfd2Ro6Q7MYQ,173
37
- qase_python_commons-3.1.8.dist-info/METADATA,sha256=6lr1O9vlI3BDkCu9ekgNJ9HqC0Yxl0Cj3PMTMYJ1Tog,1859
38
- qase_python_commons-3.1.8.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
39
- qase_python_commons-3.1.8.dist-info/top_level.txt,sha256=Mn5aFk7H7Uia4s1NRDsvebu8vCrFy9nOuRIBfkIY5kQ,5
40
- qase_python_commons-3.1.8.dist-info/RECORD,,
36
+ qase_python_commons-3.2.0.dist-info/METADATA,sha256=7HxmqCpafL3UdsAHcKASQNFBnrubf9S3Crud2NQM8QQ,1859
37
+ qase_python_commons-3.2.0.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
38
+ qase_python_commons-3.2.0.dist-info/top_level.txt,sha256=Mn5aFk7H7Uia4s1NRDsvebu8vCrFy9nOuRIBfkIY5kQ,5
39
+ qase_python_commons-3.2.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,13 +0,0 @@
1
- import uuid
2
-
3
- from typing import List, Optional
4
-
5
- from .basemodel import BaseModel
6
-
7
-
8
- class Suite(BaseModel):
9
- def __init__(self, title: str, description: Optional[str] = None, parent_id: Optional[str] = None):
10
- self.title = title
11
- self.description = description
12
- self.parent_id = parent_id
13
- self.id = str(uuid.uuid4())