# Katı Veri Sınıfları

`huggingface_hub` paketi, **strict dataclass** oluşturmak için bir yardımcı araç sağlar. Bunlar, ek doğrulama özelliklerine sahip, Python'un standart `dataclass` yapısının geliştirilmiş versiyonlarıdır. Strict dataclass'lar, alanların hem başlatma hem de atama sırasında doğrulanmasını garanti ederek, veri bütünlüğünün kritik olduğu senaryolar için idealdir.

## Genel Bakış

Strict dataclass'lar `@strict` dekoratörü kullanılarak oluşturulur. Düzenli dataclass'ların işlevselliğini şu şekilde genişletirler:

- Tip ipuçlarına dayalı alan türlerini doğrulama
- Ek kontroller için özel doğrulayıcıları destekleme
- Oluşturucuda isteğe bağlı olarak keyfi anahtar kelime argümanlarına izin verme
- Alanların hem başlatma sırasında hem de atama sırasında doğrulanması

## Avantajlar

- **Veri Bütünlüğü**: Alanların her zaman geçerli veri içerdiğini sağlar
- **Kullanım Kolaylığı**: Python'un `dataclass` modülüyle kusursuz bir şekilde bütünleşir
- **Esneklik**: Karmaşık doğrulama mantığı için özel doğrulayıcıları destekler
- **Hafif**: Pydantic, attrs veya benzeri kütüphaneler gibi ek bağımlılıklar gerektirmez

## Kullanım

### Temel Örnek

```python
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})")
```

Alanlar başlatma sırasında doğrulanır:

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

Alanlar arasındaki tutarlılık, başlatma sırasında da doğrulanır (sınıf bazlı doğrulama):

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

Alanlar atama sırasında da doğrulanır:

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

Atama sonrasında sınıf genelindeki doğrulamayı yeniden çalıştırmak için `.validate` fonksiyonunu açıkça çağırmalısınız:

```python
config.validate()  # Runs all class validators
```

### Özel Doğrulayıcılar

`validated_field` kullanarak alanlara birden fazla özel doğrulayıcı ekleyebilirsiniz. Doğrulayıcı, tek bir argüman alır ve değer geçersizse bir istisna fırlatan çağrılabilir bir nesnedir.

```python
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])
```

Bu örnekte, her iki doğrulayıcı da `hidden_size` alanına uygulanır.

### Ek Anahtar Sözcük Argümanları

Varsayılan olarak, strict dataclasses yalnızca sınıfta tanımlanmış alanları kabul eder. `@strict` dekoratöründe `accept_kwargs=True` ayarlayarak ek anahtar kelime argümanlarına izin verebilirsiniz.

```python
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')
```

Ek anahtar kelime argümanları, dataclass'ın string gösteriminde görünür ancak doğrulanmadıklarını vurgulamak için `*` önekiyle işaretlenir.

### Type Hints ile Entegrasyon

Strict dataclasses, tip ipuçlarına uyar ve bunları otomatik olarak doğrular. Örneğin:

```python
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
```

Desteklenen türler şunları içerir:
- Herhangi
- Birleşim
- İsteğe bağlı
- Literal
- Liste
- Dict
- Tuple
- Set

Ve bu türlerin herhangi bir kombinasyonu. Daha karmaşık tür doğrulaması gerekiyorsa, bunu özel bir doğrulayıcı (validator) aracılığıyla yapabilirsiniz.

### Sınıf doğrulayıcıları

`validate_xxx` adlı yöntemler sınıf doğrulayıcıları olarak ele alınır. Bu yöntemler yalnızca `self` argümanını almalıdır. Sınıf doğrulayıcıları, başlatma sırasında bir kez, `__post_init__` hemen ardından çalıştırılır. İhtiyaç duyduğunuz kadarını tanımlayabilirsiniz; sıralarıyla ardışık olarak yürütülürler.

Sınıf doğrulayıcılarının, başlatma sonrasında bir alan güncellendiğinde otomatik olarak yeniden çalıştırılmadığına dikkat edin. Nesneyi manuel olarak yeniden doğrulamak için `obj.validate()` çağrısını yapmanız gerekir.

```py
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
```

> [!WARNING]
> `.validate()` yöntemi, strict dataclass'lar için ayrılmış bir isimdir. Beklenmeyen davranışları önlemek için, sınıfınız zaten böyle bir yöntem tanımlıyorsa `StrictDataclassDefinitionError` hatası oluşturulur.

## API Referansı

### `@strict`[[huggingface_hub.dataclasses.strict]]

`@strict` dekoratörü, bir dataclass'ı katı doğrulama ile güçlendirir.

#### huggingface_hub.dataclasses.strict[[huggingface_hub.dataclasses.strict]]

```python
huggingface_hub.dataclasses.strict(accept_kwargs: bool = False)
```

[Kaynak](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/dataclasses.py#L56)

**Parametreler:**

cls : Sıkı bir dataclass'a dönüştürülecek sınıf.

accept_kwargs (`bool`, *isteğe bağlı*) : True ise, `__init__` içinde keyfi anahtar kelime argümanlarına izin verir. Varsayılan olarak False'dur.

**Dönüş:**

Alan atamasında katı doğrulama içeren geliştirilmiş dataclass.

Bir dataclass'a katı doğrulama eklemek için dekoratör.

Bu dekoratör, IDE'lerin ve statik tip denetimi araçlarının sınıfı bir dataclass olarak tanımasını sağlamak için `@dataclass` üzerine kullanılmalıdır.

Argümanlarla veya argümansız kullanılabilir:
- `@strict`
- `@strict(accept_kwargs=True)`

Örnek:
```py
>>> 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`[[huggingface_hub.dataclasses.validate_typed_dict]]

Bir `TypedDict` sınıfında tanımlanan tiplere uygunluğu doğrulamak için kullanılan yöntem.

Bu, `TypedDict`ler için dataclass doğrulamasının eşdeğeridir. Tip işaretli sözlükler asla örneklenmediğinden (yalnızca statik tip denetleyicileri tarafından kullanıldıklarından), doğrulama adımının manuel olarak çağrılması gerekir.

#### huggingface_hub.dataclasses.validate_typed_dict[[huggingface_hub.dataclasses.validate_typed_dict]]

```python
huggingface_hub.dataclasses.validate_typed_dict(schema: type, data: dict)
```

[Kaynak](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/dataclasses.py#L286)

**Parametreler:**

schema (`type[TypedDictType]`) : Beklenen yapıyı ve türleri tanımlayan TypedDict sınıfı.

data (`dict`) : Doğrulanacak sözlük.

**Yükselen:** ``StrictDataclassFieldValidationError``

- ``StrictDataclassFieldValidationError`` -- Sözlükteki herhangi bir alan beklenen tipe uymuyorsa.

Bir sözlüğün, bir TypedDict sınıfında tanımlanan tiplere uygun olduğunu doğrulayın.

Arka planda, typed dict, `@strict` dekoratörü kullanılarak doğrulanan katı bir dataclass'a dönüştürülür.

Örnek:
```py
>>> 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`[[huggingface_hub.dataclasses.as_validated_field]]

Tek bir doğrulayıcıya sahip alanlarda gereksiz kodu önlemek için önerilen, `validated_field` oluşturmak için kullanılan dekoratör.

#### huggingface_hub.dataclasses.as_validated_field[[huggingface_hub.dataclasses.as_validated_field]]

```python
huggingface_hub.dataclasses.as_validated_field(validator: Callable)
```

[Kaynak](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/dataclasses.py#L426)

**Parametreler:**

validator (`Callable`) : Bir değeri girdi olarak alır ve değer geçersizse ValueError/TypeError fırlatan bir yöntem.

Bir doğrulayıcı fonksiyonunu `validated_field` (yani özel bir doğrulayıcıya sahip bir dataclass alanı) olarak süsler.

### `validated_field`[[huggingface_hub.dataclasses.validated_field]]

Özel doğrulama ile bir dataclass alanı oluşturur.

#### huggingface_hub.dataclasses.validated_field[[huggingface_hub.dataclasses.validated_field]]

```python
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 0x7fabedd4e6b0>, default_factory: typing.Any = <dataclasses._MISSING_TYPE object at 0x7fabedd4e6b0>, init: bool = True, repr: bool = True, hash: bool | None = None, compare: bool = True, metadata: dict | None = None, **kwargs: typing.Any)
```

[Kaynak](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/dataclasses.py#L383)

**Parametreler:**

validator (`Callable` veya `list[Callable]`) : Bir değeri girdi olarak alır ve değer geçersizse ValueError/TypeError fırlatan bir yöntem. Birden fazla kontrol uygulamak için doğrulayıcıların bir listesi olabilir.

- ****kwargs** : `dataclasses.field()` fonksiyonuna iletilecek ek argümanlar.

**Dönüş:**

metadata içinde doğrulayıcı eklenmiş bir alan

Özel bir doğrulayıcıyla bir dataclass alanı oluşturun.

Bir alana birden fazla kontrol uygulamak için faydalıdır. Sadece bir kural uyguluyorsanız, `as_validated_field` dekoratörüne göz atın.

### Hatalar[[huggingface_hub.errors.StrictDataclassError]]

#### huggingface_hub.errors.StrictDataclassError[[huggingface_hub.errors.StrictDataclassError]]

[Kaynak](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/errors.py#L540)

Katı veri sınıfları için temel istisna.

#### huggingface_hub.errors.StrictDataclassDefinitionError[[huggingface_hub.errors.StrictDataclassDefinitionError]]

[Kaynak](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/errors.py#L544)

Yanlış tanımlanan bir strict dataclass için atılan istisna.

#### huggingface_hub.errors.StrictDataclassFieldValidationError[[huggingface_hub.errors.StrictDataclassFieldValidationError]]

```python
huggingface_hub.errors.StrictDataclassFieldValidationError(field: str, cause: Exception)
```

[Kaynak](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/errors.py#L548)

Belirli bir alan için doğrulama başarısız olduğunda bir strict dataclass tarafından fırlatılan istisna.

## `pydantic` Neden Kullanılmıyor? (ya da `attrs`? ya da `marshmallow_dataclass`?)

- Pydantic'in bir bağımlılık olarak eklenmesine ilişkin tartışma için https://github.com/huggingface/transformers/issues/36329 adresine bakın. Bu, ağır bir ekleme olacak ve hem v1 hem de v2 sürümlerini desteklemek için dikkatli bir mantık gerektirecektir.
- Pydantic'in çoğu özelliğine, özellikle otomatik dönüştürme, jsonschema, seri hale getirme, takma adlar (aliases) vb. ile ilgili olanlara ihtiyacımız yok.
- Bir sözlükten sınıf örneği oluşturma yeteneğine ihtiyacımız yok.
- Verileri değiştirmek istemiyoruz. `@strict` içinde "validation" (doğrulama), "bir değerin geçerli olup olmadığını kontrol etme" anlamına gelir. Pydantic'te ise "validation" (doğrulama), "bir değeri dönüştürme, gerekirse değiştirmeye ve ardından geçerli olup olmadığını kontrol etme" anlamına gelir.
- Çok hızlı doğrulama yapmamıza gerek yok. `@strict`, performansın kritik olduğu ağır yükler için tasarlanmamıştır. Yaygın kullanım senaryoları, bir model yapılandırmasını doğrulamayı içerir (bu işlem yalnızca bir kez yapılır ve modelin çalıştırılmasına kıyasla ihmal edilebilir düzeydedir). Bu sayede kodu minimal tutabiliriz.

