1+ from typing import Annotated , Self
2+
13from pydantic import (
24 BaseModel ,
3- computed_field ,
5+ ConfigDict ,
46 Field ,
5- model_validator ,
7+ computed_field ,
68 field_validator ,
7- ConfigDict ,
9+ model_validator ,
810)
9- from typing import Annotated
11+
1012from fastapi_forge .enums import FieldDataType
11- from typing_extensions import Self
12- from fastapi_forge .string_utils import snake_to_camel , camel_to_snake_hyphen
13+ from fastapi_forge .string_utils import camel_to_snake_hyphen , snake_to_camel
1314
1415BoundedStr = Annotated [str , Field (..., min_length = 1 , max_length = 100 )]
1516SnakeCaseStr = Annotated [BoundedStr , Field (..., pattern = r"^[a-z][a-z0-9_]*$" )]
1617ModelName = SnakeCaseStr
1718FieldName = SnakeCaseStr
1819BackPopulates = Annotated [str , Field (..., pattern = r"^[a-z][a-z0-9_]*$" )]
1920ProjectName = Annotated [
20- BoundedStr , Field (..., pattern = r"^[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?$" )
21+ BoundedStr ,
22+ Field (..., pattern = r"^[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?$" ),
2123]
2224
2325
@@ -55,19 +57,23 @@ def _validate(self) -> Self:
5557 """Validate field constraints."""
5658 if self .primary_key :
5759 if self .nullable :
58- raise ValueError ("Primary key cannot be nullable." )
60+ msg = "Primary key cannot be nullable."
61+ raise ValueError (msg )
5962 if not self .unique :
6063 self .unique = True
6164
6265 metadata = self .metadata
63- if metadata .is_created_at_timestamp or metadata .is_updated_at_timestamp :
64- if self .type != FieldDataType .DATETIME :
65- raise ValueError (
66- "Create/update timestamp fields must be of type DateTime."
67- )
66+ if (
67+ metadata .is_created_at_timestamp or metadata .is_updated_at_timestamp
68+ ) and self .type != FieldDataType .DATETIME :
69+ msg = "Create/update timestamp fields must be of type DateTime."
70+ raise ValueError (
71+ msg ,
72+ )
6873
6974 if metadata .is_foreign_key and self .type != FieldDataType .UUID :
70- raise ValueError ("Foreign Keys must be of type UUID." )
75+ msg = "Foreign Keys must be of type UUID."
76+ raise ValueError (msg )
7177 return self
7278
7379 @computed_field
@@ -112,7 +118,8 @@ class ModelRelationship(_Base):
112118 def _validate_field_name (cls , value : str ) -> str :
113119 """Ensure relationship field names end with '_id'."""
114120 if not value .endswith ("_id" ):
115- raise ValueError ("Relationship field names must end with '_id'." )
121+ msg = "Relationship field names must end with '_id'."
122+ raise ValueError (msg )
116123 return value
117124
118125 @computed_field
@@ -189,7 +196,7 @@ def _validate(self) -> Self:
189196 ]
190197 if len (unque_relationships ) != len (set (unque_relationships )):
191198 raise ValueError (
192- f"Model '{ self .name } ' contains duplicate relationship field names."
199+ f"Model '{ self .name } ' contains duplicate relationship field names." ,
193200 )
194201
195202 return self
@@ -232,7 +239,7 @@ def _validate_metadata(self) -> Self:
232239 ]
233240 if missing :
234241 error_message = rule ["error_message" ].format (
235- missing = ", " .join (missing )
242+ missing = ", " .join (missing ),
236243 )
237244 raise ValueError (error_message )
238245
@@ -251,7 +258,7 @@ def get_preview(self) -> "Model":
251258 unique = relation .unique ,
252259 index = relation .index ,
253260 metadata = ModelFieldMetadata (is_foreign_key = True ),
254- )
261+ ),
255262 )
256263
257264 return preview_model
@@ -273,20 +280,23 @@ def _validate_models(self) -> Self:
273280 model_names = [model .name for model in self .models ]
274281 model_names_set = set (model_names )
275282 if len (model_names ) != len (model_names_set ):
276- raise ValueError ("Model names must be unique." )
283+ msg = "Model names must be unique."
284+ raise ValueError (msg )
277285
278286 if self .use_alembic and not self .use_postgres :
279- raise ValueError ("Cannot use Alembic if PostgreSQL is not enabled." )
287+ msg = "Cannot use Alembic if PostgreSQL is not enabled."
288+ raise ValueError (msg )
280289
281290 if self .use_builtin_auth and not self .use_postgres :
282- raise ValueError ("Cannot use built-in auth if PostgreSQL is not enabled." )
291+ msg = "Cannot use built-in auth if PostgreSQL is not enabled."
292+ raise ValueError (msg )
283293
284294 for model in self .models :
285295 for relationship in model .relationships :
286296 if relationship .target_model not in model_names_set :
287297 raise ValueError (
288298 f"Model '{ model .name } ' has a relationship to "
289- f"'{ relationship .target_model } ', which does not exist."
299+ f"'{ relationship .target_model } ', which does not exist." ,
290300 )
291301
292302 return self
@@ -324,7 +334,7 @@ def has_cycle(node):
324334 if has_cycle (model_name ):
325335 raise ValueError (
326336 f"Circular reference detected involving model '{ model_name } '. "
327- "Remove bidirectional relationships between models."
337+ "Remove bidirectional relationships between models." ,
328338 )
329339
330340 return self
0 commit comments