Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Removed

Fixed
+++++
* Backslashes in datatable and examples table cells are no longer over-quoted. A cell containing a single backslash now reaches the step as a single backslash, matching the Gherkin escaping rules. `#769 <https://github.com/pytest-dev/pytest-bdd/issues/769>`_

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Backslashes in datatable and examples table cells are no longer over-quoted. A cell containing a single backslash now reaches the step as a single backslash, matching the Gherkin escaping rules. `#769 <https://github.com/pytest-dev/pytest-bdd/issues/769>`_
* Backslashes in datatable and examples table cells are no longer over-quoted. A cell containing a single backslash now reaches the step as a single backslash, matching the Gherkin escaping rules. if you compensated by doubling backslashes in feature files, undo that `#769 <https://github.com/pytest-dev/pytest-bdd/issues/769>`_

* Made type annotations stronger and removed most of the ``typing.Any`` usages and ``# type: ignore`` annotations. `#658 <https://github.com/pytest-dev/pytest-bdd/pull/658>`_
* Empty docstrings are now correctly forwarded to step functions as an empty string instead of being silently dropped, which previously caused pytest to report a missing ``docstring`` fixture. `#809 <https://github.com/pytest-dev/pytest-bdd/issues/809>`_

Expand Down
6 changes: 1 addition & 5 deletions src/pytest_bdd/gherkin_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class Cell:

@classmethod
def from_dict(cls, data: dict[str, Any]) -> Self:
return cls(location=Location.from_dict(data["location"]), value=_to_raw_string(data["value"]))
return cls(location=Location.from_dict(data["location"]), value=data["value"])


@dataclass
Expand Down Expand Up @@ -304,10 +304,6 @@ def from_dict(cls, data: Mapping[str, Any]) -> Self:
)


def _to_raw_string(normal_string: str) -> str:
return normal_string.replace("\\", "\\\\")


def get_gherkin_document(abs_filename: str, encoding: str = "utf-8") -> GherkinDocument:
with open(abs_filename, encoding=encoding) as f:
feature_file_text = f.read()
Expand Down
55 changes: 55 additions & 0 deletions tests/datatable/test_datatable.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,61 @@ def test_datatable():
result.assert_outcomes(passed=1)


def test_datatable_preserves_backslashes(pytester):
"""Backslashes in a datatable cell must not be over-quoted (see issue #769).

Gherkin already resolves cell escaping: "\\\\" is a single backslash, "\\|" is a
literal pipe, and a lone backslash stays a single backslash. The cell value must
reach the step exactly as the feature author wrote it.
"""
pytester.makefile(
".feature",
backslash_datatable=textwrap.dedent(
r"""Feature: Backslashes in datatables

Scenario: Backslashes are not over-quoted
Given a datatable with backslashes:
| single | double | escaped_pipe | path |
| \ | \\ | \| | C:\Users\John |
"""
),
)
pytester.makeconftest(
textwrap.dedent(
"""\
from pytest_bdd import given
from pytest_bdd.utils import dump_obj


@given("a datatable with backslashes:")
def _(datatable):
dump_obj(datatable)

"""
)
)
pytester.makepyfile(
textwrap.dedent(
"""\
from pytest_bdd import scenario

@scenario("backslash_datatable.feature", "Backslashes are not over-quoted")
def test_backslash_datatable():
pass
"""
)
)

result = pytester.runpytest("-s")
result.assert_outcomes(passed=1)

datatable = collect_dumped_objects(result)[0]
assert datatable == [
["single", "double", "escaped_pipe", "path"],
["\\", "\\", "|", r"C:\Users\John"],
]


def test_datatable_step_argument_is_reserved_and_cannot_be_used(pytester):
pytester.makefile(
".feature",
Expand Down
5 changes: 3 additions & 2 deletions tests/feature/test_outline.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,9 @@ def _(string):
r"bork |",
r"bork||bork",
r"|",
r"bork \\",
r"bork \\|",
# An escaped backslash "\\" in a cell is a single backslash, per the Gherkin spec.
"bork \\",
r"bork \|",
]


Expand Down
Loading