forked from cardosofelipe/fast-next-template
Add # pragma: no cover to defensive code sections in validators and CRUD operations
- Mark unreachable code paths in `validators.py` and `base.py` with `# pragma: no cover` for coverage accuracy. - Add comments to clarify defensive code's purpose and usage across methods.
This commit is contained in:
@@ -125,16 +125,22 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
|
|||||||
logger.error(f"Error retrieving multiple {self.model.__name__} records: {str(e)}")
|
logger.error(f"Error retrieving multiple {self.model.__name__} records: {str(e)}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
async def create(self, db: AsyncSession, *, obj_in: CreateSchemaType) -> ModelType:
|
async def create(self, db: AsyncSession, *, obj_in: CreateSchemaType) -> ModelType: # pragma: no cover
|
||||||
"""Create a new record with error handling."""
|
"""Create a new record with error handling.
|
||||||
try:
|
|
||||||
|
NOTE: This method is defensive code that's never called in practice.
|
||||||
|
All CRUD subclasses (CRUDUser, CRUDOrganization, CRUDSession) override this method
|
||||||
|
with their own implementations, so the base implementation and its exception handlers
|
||||||
|
are never executed. Marked as pragma: no cover to avoid false coverage gaps.
|
||||||
|
"""
|
||||||
|
try: # pragma: no cover
|
||||||
obj_in_data = jsonable_encoder(obj_in)
|
obj_in_data = jsonable_encoder(obj_in)
|
||||||
db_obj = self.model(**obj_in_data)
|
db_obj = self.model(**obj_in_data)
|
||||||
db.add(db_obj)
|
db.add(db_obj)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
await db.refresh(db_obj)
|
await db.refresh(db_obj)
|
||||||
return db_obj
|
return db_obj
|
||||||
except IntegrityError as e:
|
except IntegrityError as e: # pragma: no cover
|
||||||
await db.rollback()
|
await db.rollback()
|
||||||
error_msg = str(e.orig) if hasattr(e, 'orig') else str(e)
|
error_msg = str(e.orig) if hasattr(e, 'orig') else str(e)
|
||||||
if "unique" in error_msg.lower() or "duplicate" in error_msg.lower():
|
if "unique" in error_msg.lower() or "duplicate" in error_msg.lower():
|
||||||
@@ -142,11 +148,11 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
|
|||||||
raise ValueError(f"A {self.model.__name__} with this data already exists")
|
raise ValueError(f"A {self.model.__name__} with this data already exists")
|
||||||
logger.error(f"Integrity error creating {self.model.__name__}: {error_msg}")
|
logger.error(f"Integrity error creating {self.model.__name__}: {error_msg}")
|
||||||
raise ValueError(f"Database integrity error: {error_msg}")
|
raise ValueError(f"Database integrity error: {error_msg}")
|
||||||
except (OperationalError, DataError) as e:
|
except (OperationalError, DataError) as e: # pragma: no cover
|
||||||
await db.rollback()
|
await db.rollback()
|
||||||
logger.error(f"Database error creating {self.model.__name__}: {str(e)}")
|
logger.error(f"Database error creating {self.model.__name__}: {str(e)}")
|
||||||
raise ValueError(f"Database operation failed: {str(e)}")
|
raise ValueError(f"Database operation failed: {str(e)}")
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover
|
||||||
await db.rollback()
|
await db.rollback()
|
||||||
logger.error(f"Unexpected error creating {self.model.__name__}: {str(e)}", exc_info=True)
|
logger.error(f"Unexpected error creating {self.model.__name__}: {str(e)}", exc_info=True)
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -111,11 +111,12 @@ def validate_phone_number(phone: str | None) -> str | None:
|
|||||||
raise ValueError('Phone number must start with + or 0 followed by 8-14 digits')
|
raise ValueError('Phone number must start with + or 0 followed by 8-14 digits')
|
||||||
|
|
||||||
# Additional validation to catch specific invalid cases
|
# Additional validation to catch specific invalid cases
|
||||||
if cleaned.count('+') > 1:
|
# NOTE: These checks are defensive code - the regex pattern above already catches these cases
|
||||||
|
if cleaned.count('+') > 1: # pragma: no cover
|
||||||
raise ValueError('Phone number can only contain one + symbol at the start')
|
raise ValueError('Phone number can only contain one + symbol at the start')
|
||||||
|
|
||||||
# Check for any non-digit characters (except the leading +)
|
# Check for any non-digit characters (except the leading +)
|
||||||
if not all(c.isdigit() for c in cleaned[1:]):
|
if not all(c.isdigit() for c in cleaned[1:]): # pragma: no cover
|
||||||
raise ValueError('Phone number can only contain digits after the prefix')
|
raise ValueError('Phone number can only contain digits after the prefix')
|
||||||
|
|
||||||
return cleaned
|
return cleaned
|
||||||
|
|||||||
Reference in New Issue
Block a user