Skip to content

Commit ab5671d

Browse files
authored
Merge pull request #404 from reportportal/develop
Release
2 parents 9a119c7 + edffd1e commit ab5671d

File tree

13 files changed

+114
-231
lines changed

13 files changed

+114
-231
lines changed

.flake8

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
[flake8]
2+
ignore = E203, W503
23
max-line-length = 119

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ celerybeat.pid
105105
# Environments
106106
.env
107107
.venv
108+
.venv38
109+
.venv39
110+
.venv310
111+
.venv311
108112
env/
109113
venv/
110114
ENV/

CHANGELOG.md

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

33
## [Unreleased]
4+
### Added
5+
- OAuth 2.0 Password Grant authentication, by @HardNorth
6+
### Changed
7+
- Client version updated to [5.6.7](https://github.com/reportportal/client-Python/releases/tag/5.6.7), by @HardNorth
8+
### Fixed
9+
- Some configuration parameter names, which are different in the client, by @HardNorth
10+
### Removed
11+
- `rp_uuid` param support, as it was deprecated pretty while ago, by @HardNorth
12+
13+
## [5.5.2]
414
### Fixed
515
- Issue [#397](https://github.com/reportportal/agent-python-pytest/issues/397) pytest launch stuck with xdist, by @HardNorth
616

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
[build-system]
22
requires = [
3-
# sync with setup.py until we discard non-pep-517/518
43
"setuptools>=68.0.0",
54
"setuptools-scm",
65
"wheel==0.40.0",

pytest_reportportal/config.py

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
class AgentConfig:
3333
"""Storage for the RP agent initialization attributes."""
3434

35+
rp_enabled: bool
3536
rp_client_type: Optional[ClientType]
3637
rp_rerun: Optional[bool]
3738
pconfig: Config
@@ -53,16 +54,26 @@ class AgentConfig:
5354
rp_tests_attributes: Optional[List[str]]
5455
rp_launch_description: str
5556
rp_log_batch_size: int
56-
rp_log_batch_payload_size: int
57+
rp_log_batch_payload_limit: int
5758
rp_log_level: Optional[int]
5859
rp_log_format: Optional[str]
5960
rp_mode: str
6061
rp_parent_item_id: Optional[str]
6162
rp_project: str
6263
rp_rerun_of: Optional[str]
6364
rp_api_retries: int
64-
rp_skip_connection_test: bool
65-
rp_api_key: str
65+
66+
# API key auth parameter
67+
rp_api_key: Optional[str]
68+
69+
# OAuth 2.0 parameters
70+
rp_oauth_uri: Optional[str]
71+
rp_oauth_username: Optional[str]
72+
rp_oauth_password: Optional[str]
73+
rp_oauth_client_id: Optional[str]
74+
rp_oauth_client_secret: Optional[str]
75+
rp_oauth_scope: Optional[str]
76+
6677
rp_verify_ssl: Union[bool, str]
6778
rp_launch_timeout: int
6879
rp_launch_uuid_print: bool
@@ -72,8 +83,9 @@ class AgentConfig:
7283

7384
def __init__(self, pytest_config: Config) -> None:
7485
"""Initialize required attributes."""
86+
self.rp_enabled = to_bool(getattr(pytest_config.option, "rp_enabled", True))
7587
self.rp_rerun = pytest_config.option.rp_rerun or pytest_config.getini("rp_rerun")
76-
self.rp_endpoint = self.find_option(pytest_config, "rp_endpoint")
88+
self.rp_endpoint = getenv("RP_ENDPOINT") or self.find_option(pytest_config, "rp_endpoint")
7789
self.rp_hierarchy_code = to_bool(self.find_option(pytest_config, "rp_hierarchy_code"))
7890
self.rp_dir_level = int(self.find_option(pytest_config, "rp_hierarchy_dirs_level"))
7991
self.rp_hierarchy_dirs = to_bool(self.find_option(pytest_config, "rp_hierarchy_dirs"))
@@ -100,19 +112,18 @@ def __init__(self, pytest_config: Config) -> None:
100112
self.rp_tests_attributes = self.find_option(pytest_config, "rp_tests_attributes")
101113
self.rp_launch_description = self.find_option(pytest_config, "rp_launch_description")
102114
self.rp_log_batch_size = int(self.find_option(pytest_config, "rp_log_batch_size"))
103-
batch_payload_size = self.find_option(pytest_config, "rp_log_batch_payload_size")
104-
if batch_payload_size:
105-
self.rp_log_batch_payload_size = int(batch_payload_size)
115+
batch_payload_size_limit = self.find_option(pytest_config, "rp_log_batch_payload_limit")
116+
if batch_payload_size_limit:
117+
self.rp_log_batch_payload_limit = int(batch_payload_size_limit)
106118
else:
107-
self.rp_log_batch_payload_size = MAX_LOG_BATCH_PAYLOAD_SIZE
119+
self.rp_log_batch_payload_limit = MAX_LOG_BATCH_PAYLOAD_SIZE
108120
self.rp_log_level = get_actual_log_level(pytest_config, "rp_log_level")
109121
self.rp_log_format = self.find_option(pytest_config, "rp_log_format")
110122
self.rp_thread_logging = to_bool(self.find_option(pytest_config, "rp_thread_logging") or False)
111123
self.rp_mode = self.find_option(pytest_config, "rp_mode")
112124
self.rp_parent_item_id = self.find_option(pytest_config, "rp_parent_item_id")
113125
self.rp_project = self.find_option(pytest_config, "rp_project")
114126
self.rp_rerun_of = self.find_option(pytest_config, "rp_rerun_of")
115-
self.rp_skip_connection_test = to_bool(self.find_option(pytest_config, "rp_skip_connection_test"))
116127

117128
rp_api_retries_str = self.find_option(pytest_config, "rp_api_retries")
118129
rp_api_retries = rp_api_retries_str and int(rp_api_retries_str)
@@ -134,27 +145,16 @@ def __init__(self, pytest_config: Config) -> None:
134145
else:
135146
self.rp_api_retries = 0
136147

148+
# API key auth parameter
137149
self.rp_api_key = getenv("RP_API_KEY") or self.find_option(pytest_config, "rp_api_key")
138-
if not self.rp_api_key:
139-
self.rp_api_key = getenv("RP_UUID") or self.find_option(pytest_config, "rp_uuid")
140-
if self.rp_api_key:
141-
warnings.warn(
142-
"Parameter `rp_uuid` is deprecated since 5.1.9 "
143-
"and will be subject for removing in the next "
144-
"major version. Use `rp_api_key` argument "
145-
"instead.",
146-
DeprecationWarning,
147-
2,
148-
)
149-
else:
150-
warnings.warn(
151-
"Argument `rp_api_key` is `None` or empty string, "
152-
"that is not supposed to happen because Report "
153-
"Portal is usually requires an authorization key. "
154-
"Please check your configuration.",
155-
RuntimeWarning,
156-
2,
157-
)
150+
151+
# OAuth 2.0 parameters
152+
self.rp_oauth_uri = self.find_option(pytest_config, "rp_oauth_uri")
153+
self.rp_oauth_username = self.find_option(pytest_config, "rp_oauth_username")
154+
self.rp_oauth_password = self.find_option(pytest_config, "rp_oauth_password")
155+
self.rp_oauth_client_id = self.find_option(pytest_config, "rp_oauth_client_id")
156+
self.rp_oauth_client_secret = self.find_option(pytest_config, "rp_oauth_client_secret")
157+
self.rp_oauth_scope = self.find_option(pytest_config, "rp_oauth_scope")
158158

159159
rp_verify_ssl = self.find_option(pytest_config, "rp_verify_ssl", True)
160160
try:

pytest_reportportal/plugin.py

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import pytest
2525

2626
# noinspection PyPackageRequirements
27-
import requests
2827
from pytest import Item, Session
2928
from reportportal_client import RP, RPLogHandler
3029
from reportportal_client.errors import ResponseError
@@ -49,10 +48,7 @@
4948
LOGGER: Logger = logging.getLogger(__name__)
5049

5150
MANDATORY_PARAMETER_MISSED_PATTERN: str = (
52-
"One of the following mandatory parameters is unset: "
53-
+ "rp_project: {}, "
54-
+ "rp_endpoint: {}, "
55-
+ "rp_api_key: {}"
51+
"One of the following mandatory parameters is unset: " + "rp_project: {}, rp_endpoint: {}"
5652
)
5753

5854
FAILED_LAUNCH_WAIT: str = (
@@ -182,25 +178,6 @@ def register_markers(config) -> None:
182178
config.addinivalue_line("markers", "name(name): report the test case with a custom Name.")
183179

184180

185-
def check_connection(agent_config: AgentConfig):
186-
"""Check connection to RP using provided options.
187-
188-
If connection is successful returns True either False.
189-
:param agent_config: Instance of the AgentConfig class
190-
:return True on successful connection check, either False
191-
"""
192-
url = "{0}/api/v1/project/{1}".format(agent_config.rp_endpoint, agent_config.rp_project)
193-
headers = {"Authorization": "bearer {0}".format(agent_config.rp_api_key)}
194-
try:
195-
resp = requests.get(url, headers=headers, verify=agent_config.rp_verify_ssl)
196-
resp.raise_for_status()
197-
return True
198-
except requests.exceptions.RequestException as exc:
199-
LOGGER.exception(exc)
200-
LOGGER.error("Unable to connect to Report Portal, the launch won't be reported")
201-
return False
202-
203-
204181
# no 'config' type for backward compatibility for older pytest versions
205182
# noinspection PyProtectedMember
206183
def pytest_configure(config) -> None:
@@ -216,24 +193,17 @@ def pytest_configure(config) -> None:
216193
or not config.option.rp_enabled
217194
)
218195
if not config._rp_enabled:
196+
LOGGER.debug("Disabling reporting to RP.")
219197
return
220198

221199
agent_config = AgentConfig(config)
222-
223-
cond = (agent_config.rp_project, agent_config.rp_endpoint, agent_config.rp_api_key)
200+
cond = (agent_config.rp_project, agent_config.rp_endpoint)
224201
config._rp_enabled = all(cond)
225202
if not config._rp_enabled:
226203
LOGGER.debug(MANDATORY_PARAMETER_MISSED_PATTERN.format(*cond))
227204
LOGGER.debug("Disabling reporting to RP.")
228205
return
229206

230-
if not agent_config.rp_skip_connection_test:
231-
config._rp_enabled = check_connection(agent_config)
232-
233-
if not config._rp_enabled:
234-
LOGGER.debug("Failed to establish connection with RP. " "Disabling reporting.")
235-
return
236-
237207
config._reporter_config = agent_config
238208

239209
if is_control(config):
@@ -592,7 +562,6 @@ def add_shared_option(name, help_str, default=None, action="store"):
592562
name="rp_parent_item_id",
593563
help_str="Create all test item as child items of the given (already " "existing) item.",
594564
)
595-
add_shared_option(name="rp_uuid", help_str="Deprecated: use `rp_api_key` " "instead.")
596565
add_shared_option(name="rp_api_key", help_str="API key of Report Portal. Usually located on UI profile " "page.")
597566
add_shared_option(name="rp_endpoint", help_str="Server endpoint")
598567
add_shared_option(name="rp_mode", help_str="Visibility of current launch [DEFAULT, DEBUG]", default="DEFAULT")
@@ -613,11 +582,19 @@ def add_shared_option(name, help_str, default=None, action="store"):
613582
help_str="Launch UUID print output. Default `stdout`. Possible values: [stderr, stdout]",
614583
)
615584

585+
# OAuth 2.0 parameters
586+
parser.addini("rp_oauth_uri", type="args", help="OAuth 2.0 token endpoint URL for password grant authentication")
587+
parser.addini("rp_oauth_username", type="args", help="OAuth 2.0 username for password grant authentication")
588+
parser.addini("rp_oauth_password", type="args", help="OAuth 2.0 password for password grant authentication")
589+
parser.addini("rp_oauth_client_id", type="args", help="OAuth 2.0 client identifier")
590+
parser.addini("rp_oauth_client_secret", type="args", help="OAuth 2.0 client secret")
591+
parser.addini("rp_oauth_scope", type="args", help="OAuth 2.0 access token scope")
592+
616593
parser.addini("rp_launch_attributes", type="args", help="Launch attributes, i.e Performance Regression")
617594
parser.addini("rp_tests_attributes", type="args", help="Attributes for all tests items, e.g. Smoke")
618595
parser.addini("rp_log_batch_size", default="20", help="Size of batch log requests in async mode")
619596
parser.addini(
620-
"rp_log_batch_payload_size",
597+
"rp_log_batch_payload_limit",
621598
default=str(MAX_LOG_BATCH_PAYLOAD_SIZE),
622599
help="Maximum payload size in bytes of async batch log requests",
623600
)
@@ -669,7 +646,6 @@ def add_shared_option(name, help_str, default=None, action="store"):
669646
parser.addini("rp_issue_id_marks", type="bool", default=True, help="Add tag with issue id to the test")
670647
parser.addini("retries", default="0", help="Deprecated: use `rp_api_retries` instead")
671648
parser.addini("rp_api_retries", default="0", help="Amount of retries for performing REST calls to RP server")
672-
parser.addini("rp_skip_connection_test", default=False, type="bool", help="Skip Report Portal connection test")
673649
parser.addini(
674650
"rp_launch_timeout",
675651
default=86400,

pytest_reportportal/service.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ def _create_leaf(
285285
286286
:param leaf_type: the leaf type
287287
:param parent_item: parent pytest.Item of the current leaf
288-
:param item: leaf's pytest.Item
288+
:param item: the leaf's pytest.Item
289289
:return: a leaf
290290
"""
291291
return {
@@ -434,7 +434,10 @@ def _merge_code(self, test_tree: Dict[str, Any]) -> None:
434434

435435
def _build_item_paths(self, leaf: Dict[str, Any], path: List[Dict[str, Any]]) -> None:
436436
children = leaf.get("children", {})
437-
all_background_steps = all([isinstance(child, Background) for child in children.keys()])
437+
if PYTEST_BDD:
438+
all_background_steps = all([isinstance(child, Background) for child in children.keys()])
439+
else:
440+
all_background_steps = False
438441
if len(children) > 0 and not all_background_steps:
439442
path.append(leaf)
440443
for name, child_leaf in leaf["children"].items():
@@ -1123,7 +1126,8 @@ def start_bdd_scenario(self, feature: Feature, scenario: Scenario) -> None:
11231126
root_leaf = self._bdd_tree
11241127
if not root_leaf:
11251128
self._bdd_tree = root_leaf = self._create_leaf(LeafType.ROOT, None, None, item_id=self.parent_item_id)
1126-
children_leafs = root_leaf["children"]
1129+
# noinspection PyTypeChecker
1130+
children_leafs: Dict[Any, Any] = root_leaf["children"]
11271131
if feature in children_leafs:
11281132
feature_leaf = children_leafs[feature]
11291133
else:
@@ -1389,11 +1393,18 @@ def start(self) -> None:
13891393
retries=self._config.rp_api_retries,
13901394
verify_ssl=self._config.rp_verify_ssl,
13911395
launch_uuid=launch_id,
1392-
log_batch_payload_size=self._config.rp_log_batch_payload_size,
1396+
log_batch_payload_limit=self._config.rp_log_batch_payload_limit,
13931397
launch_uuid_print=self._config.rp_launch_uuid_print,
13941398
print_output=self._config.rp_launch_uuid_print_output,
13951399
http_timeout=self._config.rp_http_timeout,
13961400
mode=self._config.rp_mode,
1401+
# OAuth 2.0 parameters
1402+
oauth_uri=self._config.rp_oauth_uri,
1403+
oauth_username=self._config.rp_oauth_username,
1404+
oauth_password=self._config.rp_oauth_password,
1405+
oauth_client_id=self._config.rp_oauth_client_id,
1406+
oauth_client_secret=self._config.rp_oauth_client_secret,
1407+
oauth_scope=self._config.rp_oauth_scope,
13971408
)
13981409
if hasattr(self.rp, "get_project_settings"):
13991410
self.project_settings = self.rp.get_project_settings()

requirements-dev.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
delayed-assert
22
pytest-cov
33
pytest-parallel
4+
black
5+
isort

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
dill>=0.3.6
22
pytest>=4.6.10
3-
reportportal-client~=5.6.4
3+
reportportal-client~=5.6.7
44
aenum>=3.1.0

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
from setuptools import setup
1919

20-
__version__ = "5.5.2"
20+
__version__ = "5.5.3"
2121

2222

2323
def read_file(fname):

0 commit comments

Comments
 (0)