Подтвердить что ты не робот

Как включить специальные символы (tab, newline) в строку результатов доктрины python?

Учитывая следующий python script:

# dedupe.py
import re

def dedupe_whitespace(s,spacechars='\t '):
    """Merge repeated whitespace characters.
    Example:
    >>> dedupe_whitespace(r"Green\t\tGround")  # doctest: +REPORT_NDIFF
    'Green\tGround'
    """
    for w in spacechars:
        s = re.sub(r"("+w+"+)", w, s)
    return s

Функция работает по назначению в интерпретаторе python:

$ python
>>> import dedupe
>>> dedupe.dedupe_whitespace('Purple\t\tHaze')
'Purple\tHaze'
>>> print dedupe.dedupe_whitespace('Blue\t\tSky')
Blue    Sky

Однако пример доктрины терпит неудачу, потому что символы табуляции преобразуются в пробелы перед сравнением с результирующей строкой:

>>> import doctest, dedupe
>>> doctest.testmod(dedupe)

дает

Failed example:
    dedupe_whitespace(r"Green           Ground")  #doctest: +REPORT_NDIFF
Differences (ndiff with -expected +actual):
    - 'Green  Ground'
    ?       -
    + 'Green Ground'

Как я могу кодировать символы табуляции в строке heestoc doctest, чтобы сравнение результатов теста выполнялось соответствующим образом?

4b9b3361

Ответ 1

Я получил это, чтобы работать с литеральной строковой нотацией для docstring:

def join_with_tab(iterable):
    r"""
    >>> join_with_tab(['1', '2'])
    '1\t2'
    """

    return '\t'.join(iterable)

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Ответ 2

Это текстовая нотация Heredoc string (r"""), которая сделала трюк:

# filename: dedupe.py
import re,doctest
def dedupe_whitespace(s,spacechars='\t '):
    r"""Merge repeated whitespace characters.
    Example:
    >>> dedupe_whitespace('Black\t\tGround')  #doctest: +REPORT_NDIFF
    'Black\tGround'
    """
    for w in spacechars:
        s = re.sub(r"("+w+"+)", w, s)
    return s

if __name__ == "__main__":
    doctest.testmod()

Ответ 3

Вы должны установить NORMALIZE_WHITESPACE. Или, наоборот, захватить вывод и сравнить его с ожидаемым значением:

def dedupe_whitespace(s,spacechars='\t '):
    """Merge repeated whitespace characters.
    Example:
    >>> output = dedupe_whitespace(r"Black\t\tGround")  #doctest: +REPORT_NDIFF
    >>> output == 'Black\tGround'
    True
    """

Забастовкa >

В разделе документации doctest Как распознаются примеры Docstring?:

Все символы жесткой вкладки расширяются до пробелов, используя вкладку с 8 столбцами останавливается. Вкладки, выводимые с помощью тестируемого кода, не изменяются. Поскольку все жесткие вкладки в образце выводятся, это означает, что что если вывод кода включает в себя жесткие вкладки, единственный способ доктрины может пройти, если NORMALIZE_WHITESPACEвариант или директива. В качестве альтернативы, тест может быть переписан для захвата вывода и сравнения его с ожидаемым значением как часть теста. Эта обработка вкладок в источнике была получена посредством проб и ошибок, и оказался наименее подверженным ошибкам способ их обработки. Можно использовать другой алгоритм для используя вкладки DocTestParser.

Изменить: Моя ошибка, я понял документы в обратном порядке. Вкладки расширяются до 8 пробелов как при строчном аргументе, переданном в dedupe_whitespace, так и в строковом литерале, который сравнивается в следующей строке, поэтому output содержит:

"Black Ground"

и сравнивается с:

"Black        Ground"

Я не могу найти способ преодолеть это ограничение без написания собственного DocTestParser или тестирования для дедуплицированных пространств вместо вкладок.

Ответ 4

TL; DR: Удалите обратную косую черту, т.е. используйте \\n или \\t вместо \n или \t в своих неизмененных строках;

Вероятно, вы не хотите, чтобы ваши docstrings были сырыми, как тогда вы не сможете использовать любые escape-строки в Python, включая те, которые вы можете захотеть.

Для метода, который поддерживает использование обычных экранов, просто удалите обратную косую черту в escape-символе обратной косой черты, чтобы после интерпретации Python она оставила буквальную обратную косую черту с последующим символом, который doctest может анализировать.

Ответ 5

Это в основном ответ YatharhROCK, но немного более явный. Вы можете использовать необработанные строки или двойное экранирование. Но почему?

Вам нужен строковый литерал, чтобы содержать действительный код Python, который при интерпретации является кодом, который вы хотите запустить/проверить. Эти обе работают:

#!/usr/bin/env python

def split_raw(val, sep='\n'):
  r"""Split a string on newlines (by default).

  >>> split_raw('alpha\nbeta\ngamma')
  ['alpha', 'beta', 'gamma']
  """
  return val.split(sep)


def split_esc(val, sep='\n'):
  """Split a string on newlines (by default).

  >>> split_esc('alpha\\nbeta\\ngamma')
  ['alpha', 'beta', 'gamma']
  """
  return val.split(sep)

import doctest
doctest.testmod()

Эффект использования сырых строк и эффект двойного экранирования (выход из косой черты) уходит в строку двумя символами, косой чертой и n. Этот код передается интерпретатору Python, который принимает "slash then n" для обозначения "символ новой строки" внутри строкового литерала.

Используйте то, что вы предпочитаете.