예제 #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