# Copyright 2019 Ram Rachum and collaborators. # This program is distributed under the MIT license. import os import re import abc import inspect import sys from pysnooper.utils import DEFAULT_REPR_RE try: from itertools import zip_longest except ImportError: from itertools import izip_longest as zip_longest from . import mini_toolbox import pysnooper.pycompat def get_function_arguments(function, exclude=()): try: getfullargspec = inspect.getfullargspec except AttributeError: result = inspect.getargspec(function).args else: result = getfullargspec(function).args for exclude_item in exclude: result.remove(exclude_item) return result class _BaseEntry(pysnooper.pycompat.ABC): def __init__(self, prefix='', min_python_version=None, max_python_version=None): self.prefix = prefix self.min_python_version = min_python_version self.max_python_version = max_python_version @abc.abstractmethod def check(self, s): pass def is_compatible_with_current_python_version(self): compatible = True if self.min_python_version and self.min_python_version > sys.version_info: compatible = False if self.max_python_version and self.max_python_version < sys.version_info: compatible = False return compatible def __repr__(self): init_arguments = get_function_arguments(self.__init__, exclude=('self',)) attributes = { key: repr(getattr(self, key)) for key in init_arguments if getattr(self, key) is not None } return '%s(%s)' % ( type(self).__name__, ', '.join('{key}={value}'.format(**locals()) for key, value in attributes.items()) ) class _BaseValueEntry(_BaseEntry): def __init__(self, prefix='', min_python_version=None, max_python_version=None): _BaseEntry.__init__(self, prefix=prefix, min_python_version=min_python_version, max_python_version=max_python_version) self.line_pattern = re.compile( r"""^%s(?P(?: {4})*)(?P[^:]*):""" r"""\.{2,7} (?P.*)$""" % (re.escape(self.prefix),) ) @abc.abstractmethod def _check_preamble(self, preamble): pass @abc.abstractmethod def _check_content(self, preamble): pass def check(self, s): match = self.line_pattern.match(s) if not match: return False _, preamble, content = match.groups() return (self._check_preamble(preamble) and self._check_content(content)) class ElapsedTimeEntry(_BaseEntry): def __init__(self, elapsed_time_value=None, tolerance=0.2, prefix='', min_python_version=None, max_python_version=None): _BaseEntry.__init__(self, prefix=prefix, min_python_version=min_python_version, max_python_version=max_python_version) self.line_pattern = re.compile( r"""^%s(?P(?: {4})*)Elapsed time: (?P