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

Chain exceptions where appropriate #15986

Open
eric-wieser opened this issue Apr 15, 2020 · 16 comments
Open

Chain exceptions where appropriate #15986

eric-wieser opened this issue Apr 15, 2020 · 16 comments

Comments

@eric-wieser
Copy link
Member

@eric-wieser eric-wieser commented Apr 15, 2020

Picking up from #15731, there are many places in numpy where we do something like:

try:
    something_which_throws_typeError
except TypeError:
    raise ValueError("a clearer explanation of what went wrong")

It would produce a marginally clearer error if we could change these to use traceback chaining. Our two options are either:

  1. The inner error provides valuable information that is not present in the outer error. We should use from e.
    try:
        something_which_throws_typeError
    except TypeError as e:
        raise ValueError("a clearer explanation of what went wrong") from e
  2. The inner error provides no valuable information that is not present in the outer error. We should use from None:
    try:
        some_dict[name]
    except KeyError:
        raise ValueError("The name %s is not supported") from None

An example of such a change would be this line of this otherwise-discarded patch.

For now, I would recommend we only apply this to cases where the exception is thrown unconditionally, as other cases can be more nuanced.


Please see this list for potential places to contribute. Special thanks to @nkleinbaer for compiling the list!

@seberg
Copy link
Member

@seberg seberg commented Apr 17, 2020

Sure @JanukanS, thanks. We don't usually assign issues. So you can search for these type of calls and simply open a PR with suggested changes linking this issue.

@keremh
Copy link
Contributor

@keremh keremh commented Apr 18, 2020

Hi @seberg
I determined the part to be changed, can i work on this issue too?

seberg pushed a commit that referenced this issue May 14, 2020
This solution is related to the issue #15986. I also made a change to the newer string formatting.
Uses NameError, which prints nicer, and is actually the more correct error type.

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
Co-authored-by: Ross Barnowski <rossbar@berkeley.edu>
anirudh2290 added a commit to anirudh2290/numpy that referenced this issue May 28, 2020
This solution is related to the issue numpy#15986. I also made a change to the newer string formatting.
Uses NameError, which prints nicer, and is actually the more correct error type.

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
Co-authored-by: Ross Barnowski <rossbar@berkeley.edu>
@ayao451
Copy link

@ayao451 ayao451 commented Jun 30, 2020

Can I work on this issue? It is my first issue and I want to give it a try!

seberg pushed a commit that referenced this issue Jun 30, 2020
this solution is related to the following issue #15986


Co-authored-by: Ross Barnowski <rossbar@berkeley.edu>
@rossbar
Copy link
Contributor

@rossbar rossbar commented Jul 1, 2020

@ayao451 please feel free. A good place to start might be by checking the PRs linked in this issue: exception chaining has been added in quite a few places, and a few other instances have been identified as better off unchanged (e.g. nested exceptions in the test suite).

@rossbar
Copy link
Contributor

@rossbar rossbar commented Jul 12, 2020

A lot of these instances have been fixed (thanks to all the contributors for this!) It would be nice to have a "definition of done" for this issue if anyone wants to do a little forensics to see what's already been tackled, what's been reviewed and determined better left as-is, and what still remains to be done.

@nkleinbaer
Copy link

@nkleinbaer nkleinbaer commented Jul 17, 2020

@rossbar I think I can help the 'forensics' you describe above. My thought was to create a regex expression to search for instances of nested exceptions in the codebase (excluding tests). Something like (\s*)except .*\n(\1\s+.*\n)*\1\s+raise to capture the indentation level of the original except statement, then searching for raise within that indent block.

Then I could cross-reference that list with those instances that have already been addressed in the PRs above, and make a table of what's been addressed and what still needs to be reviewed.

Does that seem like a reasonable approach? I'm a complete beginner, found this issue through the 'good first issue' tag, so just want to ensure I'm not going down a rabbit hole or creating additional confusion.

@rossbar
Copy link
Contributor

@rossbar rossbar commented Jul 18, 2020

@nkleinbaer that approach sounds reasonable, and I think tabulating the results in this issue would be very useful. Even if the cross-referencing proves to be difficult to automate, having a list of all of the potential instances for exception chaining would help finish off this issue. If you are interested in taking this on I think that'd be great! Feel free ping with any questions/comments.

@nkleinbaer
Copy link

@nkleinbaer nkleinbaer commented Jul 18, 2020

OK, to start off here is a table of the files that have been touched in reference to this issue, the number of instances reviewed, the action taken, and associated PRs. I've used the nomenclature "Implemented exception chaining" to indicate something of the form except SomeError as e: raise SomeOtherError from e and "Explicitly silenced exception chaining" to indicate the form except SomeError as e: raise SomeOtherError from None. Please correct if the this can be phrased better.

In some cases my regex found additional instances of 'nested' exceptions in these files that I do not see included in the PRs. It may be the case that they were intentionally left as is, but because I cannot find any documented 'review' of them I have included them for completeness.

File Action Taken Associated PR(s) Comments
ctypeslib.py 1 instance each: explicitly silenced exception chaining and implemented exception chaining #16418 1 additional instances may need review
except OSError:
core/_dtype.py 1 instance(s): explicitly silenced exception chaining #16418
core/_internal.py 2 instance(s): explicitly silenced exception chaining #16747
core/fromnumeric.py 1 instance(s): implemented exception chaining #16418
core/memap.py 1 instance(s): explicitly silenced exception chaining #16067
core/records.py 2 instance(s): implemented exception chaining #16418 1 additional instance may need review
except Exception:
core/code_generators/generate_umath.py 1 instance(s): implemented exception chaining #16254
distutils/command/build_clib.py 1 instance(s): implemented exception chaining #16032
distutils/command/build_ext.py 1 instance(s): implemented exception chaining #16042
lib/_datasource.py 1 instance(s): Completely removed nested exception -> left inner exception by itself #16761
lib/hisograms.py 1 instance(s): implemented exception chaining #16064 1 additional instance added in #16129 - seems to implement exception chaining correctly but may need review
lib/index_tricks.py 1 instance(s): implemented exception chaining #16064 1 additional instance needs review
except (ValueError, TypeError):
lib/npyio.py 2 instance(s): implemented exception chaining #16121 A bit confused on what happened here. My regex finds 8 instances total - I think all have been reviewed and some were determined to be better left as is in #16218, may be worth a second look
lib/shape_base.py 1 instance(s): explicitly silenced exception chaining #16064 2 additional instances may need review
except TypeError:
except TypeError:
lib/ufunclike.py 2 instance(s): implemented exception chaining #16064
linalg/linalg.py 2 instance(s): implemented exception chaining #16061
ma/core.py 1 instance(s): explicitly silenced exception chaining #16067 3 additional instances may need review
except ValueError:
except (OverflowError, ValueError):
except IndexError:
matrixlib/defmatrix.py 1 instance(s): explicitly silenced exception chaining #16215
polynomial/polyutils.py 2 instance(s): implemented exception chaining #16061
@nkleinbaer
Copy link

@nkleinbaer nkleinbaer commented Jul 18, 2020

And here is a table of additional files/instances found by my regex that have NOT yet been reviewed in a PR related to this issue. Some of these look like they are already handling exception chaining properly (example einsumfunc.py), but again included here for completeness because I see no documentation of an explicit review.

File Instances found by Regex Instances
init.py 2
except ImportError:
except AssertionError:
compat/py3k.py 1
except AttributeError:
core/_type_aliases.py 1
except StopIteration:
core/einsumfunc.py 2
except TypeError as e:
except TypeError as e:
core/code_generators/genapi.py 1
except Exception:
distutils/conv_template.py 4
except KeyError:
except ValueError as e:
except ValueError as e:
except ValueError as e:
distutils/mingw32ccompiler.py 1
except KeyError:
distutils/unixccompiler.py 2
except DistutilsExecError as e:
except DistutilsExecError as e:
distutils/command/config.py 3
except IOError as e:
except (DistutilsExecError, CompileError) as e:
except Exception:
distutils/fcompiler/init.py 2
except DistutilsExecError as e:
except DistutilsExecError as e:
distutils/fcompiler/compaq.py 3
except AttributeError as e:
except IOError as e:
except ValueError as e:
distutils/fcompiler/environment.py 1
fft/_pocketfft.py 1
except KeyError:
lib/arraypad.py 1
raise ValueError("unsupported keyword arguments for mode '{}': {}"
lib/arraysetops.py 2
except np.AxisError:
except TypeError:
lib/format.py 4
except struct.error:
except SyntaxError as e:
except TypeError:
except UnicodeError as err:
linalg/lapack_lite/make_lite.py 1
except subprocess.CalledProcessError:
ma/mrecords.py 3
except (TypeError, KeyError):
except Exception:
except (TypeError, KeyError):
ma/timer_comparison.py 1
except ValueError:
polynomial/_polybase.py 2
except ZeroDivisionError as e:
except ZeroDivisionError as e:
@rossbar
Copy link
Contributor

@rossbar rossbar commented Jul 19, 2020

Thanks for taking the time to put this report together @nkleinbaer , this is a really nice review of the current state of things!

I think the most effective way to present the information to help close this issue would be if we could take all of the instances that you found in your regex search, and list them using a list of checkboxes, e.g.

 - [x] https://github.com/numpy/numpy/blob/6ef5ec39cdfaf77aa4600ec2e3bf9f679a4fd527/numpy/ctypeslib.py#L151
 - [ ] https://github.com/numpy/numpy/blob/6ef5ec39cdfaf77aa4600ec2e3bf9f679a4fd527/numpy/__init__.py#L127
 ...

where instances that have been changed or reviewed get a check, and instances that haven't been addressed yet are left un-checked. That way, we have a running list of the instances where a decision has been made (whether to chain exceptions, use from None, or leave as-is) so that contributors can focus on the remaining ones.

This should give us a list like:

which I believe GitHub will summarize in a progress bar for the issue.

If it is easy for you to re-organize your results in this way and you don't mind the extra effort, it'd be great if you could add a list formatted as described in a comment below, then I will take the list and move it up to the top comment so it is more visible. You've already done plenty though, so if you don't have the bandwidth that's totally fine - just let me know and I'll organize the list using your results. Thanks for all you've done so far!

@nkleinbaer
Copy link

@nkleinbaer nkleinbaer commented Jul 20, 2020

Sure, I can do that! I actually wanted to have check boxes in the tables above, but couldn't figure out how to do the formatting (not sure if possible at all). Mega-checklist to follow.

@nkleinbaer
Copy link

@nkleinbaer nkleinbaer commented Jul 20, 2020

@rossbar
Copy link
Contributor

@rossbar rossbar commented Jul 21, 2020

@nkleinbaer I wasn't able to add the full list to the top comment (trying to do so gave github fits), so I've linked to it instead. Many thanks for compiling it!

@nomanarshad94
Copy link
Contributor

@nomanarshad94 nomanarshad94 commented Jul 27, 2020

Hi, picked this file numpy/numpy/lib/arraypad.py to update exceptions and created a pull request.

@applemonkey496
Copy link

@applemonkey496 applemonkey496 commented Aug 19, 2020

I found more: #17108.

seberg pushed a commit that referenced this issue Sep 3, 2020
This edit is relation to issue gh-15986.
Chained exception in shape_base.py
@eric-wieser eric-wieser reopened this Sep 16, 2020
@mattip
Copy link
Member

@mattip mattip commented Oct 7, 2020

In the recent developer meeting we discussed this issue, which is pretty low on the benefit/cost ratio. We would like to suggest that contributors show the output from the error. This will require you think about the error: is the code path actually hit? Does it make sense to chain the exception?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants
You can’t perform that action at this time.