123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- import os
- import string
- import sys
- import time
- import uuid
- import json
- import socket
- import inspect
- import hashlib
- import platform
- import threading
- import traceback
- import collections
- from traceback import format_exception_only
- def md5(*args):
- m = hashlib.md5()
- for arg in args:
- if not isinstance(arg, bytes):
- if not isinstance(arg, str):
- arg = repr(arg)
- arg = arg.encode('utf-8')
- m.update(arg)
- return m.hexdigest()
- def uuid4():
- return str(uuid.uuid4())
- def now():
- return int(round(1000 * time.time()))
- def platform_label():
- major_version, *_ = platform.python_version_tuple()
- implementation = platform.python_implementation().lower()
- return f'{implementation}{major_version}'
- def thread_tag():
- return '{0}-{1}'.format(os.getpid(), threading.current_thread().name)
- def host_tag():
- return socket.gethostname()
- def represent(item):
- """
- >>> represent(None)
- 'None'
- >>> represent(123)
- '123'
- >>> represent('hi')
- "'hi'"
- >>> represent('привет')
- "'привет'"
- >>> represent(bytearray([0xd0, 0xbf])) # doctest: +ELLIPSIS
- "<... 'bytearray'>"
- >>> from struct import pack
- >>> represent(pack('h', 0x89))
- "<class 'bytes'>"
- >>> represent(int)
- "<class 'int'>"
- >>> represent(represent) # doctest: +ELLIPSIS
- '<function represent at ...>'
- >>> represent([represent]) # doctest: +ELLIPSIS
- '[<function represent at ...>]'
- >>> class ClassWithName:
- ... pass
- >>> represent(ClassWithName)
- "<class 'utils.ClassWithName'>"
- """
- if isinstance(item, str):
- return f"'{item}'"
- elif isinstance(item, (bytes, bytearray)):
- return repr(type(item))
- else:
- return repr(item)
- def func_parameters(func, *args, **kwargs):
- """
- >>> def helper(func):
- ... def wrapper(*args, **kwargs):
- ... params = func_parameters(func, *args, **kwargs)
- ... print(list(params.items()))
- ... return func(*args, **kwargs)
- ... return wrapper
- >>> @helper
- ... def args(a, b):
- ... pass
- >>> args(1, 2)
- [('a', '1'), ('b', '2')]
- >>> args(*(1,2))
- [('a', '1'), ('b', '2')]
- >>> args(1, b=2)
- [('a', '1'), ('b', '2')]
- >>> @helper
- ... def kwargs(a=1, b=2):
- ... pass
- >>> kwargs()
- [('a', '1'), ('b', '2')]
- >>> kwargs(a=3, b=4)
- [('a', '3'), ('b', '4')]
- >>> kwargs(b=4, a=3)
- [('a', '3'), ('b', '4')]
- >>> kwargs(a=3)
- [('a', '3'), ('b', '2')]
- >>> kwargs(b=4)
- [('a', '1'), ('b', '4')]
- >>> @helper
- ... def args_kwargs(a, b, c=3, d=4):
- ... pass
- >>> args_kwargs(1, 2)
- [('a', '1'), ('b', '2'), ('c', '3'), ('d', '4')]
- >>> args_kwargs(1, 2, d=5)
- [('a', '1'), ('b', '2'), ('c', '3'), ('d', '5')]
- >>> args_kwargs(1, 2, 5, 6)
- [('a', '1'), ('b', '2'), ('c', '5'), ('d', '6')]
- >>> args_kwargs(1, b=2)
- [('a', '1'), ('b', '2'), ('c', '3'), ('d', '4')]
- >>> @helper
- ... def varargs(*a):
- ... pass
- >>> varargs()
- []
- >>> varargs(1, 2)
- [('a', '(1, 2)')]
- >>> @helper
- ... def keywords(**a):
- ... pass
- >>> keywords()
- []
- >>> keywords(a=1, b=2)
- [('a', '1'), ('b', '2')]
- >>> @helper
- ... def args_varargs(a, b, *c):
- ... pass
- >>> args_varargs(1, 2)
- [('a', '1'), ('b', '2')]
- >>> args_varargs(1, 2, 2)
- [('a', '1'), ('b', '2'), ('c', '(2,)')]
- >>> @helper
- ... def args_kwargs_varargs(a, b, c=3, **d):
- ... pass
- >>> args_kwargs_varargs(1, 2)
- [('a', '1'), ('b', '2'), ('c', '3')]
- >>> args_kwargs_varargs(1, 2, 4, d=5, e=6)
- [('a', '1'), ('b', '2'), ('c', '4'), ('d', '5'), ('e', '6')]
- >>> @helper
- ... def args_kwargs_varargs_keywords(a, b=2, *c, **d):
- ... pass
- >>> args_kwargs_varargs_keywords(1)
- [('a', '1'), ('b', '2')]
- >>> args_kwargs_varargs_keywords(1, 2, 4, d=5, e=6)
- [('a', '1'), ('b', '2'), ('c', '(4,)'), ('d', '5'), ('e', '6')]
- >>> class Class:
- ... @staticmethod
- ... @helper
- ... def static_args(a, b):
- ... pass
- ...
- ... @classmethod
- ... @helper
- ... def method_args(cls, a, b):
- ... pass
- ...
- ... @helper
- ... def args(self, a, b):
- ... pass
- >>> cls = Class()
- >>> cls.args(1, 2)
- [('a', '1'), ('b', '2')]
- >>> cls.method_args(1, 2)
- [('a', '1'), ('b', '2')]
- >>> cls.static_args(1, 2)
- [('a', '1'), ('b', '2')]
- """
- parameters = {}
- arg_spec = inspect.getfullargspec(func)
- arg_order = list(arg_spec.args)
- args_dict = dict(zip(arg_spec.args, args))
- if arg_spec.defaults:
- kwargs_defaults_dict = dict(zip(arg_spec.args[-len(arg_spec.defaults):], arg_spec.defaults))
- parameters.update(kwargs_defaults_dict)
- if arg_spec.varargs:
- arg_order.append(arg_spec.varargs)
- 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']:
- args_dict.pop(arg_spec.args[0], None)
- if kwargs:
- if sys.version_info < (3, 7):
- # Sort alphabetically as old python versions does
- # not preserve call order for kwargs.
- arg_order.extend(sorted(list(kwargs.keys())))
- else:
- # Keep py3.7 behaviour to preserve kwargs order
- arg_order.extend(list(kwargs.keys()))
- parameters.update(kwargs)
- parameters.update(args_dict)
- items = parameters.items()
- sorted_items = sorted(
- map(
- lambda kv: (kv[0], represent(kv[1])),
- items
- ),
- key=lambda x: arg_order.index(x[0])
- )
- return collections.OrderedDict(sorted_items)
- def format_traceback(exc_traceback):
- return ''.join(traceback.format_tb(exc_traceback)) if exc_traceback else None
- def format_exception(etype, value):
- """
- >>> import sys
- >>> try:
- ... assert False, 'Привет'
- ... except AssertionError:
- ... etype, e, _ = sys.exc_info()
- ... format_exception(etype, e) # doctest: +ELLIPSIS
- 'AssertionError: ...\\n'
- >>> try:
- ... assert False, 'Привет'
- ... except AssertionError:
- ... etype, e, _ = sys.exc_info()
- ... format_exception(etype, e) # doctest: +ELLIPSIS
- 'AssertionError: ...\\n'
- >>> try:
- ... compile("bla 'Привет'", "fake.py", "exec")
- ... except SyntaxError:
- ... etype, e, _ = sys.exc_info()
- ... format_exception(etype, e) # doctest: +ELLIPSIS
- ' File "fake.py", line 1...SyntaxError: invalid syntax\\n'
- >>> try:
- ... compile("bla 'Привет'", "fake.py", "exec")
- ... except SyntaxError:
- ... etype, e, _ = sys.exc_info()
- ... format_exception(etype, e) # doctest: +ELLIPSIS
- ' File "fake.py", line 1...SyntaxError: invalid syntax\\n'
- >>> from hamcrest import assert_that, equal_to
- >>> try:
- ... assert_that('left', equal_to('right'))
- ... except AssertionError:
- ... etype, e, _ = sys.exc_info()
- ... format_exception(etype, e) # doctest: +ELLIPSIS
- "AssertionError: \\nExpected:...but:..."
- >>> try:
- ... assert_that('left', equal_to('right'))
- ... except AssertionError:
- ... etype, e, _ = sys.exc_info()
- ... format_exception(etype, e) # doctest: +ELLIPSIS
- "AssertionError: \\nExpected:...but:..."
- """
- return '\n'.join(format_exception_only(etype, value)) if etype or value else None
- def get_testplan():
- planned_tests = []
- 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:
- plan = json.load(plan_file)
- planned_tests = plan.get("tests", [])
- return planned_tests
- class SafeFormatter(string.Formatter):
- """
- Format string safely - skip any non-passed keys
- >>> f = SafeFormatter().format
- Make sure we don't broke default formatting behaviour
- >>> f("literal string")
- 'literal string'
- >>> f("{expected.format}", expected=str)
- "<method 'format' of 'str' objects>"
- >>> f("{expected[0]}", expected=["value"])
- 'value'
- >>> f("{expected[0]}", expected=123)
- Traceback (most recent call last):
- ...
- TypeError: 'int' object is not subscriptable
- >>> f("{expected[0]}", expected=[])
- Traceback (most recent call last):
- ...
- IndexError: list index out of range
- >>> f("{expected.format}", expected=int)
- Traceback (most recent call last):
- ...
- AttributeError: type object 'int' has no attribute 'format'
- Check that unexpected keys do not cause some errors
- >>> f("{expected} {unexpected}", expected="value")
- 'value {unexpected}'
- >>> f("{unexpected[0]}", expected=["value"])
- '{unexpected[0]}'
- >>> f("{unexpected.format}", expected=str)
- '{unexpected.format}'
- """
- class SafeKeyOrIndexError(Exception):
- pass
- def get_field(self, field_name, args, kwargs):
- try:
- return super().get_field(field_name, args, kwargs)
- except self.SafeKeyOrIndexError:
- return "{" + field_name + "}", field_name
- def get_value(self, key, args, kwargs):
- try:
- return super().get_value(key, args, kwargs)
- except (KeyError, IndexError):
- raise self.SafeKeyOrIndexError()
|