Skip to content

Commit 8a23dc3

Browse files
authored
Merge pull request #245 from reportportal/develop
Release
2 parents c44cb2a + e60998e commit 8a23dc3

File tree

10 files changed

+70
-29
lines changed

10 files changed

+70
-29
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
- name: Set up Python
4242
uses: actions/setup-python@v5
4343
with:
44-
python-version: '3.8'
44+
python-version: '3.10'
4545

4646
- name: Install dependencies
4747
run: python -m pip install --upgrade pip setuptools wheel

.github/workflows/tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
runs-on: ubuntu-latest
3535
strategy:
3636
matrix:
37-
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', '3.12' ]
37+
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13' ]
3838
steps:
3939
- name: Checkout repository
4040
uses: actions/checkout@v4
@@ -54,7 +54,7 @@ jobs:
5454
run: tox
5555

5656
- name: Upload coverage to Codecov
57-
if: matrix.python-version == 3.8 && success()
57+
if: matrix.python-version == 3.10 && success()
5858
uses: codecov/codecov-action@v4
5959
with:
6060
token: ${{ secrets.CODECOV_TOKEN }}

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+
### Added
5+
- Official `Python 3.13` support, by @HardNorth
6+
### Fixed
7+
- Issue [#244](https://github.com/reportportal/client-Python/issues/244): Client crash on different error responses, by @HardNorth
8+
9+
## [5.5.9]
410
### Fixed
511
- Empty parameter Dict conversion, by @HardNorth
612

reportportal_client/core/rp_requests.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
"""
2020

2121
import asyncio
22-
import json as json_converter
2322
import logging
2423
from dataclasses import dataclass
2524
from typing import Callable, Optional, Union, List, Tuple, Any, TypeVar
@@ -43,6 +42,12 @@
4342
from reportportal_client.core.rp_responses import RPResponse, AsyncRPResponse
4443
from reportportal_client.helpers import dict_to_payload, await_if_necessary
4544

45+
try:
46+
# noinspection PyPackageRequirements
47+
import simplejson as json_converter
48+
except ImportError:
49+
import json as json_converter
50+
4651
logger = logging.getLogger(__name__)
4752
T = TypeVar("T")
4853

reportportal_client/core/rp_responses.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919
"""
2020

2121
import logging
22-
from json import JSONDecodeError
2322
from typing import Any, Optional, Generator, Mapping, Tuple, Union
2423

25-
from aiohttp import ClientResponse
24+
from aiohttp import ClientResponse, ClientError
2625
from requests import Response
2726

2827
# noinspection PyProtectedMember
@@ -42,8 +41,9 @@ def _iter_json_messages(json: Any) -> Generator[str, None, None]:
4241

4342

4443
def _get_json_decode_error_message(response: Union[Response, ClientResponse]) -> str:
45-
status = getattr(response, 'status', getattr(response, 'status_code'))
46-
return f'Unable to decode JSON response, got {"passed" if response.ok else "failed"} ' \
44+
status = getattr(response, 'status', getattr(response, 'status_code', None))
45+
ok = getattr(response, 'ok', None)
46+
return f'Unable to decode JSON response, got {"passed" if ok else "failed"} ' \
4747
f'response with code "{status}" please check your endpoint configuration or API key'
4848

4949

@@ -88,7 +88,7 @@ def json(self) -> Any:
8888
if self.__json is NOT_SET:
8989
try:
9090
self.__json = self._resp.json()
91-
except (JSONDecodeError, TypeError) as exc:
91+
except (ValueError, TypeError) as exc:
9292
logger.error(_get_json_decode_error_message(self._resp), exc_info=exc)
9393
self.__json = None
9494
return self.__json
@@ -156,7 +156,7 @@ async def json(self) -> Any:
156156
if self.__json is NOT_SET:
157157
try:
158158
self.__json = await self._resp.json()
159-
except (JSONDecodeError, TypeError) as exc:
159+
except (ValueError, TypeError, ClientError) as exc:
160160
logger.error(_get_json_decode_error_message(self._resp), exc_info=exc)
161161
self.__json = None
162162
return self.__json

reportportal_client/helpers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
import asyncio
1717
import inspect
18-
import json
1918
import logging
2019
import sys
2120
import threading
@@ -27,6 +26,12 @@
2726

2827
from reportportal_client.core.rp_file import RPFile
2928

29+
try:
30+
# noinspection PyPackageRequirements
31+
import simplejson as json
32+
except ImportError:
33+
import json
34+
3035
logger: logging.Logger = logging.getLogger(__name__)
3136
_T = TypeVar('_T')
3237
ATTRIBUTE_LENGTH_LIMIT: int = 128

requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
aenum
2-
requests>=2.28.0
3-
aiohttp>=3.8.3
4-
certifi>=2023.7.22
2+
requests>=2.31.0
3+
aiohttp>=3.8.6
4+
certifi>=2024.8.30

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from setuptools import setup, find_packages
66

7-
__version__ = '5.5.9'
7+
__version__ = '5.5.10'
88

99
TYPE_STUBS = ['*.pyi']
1010

@@ -46,6 +46,7 @@ def read_file(fname):
4646
'Programming Language :: Python :: 3.10',
4747
'Programming Language :: Python :: 3.11',
4848
'Programming Language :: Python :: 3.12',
49+
'Programming Language :: Python :: 3.13',
4950
],
5051
install_requires=read_file('requirements.txt').splitlines(),
5152
)

tests/core/test_rp_responses.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,37 +20,59 @@
2020
from reportportal_client.core.rp_responses import RPResponse, AsyncRPResponse
2121

2222

23+
class JSONDecodeError(ValueError):
24+
pass
25+
26+
2327
def json_error():
2428
raise json.JSONDecodeError('Expecting value: line 1 column 1 (char 0)', '<html />', 0)
2529

2630

31+
def custom_error():
32+
raise JSONDecodeError('Expecting value: line 1 column 1 (char 0)')
33+
34+
2735
@mock.patch('reportportal_client.core.rp_responses.logging.Logger.error')
28-
def test_json_decode_error(error_log):
36+
@pytest.mark.parametrize('ok, response_code, error_function, expected_message', [
37+
(False, 404, json_error, 'Unable to decode JSON response, got failed response with code "404" please check your '
38+
'endpoint configuration or API key'),
39+
(True, 200, json_error, 'Unable to decode JSON response, got passed response with code "200" please check your '
40+
'endpoint configuration or API key'),
41+
(True, 200, custom_error, 'Unable to decode JSON response, got passed response with code "200" please check your '
42+
'endpoint configuration or API key'),
43+
])
44+
def test_custom_decode_error(error_log, ok, response_code, error_function, expected_message):
2945
response = mock.Mock()
30-
response.ok = False
46+
response.ok = ok
3147
del response.status
32-
response.status_code = 404
33-
response.json.side_effect = json_error
48+
response.status_code = response_code
49+
response.json.side_effect = error_function
3450

3551
rp_response = RPResponse(response)
3652
assert rp_response.json is None
3753
error_log.assert_called_once()
38-
assert error_log.call_args_list[0][0][0] == ('Unable to decode JSON response, got failed response with code "404" '
39-
'please check your endpoint configuration or API key')
54+
assert error_log.call_args_list[0][0][0] == expected_message
4055

4156

4257
@pytest.mark.skipif(sys.version_info < (3, 8),
4358
reason='the test requires AsyncMock which was introduced in Python 3.8')
4459
@mock.patch('reportportal_client.core.rp_responses.logging.Logger.error')
4560
@pytest.mark.asyncio
46-
async def test_json_decode_error_async(error_log):
61+
@pytest.mark.parametrize('ok, response_code, error_function, expected_message', [
62+
(False, 404, json_error, 'Unable to decode JSON response, got failed response with code "404" please check your '
63+
'endpoint configuration or API key'),
64+
(True, 200, json_error, 'Unable to decode JSON response, got passed response with code "200" please check your '
65+
'endpoint configuration or API key'),
66+
(True, 200, custom_error, 'Unable to decode JSON response, got passed response with code "200" please check your '
67+
'endpoint configuration or API key'),
68+
])
69+
async def test_json_decode_error_async(error_log, ok, response_code, error_function, expected_message):
4770
response = mock.AsyncMock()
48-
response.ok = False
49-
response.status = 403
50-
response.json.side_effect = json_error
71+
response.ok = ok
72+
response.status = response_code
73+
response.json.side_effect = error_function
5174

5275
rp_response = AsyncRPResponse(response)
5376
assert await rp_response.json is None
5477
error_log.assert_called_once()
55-
assert error_log.call_args_list[0][0][0] == ('Unable to decode JSON response, got failed response with code "403" '
56-
'please check your endpoint configuration or API key')
78+
assert error_log.call_args_list[0][0][0] == expected_message

tox.ini

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ envlist =
88
py310
99
py311
1010
py312
11+
py313
1112

1213
[testenv]
1314
deps =
@@ -27,8 +28,9 @@ commands = pre-commit run --all-files --show-diff-on-failure
2728
[gh-actions]
2829
python =
2930
3.7: py37
30-
3.8: pep, py38
31+
3.8: py38
3132
3.9: py39
32-
3.10: py310
33+
3.10: pep, py310
3334
3.11: py311
3435
3.12: py312
36+
3.13: py313

0 commit comments

Comments
 (0)