Hub Python Library documentation

Strict Dataclasses

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Strict Dataclasses

Paket huggingface_hub menyediakan utilitas untuk membuat strict dataclasses. Ini adalah versi yang ditingkatkan dari dataclass standar Python dengan fitur validasi tambahan. Strict dataclasses memastikan bahwa field divalidasi baik saat inisialisasi maupun penugasan, sehingga ideal untuk skenario di mana integritas data sangat penting.

Ikhtisar

Strict dataclasses dibuat menggunakan dekorator @strict. Mereka memperluas fungsionalitas dataclasses reguler dengan:

  • Memvalidasi tipe bidang berdasarkan type hints
  • Mendukung validator kustom untuk pemeriksaan tambahan
  • Secara opsional, mengizinkan argumen kata kunci arbitrer dalam konstruktor
  • Memvalidasi field baik saat inisialisasi maupun selama penugasan

Manfaat

  • Integritas Data: Memastikan field selalu berisi data yang valid
  • Kemudahan Penggunaan: Terintegrasi dengan mulus dengan modul dataclass Python
  • Fleksibilitas: Mendukung validator kustom untuk logika validasi yang kompleks
  • Ringan: Tidak memerlukan dependensi tambahan seperti Pydantic, attrs, atau pustaka serupa

Penggunaan

Contoh Dasar

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict, as_validated_field

# Custom validator to ensure a value is positive
@as_validated_field
def positive_int(value: int):
    if not value > 0:
        raise ValueError(f"Value must be positive, got {value}")

@strict
@dataclass
class Config:
    model_type: str
    hidden_size: int = positive_int(default=16)
    vocab_size: int = 32  # Default value

    # Methods named `validate_xxx` are treated as class-wise validators
    def validate_big_enough_vocab(self):
        if self.vocab_size < self.hidden_size:
            raise ValueError(f"vocab_size ({self.vocab_size}) must be greater than hidden_size ({self.hidden_size})")

Field divalidasi selama inisialisasi:

config = Config(model_type="bert", hidden_size=24)   # Valid
config = Config(model_type="bert", hidden_size=-1)   # Raises StrictDataclassFieldValidationError

Konsistensi antar bidang juga divalidasi selama inisialisasi (validasi per kelas):

# `vocab_size` too small compared to `hidden_size`
config = Config(model_type="bert", hidden_size=32, vocab_size=16)   # Raises StrictDataclassClassValidationError

Field juga divalidasi saat penugasan:

config.hidden_size = 512  # Valid
config.hidden_size = -1   # Raises StrictDataclassFieldValidationError

Untuk menjalankan ulang validasi seluruh kelas setelah penugasan, Anda harus memanggil .validate secara eksplisit:

config.validate()  # Runs all class validators

Validator Kustom

Anda dapat melampirkan beberapa validator kustom ke field menggunakan validated_field. Validator adalah callable yang menerima satu argumen dan melempar pengecualian jika nilai tidak valid.

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict, validated_field

def multiple_of_64(value: int):
    if value % 64 != 0:
        raise ValueError(f"Value must be a multiple of 64, got {value}")

@strict
@dataclass
class Config:
    hidden_size: int = validated_field(validator=[positive_int, multiple_of_64])

Pada contoh ini, kedua validator diterapkan pada bidang hidden_size.

Argumen Kata Kunci Tambahan

Secara default, strict dataclasses hanya menerima field yang didefinisikan dalam kelas. Anda dapat mengizinkan argumen kata kunci tambahan dengan mengatur accept_kwargs=True di dekorator @strict.

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict

@strict(accept_kwargs=True)
@dataclass
class ConfigWithKwargs:
    model_type: str
    vocab_size: int = 16

config = ConfigWithKwargs(model_type="bert", vocab_size=30000, extra_field="extra_value")
print(config)  # ConfigWithKwargs(model_type='bert', vocab_size=30000, *extra_field='extra_value')

Argumen kata kunci tambahan muncul dalam representasi string dari dataclass tetapi diberi awalan * untuk menyoroti bahwa argumen tersebut tidak divalidasi.

Integrasi dengan Type Hints

Strict dataclasses menghormati type hints dan memvalidasinya secara otomatis. Sebagai contoh:

from typing import List
from dataclasses import dataclass
from huggingface_hub.dataclasses import strict

@strict
@dataclass
class Config:
    layers: List[int]

config = Config(layers=[64, 128])  # Valid
config = Config(layers="not_a_list")  # Raises StrictDataclassFieldValidationError

Jenis yang didukung meliputi:

  • Semua
  • Union
  • Opsional
  • Literal
  • Daftar
  • Dict
  • Tuple
  • Set

Dan kombinasi apa pun dari tipe-tipe ini. Jika Anda memerlukan validasi tipe yang lebih kompleks, Anda dapat melakukannya melalui validator kustom.

Validator kelas

Metode bernama validate_xxx diperlakukan sebagai validator kelas. Metode-metode ini hanya boleh mengambil self sebagai argumen. Validator kelas dijalankan sekali selama inisialisasi, tepat setelah __post_init__. Anda dapat mendefinisikan sebanyak yang diperlukan—mereka akan dieksekusi secara berurutan sesuai urutan kemunculannya.

Perhatikan bahwa validator kelas tidak dijalankan ulang secara otomatis ketika sebuah field diperbarui setelah inisialisasi. Untuk memvalidasi ulang objek secara manual, Anda perlu memanggil obj.validate().

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict

@strict
@dataclass
class Config:
    foo: str
    foo_length: int
    upper_case: bool = False

    def validate_foo_length(self):
        if len(self.foo) != self.foo_length:
            raise ValueError(f"foo must be {self.foo_length} characters long, got {len(self.foo)}")

    def validate_foo_casing(self):
        if self.upper_case and self.foo.upper() != self.foo:
            raise ValueError(f"foo must be uppercase, got {self.foo}")

config = Config(foo="bar", foo_length=3) # ok

config.upper_case = True
config.validate() # Raises StrictDataclassClassValidationError

Config(foo="abcd", foo_length=3) # Raises StrictDataclassFieldValidationError
Config(foo="Bar", foo_length=3, upper_case=True) # Raises StrictDataclassFieldValidationError

Metode .validate() adalah nama yang direservasi pada dataclass ketat. Untuk mencegah perilaku yang tidak terduga, error StrictDataclassDefinitionError akan dilemparkan jika kelas Anda sudah mendefinisikannya.

Referensi API

@strict

Dekorator @strict meningkatkan dataclass dengan validasi ketat.

huggingface_hub.dataclasses.strict

< >

( accept_kwargs: bool = False )

Parameter

  • cls — Kelas yang akan dikonversi menjadi dataclass ketat.
  • accept_kwargs (bool, opsional) — Jika True, memungkinkan argumen kata kunci arbitrer di __init__. Bawaan adalah False.

Decorator untuk menambahkan validasi ketat ke dataclass.

Decorator ini harus digunakan di atas @dataclass untuk memastikan IDE dan alat pengetikan statis mengenali kelas tersebut sebagai dataclass.

Dapat digunakan dengan atau tanpa argumen:

  • @strict
  • @strict(accept_kwargs=True)

Contoh:

>>> from dataclasses import dataclass
>>> from huggingface_hub.dataclasses import as_validated_field, strict, validated_field

>>> @as_validated_field
>>> def positive_int(value: int):
...     if not value >= 0:
...         raise ValueError(f"Value must be positive, got {value}")

>>> @strict(accept_kwargs=True)
... @dataclass
... class User:
...     name: str
...     age: int = positive_int(default=10)

# Initialize
>>> User(name="John")
User(name='John', age=10)

# Extra kwargs are accepted
>>> User(name="John", age=30, lastname="Doe")
User(name='John', age=30, *lastname='Doe')

# Invalid type => raises
>>> User(name="John", age="30")
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    TypeError: Field 'age' expected int, got str (value: '30')

# Invalid value => raises
>>> User(name="John", age=-1)
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    ValueError: Value must be positive, got -1

validate_typed_dict

Metode untuk memvalidasi bahwa sebuah kamus sesuai dengan tipe yang didefinisikan dalam kelas TypedDict.

Ini adalah ekuivalen dari validasi dataclass tetapi untuk TypedDict. Karena typed dict tidak pernah diinstansiasi (hanya digunakan oleh penguji tipe statis), langkah validasi harus dipanggil secara manual.

huggingface_hub.dataclasses.validate_typed_dict

< >

( schema: typedata: dict )

Parameter

  • schema (type[TypedDictType]) — Kelas TypedDict yang mendefinisikan struktur dan tipe yang diharapkan.
  • data (dict) — Kamus yang akan divalidasi.

Membuang

StrictDataclassFieldValidationError

  • StrictDataclassFieldValidationError — Jika ada field dalam dictionary yang tidak sesuai dengan tipe yang diharapkan.

Validasi bahwa sebuah dictionary sesuai dengan tipe yang didefinisikan dalam kelas TypedDict.

Di balik layar, typed dict dikonversi menjadi dataclass yang ketat dan divalidasi menggunakan dekorator @strict.

Contoh:

>>> from typing import Annotated, TypedDict
>>> from huggingface_hub.dataclasses import validate_typed_dict

>>> def positive_int(value: int):
...     if not value >= 0:
...         raise ValueError(f"Value must be positive, got {value}")

>>> class User(TypedDict):
...     name: str
...     age: Annotated[int, positive_int]

>>> # Valid data
>>> validate_typed_dict(User, {"name": "John", "age": 30})

>>> # Invalid type for age
>>> validate_typed_dict(User, {"name": "John", "age": "30"})
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    TypeError: Field 'age' expected int, got str (value: '30')

>>> # Invalid value for age
>>> validate_typed_dict(User, {"name": "John", "age": -1})
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    ValueError: Value must be positive, got -1

as_validated_field

Decorator untuk membuat validated_field. Direkomendasikan untuk field dengan satu validator untuk menghindari kode boilerplate.

huggingface_hub.dataclasses.as_validated_field

< >

( validator: Callable )

Parameter

  • validator (Callable) — Metode yang menerima nilai sebagai input dan melempar ValueError/TypeError jika nilai tersebut tidak valid.

Menghiasi fungsi validator sebagai validated_field (yaitu field dataclass dengan validator kustom).

validated_field

Membuat field dataclass dengan validasi kustom.

huggingface_hub.dataclasses.validated_field

< >

( validator: list[collections.abc.Callable[[typing.Any], None]] | collections.abc.Callable[[typing.Any], None]default: typing.Any = <dataclasses._MISSING_TYPE object at 0x7f9675fda620>default_factory: typing.Any = <dataclasses._MISSING_TYPE object at 0x7f9675fda620>init: bool = Truerepr: bool = Truehash: bool | None = Nonecompare: bool = Truemetadata: dict | None = None**kwargs: typing.Any )

Parameter

  • validator (Callable atau list[Callable]) — Metode yang menerima nilai sebagai input dan melempar ValueError/TypeError jika nilai tersebut tidak valid. Dapat berupa daftar validator untuk menerapkan beberapa pemeriksaan.
  • **kwargs — Argumen tambahan untuk diteruskan ke dataclasses.field().

Buat field dataclass dengan validator kustom.

Berfungsi untuk menerapkan beberapa pemeriksaan pada sebuah field. Jika hanya menerapkan satu aturan, lihat dekorator as_validated_field.

Kesalahan

kelas huggingface_hub.errors.StrictDataclassError

< >

( )

Pengecualian dasar untuk dataclass ketat.

kelas huggingface_hub.errors.StrictDataclassDefinitionError

< >

( )

Pengecualian yang dilempar ketika dataclass ketat didefinisikan dengan tidak benar.

kelas huggingface_hub.errors.StrictDataclassFieldValidationError

< >

( field: strcause: Exception )

Exception yang dilempar ketika strict dataclass gagal validasi untuk field tertentu.

Mengapa Tidak Menggunakan pydantic? (atau attrs? atau marshmallow_dataclass?)

  • Lihat diskusi di https://github.com/huggingface/transformers/issues/36329 mengenai penambahan Pydantic sebagai dependensi. Tambahkan ini akan cukup berat dan memerlukan logika yang cermat untuk mendukung baik v1 maupun v2.
  • Kami tidak membutuhkan sebagian besar fitur Pydantic, terutama yang terkait dengan pencetakan otomatis, jsonschema, serialisasi, alias, dan sebagainya.
  • Kami tidak memerlukan kemampuan untuk menginstansiasi kelas dari kamus.
  • Kami tidak ingin mengubah data. Dalam @strict, “validasi” berarti “memeriksa apakah suatu nilai valid.” Dalam Pydantic, “validasi” berarti “mengubah tipe suatu nilai, yang mungkin mengubah nilainya, lalu memeriksa apakah nilainya valid.”
  • Kami tidak perlu validasi yang sangat cepat. @strict tidak dirancang untuk beban berat di mana kinerja sangat krusial. Kasus penggunaan umum melibatkan validasi konfigurasi model (dilakukan sekali dan dapat diabaikan dibandingkan dengan menjalankan model). Hal ini memungkinkan kami untuk menjaga kode tetap minimal.
Update on GitHub