Skip to content

Conversation

@intgr
Copy link
Contributor

@intgr intgr commented Aug 4, 2025

What was done

I and @CodingWithSaksham adapted djangorestframework-stubs to the uv package manager, like django-stubs.

  • Using build backend uv_build -- as opposed to hatchling which is used by django-stubs
  • setup.py and setup.cfg migrated into pyproject.toml
    • Removed obsolete flake8 config.
  • requirements.txt merged into pyproject.toml
  • pytest.ini merged into pyproject.toml
  • GitHub test.yml workflows
    • Using astral-sh/setup-uv@v6 to install uv & Python
    • Converted to use uv run & other uv commands.
    • New check to ensure uv.lock is up to date
  • No longer depending on setuptools -- closes Update setuptools requirement from <79.0.0 to <81.0.0 #761

Related django-stubs PRs:

@intgr
Copy link
Contributor Author

intgr commented Aug 14, 2025

@UnknownPlatypus would you be interested in looking into this?

@UnknownPlatypus
Copy link

@intgr probably not until next week but I can have a look yes 👍

@CodingWithSaksham
Copy link
Contributor

I can take a look after in October when I am free. I don't have much experience with uv though.

@CodingWithSaksham
Copy link
Contributor

I have made progress with this but the tests keep failing. I have tried everything that I could. Here is a sample of the error code

E   pytest_mypy_plugins.utils.TypecheckAssertionError: Output is not expected: 
E   Actual:
E     main:1: error: Skipping analyzing "rest_framework.permissions": module is installed, but missing library stubs or py.typed marker  [import-untyped] (diff)
E     main:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports (diff)
E     main:2: error: Skipping analyzing "rest_framework.decorators": module is installed, but missing library stubs or py.typed marker  [import-untyped] (diff)
E     main:9: error: Unsupported operand type for ~ ("type[Permission]")  [operator] (diff)
E   Expected:
E     (empty)

Every test is giving nearly the same error but the line

E Actual:
E     main:1: error: Skipping analyzing "rest_framework.permissions": module is installed, but missing library stubs or py.typed marker  [import-untyped] (diff)

is repeated in every one, even though I have added a py.typed file in rest_framework-stubs directory.

I have configured pyproject.toml with this for mypy to use

[tool.mypy]
mypy_path = ["rest_framework-stubs"]
allow_redefinition = true
check_untyped_defs = true
incremental = true
strict_optional = false
show_traceback = true
warn_redundant_casts = true
warn_unused_configs = true
warn_unreachable = true
disallow_untyped_defs = true
namespace_packages = true
disable_error_code = "empty-body"
show_error_codes = false
plugins = ["mypy_django_plugin.main", "mypy_drf_plugin.main"]

Could you please guide me with this?

@intgr
Copy link
Contributor Author

intgr commented Sep 19, 2025

@CodingWithSaksham Thanks! Have you pushed the changes to some public branch where I could take a look?

I couldn't find it at https://github.com/CodingWithSaksham/djangorestframework-stubs/branches

@CodingWithSaksham
Copy link
Contributor

Haven't pushed it yet! Will push it today for you to take a look at!

@CodingWithSaksham
Copy link
Contributor

Pushed the code! @intgr
Here's the repo link!

https://github.com/CodingWithSaksham/djangorestframework-stubs/tree/use-uv

@intgr intgr force-pushed the use-uv branch 3 times, most recently from dc8516b to 0fcf467 Compare September 20, 2025 15:18
@intgr intgr marked this pull request as ready for review September 20, 2025 15:23
@intgr
Copy link
Contributor Author

intgr commented Sep 20, 2025

@CodingWithSaksham Thanks! I took your branch and managed to make it build successfully with some changes.

I lost track of exactly who made what changes, is it OK if I credit you with a Co-authored-by: commit message tag?

  • Switching from hatchling build system to uv's own uv_build seemed to solve the main issue.
  • Configuring mypy in pyproject.toml caused configuration to be ignored by pytest_mypy_plugins -- moved it back into mypy.ini for now. This migration can be done separately.
  • Updated all dependency versions to match those in latest master branch.

@CodingWithSaksham
Copy link
Contributor

I am absolutely fine with this! Thanks for the help!

@intgr intgr changed the title [WIP] Use 'uv' package manager Switch to uv to manage dev dependencies Sep 20, 2025
- name: Run tests
# Suppress errors from other packages due to https://github.com/typeddjango/pytest-mypy-plugins/issues/134
run: pytest --mypy-only-local-stub
run: uv run pytest
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--mypy-only-local-stub moved to pyproject.toml pytest config.

@intgr intgr requested review from Copilot and sobolevn September 20, 2025 16:55
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR migrates the djangorestframework-stubs project from using setuptools to the uv package manager for build and dependency management, following the same pattern applied to django-stubs.

Key changes:

  • Adopts uv_build as the build backend instead of setuptools
  • Consolidates configuration files into pyproject.toml
  • Updates GitHub workflows to use uv commands throughout the CI pipeline

Reviewed Changes

Copilot reviewed 7 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
setup.py Removes entire setuptools-based configuration file
setup.cfg Removes flake8 configuration and metadata settings
pytest.ini Removes pytest configuration (moved to pyproject.toml)
pyproject.toml Adds comprehensive project configuration including dependencies, build settings, and tool configurations
CONTRIBUTING.md Updates development setup instructions to use uv
.github/workflows/test.yml Converts CI pipeline to use uv commands and setup-uv action
.editorconfig Adds TOML file formatting configuration

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +77 to +78
"--mypy-only-local-stub",
"--mypy-ini-file=mypy.ini"
Copy link

Copilot AI Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mypy configuration reference should be updated to use pyproject.toml instead of mypy.ini since the project is consolidating configurations. Consider migrating mypy settings to [tool.mypy] in this file.

Suggested change
"--mypy-only-local-stub",
"--mypy-ini-file=mypy.ini"
"--mypy-only-local-stub"

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@intgr intgr Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migrating mypy.ini turned out to be problematic. Maybe later.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this previously, it made none of the tests pass. We need to approach this carefully then.

Copy link
Contributor

@CodingWithSaksham CodingWithSaksham Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated my code to use uv-build instead of hatch and 29 out of the 36 test cases are failing!

Seems like pytest is unable to find

disable_error_code = ["empty-body"]
enable_error_code = ["ignore-without-code"]

when written in pyproject.toml

@intgr
Copy link
Contributor Author

intgr commented Sep 21, 2025

I removed py.typed file also. Stubs-only packages don't need to include py.typed. This file is meant for ordinary .py packages that already include embedded type hints.

@intgr intgr force-pushed the use-uv branch 2 times, most recently from 658f540 to a60135d Compare September 21, 2025 11:09
* Using build backend `uv_build` -- as opposed to `hatchling` which is used by `django-stubs`
* `setup.py` and `setup.cfg` migrated into `pyproject.toml`
  * Removed obsolete flake8 config.
* `requirements.txt` merged into `pyproject.toml`
* `pytest.ini` merged into `pyproject.toml`
* GitHub `test.yml` workflows
  * Using `astral-sh/setup-uv@v6` to install uv & Python
  * Converted to use `uv run` & other `uv` commands.
  * New check to ensure `uv.lock` is up to date
* No longer depending on `setuptools`

Co-authored-by: CodingWithSaksham <[email protected]>
[[package]]
name = "django-stubs"
version = "5.2.5"
source = { git = "https://github.com/typeddjango/django-stubs#f0419144b6dcdf44198b3be5f6994194ab6a94a5" }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I realized is that uv.lock now also freezes the django-stubs repo commit & it won't update automatically. So this PR as-is would prevent finding out when django-stubs changes have broken djangofestframework-stubs. That would be bad.

Options:

  1. Add uv lock --upgrade-package=django-stubs --upgrade-package=django-stubs-ext to workflows, which would restore the status quo: if a breaking django-stubs change is made, it will break our workflows without clear indication that was the cause. That was never ideal, this would be simplest for now.
  2. Maybe teach @dependabot to update this. That would cause a lot of PRs & noise though, every time there's a commit to django-stubs. I would prefer not.
  3. Ideally we would test every master build with latest django-stubs & only open a PR when breakage is detected. But I'm not sure how to set that up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the 3rd one, we could make a cron job or have django-stubs make a release webhook

The GitHub action will take the new django-stubs and run our tests against it, if it fails we can open a PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also a little hesitant about complex CI configurations; if something fails, debugging them can be a PITA. Perhaps there are more alternatives that I didn't consider.

Copy link

@UnknownPlatypus UnknownPlatypus Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we would test every master build with latest django-stubs & only open a PR when breakage is detected. But I'm not sure how to set that up.

We can install django-stubs@master in ci (I attempted that for mypy in django-stubs ) or could setup a daily ci job ( see this ruff daily fuzzing job for ex)

I think it depend on when you want to ensure latest django-stubs works. But I'm not a big fan of random ci jobs failing because it gives bad signals to contributors that have to understand it might not be their code the issue

Copy link
Contributor

@CodingWithSaksham CodingWithSaksham Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it depend on when you want to ensure latest django-stubs works. But I'm not a big fan of random ci jobs failing because it gives bad signals to contributors that have to understand it might not be their code the issue

I completely agree with this! Even as a new contributor, I would hate to see a random documentation-only PR fail just because django-stubs released something that broke compatibility. That kind of noise can be discouraging.

In the end, whenever CI fails we really only have two options to check:

  • Did the contributor’s change break it?

  • Or did a new django-stubs release break it?

Maybe keeping it this simple is fine for now, rather than adding more complex CI logic that might be harder to debug.

Copy link
Contributor Author

@intgr intgr Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option would be to use Mend Renovate bot in the following way:

  • Perform "lock file maintenance" periodically -- which updates all unlocked dependencies in uv.lock.
  • Enable "auto-merge" -- it creates a branch, waits for branch CI to complete. If the CI succeeds, then it will auto-merge without a PR. It only opens a PR if the CI failed. This would prevent much of the "noise" aspect that I described.

Of course it's yet another tool to manage, but better than creating a custom workflow ourselves. I've been using it in multiple projects (open source & proprietary) and had good experience with it.

AFAIK @dependabot can't be configured to behave this way, but correct me if I'm wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sobolevn I've requested to enable the Renovate app in this repo.

Copy link
Contributor Author

@intgr intgr Sep 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@intgr
Copy link
Contributor Author

intgr commented Sep 27, 2025

I would like to merge this, but I haven't received any approvals.

The follow-up about updating unpinned dependencies will be dealt with in #832.

@UnknownPlatypus UnknownPlatypus self-requested a review September 28, 2025 15:19
Copy link

@UnknownPlatypus UnknownPlatypus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good for me, thanks for the work on this!

@sobolevn
Copy link
Member

sobolevn commented Sep 28, 2025

Done. https://developer.mend.io/github/typeddjango

@intgr intgr merged commit e51cc05 into typeddjango:master Sep 28, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

4 participants