Contribute to TUI Forms#
This guide walks you through setting up a local development environment, running quality checks, and submitting your changes.
Prerequisites#
You need the following tools installed on your machine:
Set up the development environment#
Clone the repository and install all dependencies into a local virtual environment:
git clone https://github.com/collective/tui-forms.git
cd tui-forms
make install
make install runs uv sync --all-extras, which creates a .venv directory with all runtime and optional dependencies installed.
Run the tests#
Run the full test suite:
make test
Run the tests with a coverage report:
make test-coverage
All new features, bug fixes, and refactors require tests. See the project's testing conventions in Concepts.
Check code quality#
Format the codebase:
make format
Run the linter:
make lint
Check type hints:
make lint-mypy
Run format and lint together:
make check
Fix all issues reported by the linter before submitting your changes.
Build the documentation#
Build the HTML documentation:
make docs-html
Preview the documentation with live reload:
make docs-livehtml
Run the Vale style checker on the documentation:
make docs-vale
Code standards#
Style and formatting#
Line length: 88 characters maximum (enforced by
ruff).Naming:
snake_casefor functions and variables,PascalCasefor classes,UPPER_SNAKE_CASEfor module-level constants.Imports: one import per line;
from package import namestyle; no wildcard imports. When importing more than three names from the same package, preferimport packageand reference them aspackage.Name.Use f-strings for string formatting.
autoescape=Trueis always forced in Jinja2 environments and must not be disabled.
Functions and classes#
Every function and class must have a docstring.
Functions must be focused and small.
Prefer a single
returnstatement per function. Use an intermediate variable rather than multiple early returns:# preferred func = self._ask_string if isinstance(question, QuestionBoolean): func = self._ask_boolean elif isinstance(question, QuestionChoice): func = self._ask_choice return func(question, default, prefix)
Use
dict.get("key")rather thandict.get("key", None).Type hints are required on all functions, including tests.
Testing#
Framework:
pytestviauv run pytest.Use
pytest.mark.parametrizefor groups of similar test cases rather than duplicating test functions.Use
pytestfixtures instead of module-level helper variables or functions.Avoid class-based test organisation; prefer plain
test_functions.Every new feature, bug fix, and refactoring requires tests. Bug fixes must include a regression test that reproduces the original failure.
Running checks#
Run all quality checks in one step before committing:
make check
This runs make format followed by make lint.
After that, run type-checking:
make lint-mypy
Fix all issues reported before pushing.
Changelog entry#
Every pull request must include a changelog entry so that changes are captured in the release notes. TUI Forms uses towncrier to manage changelog fragments.
Create a fragment file#
Add a file in the news/ directory at the repository root.
Name the file after the GitHub issue or pull request number, followed by a dot and the fragment type:
news/<number>.<type>
For example, a bug fix for issue 42 is news/42.bugfix.
If no GitHub issue exists for your change, prefix the filename with + followed by a single word that identifies the change:
news/+<identifier>.<type>
For example, news/+email-validator.feature. The + prefix tells towncrier to treat the file as an orphan fragment not linked to any issue number.
The six allowed types are:
Type |
Use for |
|---|---|
|
Changes that are not backwards compatible |
|
New user-facing functionality |
|
Bug fixes |
|
Documentation-only changes |
|
Refactoring, dependency updates, CI changes |
|
New or changed tests that do not affect runtime behaviour |
Write the entry#
The file content should be a single short paragraph in the past tense, written in plain English.
End with an attribution in the form @github_username.
Added format-based validators for email, date, date-time, and data-url fields.
Renderers now automatically re-prompt when the user's input fails validation. @your_username
Keep entries user-oriented: describe what changed and why it matters, not how it was implemented.
Good:
Fixed a crash when a
oneOfoption list contained anullvalue. @username
Poor:
Fixed #99 by adding a None check in
_extract_options. @username
Preview the draft changelog#
To see how your entry will appear in the release notes:
make changelog
This runs towncrier --draft and prints the rendered changelog to the terminal without writing any files.
Submit a pull request#
Create a branch from
main:git checkout -b my-featureMake your changes, then run
make checkandmake testto verify everything passes.Commit your changes with a descriptive message.
Push the branch and open a pull request against
mainon GitHub.
A pull request is ready for review when make check, make test, and make docs-html all pass with zero errors.