Git Product home page Git Product logo

client-python's Introduction

ReportPortal python client

PyPI Python versions Build Status codecov.io Join Slack chat! stackoverflow Build with Love

Library used only for implementors of custom listeners for ReportPortal

Already implemented listeners:

Installation

The latest stable version is available on PyPI:

pip install reportportal-client

Usage

Basic usage example:

import os
import subprocess
from mimetypes import guess_type

from reportportal_client import RPClient
from reportportal_client.helpers import timestamp

endpoint = "http://docker.local:8080"
project = "default"
# You can get UUID from user profile page in the ReportPortal.
api_key = "1adf271d-505f-44a8-ad71-0afbdf8c83bd"
launch_name = "Test launch"
launch_doc = "Testing logging with attachment."


client = RPClient(endpoint=endpoint, project=project,
                  api_key=api_key)

# Start log upload thread
client.start()

# Start launch.
launch = client.start_launch(name=launch_name,
                             start_time=timestamp(),
                             description=launch_doc)

item_id = client.start_test_item(name="Test Case",
                                 description="First Test Case",
                                 start_time=timestamp(),
                                 attributes=[{"key": "key", "value": "value"},
                                             {"value", "tag"}],
                                 item_type="STEP",
                                 parameters={"key1": "val1",
                                             "key2": "val2"})

# Create text log message with INFO level.
client.log(time=timestamp(),
           message="Hello World!",
           level="INFO")

# Create log message with attached text output and WARN level.
client.log(time=timestamp(),
           message="Too high memory usage!",
           level="WARN",
           attachment={
               "name": "free_memory.txt",
               "data": subprocess.check_output("free -h".split()),
               "mime": "text/plain"
           })

# Create log message with binary file, INFO level and custom mimetype.
image = "/tmp/image.png"
with open(image, "rb") as fh:
    attachment = {
        "name": os.path.basename(image),
        "data": fh.read(),
        "mime": guess_type(image)[0] or "application/octet-stream"
    }
    client.log(timestamp(), "Screen shot of issue.", "INFO", attachment)

client.finish_test_item(item_id=item_id, end_time=timestamp(), status="PASSED")

# Finish launch.
client.finish_launch(end_time=timestamp())

# Due to async nature of the service we need to call terminate() method which
# ensures all pending requests to server are processed.
# Failure to call terminate() may result in lost data.
client.terminate()

Send attachment (screenshots)

The client uses requests library for working with RP and the same semantics to work with attachments (data).

To log an attachment you need to pass file content and metadata to ``

import logging

from reportportal_client import RPLogger, RPLogHandler

logging.setLoggerClass(RPLogger)
rp_logger = logging.getLogger(__name__)
rp_logger.setLevel(logging.DEBUG)
rp_logger.addHandler(RPLogHandler())

screenshot_file_path = 'path/to/file.png'

with open(screenshot_file_path, "rb") as image_file:
    file_data = image_file.read()

    # noinspection PyArgumentList
    rp_logger.info(
        "Some Text Here",
        attachment={"name": "test_name_screenshot.png",
                    "data": file_data,
                    "mime": "image/png"}
    )

Copyright Notice

Licensed under the Apache 2.0 license (see the LICENSE.txt file).

client-python's People

Contributors

arozumenko avatar avarabyeu avatar ericz15 avatar eyalratbay avatar filland avatar frizzby avatar h3rold avatar hanikhan avatar hardnorth avatar iivanou avatar jmoravec avatar krasoffski avatar mshriver avatar nbob31 avatar nikitafedoraev avatar osherdp avatar pahniki avatar pshv avatar raikbitters avatar rb1 avatar rjswitzer3 avatar rplevka avatar ryanfaircloth avatar scanters avatar scorpibear avatar tkachoff avatar tmarenko avatar trinhpham avatar vakulich avatar vitalka12345 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

client-python's Issues

AttributeError: 'NoneType' object has no attribute 'log'

A PytestUnhandledThreadExceptionWarning is triggered when returning the log property from the rp_client object:

AttributeError: 'NoneType' object has no attribute 'log'

This warning does not appear with reportportal-client at version 5.1.0 and below but appears at 5.2.0 onwards.

ReportPortalService should handle connection issues when processing log batches

RP service stops reporting if any connection issue occurs during log batch processing instead of trying to reconnect.

Traceback (most recent call last):
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/connectionpool.py", line 600, in urlopen
chunked=chunked)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/connectionpool.py", line 384, in _make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/connectionpool.py", line 380, in _make_request
httplib_response = conn.getresponse()
File "/fs/depot/python/x64_linux/3.6.6/python3.6/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/fs/depot/python/x64_linux/3.6.6/python3.6/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/fs/depot/python/x64_linux/3.6.6/python3.6/lib/python3.6/http/client.py", line 266, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/requests/adapters.py", line 449, in send
timeout=timeout
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/connectionpool.py", line 638, in urlopen
_stacktrace=sys.exc_info()[2])
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/util/retry.py", line 368, in increment
raise six.reraise(type(error), error, _stacktrace)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/packages/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/connectionpool.py", line 600, in urlopen
chunked=chunked)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/connectionpool.py", line 384, in _make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/urllib3/connectionpool.py", line 380, in _make_request
httplib_response = conn.getresponse()
File "/fs/depot/python/x64_linux/3.6.6/python3.6/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/fs/depot/python/x64_linux/3.6.6/python3.6/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/fs/depot/python/x64_linux/3.6.6/python3.6/lib/python3.6/http/client.py", line 266, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/reportportal_client/service_async.py", line 231, in process_item
self.process_log(**kwargs)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/reportportal_client/service_async.py", line 215, in process_log
self._post_log_batch()
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/reportportal_client/service_async.py", line 203, in _post_log_batch
self.rp_client.log_batch(self.log_batch)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/reportportal_client/service.py", line 305, in log_batch
verify=self.verify_ssl
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/requests/sessions.py", line 581, in post
return self.request('POST', url, data=data, json=json, **kwargs)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/requests/sessions.py", line 533, in request
resp = self.send(prep, **send_kwargs)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/requests/sessions.py", line 646, in send
r = adapter.send(request, **kwargs)
File "/net/nfs.paneast.panasas.com/sb31/jenkins/venvs/rnr/lib/python3.6/site-packages/requests/adapters.py", line 498, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))

How to send screenshot to report portal

Hi All,

I am very new to reportportal. I have installed agent for robotframework. I would like to send the failure cases screenshots to report portal i went through the code from here https://github.com/reportportal/client-Python#send-attachement-screenshots

but I am not able to follow it on where to add this code snippet. Kindly help me with the same.

Case 1 - pass file-like object
with open(screenshot_file_path, "rb") as image_file:
rp_logger.info("Some Text Here",
attachment={"name": "test_name_screenshot.png",
"data": image_file,
"mime": "image/png"})
Case 2 - pass file content itself (like you did)
with open(screenshot_file_path, "rb") as image_file:
file_data = image_file.read()

rp_logger.info("Some Text Here",
attachment={"name": "test_name_screenshot.png",
"data": file_data,
"mime": "image/png"})

current design does not allow to trigger sibling test items simultaneously

Looking into the code, the ReportPortalService class has a hardcoded mechanism of nesting the test items inside each other (it simply sequentially adds test items to self.stack which contains the uuids of the tests, and every action (start/finish item) is performed on the recent item).

This simply starts 1 test item inside another in case one triggers start_test_item several times in a row:

Launch
  |_ TestItem1
       |_ TestItem2
           |_ TestItem3

What I'm looking for is the ability to pass the uuid of the parent item as a parameter of the start_test_item (to use the POST /{projectName}/item/{parentItem} api endpoint) so I can trigger sibling items at various levels simultaneously, like:

Launch
  |_ TestItem1
  |    |_ TestItem1.1
  |    |   |_ TestItem1.1.1
  |    |   |_ TestItem1.1.2
  |    |_ TestItem1.2
  |_ TestItem2
       |_ TestItem2.1
       | _TestItem2.2
  • this would also unblock the hierarchy feature for pytest xdist
  • I don't know, whether there is a good reason for the current design

KeyError: 'PYTEST_CURRENT_TEST' while sending POST/PUT requests to RP

#39 fixed only one problem case.
To finally fix race condition issue need to handle all possible cases which are all HTTP requests via request package since there is no guarantee that environ dict wouldn't be modified by other service
There are next events which have same problem:

  • reportportal_client/service.py::ReportPortalService::start_launch
  • reportportal_client/service.py::ReportPortalService::finish_launch
  • reportportal_client/service.py::ReportPortalService::start_test_item
  • reportportal_client/service.py::ReportPortalService::update_test_item
  • reportportal_client/service.py::ReportPortalService::finish_test_item
  • reportportal_client/service.py::ReportPortalService::log
  • reportportal_client/service.py::ReportPortalService::get_item_id_by_uuid
  • reportportal_client/service.py::ReportPortalService::get_project_settings

I regulary have fails with:

  • reportportal_client/service.py::ReportPortalService::start_test_item
  • reportportal_client/service.py::ReportPortalService::finish_test_item
File /usr/local/lib/python3.6/dist-packages/reportportal_client/service.py, line 229, in finish_test_item.    r = self.session.put(url=url, json=data, verify=self.verify_ssl).
File /usr/local/lib/python3.6/dist-packages/requests/sessions.py, line 590, in put.    return self.request(PUT, url, data=data, **kwargs).
File /usr/local/lib/python3.6/dist-packages/requests/sessions.py, line 521, in request.    prep.url, proxies, stream, verify, cert.
File /usr/local/lib/python3.6/dist-packages/requests/sessions.py, line 697, in merge_environment_settings.    env_proxies = get_environ_proxies(url, no_proxy=no_proxy).
File /usr/local/lib/python3.6/dist-packages/requests/utils.py, line 766, in get_environ_proxies.    if should_bypass_proxies(url, no_proxy=no_proxy):.
File /usr/local/lib/python3.6/dist-packages/requests/utils.py, line 750, in should_bypass_proxies.    bypass = proxy_bypass(parsed.hostname).
File /usr/lib/python3.6/urllib/request.py, line 2497, in proxy_bypass_environment.    proxies = getproxies_environment().
File /usr/lib/python3.6/urllib/request.py, line 2470, in getproxies_environment.    for name, value in os.environ.items():.
File /usr/lib/python3.6/_collections_abc.py, line 744, in __iter__.    yield (key, self._mapping[key]).
File /usr/lib/python3.6/os.py, line 669, in __getitem__.    raise KeyError(key) from None.KeyError: PYTEST_CURRENT_TEST

I'm going to prepare PR if you don't mind.
Could you please grant me write permissions?

Please note that it is very important for my team to provide fix for this issue in https://github.com/reportportal/client-Python/releases/tag/3.2.3 too since can't to work with the latest report portal agent/ client right now

Adopt client to latest 5.0+ sync-reporting API

I'm trying running cline-python current version on docker-compose and has many errors related a request.

for example:

{'errorCode': 4001, 'message': "Incorrect Request. [Field 'startTime' should not be null.] "}

Or

{'errorCode': 4001, 'message': "Incorrect Request. [Field 'stopTime' should not be null.] "}

When investigating that I found in ReportPortalService many calls with the wrong payload. Like that:

    def start_launch(self, name, start_time, description=None, tags=None,
                     mode=None):
        data = {
            "name": name,
            "description": description,
            "tags": tags,
            "start_time": start_time,
            "mode": mode
        }

Maybe the API change, but I don't know exactly, because yesterday I started my first tests with report portal.

RP session does not log anything when it fails to log an attachment that is too large

Describe the bug
The RP session does not have any logs after an error occurs from trying to attach a large file that is larger than the configured maximum. In this case the max is 128Mb and the file is 160Mb. The RP session is opened, logs created, then the large log raises an exception and no logs are on RP for the session.

reportportal_client.errors.ResponseError: 5000: Unclassified error [Maximum upload size of 134217728 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (161505748) exceeds the configured maximum (134217728)]

Test Code to Reproduce

import logging
import os

import pytest
from reportportal_client.errors import ResponseError


@pytest.mark.parametrize("log_file", ["/tmp/small.txt", "/tmp/large.txt"])
def test_logs(log_file: str):
    rp_log = logging.getLogger(__name__)
    name = os.path.basename(log_file)
    with open(log_file, "r") as fp:
        data = fp.read()
        try:
            rp_log.info(
                f"ATTACHMENT: {name}",
                attachment={"name": name, "data": data, "mime": "text/plain",
                },
            )
        except ResponseError as err:
            if "Maximum upload size" in err:
                rp_log.info(f"Can't attach file - file is too large. name: {name}.\n{err}")
            else:
                raise err

Expected behavior
The exception can be caught in the client and other good logs should still be available in the RP session.

Or please provide a workaround to properly handle the exception.

Versions:

  • Mac, Chrome Version 103.0.5060.114 (Official Build) (x86_64)
  • Version of RP [find it under Login form, copy as is]
  • Current version:API Service: 5.6.3;Jobs Service: 5.6.3;Authorization Service: 5.6.3;Service UI: 5.6.0;
  • pytest-reportportal==5.0.11

incorrect processor info in docker container

platform.processor() is not work in docker container. the value is empty, and cannot post to API.

# tmp fix
        return {'agent': agent,
                'os': platform.system(),
                'cpu': platform.processor(),
                'machine': platform.machine()}

tmp fix

        return {'agent': agent,
                'os': platform.system(),
                'cpu': (platform.processor() if platform.processor() else 'unkown'),
                'machine': platform.machine()}

attachments are not arriving to reportportal and new messages are not arriving after attachment attempt

sending attachment to log is not flushed and log data stops arriving to reportportal

I have tested it in my environment with pytest-reportportal ==5.1.0 and reportportal-client == 5.2.0

sent the following line :
log.info('test.json', attachment={"data": '[{"test": "id"}]', "mime": "application/json"})
after trying to send an attachment no more logs are arriving to reportportal in the current session
this works if using pytest-reportportal ==5.0.12

i didn't noticed any error in logs or exception so my guess this is something related to flushing messages to reportportal

https connection issue with report portal python requests

Hi Team,

Could you please help me with this issue. We are not able to send the data to report portal using python client with https connection.

Error:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/reportportal_client/service_async.py", line 208, in process_item
getattr(self.rp_client, method)(**kwargs)
File "/usr/local/lib/python2.7/site-packages/reportportal_client/service.py", line 144, in finish_launch
status=status)
File "/usr/local/lib/python2.7/site-packages/reportportal_client/service.py", line 137, in _finalize_launch
r = self.session.put(url=url, json=data)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 593, in put
return self.request('PUT', url, data=data, **kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 533, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 646, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 514, in send
raise SSLError(e, request=request)
SSLError: HTTPSConnectionPool(host='report-portal.****.com', port=8080): Max retries exceeded with url: /api/v1/api_automation/launch/None/finish (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))

Could you please check and help here.

Implement the rerun functionality in the client

ReportPortal now supports a functionality through the API which makes rerunning tests possible. It would be nice if it's implemented in the client to support it.

I'm happy to contribute this modification.

invalid syntax issue due to is_skipped_an_issue

Error message while executing report module
File "/home/test/agent/workspace/mv/test_backup/.pyenv/local/lib/python2.7/site-packages/lemoncheesecake/reporting/backends/reportportal.py", line 9, in
from reportportal_client import ReportPortalServiceAsync
File "/home/test/agent/workspace/mv/test_backup/.pyenv/local/lib/python2.7/site-packages/reportportal_client/init.py", line 15, in
from .service import ReportPortalService
File "/home/test/agent/workspace/mv/test_backup/.pyenv/local/lib/python2.7/site-packages/reportportal_client/service.py", line 124
is_skipped_an_issue=True,
^
SyntaxError: invalid syntax
This is caused due to latest merged code.

Getting ImportError while Importing ReportPortalServiceAsync

I am using a reportportal_client to send data to my reportportal.
But when I install reportportal_client and import ReportPortalServiceAsync it through me import error.
Here are the steps I did in my system:-

[root@vm138 Jenkins]# virtualenv -p /usr/bin/python2.7 report_test_env
Running virtualenv with interpreter /usr/bin/python2.7
New python executable in /home/workspace/hardware_gui/Spicegate_Hardware_RHEL8_CERT_Stage/spicegate/Jenkins/report_test_env/bin/python2.7
Not overwriting existing python script /home/workspace/hardware_gui/Spicegate_Hardware_RHEL8_CERT_Stage/spicegate/Jenkins/report_test_env/bin/python (you must use /home/workspace/hardware_gui/Spicegate_Hardware_RHEL8_CERT_Stage/spicegate/Jenkins/report_test_env/bin/python2.7)
Installing setuptools, pip, wheel...done.
[root@vm138 Jenkins]# source report_test_env/bin/activate
(report_test_env) [root@vm138 Jenkins]# pip list
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Package    Version
---------- -------
pip        20.0.2 
setuptools 44.0.0 
wheel      0.34.2 
(report_test_env) [root@vm138 Jenkins]# pip install reportportal-client
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting reportportal-client
  Using cached reportportal_client-5.0.1-py2.py3-none-any.whl (10 kB)
Collecting requests>=2.4.2
  Using cached requests-2.23.0-py2.py3-none-any.whl (58 kB)
Collecting six
  Using cached six-1.14.0-py2.py3-none-any.whl (10 kB)
Collecting certifi>=2017.4.17
  Using cached certifi-2019.11.28-py2.py3-none-any.whl (156 kB)
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1
  Using cached urllib3-1.25.8-py2.py3-none-any.whl (125 kB)
Collecting idna<3,>=2.5
  Using cached idna-2.9-py2.py3-none-any.whl (58 kB)
Collecting chardet<4,>=3.0.2
  Using cached chardet-3.0.4-py2.py3-none-any.whl (133 kB)
Installing collected packages: certifi, urllib3, idna, chardet, requests, six, reportportal-client
Successfully installed certifi-2019.11.28 chardet-3.0.4 idna-2.9 reportportal-client-5.0.1 requests-2.23.0 six-1.14.0 urllib3-1.25.8
(report_test_env) [root@vm138 Jenkins]# pip list
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Package             Version   
------------------- ----------
certifi             2019.11.28
chardet             3.0.4     
idna                2.9       
pip                 20.0.2    
reportportal-client 5.0.1     
requests            2.23.0    
setuptools          44.0.0    
six                 1.14.0    
urllib3             1.25.8    
wheel               0.34.2    
(report_test_env) [root@vm138 Jenkins]# python
Python 2.7.5 (default, May  3 2017, 07:55:04) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-14)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from reportportal_client import ReportPortalServiceAsync
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name ReportPortalServiceAsync
>>> from reportportal_client import ReportPortalServiceAsync
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name ReportPortalServiceAsync

Steps to reproduce:-
Create a new virtual environment
virtualenv -p /usr/bin/python2.7 report_test_env
activate reportportal-client and run pip list to verify that there should no other packages
pip list
install reportportal-client
pip install reportportal-client
and try to import ReportPortalServiceAsync

(report_test_env) [root@vm138 Jenkins]# python
Python 2.7.5 (default, May  3 2017, 07:55:04) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-14)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from reportportal_client import ReportPortalServiceAsync
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name ReportPortalServiceAsync

I just checked It's working fine till version 3.2.3.

batch logging should watch the resulting batch payload size

Describe the bug
We currently only issue the batch logging after the configured batch_log_size is about to be exceeded.
https://github.com/reportportal/client-Python/blob/master/reportportal_client/core/log_manager.py#L72

This method also needs to watch the current batch payload size, as RP server refuses requests that exceed the pre-configured maximum payload size:

ResponseError(error_messages[0])
16:10:24  reportportal_client.errors.ResponseError: 5000: Unclassified error [Maximum upload size of 67108864 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$FileSizeLimitExceededException: The field json_request_part exceeds its maximum permitted size of 67108864 bytes.]

Steps to Reproduce
Steps to reproduce the behavior:

  1. either set the log_batch_size to a really high value and try to log a lot of messages or try to log a really long message (tl;dr generate a payload larger than a max allowed payload size on a server - default is probably 67108864 bytes)

Expected behavior

  • implement configurable parameter: log_batch_payload_size.

  • _log_process function should watch this and "flush" (send) the batch before appending another log message in case the payload is about to be exceeded.

  • Figure out a sane way of handling a single log that itself exceeds the limit - maybe some string-splitting strategy could apply with a WARNING message being logged.

Actual behavior
the client crashes with raising the ResponseError

Package versions
5.2.0

Reportportal client crashing due to maximum upload size exceeded

Describe the bug
Report Portal client causing pytest crash with the following trace.

021-09-21 01:38:05failures/test_ncc_failure.py:627: in test_ncc_failure
    logger, testinfo, rp_logger)
lib/dnet_generic.py:802: in process_test_function_results
    attach_session_logs(testinfo,rp_logger)
lib/dnet_generic.py:788: in attach_session_logs
    "data": contents, "mime": "text/plain"})
/usr/local/lib/python3.7/logging/__init__.py:1378: in info
    self._log(INFO, msg, args, **kwargs)
/opt/p1-dir/python-venv/p1-user-venv/lib/python3.7/site-packages/pytest_reportportal/rp_logging.py:49: in _log
    self.handle(record)
/usr/local/lib/python3.7/logging/__init__.py:1524: in handle
    self.callHandlers(record)
/usr/local/lib/python3.7/logging/__init__.py:1586: in callHandlers
    hdlr.handle(record)
/usr/local/lib/python3.7/logging/__init__.py:894: in handle
    self.emit(record)
/opt/p1-dir/python-venv/p1-user-venv/lib/python3.7/site-packages/pytest_reportportal/rp_logging.py:102: in emit
    attachment=record.__dict__.get('attachment', None),
/opt/p1-dir/python-venv/p1-user-venv/lib/python3.7/site-packages/pytest_reportportal/service.py:329: in post_log
    self.rp.log(**sl_rq)
/opt/p1-dir/python-venv/p1-user-venv/lib/python3.7/site-packages/reportportal_client/service.py:391: in log
    return self.log_batch([data], item_id=item_id)
/opt/p1-dir/python-venv/p1-user-venv/lib/python3.7/site-packages/reportportal_client/service.py:461: in log_batch
    return _get_data(r)
/opt/p1-dir/python-venv/p1-user-venv/lib/python3.7/site-packages/reportportal_client/service.py:98: in _get_data
    raise ResponseError(error_messages[0])
E   reportportal_client.errors.ResponseError: 5000: Unclassified error [Maximum upload size of 67108864 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 67108864 bytes.]

Steps to Reproduce
Steps to reproduce the behavior:
Certain tests I'm running produce large log files. These log files are uploaded to report portal via the reportportal_client. (I believe this is happening during log file upload...) Is there a way to increase this value to accommodate larger File uploads?

This is the code that is uploading log files:

#############################################################
# Send netmiko session logs as attachments to ReportPortal
#############################################################
def attach_session_logs(testinfo,rp_logger):
    for dev in testinfo['log_files']: # loop through session log file names
        dirpath = os.getcwd()

        # get log file in current working directory
        log_dir = Path(dirpath,testinfo['log_files'][dev]) 

        # open log file and send contents as an attachment to reportportal
        with open(log_dir) as file: 
            contents = file.read()
            rp_logger.info("Session Log Attachment - " + testinfo['log_files'][dev],
                                     attachment={"name": testinfo['log_files'][dev],
                                    "data": contents, "mime": "text/plain"})

Expected behavior
The large log file should be upload without crashing report portal client

Actual behavior
What actually happened.

Package versions
pytest-reportportal==5.0.3
reportportal-client==5.0.3

Additional context
Add any other context about the problem here.

Add a way to get launch UI id and UI URL.

ReportPortalService() does not have a method to get UI ID and URL that a user may use to get the launch in ReportPortal.like http://172.17.120.254:8080/ui/#superadmin_personal/launches/all/11

Would be great to have it. SO that we could print in in Pytest/other clients at the beginning/end of a session to be used by one click.

Launch is not populated on the gui but a uuid for that launch is generated

Hello

We use reportportal_client in our tool to import xunit files to RP instance.Once launch is completed we use the below api to get the launch id
/launch?filter.eq.uuid=<UUID>

We are seeing this issue where the launch starts and finishes and generates the uuid, but while using the above api , the response is empty. The gui also does not show any launch started. This issue is seen around every 10 launches

output from the uuid filter api


DEBUG (api_get) url: https://<OUR_RP_INSTANCE>/api/v1/<OUR_PROJECT>/launch?filter.eq.uuid=b399ce6a-446b-4843-a8e2-56d44514b306
2022-07-08 10:57:33,627 DEBUG (api_get) r.status_code: 200
2022-07-08 10:57:33,628 DEBUG (api_get) r.text: {"content":[],"page":{"number":1,"size":20,"totalElements":0,"totalPages":0}}

If i use this uuid and run it from the swagger api provided on the RP instance, i still get an empty content with 200 response.

Any idea where i can debug further or what could be the reason of this behavior

reportportal-client==5.2.2
Python 3.9.9
ReportPortal Current version:API Service: 5.6.3;Authorization Service: 5.6.3;Service UI: 5.6.0;

Appreciate any help!
Thanks,
Rujuta

Report Portal Client should have a way to silence error messages.

When my Report Portal goes down or I have a connection issue report portal get flooded with messages in my behave tests.
For example: 404 and 401 I get a whole html page or a giant exception message.

Long story short: A supress messages parameter for report portal related messages would be nice.

New Release

Can you please release the current code which has parameters support?

client-python is not finishing launches in ReportPortal Version 5.3.3

Hi all,
I am trying to push some results to a ReportPortal instance has version 5.3.3.
But the script I am using is not working so I try to follow all the steps mentioned in this REPO but it's still not finishing.
Python file I am using.

import os
import subprocess
import traceback
from mimetypes import guess_type
from time import time
from reportportal_client import ReportPortalService

def timestamp():
    return str(int(time() * 1000))

endpoint = "my_rp_id"
project = "test"
# You can get UUID from user profile page in the Report Portal.
token = "my_token"
launch_name = "Test launch"
launch_doc = "Testing logging with attachment."

service = ReportPortalService(endpoint=endpoint, project=project,
                                   token=token)

launch = service.start_launch(name=launch_name,
                              start_time=timestamp(),
                              description=launch_doc)

item_id = service.start_test_item(name="Test Case",
                                  description="First Test Case",
                                  start_time=timestamp(),
                                  item_type="STEP",
                                  parameters={"key1": "val1",
                                              "key2": "val2"})

service.log(time=timestamp(),
            message="Hello World!",
            level="INFO")

service.finish_test_item(item_id=item_id, end_time=timestamp(), status="PASSED")
service.finish_launch(end_time=timestamp())
service.terminate()

and the output goes like this

(test_vert) [vipikuma@kvy rp_issue]$ python rp.py 
(test_vert) [vipikuma@kvy rp_issue]$ 

But On the ReportPortal WUI, it's looking like this.
Screenshot from 2021-03-15 11-33-58

Tools Used:
OS: Fedora release 32 (Thirty Two)
Python: Python 3.8.7
Report Portal Client: reportportal-client 5.0.9

I tried waiting for 1-2 hours but it's still the same.

New Release 3.2.3

For what I've seen, the released code on pypi seems to be outdated.
The support for verify ssl and get project settings is not available with current version(3.2.0).
Is the current code ready to release?
What's the process to get it release?

Reportportal is starting a huge number of connections when using the requests lib in a test

Hi!

I have been trouble shooting a large amount of the day a found that when using the requests lib in a pytest and issuing a GET request the reportportal_client floods the log with:
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection ...

I enabled logging in pytest.ini as my testcase seamed to hang (bold row in test_file.py) when running pytest with --reportportal flag. Without using reportportal the test is passing OK.

pytest.ini
[pytest] rp_endpoint = http://10.46.61.14:8080/ rp_uuid = 67d0585c-9812-439e-9a8a-dece859204c7 rp_launch = Test_framework rp_project = LHD_PERSONAL rp_launch_attributes = 'LHD' log_cli = True log_level = DEBUG

test_file.py
`import requests
import time
import pytest

def test_one():
for i in range(6):
print(requests.get("http://10.46.100.135:5001/"))
time.sleep(1)`

conftest.py
from pathlib import Path
import pytest

Using Reportportal: Build: 5.1.0
Using a virtual environment with the following packages installed:
atomicwrites (1.4.0)
attrs (19.3.0)
certifi (2020.4.5.1)
chardet (3.0.4)
dill (0.3.1.1)
idna (2.9)
importlib-metadata (1.6.0)
more-itertools (8.3.0)
packaging (20.4)
pip (9.0.1)
pkg-resources (0.0.0)
pluggy (0.13.1)
py (1.8.1)
pyparsing (2.4.7)
pytest (5.4.2)
pytest-reportportal (5.0.3)
reportportal-client (5.0.3)
requests (2.23.0)
setuptools (39.0.1)
six (1.15.0)
urllib3 (1.25.9)
wcwidth (0.2.2)
zipp (3.1.0)

LOGG when NOissue occurs (not using reportportal)
(venv) ubuntu@ubuntu-TMGmlin:~/stash/pytest_lab$ python3 -m pytest /home/ubuntu/stash/pytest_lab/test_file.py
================================================================== test session starts ===================================================================
platform linux -- Python 3.6.9, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: /home/ubuntu/stash/pytest_lab, inifile: pytest.ini
plugins: reportportal-5.0.3
collected 1 item

test_file.py::test_one
--------------------------------------------------------------------- live log call ----------------------------------------------------------------------
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.100.135:5001
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.100.135:5001 "GET / HTTP/1.1" 200 35440
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.100.135:5001
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.100.135:5001 "GET / HTTP/1.1" 200 35440
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.100.135:5001
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.100.135:5001 "GET / HTTP/1.1" 200 35440
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.100.135:5001
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.100.135:5001 "GET / HTTP/1.1" 200 35440
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.100.135:5001
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.100.135:5001 "GET / HTTP/1.1" 200 35440
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.100.135:5001
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.100.135:5001 "GET / HTTP/1.1" 200 35440
PASSED [100%]

=================================================================== 1 passed in 6.34s ====================================================================

LOGG when issue occurs
(venv) ubuntu@ubuntu-TMGmlin:~/stash/pytest_lab$ python3 -m pytest /home/ubuntu/stash/pytest_lab/test_file.py --reportportal
----------------------------------------------------------------- live log sessionstart ------------------------------------------------------------------
DEBUG pytest_reportportal.service:service.py:128 ReportPortal - Init service: endpoint=http://10.46.61.14:8080/, project=LHD_PERSONAL, uuid=67d0585c-9812-439e-9a8a-dece859204c7
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.61.14:8080 "GET /api/v1/LHD_PERSONAL/settings HTTP/1.1" 200 676
DEBUG reportportal_client.service:service.py:367 settings
DEBUG pytest_reportportal.service:service.py:160 ReportPortal - Start launch: equest_body={'attributes': [{'value': 'LHD'}, {'key': 'agent', 'value': 'pytest-reportportal-pytest-reportportal 5.0.3', 'system': True}, {'key': 'cpu', 'value': 'x86_64', 'system': True}, {'key': 'machine', 'value': 'x86_64', 'system': True}, {'key': 'os', 'value': 'Linux', 'system': True}], 'name': 'Test_framework', 'start_time': '1591126941056', 'description': '', 'mode': None}
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.61.14:8080 "POST /api/v2/LHD_PERSONAL/launch HTTP/1.1" 201 59
DEBUG reportportal_client.service:service.py:225 start_launch - ID: 5590b041-8a1b-4c9c-a3d8-dd464cc11cf4
DEBUG pytest_reportportal.service:service.py:162 ReportPortal - Launch started: id=5590b041-8a1b-4c9c-a3d8-dd464cc11cf4
collected 1 item
------------------------------------------------------------------ live log collection -------------------------------------------------------------------
DEBUG pytest_reportportal.service:service.py:243 ReportPortal - Start Suite: request_body={'name': 'test_file.py', 'description': None, 'start_time': '1591126941143', 'item_type': 'SUITE', 'parent_item_id': None}
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.61.14:8080 "POST /api/v2/LHD_PERSONAL/item HTTP/1.1" 201 45
DEBUG reportportal_client.service:service.py:290 start_test_item - ID: 4030c073-cbea-42d5-affc-5435e8e5f2c5
DEBUG pytest_reportportal.service:service.py:262 ReportPortal - Start TestItem: request_body={'attributes': [], 'name': 'test_one', 'description': None, 'start_time': '1591126941216', 'item_type': 'STEP', 'parent_item_id': '4030c073-cbea-42d5-affc-5435e8e5f2c5', 'parameters': None}
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.61.14:8080 "POST /api/v2/LHD_PERSONAL/item/4030c073-cbea-42d5-affc-5435e8e5f2c5 HTTP/1.1" 201 45
DEBUG reportportal_client.service:service.py:290 start_test_item - ID: 5e9da4a3-2dde-4e0e-b64b-788919bacfd2

--------------------------------------------------------------------- live log call ----------------------------------------------------------------------
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (1): 10.46.100.135:5001
DEBUG urllib3.connectionpool:connectionpool.py:442 http://10.46.61.14:8080 "POST /api/v2/LHD_PERSONAL/log HTTP/1.1" 201 45
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (2): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (3): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (4): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (5): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (6): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (7): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (8): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (9): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (10): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (11): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (12): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (13): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (14): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (15): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (16): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (17): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (18): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (19): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (20): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (21): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (22): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (23): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (24): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (25): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (26): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (27): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (28): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (29): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (30): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (31): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (32): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (33): 10.46.61.14:8080
WARNING urllib3.connectionpool:connectionpool.py:303 Connection pool is full, discarding connection: 10.46.61.14
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (34): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (35): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (36): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (37): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (38): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (39): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (40): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (41): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (42): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (43): 10.46.61.14:8080
WARNING urllib3.connectionpool:connectionpool.py:303 Connection pool is full, discarding connection: 10.46.61.14
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (44): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (45): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (46): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (47): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (48): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (49): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (50): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (51): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (52): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (53): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (54): 10.46.61.14:8080
WARNING urllib3.connectionpool:connectionpool.py:303 Connection pool is full, discarding connection: 10.46.61.14
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (55): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (56): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (57): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (58): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (59): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (60): 10.46.61.14:8080
DEBUG urllib3.connectionpool:connectionpool.py:230 Starting new HTTP connection (61): 10.46.61.14:8080
..... and it just keeps on going ....

Any suggestions how to solve this is appreciated. Please let me know i you need more information.

Detect spurious slash at end of ReportPortal URL

Is your feature request related to a problem? Please describe.
My configuration

  • ReportPortal 5.7.2 in Docker in WSL2 on my laptop
  • I am running some simple tests Robot Framework tests (https://gitlab.com/m4711/robotframework-samples)
  • I try to push their results in ReportPortal (using gitbash in Windows on my laptop)

I tried initially with the following command line;

robot --outputdir reports --listener robotframework_reportportal.listener --variable RP_UUID:"b58f8cf0-56a1-44eb-a1ca-45453d5302bc" --variable RP_ENDPOINT:"http://127.0.0.1:8080/" --variable RP_LAUNCH:"my ROBOTFRAMEWORKSAMPLES launch" --variable RP_PROJECT:"ROBOTFRAMEWORKSAMPLES" --xunit junit_report.xml --variable RP_ATTACH_XUNIT:"True" --variable RP_ATTACH_REPORT:"True" --variable RP_ATTACH_LOG:"True" mazure.robot

I got:

$ robot --outputdir reports --listener robotframework_reportportal.listener --variable RP_UUID:"b58f8cf0-56a1-44eb-a1ca-45453d5302bc" --variable RP_ENDPOINT:"http://127.0.0.1:8080/" --variable RP_LAUNCH:"my ROBOTFRAMEWORKSAMPLES launch" --variable RP_PROJECT:"ROBOTFRAMEWORKSAMPLES" --xunit junit_report.xml --variable RP_ATTACH_XUNIT:"true" --variable RP_ATTACH_REPORT:"true" --variable RP_ATTACH_LOG:"true" mazure.robot
==============================================================================
Mazure :: An example to discover Robot Framework
==============================================================================
Redirection                                                           | PASS |
------------------------------------------------------------------------------
Access to site map                                                    | PASS |
------------------------------------------------------------------------------
Open and close site map nodes                                         | PASS |
------------------------------------------------------------------------------
Mazure :: An example to discover Robot Framework                      | PASS |
3 tests, 3 passed, 0 failed
==============================================================================
Output:  C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\output.xml
XUnit:   C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\junit_report.xml
Log:     C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\log.html
Report:  C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\report.html
Invalid response: Expecting value: line 1 column 1 (char 0): <!doctype html>
  <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta charset="utf-8">
      <title>Report Portal</title>
      <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="shortcut icon" href="favicon.ico" integrity="sha256-Mr4AWVWgTArdmfjZN1U+2tmaoaN8yDYA3/qI6356in8= sha384-QcqS5R2LgskCl7kI5omfbGh5EfXB0V9SPHt4iyhgQJT2A7YBrhh26RT1hiL9Ji7H" crossorigin="anonymous"><link href="styles.4cddaa.css" rel="stylesheet" integrity="sha256-QOuA3f687xImz6IhHhV1/4Q00gomP94tOVF/gD5eJ2k= sha384-vpHCo6OBGrJ3Wx553KODN2v6hrQFCMOXx7jFT3ANRCGY2tiTRtq2zoERgvBs9t2t" crossorigin="anonymous"><link href="main.4cddaa.css" rel="stylesheet" integrity="sha256-T9iuSHMgycfoYAns8tS160x/YNDBE+zdEQ3jX5NVqlU= sha384-9ryc8ya6F0/wdwD5uOlZ0/r/xh0DrE8Y+LB8N0jKkiKt00issn2er8ondLqkV07W" crossorigin="anonymous"></head>
    <body>
      <div id="app" style="width: 100%; height: 100%;"></div>
      <div id="popover-root"></div>
      <div id="modal-root"></div>
      <div id="tooltip-root"></div>
      <div id="notification-root"></div>
      <div id="screen-lock-root"></div>
    <script type="text/javascript" src="polyfills.app.4cddaa.js" integrity="sha256-1ZGc8CL195nAHjxzHp1O3nlwQ/MJugkpsnHDGfxwxz8= sha384-P6ra7XZ+Lp6c9WiEFw4iLDwIxwE9B1mo8lnn8eGMcjmKQ1US6dNFZHzmbveTRzfd" crossorigin="anonymous"></script><script type="text/javascript" src="styles.app.4cddaa.js" integrity="sha256-+lh4MEnjvnB1JzBHdRBt/6Su+cjbu2TMg4UZ8qos0Pw= sha384-9pFLuwI8xfYv2fBMN1fDMjOllhCYZwarv8CmE9SvkmV5MVuSSXrt6NWj7G7BInpV" crossorigin="anonymous"></script><script type="text/javascript" src="main.app.4cddaa.js" integrity="sha256-GHReOkFpGqOMJmpHoy4Jc6N7eF9qjVRhaSAZYoAq/54= sha384-F13Po5ujXxWAYhF6zQJz1TUroRD021Sj98x782IURdgdDoc491qr9+x8t8TeLCYT" crossorigin="anonymous"></script></body>
  </html>
Traceback (most recent call last):
  File "C:\Users\lmazure\AppData\Local\Programs\Python\Python39\lib\site-packages\reportportal_client\core\rp_responses.py", line 77, in _get_json
    return data.json()
  File "C:\Users\lmazure\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\models.py", line 910, in json
    return complexjson.loads(self.text, **kwargs)
  File "C:\Users\lmazure\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "C:\Users\lmazure\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Users\lmazure\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

After some time, I got the idea to remove the slash at the end of the ReportPortal URL, things went better:

$ robot --outputdir reports --listener robotframework_reportportal.listener --variable RP_UUID:"b58f8cf0-56a1-44eb-a1ca-45453d5302bc" --variable RP_ENDPOINT:"http://127.0.0.1:8080" --variable RP_LAUNCH:"my ROBOTFRAMEWORKSAMPLES launch" --variable RP_PROJECT:"ROBOTFRAMEWORKSAMPLES" --xunit junit_report.xml --variable RP_ATTACH_XUNIT:"True" --variable RP_ATTACH_REPORT:"True" --variable RP_ATTACH_LOG:"True" mazure.robotNDPOINT:"http://127.0.0.1:8080" --variable RP_LAUNCH:"my ROBOTFRAMEWORKSAMPLES launch" --variable RP_PROJECT:"ROBOTFRAMEWO==============================================================================le RP_ATTACH_REPORT:"true" --variable RP_ATTACH_LOG:"true" mazure.robot
Mazure :: An example to discover Robot Framework
==============================================================================
Redirection                                                           | PASS |
------------------------------------------------------------------------------
Access to site map                                                    | PASS |
------------------------------------------------------------------------------
Open and close site map nodes                                         | PASS |
------------------------------------------------------------------------------
Mazure :: An example to discover Robot Framework                      | PASS |
3 tests, 3 passed, 0 failed
==============================================================================
Output:  C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\output.xml
XUnit:   C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\junit_report.xml
Log:     C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\log.html
Report:  C:\Users\lmazure\Documents\code\tempo\robotframework-samples\reports\report.html

Describe the solution you'd like
Would it be possible to get a real error message when the URL is incorrect?

Describe alternatives you've considered

Additional context

KeyError: 'PYTEST_CURRENT_TEST' on _post_log_batch

I really don't know what is going on here, i spotted this in a wild, while running py.test with xdist.
according the logs, the [gw5] worker wasn't stuck but successfully executed other tests, however the "crashed" test wasn't properly stopped on RP. Now the whole py.test seems to be hanging.

[gw5] [  7%] FAILED tests/foreman/api/test_contentviewversion.py::ContentViewVersionDeleteTestCase::test_positive_delete_with_puppet_content Traceback (most recent call last):
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/reportportal_client/service_async.py", line 228, in process_item
    self.process_log(**kwargs)
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/reportportal_client/service_async.py", line 212, in process_log
    self._post_log_batch()
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/reportportal_client/service_async.py", line 200, in _post_log_batch
    self.rp_client.log_batch(self.log_batch)
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/reportportal_client/service.py", line 294, in log_batch
    r = self.session.post(url=url, files=files, verify=self.verify_ssl)
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/requests/sessions.py", line 559, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/requests/sessions.py", line 503, in request
    prep.url, proxies, stream, verify, cert
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/requests/sessions.py", line 676, in merge_environment_settings
    env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib/python3.6/site-packages/requests/utils.py", line 763, in get_environ_proxies
    return getproxies()
  File "/usr/lib64/python3.6/urllib/request.py", line 2480, in getproxies_environment
    for name, value in os.environ.items():
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib64/python3.6/_collections_abc.py", line 744, in __iter__
    yield (key, self._mapping[key])
  File "/home/jenkins/shiningpanda/jobs/9ce8c4b2/virtualenvs/d41d8cd9/lib64/python3.6/os.py", line 669, in __getitem__
    raise KeyError(key) from None
KeyError: 'PYTEST_CURRENT_TEST'

this also happened on some other workers during the same run later - same symptoms.

Test hangs if the launch request gets no response

Describe the bug
Test hangs on ReportPortalService.start_launch() if report portal service is accessible but cannot handle launch POST request.

r = self.session.post(url=url, json=data, verify=self.verify_ssl)
never timeouts in that instance.

This issue is caused by no response from the service-api but the client should handle even that case.

Steps to Reproduce

  1. Deploy report portal stack.
  2. Fill the disk where the stack is running.
  3. Start test from different machine with the rp_endpoint set.

Expected behavior
service-api sends a fail/success response normally or the python client timeouts if no response.

Actual behavior
Test hangs on the launch POST request.

Package versions
pytest-reportportal==5.0.11
reportportal-client==5.1.0

Additional context
Related service-api issue: reportportal/service-api#1546

Pytest reportportal throws Connection pool is full; Discarding connection issue when trying to use Multiprocessing for sending requests to AWS using boto3

Seeing an issue of 'connection pool being full; discarding connection' when using reportportal pytest package for logging along with the test using Multiprocessing for sending requests to AWS using boto3. I have upgraded report portal to v5

requirements:
pytest-reportportal 5.0.3
reportportal-client 5.0.3

Here is the error I am seeing:
Creating sns topics
AKIA5MLTZV3YLZJVTYWY Ig2IE/2RnXMeq8cpkAZgcEXNmn/MD6Itlfns33Fp autotesttopic 5000 0
AKIA5MLTZV3YLZJVTYWY Ig2IE/2RnXMeq8cpkAZgcEXNmn/MD6Itlfns33Fp autotesttopic 5000 2
AKIA5MLTZV3YLZJVTYWY Ig2IE/2RnXMeq8cpkAZgcEXNmn/MD6Itlfns33Fp autotesttopic 5000 4
AKIA5MLTZV3YLZJVTYWY Ig2IE/2RnXMeq8cpkAZgcEXNmn/MD6Itlfns33Fp autotesttopic 5000 6
Connection pool is full, discarding connection: testperf.com
Connection pool is full, discarding connection: testperf.com
Connection pool is full, discarding connection: testperf.com
Connection pool is full, discarding connection: testperf.com

Note: I was not seeing this issue in the previous versions and also without report portal in picture, this issue is not happening

rp_ignore_errors = True flag is not working

Hello,

When report portal server is not reachable then my job is failing, even if i have added rp_ignore_errors = True in my pytest ini file .

pytest.ini

{code}
[pytest]

rp_uuid = XXXXXX
rp_endpoint = http://XXXX:8080
rp_project = XXX
rp_launch = default_launcher
rp_ignore_errors = True
rp_hierarchy_dirs = True

Error

NodeXXXXXXX::XXXXXX
 Fail to take screen-shot: Invalid response: Expecting value: line 1 column 1 (char 0): Bad Gateway
 INTERNALERROR> Traceback (most recent call last):
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 119, in _get_json
 INTERNALERROR>     return response.json()
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/requests/models.py", line 898, in json
 INTERNALERROR>     return complexjson.loads(self.text, **kwargs)
 INTERNALERROR>   File "/usr/lib/python3.6/json/__init__.py", line 354, in loads
 INTERNALERROR>     return _default_decoder.decode(s)
 INTERNALERROR>   File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
 INTERNALERROR>     obj, end = self.raw_decode(s, idx=_w(s, 0).end())
 INTERNALERROR>   File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
 INTERNALERROR>     raise JSONDecodeError("Expecting value", s, err.value) from None
 INTERNALERROR> json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
 INTERNALERROR> 
 INTERNALERROR> During handling of the above exception, another exception occurred:
 INTERNALERROR> 
 INTERNALERROR> Traceback (most recent call last):
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/_pytest/main.py", line 197, in wrap_session
 INTERNALERROR>     session.exitstatus = doit(config, session) or 0
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/_pytest/main.py", line 247, in _main
 INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/hooks.py", line 286, in __call__
 INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 93, in _hookexec
 INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 87, in <lambda>
 INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 208, in _multicall
 INTERNALERROR>     return outcome.get_result()
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 80, in get_result
 INTERNALERROR>     raise ex[1].with_traceback(ex[2])
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 187, in _multicall
 INTERNALERROR>     res = hook_impl.function(*args)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/_pytest/main.py", line 271, in pytest_runtestloop
 INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/hooks.py", line 286, in __call__
 INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 93, in _hookexec
 INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 87, in <lambda>
 INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 203, in _multicall
 INTERNALERROR>     gen.send(outcome)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pytest_reportportal/listener.py", line 47, in pytest_runtest_protocol
 INTERNALERROR>     item, item_id, self.result or 'SKIPPED', self.issue or None)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/pytest_reportportal/service.py", line 282, in finish_pytest_item
 INTERNALERROR>     self.rp.finish_test_item(**fta_rq)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 347, in finish_test_item
 INTERNALERROR>     return _get_msg(r)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 80, in _get_msg
 INTERNALERROR>     return _get_data(response)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 93, in _get_data
 INTERNALERROR>     data = _get_json(response)
 INTERNALERROR>   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 124, in _get_json
 INTERNALERROR>     "Invalid response: {0}: {1}".format(value_error, response.text))
 INTERNALERROR> reportportal_client.errors.ResponseError: Invalid response: Expecting value: line 1 column 1 (char 0): Bad Gateway
 Traceback (most recent call last):
   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 119, in _get_json
     return response.json()
   File "/usr/local/lib/python3.6/dist-packages/requests/models.py", line 898, in json
     return complexjson.loads(self.text, **kwargs)
   File "/usr/lib/python3.6/json/__init__.py", line 354, in loads
     return _default_decoder.decode(s)
   File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
     obj, end = self.raw_decode(s, idx=_w(s, 0).end())
   File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
     raise JSONDecodeError("Expecting value", s, err.value) from None
 json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
 During handling of the above exception, another exception occurred:
 Traceback (most recent call last):
   File "/usr/local/bin/pytest", line 11, in <module>
     sys.exit(main())
   File "/usr/local/lib/python3.6/dist-packages/_pytest/config/__init__.py", line 93, in main
     config=config
   File "/usr/local/lib/python3.6/dist-packages/pluggy/hooks.py", line 286, in __call__
     return self._hookexec(self, self.get_hookimpls(), kwargs)
   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 93, in _hookexec
     return self._inner_hookexec(hook, methods, kwargs)
   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 87, in <lambda>
     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 208, in _multicall
     return outcome.get_result()
   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 80, in get_result
     raise ex[1].with_traceback(ex[2])
   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 187, in _multicall
     res = hook_impl.function(*args)
   File "/usr/local/lib/python3.6/dist-packages/_pytest/main.py", line 240, in pytest_cmdline_main
     return wrap_session(config, _main)
   File "/usr/local/lib/python3.6/dist-packages/_pytest/main.py", line 233, in wrap_session
     session=session, exitstatus=session.exitstatus
   File "/usr/local/lib/python3.6/dist-packages/pluggy/hooks.py", line 286, in __call__
     return self._hookexec(self, self.get_hookimpls(), kwargs)
   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 93, in _hookexec
     return self._inner_hookexec(hook, methods, kwargs)
   File "/usr/local/lib/python3.6/dist-packages/pluggy/manager.py", line 87, in <lambda>
     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 203, in _multicall
     gen.send(outcome)
   File "/app/tests/fixtures/api_fixtures.py", line 133, in pytest_sessionfinish
     return (yield).get_result()
   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 80, in get_result
     raise ex[1].with_traceback(ex[2])
   File "/usr/local/lib/python3.6/dist-packages/pluggy/callers.py", line 187, in _multicall
     res = hook_impl.function(*args)
   File "/usr/local/lib/python3.6/dist-packages/pytest_reportportal/plugin.py", line 96, in pytest_sessionfinish
     session.config.py_test_service.finish_launch()
   File "/usr/local/lib/python3.6/dist-packages/pytest_reportportal/service.py", line 310, in finish_launch
     self.rp.finish_launch(**fl_rq)
   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 241, in finish_launch
     return _get_msg(r)
   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 80, in _get_msg
     return _get_data(response)
   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 93, in _get_data
     data = _get_json(response)
   File "/usr/local/lib/python3.6/dist-packages/reportportal_client/service.py", line 124, in _get_json
     "Invalid response: {0}: {1}".format(value_error, response.text))
 reportportal_client.errors.ResponseError: Invalid response: Expecting value: line 1 column 1 (char 0): Bad Gateway
 ERROR: Job failed: exit code 1

Duplicate agent name in agent name attached as system information

# python
Python 3.6.5 (default, Apr 10 2018, 17:08:37) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from reportportal_client.service import ReportPortalService
>>> ReportPortalService.get_system_information('pytest-reportportal')
{'agent': 'pytest-reportportal-pytest-reportportal 5.0.2', 'os': 'Linux', 'cpu': 'x86_64', 'machine': 'x86_64'}

run pybot got the 'NoneType' object has no attribute 'put_nowait' errors

I just run the pybot command, but an got error as below

pybot --listener robotframework_reportportal.listener --variable RP_UUID:"b514a045-0a6d-4dc9-a496-fae494f8c928" --variable RP_ENDPOINT:"http://ip172-18-0-10-bc51moquguig00f5g7i0-8080.direct.labs.play-with-docker.com" --variable RP_LAUNCH:"Robotframework_test_demo" --variable RP_PROJECT:"Robotframework_test_demo" -d Results test.robot

==============================================================================
Test

test | PASS |

[ ERROR ] Calling method 'log_message' of listener 'robotframework_reportportal.listener' failed: AttributeError: 'NoneType' object has no attribute 'put_nowait'
gfp Traceback (most recent call last):
File "/Users/Larry/anaconda2/lib/python2.7/site-packages/reportportal_client/service_async.py", line 204, in process_item
getattr(self.rp_client, method)(**kwargs)
File "/Users/Larry/anaconda2/lib/python2.7/site-packages/reportportal_client/service.py", line 187, in finish_test_item
return _get_msg(r)
File "/Users/Larry/anaconda2/lib/python2.7/site-packages/reportportal_client/service.py", line 22, in _get_msg
return _get_data(response)["msg"]
File "/Users/Larry/anaconda2/lib/python2.7/site-packages/reportportal_client/service.py", line 34, in _get_data
raise ResponseError(error_messages[0])
ResponseError: 5000: Unclassified error [null]
[ ERROR ] Calling method 'end_keyword' of listener 'robotframework_reportportal.listener' failed: AttributeError: 'NoneType' object has no attribute 'put_nowait'
[ ERROR ] Calling method 'start_keyword' of listener 'robotframework_reportportal.listener' failed: AttributeError: 'NoneType' object has no attribute 'put_nowait'
[ ERROR ] Calling method 'end_keyword' of listener 'robotframework_reportportal.listener' failed: AttributeError: 'NoneType' object has no attribute 'put_nowait'
[ ERROR ] Calling method 'end_test' of listener 'robotframework_reportportal.listener' failed: AttributeError: 'NoneType' object has no attribute 'put_nowait'

my robot framework version is Robot Framework 3.0.2 (Python 2.7.12 on darwin)

Add support to push tags in ReportPortalService class for Report Portal Version 5

Hi all, in client-Python v3 we can pass tags in start_launch method of class ReportPortalServiceAsync but this feature seems to be missing in
client-Python v5 with class ReportPortalService.

Can we implement the same in ReportPortalService or in client-python v5?
I will try to implement it if I can by the time creating this Feature request so that if anyone else has the feature implementd they can push there changes. :)

Pass specific launch_id in start_test_item

I am integrating reportportal with my automation framework. The way the framework is designed, it creates the launch in the initiation but I need to call start_test_items from individual test case (python classes) files. For which the solution I thought is to pass launch_id in start_test_item().

I made the required changes in start_test_item and it works fine for me now.
If this sounds to be a generic requirement, I can send a PR on service.py

Feature: finish_launch updates launch attributes(tags)

finish_launch() does not provide the ability to update/override launch attributes(tags) upon completion. This feature is supported by the underlying API, but has not been included in the client.

Based on the implementation of finish_test(), this seems to be a relatively straightforward implementation.

def finish_launch(self, end_time, status=None, attributes=None, **kwargs):
    """Finish a launch with the given parameters.
    Status can be one of the followings:
    (PASSED, FAILED, STOPPED, SKIPPED, RESETED, CANCELLED)
    """
    # process log batches firstly:
    if self._batch_logs:
        self.log_batch([], force=True)
    if attributes and isinstance(attributes, dict):
        attributes = _dict_to_payload(attributes)
    data = {
        "endTime": end_time,
        "status": status,
        "attributes": attributes
    }
    url = uri_join(self.base_url_v1, "launch", self.launch_id, "finish")
    r = self.session.put(url=url, json=data, verify=self.verify_ssl)
    logger.debug("finish_launch - ID: %s", self.launch_id)
    return _get_msg(r)

This would be great to have so one could add additional tags based on the results of a launch. Of which would also provide more filtering capabilities in the launch view.

Client is reporting "bearer" in lowercase for the token but it should be "Bearer"

Describe the bug
We tried running service-api behind an Envoy proxy and when Python client was reporting the test results, it failed because Envoy rejected the request saying "RBAC failure". When drilled into it, it turns that Envoy expects the beader token prefix as Bearer , not bearer . See https://tools.ietf.org/id/draft-ietf-oauth-v2-bearer-13.xml%5C#rfc.section.1.1 which clearly says this is case sensisitve.

Steps to Reproduce
Steps to reproduce the behavior:

  1. Run service-api behind an envoy proxy or in Istio
  2. Report some results using Python client of RP.

Expected behavior
Tests should be reported correctly.

Actual behavior
RBAC failure reported by the Envoy proxy.

Package versions
Python client: 5.0.10

Raised #154 to fix it because it's just one letter change.

Invalid error handling.

Summary

  1. Wrong approach for exception message updating.
  2. Useless error handling for invalid requests.
  3. Missing response handler for mult-part form request.

Part 1

At the current moment implemented wrong approach for updating error massage like bellow:

try:
    return json.loads(self.raw)["id"]
except KeyError as error:
    error.message += "Raw: {0}".format(self.raw)
    raise

Let's create a simple example err.py and test it on different versions of python:

try:
    x = {"abc":123}["id"]
except KeyError as error:
    error.message += "Raw: {0}".format("some additional info")
    raise

Here is the output:

$ python2 err.py 
Traceback (most recent call last):
  File "err.py", line 2, in <module>
    x = {"abc":123}["id"]
KeyError: 'id'
$ python3 err.py 
Traceback (most recent call last):
  File "err.py", line 2, in <module>
    x = {"abc":123}["id"]
KeyError: 'id'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "err.py", line 4, in <module>
    error.message += "Raw: {0}".format("some additiona info")
AttributeError: 'KeyError' object has no attribute 'message'

As you can see for python2 there is no any additional info appeared. Moreover, python3 exception does not have attribute with name message (chain exception).

Part 2 (more serious)

No exception appeared in case of invalid request!
Let me show an example err2.py.txt
Create save log request without time field like bellow:

log_rq = SaveLogRQ(
    item_id=test.id,
    # time=timestamp(),
    message="Hello World!",
    level="INFO",
)
service.log(log_rq)

image

If you run attached file, no error is appeared and no log message is created in the Report Portal!

You will get error in case of trying to access id from response object for invalid save log request:

log_rq = SaveLogRQ(item_id=test.id,
                                  # time=timestamp(),
                                  message="Hello World!",
                                  level="INFO")
r = service.log(log_rq)
print(r.id)

Traceback is following:

Traceback (most recent call last):
  File "err2.py.txt", line 49, in <module>
    print(r.id)
  File "./client-python/reportportal_client/model/response.py", line 17, in id
    return json.loads(self.raw)["id"]
KeyError: 'id'

Part 3 (improvements)

Need to add response handler for multi-part form request, because json part represented as an array.

image

_log_batch function in ReportPortal service class no longer takes item_id as its parameter

Describe the bug
Previous to the commit mentioned below, the log_batch function was taking item_id as parameter and the log was attaching to that particular item_id specified. But since this commit, item_id is removed from _log_batch function making it impossible to attach the batch log to particular item_id.

29200b0#diff-a76d396c04c4c11ad4bb41b1b9b37f04acdceaa2e6423620cf5b9bff48053f0a

Steps to Reproduce
NOT REQUIRED

Expected behavior
_log_batch function should have item_id parameter added back. And the logs should be attached to item_id if it is given

Actual behavior
_log_batch function does not take in a parameter called item_id hence attaching batch logs to an item_id is not possible

Package versions
Latest Master/eng code

Additional context
Would like to have item_id parameter back into _log_batch function

cc: @iivanou

start_launch failing on RPv4

We are having an issue using a tool we wrote that uses the reportportal-client to interact with our ReportPortal instance. The issue specifically is calling the start_launch method against Report Portal v4.x the error has usually been some form of the following below.

We were able to determine with these latest releases of the client that it's hard-coded to use the v2 API for start_launch but RPv4 does not have that V2 APIs. We were able to workaround this by downgrading the client to 3.2.3

Any chance we can make the API version selection configurable? Make it an option passed to the ReportPortalService class?

Traceback (most recent call last):
  File "/home/dbaez/.virtualenvs/rp_preproc/bin/rp_preproc", line 8, in <module>
    sys.exit(main())
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/rp_preproc/main.py", line 159, in main
    return_code = run(args)
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/rp_preproc/main.py", line 91, in run
    rp_response = preproc.process()
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/rp_preproc/libs/preproc.py", line 130, in process
    response = xunit_xml.process()
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/rp_preproc/libs/xunit_xml.py", line 57, in process
    launch_id = launch.start()
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/rp_preproc/libs/reportportal.py", line 380, in start
    description=self.description)
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/reportportal_client/service.py", line 174, in start_launch
    self.launch_id = _get_id(r)
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/reportportal_client/service.py", line 46, in _get_id
    return _get_data(response)["id"]
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/reportportal_client/service.py", line 61, in _get_data
    data = _get_json(response)
  File "/home/dbaez/.virtualenvs/rp_preproc/lib/python3.6/site-packages/reportportal_client/service.py", line 86, in _get_json
    "Invalid response: {0}: {1}".format(value_error, response.text))
reportportal_client.errors.ResponseError: Invalid response: Expecting value: line 1 column 1 (char 0): <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1">

    <meta name="description" content="">
    <meta name="author" content="">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <!-- Fav and touch icons -->
    <link rel="apple-touch-icon-precomposed" sizes="144x144"
        href="./img/bootstrap/assets/ico/apple-touch-icon-144-precomposed.png">
    <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon">

    <title>Report Portal - Page 404</title>
</head>
<body>

or

Traceback (most recent call last):
  File "/opt/app-root/lib/python3.6/site-packages/reportportal_client/service.py", line 32, in _get_id
    return _get_data(response)["id"]
KeyError: 'id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/opt/app-root/lib/python3.6/site-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/opt/app-root/lib/python3.6/site-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/opt/app-root/lib/python3.6/site-packages/flask_restplus/api.py", line 309, in wrapper
    resp = resource(*args, **kwargs)
  File "/opt/app-root/lib/python3.6/site-packages/flask/views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "/opt/app-root/lib/python3.6/site-packages/flask_restplus/resource.py", line 44, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/opt/app-root/src/rp_preproc/api/process/endpoints/process_payload.py", line 53, in post
    response = preproc.process()
  File "/opt/app-root/src/rp_preproc/libs/preproc.py", line 130, in process
    response = xunit_xml.process()
  File "/opt/app-root/src/rp_preproc/libs/xunit_xml.py", line 57, in process
    launch_id = launch.start()
  File "/opt/app-root/src/rp_preproc/libs/reportportal.py", line 380, in start
    description=self.description)
  File "/opt/app-root/lib/python3.6/site-packages/reportportal_client/service.py", line 153, in start_launch
    self.launch_id = _get_id(r)
  File "/opt/app-root/lib/python3.6/site-packages/reportportal_client/service.py", line 35, in _get_id
    "No 'id' in response: {0}".format(response.text))
reportportal_client.errors.EntryCreatedError: No 'id' in response: {"content":[],"page":{"number":1,"size":20,"totalElements":0,"totalPages":0}}

robotframework and reportportal v5 reporting failing to get launch_id

I did some debugging and it looks like start_launch, start_test_item, finish_test_item throw 400 responses when using reportportal_client to report to version 5 of reportportal. I can see in the url is going to api/v1. Not sure if there is a param to pass to tell the client lib its reporting to v5.
Changing the api/v2 doesn't help either. Looks like its failing to get the launch_id.
File "\venv\lib\site-packages\reportportal_client\service_async.py", line 234, in process_item
getattr(self.rp_client, method)(kwargs)
File "\venv\lib\site-packages\reportportal_client\service.py", line 160, in start_launch
self.launch_id = _get_id(r)
File "
\venv\lib\site-packages\reportportal_client\service.py", line 32, in _get_id
return _get_data(response)["id"]
File "
\venv\lib\site-packages\reportportal_client\service.py", line 55, in _get_data
raise ResponseError(error_messages[0])
reportportal_client.errors.ResponseError: Incorrect Request. [Field 'attributes[].value' should have size from '1' to '128'.] [Field 'attributes[].value' should not contain only white spaces and shouldn't be empty.]
\venv\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Traceback (most recent call last):
File "\venv\lib\site-packages\reportportal_client\service_async.py", line 234, in process_item
getattr(self.rp_client, method)(kwargs)
File "
\venv\lib\site-packages\reportportal_client\service.py", line 223, in start_test_item
item_id = _get_id(r)
File "
\venv\lib\site-packages\reportportal_client\service.py", line 32, in _get_id
return _get_data(response)["id"]
File "
\venv\lib\site-packages\reportportal_client\service.py", line 55, in _get_data
raise ResponseError(error_messages[0])
reportportal_client.errors.ResponseError: Incorrect Request. [Field 'launchUuid' should not be null.]
Traceback (most recent call last):
File "\venv\lib\site-packages\reportportal_client\service_async.py", line 234, in process_item
getattr(self.rp_client, method)(**kwargs)
File "
\venv\lib\site-packages\reportportal_client\service.py", line 223, in start_test_item
item_id = _get_id(r)
File "
\venv\lib\site-packages\reportportal_client\service.py", line 32, in _get_id
return _get_data(response)["id"]
File "
************\venv\lib\site-packages\reportportal_client\service.py", line 55, in _get_data
raise ResponseError(error_messages[0])
reportportal_client.errors.ResponseError: Incorrect Request. [Field 'launchUuid' should not be null.]
**************\venv\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
**************\venv\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
\venv\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
\venv\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
...

<Response [201]>


Traceback (most recent call last):
File "\venv\lib\site-packages\reportportal_client\service_async.py", line 233, in process_item
self._post_log_batch()
File "
\venv\lib\site-packages\reportportal_client\service_async.py", line 203, in _post_log_batch
self.rp_client.log_batch(self.log_batch)
File "**\venv\lib\site-packages\reportportal_client\service.py", line 335, in log_batch
return _get_data(r)
File "
\venv\lib\site-packages\reportportal_client\service.py", line 58, in _get_data
"\n - ".join(["Multiple errors:"] + error_messages))
reportportal_client.errors.ResponseError: Multiple errors:

  • NullPointerException:
  • NullPointerException:
  • NullPointerException:
    %%%%%%%%%%%%%%

Certain configurations of logger fails execution with `AttributeError: 'LogRecord' object has no attribute 'attachment'`

Describe the bug
Under some configurations, test execution may fail with the following error:
AttributeError: 'LogRecord' object has no attribute 'attachment'
This is caused by RPLogHandler.emit calling getattr(record, 'attachment').
Normally, when the logger is configured correctly, this causes no problem because RP patches the logger properly. However, under some conditions, logger initialization could happen before the logger is patched by rp, which then leads to this bug.
Unfortunately I don't have a simple reproduction code for this issue, I will attach it if I can isolate this.

In my opinion, this shouldn't fail the test execution completely.
I noticed that in a previous version, this code was part of reportportal pytest plugin, where the call to get the attachment attribute was done in a safer manner:
attachment=record.__dict__.get('attachment', None) https://github.com/reportportal/agent-python-pytest/blob/def2fa06d79256577ea568b431f6e0f8b497c276/pytest_reportportal/rp_logging.py#L148

Seems like when these classes were moved to the client, this bug may have been introduced, specifically in this commit 0664393

Expected behavior
Logger should fail silently or with some warning, but shouldn't prevent tests from running.

Actual behavior
Tests are failing due to rp logger misconfiguration

Package versions
Using:

  • reportportal pytest plugin 5.1.1
  • reportportal client 5.2.2

Additional context

Long pytest makers make report portal status:interrupted

When i use this on a test:
@pytest.mark.required_options('MACHINE_TYPE=100/101/102/103/104/105/106/107/108/110/111/112, USE_FAM_HLM_SENSOR=1, USE_FAM_OPTION=1, USE_HOLE_LENGTH_MEASURE=1)

report portalt get status:interrupted and this error:
INTERNALERROR> reportportal_client.errors.ResponseError: 4001: Incorrect Request. [Field 'attributes[].value' should have size from '1' to '128'.]

the @pytest.mark.required_options are too long, But are there anything you can do, or do we have to live whit this?

Running robot framework tests inside a container is causing ResponseError: 5000: Unclassified error [null]

I am facing an issue where I am unable to publish my test results to report portal and I suspect it could be because of networking. Below is a more detailed view of my problem.

Test Setup

  • Tests are running inside a ubuntu image on a gitlab-runner container , say hostname gitlab.network
  • The reportportal server is running on a different host, say report-portal.network
  • The tests are called in the docker container with the below command:
robot -d reports --pythonpath lib --listener robotframework_reportportal.listener --variable RP_ENDPOINT:"http://report-portal.network:8080" --variable RP_UUID:"XXXXX-XXXX-XXXX-XXXX-XXXXXXXX" --variable RP_LAUNCH:"GitLab Demo" --variable RP_PROJECT:"GITLAB_TEST" tests/

Issue

As each step is executed, I see the below log writing:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service_async.py", line 208, in process_item
    getattr(self.rp_client, method)(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 199, in finish_test_item
    return _get_msg(r)
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 22, in _get_msg
    return _get_data(response)["msg"]
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 34, in _get_data
    raise ResponseError(error_messages[0])
ResponseError: 5000: Unclassified error [null]
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service_async.py", line 208, in process_item
    getattr(self.rp_client, method)(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 199, in finish_test_item
    return _get_msg(r)
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 22, in _get_msg
    return _get_data(response)["msg"]
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 34, in _get_data
    raise ResponseError(error_messages[0])
ResponseError: 40022: Finish test item is not allowed. Test item '5bc5c17442eba400010da6be' has descendants with 'IN_PROGRESS' status. All descendants '[XvfbRobot.Start Virtual Display (1920, 1080)]'
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service_async.py", line 208, in process_item
    getattr(self.rp_client, method)(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 199, in finish_test_item
    return _get_msg(r)
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 22, in _get_msg
    return _get_data(response)["msg"]
  File "/usr/local/lib/python2.7/dist-packages/reportportal_client/service.py", line 34, in _get_data
    raise ResponseError(error_messages[0])
ResponseError: 40022: Finish test item is not allowed. Test item '5bc5c17442eba400010da6bd' has descendants with 'IN_PROGRESS' status. All descendants '[login.Open Headless Browser (), XvfbRobot.Start Virtual Display (1920, 1080)]'
T

I am not really sure why this should occur. How can we work together to fix this ? Can I provide you with more information or logs ?

service.start_launch doesnot address the rerun flag for the launches

def start_launch(self,
                 name,
                 start_time,
                 description=None,
                 attributes=None,
                 mode=None,
                 **kwargs):

kwargs has never been used to add more data arguments.

    data = {
        "name": name,
        "description": description,
        "attributes": attributes,
        "startTime": start_time,
        "mode": mode,
        "rerun": ???  <-------
    }

RuntimeError: dictionary changed size during iteration

  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/site-packages/reportportal_client/service_async.py", line 208, in process_item
    getattr(self.rp_client, method)(**kwargs)
  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/site-packages/reportportal_client/service.py", line 197, in finish_test_item
    r = self.session.put(url=url, json=data)
  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/site-packages/requests/sessions.py", line 593, in put
    return self.request('PUT', url, data=data, **kwargs)
  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/site-packages/requests/sessions.py", line 524, in request
    prep.url, proxies, stream, verify, cert
  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/site-packages/requests/sessions.py", line 700, in merge_environment_settings
    env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/site-packages/requests/utils.py", line 764, in get_environ_proxies
    return getproxies()
  File "/usr/lib/python3.5/urllib/request.py", line 2421, in getproxies_environment
    for name, value in os.environ.items():
  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/_collections_abc.py", line 676, in __iter__
    for key in self._mapping:
  File "/ws/runner/builds/602f86ba/0/pytest/pytest-qnx/env/lib/python3.5/os.py", line 744, in __iter__
    for key in self._data:
RuntimeError: dictionary changed size during iteration

client-Python seems have no way to use custom SSL certificates

Hi, we are trying to make it work with custom SSL certificates inside our corporate network.

I haven't found any ways to make it use custom certificates because reportportal-client does not pass needed requests param to the user (requests library can accept a custom certificate file on connections). Do you have any plans to implement it or is there any other way to make it work?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.