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

Deriving all custom error from Exception and related #2671

Merged
merged 9 commits into from
Jan 19, 2024

Conversation

germa89
Copy link
Collaborator

@germa89 germa89 commented Jan 16, 2024

I'm not very convinced on this one...

The idea is to have all the MAPDL error classes deriving from one (MapdlException), so we can do something like:

try:
    mapdl = launch_mapdl()
except MapdlException:
    # Exception raised by PyMAPDL handleing this different
    handle_pymapdl_exception()
except Exception:
    # handles everything else

With the current implementation, you can do this too:

try:
    raise MapdlValueError
except MapdlValueError:
    # this is activated (ofc)
    handle_value_error()
except MapdlException:
    # this could be also activated
    handle_value_error()
except MapdlException:
    # this could be also activated
    handle_value_error()
except Exception:
    # this could be also activated
    handle_value_error()

I think it could add value, but it does generate maybe complicated inheritance relationships:

graph TD;
    Exception-->ValueError;
    Exception-->MapdlException;
    ValueError-->MapdlValueError;
    MapdlException--> MapdlValueError;

Because MapdlValueError inheritates from ValueError(which inheritates from Exception) and from MapdlException (which inheritates from Exception).
This creates a "diamond" which is not recommended diamond problem

Surely this classes are simple, and we are only overwritting __init__ method... if anything, we can always go back?

Related (but not much) #2653

Pinging @ansys/pyansys-core for technical feedback. Also pinging @koubaa @greschd

@ansys-reviewer-bot
Copy link
Contributor

Thanks for opening a Pull Request. If you want to perform a review write a comment saying:

@ansys-reviewer-bot review

@github-actions github-actions bot added Enhancement Improve any current implemented feature New Feature Request or proposal for a new feature labels Jan 16, 2024
@germa89 germa89 self-assigned this Jan 16, 2024
@germa89
Copy link
Collaborator Author

germa89 commented Jan 16, 2024

I think it could add value, but it does generate maybe complicated inheritance relationships:

Here it goes: https://github.com/ansys/pymapdl/actions/runs/7544725242/job/20538709809?pr=2671#step:3:58

GitHub
Pythonic interface to MAPDL. Contribute to ansys/pymapdl development by creating an account on GitHub.

@greschd
Copy link
Member

greschd commented Jan 16, 2024

Typically I wouldn't worry about the diamond inheritance if all you're doing is inheriting from "empty" classes for the purposes of enabling an isinstance check.

However, I also found this: https://docs.python.org/3/library/exceptions.html#inheriting-from-built-in-exceptions

It’s recommended to only subclass one exception type at a time to avoid any possible conflicts between how the bases handle the args attribute, as well as due to possible memory layout incompatibilities.

I'm not entirely sure if this guidance applies here. As the MapdlException's base Exception is anyway already in the inheritance chain, I would tend to think it's not a problem.
But, you could also change it to be [1]

class MapdlExceptionMixin:
    """Mixin class to mark an exception type as originating from MAPDL"""

which would avoid inheriting from the built-in exceptions twice.

[1] remove the base Exception, and rename MapdlException to MapdlExceptionMixin to indicate it's not a standalone exception class.

Python documentation
In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any excep...

@greschd
Copy link
Member

greschd commented Jan 16, 2024

Here it goes: https://github.com/ansys/pymapdl/actions/runs/7544725242/job/20538709809?pr=2671#step:3:58

I think that might've worked if MapdlException was the right-hand-side in that inheritance.

GitHub
Pythonic interface to MAPDL. Contribute to ansys/pymapdl development by creating an account on GitHub.

Copy link

codecov bot commented Jan 16, 2024

Codecov Report

Attention: 1 lines in your changes are missing coverage. Please review.

Comparison is base (183923c) 84.81% compared to head (520c19f) 82.86%.
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2671      +/-   ##
==========================================
- Coverage   84.81%   82.86%   -1.96%     
==========================================
  Files          47       47              
  Lines        9313     9319       +6     
==========================================
- Hits         7899     7722     -177     
- Misses       1414     1597     +183     

@germa89
Copy link
Collaborator Author

germa89 commented Jan 16, 2024

Here it goes: https://github.com/ansys/pymapdl/actions/runs/7544725242/job/20538709809?pr=2671#step:3:58

I think that might've worked if MapdlException was the right-hand-side in that inheritance.

this one was an easy one because DeprecationError inheritate also from MapdlException. So I just removed one here: ec36e9a

GitHub
Pythonic interface to MAPDL. Contribute to ansys/pymapdl development by creating an account on GitHub.

@germa89
Copy link
Collaborator Author

germa89 commented Jan 16, 2024

Typically I wouldn't worry about the diamond inheritance if all you're doing is inheriting from "empty" classes for the purposes of enabling an isinstance check.

However, I also found this: https://docs.python.org/3/library/exceptions.html#inheriting-from-built-in-exceptions

It’s recommended to only subclass one exception type at a time to avoid any possible conflicts between how the bases handle the args attribute, as well as due to possible memory layout incompatibilities.

I'm not entirely sure if this guidance applies here. As the MapdlException's base Exception is anyway already in the inheritance chain, I would tend to think it's not a problem. But, you could also change it to be [1]

class MapdlExceptionMixin:
    """Mixin class to mark an exception type as originating from MAPDL"""

which would avoid inheriting from the built-in exceptions twice.

[1] remove the base Exception, and rename MapdlException to MapdlExceptionMixin to indicate it's not a standalone exception class.

Python documentation**Built-in Exceptions**In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any excep...

I'm also in the opinion on going ahead because as you mention the classes are not really complex and they are only for catching in try and isinstance.

Thank you a lot for your review @greschd !!

Python documentation
In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any excep...

@germa89
Copy link
Collaborator Author

germa89 commented Jan 17, 2024

Interesting read: http://python-history.blogspot.com/2010/06/method-resolution-order.html

In languages that use multiple inheritance, the order in which base classes are searched when looking for a method is often called the Metho...

Copy link
Contributor

@clatapie clatapie left a comment

Choose a reason for hiding this comment

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

LGTM!

src/ansys/mapdl/core/errors.py Show resolved Hide resolved
@germa89 germa89 merged commit 5ffde4e into main Jan 19, 2024
29 checks passed
@germa89 germa89 deleted the feat/deriving-all-errors-from-one branch January 19, 2024 08:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Improve any current implemented feature New Feature Request or proposal for a new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants