Skip to main content

Automatically upgrade your Django projects.

Project description

https://img.shields.io/github/workflow/status/adamchainz/django-upgrade/CI/main?style=for-the-badge https://img.shields.io/codecov/c/github/adamchainz/django-upgrade/main?style=for-the-badge https://img.shields.io/pypi/v/django-upgrade.svg?style=for-the-badge https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge pre-commit

Automatically upgrade your Django projects.

Installation

Use pip:

python -m pip install django-upgrade

Python 3.8 to 3.9 supported.

Or with pre-commit in the repos section of your .pre-commit-config.yaml file (docs):

-   repo: https://github.com/adamchainz/django-upgrade
    rev: ''  # replace with latest tag on GitHub
    hooks:
    -   id: django-upgrade
        args: [--target-version, "3.2"]   # Replace with Django version

Works best before any reformatters such as isort or Black.


Are your tests slow? Check out my book Speed Up Your Django Tests which covers loads of best practices so you can write faster, more accurate tests.


Usage

django-upgrade is a commandline tool that rewrites files in place. Pass your Django version as <major>.<minor> with --target-version and the fixers will rewrite code not to trigger DeprecationWarning on that version of Django. For example:

django-upgrade --target-version 3.2 example/core/models.py example/settings.py

For more on usage run django-upgrade --help. The full list of fixers is below.

History

django-codemod is a pre-existing, more complete Django auto-upgrade tool, written by Bruno Alla. Unfortunately its underlying library LibCST is particularly slow, making it annoying to run django-codemod on every commit and in CI. Additionally LibCST only advertises support up to Python 3.8 (at time of writing).

django-upgrade is an experiment in reimplementing such a tool using the same techniques as the fantastic pyupgrade. The tool leans on the standard library’s ast and tokenize modules, the latter via the tokenize-rt wrapper. This means it will always be fast and support the latest versions of Python.

For a quick benchmark: running django-codemod against a medium Django repository with 153k lines of Python takes 133 seconds. pyupgrade and django-upgrade both take less than 0.5 seconds.

Fixers

Django 2.2

Based on the Django 2.2 release notes.

QuerySetPaginator

Rewrites depreceated alias django.core.paginator.QuerySetPaginator to Paginator.

-from django.core.paginator import QuerySetPaginator
+from django.core.paginator import Paginator

-QuerySetPaginator(...)
+Paginator(...)

FixedOffset

Rewrites deprecated class FixedOffset(x, y)) to timezone(timedelta(minutes=x), y)

Known limitation: this fixer will leave code broken with an ImportError if FixedOffset is called with only *args or **kwargs.

-from django.utils.timezone import FixedOffset
-FixedOffset(120, "Super time")
+from datetime import timedelta, timezone
+timezone(timedelta(minutes=120), "Super time")

Django 3.0

Based on the Django 3.0 release notes.

django.utils.encoding aliases

Rewrites smart_text() to smart_str(), and force_text() to force_str().

-from django.utils.encoding import force_text, smart_text
+from django.utils.encoding import force_str, smart_str


-force_text("yada")
-smart_text("yada")
+force_str("yada")
+smart_str("yada")

Django 3.1

Based on the Django 3.1 release notes.

JSONField

Rewrites imports of JSONField and related transform classes from those in django.contrib.postgres to the new all-database versions.

-from django.contrib.postgres.fields import JSONField
+from django.db.models import JSONField

PASSWORD_RESET_TIMEOUT_DAYS

Rewrites the setting PASSWORD_RESET_TIMEOUT_DAYS to PASSWORD_RESET_TIMEOUT, adding the multiplication by the number of seconds in a day.

Settings files are heuristically detected as modules with the whole word “settings” somewhere in their path. For example myproject/settings.py or myproject/settings/production.py.

-PASSWORD_RESET_TIMEOUT_DAYS = 4
+PASSWORD_RESET_TIMEOUT = 60 * 60 * 24 * 4

Signal

Removes the deprecated documentation-only providing_args argument.

 from django.dispatch import Signal
-my_cool_signal = Signal(providing_args=["documented", "arg"])
+my_cool_signal = Signal()

get_random_string

Injects the now-required length argument, with its previous default 12.

 from django.utils.crypto import get_random_string
-key = get_random_string(allowed_chars="01234567899abcdef")
+key = get_random_string(length=12, allowed_chars="01234567899abcdef")

Django 3.2

Based on the Django 3.2 release notes.

EmailValidator

Rewrites keyword arguments to their new names: whitelist to allowlist, and domain_whitelist to domain_allowlist.

 from django.core.validators import EmailValidator

-EmailValidator(whitelist=["example.com"])
+EmailValidator(allowlist=["example.com"])
-EmailValidator(domain_whitelist=["example.org"])
+EmailValidator(domain_allowlist=["example.org"])

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-upgrade-1.1.0.tar.gz (15.4 kB view hashes)

Uploaded Source

Built Distribution

django_upgrade-1.1.0-py3-none-any.whl (17.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