For each of metadata and queries, there now is a module for all the errors.
The errors now have a hierarchy which helps when handling a group of exceptions at once
Query exceptions hierarchy:
Exception
|__QueryError
|__InspectionQueryError
|__LabelInformationQueryError
|__LabelDimensionQueryError
|__MetricQueryError
|__UnitQueryError
|__ElementCompoundQueryError
|__MicronutrientQueryError
|__GuaranteedAnalysisQueryError
|__OrganizationQueryError
|__OrganizationInformationQueryError
|__LocationQueryError
|__RegionQueryError
|__ProvinceQueryError
|__SpecificationQueryError
|__SubLabelQueryError
|__SubTypeQueryError
Each QueryError sub type exception has specific errors related to creation, retrieval, updating, and deletion, as well as a 'not found' error.
Because the error handling pattern is the same for pretty much all the query functions, we use a decorator to minimize code repetition:
def handle_query_errors(error_cls=QueryError):
"""Decorator for handling query errors."""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except QueryError:
raise
except Error as db_error:
raise error_cls(f"Database error: {db_error}") from db_error
except Exception as e:
raise error_cls(f"Unexpected error: {e}") from e
return wrapper
return decorator
The code using a decorator:
```python
@handle_query_errors(LabelInformationRetrievalError)
def get_label_information_json(cursor, label_info_id) -> dict:
query = """
SELECT get_label_info_json(%s);
"""
cursor.execute(query, (str(label_info_id),))
label_info = cursor.fetchone()
if label_info is None or label_info[0] is None:
raise LabelInformationNotFoundError(
"Error: could not get the label information: " + str(label_info_id)
)
return label_info[0]
is equivalent to:
def get_label_information_json(cursor, label_info_id) -> dict:
try:
query = """
SELECT get_label_info_json(%s);
"""
cursor.execute(query, (str(label_info_id),))
label_info = cursor.fetchone()
if label_info is None or label_info[0] is None:
raise LabelInformationNotFoundError(
"Error: could not get the label information: " + str(label_info_id)
)
return label_info[0]
except QueryError:
raise
except Error as db_error:
raise LabelInformationRetrievalError(f"Database error: {db_error}") from db_error
except Exception as e:
raise LabelInformationRetrievalError(f"Unexpected error: {e}") from e
Note that LabelInformationNotFoundError is a QueryError.
Changes:
Because the error handling pattern is the same for pretty much all the query functions, we use a decorator to minimize code repetition:
is equivalent to:
Note that
LabelInformationNotFoundError
is aQueryError
.