Skip to main content

Django typing helper

Project description

django-autotyping

Automatically add type hints for Django powered applications.

To understand the purpose of this library, you can refer to this article.

django-autotyping is built with LibCST.

Python versions PyPI version Ruff

[!WARNING]
This project is still work in progress.

Installation

Through pip:

pip install django-autotyping

Usage

django-autotyping is usable in two ways:

  • As a Django development application.
  • As a linter that will automatically apply changes to your code.

Django application - dynamic stub files

django-autotyping can generate custom dynamic stubs for your application:

  • Add django_autotyping to your INSTALLED_APPS.
  • In your configuration, set AUTOTYPING_STUBS_DIR to a directory where local stubs should live. By default, pyright looks for the directory typings/. For mypy, you will have to configure the mypy_path value (or use the MYPY_PATH environment variable).
  • Optionally, you can disable specific rules by setting AUTOTYPING_DISABLED_RULES.
  • Install django-stubs into your environment.

Stubs will be generated when the post_migrate signal is emitted (you can still run the migrate command even if no migrations are to be applied).

Available rules

Add type hints to related fields (DJAS001)

A codemod that will add overloads to the __init__ methods of related fields.

This codemod is meant to be applied on the django-stubs/db/models/fields/related.pyi stub file.

class ForeignKey(ForeignObject[_ST, _GT]):
    # For each model, will add two overloads:
    # - 1st: `null: Literal[True]`, which will parametrize `ForeignKey` get types as `Optional`.
    # - 2nd: `null: Literal[False] = ...` (the default).
    # `to` is annotated as a `Literal`, with two values: {app_label}.{model_name} and {model_name}.
    # If two models from different apps have the same name, only the first form will be available.
    @overload
    def __init__(
        self: ForeignKey[MyModel | None, MyModel | None],
        to: Literal["MyModel", "myapp.MyModel"],
        ...
    ) -> None: ...

Add type hints to Manager and QuerySet methods (DJAS002)

[!WARNING]
This rule is still in progress, and waiting on some Python typing features to land.

Linter - automatic codemods

django-autotyping can be also used as a CLI program. Running the CLI will apply explicit annotations to your code.

usage: Add type hints to your models for better auto-completion.

positional arguments:
  path                  Path to the directory containing the Django application. This directory should contain your `manage.py` file.

options:
  -h, --help            show this help message and exit
  --settings-module SETTINGS_MODULE
                        Value of the `DJANGO_SETTINGS_MODULE` environment variable (a dotted Python path).
  --diff                Show diff instead of applying changes to existing files.
  --disable [{DJA001} ...]
                        Rules to be disabled.
  --type-checking-block
                        Whether newly added imports should be in an `if TYPE_CHECKING` block (avoids circular imports).
  --assume-class-getitem
                        Whether generic classes in stubs files but not at runtime should be assumed to have a `__class_getitem__` method. This can be
                        achieved by using `django-stubs-ext` or manually.

Rules

Add type hints to forward relations (DJA001)

All subclasses of RelatedField will be taken into account.

from typing import TYPE_CHECKING

from django.db import models

# Model is imported in an `if TYPE_CHECKING` block if `--type-checking-block` is used.
if TYPE_CHECKING:
    # Related model is imported from the corresponding apps models module:
    from myproject.reporters.models import Reporter


class Article(models.Model):
    # If the field supports `__class_getitem__` at runtime, it is parametrized directly:
    reporter = models.ForeignKey["Reporter"](
        "reporters.Reporter",
        on_delete=models.CASCADE,
    )

    # Otherwise, an explicit annotation is used. No unnecessary import if model is in the same file.
    article_version: "models.OneToOneField[ArticleVersion]" = models.OneToOneField(
        "ArticleVersion",
        on_delete=models.CASCADE,
    )

[!NOTE]
As of today, generated type hints will only play well with django-types. django-stubs requires a type for both the __set__ and __get__ types. Instead, it is recommended to use the corresponding dynamic stub rule (DJAS001).

Add type hints for reverse relationships (DJA002)

[!WARNING]
This rule is still in progress.

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

django-autotyping-0.1.0.tar.gz (21.4 kB view hashes)

Uploaded Source

Built Distribution

django_autotyping-0.1.0-py3-none-any.whl (26.9 kB view hashes)

Uploaded Python 3

Supported by

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