Skip to content

Printers

Printer modules convert behave-model objects into formatted Gherkin text. Each printer handles a specific model element and is responsible for indentation, alignment, and spacing.

Feature Printer

Formats a complete Feature — including tags, description, background, scenarios, scenario outlines, and rules — into a full .feature file string.

behave_format.printer.feature_printer

Feature printer — formats a complete Feature as .feature text.

print_feature

print_feature(feature: Feature, indent: int = 2, *, line_length: int | None = None) -> str

Format a Feature as valid, deterministic Gherkin text.

Parameters:

Name Type Description Default
feature Feature

The Feature to print.

required
indent int

Base indentation for scenarios and rules.

2
line_length int | None

Optional maximum line length for tag wrapping.

None

Returns:

Type Description
str

Multi-line string representing the complete feature file content.

Source code in behave_format/printer/feature_printer.py
def print_feature(
    feature: Feature,
    indent: int = 2,
    *,
    line_length: int | None = None,
) -> str:
    """Format a Feature as valid, deterministic Gherkin text.

    Args:
        feature: The Feature to print.
        indent: Base indentation for scenarios and rules.
        line_length: Optional maximum line length for tag wrapping.

    Returns:
        Multi-line string representing the complete feature file content.
    """
    language = feature.language or "en"
    lines: list[str] = []

    # Emit the directive only for languages behave can actually re-parse;
    # an unknown code would produce output that fails to round-trip.
    if language != "en" and is_known_language(language):
        lines.append(f"# language: {language}")

    for comment in feature.comments:
        lines.append(comment.text)

    if feature.tags:
        lines.append(print_tags(feature.tags, indent=0, line_length=line_length))

    keyword = gherkin_keyword(feature, "feature", language)
    header = f"{keyword}: {feature.name}" if feature.name else f"{keyword}:"
    lines.append(header)

    if feature.description:
        for desc_line in feature.description.splitlines():
            lines.append(f"{' ' * indent}{desc_line}" if desc_line else "")

    if feature.background:
        lines.append("")
        lines.append(print_background(feature.background, indent=indent, language=language))

    for scenario in feature.scenarios:
        lines.append("")
        lines.append(
            _print_scenario_like(
                scenario, indent=indent, language=language, line_length=line_length
            )
        )

    for rule in feature.rules:
        lines.append("")
        lines.append(_print_rule(rule, indent=indent, language=language, line_length=line_length))

    return "\n".join(lines)

Scenario Printer

Formats Background, Scenario, and ScenarioOutline blocks, including their tags, descriptions, steps, and examples tables.

behave_format.printer.scenario_printer

Scenario printer — formats scenarios and scenario outlines.

print_background

print_background(background: Background, indent: int = 2, *, language: str = 'en') -> str

Format a Background block.

Parameters:

Name Type Description Default
background Background

The Background to print.

required
indent int

Base indentation level.

2
language str

Feature language for keyword resolution.

'en'

Returns:

Type Description
str

Multi-line string with the background and its steps.

Source code in behave_format/printer/scenario_printer.py
def print_background(
    background: Background,
    indent: int = 2,
    *,
    language: str = "en",
) -> str:
    """Format a Background block.

    Args:
        background: The Background to print.
        indent: Base indentation level.
        language: Feature language for keyword resolution.

    Returns:
        Multi-line string with the background and its steps.
    """
    prefix = " " * indent
    keyword = gherkin_keyword(background, "background", language)
    header = f"{keyword}:"
    if background.name:
        header = f"{keyword}: {background.name}"
    lines: list[str] = [f"{prefix}{header}"]
    for step in background.steps:
        lines.append(print_step(step, indent=indent + 2))
    return "\n".join(lines)

print_scenario

print_scenario(scenario: Scenario, indent: int = 2, *, language: str = 'en', line_length: int | None = None) -> str

Format a Scenario as Gherkin text.

Parameters:

Name Type Description Default
scenario Scenario

The Scenario to print.

required
indent int

Base indentation level.

2
language str

Feature language for keyword resolution.

'en'
line_length int | None

Optional maximum line length for tag wrapping.

None

Returns:

Type Description
str

Multi-line string with tags, scenario header, and steps.

Source code in behave_format/printer/scenario_printer.py
def print_scenario(
    scenario: Scenario,
    indent: int = 2,
    *,
    language: str = "en",
    line_length: int | None = None,
) -> str:
    """Format a Scenario as Gherkin text.

    Args:
        scenario: The Scenario to print.
        indent: Base indentation level.
        language: Feature language for keyword resolution.
        line_length: Optional maximum line length for tag wrapping.

    Returns:
        Multi-line string with tags, scenario header, and steps.
    """
    prefix = " " * indent
    lines: list[str] = []

    for comment in scenario.comments:
        lines.append(f"{prefix}{comment.text}")

    if scenario.tags:
        lines.append(print_tags(scenario.tags, indent=indent, line_length=line_length))

    keyword = gherkin_keyword(scenario, "scenario", language)
    header = f"{keyword}: {scenario.name}" if scenario.name else f"{keyword}:"
    lines.append(f"{prefix}{header}")

    _append_description(lines, scenario.description, indent + 2)

    for step in scenario.steps:
        lines.append(print_step(step, indent=indent + 2))

    return "\n".join(lines)

print_scenario_outline

print_scenario_outline(outline: ScenarioOutline, indent: int = 2, *, language: str = 'en', line_length: int | None = None) -> str

Format a ScenarioOutline as Gherkin text.

Parameters:

Name Type Description Default
outline ScenarioOutline

The ScenarioOutline to print.

required
indent int

Base indentation level.

2
language str

Feature language for keyword resolution.

'en'
line_length int | None

Optional maximum line length for tag wrapping.

None

Returns:

Type Description
str

Multi-line string with tags, outline header, steps, and examples.

Source code in behave_format/printer/scenario_printer.py
def print_scenario_outline(
    outline: ScenarioOutline,
    indent: int = 2,
    *,
    language: str = "en",
    line_length: int | None = None,
) -> str:
    """Format a ScenarioOutline as Gherkin text.

    Args:
        outline: The ScenarioOutline to print.
        indent: Base indentation level.
        language: Feature language for keyword resolution.
        line_length: Optional maximum line length for tag wrapping.

    Returns:
        Multi-line string with tags, outline header, steps, and examples.
    """
    prefix = " " * indent
    lines: list[str] = []

    for comment in outline.comments:
        lines.append(f"{prefix}{comment.text}")

    if outline.tags:
        lines.append(print_tags(outline.tags, indent=indent, line_length=line_length))

    keyword = gherkin_keyword(outline, "scenario_outline", language)
    header = f"{keyword}: {outline.name}" if outline.name else f"{keyword}:"
    lines.append(f"{prefix}{header}")

    _append_description(lines, outline.description, indent + 2)

    for step in outline.steps:
        lines.append(print_step(step, indent=indent + 2))

    for examples in outline.examples:
        lines.append("")
        lines.append(
            _print_examples(examples, indent=indent + 2, language=language, line_length=line_length)
        )

    return "\n".join(lines)

Step Printer

Formats a Step with proper indentation, including attached DocString and data Table.

behave_format.printer.step_printer

Step printer — formats steps with proper indentation.

print_step

print_step(step: Step, indent: int = 4) -> str

Format a single step as Gherkin text.

Parameters:

Name Type Description Default
step Step

The Step to print.

required
indent int

Number of spaces for indentation.

4

Returns:

Type Description
str

Multi-line string with the step and any attached docstring or table.

Source code in behave_format/printer/step_printer.py
def print_step(step: Step, indent: int = 4) -> str:
    """Format a single step as Gherkin text.

    Args:
        step: The Step to print.
        indent: Number of spaces for indentation.

    Returns:
        Multi-line string with the step and any attached docstring or table.
    """
    prefix = " " * indent
    lines: list[str] = []

    for comment in step.comments:
        lines.append(f"{prefix}{comment.text}")

    lines.append(f"{prefix}{step.keyword} {step.name}".rstrip())

    if step.doc_string:
        lines.append(_print_doc_string(step.doc_string, indent))

    if step.data_table:
        table_text = print_table(step.data_table, indent=indent + 2)
        if table_text:
            lines.append(table_text)

    return "\n".join(lines)

Table Printer

Formats a Table with aligned columns. Computes column widths from headers and all rows to produce a rectangular, padded table.

behave_format.printer.table_printer

Table printer — formats data tables with aligned columns.

print_table

print_table(table: Table, indent: int = 4) -> str

Format a Table as aligned Gherkin table text.

Cell values are re-escaped for Gherkin (| -> \|) and column widths are computed on the escaped, display-width of each cell so wide characters (CJK) stay aligned.

Parameters:

Name Type Description Default
table Table

The Table to print.

required
indent int

Number of spaces for indentation.

4

Returns:

Type Description
str

Multi-line string with aligned table rows.

Source code in behave_format/printer/table_printer.py
def print_table(table: Table, indent: int = 4) -> str:
    """Format a Table as aligned Gherkin table text.

    Cell values are re-escaped for Gherkin (``|`` -> ``\\|``) and column
    widths are computed on the escaped, display-width of each cell so
    wide characters (CJK) stay aligned.

    Args:
        table: The Table to print.
        indent: Number of spaces for indentation.

    Returns:
        Multi-line string with aligned table rows.
    """
    if not table.headers and not table.rows:
        return ""

    rows = [[_escape_cell(c) for c in row.cells] for row in table.rows]
    headers = [_escape_cell(h) for h in table.headers]
    widths = _compute_widths(headers, rows)
    prefix = " " * indent
    lines: list[str] = []

    lines.append(_format_row(prefix, headers, widths))
    for row in rows:
        lines.append(_format_row(prefix, row, widths))

    return "\n".join(lines)

Tag Printer

Formats a list of Tag objects as space-separated lines, wrapping onto continuation lines when line_length is exceeded.

behave_format.printer.tag_printer

Tag printer — formats tags as space-separated strings.

print_tags

print_tags(tags: list[Tag], indent: int = 0, line_length: int | None = None) -> str

Format a list of tags as one or more space-separated lines.

Parameters:

Name Type Description Default
tags list[Tag]

List of Tag objects.

required
indent int

Number of spaces to prefix.

0
line_length int | None

Optional maximum line length. When exceeded, tags wrap onto continuation lines at the same indent.

None

Returns:

Type Description
str

A space-separated tag string, or empty string if no tags.

Source code in behave_format/printer/tag_printer.py
def print_tags(tags: list[Tag], indent: int = 0, line_length: int | None = None) -> str:
    """Format a list of tags as one or more space-separated lines.

    Args:
        tags: List of Tag objects.
        indent: Number of spaces to prefix.
        line_length: Optional maximum line length. When exceeded, tags
            wrap onto continuation lines at the same indent.

    Returns:
        A space-separated tag string, or empty string if no tags.
    """
    if not tags:
        return ""
    prefix = " " * indent
    names = [t.name for t in tags]
    if line_length is None or line_length <= 0:
        return prefix + " ".join(names)

    lines: list[str] = []
    current: list[str] = []
    current_len = indent
    for name in names:
        extra = len(name) + (1 if current else 0)
        if current and current_len + extra > line_length:
            lines.append(prefix + " ".join(current))
            current = [name]
            current_len = indent + len(name)
        else:
            current.append(name)
            current_len += extra
    if current:
        lines.append(prefix + " ".join(current))
    return "\n".join(lines)

Keywords

Resolves the Gherkin keyword to print for each element — the original keyword when the element was parsed from a file, or the canonical i18n alias for the feature's language.

behave_format.printer.keywords

Gherkin keyword resolution.

Elements parsed from a file carry their original keyword in the private _gherkin_keyword attribute (restored by :mod:behave_format.loader). Programmatically built models fall back to the first behave i18n alias for the element's language.

is_known_language

is_known_language(language: str) -> bool

Return True if behave's i18n tables know this language code.

Source code in behave_format/printer/keywords.py
def is_known_language(language: str) -> bool:
    """Return True if behave's i18n tables know this language code."""
    return language in i18n.languages

gherkin_keyword

gherkin_keyword(element, kind: str, language: str = 'en') -> str

Return the Gherkin keyword to print for an element.

Parameters:

Name Type Description Default
element

Model element (Feature, Rule, Scenario, Examples, ...).

required
kind str

behave i18n keyword kind ("feature", "scenario", ...).

required
language str

Feature file language code (e.g. "en", "es").

'en'

Returns:

Type Description
str

The original keyword if the element was parsed from a file,

str

otherwise the conventional i18n alias for the language.

Source code in behave_format/printer/keywords.py
def gherkin_keyword(element, kind: str, language: str = "en") -> str:
    """Return the Gherkin keyword to print for an element.

    Args:
        element: Model element (Feature, Rule, Scenario, Examples, ...).
        kind: behave i18n keyword kind (``"feature"``, ``"scenario"``, ...).
        language: Feature file language code (e.g. ``"en"``, ``"es"``).

    Returns:
        The original keyword if the element was parsed from a file,
        otherwise the conventional i18n alias for the language.
    """
    keyword = getattr(element, "_gherkin_keyword", "")
    if keyword:
        return keyword
    aliases = i18n.languages.get(language, _ENGLISH)
    choices = aliases.get(kind) or _ENGLISH[kind]
    preferred = _PREFERRED[kind]
    return preferred if preferred in choices else choices[0]