diff --git a/README.md b/README.md index c091f8f..0ad54de 100644 --- a/README.md +++ b/README.md @@ -352,6 +352,27 @@ def test_zen(patterns, zen_patterns): assert full_pattern == zen ``` +## Handling tabs and whitespace + +When copying and pasting output from commands its easy to turn tabs from an +original source into spaces and then accidentally not aligning things right. + +As its more typical to not insert tabs in your code pytest-patterns converts +tabs to spaces (properly aligned to 8 character stops as terminals render them): + +```python +def test_tabs_and_spaces(patterns): + data = """ +pre>\taligned text +prefix>\tmore aligned text +""" + tabs = patterns.tabs + tabs.in_order(""" +pre> aligned text +prefix> aligned text +""") + assert tabs == data +``` # Development @@ -378,8 +399,7 @@ $ hatch run test -> whitespace (pattern and tested content) -> strip whitespace at beginning and end - -> replace tabs with spaces - -> fold multiple spaces into single spaces + -> fold multiple spaces into single spaces (makes it harder to diagnose things) * [ ] proper release process with tagging, version updates, etc. diff --git a/src/pytest_patterns/plugin.py b/src/pytest_patterns/plugin.py index 9317d61..9337426 100644 --- a/src/pytest_patterns/plugin.py +++ b/src/pytest_patterns/plugin.py @@ -2,7 +2,7 @@ import enum import re -from typing import Any, Iterator +from typing import Any, Iterator, List, Set, Tuple import pytest @@ -45,13 +45,19 @@ def symbol(self) -> str: EMPTY_LINE_PATTERN = "" +def tab_replace(line: str) -> str: + while (position := line.find("\t")) != -1: + fill = " " * (8 - (position % 8)) + line = line.replace("\t", fill) + return line + def match(pattern: str, line: str) -> bool | re.Match[str] | None: if pattern == EMPTY_LINE_PATTERN: if not line: return True - pattern = pattern.replace("\t", " " * 8) - line = line.replace("\t", " " * 8) + + line = tab_replace(line) pattern = re.escape(pattern) pattern = pattern.replace(r"\.\.\.", ".*?") re_pattern = re.compile("^" + pattern + "$") diff --git a/tests/test_basics.py b/tests/test_basics.py index 04e5a7e..37879e4 100644 --- a/tests/test_basics.py +++ b/tests/test_basics.py @@ -11,6 +11,20 @@ "", ] +def test_tab_replace() -> None: + from pytest_patterns.plugin import tab_replace + + assert tab_replace("\t") == " " * 8 + assert tab_replace("1\t9") == "1 9" + assert tab_replace("12\t9") == "12 9" + assert tab_replace("123\t9") == "123 9" + assert tab_replace("1234\t9") == "1234 9" + assert tab_replace("12345\t9") == "12345 9" + assert tab_replace("123456\t9") == "123456 9" + assert tab_replace("1234567\t9") == "1234567 9" + assert tab_replace("12345678\t9") == "12345678 9" + assert tab_replace("123456789\t0") == "123456789 0" + def test_patternslib_multiple_accesses(patterns: PatternsLib) -> None: assert patterns.foo is patterns.foo