summaryrefslogtreecommitdiffstats
path: root/contrib/python/allure-python-commons/allure_commons
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2026-05-13 08:51:44 +0300
committerrobot-piglet <[email protected]>2026-05-13 09:43:18 +0300
commit21b994f3cab88fade95b9dabe9b1b491627b822d (patch)
treee27d9725b1f4f23d6e137c5c115715c1070600df /contrib/python/allure-python-commons/allure_commons
parent2e7284b4e24ef8749490a6bb96e6edb645520af1 (diff)
Intermediate changes
commit_hash:9dd0a391400eb50723299039cdf1b64398309ddd
Diffstat (limited to 'contrib/python/allure-python-commons/allure_commons')
-rw-r--r--contrib/python/allure-python-commons/allure_commons/__init__.py16
-rw-r--r--contrib/python/allure-python-commons/allure_commons/_allure.py45
-rw-r--r--contrib/python/allure-python-commons/allure_commons/_core.py2
-rw-r--r--contrib/python/allure-python-commons/allure_commons/_hooks.py16
-rw-r--r--contrib/python/allure-python-commons/allure_commons/lifecycle.py52
-rw-r--r--contrib/python/allure-python-commons/allure_commons/logger.py16
-rw-r--r--contrib/python/allure-python-commons/allure_commons/mapping.py4
-rw-r--r--contrib/python/allure-python-commons/allure_commons/model2.py37
-rw-r--r--contrib/python/allure-python-commons/allure_commons/reporter.py40
-rw-r--r--contrib/python/allure-python-commons/allure_commons/types.py50
-rw-r--r--contrib/python/allure-python-commons/allure_commons/utils.py14
11 files changed, 220 insertions, 72 deletions
diff --git a/contrib/python/allure-python-commons/allure_commons/__init__.py b/contrib/python/allure-python-commons/allure_commons/__init__.py
index 111c2d06c28..e480aceab69 100644
--- a/contrib/python/allure-python-commons/allure_commons/__init__.py
+++ b/contrib/python/allure-python-commons/allure_commons/__init__.py
@@ -1,12 +1,12 @@
-from allure_commons._hooks import hookimpl # noqa: F401
-from allure_commons._core import plugin_manager # noqa: F401
-from allure_commons._allure import fixture # noqa: F401
-from allure_commons._allure import test # noqa: F401
+from allure_commons._hooks import hookimpl
+from allure_commons._core import plugin_manager
+from allure_commons._allure import fixture
+from allure_commons._allure import test
__all__ = [
- 'hookimpl',
- 'plugin_manager',
- 'fixture',
- 'test'
+ "hookimpl",
+ "plugin_manager",
+ "fixture",
+ "test"
]
diff --git a/contrib/python/allure-python-commons/allure_commons/_allure.py b/contrib/python/allure-python-commons/allure_commons/_allure.py
index b7bbe2a5e07..607e1cb873b 100644
--- a/contrib/python/allure-python-commons/allure_commons/_allure.py
+++ b/contrib/python/allure-python-commons/allure_commons/_allure.py
@@ -4,6 +4,7 @@ from typing import Any, Callable, TypeVar, Union, overload
from allure_commons._core import plugin_manager
from allure_commons.types import LabelType, LinkType, ParameterMode
from allure_commons.utils import uuid4
+from allure_commons.utils import format_exception, format_traceback
from allure_commons.utils import func_parameters, represent
_TFunc = TypeVar("_TFunc", bound=Callable[..., Any])
@@ -125,7 +126,7 @@ class Dynamic:
Dynamic.label(LabelType.TAG, *tags)
@staticmethod
- def id(id): # noqa: A003,A002
+ def id(id): # noqa: A002
Dynamic.label(LabelType.ID, id)
@staticmethod
@@ -216,6 +217,48 @@ class Attach:
attach = Attach()
+class GlobalAttach:
+
+ def __call__(self, body, name=None, attachment_type=None, extension=None):
+ plugin_manager.hook.global_attach_data(
+ body=body,
+ name=name,
+ attachment_type=attachment_type,
+ extension=extension,
+ )
+
+ def file(self, source, name=None, attachment_type=None, extension=None):
+ plugin_manager.hook.global_attach_file(
+ source=source,
+ name=name,
+ attachment_type=attachment_type,
+ extension=extension,
+ )
+
+
+global_attach = GlobalAttach()
+
+
+@overload
+def global_error(value: BaseException) -> None:
+ ...
+
+
+@overload
+def global_error(value: str, trace: Union[str, None] = None) -> None:
+ ...
+
+
+def global_error(value, trace=None):
+ message = None
+ if isinstance(value, BaseException):
+ message = format_exception(type(value), value)
+ trace = format_traceback(value.__traceback__)
+ else:
+ message = value
+ plugin_manager.hook.global_error(message=message, trace=trace)
+
+
class fixture:
def __init__(self, fixture_function, parent_uuid=None, name=None):
self._fixture_function = fixture_function
diff --git a/contrib/python/allure-python-commons/allure_commons/_core.py b/contrib/python/allure-python-commons/allure_commons/_core.py
index 40d9deafb78..8687891cf75 100644
--- a/contrib/python/allure-python-commons/allure_commons/_core.py
+++ b/contrib/python/allure-python-commons/allure_commons/_core.py
@@ -8,7 +8,7 @@ class MetaPluginManager(type):
@staticmethod
def get_plugin_manager():
if not MetaPluginManager._plugin_manager:
- MetaPluginManager._plugin_manager = PluginManager('allure')
+ MetaPluginManager._plugin_manager = PluginManager("allure")
MetaPluginManager._plugin_manager.add_hookspecs(_hooks.AllureUserHooks)
MetaPluginManager._plugin_manager.add_hookspecs(_hooks.AllureDeveloperHooks)
diff --git a/contrib/python/allure-python-commons/allure_commons/_hooks.py b/contrib/python/allure-python-commons/allure_commons/_hooks.py
index 0ff19a27d3a..84e916d900b 100644
--- a/contrib/python/allure-python-commons/allure_commons/_hooks.py
+++ b/contrib/python/allure-python-commons/allure_commons/_hooks.py
@@ -66,6 +66,18 @@ class AllureUserHooks:
def attach_file(self, source, name, attachment_type, extension):
""" attach file """
+ @hookspec
+ def global_attach_data(self, body, name, attachment_type, extension):
+ """ attach global data """
+
+ @hookspec
+ def global_attach_file(self, source, name, attachment_type, extension):
+ """ attach global file """
+
+ @hookspec
+ def global_error(self, message, trace):
+ """ global error """
+
class AllureDeveloperHooks:
@@ -100,3 +112,7 @@ class AllureDeveloperHooks:
@hookspec
def report_attached_data(self, body, file_name):
""" reporting """
+
+ @hookspec
+ def report_globals(self, globals_item):
+ """ reporting """
diff --git a/contrib/python/allure-python-commons/allure_commons/lifecycle.py b/contrib/python/allure-python-commons/allure_commons/lifecycle.py
index 2e730e2e433..e2c2251ebcf 100644
--- a/contrib/python/allure-python-commons/allure_commons/lifecycle.py
+++ b/contrib/python/allure-python-commons/allure_commons/lifecycle.py
@@ -4,6 +4,7 @@ from allure_commons._core import plugin_manager
from allure_commons.model2 import TestResultContainer
from allure_commons.model2 import TestResult
from allure_commons.model2 import Attachment, ATTACHMENT_PATTERN
+from allure_commons.model2 import GlobalAttachment, GlobalError, Globals
from allure_commons.model2 import TestStepResult
from allure_commons.model2 import ExecutableItem
from allure_commons.model2 import TestBeforeResult
@@ -124,14 +125,11 @@ class AllureLifecycle:
fixture.stop = now()
def _attach(self, uuid, name=None, attachment_type=None, extension=None, parent_uuid=None):
- mime_type = attachment_type
- extension = extension if extension else 'attach'
-
- if type(attachment_type) is AttachmentType:
- extension = attachment_type.extension
- mime_type = attachment_type.mime_type
-
- file_name = ATTACHMENT_PATTERN.format(prefix=uuid, ext=extension)
+ file_name, mime_type = self.__resolve_attachment_filename_and_type(
+ uuid,
+ attachment_type=attachment_type,
+ extension=extension,
+ )
attachment = Attachment(source=file_name, name=name, type=mime_type)
last_uuid = parent_uuid if parent_uuid else self._last_item_uuid(ExecutableItem)
self._items[last_uuid].attachments.append(attachment)
@@ -147,3 +145,41 @@ class AllureLifecycle:
file_name = self._attach(uuid, name=name, attachment_type=attachment_type,
extension=extension, parent_uuid=parent_uuid)
plugin_manager.hook.report_attached_data(body=body, file_name=file_name)
+
+ def global_attach_file(self, uuid, source, name=None, attachment_type=None, extension=None):
+ file_name, mime_type = self.__resolve_attachment_filename_and_type(
+ uuid,
+ attachment_type=attachment_type,
+ extension=extension,
+ )
+ plugin_manager.hook.report_attached_file(source=source, file_name=file_name)
+ plugin_manager.hook.report_globals(globals_item=Globals(attachments=[
+ GlobalAttachment(source=file_name, name=name, type=mime_type, timestamp=now())
+ ]))
+
+ def global_attach_data(self, uuid, body, name=None, attachment_type=None, extension=None):
+ file_name, mime_type = self.__resolve_attachment_filename_and_type(
+ uuid,
+ attachment_type=attachment_type,
+ extension=extension,
+ )
+ plugin_manager.hook.report_attached_data(body=body, file_name=file_name)
+ plugin_manager.hook.report_globals(globals_item=Globals(attachments=[
+ GlobalAttachment(source=file_name, name=name, type=mime_type, timestamp=now())
+ ]))
+
+ def global_error(self, message=None, trace=None):
+ plugin_manager.hook.report_globals(globals_item=Globals(errors=[
+ GlobalError(message=message, trace=trace, timestamp=now())
+ ]))
+
+ def __resolve_attachment_filename_and_type(self, uuid, attachment_type=None, extension=None):
+ mime_type = attachment_type
+ extension = extension if extension else "attach"
+
+ if type(attachment_type) is AttachmentType:
+ extension = attachment_type.extension
+ mime_type = attachment_type.mime_type
+
+ file_name = ATTACHMENT_PATTERN.format(prefix=uuid, ext=extension)
+ return file_name, mime_type
diff --git a/contrib/python/allure-python-commons/allure_commons/logger.py b/contrib/python/allure-python-commons/allure_commons/logger.py
index 55f956f2507..4345bc77db0 100644
--- a/contrib/python/allure-python-commons/allure_commons/logger.py
+++ b/contrib/python/allure-python-commons/allure_commons/logger.py
@@ -22,7 +22,7 @@ class AllureFileLogger:
indent = INDENT if os.environ.get("ALLURE_INDENT_OUTPUT") else None
filename = item.file_pattern.format(prefix=uuid.uuid4())
data = asdict(item, filter=lambda _, v: v or v is False)
- with io.open(self._report_dir / filename, 'w', encoding='utf8') as json_file:
+ with io.open(self._report_dir / filename, "w", encoding="utf8") as json_file:
json.dump(data, json_file, indent=indent, ensure_ascii=False)
@hookimpl
@@ -41,12 +41,16 @@ class AllureFileLogger:
@hookimpl
def report_attached_data(self, body, file_name):
destination = self._report_dir / file_name
- with open(destination, 'wb') as attached_file:
+ with open(destination, "wb") as attached_file:
if isinstance(body, str):
- attached_file.write(body.encode('utf-8'))
+ attached_file.write(body.encode("utf-8"))
else:
attached_file.write(body)
+ @hookimpl
+ def report_globals(self, globals_item):
+ self._report_item(globals_item)
+
class AllureMemoryLogger:
@@ -54,6 +58,7 @@ class AllureMemoryLogger:
self.test_cases = []
self.test_containers = []
self.attachments = {}
+ self.globals = []
@hookimpl
def report_result(self, result):
@@ -72,3 +77,8 @@ class AllureMemoryLogger:
@hookimpl
def report_attached_data(self, body, file_name):
self.attachments[file_name] = body
+
+ @hookimpl
+ def report_globals(self, globals_item):
+ data = asdict(globals_item, filter=lambda _, v: v or v is False)
+ self.globals.append(data)
diff --git a/contrib/python/allure-python-commons/allure_commons/mapping.py b/contrib/python/allure-python-commons/allure_commons/mapping.py
index 737d3390a46..0cd099f0c3b 100644
--- a/contrib/python/allure-python-commons/allure_commons/mapping.py
+++ b/contrib/python/allure-python-commons/allure_commons/mapping.py
@@ -20,7 +20,7 @@ def allure_tag_sep(tag):
def __is(kind, t):
- return kind in [v for k, v in t.__dict__.items() if not k.startswith('__')]
+ return kind in [v for k, v in t.__dict__.items() if not k.startswith("__")]
def parse_tag(tag, issue_pattern=None, link_pattern=None):
@@ -51,7 +51,7 @@ def parse_tag(tag, issue_pattern=None, link_pattern=None):
"""
sep = allure_tag_sep(tag)
schema, value = islice(chain(tag.split(sep, 1), [None]), 2)
- prefix, kind, name = islice(chain(schema.split('.'), [None], [None]), 3)
+ prefix, kind, name = islice(chain(schema.split("."), [None], [None]), 3)
if tag in [severity for severity in Severity]:
return Label(name=LabelType.SEVERITY, value=tag)
diff --git a/contrib/python/allure-python-commons/allure_commons/model2.py b/contrib/python/allure-python-commons/allure_commons/model2.py
index d8591598533..cd069b176fd 100644
--- a/contrib/python/allure-python-commons/allure_commons/model2.py
+++ b/contrib/python/allure-python-commons/allure_commons/model2.py
@@ -4,7 +4,8 @@ from attr import Factory
TEST_GROUP_PATTERN = "{prefix}-container.json"
TEST_CASE_PATTERN = "{prefix}-result.json"
-ATTACHMENT_PATTERN = '{prefix}-attachment.{ext}'
+ATTACHMENT_PATTERN = "{prefix}-attachment.{ext}"
+GLOBALS_PATTERN = "{prefix}-globals.json"
INDENT = 4
@@ -54,7 +55,7 @@ class TestResult(ExecutableItem):
@attrs
class TestStepResult(ExecutableItem):
- id = attrib(default=None) # noqa: A003
+ id = attrib(default=None)
@attrs
@@ -83,7 +84,7 @@ class Label:
@attrs
class Link:
- type = attrib(default=None) # noqa: A003
+ type = attrib(default=None)
url = attrib(default=None)
name = attrib(default=None)
@@ -100,12 +101,30 @@ class StatusDetails:
class Attachment:
name = attrib(default=None)
source = attrib(default=None)
- type = attrib(default=None) # noqa: A003
+ type = attrib(default=None)
+
+
+@attrs
+class GlobalAttachment(Attachment):
+ timestamp = attrib(default=None)
+
+
+@attrs
+class GlobalError(StatusDetails):
+ timestamp = attrib(default=None)
+
+
+@attrs
+class Globals:
+ file_pattern = GLOBALS_PATTERN
+
+ attachments = attrib(default=Factory(list))
+ errors = attrib(default=Factory(list))
class Status:
- FAILED = 'failed'
- BROKEN = 'broken'
- PASSED = 'passed'
- SKIPPED = 'skipped'
- UNKNOWN = 'unknown'
+ FAILED = "failed"
+ BROKEN = "broken"
+ PASSED = "passed"
+ SKIPPED = "skipped"
+ UNKNOWN = "unknown"
diff --git a/contrib/python/allure-python-commons/allure_commons/reporter.py b/contrib/python/allure-python-commons/allure_commons/reporter.py
index 2e1f4a89d3a..7e7b7594e77 100644
--- a/contrib/python/allure-python-commons/allure_commons/reporter.py
+++ b/contrib/python/allure-python-commons/allure_commons/reporter.py
@@ -5,6 +5,7 @@ from allure_commons.types import AttachmentType
from allure_commons.model2 import ExecutableItem
from allure_commons.model2 import TestResult
from allure_commons.model2 import Attachment, ATTACHMENT_PATTERN
+from allure_commons.model2 import GlobalAttachment, GlobalError, Globals
from allure_commons.utils import now
from allure_commons._core import plugin_manager
@@ -140,14 +141,7 @@ class AllureReporter:
self._items.pop(uuid)
def _attach(self, uuid, name=None, attachment_type=None, extension=None, parent_uuid=None):
- mime_type = attachment_type
- extension = extension if extension else 'attach'
-
- if type(attachment_type) is AttachmentType:
- extension = attachment_type.extension
- mime_type = attachment_type.mime_type
-
- file_name = ATTACHMENT_PATTERN.format(prefix=uuid, ext=extension)
+ file_name, mime_type = self.__resolve_attachment_filename_and_type(uuid, attachment_type, extension)
attachment = Attachment(source=file_name, name=name, type=mime_type)
last_uuid = parent_uuid if parent_uuid else self._last_executable()
self._items[last_uuid].attachments.append(attachment)
@@ -163,3 +157,33 @@ class AllureReporter:
file_name = self._attach(uuid, name=name, attachment_type=attachment_type,
extension=extension, parent_uuid=parent_uuid)
plugin_manager.hook.report_attached_data(body=body, file_name=file_name)
+
+ def global_attach_file(self, uuid, source, name=None, attachment_type=None, extension=None):
+ file_name, mime_type = self.__resolve_attachment_filename_and_type(uuid, attachment_type, extension)
+ plugin_manager.hook.report_attached_file(source=source, file_name=file_name)
+ plugin_manager.hook.report_globals(globals_item=Globals(attachments=[
+ GlobalAttachment(source=file_name, name=name, type=mime_type, timestamp=now())
+ ]))
+
+ def global_attach_data(self, uuid, body, name=None, attachment_type=None, extension=None):
+ file_name, mime_type = self.__resolve_attachment_filename_and_type(uuid, attachment_type, extension)
+ plugin_manager.hook.report_attached_data(body=body, file_name=file_name)
+ plugin_manager.hook.report_globals(globals_item=Globals(attachments=[
+ GlobalAttachment(source=file_name, name=name, type=mime_type, timestamp=now())
+ ]))
+
+ def global_error(self, message=None, trace=None):
+ plugin_manager.hook.report_globals(globals_item=Globals(errors=[
+ GlobalError(message=message, trace=trace, timestamp=now())
+ ]))
+
+ def __resolve_attachment_filename_and_type(self, uuid, attachment_type=None, extension=None):
+ mime_type = attachment_type
+ extension = extension if extension else "attach"
+
+ if type(attachment_type) is AttachmentType:
+ extension = attachment_type.extension
+ mime_type = attachment_type.mime_type
+
+ file_name = ATTACHMENT_PATTERN.format(prefix=uuid, ext=extension)
+ return file_name, mime_type
diff --git a/contrib/python/allure-python-commons/allure_commons/types.py b/contrib/python/allure-python-commons/allure_commons/types.py
index 1db7fd512f7..43b8d5edfda 100644
--- a/contrib/python/allure-python-commons/allure_commons/types.py
+++ b/contrib/python/allure-python-commons/allure_commons/types.py
@@ -1,37 +1,37 @@
from enum import Enum
-ALLURE_UNIQUE_LABELS = ['severity', 'thread', 'host']
+ALLURE_UNIQUE_LABELS = ["severity", "thread", "host"]
class Severity(str, Enum):
- BLOCKER = 'blocker'
- CRITICAL = 'critical'
- NORMAL = 'normal'
- MINOR = 'minor'
- TRIVIAL = 'trivial'
+ BLOCKER = "blocker"
+ CRITICAL = "critical"
+ NORMAL = "normal"
+ MINOR = "minor"
+ TRIVIAL = "trivial"
class LinkType:
- LINK = 'link'
- ISSUE = 'issue'
- TEST_CASE = 'tms'
+ LINK = "link"
+ ISSUE = "issue"
+ TEST_CASE = "tms"
class LabelType(str):
- EPIC = 'epic'
- FEATURE = 'feature'
- STORY = 'story'
- PARENT_SUITE = 'parentSuite'
- SUITE = 'suite'
- SUB_SUITE = 'subSuite'
- SEVERITY = 'severity'
- THREAD = 'thread'
- HOST = 'host'
- TAG = 'tag'
- ID = 'as_id'
- FRAMEWORK = 'framework'
- LANGUAGE = 'language'
- MANUAL = 'ALLURE_MANUAL'
+ EPIC = "epic"
+ FEATURE = "feature"
+ STORY = "story"
+ PARENT_SUITE = "parentSuite"
+ SUITE = "suite"
+ SUB_SUITE = "subSuite"
+ SEVERITY = "severity"
+ THREAD = "thread"
+ HOST = "host"
+ TAG = "tag"
+ ID = "as_id"
+ FRAMEWORK = "framework"
+ LANGUAGE = "language"
+ MANUAL = "ALLURE_MANUAL"
class AttachmentType(Enum):
@@ -67,6 +67,6 @@ class AttachmentType(Enum):
class ParameterMode(Enum):
- HIDDEN = 'hidden'
- MASKED = 'masked'
+ HIDDEN = "hidden"
+ MASKED = "masked"
DEFAULT = None
diff --git a/contrib/python/allure-python-commons/allure_commons/utils.py b/contrib/python/allure-python-commons/allure_commons/utils.py
index 5ba0d3775b7..c50cb7ecbd3 100644
--- a/contrib/python/allure-python-commons/allure_commons/utils.py
+++ b/contrib/python/allure-python-commons/allure_commons/utils.py
@@ -21,7 +21,7 @@ def md5(*args):
if not isinstance(arg, bytes):
if not isinstance(arg, str):
arg = repr(arg)
- arg = arg.encode('utf-8')
+ arg = arg.encode("utf-8")
m.update(arg)
return m.hexdigest()
@@ -37,11 +37,11 @@ def now():
def platform_label():
major_version, *_ = platform.python_version_tuple()
implementation = platform.python_implementation().lower()
- return f'{implementation}{major_version}'
+ return f"{implementation}{major_version}"
def thread_tag():
- return '{0}-{1}'.format(os.getpid(), threading.current_thread().name)
+ return "{0}-{1}".format(os.getpid(), threading.current_thread().name)
def host_tag():
@@ -241,7 +241,7 @@ def func_parameters(func, *args, **kwargs):
varargs = args[len(arg_spec.args):]
parameters.update({arg_spec.varargs: varargs} if varargs else {})
- if arg_spec.args and arg_spec.args[0] in ['cls', 'self']:
+ if arg_spec.args and arg_spec.args[0] in ["cls", "self"]:
args_dict.pop(arg_spec.args[0], None)
if kwargs:
@@ -269,7 +269,7 @@ def func_parameters(func, *args, **kwargs):
def format_traceback(exc_traceback):
- return ''.join(traceback.format_tb(exc_traceback)) if exc_traceback else None
+ return "".join(traceback.format_tb(exc_traceback)) if exc_traceback else None
def format_exception(etype, value):
@@ -320,7 +320,7 @@ def format_exception(etype, value):
... format_exception(etype, e) # doctest: +ELLIPSIS
"AssertionError: \\nExpected:...but:..."
"""
- return '\n'.join(format_exception_only(etype, value)) if etype or value else None
+ return "\n".join(format_exception_only(etype, value)) if etype or value else None
def get_testplan():
@@ -328,7 +328,7 @@ def get_testplan():
file_path = os.environ.get("ALLURE_TESTPLAN_PATH")
if file_path and os.path.exists(file_path):
- with open(file_path, 'r') as plan_file:
+ with open(file_path, "r") as plan_file:
plan = json.load(plan_file)
planned_tests = plan.get("tests", [])