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

Make error handling more useful and Pythonic #1085

Open
4 tasks
nmoroze opened this issue Jul 15, 2022 · 0 comments
Open
4 tasks

Make error handling more useful and Pythonic #1085

nmoroze opened this issue Jul 15, 2022 · 0 comments

Comments

@nmoroze
Copy link
Contributor

nmoroze commented Jul 15, 2022

Based on some user feedback, I've been thinking about how to improve our SC error handling.

I think we should try to adhere to the following principles:

  • Use built-in ValueError and TypeError where appropriate
    • We solely use SiliconCompilerError for exceptions, but it's considered good practice to use these built-in types when appropriate, since they have standardized meetings
  • Raise errors close to public API waterline
    • The main piece of feedback that inspired this issue is that SC tracebacks can be confusing
    • Both @WRansohoff and I have looked into this, and it seems to be considered bad practice to attempt to modify tracebacks, even for readability
    • The best-practice approach seems to be to be thoughtful about where exceptions are raised, and in some cases catch exceptions that occur deep in the implementation and raise a fresh one in the top-level public API call
    • Note: our self.error() approach works against us here, since it adds a layer to the traceback. I'm not sure if it's worth doing anything at this point **
  • Gracefully catch any errors that may arise
  • Document when an API method may raise an exception

Some proposed changes based on these principles:

  • Make chip.error() take in an optional exception type to throw as a kwarg
    • This will allow for raising TypeError and ValueError
  • Make set()/get()/add() errors cleaner
    • These errors are common since it's easy to make a mistake in input, and the extra layer of _search() clutters the traceback a bit
    • _search() can be made to just raise a custom exception type directly (a custom type is better to ensure we don't accidentally swallow other errors)
    • set()/get()/add() can catch the internal exceptions and raise a ValueError or TypeError
  • Audit other chip.error() calls to make sure they throw the correct exception type
  • Document which public API calls may raise a SiliconCompilerError and when

I think we can keep this issue open until we have a chance to discuss and implement these proposals. After that, we can close the issue but we should keep these principles in mind going forward, and open issues if we notice existing code that violates them.

** A somewhat radical idea we could do to fix the chip.error() in the traceback could be to throw exceptions directly in the code and then put a decorator on public API methods, but this might not be that worthwhile:

def exc_decorator(func):
    def wrap(self, *args, **kwargs):
        try:
            return func(self, *args, **kwargs)
        except SCOptionalTypeError as e:
            msg = str(e)
            if not self.get('option', 'continue'):
                raise TypeError(msg) from None
            else:
                self.logger.error(msg)
                self._error = True
        except SCOptionalValueError as e:
            # ...
        except SCOptionalError as e:
            # ... 

    return wrap
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

No branches or pull requests

1 participant