تطوير الويب

Ruff وuv: سير عمل Python الحديث في 2026 خطوة بخطوة

4 min de lecture

🔝 الدليل الرئيسي للسلسلة: بايثون: لغة ومنظومة وأطر للمطوّرين

تأرجحت أدوات Python في 2026. أصدرت Astral، الناشر خلف Ruff، أداة uv في 2024 وثبّتت المنظومة في كدسة متماسكة: uv يحل محل pip + virtualenv + pip-tools + pyenv + poetry بثنائي Rust واحد، وruff يحل محل flake8 + black + isort + pydocstyle + pyupgrade بـ linter+formatter Rust واحد. المكسب جذري: مشروع يستغرق 45 ثانية لتثبيت تبعياته بـ pip يُثبَّت في ثانيتين مع uv. linter يستغرق 8 ثوانٍ مع flake8 يعمل في 200 ms مع Ruff. يُثبّت هذا الدرس ويُعدّ الاثنين لسير عمل احترافي في 2026.

المتطلبات

  • Python 3.13.13 أو 3.14.5 متوفر محليًا (راجع تثبيت Python 3) — اختياري، uv يستطيع تثبيته بنفسه
  • طرفية (zsh، bash أو PowerShell)
  • مشروع موجود أو نية إنشاء جديد
  • الوقت المُقدَّر: 60 دقيقة

الخطوة 1 — تثبيت uv (مستقل، مبني بـ Rust)

uv 0.11.14 صدر في 12 مايو 2026. التثبيت عبر سكربت مستقل لا يحتاج Python مُسبق التثبيت (uv ثنائي Rust مستقل).

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows PowerShell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

uv --version
# uv 0.11.14

uv self update

الثنائي يُثبَّت في ~/.local/bin/uv (Linux/macOS) أو %LOCALAPPDATA%/uv/bin/uv.exe (Windows) ويُضاف تلقائيًا لـ PATH بعد إعادة تشغيل shell. في هذه المرحلة، uv جاهز لإدارة Python نفسه: uv python install 3.14 يُحمّل المفسّر الرسمي دون لمس النظام.

الخطوة 2 — إنشاء مشروع بـ uv init

uv init يُهيئ مشروعًا نظيفًا: pyproject.toml أدنى، .python-version، بيئة افتراضية، هيكل ملفات.

uv init mon-service --python 3.14
cd mon-service

uv add httpx pydantic
uv add --dev pytest pytest-cov ruff

uv sync

uv run python -c "import httpx; print(httpx.__version__)"

uv run pytest

ثلاثة فروق رئيسية مع poetry/pip-tools. الـ uv.lock يُولَّد تلقائيًا وحتميًا: حتى على Mac M2 وrunner Linux x86_64، الإصدارات المحلولة متطابقة. uv sync يُنشئ ويُزامن .venv في ثوانٍ. uv run يُنفّذ أمرًا في venv دون الحاجة لتفعيله يدويًا.

الخطوة 3 — إعداد pyproject.toml مع uv

uv يتبع PEP 621 (project metadata موحد) ويمدّد بخياراته الخاصة تحت [tool.uv].

[project]
name = "mon-service"
version = "0.1.0"
description = "Service API en Python 3.14"
requires-python = ">=3.13,<3.15"
dependencies = [
    "httpx>=0.27,<1.0",
    "pydantic>=2.13,<3.0",
    "fastapi>=0.136",
]

[project.optional-dependencies]
postgres = ["asyncpg>=0.30", "sqlalchemy[asyncio]>=2.0"]
redis = ["redis>=5.0"]

[dependency-groups]
dev = [
    "pytest>=9.0",
    "pytest-cov>=7.1",
    "pytest-asyncio>=1.3",
    "ruff>=0.13",
    "mypy>=1.13",
]

[tool.uv]
package = true
default-groups = ["dev"]
managed = true

requires-python = ">=3.13,<3.15" انضباط هيكلي: يُفشل uv sync على Python غير متوافق. الـ extras يُتيحان تثبيت الحد الأدنى (uv sync) أو الإثراء (uv sync --extra postgres --extra redis). dependency-groups (PEP 735) يحلّان محل dev extras المُسيء.

الخطوة 4 — تثبيت وإعداد Ruff

Ruff يدمج linter وformatter. إعداده يعيش في pyproject.toml تحت [tool.ruff].

[tool.ruff]
line-length = 100
target-version = "py314"
src = ["src", "tests"]
extend-exclude = ["migrations", "vendor"]

[tool.ruff.lint]
select = [
    "E", "W", "F", "I", "B", "C4", "UP", "N", "S", "SIM", "RUF",
]
ignore = [
    "E501",  # line too long — géré par le formatter
    "S101",  # use of assert — OK en tests
]

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "S105", "S106"]
"__init__.py" = ["F401"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
docstring-code-format = true
line-ending = "lf"

target-version = "py314" يتيح لـ Ruff اقتراح تحديثات تلقائية (مثل typing.Listlist). per-file-ignores يسمح بالاستثناءات المُستهدفة دون تلويث الإعداد العام. docstring-code-format يُنسّق أيضًا snippets في docstrings.

الخطوة 5 — سير عمل Ruff اليومي

# Linter — affiche les violations
uv run ruff check .

# Linter avec auto-fix
uv run ruff check . --fix

# Linter avec fix unsafe
uv run ruff check . --fix --unsafe-fixes

# Formatter
uv run ruff format .

# Check sans modifier (CI)
uv run ruff format --check .

# Lister les règles activées
uv run ruff linter

الثلاثي العملي: ruff format ثم ruff check --fix ثم ruff check لرؤية ما يتبقّى للتصحيح يدويًا. على قاعدة كود 50,000 سطر، هذه الأوامر الثلاثة تعمل في أقل من ثانيتين إجمالًا — بعيد كل البعد عن أوقات انتظار flake8/black/isort.

الخطوة 6 — Hook pre-commit مع pre-commit framework

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.13
    hooks:
      - id: ruff-check
        args: [--fix, --exit-non-zero-on-fix]
      - id: ruff-format

  - repo: https://github.com/astral-sh/uv-pre-commit
    rev: 0.11.14
    hooks:
      - id: uv-lock   # vérifie que uv.lock est à jour avec pyproject.toml

# Installation
uv tool install pre-commit
pre-commit install
pre-commit run --all-files

الـ hook uv-lock يمنع مطورًا من commit تغييرات في pyproject.toml دون إعادة توليد uv.lock، مما سيُسبّب تثبيتات متباعدة بين المطوّرين. uv tool install pre-commit مكافئ لـ pipx install.

الخطوة 7 — دمج Ruff وuv في CI GitHub Actions

name: CI
on: [push, pull_request]
jobs:
  qualite:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: astral-sh/setup-uv@v8.1.0
        with:
          version: "latest"
          enable-cache: true
      - run: uv python install 3.14
      - run: uv sync --all-extras --dev
      - name: Ruff lint
        run: uv run ruff check .
      - name: Ruff format
        run: uv run ruff format --check .
      - name: Tests
        run: uv run pytest --cov=src --cov-report=xml
      - uses: codecov/codecov-action@v6

خيار enable-cache: true في setup-uv يُخزّن مؤقتًا المُحلِّل والـ wheels المُحمَّلة. عند التشغيل الثاني، التثبيت ينخفض من 5 ثوانٍ إلى ثانية واحدة. على 100 PR شهريًا، عدة ساعات من وقت CI مُوفَّرة.

الخطوة 8 — الترحيل من Poetry / pip-tools

# Migration depuis Poetry
cp pyproject.toml pyproject.toml.poetry-backup

# Convertir [tool.poetry.dependencies] -> [project].dependencies
# et [tool.poetry.group.dev.dependencies] -> [dependency-groups.dev]

rm poetry.lock
uv lock

uv sync
uv run pytest

# Migration depuis pip-tools
cat requirements.in | xargs uv add
cat requirements-dev.in | xargs uv add --dev

للمشاريع القديمة جدًا بـ setup.py + requirements.txt، أداة migrate-to-uv تُؤتمت التحويل. للمشاريع الجديدة، البدء مباشرة بـ uv init يتجنّب كل هذا المسار.

أخطاء شائعة

العَرَض السبب الحل
uv غير موجود بعد التثبيت PATH غير مُحمَّل إعادة تشغيل الطرفية أو source ~/.bashrc
uv.lock يتغيّر على آلات أخرى فروقات منصات (Linux مقابل macOS) uv يُولّد lock عالميًا افتراضيًا؛ تحقق من تطابق إصدار uv
Ruff يُعيد كتابة كود بعد formatter تعارض قواعد linter مع formatter تعطيل E501 (طول السطر، يُدار من formatter)
قاعدة S101 على الاختبارات per-file-ignores مفقود إضافة "tests/**/*.py" = ["S101"]
Import غير مستخدم في __init__.py F401 صارم جدًا لإعادات التصدير per-file-ignores ["F401"] على __init__.py
الاختبارات لا تجد الحزمة package = true مفقود إضافة package = true في [tool.uv]

الأسئلة الشائعة

uv أم Poetry في 2026؟
uv لكل مشروع جديد: أسرع 10-50×، يتبع PEPs قياسية، مستقبل مضمون. Poetry يبقى قابلًا للاستخدام للمشاريع الموجودة حيث الترحيل ليس أولوية.

Ruff أم black + isort + flake8؟
Ruff منهجيًا: ثنائي واحد، أسرع 100×، إعداد موحّد. Black يبقى لقيود استقرار طويل الأمد، لكن Ruff format متوافق مع Black.

كيف ننتقل لـ Ruff تدريجيًا على قاعدة موجودة؟
تفعيل مجموعة فرعية من القواعد، ruff check --fix، commit، ثم توسيع select تدريجيًا. تجنّب ruff check --add-noqa الذي يُلوّث الكود بتعليقات.

هل uv يدعم wheels الخاصة؟
نعم عبر [[tool.uv.index]] بـ URL وcredentials عبر متغيّر بيئة. متوافق مع Azure Artifacts وAWS CodeArtifact وJFrog.

هل نحفظ .venv؟
لا. أضف .venv/ إلى .gitignore. uv يُعيد إنشاء البيئة في ثوانٍ من lock.

مقالات ذات صلة

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité