django-upgrade-report 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_upgrade_report-0.2.0/.gitignore +8 -0
- django_upgrade_report-0.2.0/CHANGELOG.md +71 -0
- django_upgrade_report-0.2.0/CODE_OF_CONDUCT.md +83 -0
- django_upgrade_report-0.2.0/CONTRIBUTING.md +60 -0
- django_upgrade_report-0.2.0/LICENSE +21 -0
- django_upgrade_report-0.2.0/PKG-INFO +351 -0
- django_upgrade_report-0.2.0/README.md +308 -0
- django_upgrade_report-0.2.0/SECURITY.md +15 -0
- django_upgrade_report-0.2.0/action.yml +104 -0
- django_upgrade_report-0.2.0/pyproject.toml +118 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/__init__.py +9 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/__main__.py +3 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/analysis.py +1189 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/cli.py +219 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/py.typed +0 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/pypi.py +335 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/render/__init__.py +130 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/render/html.py +212 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/render/json.py +80 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/render/markdown.py +103 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/render/text.py +74 -0
- django_upgrade_report-0.2.0/src/django_upgrade_report/sources.py +1115 -0
- django_upgrade_report-0.2.0/tests/conftest.py +166 -0
- django_upgrade_report-0.2.0/tests/data/uv-forked.lock +155 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/dj-database-url.json +37 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/django-allauth.json +224 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/django-prometheus.json +172 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/django-ses.json +77 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/django.json +226 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/djangorestframework.json +170 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/mayan-edms.json +309 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/netbox.json +13 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/wagtail-grapple.json +78 -0
- django_upgrade_report-0.2.0/tests/fixtures/pypi/wagtail.json +365 -0
- django_upgrade_report-0.2.0/tests/fixtures/record.py +148 -0
- django_upgrade_report-0.2.0/tests/test_analysis.py +910 -0
- django_upgrade_report-0.2.0/tests/test_cli.py +459 -0
- django_upgrade_report-0.2.0/tests/test_integration.py +126 -0
- django_upgrade_report-0.2.0/tests/test_packaging.py +34 -0
- django_upgrade_report-0.2.0/tests/test_pypi.py +250 -0
- django_upgrade_report-0.2.0/tests/test_sources.py +1092 -0
- django_upgrade_report-0.2.0/uv.lock +342 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.2.0] - 2026-09-27
|
|
8
|
+
|
|
9
|
+
First release on PyPI.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `--target auto`, the new default: the newest LTS above your Django, or the newest release when no LTS is above it.
|
|
14
|
+
- `--from` sets the Django version you run when your requirements only give a range.
|
|
15
|
+
- The project's Python is read from `.python-version`, `uv.lock`, `pyproject.toml` or `Pipfile.lock`. The report warns when the target Django needs a newer Python.
|
|
16
|
+
- Packages from git, local paths, URLs or a private index are listed as "Not from PyPI, not checked" and their names are never sent to PyPI. `--check-private-on-pypi` looks them up anyway, for an index that mirrors PyPI. A project-wide index counts too: `--index-url` or `--no-index` in requirement files, `[tool.uv]` and PDM index settings, and the pip and uv index environment variables.
|
|
17
|
+
- Warnings when the target skips an LTS, when your Django requirement excludes the target, and when Django is not pinned.
|
|
18
|
+
- Notes when a release needs a newer patch of your current Django, or a newer version of another package you pin. Upgrades that depend on one going with Django go with Django, too.
|
|
19
|
+
- Packages marked `Development Status :: 7 - Inactive` are flagged. Packages built only on Wagtail or django CMS are included, with a note.
|
|
20
|
+
- `schema_version` and documented fields in the JSON report.
|
|
21
|
+
- Action inputs `from` and `check-private-on-pypi`, and outputs `blocked`, `upgrade`, `check` and `ready`. The action caches PyPI responses and runs on Windows runners.
|
|
22
|
+
- A release workflow that publishes to PyPI with trusted publishing and moves the `v0` tag, so `uvx django-upgrade-report` and `uses: derblub/django-upgrade-report@v0` work.
|
|
23
|
+
- Exit status 2 for every error, so it cannot be mistaken for `--fail-on`'s status 1.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- The default target was `lts`, which gave a downgrade report for projects on Django 6.0 or 6.1. `lts` now shows a health check of your version when your Django is newer.
|
|
28
|
+
- An upper bound such as `Django<6.0` only counts as support when the release came out after the target. For a target that is not released yet, only classifiers count.
|
|
29
|
+
- Unknown targets (`5.3`, `52`) and targets below your Django are an error instead of an empty report.
|
|
30
|
+
- Unpinned requirements are judged by the newest release they allow, not the newest release overall.
|
|
31
|
+
- Environment markers are evaluated for your project's Python on Linux, not for the machine running the tool, and all Django requirement lines that apply are combined.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- Exact pins such as `Django==5.2.17` were read as excluding the version they pin.
|
|
36
|
+
- A package was "Blocked" when only its newest release excluded the target, even though yours or an older one allowed it. It is now "Check manually".
|
|
37
|
+
- Only the newest 40 releases were searched, so the suggested release was often not the smallest one.
|
|
38
|
+
- Major-only classifiers such as `Framework :: Django :: 5` were ignored.
|
|
39
|
+
- uv's forked resolutions, and duplicate entries in `poetry.lock` and `pdm.lock`, used the last entry instead of the one for your Python.
|
|
40
|
+
- Pins from `-c` constraint files and `-r` includes were overwritten by later unpinned lines, and constraint-only packages were reported as dependencies. Later `pyproject.toml` tables overwrote earlier pins, and Poetry dependencies with several constraints were dropped.
|
|
41
|
+
- Requirement files with a UTF-8 BOM lost their first line, and UTF-16 files crashed. Lockfiles and TOML are read as UTF-8 whatever the locale.
|
|
42
|
+
- An empty lockfile gave an all-clear report instead of an error.
|
|
43
|
+
- `--python` reported a shadowed copy of a package installed twice, and failed on Python 3.7 and older environments.
|
|
44
|
+
- Tracebacks for unreadable files, `--python` failures, a bad `--index-url` (which printed its credentials) or `-o` into a missing directory. Missing directories are now created.
|
|
45
|
+
- Reports are written as UTF-8, so `-o` and redirected output no longer crash on Windows.
|
|
46
|
+
- Timeouts, connection resets, HTTP 429 and truncated answers from the index are retried.
|
|
47
|
+
- Ready packages hid their notes, such as "version not pinned", in text and Markdown output.
|
|
48
|
+
- An installed version missing from the index was shown as ready, without a note.
|
|
49
|
+
- The Markdown report left out packages not on the index, and `*` in version specifiers turned into emphasis.
|
|
50
|
+
- The progress counter never reached its total.
|
|
51
|
+
- The action failed on Windows runners, and a second use in one job overwrote the first JSON report.
|
|
52
|
+
- The action and CI used Node 20 actions, which GitHub runners no longer run.
|
|
53
|
+
- `--fail-on` passed when every Django-related package came from another index, as soon as one unrelated package came from PyPI.
|
|
54
|
+
|
|
55
|
+
## [0.1.0]
|
|
56
|
+
|
|
57
|
+
Preview, not published on PyPI.
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- Reads dependencies from `uv.lock`, `poetry.lock`, `pdm.lock`, `Pipfile.lock`, `requirements*.txt`, `requirements/*.txt`, `pyproject.toml` (PEP 621, dependency groups and Poetry) or an installed environment (`--python`).
|
|
62
|
+
- Sorts every Django-related package into blocked, upgrade first, upgrade together with Django, check manually and ready, and names the smallest release that declares support for the target.
|
|
63
|
+
- Targets: `lts` (default), `latest` or an explicit version such as `5.2`.
|
|
64
|
+
- Text, Markdown, JSON and self-contained HTML output.
|
|
65
|
+
- `--fail-on blocked|upgrade|check` for CI.
|
|
66
|
+
- GitHub Action that writes the report to the job summary.
|
|
67
|
+
- 24 hour cache for PyPI responses.
|
|
68
|
+
|
|
69
|
+
[Unreleased]: https://github.com/derblub/django-upgrade-report/compare/v0.2.0...HEAD
|
|
70
|
+
[0.2.0]: https://github.com/derblub/django-upgrade-report/releases/tag/v0.2.0
|
|
71
|
+
[0.1.0]: https://github.com/derblub/django-upgrade-report/commit/35e1e97
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
8
|
+
|
|
9
|
+
## Our Standards
|
|
10
|
+
|
|
11
|
+
Examples of behavior that contributes to a positive environment for our community include:
|
|
12
|
+
|
|
13
|
+
* Demonstrating empathy and kindness toward other people
|
|
14
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
15
|
+
* Giving and gracefully accepting constructive feedback
|
|
16
|
+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
|
17
|
+
* Focusing on what is best not just for us as individuals, but for the overall community
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behavior include:
|
|
20
|
+
|
|
21
|
+
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
22
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
23
|
+
* Public or private harassment
|
|
24
|
+
* Publishing others' private information, such as a physical or email address, without their explicit permission
|
|
25
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
26
|
+
|
|
27
|
+
## Enforcement Responsibilities
|
|
28
|
+
|
|
29
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
|
30
|
+
|
|
31
|
+
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
|
32
|
+
|
|
33
|
+
## Scope
|
|
34
|
+
|
|
35
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
|
36
|
+
|
|
37
|
+
## Enforcement
|
|
38
|
+
|
|
39
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [daniel@pushingpixels.at](mailto:daniel@pushingpixels.at). All complaints will be reviewed and investigated promptly and fairly.
|
|
40
|
+
|
|
41
|
+
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
|
42
|
+
|
|
43
|
+
## Enforcement Guidelines
|
|
44
|
+
|
|
45
|
+
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
|
46
|
+
|
|
47
|
+
### 1. Correction
|
|
48
|
+
|
|
49
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
|
50
|
+
|
|
51
|
+
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
|
52
|
+
|
|
53
|
+
### 2. Warning
|
|
54
|
+
|
|
55
|
+
**Community Impact**: A violation through a single incident or series of actions.
|
|
56
|
+
|
|
57
|
+
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
|
58
|
+
|
|
59
|
+
### 3. Temporary Ban
|
|
60
|
+
|
|
61
|
+
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
|
62
|
+
|
|
63
|
+
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
|
64
|
+
|
|
65
|
+
### 4. Permanent Ban
|
|
66
|
+
|
|
67
|
+
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
|
68
|
+
|
|
69
|
+
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
|
70
|
+
|
|
71
|
+
## Attribution
|
|
72
|
+
|
|
73
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
74
|
+
|
|
75
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
76
|
+
|
|
77
|
+
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
|
|
78
|
+
|
|
79
|
+
[homepage]: https://www.contributor-covenant.org
|
|
80
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
81
|
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
82
|
+
[FAQ]: https://www.contributor-covenant.org/faq
|
|
83
|
+
[translations]: https://www.contributor-covenant.org/translations
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time. Bug reports with a real `requirements.txt` or lockfile are the most useful contribution there is: most wrong verdicts come from packaging metadata nobody anticipated.
|
|
4
|
+
|
|
5
|
+
## Reporting a wrong verdict
|
|
6
|
+
|
|
7
|
+
Open an [issue](https://github.com/derblub/django-upgrade-report/issues/new/choose) with:
|
|
8
|
+
|
|
9
|
+
- the command you ran and `django-upgrade-report --version`,
|
|
10
|
+
- the package, the version you use and the target Django version,
|
|
11
|
+
- what the tool said and what you expected, ideally with a link to the package's changelog or PyPI page.
|
|
12
|
+
|
|
13
|
+
`--format json` output helps, since it includes the reason for every verdict.
|
|
14
|
+
|
|
15
|
+
## Development setup
|
|
16
|
+
|
|
17
|
+
You need [uv](https://docs.astral.sh/uv/).
|
|
18
|
+
|
|
19
|
+
```console
|
|
20
|
+
$ git clone https://github.com/derblub/django-upgrade-report
|
|
21
|
+
$ cd django-upgrade-report
|
|
22
|
+
$ uv run --group dev pytest
|
|
23
|
+
$ uv run python -m django_upgrade_report path/to/a/project
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Before you open a pull request:
|
|
27
|
+
|
|
28
|
+
```console
|
|
29
|
+
$ uv run --group dev pytest
|
|
30
|
+
$ uvx ruff check .
|
|
31
|
+
$ uvx ruff format .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The tests never touch the network. Please keep it that way. There are two package indexes in `tests/conftest.py`:
|
|
35
|
+
|
|
36
|
+
- a small in-memory index for the rules: add the releases you need to it instead of calling PyPI,
|
|
37
|
+
- real PyPI metadata recorded in `tests/fixtures/pypi/`, for the golden tests in `tests/test_analysis.py`. To add a package, add it to `CASES` in `tests/fixtures/record.py` and run `PYTHONPATH=src python3 tests/fixtures/record.py`. Re-recording changes the facts the golden tests assert, so check them against the new data.
|
|
38
|
+
|
|
39
|
+
CI also measures coverage: `uv run --group dev pytest --cov=django_upgrade_report`.
|
|
40
|
+
|
|
41
|
+
## Where things live
|
|
42
|
+
|
|
43
|
+
| File | What it does |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `src/django_upgrade_report/sources.py` | Reads lockfiles, requirement files, `pyproject.toml` and environments into `Dependency` objects, and finds the project's Python |
|
|
46
|
+
| `src/django_upgrade_report/pypi.py` | Cached client for the PyPI JSON API, with retries |
|
|
47
|
+
| `src/django_upgrade_report/analysis.py` | The target (`resolve_target()`), the verdict rules (`supports()`) and the per-package status and phase |
|
|
48
|
+
| `src/django_upgrade_report/render/` | Text, Markdown, JSON and HTML output. `render/json.py` documents the JSON fields and `schema_version` |
|
|
49
|
+
| `src/django_upgrade_report/cli.py` | Command line interface |
|
|
50
|
+
| `action.yml` | The GitHub Action |
|
|
51
|
+
|
|
52
|
+
A change to the verdict rules in `supports()` needs a test case in `tests/test_analysis.py` and an update to "How it decides" in the README.
|
|
53
|
+
|
|
54
|
+
## Pull requests
|
|
55
|
+
|
|
56
|
+
- One topic per pull request, with a test that fails without the change.
|
|
57
|
+
- Describe the user-visible change in `CHANGELOG.md` under "Unreleased".
|
|
58
|
+
- By contributing you agree that your contribution is licensed under the [MIT License](LICENSE).
|
|
59
|
+
|
|
60
|
+
Everyone taking part is expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Kurdoghlian, Pushing Pixels (https://pushingpixels.at)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-upgrade-report
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Which of your dependencies block a Django upgrade, and in which order to upgrade them.
|
|
5
|
+
Project-URL: Homepage, https://github.com/derblub/django-upgrade-report
|
|
6
|
+
Project-URL: Documentation, https://github.com/derblub/django-upgrade-report#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/derblub/django-upgrade-report
|
|
8
|
+
Project-URL: Changelog, https://github.com/derblub/django-upgrade-report/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/derblub/django-upgrade-report/issues
|
|
10
|
+
Project-URL: Pushing Pixels, https://pushingpixels.at
|
|
11
|
+
Project-URL: Django upgrade audit, https://pushingpixels.at/creates/django-upgrades
|
|
12
|
+
Author-email: Daniel Kurdoghlian <daniel@pushingpixels.at>
|
|
13
|
+
Maintainer-email: Daniel Kurdoghlian <daniel@pushingpixels.at>
|
|
14
|
+
License-Expression: MIT
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Keywords: ci,compatibility,dependencies,django,lockfile,lts,migration,requirements,upgrade
|
|
17
|
+
Classifier: Development Status :: 4 - Beta
|
|
18
|
+
Classifier: Environment :: Console
|
|
19
|
+
Classifier: Framework :: Django
|
|
20
|
+
Classifier: Framework :: Django :: 4.2
|
|
21
|
+
Classifier: Framework :: Django :: 5.0
|
|
22
|
+
Classifier: Framework :: Django :: 5.1
|
|
23
|
+
Classifier: Framework :: Django :: 5.2
|
|
24
|
+
Classifier: Framework :: Django :: 6.0
|
|
25
|
+
Classifier: Framework :: Django :: 6.1
|
|
26
|
+
Classifier: Intended Audience :: Developers
|
|
27
|
+
Classifier: Natural Language :: English
|
|
28
|
+
Classifier: Operating System :: OS Independent
|
|
29
|
+
Classifier: Programming Language :: Python :: 3
|
|
30
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
31
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
32
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
36
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
37
|
+
Classifier: Topic :: Utilities
|
|
38
|
+
Classifier: Typing :: Typed
|
|
39
|
+
Requires-Python: >=3.10
|
|
40
|
+
Requires-Dist: packaging>=23
|
|
41
|
+
Requires-Dist: tomli>=2; python_version < '3.11'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
<div align="center">
|
|
45
|
+
|
|
46
|
+
<a href="https://pushingpixels.at">
|
|
47
|
+
<picture>
|
|
48
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/derblub/django-upgrade-report/main/docs/assets/logo-dark.svg">
|
|
49
|
+
<img src="https://raw.githubusercontent.com/derblub/django-upgrade-report/main/docs/assets/logo-light.svg" alt="Pushing Pixels" width="96">
|
|
50
|
+
</picture>
|
|
51
|
+
</a>
|
|
52
|
+
|
|
53
|
+
<h1>django-upgrade-report</h1>
|
|
54
|
+
|
|
55
|
+
<p><strong>Which of your dependencies block a Django upgrade, and in which order to upgrade them.</strong></p>
|
|
56
|
+
|
|
57
|
+
<p>
|
|
58
|
+
<a href="https://github.com/derblub/django-upgrade-report/actions/workflows/ci.yml"><img src="https://github.com/derblub/django-upgrade-report/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
59
|
+
<a href="https://github.com/derblub/django-upgrade-report/actions/workflows/ci.yml"><img src="https://img.shields.io/badge/coverage-94%25-brightgreen" alt="Coverage 94%"></a>
|
|
60
|
+
<a href="https://pypi.org/project/django-upgrade-report/"><img src="https://img.shields.io/pypi/v/django-upgrade-report" alt="PyPI"></a>
|
|
61
|
+
<a href="https://pypi.org/project/django-upgrade-report/"><img src="https://img.shields.io/pypi/pyversions/django-upgrade-report" alt="Python versions"></a>
|
|
62
|
+
<a href="https://pypi.org/project/django-upgrade-report/"><img src="https://img.shields.io/pypi/frameworkversions/django/django-upgrade-report" alt="Django versions"></a>
|
|
63
|
+
<a href="https://github.com/derblub/django-upgrade-report/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License"></a>
|
|
64
|
+
<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
|
|
65
|
+
</p>
|
|
66
|
+
|
|
67
|
+
<p>
|
|
68
|
+
<a href="https://github.com/derblub/django-upgrade-report#quick-start">Quick start</a> ·
|
|
69
|
+
<a href="https://github.com/derblub/django-upgrade-report#what-the-statuses-mean">Statuses</a> ·
|
|
70
|
+
<a href="https://github.com/derblub/django-upgrade-report#usage">Usage</a> ·
|
|
71
|
+
<a href="https://github.com/derblub/django-upgrade-report#in-ci">CI</a> ·
|
|
72
|
+
<a href="https://github.com/derblub/django-upgrade-report#how-it-decides">How it decides</a> ·
|
|
73
|
+
<a href="https://github.com/derblub/django-upgrade-report#faq">FAQ</a> ·
|
|
74
|
+
<a href="https://github.com/derblub/django-upgrade-report/blob/main/CHANGELOG.md">Changelog</a>
|
|
75
|
+
</p>
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
Before you touch Django, you need to know whether the 20 to 200 packages your project depends on are ready for the new version, which of them you can upgrade today, and which have to move together with Django. Finding that out by hand means reading every changelog.
|
|
82
|
+
|
|
83
|
+
**django-upgrade-report** reads your lockfile, asks PyPI what every Django-related package declares, and gives you the upgrade plan: blockers first, then the smallest safe step for each package, in the right order.
|
|
84
|
+
|
|
85
|
+
```console
|
|
86
|
+
uvx django-upgrade-report
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
<p align="center">
|
|
90
|
+
<picture>
|
|
91
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/derblub/django-upgrade-report/main/docs/assets/report-dark.png">
|
|
92
|
+
<img src="https://raw.githubusercontent.com/derblub/django-upgrade-report/main/docs/assets/report-light.png" alt="HTML report for an upgrade from Django 4.2.7 to 5.2: 15 packages to upgrade before Django, 3 to check manually" width="820">
|
|
93
|
+
</picture>
|
|
94
|
+
</p>
|
|
95
|
+
|
|
96
|
+
## Highlights
|
|
97
|
+
|
|
98
|
+
- **Knows the order.** Separates upgrades you can ship today, on your current Django, from the ones that have to land in the same change as the Django bump. It also tells you when a release first needs a newer patch of your Django, or a newer version of another package.
|
|
99
|
+
- **Smallest step, not latest.** For every package it names the oldest release that declares support for the target, so each change stays small and reviewable.
|
|
100
|
+
- **Reads what you already have.** `uv.lock`, `poetry.lock`, `pdm.lock`, `Pipfile.lock`, `requirements*.txt`, `pyproject.toml` or an installed environment, transitive dependencies included.
|
|
101
|
+
- **Honest about uncertainty.** A missing classifier means "check manually", not "blocked". An upper bound written before the target was released is not taken as a promise. Packages without a release in two years, or marked inactive, are flagged.
|
|
102
|
+
- **Knows your Python.** Finds your project's Python version, warns when the target Django needs a newer one, and evaluates environment markers for your project, not for the machine running the tool.
|
|
103
|
+
- **Made for pipelines and for people.** Markdown for pull request summaries, versioned JSON for scripts, a self-contained HTML report to attach to a ticket, and `--fail-on` to break the build.
|
|
104
|
+
- **Your code stays put.** Only names and versions of packages that come from PyPI are sent to PyPI. Git, path and private-index packages are listed, never looked up. No account, no configuration.
|
|
105
|
+
|
|
106
|
+
## Quick start
|
|
107
|
+
|
|
108
|
+
Run it in your project directory. You need Python 3.10 or newer, but not Django and not your project's virtualenv.
|
|
109
|
+
|
|
110
|
+
```console
|
|
111
|
+
uvx django-upgrade-report # with uv
|
|
112
|
+
pipx run django-upgrade-report # with pipx
|
|
113
|
+
pip install django-upgrade-report # or install it
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
By default it picks the next sensible step for your project: the newest LTS above the Django you run, or the newest release when no LTS is above it. A project on Django 4.2 gets a report for 5.2, a project on 5.2 one for 6.1. Pick another target with `--target`:
|
|
117
|
+
|
|
118
|
+
```console
|
|
119
|
+
django-upgrade-report --target 6.1
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
<p align="center">
|
|
123
|
+
<img src="https://raw.githubusercontent.com/derblub/django-upgrade-report/main/docs/assets/terminal.png" alt="Terminal output for an upgrade from Django 5.2.7 to 6.1: django-celery-beat is blocked, four packages can be upgraded first, four need a manual check, one is ready" width="820">
|
|
124
|
+
</p>
|
|
125
|
+
|
|
126
|
+
## What the statuses mean
|
|
127
|
+
|
|
128
|
+
| Status | Meaning | What to do |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| **Blocked** | Your release and every newer one exclude the target, for example with `Django<6.1`. | Wait for a release, find a fork or replace the package. |
|
|
131
|
+
| **Upgrade first** | A newer release declares the target and still runs on your current Django. | Upgrade these one at a time, before you touch Django. |
|
|
132
|
+
| **Upgrade together with Django** | The release that declares the target has dropped your current Django, or needs another package that has. | Bump it in the same change as Django. |
|
|
133
|
+
| **Check manually** | Nothing excludes the target, but nothing declares it either. | Read the changelog or run your test suite. Usually a classifier nobody updated. |
|
|
134
|
+
| **Ready** | The version you use already declares support. | Nothing. |
|
|
135
|
+
|
|
136
|
+
The notes on a row tell you more, for example "update Django 4.2 first" when a release needs a newer patch of your current Django, "upgrade django-crispy-forms first" when it needs a newer version of another package you pin, or "newer releases exclude Django 6.1".
|
|
137
|
+
|
|
138
|
+
## Usage
|
|
139
|
+
|
|
140
|
+
```console
|
|
141
|
+
django-upgrade-report [PROJECT] [options]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
| Option | Description |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `PROJECT` | Project directory, or a single lockfile, requirements file or `pyproject.toml`. Defaults to the current directory. |
|
|
147
|
+
| `-t`, `--target` | `auto` (default), `lts` (the newest x.2 release), `latest`, or a version such as `5.2`. See [Choosing the target](#choosing-the-target). |
|
|
148
|
+
| `--from VERSION` | The Django version you run today, e.g. `4.2` or `4.2.16`, when your requirements only give a range. `4.2` means the newest 4.2 release. |
|
|
149
|
+
| `--python PATH` | Read the exact installed versions from this interpreter, e.g. `.venv/bin/python`. |
|
|
150
|
+
| `-f`, `--format` | `text` (default), `markdown`, `json` or `html`. |
|
|
151
|
+
| `-o`, `--output` | Write the report to a file instead of stdout. Missing directories are created. |
|
|
152
|
+
| `--fail-on` | Exit with status 1 when a package is `blocked`, needs an `upgrade` (or is blocked), or needs a `check` (or anything worse). |
|
|
153
|
+
| `-v`, `--verbose` | Text output only: list every ready package with its reason. The other formats always do. |
|
|
154
|
+
| `--index-url` | Base URL of an index that implements PyPI's JSON API. Default: `https://pypi.org/pypi`. |
|
|
155
|
+
| `--check-private-on-pypi` | Look up packages your project installs from another index on PyPI, too. For an index that mirrors PyPI (Artifactory, Nexus, devpi). Their names are sent to PyPI. |
|
|
156
|
+
| `--no-cache` | Do not cache PyPI responses. |
|
|
157
|
+
| `--version` | Show the version and exit. |
|
|
158
|
+
|
|
159
|
+
Responses are cached in `~/.cache/django-upgrade-report` (or `$XDG_CACHE_HOME/django-upgrade-report`): a project's release list for 24 hours, the metadata of a single release for good, since it never changes.
|
|
160
|
+
|
|
161
|
+
### Exit codes
|
|
162
|
+
|
|
163
|
+
| Code | Meaning |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| `0` | The report was written, and no package matched `--fail-on`. |
|
|
166
|
+
| `1` | A package matched `--fail-on`. |
|
|
167
|
+
| `2` | An error: no dependencies found, an unreadable file, an unknown target, the index could not be reached. Also with `--fail-on` when no dependency could be checked because they all come from another index. |
|
|
168
|
+
|
|
169
|
+
So CI can tell "packages need attention" from "the tool could not run".
|
|
170
|
+
|
|
171
|
+
### Choosing the target
|
|
172
|
+
|
|
173
|
+
| `--target` | Checks against |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| `auto` | The newest LTS above your Django, or the newest release when no LTS is above it. When you already run the newest release, a health check of it. When your Django version is unknown, the newest LTS. |
|
|
176
|
+
| `lts` | The newest x.2 release. When your Django is newer, a health check of your version instead. |
|
|
177
|
+
| `latest` | The newest release. |
|
|
178
|
+
| `5.2`, `6.1`, ... | That feature version. The next, unreleased one (6.2 today) is accepted for planning, see [How it decides](#how-it-decides). Unknown versions and versions below yours are an error. |
|
|
179
|
+
|
|
180
|
+
The report warns when the target skips an LTS (upgrading one LTS at a time is easier), when your own Django requirement excludes the target, and when the target needs a newer Python than your project uses.
|
|
181
|
+
|
|
182
|
+
### Where versions come from
|
|
183
|
+
|
|
184
|
+
The most precise source wins:
|
|
185
|
+
|
|
186
|
+
| Priority | Source | Versions | Transitive dependencies |
|
|
187
|
+
| --- | --- | --- | --- |
|
|
188
|
+
| 1 | `--python PATH` | exact, as installed | yes |
|
|
189
|
+
| 2 | `uv.lock`, `poetry.lock`, `pdm.lock`, `Pipfile.lock` | exact | yes |
|
|
190
|
+
| 3 | `requirements*.txt`, `requirements/*.txt`, `pyproject.toml` | exact when pinned with `==` | no |
|
|
191
|
+
|
|
192
|
+
Requirement files follow `-r` includes and `-c` constraint files; constraints only pin packages that are listed elsewhere. `pyproject.toml` is read as PEP 621, dependency groups and Poetry. When a lockfile holds several versions of one package for different Pythons, as uv's forked resolutions do, the one for your project's Python is used.
|
|
193
|
+
|
|
194
|
+
Unpinned requirements are judged by the newest release they allow and marked as such. Use a lockfile for exact results. When Django itself is only given as a range with an upper bound, such as `Django>=4.2,<5.0`, the newest release it allows is assumed and a warning says so. Without an upper bound the report cannot tell what can be upgraded first. In both cases, `--from` sets the version you run.
|
|
195
|
+
|
|
196
|
+
### Which Python
|
|
197
|
+
|
|
198
|
+
Environment markers such as `python_version < "3.12"` decide which requirements apply, so the tool needs your project's Python. It takes the first of:
|
|
199
|
+
|
|
200
|
+
1. the interpreter passed with `--python`,
|
|
201
|
+
2. `.python-version`,
|
|
202
|
+
3. `requires-python` in `uv.lock`,
|
|
203
|
+
4. `requires-python` in `pyproject.toml`,
|
|
204
|
+
5. the `python` dependency in Poetry's `pyproject.toml`,
|
|
205
|
+
6. `python_version` in `Pipfile.lock`.
|
|
206
|
+
|
|
207
|
+
A range counts as its lower bound. The report shows the Python it found and warns when the target Django needs a newer one, for example `Django 6.1 needs Python >=3.12, your project uses 3.11 (from .python-version)`.
|
|
208
|
+
|
|
209
|
+
Markers are evaluated for CPython on Linux, where Django apps are deployed, never for the machine running the tool. Against the target, a package is judged on the newer of your project's Python and the oldest Python the target Django supports. Against your current Django, on your project's Python, or the oldest Python your current Django supports when none was found.
|
|
210
|
+
|
|
211
|
+
### Packages not from PyPI
|
|
212
|
+
|
|
213
|
+
Packages from git, a local path, a URL or a private index are listed as "Not from PyPI, not checked", with where they come from, and their names are never sent to PyPI. This covers `git+https://...`, `-e` and local path lines in requirement files, `name @ url` requirements, git, path and URL sources in lockfiles, `--index-url` and `--no-index` in requirement files, a private default index or `no-index` in uv, Poetry, PDM or Pipenv, and the `PIP_INDEX_URL`, `UV_INDEX_URL`, `UV_DEFAULT_INDEX`, `PIP_NO_INDEX` and `UV_NO_INDEX` environment variables (lockfiles keep the index they record). Credentials in those URLs are removed before anything is shown.
|
|
214
|
+
|
|
215
|
+
To check packages from a private index, point `--index-url` at its PyPI JSON API. If the index only mirrors PyPI, pass `--check-private-on-pypi` instead. Packages the index does not know at all are listed as "Not on the package index".
|
|
216
|
+
|
|
217
|
+
## In CI
|
|
218
|
+
|
|
219
|
+
### GitHub Actions
|
|
220
|
+
|
|
221
|
+
The action writes the Markdown report to the job summary, exposes the counts as outputs, and can fail the job:
|
|
222
|
+
|
|
223
|
+
```yaml
|
|
224
|
+
- uses: actions/checkout@v7
|
|
225
|
+
- uses: derblub/django-upgrade-report@v0
|
|
226
|
+
id: django
|
|
227
|
+
with:
|
|
228
|
+
fail-on: blocked # optional: blocked, upgrade or check
|
|
229
|
+
- run: echo "${{ steps.django.outputs.blocked }} blocked, ${{ steps.django.outputs.upgrade }} to upgrade"
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
| Input | Default | Description |
|
|
233
|
+
| --- | --- | --- |
|
|
234
|
+
| `path` | `.` | Project directory with a lockfile, `requirements*.txt` or `pyproject.toml`. |
|
|
235
|
+
| `target` | `auto` | `auto`, `lts`, `latest` or a version such as `6.1`. |
|
|
236
|
+
| `from` | | The Django version you run today, when your requirements only give a range. Empty reads it from the project. |
|
|
237
|
+
| `fail-on` | | `blocked`, `upgrade` or `check`. Empty never fails the step because of a package. |
|
|
238
|
+
| `check-private-on-pypi` | `false` | `true` looks up packages from another index on PyPI, too. |
|
|
239
|
+
|
|
240
|
+
| Output | Description |
|
|
241
|
+
| --- | --- |
|
|
242
|
+
| `report` | Path to the JSON report, unique per use of the action. |
|
|
243
|
+
| `blocked`, `upgrade`, `check`, `ready` | Number of packages with that status. |
|
|
244
|
+
|
|
245
|
+
The action brings its own Python, runs on Linux and Windows runners, and caches PyPI responses between runs. The summary and the outputs are written before `fail-on` fails the step.
|
|
246
|
+
|
|
247
|
+
### GitLab CI
|
|
248
|
+
|
|
249
|
+
```yaml
|
|
250
|
+
django-upgrade-report:
|
|
251
|
+
image: ghcr.io/astral-sh/uv:python3.12-bookworm-slim
|
|
252
|
+
script:
|
|
253
|
+
- uvx django-upgrade-report --format html --output upgrade-report.html
|
|
254
|
+
- uvx django-upgrade-report --fail-on blocked
|
|
255
|
+
artifacts:
|
|
256
|
+
when: always
|
|
257
|
+
paths: [upgrade-report.html]
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Anywhere else
|
|
261
|
+
|
|
262
|
+
```console
|
|
263
|
+
django-upgrade-report --format markdown >> "$GITHUB_STEP_SUMMARY"
|
|
264
|
+
django-upgrade-report --format json --output upgrade-report.json
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The JSON report carries a `schema_version`: adding a field keeps it, renaming, removing or retyping one bumps it. The fields are documented in [`render/json.py`](https://github.com/derblub/django-upgrade-report/blob/main/src/django_upgrade_report/render/json.py).
|
|
268
|
+
|
|
269
|
+
## How it decides
|
|
270
|
+
|
|
271
|
+
For every release the tool looks at two pieces of metadata that maintainers publish on PyPI: the `Framework :: Django :: X.Y` classifiers and the `Django` requirement. For a target version, in this order:
|
|
272
|
+
|
|
273
|
+
1. A requirement that excludes every release of the target means **no**. Each patch release counts, so `Django==5.2.17` or `Django>=5.2.3,<5.2.8` allow 5.2. Requirements that only apply to an optional extra are ignored. Lines with environment markers count when they apply to your Python ([see above](#which-python)), and all lines that apply are combined.
|
|
274
|
+
2. A `Framework :: Django :: 5.2` classifier means **yes**.
|
|
275
|
+
3. An upper bound that allows the target, such as `Django>=4.2,<6.0` or an exact pin, means **yes**, but only when the release was uploaded on or after the day the target came out. A bound written before that is a guess, not a promise: Wagtail 6.3 allows `Django<6.0` but came out before Django 5.2, and only Wagtail 6.3.4 added 5.2 support.
|
|
276
|
+
4. Everything else means **not declared**: classifiers that stop at an older version or start at a newer one, a major-only classifier such as `Framework :: Django :: 5`, a lower bound without an upper one, or no information at all. That is a question, not a blocker: classifiers often lag behind releases.
|
|
277
|
+
|
|
278
|
+
For a target that is not released yet, such as 6.2 today, only classifiers count, and the report says so. An upper bound like `<7.0` says nothing about a version nobody could test.
|
|
279
|
+
|
|
280
|
+
From these verdicts, per package:
|
|
281
|
+
|
|
282
|
+
- **Ready** when the version you use says yes.
|
|
283
|
+
- **Upgrade** when a newer release says yes. The report names the oldest one. It goes **first** when that release still runs on your current Django. A release that needs `Django>=4.2.16` while you run 4.2.7 still goes first, with a note to update Django 4.2 first. It goes **together with Django** when the release excludes your whole Django series, declares only newer Django versions, or needs a newer version of another package you pin that has itself dropped your Django.
|
|
284
|
+
- **Check manually** when no release says yes, but yours or a newer one is not excluded.
|
|
285
|
+
- **Blocked** when your release and every newer one exclude the target.
|
|
286
|
+
|
|
287
|
+
A package counts as Django-related when it depends on Django or has a `Framework :: Django` classifier. Packages that only depend on Wagtail or django CMS are included too, with a note to check them against that framework. Everything else is skipped.
|
|
288
|
+
|
|
289
|
+
> [!NOTE]
|
|
290
|
+
> The report shows what maintainers declare, not whether your tests pass. Use it to plan the upgrade, then run [django-upgrade](https://github.com/adamchainz/django-upgrade) on your code and your test suite with `python -W error::DeprecationWarning`.
|
|
291
|
+
|
|
292
|
+
## FAQ
|
|
293
|
+
|
|
294
|
+
<details>
|
|
295
|
+
<summary><strong>Does it send my code anywhere?</strong></summary>
|
|
296
|
+
|
|
297
|
+
No. It reads your lockfile or requirement files locally and sends only names and versions of packages that come from PyPI to the package index, PyPI by default. Packages from git, local paths or a private index are never looked up unless you ask for it. It does not import your project and does not need Django installed.
|
|
298
|
+
</details>
|
|
299
|
+
|
|
300
|
+
<details>
|
|
301
|
+
<summary><strong>Why are so many packages "check manually"?</strong></summary>
|
|
302
|
+
|
|
303
|
+
Many maintainers forget to add the classifier for a new Django version, or only add it with the next release. The tool refuses to guess. Packages that are really incompatible almost always say so with an upper bound, and those show up as blocked.
|
|
304
|
+
</details>
|
|
305
|
+
|
|
306
|
+
<details>
|
|
307
|
+
<summary><strong>What about private packages?</strong></summary>
|
|
308
|
+
|
|
309
|
+
Packages your project installs from git, a path or a private index are listed as "Not from PyPI, not checked" and otherwise ignored. If your private index implements PyPI's JSON API, point `--index-url` at it. If it mirrors PyPI, pass `--check-private-on-pypi`. See [Packages not from PyPI](#packages-not-from-pypi).
|
|
310
|
+
</details>
|
|
311
|
+
|
|
312
|
+
<details>
|
|
313
|
+
<summary><strong>How is this different from Dependabot or Renovate?</strong></summary>
|
|
314
|
+
|
|
315
|
+
They bump versions one package at a time. They do not know which release is the first one to support the Django version you are heading for, or which upgrades have to wait for Django. Use this tool to plan, and let them open the pull requests.
|
|
316
|
+
</details>
|
|
317
|
+
|
|
318
|
+
<details>
|
|
319
|
+
<summary><strong>How is this different from django-upgrade?</strong></summary>
|
|
320
|
+
|
|
321
|
+
[django-upgrade](https://github.com/adamchainz/django-upgrade) rewrites *your* code for a new Django version. django-upgrade-report looks at your *dependencies*. You want both.
|
|
322
|
+
</details>
|
|
323
|
+
|
|
324
|
+
## Related projects
|
|
325
|
+
|
|
326
|
+
| Project | What it does |
|
|
327
|
+
| --- | --- |
|
|
328
|
+
| [django-upgrade](https://github.com/adamchainz/django-upgrade) | Rewrites your code for new Django versions. |
|
|
329
|
+
| [Django Packages readiness](https://djangopackages.org/readiness/) | Shows compatibility per package on the web. |
|
|
330
|
+
| [Django's upgrade guide](https://docs.djangoproject.com/en/stable/howto/upgrade-version/) | The official checklist for an upgrade. |
|
|
331
|
+
|
|
332
|
+
## Contributing
|
|
333
|
+
|
|
334
|
+
Bug reports with a real lockfile are the most useful contribution. See [CONTRIBUTING.md](https://github.com/derblub/django-upgrade-report/blob/main/CONTRIBUTING.md) for the development setup, and the [Code of Conduct](https://github.com/derblub/django-upgrade-report/blob/main/CODE_OF_CONDUCT.md). Security issues go through [SECURITY.md](https://github.com/derblub/django-upgrade-report/blob/main/SECURITY.md).
|
|
335
|
+
|
|
336
|
+
## License
|
|
337
|
+
|
|
338
|
+
[MIT](https://github.com/derblub/django-upgrade-report/blob/main/LICENSE) © Daniel Kurdoghlian, Pushing Pixels
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
<div align="center">
|
|
343
|
+
<a href="https://pushingpixels.at">
|
|
344
|
+
<picture>
|
|
345
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/derblub/django-upgrade-report/main/docs/assets/pushing-pixels-dark.svg">
|
|
346
|
+
<img src="https://raw.githubusercontent.com/derblub/django-upgrade-report/main/docs/assets/pushing-pixels-light.svg" alt="Pushing Pixels" width="320">
|
|
347
|
+
</picture>
|
|
348
|
+
</a>
|
|
349
|
+
<p>Built and maintained by <a href="https://pushingpixels.at">Daniel Kurdoghlian</a> at <a href="https://pushingpixels.at">Pushing Pixels</a> in Vienna.<br>
|
|
350
|
+
Planning a larger upgrade? I do <a href="https://pushingpixels.at/creates/django-upgrades">fixed-price Django upgrade audits</a>.</p>
|
|
351
|
+
</div>
|