Skip to main content

Opinionated Python project structure and code quality linter

Project description

kdaquila-structure-lint

Opinionated Python and TypeScript project structure and code quality linter.

License: MIT Python 3.10+

Overview

kdaquila-structure-lint is a linter that enforces code quality and project structure conventions for Python and TypeScript projects. It provides three validators that can be enabled independently:

  • Line Limits Validator (enabled by default) - Enforces maximum line count per file
  • One-Per-File Validator (enabled by default) - Ensures single function/class per file
  • Structure Validator (opt-in) - Enforces opinionated folder structure rules

Installation

Install from PyPI using pip:

pip install kdaquila-structure-lint

For development installations:

git clone https://github.com/kdaquila/kdaquila-structure-lint.git
cd kdaquila-structure-lint
pip install -e ".[dev]"

Quick Start

Run the linter in your project directory:

structure-lint

The tool will:

  1. Auto-detect your project root by searching for pyproject.toml
  2. Load configuration from [tool.structure-lint] section (or use defaults)
  3. Run all enabled validators
  4. Report any violations with clear error messages

Basic Example

Add configuration to your pyproject.toml:

[tool.structure-lint]
enabled = true

[tool.structure-lint.validators]
line_limits = true
one_per_file = true
structure = false  # Opt-in only

Run the linter:

structure-lint

Features

Supported Languages

  • Python (.py files)
  • TypeScript (.ts, .tsx files) - with React/hooks support

Line Limits Validator

Enforces a maximum number of lines per file to encourage modular, maintainable code.

Default: 150 lines per file

Configuration:

[tool.structure-lint]
search_paths = ["src"]  # Applies to all validators

[tool.structure-lint.line_limits]
max_lines = 150

Example Output:

============================================================
Running line limit validation...
============================================================
✗ src/features/data_processing/processor.py: 187 lines (exceeds 150 line limit)
✗ src/analysis/report_generator.py: 203 lines (exceeds 150 line limit)

2 files exceed the line limit

One-Per-File Validator

Ensures files contain only one top-level function or class definition - no extra definitions allowed. Uses folder-aware rules to apply appropriate checks:

Folder Python Rule TypeScript Rule
_functions 1 function only 1 function only
_classes 1 class only 1 class only
_components - 1 function only (React component)
_hooks - 1 function only (React hook)
_types, _constants no limit no limit

What's NOT allowed in one-per-file validated folders:

  • Extra type definitions (TypeScript type, interface, enum)
  • Constants or variable assignments
  • Additional functions or classes

Move these to the appropriate folders (_types, _constants, etc.) instead.

Configuration:

[tool.structure-lint]
search_paths = ["src"]  # Applies to all validators

[tool.structure-lint.one_per_file]
# TypeScript rules (all default: true)
ts_fun_in_functions = true
ts_fun_in_components = true
ts_fun_in_hooks = true
ts_cls_in_classes = true

# Python rules (all default: true)
py_fun_in_functions = true
py_cls_in_classes = true

# Skip type definition files
excluded_patterns = ["*.d.ts"]

Example Output (Python - multiple definitions):

✗ src/_functions/helpers.py: 3 definitions (expected 1)
  - format_date (function)
  - parse_date (function)
  - DateFormatter (class)

Example Output (TypeScript - multiple definitions):

✗ src/_components/buttons.tsx: 2 definitions (expected 1)
  - PrimaryButton (function)
  - SecondaryButton (function)

Example Output (extra definitions):

✗ src/_functions/format_date.py: extra definitions not allowed
  - DEFAULT_FORMAT (assignment)

Structure Validator (Opt-in)

Enforces an opinionated folder structure based on feature-driven development principles. This validator is disabled by default as it's highly prescriptive.

Enable with:

[tool.structure-lint.validators]
structure = true

See docs/validators.md for detailed structure rules.

Configuration

Minimal Configuration

Create a minimal configuration in your pyproject.toml:

[tool.structure-lint]
enabled = true

This uses all default settings with line_limits and one_per_file enabled.

Full Configuration

See all available options:

[tool.structure-lint]
enabled = true
search_paths = ["src"]  # Applies to all validators

[tool.structure-lint.validators]
structure = false        # Opt-in (default: disabled)
line_limits = true       # Default: enabled
one_per_file = true      # Default: enabled

[tool.structure-lint.line_limits]
max_lines = 150

[tool.structure-lint.one_per_file]
# TypeScript rules
ts_fun_in_functions = true
ts_fun_in_components = true
ts_fun_in_hooks = true
ts_cls_in_classes = true
# Python rules
py_fun_in_functions = true
py_cls_in_classes = true
# Exclusions
excluded_patterns = ["*.d.ts"]

[tool.structure-lint.structure]
folder_depth = 2
standard_folders = ["_types", "_functions", "_constants", "_tests", "_errors", "_classes", "_components", "_hooks"]
files_allowed_anywhere = ["__init__.py", "index.ts", "index.tsx"]
ignored_folders = ["__pycache__", ".mypy_cache", ".pytest_cache", ".ruff_cache", ".hypothesis", ".tox", ".coverage", "*.egg-info"]

For detailed configuration options, see docs/configuration.md.

Example Configurations

Example configurations are available in the docs/examples/ directory:

Command-Line Interface

Basic Usage

structure-lint                    # Run in current directory
structure-lint --verbose          # Show detailed output
structure-lint --version          # Show version
structure-lint --help             # Show help message

Advanced Options

# Specify project root explicitly
structure-lint --project-root /path/to/project

# Use a specific pyproject.toml file
structure-lint --config /path/to/pyproject.toml

# Verbose output (shows project root and detailed progress)
structure-lint --verbose

Exit Codes

The CLI returns different exit codes for automation and CI/CD integration:

  • 0 - All validations passed
  • 1 - One or more validations failed
  • 2 - Configuration error or unexpected error

Usage in CI/CD

GitHub Actions

Add to your .github/workflows/ci.yml:

name: CI

on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: |
          pip install kdaquila-structure-lint
      - name: Run structure linter
        run: structure-lint

Pre-commit Hook

Add to your .pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: structure-lint
        name: structure-lint
        entry: structure-lint
        language: system
        pass_filenames: false

GitLab CI

Add to your .gitlab-ci.yml:

structure-lint:
  image: python:3.11
  script:
    - pip install kdaquila-structure-lint
    - structure-lint

Development

Running Tests

pip install -e ".[dev]"
pytest

Type Checking

mypy src/features

Linting

ruff check src/features tests

Documentation

Philosophy

This linter enforces opinions about code organization based on these principles:

  1. Modularity - Files should be small and focused
  2. Discoverability - One definition per file makes code easier to find
  3. Consistency - Predictable structure reduces cognitive load
  4. Flexibility - All rules are configurable and can be disabled

The structure validator is opt-in because it's highly opinionated. The other validators (line limits and one-per-file) represent more universally accepted best practices.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Created by kdaquila

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kdaquila_structure_lint-10.0.0.tar.gz (77.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kdaquila_structure_lint-10.0.0-py3-none-any.whl (83.8 kB view details)

Uploaded Python 3

File details

Details for the file kdaquila_structure_lint-10.0.0.tar.gz.

File metadata

  • Download URL: kdaquila_structure_lint-10.0.0.tar.gz
  • Upload date:
  • Size: 77.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for kdaquila_structure_lint-10.0.0.tar.gz
Algorithm Hash digest
SHA256 392d663968535fe0b82db2844a0178b76be68e65e59eb622ae89dc7ffb3281a9
MD5 adf672b247ee52c47030dbeef8855000
BLAKE2b-256 92bee428bac29e77c6d61f5963d1e788a00e24c6bcec78eafbd54e5a74bf433b

See more details on using hashes here.

File details

Details for the file kdaquila_structure_lint-10.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kdaquila_structure_lint-10.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 63cf7a2a732a4f353250ea24c327116eebdda67c885bd2a3108b98f1ee7f473f
MD5 8213d17f8ff3de4a61d4e1247515377b
BLAKE2b-256 830a07049b1f06877b6addcc9676a388fa368e65a93f95c3c201a79df236ee56

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page