Hub Python Library documentation

Strict Dataclasses

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v2.4.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Strict Dataclasses

huggingface_hub 패키지는 strict dataclass을 생성하는 유틸리티를 제공합니다. 이는 Python의 표준 dataclass에 추가적인 검증 기능이 강화된 버전입니다. Strict dataclass는 초기화 및 할당 시 모두 필드가 검증되도록 보장하여 데이터 무결성이 중요한 시나리오에 이상적입니다.

개요

Strict dataclasses는 @strict 데코레이터를 사용하여 생성됩니다. 이들은 다음과 같은 방식으로 일반 dataclasses의 기능을 확장합니다:

  • 타입 힌트에 기반한 필드 타입 검증
  • 추가 검사를 위한 사용자 정의 검증기 지원
  • 생성자에서 임의의 키워드 인수를 선택적으로 허용
  • 초기화 및 할당 시 필드 검증

장점

  • 데이터 무결성: 필드가 항상 유효한 데이터를 포함하도록 보장
  • 사용 편의성: Python의 dataclass 모듈과 완벽하게 통합됩니다
  • 유연성: 복잡한 검증 로직을 위한 사용자 정의 검증기를 지원합니다
  • 경량: Pydantic, attrs 또는 유사한 라이브러리 등 추가적인 의존성이 필요하지 않습니다

사용

기본 예제

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

Fields는 초기화 중에 검증됩니다:

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

초기화 시에도 필드 간 일관성이 검증됩니다(클래스별 검증):

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

필드는 할당 시에도 검증됩니다:

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

할당 후 클래스 전체의 검증을 다시 실행하려면 .validate를 명시적으로 호출해야 합니다:

config.validate()  # Runs all class validators

Custom Validators

validated_field를 사용하여 필드에 여러 개의 사용자 정의 검증기를 연결할 수 있습니다. 검증기는 단일 인수를 받아 값이 유효하지 않으면 예외를 발생시키는 호출 가능한 객체입니다.

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

이 예제에서는 두 개의 검증기가 모두 hidden_size 필드에 적용됩니다.

추가 키워드 인자

기본적으로 strict dataclasses는 클래스에 정의된 필드만 허용합니다. @strict 데코레이터에서 accept_kwargs=True를 설정하여 추가적인 키워드 인수를 허용할 수 있습니다.

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

추가 키워드 인수는 dataclass의 문자열 표현에 나타나지만, 검증되지 않음을 강조하기 위해 * 접두사가 붙습니다.

Type Hints와의 통합

Strict dataclasses는 타입 힌트를 준수하며 이를 자동으로 검증합니다. 예를 들어:

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

지원되는 유형에는 다음이 포함됩니다:

  • 모두
  • Union
  • 선택 사항
  • Literal
  • 목록
  • Dict
  • Tuple
  • 설정

그리고 이러한 유형의 모든 조합도 가능합니다. 더 복잡한 유형 검증이 필요하면 사용자 정의 검증기를 통해 수행할 수 있습니다.

클래스 검증기

validate_xxx으로 이름 붙여진 메서드는 클래스 검증기로 처리됩니다. 이러한 메서드는 인수로 self만 받아야 합니다. 클래스 검증기는 초기화 중에 __post_init__ 바로 다음에 한 번 실행됩니다. 필요한 만큼 정의할 수 있으며, 정의된 순서대로 순차적으로 실행됩니다.

클래스 검증자는 초기화 후 필드가 업데이트되어도 자동으로 다시 실행되지 않습니다. 객체를 수동으로 다시 검증하려면 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

.validate() 메서드는 strict dataclass에서 예약된 이름입니다. 예기치 않은 동작을 방지하기 위해, 클래스에 이미 해당 메서드가 정의되어 있으면 StrictDataclassDefinitionError 오류가 발생합니다.

API 참조

@strict

@strict 데코레이터는 dataclass에 엄격한 검증을 추가합니다.

huggingface_hub.dataclasses.strict

< >

( accept_kwargs: bool = False )

매개변수

  • cls — 엄격한 dataclass로 변환할 클래스.
  • accept_kwargs (bool, 선택 사항) — True인 경우 __init__에서 임의의 키워드 인수를 허용합니다. 기본값은 False입니다.

dataclass에 엄격한 검증을 추가하는 데코레이터

이 데코레이터는 IDE와 정적 타이핑 도구가 해당 클래스를 dataclass로 인식하도록 보장하기 위해 @dataclass 위에 사용해야 합니다.

인수를 사용하거나 사용하지 않고 사용할 수 있습니다:

  • @strict
  • @strict(accept_kwargs=True)

예:

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

TypedDict 클래스에 정의된 타입을 따르는지 사전을 검증하는 메서드입니다.

이것은 TypedDict에 대한 dataclass 검증과 동일한 기능입니다. typed dict는 인스턴스화되지 않으므로(정적 타입 체커에서만 사용됨) 검증 단계는 수동으로 호출해야 합니다.

huggingface_hub.dataclasses.validate_typed_dict

< >

( schema: typedata: dict )

매개변수

  • schema (type[TypedDictType]) — 기대되는 구조와 타입을 정의하는 TypedDict 클래스.
  • data (dict) — 검증할 사전.

다음 예외가 발생합니다

StrictDataclassFieldValidationError

  • StrictDataclassFieldValidationError — 사전의 필드 중 하나라도 예상된 타입에 부합하지 않는 경우.

TypedDict 클래스에 정의된 타입에 따라 사전이 준수하는지 검증합니다.

내부적으로 typed dict는 엄격한 dataclass로 변환되고 @strict 데코레이터를 사용하여 검증됩니다.

예:

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

validated_field을 생성하는 데코레이터입니다. 불필요한 코드 반복을 피하기 위해 단일 검증기를 사용하는 필드에 권장됩니다.

huggingface_hub.dataclasses.as_validated_field

< >

( validator: Callable )

매개변수

  • validator (Callable) — 값을 입력으로 받아 해당 값이 유효하지 않으면 ValueError/TypeError를 발생시키는 메서드.

validated_field로(즉, 사용자 정의 검증기를 가진 dataclass 필드로) validator 함수를 장식합니다.

validated_field

custom validation을 가진 dataclass 필드를 생성합니다.

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 = Truerepr: bool = Truehash: bool | None = Nonecompare: bool = Truemetadata: dict | None = None**kwargs: typing.Any )

매개변수

  • validator (Callable 또는 list[Callable]) — 값을 입력으로 받아 값이 유효하지 않으면 ValueError/TypeError를 발생시키는 메서드입니다. 여러 검사를 적용하기 위해 검증자 목록을 사용할 수 있습니다.
  • **kwargs — dataclasses.field()에 전달할 추가 인자.

커스텀 검증기가 있는 dataclass 필드를 생성합니다.

필드에 여러 검사를 적용하는 데 유용합니다. 규칙을 하나만 적용하는 경우 as_validated_field 데코레이터를 확인해 보세요.

오류

클래스 huggingface_hub.errors.StrictDataclassError

< >

( )

엄격한 dataclass의 기본 예외입니다.

class huggingface_hub.errors.StrictDataclassDefinitionError

< >

( )

strict dataclass가 잘못 정의된 경우 발생하는 예외입니다.

class huggingface_hub.errors.StrictDataclassFieldValidationError

< >

( field: strcause: Exception )

strict dataclass가 특정 필드에 대한 검증을 실패할 때 발생하는 예외입니다.

pydantic (또는 attrs? 또는 marshmallow_dataclass?)를 사용하지 않는 이유는 무엇인가요?

  • Pydantic을 의존성으로 추가하는 것에 대한 논의는 https://github.com/huggingface/transformers/issues/36329에서 확인하실 수 있습니다. 이는 상당한 부하를 유발하며, v1과 v2를 모두 지원하려면 신중한 로직이 필요합니다.
  • Pydantic의 대부분의 기능, 특히 자동 캐스팅, jsonschema, 직렬화, 별칭 등과 관련된 기능은 필요하지 않습니다.
  • 사전에서 클래스를 인스턴스화할 수 있는 기능은 필요하지 않습니다.
  • 데이터를 변경하지 않으려는 것입니다. @strict에서 “validation”은 “값이 유효한지 확인하는 것”을 의미합니다. Pydantic에서 “validation”은 “값을 캐스팅하고, 필요에 따라 변경한 후, 유효한지 확인하는 것”을 의미합니다.
  • 매우 빠른 검증은 필요하지 않습니다. @strict는 성능이 중요한 고부하 환경용으로 설계되지 않았습니다. 일반적인 사용 사례는 모델 구성을 검증하는 것이며(모델 실행에 비해 한 번만 수행되고 무시할 수 있을 정도로 경미함), 이를 통해 코드를 최소한으로 유지할 수 있습니다.
Update on GitHub