Coverage for src/csv_schema_validator/schema_models.py: 64%

42 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-09-20 12:34 +0200

1from pydantic import BaseModel, Field, field_validator, model_validator 

2from typing import List, Optional 

3from enum import Enum 

4 

5 

6class FieldType(str, Enum): 

7 STRING = "string" 

8 NUMBER = "number" 

9 INTEGER = "integer" 

10 BOOLEAN = "boolean" 

11 

12 

13class FieldSchema(BaseModel): 

14 name: str = Field(..., description="Field name") 

15 type: FieldType = Field(..., description="Field data type") 

16 required: bool = Field(..., description="Whether the field is required") 

17 description: Optional[str] = Field(None, description="Field description") 

18 pattern: Optional[str] = Field(None, description="Field pattern") 

19 enum: Optional[List[str]] = Field(None, description="Field enum") 

20 min: Optional[int] = Field(None, description="Field minimum value") 

21 max: Optional[int] = Field(None, description="Field maximum value") 

22 

23 @field_validator("pattern") 

24 def validate_pattern(cls, v): 

25 if v is not None: 

26 import re 

27 

28 try: 

29 re.compile(v) 

30 except re.error as e: 

31 raise ValueError(f"Invalid pattern: {e}") 

32 return v 

33 

34 @model_validator(mode="after") 

35 def validate_min_max(self): 

36 if self.min is not None or self.max is not None: 

37 if self.type in ["string", "boolean"]: 

38 raise ValueError( 

39 f"min/max constraints not applicable for {self.type} type" 

40 ) 

41 return self 

42 

43 

44class CSVSchema(BaseModel): 

45 name: str = Field(..., description="Schema name") 

46 description: Optional[str] = Field(None, description="Schema description") 

47 fields: List[FieldSchema] = Field(..., min_items=1, description="Field definitions") 

48 

49 @field_validator("fields") 

50 def validate_fields(cls, v): 

51 names = [field.name for field in v] 

52 if len(names) != len(set(names)): 

53 raise ValueError("Field names must be unique") 

54 return v