Skip to content

Commit 9bd8dfc

Browse files
authored
Merge pull request #170 from reportportal/develop
Release
2 parents 077130e + 5f2f2ff commit 9bd8dfc

28 files changed

+253
-340
lines changed

.flake8

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[flake8]
2+
max-line-length = 119

.github/workflows/tests.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ on:
3131

3232
jobs:
3333
build:
34-
runs-on: ubuntu-20.04
34+
runs-on: ubuntu-latest
3535
strategy:
3636
matrix:
37-
python-version: [ '2.7', '3.6', '3.7', '3.8', '3.9', '3.10' ]
37+
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11' ]
3838
steps:
3939
- name: Checkout repository
4040
uses: actions/checkout@v3
@@ -53,7 +53,7 @@ jobs:
5353
run: tox
5454

5555
- name: Upload coverage to Codecov
56-
if: matrix.python-version == 3.6 && success()
56+
if: matrix.python-version == 3.7 && success()
5757
uses: codecov/codecov-action@v3
5858
with:
5959
files: coverage.xml

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
# Changelog
22

33
## [Unreleased]
4+
### Added
5+
- `RP_LAUNCH_UUID_PRINT` and `RP_LAUNCH_UUID_PRINT_OUTPUT` configuration variables, by @HardNorth
6+
### Changed
7+
- Internal item list was replaced with LifoQueue, by @HardNorth
8+
- Client version updated on [5.4.0](https://github.com/reportportal/client-Python/releases/tag/5.4.0), by @HardNorth
9+
- `service.RobotService.init_service` method now accepts `variables.Variables` object as single argument instead of many of them, which were just copy-paste, by @HardNorth
10+
### Removed
11+
- Python 2.7, 3.6 support, by @HardNorth
12+
13+
## [5.3.3]
414
### Changed
515
- Client version updated on [5.3.5](https://github.com/reportportal/client-Python/releases/tag/5.3.5), by @HardNorth
616
- The Agent publish a warning and does not report anything in case of a missed required variable now, by @HardNorth

requirements-dev.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Dev dependencies
2+
pytest
3+
pytest-cov
4+
delayed_assert
5+
robotframework-datadriver

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1+
# Basic dependencies
12
python-dateutil>=2.8.1
2-
reportportal-client==5.3.5
3+
reportportal-client==5.4.0
34
robotframework
45
six>=1.15.0

robotframework_reportportal/exception.py

-17
This file was deleted.

robotframework_reportportal/listener.py

+55-49
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
import os
1919
from functools import wraps
2020
from mimetypes import guess_type
21+
from typing import Optional, Dict, Union, Any
22+
from queue import LifoQueue
23+
from warnings import warn
2124

2225
from reportportal_client.helpers import gen_attributes
2326

24-
from .exception import RobotServiceException
2527
from .model import Keyword, Launch, Test, LogMessage, Suite
2628
from .service import RobotService
2729
from .static import MAIN_SUITE_ID, PABOT_WIHOUT_LAUNCH_ID_MSG
@@ -30,6 +32,13 @@
3032
logger = logging.getLogger(__name__)
3133

3234

35+
class _LifoQueue(LifoQueue):
36+
def last(self):
37+
with self.mutex:
38+
if self._qsize():
39+
return self.queue[-1]
40+
41+
3342
def check_rp_enabled(func):
3443
"""Verify is RP is enabled in config."""
3544
@wraps(func)
@@ -41,18 +50,22 @@ def wrap(*args, **kwargs):
4150
return wrap
4251

4352

44-
class listener(object):
53+
# noinspection PyPep8Naming
54+
class listener:
4555
"""Robot Framework listener interface for reporting to Report Portal."""
4656

57+
_items: _LifoQueue = ...
58+
_service: Optional[RobotService] = ...
59+
_variables: Optional[Variables] = ...
4760
ROBOT_LISTENER_API_VERSION = 2
4861

49-
def __init__(self):
62+
def __init__(self) -> None:
5063
"""Initialize listener attributes."""
51-
self._items = []
64+
self._items = _LifoQueue()
5265
self._service = None
5366
self._variables = None
5467

55-
def _build_msg_struct(self, message):
68+
def _build_msg_struct(self, message: Dict) -> LogMessage:
5669
"""Check if the given message comes from our custom logger or not.
5770
5871
:param message: Message passed by the Robot Framework
@@ -66,18 +79,21 @@ def _build_msg_struct(self, message):
6679
msg.item_id = getattr(self.current_item, 'rp_item_id', None)
6780
return msg
6881

69-
def _finish_current_item(self):
70-
"""Remove the last item from the self._items list."""
71-
return self._items.pop()
82+
def _add_current_item(self, item: Union[Keyword, Launch, Suite, Test]) -> None:
83+
"""Add the last item from the self._items queue."""
84+
self._items.put(item)
85+
86+
def _remove_current_item(self) -> Union[Keyword, Launch, Suite, Test]:
87+
"""Remove the last item from the self._items queue."""
88+
return self._items.get()
7289

7390
@property
74-
def current_item(self):
75-
"""Get the last item from the self._items list."""
76-
if self._items:
77-
return self._items[-1]
91+
def current_item(self) -> Optional[Union[Keyword, Launch, Suite, Test]]:
92+
"""Get the last item from the self._items queue."""
93+
return self._items.last()
7894

7995
@check_rp_enabled
80-
def log_message(self, message):
96+
def log_message(self, message: Dict) -> None:
8197
"""Send log message to the Report Portal.
8298
8399
:param message: Message passed by the Robot Framework
@@ -87,7 +103,7 @@ def log_message(self, message):
87103
self.service.log(message=msg)
88104

89105
@check_rp_enabled
90-
def log_message_with_image(self, msg, image):
106+
def log_message_with_image(self, msg: Dict, image: str):
91107
"""Send log message to the Report Portal.
92108
93109
:param msg: Message passed by the Robot Framework
@@ -105,37 +121,27 @@ def log_message_with_image(self, msg, image):
105121
self.service.log(message=mes)
106122

107123
@property
108-
def parent_id(self):
124+
def parent_id(self) -> Optional[str]:
109125
"""Get rp_item_id attribute of the current item."""
110126
return getattr(self.current_item, 'rp_item_id', None)
111127

112128
@property
113-
def service(self):
129+
def service(self) -> RobotService:
114130
"""Initialize instance of the RobotService."""
115-
if self.variables.enabled and self._service is None:
131+
if self.variables.enabled and not self._service:
116132
self._service = RobotService()
117-
self._service.init_service(
118-
endpoint=self.variables.endpoint,
119-
project=self.variables.project,
120-
api_key=self.variables.api_key,
121-
log_batch_size=self.variables.log_batch_size,
122-
pool_size=self.variables.pool_size,
123-
skipped_issue=self.variables.skipped_issue,
124-
verify_ssl=self.variables.verify_ssl,
125-
log_batch_payload_size=self.variables.log_batch_payload_size,
126-
launch_id=self.variables.launch_id,
127-
)
133+
self._service.init_service(self.variables)
128134
return self._service
129135

130136
@property
131-
def variables(self):
137+
def variables(self) -> Variables:
132138
"""Get instance of the variables.Variables class."""
133139
if not self._variables:
134140
self._variables = Variables()
135141
return self._variables
136142

137143
@check_rp_enabled
138-
def start_launch(self, attributes, ts=None):
144+
def start_launch(self, attributes: Dict, ts: Optional[Any] = None) -> None:
139145
"""Start a new launch at the Report Portal.
140146
141147
:param attributes: Dictionary passed by the Robot Framework
@@ -146,7 +152,7 @@ def start_launch(self, attributes, ts=None):
146152
launch.doc = self.variables.launch_doc or launch.doc
147153
if not self.variables.launch_id:
148154
if self.variables.pabot_used:
149-
raise RobotServiceException(PABOT_WIHOUT_LAUNCH_ID_MSG)
155+
warn(PABOT_WIHOUT_LAUNCH_ID_MSG, stacklevel=2)
150156
logger.debug('ReportPortal - Start Launch: {0}'.format(
151157
launch.attributes))
152158
self.service.start_launch(
@@ -159,7 +165,7 @@ def start_launch(self, attributes, ts=None):
159165
self.service.rp.launch_id = self.variables.launch_id
160166

161167
@check_rp_enabled
162-
def start_suite(self, name, attributes, ts=None):
168+
def start_suite(self, name: str, attributes: Dict, ts: Optional[Any] = None) -> None:
163169
"""Start a new test suite at the Report Portal.
164170
165171
:param name: Test suite name
@@ -175,23 +181,23 @@ def start_suite(self, name, attributes, ts=None):
175181
.format(attributes))
176182
suite = Suite(name, attributes)
177183
suite.rp_item_id = self.service.start_suite(suite=suite, ts=ts)
178-
self._items.append(suite)
184+
self._add_current_item(suite)
179185
else:
180186
logger.debug('ReportPortal - Start Suite: {0}'.format(attributes))
181187
suite = Suite(name, attributes)
182188
suite.rp_parent_item_id = self.parent_id
183189
suite.rp_item_id = self.service.start_suite(suite=suite, ts=ts)
184-
self._items.append(suite)
190+
self._add_current_item(suite)
185191

186192
@check_rp_enabled
187-
def end_suite(self, _, attributes, ts=None):
193+
def end_suite(self, _: Optional[str], attributes: Dict, ts: Optional[Any] = None) -> None:
188194
"""Finish started test suite at the Report Portal.
189195
190196
:param attributes: Dictionary passed by the Robot Framework
191197
:param ts: Timestamp(used by the ResultVisitor)
192198
"""
193199
if attributes['id'] == MAIN_SUITE_ID:
194-
suite = self._finish_current_item().update(attributes)
200+
suite = self._remove_current_item().update(attributes)
195201
logger.debug('ReportPortal - End Suite: {0}'
196202
.format(suite.attributes))
197203
self.service.finish_suite(suite=suite, ts=ts)
@@ -200,13 +206,13 @@ def end_suite(self, _, attributes, ts=None):
200206
msg='ReportPortal - End Launch: {0}'.format(attributes))
201207
self.service.finish_launch(launch=launch, ts=ts)
202208
else:
203-
suite = self._finish_current_item().update(attributes)
209+
suite = self._remove_current_item().update(attributes)
204210
logger.debug(
205211
'ReportPortal - End Suite: {0}'.format(suite.attributes))
206212
self.service.finish_suite(suite=suite, ts=ts)
207213

208214
@check_rp_enabled
209-
def start_test(self, name, attributes, ts=None):
215+
def start_test(self, name: str, attributes: Dict, ts: Optional[Any] = None) -> None:
210216
"""Start a new test case at the Report Portal.
211217
212218
:param name: Test case name
@@ -223,10 +229,10 @@ def start_test(self, name, attributes, ts=None):
223229
self.variables.test_attributes + test.tags)
224230
test.rp_parent_item_id = self.parent_id
225231
test.rp_item_id = self.service.start_test(test=test, ts=ts)
226-
self._items.append(test)
232+
self._add_current_item(test)
227233

228234
@check_rp_enabled
229-
def end_test(self, _, attributes, ts=None):
235+
def end_test(self, _: Optional[str], attributes: Dict, ts: Optional[Any] = None) -> None:
230236
"""Finish started test case at the Report Portal.
231237
232238
:param attributes: Dictionary passed by the Robot Framework
@@ -240,11 +246,11 @@ def end_test(self, _, attributes, ts=None):
240246
if test.message:
241247
self.log_message({'message': test.message, 'level': 'DEBUG'})
242248
logger.debug('ReportPortal - End Test: {0}'.format(test.attributes))
243-
self._finish_current_item()
249+
self._remove_current_item()
244250
self.service.finish_test(test=test, ts=ts)
245251

246252
@check_rp_enabled
247-
def start_keyword(self, name, attributes, ts=None):
253+
def start_keyword(self, name: str, attributes: Dict, ts: Optional[Any] = None) -> None:
248254
"""Start a new keyword(test step) at the Report Portal.
249255
250256
:param name: Keyword name
@@ -256,20 +262,20 @@ def start_keyword(self, name, attributes, ts=None):
256262
kwd.rp_parent_item_id = self.parent_id
257263
logger.debug('ReportPortal - Start Keyword: {0}'.format(attributes))
258264
kwd.rp_item_id = self.service.start_keyword(keyword=kwd, ts=ts)
259-
self._items.append(kwd)
265+
self._add_current_item(kwd)
260266

261267
@check_rp_enabled
262-
def end_keyword(self, _, attributes, ts=None):
268+
def end_keyword(self, _: Optional[str], attributes: Dict, ts: Optional[Any] = None) -> None:
263269
"""Finish started keyword at the Report Portal.
264270
265271
:param attributes: Dictionary passed by the Robot Framework
266272
:param ts: Timestamp(used by the ResultVisitor)
267273
"""
268-
kwd = self._finish_current_item().update(attributes)
274+
kwd = self._remove_current_item().update(attributes)
269275
logger.debug('ReportPortal - End Keyword: {0}'.format(kwd.attributes))
270276
self.service.finish_keyword(keyword=kwd, ts=ts)
271277

272-
def log_file(self, log_path):
278+
def log_file(self, log_path: str) -> None:
273279
"""Attach HTML log file created by Robot Framework to RP launch.
274280
275281
:param log_path: Path to the log file
@@ -278,7 +284,7 @@ def log_file(self, log_path):
278284
message = {'message': 'Execution log', 'level': 'INFO'}
279285
self.log_message_with_image(message, log_path)
280286

281-
def report_file(self, report_path):
287+
def report_file(self, report_path: str) -> None:
282288
"""Attach HTML report created by Robot Framework to RP launch.
283289
284290
:param report_path: Path to the report file
@@ -287,7 +293,7 @@ def report_file(self, report_path):
287293
message = {'message': 'Execution report', 'level': 'INFO'}
288294
self.log_message_with_image(message, report_path)
289295

290-
def xunit_file(self, xunit_path):
296+
def xunit_file(self, xunit_path: str) -> None:
291297
"""Attach XUnit file created by Robot Framework to RP launch.
292298
293299
:param xunit_path: Path to the XUnit file
@@ -297,6 +303,6 @@ def xunit_file(self, xunit_path):
297303
self.log_message_with_image(message, xunit_path)
298304

299305
@check_rp_enabled
300-
def close(self):
306+
def close(self) -> None:
301307
"""Call service terminate when the whole test execution is done."""
302308
self.service.terminate_service()

0 commit comments

Comments
 (0)