Esempio n. 1
0
def path_to_display(path):
    # type: (Optional[Union[str, Text]]) -> Optional[Text]
    """
    Convert a bytes (or text) path to text (unicode in Python 2) for display
    and logging purposes.

    This function should never error out. Also, this function is mainly needed
    for Python 2 since in Python 3 str paths are already text.
    """
    if path is None:
        return None
    if isinstance(path, text_type):
        return path
    # Otherwise, path is a bytes object (str in Python 2).
    try:
        display_path = path.decode(sys.getfilesystemencoding(), 'strict')
    except UnicodeDecodeError:
        # Include the full bytes to make troubleshooting easier, even though
        # it may not be very human readable.
        if PY2:
            # Convert the bytes to a readable str representation using
            # repr(), and then convert the str to unicode.
            #   Also, we add the prefix "b" to the repr() return value both
            # to make the Python 2 output look like the Python 3 output, and
            # to signal to the user that this is a bytes representation.
            display_path = str_to_display('b{!r}'.format(path))
        else:
            # Silence the "F821 undefined name 'ascii'" flake8 error since
            # in Python 3 ascii() is a built-in.
            display_path = ascii(path)  # noqa: F821

    return display_path
Esempio n. 2
0
def test_str_to_display__encoding(monkeypatch, data, encoding, expected):
    monkeypatch.setattr(locale, 'getpreferredencoding', lambda: encoding)
    actual = str_to_display(data)
    assert actual == expected, (
        # Show the encoding for easier troubleshooting.
        'encoding: {!r}'.format(locale.getpreferredencoding())
    )
Esempio n. 3
0
def make_subprocess_output_error(
        cmd_args,  # type: Union[List[str], CommandArgs]
        cwd,  # type: Optional[str]
        lines,  # type: List[str]
        exit_status,  # type: int
):

    # type: (...) -> str
    """

    Create and return the error message to use to log a subprocess error

    with command output.



    :param lines: A list of lines, each ending with a newline.

    """

    command = format_command_args(cmd_args)

    # Convert `command` and `cwd` to text (unicode in Python 2) so we can use

    # them as arguments in the unicode format string below. This avoids

    # "UnicodeDecodeError: 'ascii' codec can't decode byte ..." in Python 2

    # if either contains a non-ascii character.

    command_display = str_to_display(command, desc='command bytes')

    cwd_display = path_to_display(cwd)

    # We know the joined output value ends in a newline.

    output = ''.join(lines)

    msg = (

        # Use a unicode string to avoid "UnicodeEncodeError: 'ascii'

        # codec can't encode character ..." in Python 2 when a format

        # argument (e.g. `output`) has a non-ascii character.
        'Command errored out with exit status {exit_status}:\n'
        ' command: {command_display}\n'
        '     cwd: {cwd_display}\n'
        'Complete output ({line_count} lines):\n{output}{divider}').format(
            exit_status=exit_status,
            command_display=command_display,
            cwd_display=cwd_display,
            line_count=len(lines),
            output=output,
            divider=LOG_DIVIDER,
        )

    return msg
Esempio n. 4
0
def test_str_to_display__decode_error(monkeypatch, caplog):
    monkeypatch.setattr(locale, 'getpreferredencoding', lambda: 'utf-8')
    # Encode with an incompatible encoding.
    data = u'ab'.encode('utf-16')
    actual = str_to_display(data)

    assert actual == u'\\xff\\xfea\x00b\x00', (
        # Show the encoding for easier troubleshooting.
        'encoding: {!r}'.format(locale.getpreferredencoding()))
    assert len(caplog.records) == 1
    record = caplog.records[0]
    assert record.levelname == 'WARNING'
    assert record.message == (
        'Bytes object does not appear to be encoded as utf-8')
Esempio n. 5
0
def test_str_to_display__decode_error(monkeypatch, caplog):
    monkeypatch.setattr(locale, 'getpreferredencoding', lambda: 'utf-8')
    # Encode with an incompatible encoding.
    data = 'ab'.encode('utf-16')
    actual = str_to_display(data)
    # Keep the expected value endian safe
    if sys.byteorder == "little":
        expected = "\\xff\\xfea\x00b\x00"
    elif sys.byteorder == "big":
        expected = "\\xfe\\xff\x00a\x00b"

    assert actual == expected, (
        # Show the encoding for easier troubleshooting.
        f'encoding: {locale.getpreferredencoding()!r}')
    assert len(caplog.records) == 1
    record = caplog.records[0]
    assert record.levelname == 'WARNING'
    assert record.message == (
        'Bytes object does not appear to be encoded as utf-8')
Esempio n. 6
0
def test_str_to_display(data, expected):
    actual = str_to_display(data)
    assert actual == expected, (
        # Show the encoding for easier troubleshooting.
        'encoding: {!r}'.format(locale.getpreferredencoding())
    )