Skip to main content

Русская версия

pytest-fsd

PyPI Python CI

Validate Feature-Sliced Design (FSD) architecture in a Python project using pytest. The rules are adapted from the Steiger FSD plugin, with Python-specific checks where appropriate. This is an independent Python package, not an official Steiger port.

The applicable upstream changes are tracked through Steiger 0.7.0 / FSD plugin 0.8.0. See the changelog for Python adaptations.

Install

pip install pytest-fsd
# or
uv add --dev pytest-fsd

Python 3.8–3.14 is supported.

Use

Add the layers used by your project, from highest to lowest, to pyproject.toml:

[tool.pytest_fsd]
base_path = "src"
layers = ["app", "pages", "widgets", "features", "entities", "shared"]
# ignore_paths = ["my_non_fsd_package"]

Create an architecture test:

# tests/test_architecture.py
from pytest_fsd import validate_fsd_architecture


def test_architecture():
    validate_fsd_architecture()

Run pytest tests/test_architecture.py. Violations appear as assertion failures with a rule name and path. If your source root is different, set base_path accordingly. The validator reads [tool.pytest_fsd] from the project root; validate_fsd_architecture(project_root="...") can target another project.

Rules

The default checks cover layer import direction (forbidden-imports), slice independence (no-cross-imports), public APIs (public-api, no-public-api-sidestep, no-layer-public-api), structure (no-segmentless-slices, no-segments-on-sliced-layers, typo-in-layer-name, ambiguous-slice-names), naming (segments-by-purpose, repetitive-naming), and no-ui-in-app.

segments-by-purpose includes the generic names added in Steiger's FSD plugin 0.7.0, such as schemas, handlers, fixtures, middlewares, validators, resolvers, mutations, and assets. These names are checked when used as FSD segments. Python fixtures.py in a slice is also flagged because this package checks file segments as well as directories.

no-ui-in-app rejects an app/ui directory, as in Steiger. It also retains the Python-specific check for direct imports of common desktop GUI frameworks from the app layer.

Enable additional checks only when they suit your project:

[tool.pytest_fsd]
base_path = "src"
layers = ["app", "pages", "widgets", "features", "entities", "shared"]
extra_rules = [
    "excessive-slicing",        # More than 20 slices per layer
    "shared-lib-grouping",      # More than 15 loose Python files in shared/lib
    "no-file-segments",         # Segments must be directories
    "no-reserved-folder-names", # No nested segment names such as model/model
    "no-wildcard-exports",      # No `from module import *` in __init__.py
]

no-wildcard-exports was added in Steiger FSD plugin 0.8.0 and is disabled by default in both packages. It checks __init__.py files on every configured layer, including nested packages. Explicit module imports such as from . import model as model remain valid in Python. AST import diagnostics include line and character column numbers.

no-file-segments is a Python package option; it is not registered as a rule in Steiger FSD plugin 0.8.0. no-cross-imports is enabled here for compatibility, whereas the upstream plugin does not enable it by default. These choices are intentionally different from Steiger.

See the rule documentation for examples and details.

Scope and limitations

  • forbidden-imports and no-cross-imports use pytest-archon. Imports guarded by if TYPE_CHECKING: are invisible to these runtime checks.
  • no-public-api-sidestep analyzes Python syntax and explicit __all__ lists. Dynamically assembled exports may be reported incorrectly.
  • Steiger's inconsistent-naming and import-locality have no direct equivalent here. Consider Ruff's N and TID rules for Python naming and relative imports; their behavior is not identical to Steiger's rules.
  • Steiger's insignificant-slice needs an import graph and is not implemented. The deprecated processes layer is not created by this package; omit it from layers.
  • This package checks Python files and filesystem structure. It does not implement every Steiger rule or every JavaScript-specific convention.

See the upstream FSD plugin changelog for Steiger's release history.

License

MIT. See LICENSE.

Metadata

Release files for pytest-fsd 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-fsd 0.4.0
File Size Uploaded
pytest_fsd-0.4.0.tar.gz 27.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-fsd 0.4.0
File Interpreter ABI Platform
pytest_fsd-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 74.4 kB

Release files / pytest_fsd-0.4.0.tar.gz

Download URL pytest_fsd-0.4.0.tar.gz
Size 27.0 kB
Tags Source
SHA-256 checksum
How to use checksums
7fadefa76063ff294f461991c08c8c3a2eb6010e03bc881868367a8772c6640c
BLAKE2b-256 checksum
How to use checksums
7f6d6b12056eeb3b4228954f95eafbde4bff865df3d535415941a30e3da26757
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pytest_fsd-0.4.0-py3-none-any.whl

Download URL pytest_fsd-0.4.0-py3-none-any.whl
Size 47.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2ed9633e3f0c2ee7a2b0494bbde80bbd5b42a1194ae32bb3bede48dcfd0512e8
BLAKE2b-256 checksum
How to use checksums
9c094b8dc35610d506ac193bdf20b2652b1680447bc5f362fc35bfa2f323f6af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page