Skip to content

Commit e861d74

Browse files
authored
Merge pull request #230 from reportportal/develop
Release
2 parents dd3a8c1 + e312a16 commit e861d74

File tree

4 files changed

+38
-18
lines changed

4 files changed

+38
-18
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## [Unreleased]
44
### Added
5+
- `CONTENT_TYPE_TO_EXTENSIONS` constant in `helpers` module, by @HardNorth
6+
### Fixed
7+
- Issue [#228](https://github.com/reportportal/client-Python/issues/228): AttributeError on very large request, by @HardNorth
8+
### Changed
9+
- `helpers.gen_attributes` now accepts `Iterable[str]` argument instead of `List[str]`, by @HardNorth
10+
11+
## [5.5.5]
12+
### Added
513
- `is_binary` method in `helpers` module, by @HardNorth
614
- `guess_content_type_from_bytes` method in `helpers` module, by @HardNorth
715

reportportal_client/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,8 @@ def _log(self, batch: Optional[List[RPRequestLog]]) -> Optional[Tuple[str, ...]]
736736
url = uri_join(self.base_url_v2, 'log')
737737
response = HttpRequest(self.session.post, url, files=RPLogBatch(batch).payload,
738738
verify_ssl=self.verify_ssl, http_timeout=self.http_timeout).make()
739-
return response.messages
739+
if response:
740+
return response.messages
740741

741742
def log(self,
742743
time: str,

reportportal_client/helpers.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,35 @@
2222
import time
2323
import uuid
2424
from platform import machine, processor, system
25-
from typing import Optional, Any, List, Dict, Callable, Tuple, Union, TypeVar, Generic
25+
from types import MappingProxyType
26+
from typing import Optional, Any, List, Dict, Callable, Tuple, Union, TypeVar, Generic, Iterable
2627

2728
from reportportal_client.core.rp_file import RPFile
2829

2930
logger: logging.Logger = logging.getLogger(__name__)
3031
_T = TypeVar('_T')
3132
ATTRIBUTE_LENGTH_LIMIT: int = 128
3233
TRUNCATE_REPLACEMENT: str = '...'
34+
BYTES_TO_READ_FOR_DETECTION = 128
35+
36+
CONTENT_TYPE_TO_EXTENSIONS = MappingProxyType({
37+
'application/pdf': 'pdf',
38+
'application/zip': 'zip',
39+
'application/java-archive': 'jar',
40+
'image/jpeg': 'jpg',
41+
'image/png': 'png',
42+
'image/gif': 'gif',
43+
'image/bmp': 'bmp',
44+
'image/vnd.microsoft.icon': 'ico',
45+
'image/webp': 'webp',
46+
'audio/mpeg': 'mp3',
47+
'audio/wav': 'wav',
48+
'video/mpeg': 'mpeg',
49+
'video/avi': 'avi',
50+
'video/webm': 'webm',
51+
'text/plain': 'txt',
52+
'application/octet-stream': 'bin'
53+
})
3354

3455

3556
class LifoQueue(Generic[_T]):
@@ -123,15 +144,15 @@ def dict_to_payload(dictionary: Optional[dict]) -> Optional[List[dict]]:
123144
return result
124145

125146

126-
def gen_attributes(rp_attributes: List[str]) -> List[Dict[str, str]]:
147+
def gen_attributes(rp_attributes: Iterable[str]) -> List[Dict[str, str]]:
127148
"""Generate list of attributes for the API request.
128149
129150
Example of input list:
130151
['tag_name:tag_value1', 'tag_value2']
131152
Output of the function for the given input list:
132153
[{'key': 'tag_name', 'value': 'tag_value1'}, {'value': 'tag_value2'}]
133154
134-
:param rp_attributes: List of attributes(tags)
155+
:param rp_attributes: Iterable of attributes(tags)
135156
:return: Correctly created list of dictionaries
136157
to be passed to RP
137158
"""
@@ -147,8 +168,7 @@ def gen_attributes(rp_attributes: List[str]) -> List[Dict[str, str]]:
147168
if all(attr_dict.values()):
148169
attrs.append(attr_dict)
149170
continue
150-
logger.debug('Failed to process "{0}" attribute, attribute value'
151-
' should not be empty.'.format(rp_attr))
171+
logger.debug(f'Failed to process "{rp_attr}" attribute, attribute value should not be empty.')
152172
return attrs
153173

154174

@@ -309,31 +329,22 @@ def get_function_params(func: Callable, args: tuple, kwargs: Dict[str, Any]) ->
309329

310330

311331
TYPICAL_MULTIPART_BOUNDARY: str = '--972dbca3abacfd01fb4aea0571532b52'
312-
313332
TYPICAL_JSON_PART_HEADER: str = TYPICAL_MULTIPART_BOUNDARY + '''\r
314333
Content-Disposition: form-data; name="json_request_part"\r
315334
Content-Type: application/json\r
316335
\r
317336
'''
318-
319337
TYPICAL_FILE_PART_HEADER: str = TYPICAL_MULTIPART_BOUNDARY + '''\r
320338
Content-Disposition: form-data; name="file"; filename="{0}"\r
321339
Content-Type: {1}\r
322340
\r
323341
'''
324-
325342
TYPICAL_JSON_PART_HEADER_LENGTH: int = len(TYPICAL_JSON_PART_HEADER)
326-
327343
TYPICAL_MULTIPART_FOOTER: str = '\r\n' + TYPICAL_MULTIPART_BOUNDARY + '--'
328-
329344
TYPICAL_MULTIPART_FOOTER_LENGTH: int = len(TYPICAL_MULTIPART_FOOTER)
330-
331345
TYPICAL_JSON_ARRAY: str = '[]'
332-
333346
TYPICAL_JSON_ARRAY_LENGTH: int = len(TYPICAL_JSON_ARRAY)
334-
335347
TYPICAL_JSON_ARRAY_ELEMENT: str = ','
336-
337348
TYPICAL_JSON_ARRAY_ELEMENT_LENGTH: int = len(TYPICAL_JSON_ARRAY_ELEMENT)
338349

339350

@@ -419,8 +430,8 @@ def guess_content_type_from_bytes(data: Union[bytes, bytearray, List[int]]) -> s
419430
if isinstance(data, list):
420431
my_data = bytes(my_data)
421432

422-
if len(my_data) >= 128:
423-
my_data = my_data[:128]
433+
if len(my_data) >= BYTES_TO_READ_FOR_DETECTION:
434+
my_data = my_data[:BYTES_TO_READ_FOR_DETECTION]
424435

425436
if not is_binary(my_data):
426437
return 'text/plain'

setup.py

Lines changed: 1 addition & 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.5'
7+
__version__ = '5.5.6'
88

99
TYPE_STUBS = ['*.pyi']
1010

0 commit comments

Comments
 (0)