Skip to content

Commit 20b9e3c

Browse files
Anton LysenkoAnton Lysenkoiivanou
authored
Rewrited service.py (#75)
* Rewrited service.py * added tests and updated return list_to_payload * updated name module * codestyle + docstrings * added end of file line * added sorting dict for python2 * updated documentation * updated docstrings * Update reportportal_client/service.py Co-Authored-By: Ivan Ivanou <[email protected]> * Update reportportal_client/service.py Co-Authored-By: Ivan Ivanou <[email protected]> * Update reportportal_client/service.py Co-Authored-By: Ivan Ivanou <[email protected]> * Update tests/test_service.py Co-Authored-By: Ivan Ivanou <[email protected]> * updated docstrings * updated docstrings and deleted usless imports * updated docstrings * updated folders for scanning in travis ci * updated folders for scanning in travis ci and added docstring in setup py * added setup.py docstring * updated python versions Co-authored-by: Anton Lysenko <[email protected]> Co-authored-by: Ivan Ivanou <[email protected]>
1 parent f9c0a9c commit 20b9e3c

File tree

7 files changed

+271
-71
lines changed

7 files changed

+271
-71
lines changed

.travis.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ stages:
55
language: python
66
python:
77
- "2.7"
8-
- "3.4"
98
- "3.5"
109
- "3.6"
10+
- "3.7"
11+
- "3.8"
1112
install:
12-
- pip install pycodestyle
13+
- pip install pycodestyle pydocstyle
1314
before_script:
1415
- pycodestyle .
16+
- pydocstyle .
1517
script:
18+
- python setup.py test
1619
- python setup.py -q install
1720
jobs:
1821
include:

reportportal_client/__init__.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
# Copyright (c) 2018 http://reportportal.io
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
1+
"""
2+
Copyright (c) 2018 http://reportportal.io .
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
1416

1517
from .service import ReportPortalService
1618

17-
__all__ = (
18-
ReportPortalService,
19-
)
19+
__all__ = ('ReportPortalService',)
2020

2121
POST_LOGBATCH_RETRY_COUNT = 10

reportportal_client/errors.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1-
# Copyright (c) 2018 http://reportportal.io
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
1+
"""
2+
Copyright (c) 2018 http://reportportal.io .
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
1416

1517

1618
class Error(Exception):
1719
"""General exception for package."""
1820

1921

2022
class ResponseError(Error):
21-
"""Error in response returned by RP"""
23+
"""Error in response returned by RP."""
2224

2325

2426
class EntryCreatedError(ResponseError):

reportportal_client/service.py

Lines changed: 111 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
# Copyright (c) 2018 http://reportportal.io
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
1+
"""
2+
Copyright (c) 2018 http://reportportal.io .
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
1416

1517

1618
import collections
@@ -28,20 +30,36 @@
2830
logger.addHandler(logging.NullHandler())
2931

3032

31-
def _dict_to_payload(dictionary):
32-
def _str(value):
33-
if isinstance(value, six.text_type):
34-
# Don't try to encode 'unicode' in Python 2.
35-
return value
36-
return str(value)
33+
def _convert_string(value):
34+
"""Support and convert strings in py2 and py3.
35+
36+
:param value: input string
37+
:return value: convert string
38+
"""
39+
if isinstance(value, six.text_type):
40+
# Don't try to encode 'unicode' in Python 2.
41+
return value
42+
return str(value)
43+
44+
45+
def _list_to_payload(dictionary):
46+
"""Convert dict to list of dicts.
3747
48+
:param dictionary: initial dict
49+
:return list: list of dicts
50+
"""
3851
return [
39-
{"key": key, "value": _str(value)}
40-
for key, value in dictionary.items()
52+
{"key": key, "value": _convert_string(value)}
53+
for key, value in sorted(dictionary.items())
4154
]
4255

4356

4457
def _get_id(response):
58+
"""Get id from Response.
59+
60+
:param response: Response object
61+
:return id: int value of id
62+
"""
4563
try:
4664
return _get_data(response)["id"]
4765
except KeyError:
@@ -50,6 +68,12 @@ def _get_id(response):
5068

5169

5270
def _get_msg(response):
71+
"""
72+
Get message from Response.
73+
74+
:param response: Response object
75+
:return: data: json data
76+
"""
5377
try:
5478
return _get_data(response)
5579
except KeyError:
@@ -58,6 +82,12 @@ def _get_msg(response):
5882

5983

6084
def _get_data(response):
85+
"""
86+
Get data from Response.
87+
88+
:param response: Response object
89+
:return: json data
90+
"""
6191
data = _get_json(response)
6292
error_messages = _get_messages(data)
6393
error_count = len(error_messages)
@@ -76,6 +106,12 @@ def _get_data(response):
76106

77107

78108
def _get_json(response):
109+
"""
110+
Get json from Response.
111+
112+
:param response: Response object
113+
:return: data: json object
114+
"""
79115
try:
80116
if response.text:
81117
return response.json()
@@ -87,6 +123,12 @@ def _get_json(response):
87123

88124

89125
def _get_messages(data):
126+
"""
127+
Get messages (ErrorCode) from Response.
128+
129+
:param data: dict of datas
130+
:return list: Empty list or list of errors
131+
"""
90132
error_messages = []
91133
for ret in data.get("responses", [data]):
92134
if "errorCode" in ret:
@@ -109,6 +151,7 @@ def uri_join(*uri_parts):
109151
110152
Returns:
111153
An uri string.
154+
112155
"""
113156
return '/'.join(str(s).strip('/').strip('\\') for s in uri_parts)
114157

@@ -151,6 +194,7 @@ def __init__(self,
151194
self.verify_ssl = verify_ssl
152195

153196
def terminate(self, *args, **kwargs):
197+
"""Call this to terminate the service."""
154198
pass
155199

156200
def start_launch(self,
@@ -160,8 +204,9 @@ def start_launch(self,
160204
attributes=None,
161205
mode=None,
162206
**kwargs):
207+
"""Start a new launch with the given parameters."""
163208
if attributes is not None:
164-
attributes = _dict_to_payload(attributes)
209+
attributes = _list_to_payload(attributes)
165210
data = {
166211
"name": name,
167212
"description": description,
@@ -176,8 +221,10 @@ def start_launch(self,
176221
return self.launch_id
177222

178223
def finish_launch(self, end_time, status=None, **kwargs):
179-
"""
180-
status can be (PASSED, FAILED, STOPPED, SKIPPED, RESETED, CANCELLED)
224+
"""Finish a launch with the given parameters.
225+
226+
Status can be one of the followings:
227+
(PASSED, FAILED, STOPPED, SKIPPED, RESETED, CANCELLED)
181228
"""
182229
data = {
183230
"endTime": end_time,
@@ -199,9 +246,11 @@ def start_test_item(self,
199246
has_stats=True,
200247
**kwargs):
201248
"""
202-
item_type can be (SUITE, STORY, TEST, SCENARIO, STEP, BEFORE_CLASS,
249+
Item_type can be.
250+
251+
(SUITE, STORY, TEST, SCENARIO, STEP, BEFORE_CLASS,
203252
BEFORE_GROUPS, BEFORE_METHOD, BEFORE_SUITE, BEFORE_TEST, AFTER_CLASS,
204-
AFTER_GROUPS, AFTER_METHOD, AFTER_SUITE, AFTER_TEST)
253+
AFTER_GROUPS, AFTER_METHOD, AFTER_SUITE, AFTER_TEST).
205254
206255
attributes and parameters should be a dictionary
207256
with the following format:
@@ -211,10 +260,10 @@ def start_test_item(self,
211260
...
212261
}
213262
"""
214-
if attributes is not None:
215-
attributes = _dict_to_payload(attributes)
216-
if parameters is not None:
217-
parameters = _dict_to_payload(parameters)
263+
if attributes:
264+
attributes = _list_to_payload(attributes)
265+
if parameters:
266+
parameters = _list_to_payload(parameters)
218267

219268
data = {
220269
"name": name,
@@ -226,7 +275,7 @@ def start_test_item(self,
226275
"parameters": parameters,
227276
"hasStats": has_stats
228277
}
229-
if parent_item_id is not None:
278+
if parent_item_id:
230279
url = uri_join(self.base_url_v2, "item", parent_item_id)
231280
else:
232281
url = uri_join(self.base_url_v2, "item")
@@ -243,13 +292,24 @@ def finish_test_item(self,
243292
issue=None,
244293
attributes=None,
245294
**kwargs):
295+
"""Finish the test item and return HTTP response.
296+
297+
:param item_id: id of the test item
298+
:param end_time: time in UTC format
299+
:param status: status of the test
300+
:param issue: description of an issue
301+
:param attributes: list of attributes
302+
:param kwargs: other parameters
303+
:return: json message
304+
305+
"""
246306
# check if skipped test should not be marked as "TO INVESTIGATE"
247307
if issue is None and status == "SKIPPED" \
248308
and not self.is_skipped_an_issue:
249309
issue = {"issue_type": "NOT_ISSUE"}
250310

251-
if attributes is not None:
252-
attributes = _dict_to_payload(attributes)
311+
if attributes:
312+
attributes = _list_to_payload(attributes)
253313

254314
data = {
255315
"endTime": end_time,
@@ -264,12 +324,27 @@ def finish_test_item(self,
264324
return _get_msg(r)
265325

266326
def get_project_settings(self):
327+
"""
328+
Get settings from project.
329+
330+
:return: json body
331+
"""
267332
url = uri_join(self.base_url_v1, "settings")
268333
r = self.session.get(url=url, json={}, verify=self.verify_ssl)
269334
logger.debug("settings")
270335
return _get_json(r)
271336

272337
def log(self, time, message, level=None, attachment=None, item_id=None):
338+
"""
339+
Create log for test.
340+
341+
:param time: time in UTC
342+
:param message: description
343+
:param level:
344+
:param attachment: files
345+
:param item_id: id of item
346+
:return: id of item from response
347+
"""
273348
data = {
274349
"launchUuid": self.launch_id,
275350
"time": time,
@@ -288,19 +363,18 @@ def log(self, time, message, level=None, attachment=None, item_id=None):
288363
return _get_id(r)
289364

290365
def log_batch(self, log_data, item_id=None):
291-
"""Logs batch of messages with attachment.
366+
"""
367+
Log batch of messages with attachment.
292368
293369
Args:
294-
log_data: list of log records.
370+
log_data: list of log records.
295371
log record is a dict of;
296372
time, message, level, attachment
297373
attachment is a dict of:
298374
name: name of attachment
299375
data: fileobj or content
300376
mime: content type for attachment
301-
302377
"""
303-
304378
url = uri_join(self.base_url_v2, "log")
305379

306380
attachments = []

0 commit comments

Comments
 (0)