Skip to content

Commit cf52b15

Browse files
authored
Merge pull request #193 from reportportal/develop
Release
2 parents 5713ad2 + b18692c commit cf52b15

22 files changed

+376
-152
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- uses: actions/checkout@v2
2626

2727
- name: Generate versions
28-
uses: HardNorth/github-version-generate@v1.1.2
28+
uses: HardNorth/github-version-generate@v1.2.0
2929
with:
3030
version-source: file
3131
version-file: ${{ env.VERSION_FILE }}

.github/workflows/tests.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
name: Tests
22

3-
on: [push, pull_request]
3+
on:
4+
push:
5+
branches:
6+
- '*'
7+
- '!master'
8+
pull_request:
9+
branches:
10+
- 'master'
11+
- 'develop'
412

513
jobs:
614
build:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Changelog
22

33
## [Unreleased]
4+
### Changed
5+
- `LogManager` class moved from `core` package to `logs` package, by @HardNorth
6+
### Fixed
7+
- Issue [#192](https://github.com/reportportal/client-Python/issues/192): launch URL generation, by @HardNorth
8+
9+
## [5.2.3]
410
### Added
511
- Ability to pass client instance in `RPLogHandler` constructor, by @HardNorth
612
- Issue [#179](https://github.com/reportportal/client-Python/issues/179): batch logging request payload size tracking, by @HardNorth

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
[![Python versions](https://img.shields.io/pypi/pyversions/reportportal-client.svg)](https://pypi.org/project/reportportal-client)
55
[![Build Status](https://github.com/reportportal/client-Python/actions/workflows/tests.yml/badge.svg)](https://github.com/reportportal/client-Python/actions/workflows/tests.yml)
66
[![codecov.io](https://codecov.io/gh/reportportal/client-Python/branch/master/graph/badge.svg)](https://codecov.io/gh/reportportal/client-Python)
7+
[![Join Slack chat!](https://reportportal-slack-auto.herokuapp.com/badge.svg)](https://reportportal-slack-auto.herokuapp.com)
8+
[![stackoverflow](https://img.shields.io/badge/reportportal-stackoverflow-orange.svg?style=flat)](http://stackoverflow.com/questions/tagged/reportportal)
9+
[![Build with Love](https://img.shields.io/badge/build%20with-❤%EF%B8%8F%E2%80%8D-lightgrey.svg)](http://reportportal.io?style=flat)
710

811
Library used only for implementors of custom listeners for ReportPortal
912

reportportal_client/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
__all__ = [
2323
'current',
24-
"RPLogger",
25-
"RPLogHandler",
24+
'RPLogger',
25+
'RPLogHandler',
2626
'ReportPortalService',
2727
'step',
2828
]

reportportal_client/client.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
limitations under the License.
1616
"""
1717
import logging
18-
1918
import requests
2019
from requests.adapters import HTTPAdapter, Retry
2120

2221
from ._local import set_current
23-
from .core.log_manager import LogManager, MAX_LOG_BATCH_PAYLOAD_SIZE
2422
from .core.rp_requests import (
2523
HttpRequest,
2624
ItemStartRequest,
@@ -29,6 +27,7 @@
2927
LaunchFinishRequest
3028
)
3129
from .helpers import uri_join, verify_value_length
30+
from .logs.log_manager import LogManager, MAX_LOG_BATCH_PAYLOAD_SIZE
3231
from .static.defines import NOT_FOUND
3332
from .steps import StepReporter
3433

@@ -59,6 +58,7 @@ def __init__(self,
5958
launch_id=None,
6059
http_timeout=(10, 10),
6160
log_batch_payload_size=MAX_LOG_BATCH_PAYLOAD_SIZE,
61+
mode='DEFAULT',
6262
**_):
6363
"""Initialize required attributes.
6464
@@ -100,6 +100,7 @@ def __init__(self,
100100
self.session = requests.Session()
101101
self.step_reporter = StepReporter(self)
102102
self._item_stack = []
103+
self.mode = mode
103104
if retries:
104105
retry_strategy = Retry(
105106
total=retries,
@@ -244,10 +245,19 @@ def get_launch_ui_url(self):
244245
245246
:return: launch URL or all launches URL.
246247
"""
247-
ui_id = self.get_launch_ui_id()
248+
launch_info = self.get_launch_info()
249+
ui_id = launch_info.get('id') if launch_info else None
248250
if not ui_id:
249251
return
250-
path = 'ui/#{0}/launches/all/{1}'.format(self.project, ui_id)
252+
mode = launch_info.get('mode') if launch_info else None
253+
if not mode:
254+
mode = self.mode
255+
256+
launch_type = "launches" if mode.upper() == 'DEFAULT' else 'userdebug'
257+
258+
path = 'ui/#{project_name}/{launch_type}/all/{launch_id}'.format(
259+
project_name=self.project.lower(), launch_type=launch_type,
260+
launch_id=ui_id)
251261
url = uri_join(self.endpoint, path)
252262
logger.debug('get_launch_ui_url - ID: %s', self.launch_id)
253263
return url
@@ -282,7 +292,6 @@ def start_launch(self,
282292
start_time,
283293
description=None,
284294
attributes=None,
285-
mode=None,
286295
rerun=False,
287296
rerun_of=None,
288297
**kwargs):
@@ -292,12 +301,21 @@ def start_launch(self,
292301
:param start_time: Launch start time
293302
:param description: Launch description
294303
:param attributes: Launch attributes
295-
:param mode: Launch mode
296304
:param rerun: Enables launch rerun mode
297305
:param rerun_of: Rerun mode. Specifies launch to be re-runned.
298306
Should be used with the 'rerun' option.
299307
"""
300308
url = uri_join(self.base_url_v2, 'launch')
309+
310+
# We are moving 'mode' param to the constructor, next code for the
311+
# transition period only.
312+
my_kwargs = dict(kwargs)
313+
mode = my_kwargs.get('mode')
314+
if not mode:
315+
mode = self.mode
316+
else:
317+
del my_kwargs['mode']
318+
301319
request_payload = LaunchStartRequest(
302320
name=name,
303321
start_time=start_time,
@@ -306,7 +324,7 @@ def start_launch(self,
306324
mode=mode,
307325
rerun=rerun,
308326
rerun_of=rerun_of or kwargs.get('rerunOf'),
309-
**kwargs
327+
**my_kwargs
310328
).payload
311329
response = HttpRequest(self.session.post,
312330
url=url,

reportportal_client/client.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ from typing import Any, Dict, List, Optional, Text, Tuple, Union
22

33
from requests import Session
44

5-
from reportportal_client.core.log_manager import LogManager as LogManager
5+
from reportportal_client.logs.log_manager import LogManager as LogManager
66
from reportportal_client.core.rp_issues import Issue as Issue
77
from reportportal_client.steps import StepReporter
88

@@ -27,6 +27,7 @@ class RPClient:
2727
http_timeout: Union[float, Tuple[float, float]] = ...
2828
session: Session = ...
2929
step_reporter: StepReporter = ...
30+
mode: str = ...
3031

3132
def __init__(
3233
self,

reportportal_client/core/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@
1212
# limitations under the License
1313

1414
"""This package contains core reportportal-client modules."""
15+
16+
from reportportal_client.logs import log_manager
17+
18+
__all__ = [
19+
'log_manager'
20+
]
Lines changed: 18 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
"""This module contains management functionality for processing logs."""
2-
31
# Copyright (c) 2022 EPAM Systems
42
# Licensed under the Apache License, Version 2.0 (the "License");
53
# you may not use this file except in compliance with the License.
@@ -13,127 +11,26 @@
1311
# See the License for the specific language governing permissions and
1412
# limitations under the License
1513

16-
import logging
17-
from threading import Lock
18-
19-
from six.moves import queue
20-
21-
from reportportal_client import helpers
22-
from reportportal_client.core.rp_requests import (
23-
HttpRequest,
24-
RPFile,
25-
RPLogBatch,
26-
RPRequestLog
27-
)
28-
from reportportal_client.core.worker import APIWorker
29-
from reportportal_client.static.defines import NOT_FOUND
30-
31-
logger = logging.getLogger(__name__)
32-
33-
MAX_LOG_BATCH_PAYLOAD_SIZE = 65000000
34-
35-
36-
class LogManager(object):
37-
"""Manager of the log items."""
14+
"""Deprecated module stub to avoid execution crashes.
3815
39-
def __init__(self, rp_url, session, api_version, launch_id, project_name,
40-
max_entry_number=20, verify_ssl=True,
41-
max_payload_size=MAX_LOG_BATCH_PAYLOAD_SIZE):
42-
"""Initialize instance attributes.
16+
.. deprecated:: 5.2.4
17+
Use `logs.log_manager` instead.
18+
"""
4319

44-
:param rp_url: Report portal URL
45-
:param session: HTTP Session object
46-
:param api_version: RP API version
47-
:param launch_id: Parent launch UUID
48-
:param project_name: RP project name
49-
:param max_entry_number: The amount of log objects that need to be
50-
gathered before processing
51-
:param verify_ssl: Indicates that it is necessary to verify SSL
52-
certificates within HTTP request
53-
:param max_payload_size: maximum size in bytes of logs that can be
54-
processed in one batch
55-
"""
56-
self._lock = Lock()
57-
self._batch = []
58-
self._payload_size = helpers.TYPICAL_MULTIPART_FOOTER_LENGTH
59-
self._worker = None
60-
self.api_version = api_version
61-
self.queue = queue.PriorityQueue()
62-
self.launch_id = launch_id
63-
self.max_entry_number = max_entry_number
64-
self.max_payload_size = max_payload_size
65-
self.project_name = project_name
66-
self.rp_url = rp_url
67-
self.session = session
68-
self.verify_ssl = verify_ssl
20+
import warnings
6921

70-
self._log_endpoint = (
71-
'{rp_url}/api/{version}/{project_name}/log'
72-
.format(rp_url=rp_url, version=self.api_version,
73-
project_name=self.project_name))
22+
from reportportal_client.logs.log_manager import LogManager, \
23+
MAX_LOG_BATCH_PAYLOAD_SIZE
7424

75-
def _send_batch(self):
76-
"""Send existing batch logs to the worker."""
77-
batch = RPLogBatch(self._batch)
78-
http_request = HttpRequest(
79-
self.session.post, self._log_endpoint, files=batch.payload,
80-
verify_ssl=self.verify_ssl)
81-
batch.http_request = http_request
82-
self._worker.send(batch)
83-
self._batch = []
84-
self._payload_size = helpers.TYPICAL_MULTIPART_FOOTER_LENGTH
85-
86-
def _log_process(self, log_req):
87-
"""Process the given log request.
88-
89-
:param log_req: RPRequestLog object
90-
"""
91-
with self._lock:
92-
rq_size = log_req.multipart_size
93-
if self._payload_size + rq_size >= self.max_payload_size:
94-
if len(self._batch) > 0:
95-
self._send_batch()
96-
self._batch.append(log_req)
97-
self._payload_size += rq_size
98-
if len(self._batch) >= self.max_entry_number:
99-
self._send_batch()
100-
101-
def log(self, time, message=None, level=None, attachment=None,
102-
item_id=None):
103-
"""Log message. Can be added to test item in any state.
104-
105-
:param time: Log time
106-
:param message: Log message
107-
:param level: Log level
108-
:param attachment: Attachments(images,files,etc.)
109-
:param item_id: parent item UUID
110-
"""
111-
if item_id is NOT_FOUND:
112-
logger.warning("Attempt to log to non-existent item")
113-
return
114-
rp_file = RPFile(**attachment) if attachment else None
115-
rp_log = RPRequestLog(self.launch_id, time, rp_file, item_id,
116-
level, message)
117-
self._log_process(rp_log)
118-
119-
def start(self):
120-
"""Create a new instance of the Worker class and start it."""
121-
if not self._worker:
122-
# the worker might be already created in case of deserialization
123-
self._worker = APIWorker(self.queue)
124-
self._worker.start()
125-
126-
def stop(self):
127-
"""Send last batches to the worker followed by the stop command."""
128-
if self._worker:
129-
with self._lock:
130-
if self._batch:
131-
self._send_batch()
132-
logger.debug('Waiting for worker {0} to complete'
133-
'processing batches.'.format(self._worker))
134-
self._worker.stop()
25+
warnings.warn(
26+
message="`core.log_manager` is deprecated since 5.2.4 and will be subject "
27+
"for removing in the next major version. Use logs.log_manager` "
28+
"instead",
29+
category=DeprecationWarning,
30+
stacklevel=2
31+
)
13532

136-
def stop_force(self):
137-
"""Send stop immediate command to the worker."""
138-
if self._worker:
139-
self._worker.stop_immediate()
33+
__all__ = [
34+
'LogManager',
35+
'MAX_LOG_BATCH_PAYLOAD_SIZE'
36+
]

reportportal_client/core/worker.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ def _command_process(self, cmd):
8787
else:
8888
self._stop()
8989

90+
def _request_process(self, request):
91+
"""Send request to RP and update response attribute of the request."""
92+
logger.debug('[%s] Processing {%s} request', self.name, request)
93+
try:
94+
request.response = request.http_request.make()
95+
except Exception as err:
96+
logger.exception('[%s] Unknown exception has occurred. '
97+
'Skipping it.', err)
98+
self._queue.task_done()
99+
90100
def _monitor(self):
91101
"""Monitor worker queues and process them.
92102
@@ -111,16 +121,6 @@ def _monitor(self):
111121
logger.debug('[%s] Received {%s} request', self.name, cmd)
112122
self._request_process(cmd)
113123

114-
def _request_process(self, request):
115-
"""Send request to RP and update response attribute of the request."""
116-
logger.debug('[%s] Processing {%s} request', self.name, request)
117-
try:
118-
request.response = request.http_request.make()
119-
except Exception as err:
120-
logger.exception('[%s] Unknown exception has occurred. Terminating'
121-
' the worker.', err)
122-
self._queue.task_done()
123-
124124
def _stop(self):
125125
"""Routine that stops the worker thread(s).
126126

0 commit comments

Comments
 (0)