Python API¶
The Python API provides full control over the formatting process. You can format
projects or individual features, render to text, and customize all aspects via Settings.
Importing¶
from behave_format import (
Settings,
format_project,
render_project,
format_feature,
render_feature,
)
Main functions¶
format_project¶
Applies the full pipeline (normalize → sort → align) to a behave-model Project.
The project is mutated in place and returned.
from behave_model import load_project
from behave_format import format_project, Settings
project = load_project("features/")
format_project(project, Settings(indent=4))
# project is now formatted in place
render_project¶
Formats the project and returns the formatted .feature text for all features,
joined by blank lines.
from behave_model import load_project
from behave_format import render_project
project = load_project("features/")
text = render_project(project)
print(text)
format_feature¶
Formats a single Feature in place. Applies normalization, sorting, and alignment.
from behave_model import load_feature
from behave_format import format_feature, Settings
feature = load_feature("features/login.feature")
format_feature(feature, Settings(indent=2))
render_feature¶
Formats a single feature and returns the formatted .feature file content as a string.
from behave_model import load_feature
from behave_format import render_feature, Settings
feature = load_feature("features/login.feature")
text = render_feature(feature, Settings(indent=2))
print(text)
Settings¶
Settings is an immutable (frozen) dataclass that controls formatting behavior.
Creating settings¶
from behave_format import Settings
# Default settings (indent=2, sort_tags=True, etc.)
settings = Settings()
# Custom settings
settings = Settings(
indent=4,
sort_tags=True,
sort_features=False,
sort_scenarios=True,
line_length=100,
)
# From a dict
settings = Settings.from_dict({"indent": 4, "sort_tags": False})
# From pyproject.toml
settings = Settings.from_pyproject("pyproject.toml")
Immutable override¶
settings = Settings(indent=2)
settings = settings.with_indent(4) # Returns new Settings with indent=4
# Original is unchanged
assert settings.indent == 4
Inspecting settings¶
settings = Settings()
print(settings.indent) # 2
print(settings.sort_tags) # True
print(settings.sort_features) # False
print(settings.sort_scenarios) # False
print(settings.line_length) # 120
Advanced usage¶
Format without writing¶
from behave_model import load_project
from behave_format import render_project, Settings
project = load_project("features/")
formatted_text = render_project(project, Settings())
# Compare with original
for feature in project.features:
original = feature.source_file.read_text()
formatted = render_feature(feature, Settings())
if original != formatted:
print(f"Would reformat: {feature.source_file}")
Custom pipeline¶
from behave_model import load_project
from behave_format import Settings
from behave_format.pipeline.normalize import normalize_project
from behave_format.pipeline.sort import sort_project
from behave_format.pipeline.align import align_project
from behave_format.pipeline.rules import apply_rules
project = load_project("features/")
settings = Settings(indent=4)
# Run only specific stages
normalize_project(project, settings)
sort_project(project, settings)
# Skip align if you want
Batch processing¶
from pathlib import Path
from behave_model import load_feature
from behave_format import format_feature, render_feature, Settings
settings = Settings(indent=2)
for fpath in Path("features/").rglob("*.feature"):
feature = load_feature(fpath)
format_feature(feature, settings)
formatted = render_feature(feature, settings)
if formatted + "\n" != fpath.read_text():
fpath.write_text(formatted + "\n")
print(f"Formatted: {fpath}")
Integration with behave-model¶
from behave_model import load_project, load_feature
from behave_format import format_project, render_project, Settings
# Load and format an entire project
project = load_project("features/")
format_project(project, Settings())
text = render_project(project, Settings())
# Or work with individual features
feature = load_feature("features/login.feature")
format_feature(feature, Settings())
text = render_feature(feature, Settings())
Type hints¶
All public API functions are fully type-annotated:
from behave_format import Settings, format_project, render_project
from behave_model import Project, Feature
# Type signatures
# format_project(project: Project, settings: Settings | None = None) -> Project
# render_project(project: Project, settings: Settings | None = None) -> str
# format_feature(feature: Feature, settings: Settings | None = None) -> Feature
# render_feature(feature: Feature, settings: Settings | None = None) -> str
Error handling¶
The API does not raise exceptions on malformed input — that's behave-model's job.
If load_project or load_feature succeeds, formatting will always succeed.