Skip to content

refactor: migrate from poetry to uv#1453

Open
omercnet wants to merge 4 commits intomainfrom
feat/uv
Open

refactor: migrate from poetry to uv#1453
omercnet wants to merge 4 commits intomainfrom
feat/uv

Conversation

@omercnet
Copy link
Copy Markdown
Member

@omercnet omercnet commented May 3, 2026

Summary

Completes the migration of build, lock, lint, format, and CI tooling from poetry / tox / black / isort / flake8 / pyupgrade to uv + ruff.

What changed

Build & lockfile

  • uv_build backend, uv.lock as the source of truth
  • Removes poetry.lock, requirements.txt, tox.ini
  • Wheel still bundles LICENSE (via PEP 639 license-files = ["LICENSE"])

Lint & format (single tool: ruff)

  • ruff replaces flake8 + flake8-pyproject + flake8-bugbear + isort + black + pyupgrade + pep8-naming
  • Rule families enabled: E, W, F, I, B, N, UP
  • Per-file ignores documented in pyproject.toml for intentional patterns (camelCase API params in descope/management/, blind exception checks in tests/**)
  • requires-python = ">=3.9,<4.0" → PEP 585/604 rewrite rules disabled (UP006/007/035/045/046/047) since runtime support is still 3.9
  • All sources reformatted by ruff format (mechanical)

pre-commit

  • Drop sync_with_poetry, python-poetry/poetry, poetry-plugin-export, tox-ini-fmt, flake8, isort, black, pyupgrade
  • Add astral-sh/uv-pre-commit (uv-lock hook) and astral-sh/ruff-pre-commit (ruff-check --fix + ruff-format)
  • Keep gitleaks, conventional-pre-commit, validate_manifest, pre-commit-hooks basics, local print check
  • Move pylic to CI lint job (in pre-commit's isolated env it couldn't see project deps)

CI (.github/workflows/ci.yml)

  • New lint job: ruff check . + ruff format --check . + mypy descope tests samples + pylic check
  • build matrix uses astral-sh/setup-uv + uv sync --all-extras --locked + uv run pytest
  • Matrix expanded to include Python 3.14
  • done aggregator now runs on push/schedule even when PR-only jobs are skipped (if: always() && !cancelled() && !contains(needs.*.result, 'failure'))

Release (.github/workflows/release-please.yml)

  • uv build + uv publish --trusted-publishing always
  • Drops descope/.github poetry actions and pypa/gh-action-pypi-publish
  • release-please-config.json updated to use $.project.version (PEP 621)

Docker

  • Multi-stage Dockerfile using ghcr.io/astral-sh/uv:0.11.8 (pinned)
  • Runs as non-root app user (uid/gid 1001)
  • LICENSE copied to builder so project.license-files glob resolves

Misc

  • VSCode: recommend charliermarsh.ruff extension; drop black/isort/flake8 extension recommendations
  • README: contributor section uses uv sync / uv run pytest / uv run ruff …
  • .gitignore: adds .ruff_cache/, uv-*.lock, .nomadworks/
  • pytest: conditional pin (>=9.0.3 on 3.10+, ==8.3.5 on 3.9)

User-facing wheel diff (1.13.0 poetry-built vs uv-built)

Poetry (PyPI) uv (this PR)
Module file count 41 41 (identical)
Provides-Extra: flask
Flask extra dep Flask (>=2) flask>=2
LICENSE in wheel ✓ (PEP 639)
py.typed marker
Generator (WHEEL) poetry-core 2.3.2 uv 0.11.8

pip install descope[Flask] resolves identically; PEP 503 normalization makes Flaskflask interchangeable.

Verification

  • uv run ruff check . → clean
  • uv run ruff format --check . → clean
  • uv run mypy descope tests samples → no issues (107 files)
  • uv run --with pylic pylic check → ✨ All licenses ok ✨
  • uv run pytest tests → 451 passed, 1 conditional skip (pre-existing), 98% coverage
  • All Python versions tested locally: 3.9 / 3.10 / 3.11 / 3.12 / 3.13 / 3.14
  • uv build → wheel + sdist with LICENSE bundled
  • uv publish --dry-run → tool path resolves
  • docker build . → builds clean, runs as UID 1001 (non-root)
  • pre-commit run --all-files → all hooks pass

Note on Snyk

The security/snyk check flags pre-existing dev-only CVEs (pytest 8.3.5 tmpdir, filelock 3.19.1 TOCTOU) that:

  • Are tied exclusively to the Python 3.9 path (this PR pins patched versions on 3.10+)
  • Were already present on main before this PR
  • Are not exploitable in isolated CI runners or local dev (require malicious local users on shared /tmp)

These will be resolved when Python 3.9 is dropped (it reached EOL October 2025).

Copilot AI review requested due to automatic review settings May 3, 2026 10:59
@shuni-bot-dev
Copy link
Copy Markdown

shuni-bot-dev Bot commented May 3, 2026

🐕 Review complete — View session on Shuni Portal 🐾

omercnet and others added 3 commits May 3, 2026 11:00
Flask 3.1 removed the long-deprecated _request_ctx_stack, causing the
mypy 'type' tox env (only run on 3.12/3.13) to fail with:
  samples/magiclink_web_sample_app.py:1: error: Module "flask" has
  no attribute "_request_ctx_stack"  [attr-defined]

The library code already uses flask.g; align the sample with it.

Also clean up tox.ini: drop py38 from env_list and report.depends, and
remove the dead [testenv:py37] block, matching this branch's intent of
dropping Python 3.8.
…ntain permissions'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Comment thread samples/otp_web_sample_app.py Fixed
Comment thread samples/password_web_sample_app.py Fixed
Copy link
Copy Markdown
Contributor

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

Migrates the repository’s Python packaging and developer tooling from Poetry/tox/flake8/black/isort to uv + ruff, updating CI, pre-commit hooks, and project metadata accordingly.

Changes:

  • Replaces Poetry + tox workflows with uv-based syncing, building, and test execution (including CI/release workflows).
  • Consolidates linting/formatting to ruff and updates editor + pre-commit configuration.
  • Applies repo-wide mechanical reformatting across source, tests, and samples.

Reviewed changes

Copilot reviewed 89 out of 93 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tox.ini Removed tox configuration
requirements.txt Removed exported requirements lock
liccheck.ini Removed liccheck config
pyproject.toml Migrated metadata + tooling to uv/ruff
.pre-commit-config.yaml Switched hooks to uv-lock + ruff
.github/workflows/ci.yml New uv-based lint/test pipeline
.github/workflows/release-please.yml Release build via uv build
Dockerfile Updated to use uv in multi-stage build
.gitignore Added uv/ruff caches
.vscode/settings.json Ruff formatting/lint integration
.vscode/extensions.json Ruff extension recommendation
README.md Updated contributor instructions to uv/ruff
tests/common.py Mechanical formatting + typing tweak
tests/test_auth.py Mechanical reformat
tests/test_descope_client.py Mechanical reformat
tests/test_enchantedlink.py Mechanical reformat
tests/test_flask.py Mechanical reformat
tests/test_http_client.py Mechanical reformat
tests/test_magiclink.py Mechanical reformat
tests/test_otp.py Mechanical reformat
tests/test_password.py Mechanical reformat
tests/test_saml.py Mechanical reformat
tests/test_sso.py Mechanical reformat
tests/test_totp.py Mechanical reformat
tests/test_webauthn.py Mechanical reformat
tests/management/test_access_key.py Mechanical reformat
tests/management/test_audit.py Mechanical reformat
tests/management/test_authz.py Mechanical reformat
tests/management/test_fga.py Mechanical reformat
tests/management/test_flow.py Mechanical reformat
tests/management/test_group.py Mechanical reformat
tests/management/test_jwt.py Mechanical reformat
tests/management/test_mgmtkey.py Mechanical reformat
tests/management/test_outbound_application.py Mechanical reformat
tests/management/test_permission.py Mechanical reformat
tests/management/test_role.py Mechanical reformat
tests/management/test_sso_application.py Mechanical reformat
tests/management/test_sso_settings.py Mechanical reformat
tests/management/test_tenant.py Mechanical reformat
tests/management/test_user.py Mechanical reformat
samples/access_key_sample_app.py Mechanical reformat
samples/flask_authentication.py Mechanical reformat
samples/magiclink_sample_app.py Mechanical reformat
samples/magiclink_web_sample_app.py Flask ctx usage update + reformat
samples/otp_sample_app.py Mechanical reformat
samples/otp_web_sample_app.py Mechanical reformat
samples/password_sample_app.py Mechanical reformat
samples/password_web_sample_app.py Mechanical reformat
samples/sso_sample_app.py Mechanical reformat
samples/stepup_sample_app.py Mechanical reformat
samples/totp_sample_app.py Mechanical reformat
samples/webauthn_web_sample_app.py Mechanical reformat
samples/management/access_key_sample_app.py Mechanical reformat
samples/management/audit_sample_app.py Mechanical reformat
samples/management/authz_sample_app.py Mechanical reformat
samples/management/flow_sample_app.py Mechanical reformat
samples/management/group_sample_app.py Mechanical reformat
samples/management/outbound_application_sample_app.py Mechanical reformat
samples/management/permission_sample_app.py Mechanical reformat
samples/management/role_sample_app.py Mechanical reformat
samples/management/sso_application_sample_app.py Mechanical reformat
samples/management/sso_sample_app.py Mechanical reformat
samples/management/tenant_sample_app.py Mechanical reformat
samples/management/user_sample_app.py Mechanical reformat
descope/mgmt.py Mechanical reformat
descope/auth.py Mechanical reformat
descope/common.py Mechanical reformat
descope/descope_client.py Mechanical reformat
descope/exceptions.py Mechanical reformat
descope/http_client.py Mechanical reformat
descope/jwt_common.py Mechanical reformat
descope/flask/init.py Mechanical reformat
descope/management/audit.py Mechanical reformat
descope/management/authz.py Mechanical reformat
descope/management/common.py Mechanical reformat
descope/management/fga.py Mechanical reformat
descope/management/jwt.py Mechanical reformat
descope/management/outbound_application.py Mechanical reformat
descope/management/project.py Mechanical reformat
descope/management/sso_application.py Mechanical reformat
descope/management/sso_settings.py Mechanical reformat
descope/management/tenant.py Mechanical reformat
descope/management/user.py Mechanical reformat
descope/authmethod/enchantedlink.py Mechanical reformat
descope/authmethod/magiclink.py Mechanical reformat
descope/authmethod/otp.py Mechanical reformat
descope/authmethod/password.py Mechanical reformat
descope/authmethod/saml.py Mechanical reformat
descope/authmethod/sso.py Mechanical reformat
descope/authmethod/totp.py Mechanical reformat
descope/authmethod/webauthn.py Mechanical reformat

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread descope/jwt_common.py
Comment thread descope/descope_client.py
Comment thread pyproject.toml
Comment thread .github/workflows/ci.yml
Comment thread Dockerfile Outdated
Comment thread tests/common.py
Copy link
Copy Markdown

@shuni-bot-dev shuni-bot-dev Bot left a comment

Choose a reason for hiding this comment

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

🐕 Shuni's Review

Solid migration from poetry/tox/black/isort/flake8/pyupgrade to uv + ruff. Source code changes are mechanical reformats — test counts, imports, and runtime semantics all preserved. Configs are well-organized.

Sniffed out 5 issues:

  • 2 🟡 MEDIUM: unpinned uv:latest in Dockerfile, done job depends on conditionally-skipped jobs
  • 3 🟢 LOW: stale N803 ignore on tenant.py, Python 3.14 classifier without CI coverage, pylic config drops explicit MPL/CC0 allowances

See inline comments. Good bones overall — just a couple of polish items! Woof!

Comment thread Dockerfile Outdated
Comment thread .github/workflows/ci.yml
Comment thread pyproject.toml
Comment thread pyproject.toml
Comment thread pyproject.toml
Complete migration of build, lock, lint, format, and CI tooling from
poetry/tox/black/isort/flake8/pyupgrade to uv + ruff.

- Build/lock: uv_build backend, uv.lock as source of truth
  (drop poetry.lock, requirements.txt, tox.ini)
- Lint/format: ruff replaces flake8(+bugbear/pyproject), isort, black,
  pyupgrade, pep8-naming with rule families E/W/F/I/B/N/UP and
  per-file ignores documented in pyproject.toml
- pre-commit: drop sync_with_poetry, poetry, poetry-export, tox-ini-fmt,
  flake8, isort, black, pyupgrade; add astral-sh/uv-pre-commit (uv-lock)
  and astral-sh/ruff-pre-commit
- CI: split into lint (ruff + mypy) and matrix test jobs using
  astral-sh/setup-uv with uv sync --locked and uv run pytest
- Release: uv build + pypa/gh-action-pypi-publish (drops descope/.github
  poetry actions)
- Docker: multi-stage build using ghcr.io/astral-sh/uv image
- Wheel: bundles LICENSE via PEP 639 license-files
- Reformat all sources with ruff format (mechanical)
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

Coverage report

The coverage rate went from 98.36% to 98.36% ➡️

100% of new lines are covered.

Diff Coverage details (click to unfold)

descope/http_client.py

100% of new lines are covered (100% of the complete file).

descope/management/jwt.py

100% of new lines are covered (100% of the complete file).

descope/exceptions.py

100% of new lines are covered (100% of the complete file).

descope/authmethod/sso.py

100% of new lines are covered (100% of the complete file).

descope/management/authz.py

100% of new lines are covered (100% of the complete file).

descope/authmethod/password.py

100% of new lines are covered (100% of the complete file).

descope/management/sso_settings.py

100% of new lines are covered (100% of the complete file).

descope/descope_client.py

100% of new lines are covered (97.4% of the complete file).

descope/management/project.py

100% of new lines are covered (100% of the complete file).

descope/authmethod/otp.py

100% of new lines are covered (96.36% of the complete file).

descope/auth.py

100% of new lines are covered (97.7% of the complete file).

descope/authmethod/webauthn.py

100% of new lines are covered (100% of the complete file).

descope/management/common.py

100% of new lines are covered (99.73% of the complete file).

descope/common.py

100% of new lines are covered (99.13% of the complete file).

descope/management/outbound_application.py

100% of new lines are covered (100% of the complete file).

descope/authmethod/saml.py

100% of new lines are covered (100% of the complete file).

descope/management/user.py

100% of new lines are covered (96.02% of the complete file).

descope/jwt_common.py

100% of new lines are covered (98.03% of the complete file).

descope/mgmt.py

100% of new lines are covered (100% of the complete file).

descope/authmethod/totp.py

100% of new lines are covered (100% of the complete file).

descope/authmethod/enchantedlink.py

100% of new lines are covered (97.82% of the complete file).

descope/management/audit.py

100% of new lines are covered (75% of the complete file).

descope/management/sso_application.py

100% of new lines are covered (100% of the complete file).

descope/management/tenant.py

100% of new lines are covered (100% of the complete file).

descope/authmethod/magiclink.py

100% of new lines are covered (96.11% of the complete file).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants