Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #106: improve exception handling in fertiscan #199

Merged
merged 6 commits into from
Oct 28, 2024

Conversation

k-allagbe
Copy link
Member

@k-allagbe k-allagbe commented Oct 11, 2024

Changes:

  • 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.
Metadata exceptions hierarchy:

    Exception
    |__MetadataError
       |__BuildInspectionImportError
       |__BuildInspectionExportError
       |__NPKError
  • 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:

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

@k-allagbe k-allagbe linked an issue Oct 11, 2024 that may be closed by this pull request
@k-allagbe k-allagbe force-pushed the 106-improve-exception-handling branch 2 times, most recently from 28ac44a to f13b3bc Compare October 11, 2024 14:47
@k-allagbe k-allagbe force-pushed the 106-improve-exception-handling branch from f13b3bc to 98354ad Compare October 11, 2024 21:29
@k-allagbe k-allagbe force-pushed the 106-improve-exception-handling branch from d943f6e to f14f276 Compare October 11, 2024 21:43
@k-allagbe k-allagbe force-pushed the 106-improve-exception-handling branch from c9f882e to 0903c45 Compare October 11, 2024 22:24
@k-allagbe k-allagbe marked this pull request as ready for review October 11, 2024 22:30
@k-allagbe k-allagbe requested review from a team as code owners October 11, 2024 22:30
fertiscan/db/metadata/errors.py Outdated Show resolved Hide resolved
fertiscan/db/queries/label/__init__.py Show resolved Hide resolved
fertiscan/db/queries/label/__init__.py Outdated Show resolved Hide resolved
fertiscan_pyproject.toml Outdated Show resolved Hide resolved
fertiscan_pyproject.toml Show resolved Hide resolved
@k-allagbe k-allagbe force-pushed the 106-improve-exception-handling branch from 70ca3e9 to 561b54d Compare October 17, 2024 03:14
@k-allagbe k-allagbe force-pushed the 106-improve-exception-handling branch from 561b54d to bdb058f Compare October 17, 2024 04:33
Copy link
Contributor

@Francois-Werbrouck Francois-Werbrouck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a fresh review, I think the error file will help maintain the project in the long run!

fertiscan/db/queries/errors.py Show resolved Hide resolved
@k-allagbe
Copy link
Member Author

k-allagbe commented Oct 28, 2024

This issue will not fix #108 as that is core datastore code that might affect nachet.

@k-allagbe k-allagbe merged commit 1ecfdeb into main Oct 28, 2024
8 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve Exception Handling
3 participants