On 17 July 2017 at 23:06, Nathaniel Smith <njs@pobox.com> wrote:
On Mon, Jul 17, 2017 at 5:56 AM, Nick Coghlan <ncoghlan@gmail.com> wrote:
As an added bonus: the frontend could display the exception message as part of executing the fallback.
I can live with this, but I wrote up a rationale for why it's somewhat worse than the alternative: https://mail.python.org/pipermail/distutils-sig/2017-July/030901.html
So my request is that if you're going to insist on this can you provide some similar rationale for why?
Sure: because of the way magic return values fail if the *frontend* doesn't check for them. That is, if we make the protocol "return NotImplemented", then the likely symptom of a missing check in a frontend is going to be something like this (on 3.6+):
open(NotImplemented) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: expected str, bytes or os.PathLike object, not NotImplementedType
Or, on Python 2.7, the even more cryptic:
open(NotImplemented) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: coercing to Unicode: need string or buffer, NotImplementedType found
And on earlier versions of Python 3.x:
open(NotImplemented) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: invalid file: NotImplemented
And any associated exception traceback won't point to the offending unchecked call to backend.build_sdist, it will point to the first attempted *use* of that return value as a filename. By contrast, if we make the error signal "raise NotImplementedError", then a missing check in the frontend will not only reliably give a traceback that points to the failed build_sdist call (since NotImplementedError will be treated the same as any other exception by default), but it will also include any specific message that the backend developers chose to provide. If backend implementors want to ensure that it's categorically impossible for NotImplementedError to escape unexpectedly, they can write their build_sdist like this: def build_sdist(sdist_directory, config_settings=None): try: problem = check_sdist_preconditions(sdist_directory, config_settings) except NotImplementedError as exc: raise RuntimeErrror("Unexpected NotImplementedError when checking sdist preconditions") from exc if problem: raise NotImplementedError(problem) try: return _make_sdist(sdist_directory, config_settings) except NotImplementedError as exc: raise RuntimeErrror("Unexpected NotImplementedError when making sdist") from exc However, Python APIs letting NotImplementedError escape is rare enough that even I'd consider writing a build_sdist implementation that way as being overly paranoid :) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia