Skip to content

Release #257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# Changelog

## [Unreleased]
### Added
- All Requests now have their names, by @HardNorth
### Removed
- `NOT_FOUND` constant, as it only causes infinite issues, by @HardNorth

## [5.6.2]
### Fixed
- Issue [#246](https://github.com/reportportal/client-Python/issues/246): Invalid return type, by @HardNorth
### Changed
- `helpers.common_helpers.gen_attributes` function now accepts refactored, by @HardNorth
- `helpers.common_helpers.gen_attributes` function was refactored, by @HardNorth

## [5.6.1]
### Added
Expand Down
9 changes: 3 additions & 6 deletions reportportal_client/_internal/aio/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from asyncio import Future
from typing import Any, Awaitable, Coroutine, Generator, Generic, List, Optional, TypeVar, Union

from reportportal_client._internal.static.defines import NOT_FOUND
from reportportal_client.aio.tasks import BlockingOperationError, Task

_T = TypeVar("_T")
Expand Down Expand Up @@ -58,7 +57,7 @@ def blocking_result(self) -> _T:
result = self.result()
else:
result = self.__loop.run_until_complete(self)
return result if result is not NOT_FOUND else None
return result


class ThreadedTask(Generic[_T], Task[_T]):
Expand Down Expand Up @@ -91,8 +90,7 @@ def blocking_result(self) -> _T:
:return: execution result or raise an error, or return immediately if already executed
"""
if self.done():
result = self.result()
return result if result is not NOT_FOUND else None
return self.result()
if not self.__loop.is_running() or self.__loop.is_closed():
raise BlockingOperationError("Running loop is not alive")
start_time = time.time()
Expand All @@ -101,8 +99,7 @@ def blocking_result(self) -> _T:
time.sleep(sleep_time)
if not self.done():
raise BlockingOperationError("Timed out waiting for the task execution")
result = self.result()
return result if result is not NOT_FOUND else None
return self.result()


class BatchedTaskFactory:
Expand Down
1 change: 0 additions & 1 deletion reportportal_client/_internal/static/defines.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,4 @@ class Priority(enum.IntEnum):
ATTRIBUTE_LENGTH_LIMIT = ATTRIBUTE_LIMIT
DEFAULT_PRIORITY = Priority.PRIORITY_MEDIUM
LOW_PRIORITY = Priority.PRIORITY_LOW
NOT_FOUND = _PresenceSentinel()
NOT_SET = _PresenceSentinel()
50 changes: 27 additions & 23 deletions reportportal_client/aio/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
from reportportal_client._internal.static.abstract import AbstractBaseClass, abstractmethod

# noinspection PyProtectedMember
from reportportal_client._internal.static.defines import NOT_FOUND, NOT_SET
from reportportal_client._internal.static.defines import NOT_SET
from reportportal_client.aio.tasks import Task
from reportportal_client.client import RP, OutputType
from reportportal_client.core.rp_issues import Issue
Expand Down Expand Up @@ -225,14 +225,14 @@ async def close(self) -> None:

async def __get_item_url(self, item_id_future: Union[Optional[str], Task[Optional[str]]]) -> Optional[str]:
item_id = await await_if_necessary(item_id_future)
if item_id is NOT_FOUND or item_id is None:
if not item_id:
logger.warning("Attempt to make request for non-existent id.")
return None
return root_uri_join(self.base_url_v2, "item", item_id)

async def __get_launch_url(self, launch_uuid_future: Union[Optional[str], Task[Optional[str]]]) -> Optional[str]:
launch_uuid = await await_if_necessary(launch_uuid_future)
if launch_uuid is NOT_FOUND or launch_uuid is None:
if not launch_uuid:
logger.warning("Attempt to make request for non-existent launch.")
return None
return root_uri_join(self.base_url_v2, "launch", launch_uuid, "finish")
Expand Down Expand Up @@ -270,7 +270,9 @@ async def start_launch(
rerun_of=rerun_of,
).payload

response = await AsyncHttpRequest((await self.session()).post, url=url, json=request_payload).make()
response = await AsyncHttpRequest(
(await self.session()).post, url=url, json=request_payload, name="start_launch"
).make()
if not response:
return None

Expand Down Expand Up @@ -345,11 +347,13 @@ async def start_test_item(
uuid=uuid,
).payload

response = await AsyncHttpRequest((await self.session()).post, url=url, json=request_payload).make()
response = await AsyncHttpRequest(
(await self.session()).post, url=url, json=request_payload, name="start_test_item"
).make()
if not response:
return None
item_id = await response.id
if item_id is NOT_FOUND or item_id is None:
if not item_id:
logger.warning("start_test_item - invalid response: %s", str(await response.json))
else:
logger.debug("start_test_item - ID: %s", item_id)
Expand Down Expand Up @@ -400,7 +404,9 @@ async def finish_test_item(
retry=retry,
retry_of=retry_of,
).payload
response = await AsyncHttpRequest((await self.session()).put, url=url, json=request_payload).make()
response = await AsyncHttpRequest(
(await self.session()).put, url=url, json=request_payload, name="finish_test_item"
).make()
if not response:
return None
message = await response.message
Expand Down Expand Up @@ -434,7 +440,7 @@ async def finish_launch(
description=kwargs.get("description"),
).payload
response = await AsyncHttpRequest(
(await self.session()).put, url=url, json=request_payload, name="Finish Launch"
(await self.session()).put, url=url, json=request_payload, name="finish_launch"
).make()
if not response:
return None
Expand Down Expand Up @@ -463,15 +469,17 @@ async def update_test_item(
}
item_id = await self.get_item_id_by_uuid(item_uuid)
url = root_uri_join(self.base_url_v1, "item", item_id, "update")
response = await AsyncHttpRequest((await self.session()).put, url=url, json=data).make()
response = await AsyncHttpRequest(
(await self.session()).put, url=url, json=data, name="update_test_item"
).make()
if not response:
return None
logger.debug("update_test_item - Item: %s", item_id)
return await response.message

async def __get_launch_uuid_url(self, launch_uuid_future: Union[str, Task[str]]) -> Optional[str]:
launch_uuid = await await_if_necessary(launch_uuid_future)
if launch_uuid is NOT_FOUND or launch_uuid is None:
if not launch_uuid:
logger.warning("Attempt to make request for non-existent Launch UUID.")
return None
logger.debug("get_launch_info - ID: %s", launch_uuid)
Expand All @@ -484,7 +492,7 @@ async def get_launch_info(self, launch_uuid_future: Union[str, Task[str]]) -> Op
:return: Launch information in dictionary.
"""
url = self.__get_launch_uuid_url(launch_uuid_future)
response = await AsyncHttpRequest((await self.session()).get, url=url).make()
response = await AsyncHttpRequest((await self.session()).get, url=url, name="get_launch_info").make()
if not response:
return None
launch_info = None
Expand All @@ -497,7 +505,7 @@ async def get_launch_info(self, launch_uuid_future: Union[str, Task[str]]) -> Op

async def __get_item_uuid_url(self, item_uuid_future: Union[Optional[str], Task[Optional[str]]]) -> Optional[str]:
item_uuid = await await_if_necessary(item_uuid_future)
if item_uuid is NOT_FOUND or item_uuid is None:
if not item_uuid:
logger.warning("Attempt to make request for non-existent UUID.")
return None
return root_uri_join(self.base_url_v1, "item", "uuid", item_uuid)
Expand All @@ -509,7 +517,7 @@ async def get_item_id_by_uuid(self, item_uuid_future: Union[str, Task[str]]) ->
:return: Test Item ID.
"""
url = self.__get_item_uuid_url(item_uuid_future)
response = await AsyncHttpRequest((await self.session()).get, url=url).make()
response = await AsyncHttpRequest((await self.session()).get, url=url, name="get_item_id").make()
return await response.id if response else None

async def get_launch_ui_id(self, launch_uuid_future: Union[str, Task[str]]) -> Optional[int]:
Expand Down Expand Up @@ -549,7 +557,7 @@ async def get_project_settings(self) -> Optional[dict]:
:return: Settings response in Dictionary.
"""
url = root_uri_join(self.base_url_v1, "settings")
response = await AsyncHttpRequest((await self.session()).get, url=url).make()
response = await AsyncHttpRequest((await self.session()).get, url=url, name="get_project_settings").make()
return await response.json if response else None

async def log_batch(self, log_batch: Optional[List[AsyncRPRequestLog]]) -> Optional[Tuple[str, ...]]:
Expand All @@ -561,7 +569,7 @@ async def log_batch(self, log_batch: Optional[List[AsyncRPRequestLog]]) -> Optio
url = root_uri_join(self.base_url_v2, "log")
if log_batch:
response = await AsyncHttpRequest(
(await self.session()).post, url=url, data=AsyncRPLogBatch(log_batch).payload
(await self.session()).post, url=url, data=AsyncRPLogBatch(log_batch).payload, name="log"
).make()
if not response:
return None
Expand Down Expand Up @@ -639,8 +647,6 @@ def launch_uuid(self) -> Optional[str]:

:return: UUID string.
"""
if self.__launch_uuid is NOT_FOUND:
return None
return self.__launch_uuid

@property
Expand Down Expand Up @@ -809,9 +815,10 @@ async def start_test_item(
uuid=uuid,
**kwargs,
)
if item_id and item_id is not NOT_FOUND:
logger.debug("start_test_item - ID: %s", item_id)
self._add_current_item(item_id)
if not item_id:
return None
logger.debug("start_test_item - ID: %s", item_id)
self._add_current_item(item_id)
return item_id

async def finish_test_item(
Expand Down Expand Up @@ -972,9 +979,6 @@ async def log(
:param item_id: UUID of the ReportPortal Item the message belongs to.
:return: Response message Tuple if Log message batch was sent or None.
"""
if item_id is NOT_FOUND:
logger.warning("Attempt to log to non-existent item")
return None
rp_file = RPFile(**attachment) if attachment else None
rp_log = AsyncRPRequestLog(self.__launch_uuid, time, rp_file, item_id, level, message)
return await self.__client.log_batch(await self._log_batcher.append_async(rp_log))
Expand Down
54 changes: 33 additions & 21 deletions reportportal_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
from reportportal_client._internal.static.abstract import AbstractBaseClass

# noinspection PyProtectedMember
from reportportal_client._internal.static.defines import NOT_FOUND
from reportportal_client.core.rp_issues import Issue
from reportportal_client.core.rp_requests import (
HttpRequest,
Expand Down Expand Up @@ -408,8 +407,6 @@ def launch_uuid(self) -> Optional[str]:

:return: UUID string
"""
if self.__launch_uuid is NOT_FOUND:
return None
return self.__launch_uuid

@property
Expand Down Expand Up @@ -587,6 +584,7 @@ def start_launch(
json=request_payload,
verify_ssl=self.verify_ssl,
http_timeout=self.http_timeout,
name="start_launch",
).make()
if not response:
return None
Expand Down Expand Up @@ -638,9 +636,6 @@ def start_test_item(
:param uuid: Test Item UUID to use on start (overrides server one, should be globally unique).
:return: Test Item UUID if successfully started or None.
"""
if parent_item_id is NOT_FOUND:
logger.warning("Attempt to start item for non-existent parent item.")
return None
if parent_item_id:
url = uri_join(self.base_url_v2, "item", parent_item_id)
else:
Expand All @@ -667,15 +662,16 @@ def start_test_item(
json=request_payload,
verify_ssl=self.verify_ssl,
http_timeout=self.http_timeout,
name="start_test_item",
).make()
if not response:
return None
item_id = response.id
if item_id is not NOT_FOUND:
logger.debug("start_test_item - ID: %s", item_id)
self._add_current_item(item_id)
else:
if not item_id:
logger.warning("start_test_item - invalid response: %s", str(response.json))
return None
logger.debug("start_test_item - ID: %s", item_id)
self._add_current_item(item_id)
return item_id

def finish_test_item(
Expand Down Expand Up @@ -707,7 +703,7 @@ def finish_test_item(
with the 'retry' parameter.
:return: Response message.
"""
if item_id is NOT_FOUND or not item_id:
if not item_id:
logger.warning("Attempt to finish non-existent item")
return None
url = uri_join(self.base_url_v2, "item", item_id)
Expand All @@ -724,7 +720,12 @@ def finish_test_item(
retry_of=retry_of,
).payload
response = HttpRequest(
self.session.put, url=url, json=request_payload, verify_ssl=self.verify_ssl, http_timeout=self.http_timeout
self.session.put,
url=url,
json=request_payload,
verify_ssl=self.verify_ssl,
http_timeout=self.http_timeout,
name="finish_test_item",
).make()
if not response:
return None
Expand All @@ -748,7 +749,7 @@ def finish_launch(
:param attributes: Launch attributes
"""
if self.use_own_launch:
if self.__launch_uuid is NOT_FOUND or not self.__launch_uuid:
if not self.__launch_uuid:
logger.warning("Attempt to finish non-existent launch")
return None
url = uri_join(self.base_url_v2, "launch", self.__launch_uuid, "finish")
Expand All @@ -763,8 +764,8 @@ def finish_launch(
url=url,
json=request_payload,
verify_ssl=self.verify_ssl,
name="Finish Launch",
http_timeout=self.http_timeout,
name="finish_launch",
).make()
if not response:
return None
Expand Down Expand Up @@ -793,7 +794,12 @@ def update_test_item(
item_id = self.get_item_id_by_uuid(item_uuid)
url = uri_join(self.base_url_v1, "item", item_id, "update")
response = HttpRequest(
self.session.put, url=url, json=data, verify_ssl=self.verify_ssl, http_timeout=self.http_timeout
self.session.put,
url=url,
json=data,
verify_ssl=self.verify_ssl,
http_timeout=self.http_timeout,
name="update_test_item",
).make()
if not response:
return None
Expand All @@ -809,6 +815,7 @@ def _log(self, batch: Optional[List[RPRequestLog]]) -> Optional[Tuple[str, ...]]
files=RPLogBatch(batch).payload,
verify_ssl=self.verify_ssl,
http_timeout=self.http_timeout,
name="log",
).make()
if response:
return response.messages
Expand All @@ -833,9 +840,6 @@ def log(
:param item_id: UUID of the ReportPortal Item the message belongs to.
:return: Response message Tuple if Log message batch was sent or None.
"""
if item_id is NOT_FOUND:
logger.warning("Attempt to log to non-existent item")
return None
rp_file = RPFile(**attachment) if attachment else None
rp_log = RPRequestLog(self.__launch_uuid, time, rp_file, item_id, level, message)
return self._log(self._log_batcher.append(rp_log))
Expand All @@ -848,7 +852,7 @@ def get_item_id_by_uuid(self, item_uuid: str) -> Optional[str]:
"""
url = uri_join(self.base_url_v1, "item", "uuid", item_uuid)
response = HttpRequest(
self.session.get, url=url, verify_ssl=self.verify_ssl, http_timeout=self.http_timeout
self.session.get, url=url, verify_ssl=self.verify_ssl, http_timeout=self.http_timeout, name="get_item_id"
).make()
return response.id if response else None

Expand All @@ -862,7 +866,11 @@ def get_launch_info(self) -> Optional[dict]:
url = uri_join(self.base_url_v1, "launch", "uuid", self.__launch_uuid)
logger.debug("get_launch_info - ID: %s", self.__launch_uuid)
response = HttpRequest(
self.session.get, url=url, verify_ssl=self.verify_ssl, http_timeout=self.http_timeout
self.session.get,
url=url,
verify_ssl=self.verify_ssl,
http_timeout=self.http_timeout,
name="get_launch_info",
).make()
if not response:
return None
Expand Down Expand Up @@ -911,7 +919,11 @@ def get_project_settings(self) -> Optional[dict]:
"""
url = uri_join(self.base_url_v1, "settings")
response = HttpRequest(
self.session.get, url=url, verify_ssl=self.verify_ssl, http_timeout=self.http_timeout
self.session.get,
url=url,
verify_ssl=self.verify_ssl,
http_timeout=self.http_timeout,
name="get_project_settings",
).make()
return response.json if response else None

Expand Down
Loading