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. Although a single blog post and a few passionate developers have popularized the idea, 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:

    • The module is a convention of a framework (for example, the files created by the startapp command in Django).

    • 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.