Directory layout

A first step of a new project is to define its directory layout.

Applications

Applications should follow the layout of the framework used, like Django, Scrapy or FastAPI, and should use its command for generating the layout, like django-admin startproject and django-admin startapp.

Tip

Commit the generated files before making changes, so that the changes appear in the history.

If no framework is used, prefer a smaller number of directories, like in Kingfisher Summarize or Pelican backend. For example:

├── PROJECTNAME
│   ├── migrations
│   └── static
├── COMPONENT1
├── COMPONENT2
├── docs
└── tests
    └── fixtures

Components should be logically distinct units, like apps in Django.

Packages

Packages should follow this layout, where PACKAGENAME is the name of the package:

├── PACKAGENAME
│   ├── __init__.py
│   ├── __main__.py
│   ├── commands
│   └── static
├── docs
└── tests
    └── fixtures

Note

__main__.py is executed when the package is invoked directly from the command line using the -m flag. For example:

python -m ocdskit

Note

We don’t use the src/ layout (more). In practice, we rarely encounter the problems it solves, and our use of check-manifest and test_requirements.py guard against those problems.

Modules

  • Use a single module for all models.

  • If a module defines names that are imported by only one other module, merge the modules unless:

    • It is a convention of a framework (for example, the files created by Django’s startapp command).

    • There is a divide in terms of responsibility (for example, model and view).

  • Don’t split a module only to reduce its length.

Test files

  • Put tests outside application code. Do not add tests directories inside application code.

  • Prefix filenames with test_. Do not suffix basenames with _test.

Static files

  • Don’t mix static files with Python files in the same directory.

Filename conventions

  • util for a generic module of helper functions, not utils, tools or helper.

  • exceptions for a generic module of exception classes, not errors.

  • Use verbs for commands (like add_files.py).

  • Use nouns for workers (like checker.py).

    Note

    Verbs may be used for workers if they aren’t mixed with commands.