Chapter pyproject.toml pada Section Virtual Environments dan Dependencies sudah memperkenalkan berkas ini sebagai tempat mendeklarasikan dependencies. Untuk project yang benar-benar dikemas dan dideploy, tabel [project] perlu diisi lebih serius: nama, versi, penulis, sampai kelompok dependencies opsional. Metadata yang lengkap menentukan bagaimana package tampil di PyPI dan bagaimana tool build memperlakukan project kita. Chapter ini membedah satu per satu.

Anatomi Tabel [project] #

Berikut contoh pyproject.toml utuh untuk project toko-api:

toml
[build-system]
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"

[project]
name = "toko-api"
version = "1.4.0"
description = "API manajemen produk toko buku"
readme = "README.md"
requires-python = ">=3.10"
license = "MIT"
license-files = ["LICENSE"]
authors = [
    { name = "Budi Santoso", email = "[email protected]" },
]
keywords = ["api", "toko", "fastapi"]
classifiers = [
    "Programming Language :: Python :: 3",
    "Operating System :: OS Independent",
]

[project.urls]
Homepage = "https://example.com/toko-api"
Documentation = "https://docs.example.com/toko-api"
Changelog = "https://example.com/toko-api/changelog"

Mari kita telaah baris-baris penting pada tabel [project]:

  1. name: distribution name sesuai konvensi kebab-case dari chapter sebelumnya; nama inilah yang diketik pengguna saat pip install toko-api.
  2. version: versi rilis; lompatan angka mengikuti semantic versioning (major.minor.patch).
  3. description: satu kalimat ringkas — muncul di hasil pencarian PyPI.
  4. readme: berkas yang isinya di-render sebagai halaman depan package di PyPI.
  5. requires-python = ">=3.10": pip menolak instalasi bila interpreter pengguna lebih tua dari batas ini — cara termurah mencegah laporan galat aneh.
  6. license = "MIT" dan license-files: ekspresi SPDX modern; hindari bentuk tabel license = { text = "MIT" } yang kini usang.
  7. authors: array of table — boleh berisi lebih dari satu penulis.
  8. classifiers: label taxonomi PyPI untuk memudahkan pencarian (dibahas pada Chapter Build System dan Package Metadata).
  9. [project.urls]: tautan tambahan yang tampil di bilah samping halaman PyPI.

dependencies versus optional-dependencies #

Kunci dependencies berisi paket yang selalu dibutuhkan; optional-dependencies mendefinisikan extras — kelompok paket opsional yang dipasang hanya bila diminta:

toml
dependencies = [
    "fastapi>=0.110",
    "httpx>=0.27",
]

[project.optional-dependencies]
dev = [
    "pytest>=8.0",
    "ruff>=0.4",
]

Pengguna memilih extras dengan sintaks kurung siku setelah nama package:

bash
pip install toko-api
pip install "toko-api[dev]"

Perintah pertama hanya memasang fastapi dan httpx; perintah kedua menambahkan pytest dan ruff. Karena TOML hanyalah data, kita bisa memverifikasi struktur berkas ini dengan module tomllib (hadir di Python 3.11):

python
import tomllib

with open("pyproject.toml", "rb") as berkas:
    data = tomllib.load(berkas)

print(data["project"]["name"])
print(data["project"]["dependencies"])
print(data["project"]["optional-dependencies"]["dev"])

Output yang Dihasilkan:

text
toko-api
['fastapi>=0.110', 'httpx>=0.27']
['pytest>=8.0', 'ruff>=0.4']

Contoh di atas diuji dengan berkas berisi kedua tabel dependencies tersebut — nilai tercetak sebagai list Python, membuktikan TOML berhasil terurai.

Versi Dinamis dengan setuptools-scm #

Menyimpan versi di dua tempat (tag Git dan pyproject.toml) mengundang ketidaksesuaian. Plugin setuptools-scm menyelesaikannya dengan membaca versi dari tag Git saat build berlangsung. Deklarasinya: hapus kunci version, lalu nyatakan versi sebagai dinamis:

toml
[project]
name = "toko-api"
dynamic = ["version"]

[tool.setuptools_scm]

Dengan konfigurasi tersebut, angka versi mengalir dari git tag v1.4.0 ke metadata package secara otomatis — praktik yang umum pada project dengan rilis terjadwal. Sebaliknya, project yang masih awam terhadap Git tag atau dirilis manual cukup memakai kunci version statis; keduanya sah, yang penting jangan mencampurnya sekaligus.

Jebakan Sintaks TOML #

TOML terasa ringan, tetapi ada dua jebakan yang sering menjatuhkan pemula. Pertama, array multi-baris tetap memerlukan koma di antara elemennya — tanda kutip di akhir baris tanpa koma membuat parser menelan elemen berikutnya sebagai string lanjutan hingga gagal:

python
import tomllib

isi = """
dependencies = [
    "fastapi>=0.110"
    "httpx>=0.27"
]
"""

try:
    tomllib.loads(isi)
except tomllib.TOMLDecodeError as galat:
    print(galat)

Output yang Dihasilkan:

text
Unclosed array (at line 4, column 5)

Kedua, TOML bersifat case-sensitive pada nama kunci: Version = "1.0" tidak sama dengan version = "1.0" dan tool build tidak membacanya. Nilai boolean juga harus huruf kecil (true/false), bukan True gaya Python.

Setelah metadata terisi, pertanyaan berikutnya adalah bagaimana tool build tahu cara membangun project ini — tugas tabel [build-system] yang kita bedah pada chapter berikutnya.