IlmHamroh
Python kursi/Paketlash va chiqarish5/8-dars17 daqiqa
Mundarija (22)

19.5-dars: Semantik versiyalash

19-QISM — PAKETLASH VA CHIQARISH · 5-dars


1. Kirish va motivatsiya

Paketni nashr qildingiz 19.4-bob. Vaqt o'tadi — xato tuzatasiz, yangi imkoniyat qo'shasiz, ba'zan API ni o'zgartirasiz. Har o'zgarish uchun yangi versiya chiqarasiz. Lekin versiya raqamini qanday tanlash kerak? 1.0.0 dan keyin 1.0.1 mi, 1.1.0 mi, yoki 2.0.0 mi? Bu tasodifiy tanlov emas — semantik versiyalash (SemVer) versiya raqamiga ma'no beradi: raqamning o'zi foydalanuvchiga o'zgarish turini aytadi.

To'g'ri versiyalash foydalanuvchilarga ishonch beradi: ular yangilanish xavfsiz (xato tuzatish) yoki ehtiyot talab qiladi (buzuvchi o'zgarish) ekanini versiya raqamidan biladi.

Real vaziyat. Bir kutubxona muallifi funksiya nomini o'zgartirdi va uni patch versiya (1.2.3 → 1.2.4) sifatida chiqardi. Foydalanuvchilar ~=1.2 (patch yangilanishlarga ruxsat, 18.2) ishlatgani uchun avtomatik yangi versiyani oldilar — va ularning kodi buzildi, chunki eski funksiya nomi yo'q edi. Bu SemVer buzilishi edi: API o'zgarishi asosiy (major) versiya bo'lishi kerak edi (2.0.0). Muallif buni tushundi va SemVer qoidalariga qat'iy amal qila boshladi: buzuvchi o'zgarish — major, yangi imkoniyat — minor, xato tuzatish — patch. Foydalanuvchilar ishonchni tikladi.

Bu darsda semantik versiyalashni — versiya raqamiga ma'no berishni o'rganamiz.

Bu darsda:

  • SemVer: ASOSIY.KICHIK.PATCH
  • Qachon qaysi raqamni oshirish
  • Pre-release versiyalar (alpha, beta, rc)
  • 0.x versiyalash
  • Versiyani kodda saqlash
  • O'zgarishlar jurnali (CHANGELOG)
  • SemVer buzilishi va oqibatlari
  • Amaliy: versiya boshqaruvi

ℹ Misollarda versiya mantig'i uchun packaging.version 18.2-bob ishlatiladi.


2. Nazariya — chuqur tushuntirish

2.1. SemVer tuzilishi

Semantik versiya uch qismdan iborat: ASOSIY.KICHIK.PATCH (masalan 2.5.3):

Qism Ingliz Qachon oshadi
ASOSIY MAJOR Moslikni buzuvchi o'zgarish
KICHIK MINOR Yangi imkoniyat (mos)
PATCH PATCH Xato tuzatish (mos)
2.5.3
│ │ └── PATCH — xato tuzatishlar
│ └──── KICHIK — yangi imkoniyatlar
└────── ASOSIY — buzuvchi o'zgarishlar

SemVer shartnomasi: versiya raqami o'zgarish turini aytadi — foydalanuvchi yangilanish xavfini raqamidan biladi.

2.2. Qachon qaysi raqamni oshirish

O'zgarish Misol Versiya
Xato tuzatish Noto'g'ri hisob tuzatildi 1.2.3 → 1.2.4 (PATCH)
Yangi imkoniyat Yangi funksiya qo'shildi 1.2.3 → 1.3.0 (KICHIK)
Buzuvchi o'zgarish Funksiya olib tashlandi/nomlandi 1.2.3 → 2.0.0 (ASOSIY)

Muhim qoida: quyi raqam oshganda, pastdagilar nolga tushadi: 1.2.3 da minor oshsa → 1.3.0 (patch nol), major oshsa → 2.0.0 (minor va patch nol).

2.3. Buzuvchi o'zgarish nima

Buzuvchi (breaking) o'zgarish — mavjud foydalanuvchi kodini buzadigan o'zgarish:

Buzuvchi (MAJOR) Buzmaydigan (MINOR/PATCH)
Funksiya olib tashlash Yangi funksiya qo'shish
Funksiya nomini o'zgartirish Yangi ixtiyoriy parametr
Parametr olib tashlash Xato tuzatish
Qaytish turini o'zgartirish Ichki refaktoring
Majburiy parametr qo'shish Hujjat yaxshilash

Savol: "bu o'zgarish mavjud foydalanuvchi kodini buzadimi?" Ha → MAJOR; yo'q, yangi → MINOR; yo'q, tuzatish → PATCH.

2.4. Pre-release versiyalar

Barqaror versiyadan oldin sinov versiyalari:

1.0.0-alpha.1     # alpha — erta, beqaror
1.0.0-beta.1      # beta — funksiyalar to'liq, sinovda
1.0.0-rc.1        # rc (release candidate) — deyarli tayyor
1.0.0             # barqaror (stable)
Belgi Ma'nosi
alpha Erta sinov, ko'p o'zgaradi
beta Funksiyalar to'liq, xatolar bor
rc Nomzod — chiqishga tayyor

Pre-release versiyalar barqaror versiyadan oldin keladi: 1.0.0-rc.1 < 1.0.0. Ular pip install da sukut bo'yicha o'rnatilmaydi (--pre kerak).

2.5. 0.x versiyalash

1.0.0 dan oldingi (0.x.y) versiyalar — barqaror emas:

Versiya Ma'nosi
0.x.y Dastlabki rivojlanish — API o'zgarishi mumkin
0.1.0 → 0.2.0 0.x da minor buzuvchi bo'lishi mumkin
1.0.0 Birinchi barqaror API — SemVer to'liq kuchga kiradi

0.x da SemVer qoidalari yumshoqroq: 0.x da har o'zgarish buzuvchi bo'lishi mumkin. 1.0.0 — "API barqaror" e'loni.

2.6. Versiyani kodda saqlash

Versiyani bir joyda saqlang (takror yo'q):

python
# src/wisar/__init__.py
__version__ = "1.2.3"
toml
# pyproject.toml
dynamic = ["version"]
[tool.hatch.version]
path = "src/wisar/__init__.py"    # __version__ dan oladi (19.2)

Dinamik versiya bilan versiya __init__.py da bir marta yoziladi; pyproject.toml, wheel nomi va PyPI undan oladi.

2.7. O'zgarishlar jurnali (CHANGELOG)

CHANGELOG.md — har versiyada nima o'zgarganini hujjatlaydi:

markdown
# O'zgarishlar

## [1.3.0] - 2026-09-17
### Qo'shildi
- Yangi `export_csv` funksiyasi

## [1.2.4] - 2026-09-10
### Tuzatildi
- `hisobla` da nolga bo'lish xatosi

CHANGELOG — foydalanuvchiga yangilanishda nima o'zgarganini aytadi. "Keep a Changelog" formati keng tarqalgan (Qo'shildi/O'zgardi/Tuzatildi/Olib tashlandi).

2.8. SemVer buzilishi

Buzilish Oqibat
Buzuvchi o'zgarish patch sifatida Foydalanuvchi kodi buziladi
Har o'zgarish major Foydalanuvchi qo'rqadi (juda tez major)
Versiya sakrash (1.0 → 3.0) Chalkashlik
Versiyani kamaytirish Mumkin emas (o'sib borishi kerak)

SemVer — shartnoma: uni buzsangiz, foydalanuvchilar ~=/>= ga ishona olmaydi va yangilanishdan qo'rqadi. Qat'iy amal qiling.


3. Tez ma'lumotnoma

ASOSIY.KICHIK.PATCH  (masalan 2.5.3)
  MAJOR — buzuvchi o'zgarish (2.0.0)
  MINOR — yangi imkoniyat (1.3.0)
  PATCH — xato tuzatish (1.2.4)

pre-release: 1.0.0-alpha.1 < beta.1 < rc.1 < 1.0.0
0.x.y — barqaror emas; 1.0.0 — barqaror API
python
# versiya bir joyda:
__version__ = "1.2.3"   # __init__.py
# pyproject.toml: dynamic = ["version"]

Qoidalar

buzuvchi → major; yangi → minor; tuzatish → patch
quyi raqam oshsa, pastdagilar nolga
0.x — barqaror emas; 1.0.0 — API barqaror
pre-release: alpha < beta < rc < stable
versiyani bir joyda (dinamik)
CHANGELOG bilan o'zgarishlarni hujjatlang
SemVer — shartnoma, buzmang

4. Batafsil misollar

Misollarda versiya mantig'i uchun packaging.version ishlatiladi.

Misol 1 — SemVer qoidalari

python
"""ASOSIY.KICHIK.PATCH; qaysi o'zgarishga qaysi raqam; quyi raqam oshsa pastdagilar nolga; versiya taqqoslash."""

from packaging.version import Version


def keyingi_versiya(joriy: str, ozgarish: str) -> str:
    v = Version(joriy)
    asosiy, kichik, patch = v.major, v.minor, v.micro
    if ozgarish == "major":
        return f"{asosiy + 1}.0.0"          # pastdagilar nolga
    if ozgarish == "minor":
        return f"{asosiy}.{kichik + 1}.0"    # patch nolga
    if ozgarish == "patch":
        return f"{asosiy}.{kichik}.{patch + 1}"
    raise ValueError(ozgarish)


def main() -> None:
    print("=== 1. Versiya tuzilishi ===")
    v = Version("2.5.3")
    print(f"  2.5.3 → ASOSIY={v.major}, KICHIK={v.minor}, PATCH={v.micro}")

    print("\n=== 2. Keyingi versiya (o'zgarish turiga qarab) ===")
    joriy = "1.2.3"
    for ozgarish, izoh in [("patch", "xato tuzatish"), ("minor", "yangi imkoniyat"), ("major", "buzuvchi o'zgarish")]:
        yangi = keyingi_versiya(joriy, ozgarish)
        print(f"  {joriy} + {ozgarish:6} ({izoh:18}) → {yangi}")

    print("\n=== 3. ⭐ Quyi raqam oshsa, pastdagilar nolga ===")
    print(f"  1.2.3 minor → {keyingi_versiya('1.2.3', 'minor')}  (patch nolga)")
    print(f"  1.2.3 major → {keyingi_versiya('1.2.3', 'major')}  (minor va patch nolga)")

    print("\n=== 4. Versiya taqqoslash ===")
    print(f"  2.0.0 > 1.9.9: {Version('2.0.0') > Version('1.9.9')}")
    print(f"  1.10.0 > 1.9.0: {Version('1.10.0') > Version('1.9.0')}  (10 > 9, satr emas)")
    print(f"  1.2.3 == 1.2.3: {Version('1.2.3') == Version('1.2.3')}")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Versiya tuzilishi ===
  2.5.3 → ASOSIY=2, KICHIK=5, PATCH=3

=== 2. Keyingi versiya (o'zgarish turiga qarab) ===
  1.2.3 + patch  (xato tuzatish     ) → 1.2.4
  1.2.3 + minor  (yangi imkoniyat   ) → 1.3.0
  1.2.3 + major  (buzuvchi o'zgarish) → 2.0.0

=== 3. ⭐ Quyi raqam oshsa, pastdagilar nolga ===
  1.2.3 minor → 1.3.0  (patch nolga)
  1.2.3 major → 2.0.0  (minor va patch nolga)

=== 4. Versiya taqqoslash ===
  2.0.0 > 1.9.9: True
  1.10.0 > 1.9.0: True  (10 > 9, satr emas)
  1.2.3 == 1.2.3: True

Nima ko'rsatdi: 2.1, 2.2-bo'limlar.

Misol 2 — Buzuvchi o'zgarishni aniqlash

python
"""o'zgarish buzuvchimi (major) yoki qo'shuvchimi (minor) yoki tuzatuvchimi (patch); API o'zgarishlarini toifalash; to'g'ri versiya taklifi."""

from packaging.version import Version


def versiya_turi(ozgarish_turi: str) -> str:
    buzuvchi = {"funksiya_olib_tashlash", "nom_ozgartirish", "parametr_olib_tashlash", "qaytish_turi_ozgarish", "majburiy_parametr"}
    qoshuvchi = {"yangi_funksiya", "ixtiyoriy_parametr", "yangi_imkoniyat"}
    tuzatuvchi = {"xato_tuzatish", "hujjat", "ichki_refaktoring", "tezlik"}
    if ozgarish_turi in buzuvchi:
        return "major"
    if ozgarish_turi in qoshuvchi:
        return "minor"
    if ozgarish_turi in tuzatuvchi:
        return "patch"
    return "nomalum"


def main() -> None:
    print("=== 1. O'zgarishlarni toifalash ===")
    ozgarishlar = [
        ("xato_tuzatish", "hisobda nolga bo'lish tuzatildi"),
        ("yangi_funksiya", "export_csv qo'shildi"),
        ("funksiya_olib_tashlash", "eski salom() olib tashlandi"),
        ("ixtiyoriy_parametr", "format= ixtiyoriy parametr"),
        ("nom_ozgartirish", "hisobla → calculate"),
        ("hujjat", "README yaxshilandi"),
        ("majburiy_parametr", "yangi majburiy 'kalit' argument"),
    ]
    for tur, izoh in ozgarishlar:
        versiya = versiya_turi(tur)
        belgi = "🔴" if versiya == "major" else "🟡" if versiya == "minor" else "🟢"
        print(f"  {belgi} {versiya:6} — {izoh}")

    print("\n=== 2. Kalit savol ===")
    print("  'Bu o'zgarish mavjud foydalanuvchi kodini buzadimi?'")
    print("  Ha → major | Yo'q, yangi → minor | Yo'q, tuzatish → patch")

    print("\n=== 3. Misol: bir nechta o'zgarish ===")
    o_lar = ["xato_tuzatish", "yangi_funksiya", "funksiya_olib_tashlash"]
    turlar = [versiya_turi(o) for o in o_lar]
    # eng yuqori o'zgarish belgilaydi
    if "major" in turlar:
        yakuniy = "major"
    elif "minor" in turlar:
        yakuniy = "minor"
    else:
        yakuniy = "patch"
    print(f"  o'zgarishlar: {turlar}")
    print(f"  yakuniy versiya turi: {yakuniy} (eng yuqori o'zgarish belgilaydi)")
    print(f"  1.2.3 → {'2.0.0' if yakuniy == 'major' else '1.3.0' if yakuniy == 'minor' else '1.2.4'}")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. O'zgarishlarni toifalash ===
  🟢 patch  — hisobda nolga bo'lish tuzatildi
  🟡 minor  — export_csv qo'shildi
  🔴 major  — eski salom() olib tashlandi
  🟡 minor  — format= ixtiyoriy parametr
  🔴 major  — hisobla → calculate
  🟢 patch  — README yaxshilandi
  🔴 major  — yangi majburiy 'kalit' argument

=== 2. Kalit savol ===
  'Bu o'zgarish mavjud foydalanuvchi kodini buzadimi?'
  Ha → major | Yo'q, yangi → minor | Yo'q, tuzatish → patch

=== 3. Misol: bir nechta o'zgarish ===
  o'zgarishlar: ['patch', 'minor', 'major']
  yakuniy versiya turi: major (eng yuqori o'zgarish belgilaydi)
  1.2.3 → 2.0.0

Nima ko'rsatdi: 2.3-bo'lim.

Misol 3 — Pre-release va 0.x versiyalash

python
"""pre-release: alpha < beta < rc < stable; tartib; --pre bilan o'rnatiladi; 0.x barqaror emas; 1.0.0 barqaror API."""

from packaging.version import Version


def main() -> None:
    print("=== 1. Pre-release tartibi ===")
    versiyalar = ["1.0.0a1", "1.0.0b1", "1.0.0rc1", "1.0.0"]
    saralangan = sorted(versiyalar, key=Version)
    print(f"  saralangan: {saralangan}")
    print(f"  1.0.0-alpha < 1.0.0-beta: {Version('1.0.0a1') < Version('1.0.0b1')}")
    print(f"  1.0.0-rc < 1.0.0 (barqaror): {Version('1.0.0rc1') < Version('1.0.0')}")

    print("\n=== 2. Pre-release turlari ===")
    turlar = [
        ("alpha (a)", "erta sinov, ko'p o'zgaradi"),
        ("beta (b)", "funksiyalar to'liq, xatolar bor"),
        ("rc (release candidate)", "chiqishga tayyor nomzod"),
        ("stable", "barqaror, tavsiya etiladi"),
    ]
    for tur, izoh in turlar:
        print(f"  {tur:24} — {izoh}")

    print("\n=== 3. Pre-release aniqlash ===")
    for v_str in ["1.0.0a1", "1.0.0", "2.1.0rc2"]:
        v = Version(v_str)
        print(f"  {v_str}: pre-release={v.is_prerelease}")
    print("  ⭐ pre-release pip da sukut o'rnatilmaydi (--pre kerak)")

    print("\n=== 4. 0.x vs 1.0.0 ===")
    print(f"  0.5.0: barqaror emas (API o'zgarishi mumkin)")
    print(f"  1.0.0: birinchi barqaror API (SemVer to'liq kuchga kiradi)")
    print(f"  0.5.0 < 1.0.0: {Version('0.5.0') < Version('1.0.0')}")
    print("  ⚠️ 0.x da har o'zgarish buzuvchi bo'lishi mumkin")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Pre-release tartibi ===
  saralangan: ['1.0.0a1', '1.0.0b1', '1.0.0rc1', '1.0.0']
  1.0.0-alpha < 1.0.0-beta: True
  1.0.0-rc < 1.0.0 (barqaror): True

=== 2. Pre-release turlari ===
  alpha (a)                — erta sinov, ko'p o'zgaradi
  beta (b)                 — funksiyalar to'liq, xatolar bor
  rc (release candidate)   — chiqishga tayyor nomzod
  stable                   — barqaror, tavsiya etiladi

=== 3. Pre-release aniqlash ===
  1.0.0a1: pre-release=True
  1.0.0: pre-release=False
  2.1.0rc2: pre-release=True
  ⭐ pre-release pip da sukut o'rnatilmaydi (--pre kerak)

=== 4. 0.x vs 1.0.0 ===
  0.5.0: barqaror emas (API o'zgarishi mumkin)
  1.0.0: birinchi barqaror API (SemVer to'liq kuchga kiradi)
  0.5.0 < 1.0.0: True
  ⚠️ 0.x da har o'zgarish buzuvchi bo'lishi mumkin

Nima ko'rsatdi: 2.4, 2.5-bo'limlar.

Misol 4 — Amaliy: versiya va CHANGELOG boshqaruvi

Loyihaning versiya boshqaruvini avtomatlashtiruvchi yordamchi yozamiz: o'zgarishlar ro'yxatiga qarab keyingi versiyani hisoblaydi, __init__.py dagi versiyani yangilaydi va CHANGELOG yozuvi yaratadi. Bu — har chiqishda bajarilodigan versiya boshqaruvi ish oqimi.

python
"""versiya boshqaruvi: o'zgarishlardan versiya turini aniqlash, keyingi versiyani hisoblash, __init__.py yangilash, CHANGELOG yozuvi; to'liq oqim."""

import re
from packaging.version import Version


def versiya_turi(o_lar: list[str]) -> str:
    if any(o["tur"] == "buzuvchi" for o in o_lar):
        return "major"
    if any(o["tur"] == "qoshildi" for o in o_lar):
        return "minor"
    return "patch"


def keyingi(joriy: str, tur: str) -> str:
    v = Version(joriy)
    if tur == "major":
        return f"{v.major + 1}.0.0"
    if tur == "minor":
        return f"{v.major}.{v.minor + 1}.0"
    return f"{v.major}.{v.minor}.{v.micro + 1}"


def changelog_yoz(versiya: str, sana: str, o_lar: list[str]) -> str:
    guruhlar = {"qoshildi": "Qo'shildi", "buzuvchi": "O'zgardi (buzuvchi)", "tuzatildi": "Tuzatildi"}
    satrlar = [f"## [{versiya}] - {sana}"]
    for kalit, sarlavha in guruhlar.items():
        tegishli = [o["matn"] for o in o_lar if o["tur"] == kalit]
        if tegishli:
            satrlar.append(f"### {sarlavha}")
            satrlar.extend(f"- {m}" for m in tegishli)
    return "\n".join(satrlar)


def main() -> None:
    joriy = "1.2.3"
    ozgarishlar = [
        {"tur": "tuzatildi", "matn": "hisobla() da nolga bo'lish xatosi"},
        {"tur": "qoshildi", "matn": "export_csv() funksiyasi"},
    ]

    print("=== 1. O'zgarishlar ===")
    for o in ozgarishlar:
        print(f"  [{o['tur']}] {o['matn']}")

    print("\n=== 2. Keyingi versiya ===")
    tur = versiya_turi(ozgarishlar)
    yangi = keyingi(joriy, tur)
    print(f"  joriy: {joriy}")
    print(f"  o'zgarish turi: {tur} (yangi imkoniyat bor → minor)")
    print(f"  keyingi versiya: {yangi}")

    print("\n=== 3. __init__.py yangilash ===")
    init_matn = f'__version__ = "{joriy}"\n'
    yangi_matn = re.sub(r'__version__ = "[^"]+"', f'__version__ = "{yangi}"', init_matn)
    print(f"  oldin: {init_matn.strip()}")
    print(f"  keyin: {yangi_matn.strip()}")

    print("\n=== 4. CHANGELOG yozuvi ===")
    changelog = changelog_yoz(yangi, "2026-09-17", ozgarishlar)
    for qator in changelog.splitlines():
        print(f"  {qator}")
    print("  ⭐ versiya + CHANGELOG — har chiqishda birga yangilanadi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. O'zgarishlar ===
  [tuzatildi] hisobla() da nolga bo'lish xatosi
  [qoshildi] export_csv() funksiyasi

=== 2. Keyingi versiya ===
  joriy: 1.2.3
  o'zgarish turi: minor (yangi imkoniyat bor → minor)
  keyingi versiya: 1.3.0

=== 3. __init__.py yangilash ===
  oldin: __version__ = "1.2.3"
  keyin: __version__ = "1.3.0"

=== 4. CHANGELOG yozuvi ===
  ## [1.3.0] - 2026-09-17
  ### Qo'shildi
  - export_csv() funksiyasi
  ### Tuzatildi
  - hisobla() da nolga bo'lish xatosi
  ⭐ versiya + CHANGELOG — har chiqishda birga yangilanadi

Nima ko'rsatdi: 2.2, 2.6, 2.7-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"Versiya raqami tasodifiy" SemVer — raqamga ma'no beradi
"Har o'zgarish major" Faqat buzuvchi o'zgarish major
"Xato tuzatish minor" Patch
"1.9.0 dan keyin 2.0.0" 1.10.0 (raqam, satr emas)
"0.x barqaror" Barqaror emas — API o'zgaradi
"Versiya ikki joyda" Bir joyda (dinamik)
"CHANGELOG keraksiz" Foydalanuvchiga o'zgarishlarni aytadi
"SemVer ixtiyoriy" Shartnoma — buzsangiz ishonch yo'qoladi

6. Keng tarqalgan xatolar va yechimlari

1. Buzuvchi o'zgarishni patch qilish

funksiya nomini o'zgartirib 1.2.4         # ❌ foydalanuvchi kodi buziladi
funksiya nomini o'zgartirib 2.0.0         # ✅ major

2. Yangi funksiyani major qilish

yangi funksiya qo'shib 2.0.0              # ❌ foydalanuvchi qo'rqadi
yangi funksiya qo'shib 1.3.0              # ✅ minor

3. Pastdagilarni nolga tushirmaslik

1.2.3 → 1.3.3 (minor)                     # ❌ patch nolga tushmadi
1.2.3 → 1.3.0                             # ✅

4. Versiyani ikki joyda saqlash

python
__version__ = "1.2.3"  # va pyproject da ham   # ❌ takror
dynamic = ["version"]                     # ✅ bir joyda

5. 0.x da SemVer kutish

0.2.0 barqaror API deb ishlatish          # ⚠️ 0.x o'zgaradi
# ✅ 1.0.0 ga chiqqach barqaror

6. CHANGELOG yo'q

versiya chiqarib, nima o'zgarganini yozmaslik   # ❌
# ✅ CHANGELOG.md yangilang

7. Versiyani kamaytirish

1.2.0 dan keyin 1.1.0                     # ❌ mumkin emas
# ✅ versiya doim o'sib borishi kerak

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 18.2-dars (o'tilgan): versiya belgilagichlari — ~=, >= SemVer'ga tayanadi
  • 19.2-dars (o'tilgan): pyproject — dinamik versiya
  • 19.4-dars (o'tilgan): PyPI — versiyani o'chirib bo'lmaydi
  • 28-qism: CI/CD — avtomatik versiyalash va nashr
  • 31-qism: karyera — versiyalash professional amaliyot

8. Eng yaxshi amaliyotlar

  1. SemVer'ga qat'iy amal qiling: buzuvchi→major, yangi→minor, tuzatish→patch.

  2. "Foydalanuvchi kodini buzadimi?" savolini bering.

  3. Quyi raqam oshganda pastdagilarni nolga tushiring.

  4. 0.x — barqaror emas; 1.0.0 — barqaror API e'loni.

  5. Versiyani bir joyda (dinamik) saqlang.

  6. Har versiyada CHANGELOG.md ni yangilang.

  7. Pre-release (alpha/beta/rc) bilan sinov versiyalarini belgilang.

  8. Versiyani hech qachon kamaytirmang.


9. Amaliy topshiriq

Vazifa 1: Versiyani aniqlang

1.4.2 dan keyin qaysi versiya:

1.  xato tuzatildi
2.  yangi funksiya qo'shildi
3.  funksiya nomi o'zgartirildi
4.  ixtiyoriy parametr qo'shildi
5.  README yaxshilandi
6.  parametr olib tashlandi
7.  ichki refaktoring (API o'zgarmadi)
8.  yangi funksiya + xato tuzatish (birga)
Javoblar
  1. 1.4.3 (patch)
  2. 1.5.0 (minor)
  3. 2.0.0 (major — buzuvchi)
  4. 1.5.0 (minor)
  5. 1.4.3 (patch)
  6. 2.0.0 (major — buzuvchi)
  7. 1.4.3 (patch)
  8. 1.5.0 (minor — eng yuqori belgilaydi)

Vazifa 2: Xatolarni tuzating

1.  # funksiya olib tashlandi
    1.2.3 → 1.2.4

2.  # yangi funksiya qo'shildi
    1.2.3 → 2.0.0

3.  # minor oshirish
    1.2.3 → 1.3.3

4.  # versiya kamaytirish
    1.5.0 → 1.4.0

5.  # 0.x ni barqaror deb ishlatish
    "0.3.0 API barqaror"
Javoblar
1.  1.2.3 → 2.0.0          # buzuvchi — major

2.  1.2.3 → 1.3.0          # yangi — minor

3.  1.2.3 → 1.3.0          # patch nolga

4.  # versiya kamaymaydi — 1.6.0 (yangi o'zgarish)

5.  # 0.x barqaror emas — 1.0.0 ga chiqing

Vazifa 3: Versiya kalkulyator

keyingi_versiya(joriy, o'zgarishlar):

  1. O'zgarishlar ro'yxatidan turni aniqlang
  2. Eng yuqori o'zgarish versiyani belgilasin
  3. Pre-release variantini ham qo'llang
  4. packaging.version bilan tekshiring

Vazifa 4: CHANGELOG generatori

Git commitlaridan CHANGELOG:

  1. Commit xabarlarini toifalang (feat/fix/breaking)
  2. Versiya turini aniqlang
  3. "Keep a Changelog" formatida yozing
  4. Keyingi versiyani taklif qiling

Vazifa 5: SemVer validatori

  1. Ikki versiya orasidagi o'zgarishni tekshiring
  2. API o'zgarishiga mos versiya sakraganini tasdiqlang
  3. SemVer buzilishlarini toping
  4. Tavsiya bering

Vazifa 6: Versiya tarixi

  1. Paket versiya tarixini tahlil qiling
  2. Har o'zgarish turini aniqlang (major/minor/patch nisbati)
  3. Pre-release versiyalarni toping
  4. Versiyalash sifatini baholang

Vazifa 7: O'ylash

SemVer keng qabul qilingan standart, lekin tanqidchilar uni "amaliyotda buziladi" deydilar — ko'p loyiha SemVer'ga qat'iy amal qilmaydi, va "buzuvchi o'zgarish" tushunchasi ba'zan noaniq. Nima uchun SemVer ideal bo'lsa ham amalda qiyin, va versiyalash "texnik qaror" dan ko'ra "ijtimoiy shartnoma" ekanini qanday ko'rsatadi?

Javob

Qisqa javob: SemVer amalda qiyin, chunki "buzuvchi o'zgarish" ni aniqlash subyektiv: bir foydalanuvchi uchun buzuvchi bo'lgan o'zgarish (masalan xato tuzatish natijani o'zgartiradi) boshqasi uchun oddiy tuzatish. SemVer — texnik qoida emas, ijtimoiy shartnoma: muallif va foydalanuvchilar o'rtasidagi va'da. Uning kuchi qat'iy raqamlarda emas, balki jamoa ishonchida — versiya raqami va'dani bildiradi, va va'dani bajarish odamga bog'liq.

1. Nega SemVer qiyin

Qiyinchilik Tafsilot
"Buzuvchi" subyektiv Kimga buzuvchi?
Xato tuzatish natijani o'zgartiradi Tuzatish yoki buzuvchi?
Ichki vs ommaviy API Chegara noaniq
Xatti-harakat o'zgarishi Imzo emas, xulq
Inson qarori Avtomatlashtirilmaydi

2. "Buzuvchi" ning noaniqligi

Misollar:

  • Xato tuzatish natijani o'zgartiradi (kimdir noto'g'ri natijaga tayangan bo'lsa — buzuvchi)
  • Tezlik yaxshilanishi xulqni o'zgartiradi
  • Yangi ogohlantirish (warning) — buzuvchimi?

3. Ijtimoiy shartnoma sifatida

Texnik qaror Ijtimoiy shartnoma
Qat'iy qoida Va'da
Avtomatik Inson mulohazasi
Bir xil talqin Kontekstga bog'liq
Mashina bajaradi Jamoa ishonchi

4. Nega baribir foydali

SemVer mukammal bo'lmasa ham, u umumiy til beradi: versiya raqami taxminan nimani anglatishini hamma biladi. Bu ishonch va bashoratlilikni oshiradi — mukammal bo'lmasa ham, hech narsadan yaxshi.

5. Amaliy yondashuv

  1. SemVer'ga imkon qadar amal qiling
  2. Shubhali holatda ehtiyotkorlik (major)
  3. CHANGELOG bilan o'zgarishlarni aniq tushuntiring
  4. Foydalanuvchi nuqtai nazaridan o'ylang

6. Muhandislik saboqlari

  1. Ba'zi standartlar ijtimoiy, texnik emas
  2. Versiyalash — muallif va foydalanuvchi o'rtasidagi va'da
  3. Mukammal bo'lmagan standart ham qiymatli
  4. Aniq muloqot (CHANGELOG) qoidadan muhimroq

7. Xulosa

  1. SemVer qiyin — "buzuvchi" subyektiv
  2. U texnik qoida emas, ijtimoiy shartnoma
  3. Kuchi jamoa ishonchida
  4. Mukammal emas, lekin umumiy til beradi

Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.


Xulosa

Bu darsda semantik versiyalashni — versiya raqamiga ma'no berishni o'rgandik.

Eng muhim uch fikr:

  1. SemVer: ASOSIY.KICHIK.PATCH raqamga ma'no beradi. MAJOR — moslikni buzuvchi o'zgarish (2.0.0), MINOR — yangi imkoniyat, mos (1.3.0), PATCH — xato tuzatish, mos (1.2.4). Kalit savol: "bu o'zgarish mavjud foydalanuvchi kodini buzadimi?" — ha bo'lsa major, yangi bo'lsa minor, tuzatish bo'lsa patch. Quyi raqam oshganda pastdagilar nolga tushadi (1.2.3 → minor → 1.3.0).

  2. Pre-release va 0.x. Barqaror versiyadan oldin sinov versiyalari: 1.0.0-alpha.1 < beta.1 < rc.1 < 1.0.0 (pip da sukut o'rnatilmaydi, --pre kerak). 0.x.y versiyalar barqaror emas — API o'zgarishi mumkin; 1.0.0 "API barqaror" e'loni bo'lib, SemVer to'liq kuchga kiradi. Versiyani bir joyda (__init__.py, dinamik) saqlang va har versiyada CHANGELOG.md ni yangilang.

  3. SemVer — shartnoma, ijtimoiy va'da. Uni buzsangiz (masalan buzuvchi o'zgarishni patch sifatida chiqarsangiz), foydalanuvchilar ~=/>= belgilagichlariga ishona olmaydi va yangilanishdan qo'rqadi. "Buzuvchi o'zgarish" ni aniqlash ba'zan subyektiv — shuning uchun SemVer texnik qoidadan ko'ra muallif va foydalanuvchilar o'rtasidagi ishonchga asoslanadi. Qat'iy amal qiling va CHANGELOG bilan o'zgarishlarni aniq tushuntiring.

Keyingi darsda foydalanuvchilar terminaldan ishlatadigan CLI dastur yaratishni o'rganamiz: argparse va click bilan buyruq qatori interfeysi, argumentlar, bayroqlar va yordamni loyihalash.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
19.5-dars: Semantik versiyalash — IlmHamroh