Repository: reportportal/client-Python

Issue:
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?

Discussion:

Patch:
diff --git a/reportportal_client/helpers.py b/reportportal_client/helpers.py
index a4cecf3..7a52a39 100644
--- a/reportportal_client/helpers.py
+++ b/reportportal_client/helpers.py
@@ -13,10 +13,12 @@ limitations under the License.
 """
 import logging
 import uuid
+from pkg_resources import DistributionNotFound, get_distribution
 from platform import machine, processor, system
 
 import six
-from pkg_resources import DistributionNotFound, get_distribution
+
+from .static.defines import ATTRIBUTE_LENGTH_LIMIT
 
 logger = logging.getLogger(__name__)
 
@@ -106,3 +108,27 @@ def get_package_version(package_name):
     except DistributionNotFound:
         package_version = 'not found'
     return package_version
+
+
+def verify_value_length(attributes):
+    """Verify length of the attribute value.
+
+    The length of the attribute value should have size from '1' to '128'.
+    Otherwise HTTP response will return an error.
+    Example of the input list:
+    [{'key': 'tag_name', 'value': 'tag_value1'}, {'value': 'tag_value2'}]
+    :param attributes: List of attributes(tags)
+    :return:           List of attributes with corrected value length
+    """
+    if attributes is not None:
+        for pair in attributes:
+            if not isinstance(pair, dict):
+                continue
+            attr_value = pair.get('value')
+            if attr_value is None:
+                continue
+            try:
+                pair['value'] = attr_value[:ATTRIBUTE_LENGTH_LIMIT]
+            except TypeError:
+                continue
+    return attributes
diff --git a/reportportal_client/helpers.pyi b/reportportal_client/helpers.pyi
index fbf35ad..763ec63 100644
--- a/reportportal_client/helpers.pyi
+++ b/reportportal_client/helpers.pyi
@@ -1,20 +1,19 @@
 from logging import Logger
-from typing import Dict, List, Text
+from typing import Dict, List, Text, Union
 
 logger: Logger
 
+def generate_uuid() -> Text: ...
 
-def generate_uuid() -> str: ...
-
-
-def convert_string(value: str) -> str: ...
-
+def convert_string(value: Text) -> Text: ...
 
 def dict_to_payload(value: Dict) -> List[Dict]: ...
 
-
-def gen_attributes(rp_attributes: List) -> List[Dict]: ...
+def gen_attributes(rp_attributes: List[Dict]) -> List[Dict]: ...
 
 def get_launch_sys_attrs() -> Dict[Text]: ...
 
 def get_package_version(package_name: Text) -> Text: ...
+
+def verify_value_length(
+        attributes: Union[List[Dict], None]) -> Union[List[Dict], None]: ...
diff --git a/reportportal_client/service.py b/reportportal_client/service.py
index 7ae36f5..3b62caf 100644
--- a/reportportal_client/service.py
+++ b/reportportal_client/service.py
@@ -26,6 +26,7 @@ from six.moves.collections_abc import Mapping
 from requests.adapters import HTTPAdapter
 
 from .errors import ResponseError, EntryCreatedError, OperationCompletionError
+from .helpers import verify_value_length
 
 POST_LOGBATCH_RETRY_COUNT = 10
 logger = logging.getLogger(__name__)
@@ -225,7 +226,7 @@ class ReportPortalService(object):
         data = {
             "name": name,
             "description": description,
-            "attributes": attributes,
+            "attributes": verify_value_length(attributes),
             "startTime": start_time,
             "mode": mode,
             "rerun": rerun,
@@ -251,7 +252,7 @@ class ReportPortalService(object):
         data = {
             "endTime": end_time,
             "status": status,
-            "attributes": attributes
+            "attributes": verify_value_length(attributes)
         }
         url = uri_join(self.base_url_v2, "launch", self.launch_id, "finish")
         r = self.session.put(url=url, json=data, verify=self.verify_ssl)
@@ -346,7 +347,7 @@ class ReportPortalService(object):
         data = {
             "name": name,
             "description": description,
-            "attributes": attributes,
+            "attributes": verify_value_length(attributes),
             "startTime": start_time,
             "launchUuid": self.launch_id,
             "type": item_type,
@@ -374,7 +375,7 @@ class ReportPortalService(object):
         """
         data = {
             "description": description,
-            "attributes": attributes,
+            "attributes": verify_value_length(attributes),
         }
         item_id = self.get_item_id_by_uuid(item_uuid)
         url = uri_join(self.base_url_v1, "item", item_id, "update")
@@ -413,7 +414,7 @@ class ReportPortalService(object):
             "status": status,
             "issue": issue,
             "launchUuid": self.launch_id,
-            "attributes": attributes
+            "attributes": verify_value_length(attributes)
         }
         url = uri_join(self.base_url_v2, "item", item_id)
         r = self.session.put(url=url, json=data, verify=self.verify_ssl)
diff --git a/reportportal_client/static/defines.py b/reportportal_client/static/defines.py
index dafbbb5..1616fd5 100644
--- a/reportportal_client/static/defines.py
+++ b/reportportal_client/static/defines.py
@@ -78,6 +78,7 @@ class Priority(enum.IntEnum):
     PRIORITY_LOW = 0x3
 
 
+ATTRIBUTE_LENGTH_LIMIT = 128
 DEFAULT_PRIORITY = Priority.PRIORITY_MEDIUM
 NOT_FOUND = _PresenceSentinel()
 NOT_SET = _PresenceSentinel()
diff --git a/requirements.txt b/requirements.txt
index aef8b3d..e2a43e9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,3 +2,4 @@ requests>=2.23.0
 six>=1.15.0
 pytest
 delayed-assert
+enum34


Test patch:
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index a5568b2..bb6d703 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -5,7 +5,8 @@ from six.moves import mock
 from reportportal_client.helpers import (
     gen_attributes,
     get_launch_sys_attrs,
-    get_package_version
+    get_package_version,
+    verify_value_length
 )
 
 
@@ -49,3 +50,12 @@ def test_get_launch_sys_attrs_docker():
 def test_get_package_version():
     """Test for the get_package_version() function-helper."""
     assert get_package_version('noname') == 'not found'
+
+
+def test_verify_value_length():
+    """Test for validate verify_value_length() function."""
+    inputl = [{'key': 'tn', 'value': 'v' * 130}, [1, 2],
+              {'value': 'tv2'}, {'value': 300}]
+    expected = [{'key': 'tn', 'value': 'v' * 128}, [1, 2],
+                {'value': 'tv2'}, {'value': 300}]
+    assert verify_value_length(inputl) == expected