コード例 #1
0
def _to_string_refrection(value: object,
                          print_options: _PrintOptions) -> LogBuffer:
    '''
    Returns a LogBuffer containing a string representation of the value with reflection.

    Args:
        value (bytes): The value to append
        print_options (_PrintOptions): Output options 

    Returns:
        LogBuffer: a LogBuffer
    '''
    buff = LogBuffer(_maximum_data_output_width)

    buff.append(_get_type_name(value))

    body_buff = _to_string_refrection_body(value, print_options)

    is_multi_lines = body_buff.is_multi_lines or buff.length + body_buff.length > _maximum_data_output_width

    buff.no_break_append('{')
    if is_multi_lines:
        buff.line_feed()
        buff.up_nest()

    buff.append_buffer(None, body_buff)

    if is_multi_lines:
        if buff.length > 0:
            buff.line_feed()
        buff.down_nest()
    buff.no_break_append('}')

    return buff
コード例 #2
0
def _to_string_iterable(values: object,
                        print_options: _PrintOptions) -> LogBuffer:
    '''
    Returns a LogBuffer containing a string representation of the iterable value.

    Args:
        value (object): The iterable value to append
        print_options (_PrintOptions): Output options 

    Returns:
        LogBuffer: a LogBuffer
    '''
    open_char = '{'  # set, frozenset, dict
    close_char = '}'
    if isinstance(values, list):
        # list
        open_char = '['
        close_char = ']'
    elif isinstance(values, tuple):
        # tuple
        open_char = '('
        close_char = ')'

    buff = LogBuffer(_maximum_data_output_width)
    buff.append(_get_type_name(values, len(values)))
    buff.no_break_append(open_char)

    body_buff = _to_string_iterable_body(values, print_options)
    # 1.1.0
    if open_char == '(' and len(values) == 1:
        # A tuple with 1 element
        body_buff.no_break_append(',')


####

    is_multi_lines = body_buff.is_multi_lines or buff.length + body_buff.length > _maximum_data_output_width

    if is_multi_lines:
        buff.line_feed()
        buff.up_nest()

    buff.append_buffer(None, body_buff)

    if is_multi_lines:
        buff.line_feed()
        buff.down_nest()

    buff.no_break_append(close_char)

    return buff
コード例 #3
0
def _to_string_refrection_body(value: object,
                               print_options: _PrintOptions) -> LogBuffer:
    '''
    Returns a LogBuffer containing the body of a string representation of the value with reflection.

    Args:
        value (bytes): The value to append
        print_options (_PrintOptions): Output options 

    Returns:
        LogBuffer: a LogBuffer
    '''
    buff = LogBuffer(_maximum_data_output_width)

    members = []
    try:
        base_members = inspect.getmembers(
            value, lambda v: not inspect.isclass(v) and
            (print_options.output_method or not inspect.ismethod(v)
             ) and not inspect.isbuiltin(v))

        members = [
            m for m in base_members
            if (not m[0].startswith('__') or not m[0].endswith('__')) and (
                print_options.output_private or not m[0].startswith('_'))
        ]
    except BaseException as ex:
        buff.append(str(ex))
        return buff

    was_multi_lines = False
    index = 0
    for member in members:
        if index > 0:
            buff.no_break_append(', ')

        name = member[0]
        value = member[1]
        member_buff = LogBuffer(_maximum_data_output_width)
        member_buff.append(name)
        member_buff.append_buffer(_key_value_separator,
                                  _to_string(None, value, print_options))
        if index > 0 and (was_multi_lines or member_buff.is_multi_lines):
            buff.line_feed()
        buff.append_buffer(None, member_buff)

        was_multi_lines = member_buff.is_multi_lines
        index += 1

    return buff
コード例 #4
0
def _to_string_iterable_body(values: object,
                             print_options: _PrintOptions) -> LogBuffer:
    '''
    Returns a LogBuffer containing the body of a string representation of the iterable value.

    Args:
        value (object): The iterable value to append
        print_options (_PrintOptions): Output options 

    Returns:
        LogBuffer: a LogBuffer
    '''
    buff = LogBuffer(_maximum_data_output_width)

    was_multi_lines = False
    index = 0
    for element in values:
        if index > 0:
            buff.no_break_append(', ')

        if index >= print_options.collection_limit:
            buff.append(_limit_string)
            break

        element_buff = LogBuffer(_maximum_data_output_width)
        if isinstance(values, dict):
            # dictionary
            element_buff = _to_string_key_value(element, values[element],
                                                print_options)
        else:
            # list, set, frozenset or tuple
            element_buff = _to_string(None, element, print_options)

        if index > 0 and (was_multi_lines or element_buff.is_multi_lines):
            buff.line_feed()
        buff.append_buffer(None, element_buff)

        was_multi_lines = element_buff.is_multi_lines
        index += 1

# 1.1.0
    if isinstance(values, dict) and len(values) == 0:
        buff.no_break_append(':')


####

    return buff
コード例 #5
0
    def __del__(self):
        '''
        Called when the instance is about to be destroyed.
        '''
        global _last_print_buff

        if not _is_enabled: return

        time = datetime.datetime.now() - self.enter_time

        if _last_print_buff.is_multi_lines:
            _logger.print(_get_indent_string())  # Empty Line

        _down_nest()

        _last_print_buff = LogBuffer(_maximum_data_output_width)
        _last_print_buff.no_break_append(
            _leave_format.format(self.name, self.filename, self.lineno, time))
        _last_print_buff.line_feed()
        _logger.print(_get_indent_string() + _last_print_buff.lines[0][1])
コード例 #6
0
    def __init__(self, invoker: object) -> None:
        '''
        Initializes this object.

        Args:
            invoker (object): The object or class that invoked this method.
        '''
        global _nest_level
        global _previous_nest_level
        global _last_print_buff

        if not _is_enabled: return

        if invoker is None:
            self.name = ''
        else:
            self.name = type(invoker).__name__
            if self.name == 'type':
                self.name = invoker.__name__
            self.name += '.'

        frame_summary = _get_frame_summary(4)
        self.name += frame_summary.name
        self.filename = os.path.basename(frame_summary.filename)
        self.lineno = frame_summary.lineno

        indent_string = _get_indent_string()
        if _nest_level < _previous_nest_level or _last_print_buff.is_multi_lines:
            _logger.print(indent_string)  # Empty Line

        _last_print_buff = LogBuffer(_maximum_data_output_width)
        _last_print_buff.no_break_append(
            _enter_format.format(self.name, self.filename, self.lineno))
        _last_print_buff.line_feed()
        _logger.print(indent_string + _last_print_buff.lines[0][1])

        _up_nest()

        self.enter_time = datetime.datetime.now()
コード例 #7
0
def print(name: str,
          value: object = _DO_NOT_OUTPUT,
          *,
          force_reflection: bool = False,
          output_private: bool = False,
          output_method: bool = False,
          collection_limit: int = None,
          string_limit: int = None,
          bytes_limit: int = None,
          reflection_nest_limit: int = None) -> None:
    '''
    Outputs the name and value.

    Args:
        name (str): The name of the value (simply output message if the value is omitted).
        value (object, optional): The value to output if not omitted.
        force_reflection (bool, optional): If true, outputs using reflection even if it has a __str__ or __repr__ method. Defaults to None
        output_private (bool, optional): If true, also outputs private members when using reflection. Defaults to None
        output_method (bool, optional): If true, also outputs method members when using reflection. Defaults to None
        collection_limit (int, optional): Output limit of collection elements (overrides debugtarace.ini value). Defaults to None
        string_limit (int, optional): Output limit of string characters (overrides debugtarace.ini value). Defaults to None
        bytes_limit (int, optional): Output limit of byte array elements (overrides debugtarace.ini value). Defaults to None
        reflection_nest_limit (int, optional): Nest limits when using reflection (overrides debugtarace.ini value). Defaults to None

    The following is in Japanese.
    
    名前と値を出力します。

    引数:
        name (str): 出力する名前 (valueが省略されている場合は、単に出力するメッセージ)
        value (object, optional): 出力する値 (省略されていなければ)
        force_reflection (bool, optional): Trueなら __str__ または __repr__ メソッドが定義されていてもリフレクションを使用する。デフォルトは指定なし
        output_private (bool, optional): Trueならプライベートメンバーも出力する。デフォルトは指定なし
        output_method (bool, optional): Trueならメソッドも出力する。デフォルトは指定なし
        collection_limit (int, optional): コレクションの要素の出力数の制限 (debugtarace.iniの値より優先)。デフォルトは指定なし
        string_limit (int, optional): 文字列値の出力文字数の制限 (debugtarace.iniの値より優先)。デフォルトは指定なし
        bytes_limit (int, optional): バイト配列bytesの内容の出力数の制限 (debugtarace.iniの値より優先)。デフォルトは指定なし
        reflection_nest_limit (int, optional): リフレクションのネスト数の制限 (debugtarace.iniの値より優先)。デフォルトは指定なし
    '''
    global _last_print_buff
    global _reflected_objects

    if not _is_enabled: return

    _reflected_objects.clear()

    last_is_multi_lines = _last_print_buff.is_multi_lines

    if value is _DO_NOT_OUTPUT:
        # without value
        _last_print_buff = LogBuffer(_maximum_data_output_width)
        _last_print_buff.no_break_append(name)

    else:
        # with value
        print_options = _PrintOptions(force_reflection, output_private,
                                      output_method, collection_limit,
                                      string_limit, bytes_limit,
                                      reflection_nest_limit)

        _last_print_buff = _to_string(name, value, print_options)

    # append print suffix
    frame_summary = _get_frame_summary(3)
    _last_print_buff.no_break_append(
        _print_suffix_format.format(frame_summary.name,
                                    os.path.basename(frame_summary.filename),
                                    frame_summary.lineno))

    _last_print_buff.line_feed()

    if last_is_multi_lines or _last_print_buff.is_multi_lines:
        _logger.print(_get_indent_string())  # Empty Line

    lines = _last_print_buff.lines
    for line in lines:
        _logger.print(_get_indent_string(line[0]) + line[1])
コード例 #8
0
def _to_string_bytes(value: bytes, print_options: _PrintOptions) -> LogBuffer:
    '''
    Returns a LogBuffer containing a string representation of the bytes value.

    Args:
        value (bytes): The bytes value
        print_options (_PrintOptions): Output options 

    Returns:
        LogBuffer: a LogBuffer
    '''
    bytes_length = len(value)
    buff = LogBuffer(_maximum_data_output_width)
    buff.no_break_append('(')
    if type(value) == bytes:
        buff.no_break_append('bytes')
    elif type(value) == bytearray:
        buff.no_break_append('bytearray')
    if bytes_length >= _minimum_output_length:
        buff.no_break_append(' ')
        buff.no_break_append(_length_format.format(bytes_length))
    buff.no_break_append(')[')

    is_multi_lines = bytes_length >= _bytes_count_in_line

    if is_multi_lines:
        buff.line_feed()
        buff.up_nest()

    chars = ''
    count = 0
    for element in value:
        if count != 0 and count % _bytes_count_in_line == 0:
            if is_multi_lines:
                buff.no_break_append('| ')
                buff.no_break_append(chars)
                buff.line_feed()
                chars = ''
        if (count >= print_options.bytes_limit):
            buff.no_break_append(_limit_string)
            break
        buff.no_break_append('{:02X} '.format(element))
        chars += chr(element) if element >= 0x20 and element <= 0x7E else '.'
        count += 1

    if is_multi_lines:
        # padding
        full_length = 3 * _bytes_count_in_line
        current_length = buff.length
        if current_length == 0:
            current_length = full_length
        buff.no_break_append(' ' * (full_length - current_length))
    buff.no_break_append('| ')
    buff.no_break_append(chars)

    if is_multi_lines:
        buff.line_feed()
        buff.down_nest()
    buff.no_break_append(']')

    return buff
コード例 #9
0
def _to_string_str(value: str, print_options: _PrintOptions) -> LogBuffer:
    '''
    Returns a LogBuffer containing a string representation of the string value.

    Args:
        value (str): The string value
        print_options (_PrintOptions): Output options 

    Returns:
        LogBuffer: a LogBuffer
    '''
    has_single_quote = False
    has_double_quote = False
    single_quote_buff = LogBuffer(_maximum_data_output_width)
    double_quote_buff = LogBuffer(_maximum_data_output_width)
    if len(value) >= _minimum_output_length:
        single_quote_buff.no_break_append('(')
        single_quote_buff.no_break_append(_length_format.format(len(value)))
        single_quote_buff.no_break_append(')')
        double_quote_buff.no_break_append('(')
        double_quote_buff.no_break_append(_length_format.format(len(value)))
        double_quote_buff.no_break_append(')')
    single_quote_buff.no_break_append("'")
    double_quote_buff.no_break_append('"')

    count = 1
    for char in value:
        if count > print_options.string_limit:
            single_quote_buff.no_break_append(_limit_string)
            double_quote_buff.no_break_append(_limit_string)
            break
        if char == "'":
            single_quote_buff.no_break_append("\\'")
            double_quote_buff.no_break_append(char)
            has_single_quote = True
        elif char == '"':
            single_quote_buff.no_break_append(char)
            double_quote_buff.no_break_append('\\"')
            has_double_quote = True
        elif char == '\\':
            single_quote_buff.no_break_append('\\\\')
            double_quote_buff.no_break_append('\\\\')
        elif char == '\n':
            single_quote_buff.no_break_append('\\n')
            double_quote_buff.no_break_append('\\n')
        elif char == '\r':
            single_quote_buff.no_break_append('\\r')
            double_quote_buff.no_break_append('\\r')
        elif char == '\t':
            single_quote_buff.no_break_append('\\t')
            double_quote_buff.no_break_append('\\t')
        elif char < ' ':
            num_str = format(ord(char), '02X')
            single_quote_buff.no_break_append('\\x' + num_str)
            double_quote_buff.no_break_append('\\x' + num_str)
        else:
            single_quote_buff.no_break_append(char)
            double_quote_buff.no_break_append(char)
        count += 1

    double_quote_buff.no_break_append('"')
    single_quote_buff.no_break_append("'")
    if has_single_quote and not has_double_quote:
        return double_quote_buff
    return single_quote_buff
コード例 #10
0
def _to_string(name: str, value: object,
               print_options: _PrintOptions) -> LogBuffer:
    '''
    Returns a LogBuffer containing a string representation of the the name and value.

    Args:
        name (str): The name related to the value
        value (object): The value
        print_options (_PrintOptions): Output options 

    Returns:
        LogBuffer: a LogBuffer
    '''
    buff = LogBuffer(_maximum_data_output_width)

    separator = None
    if name is not None:
        buff.append(name)
        separator = _varname_value_separator

    if value is None:
        # None
        buff.no_break_append(separator).append('None')

    elif isinstance(value, str):
        # str
        value_buff = _to_string_str(value, print_options)
        buff.append_buffer(separator, value_buff)

    elif isinstance(value, bytes) or isinstance(value, bytearray):
        # bytes
        value_buff = _to_string_bytes(value, print_options)
        buff.append_buffer(separator, value_buff)

    elif isinstance(value, int) or isinstance(value, float) or \
        isinstance(value, datetime.date) or isinstance(value, datetime.time) or \
        isinstance(value, datetime.datetime):
        # int, float, datetime.date, datetime.time, datetime.datetime
        buff.no_break_append(separator).append(str(value))

    elif isinstance(value, list) or \
            isinstance(value, set) or isinstance(value, frozenset) or \
            isinstance(value, tuple) or \
            isinstance(value, dict):
        # list, set, frozenset, tuple, dict
        value_buff = _to_string_iterable(value, print_options)
        buff.append_buffer(separator, value_buff)

    else:
        has_str, has_repr = _has_str_repr_method(value)
        value_buff = LogBuffer(_maximum_data_output_width)
        if not print_options.force_reflection and (has_str or has_repr):
            # has __str__ or __repr__ method
            if has_repr:
                value_buff.append('repr(): ')
                value_buff.no_break_append(repr(value))
            else:
                value_buff.append('str(): ')
                value_buff.no_break_append(str(value))
            buff.append_buffer(separator, value_buff)

        else:
            # use refrection
            if any(map(lambda obj: value is obj, _reflected_objects)):
                # cyclic reference
                value_buff.no_break_append(_cyclic_reference_string)
            elif len(_reflected_objects) > print_options.reflection_nest_limit:
                # over reflection level limitation
                value_buff.no_break_append(_limit_string)
            else:
                _reflected_objects.append(value)
                value_buff = _to_string_refrection(value, print_options)
                _reflected_objects.pop()
            buff.append_buffer(separator, value_buff)

    return buff