Closed pylint-bot closed 8 years ago
Original comment by BitBucket: ceridwenv, GitHub: ceridwenv:
I've looked both eliminating raise_if_nothing_inferred and raising a custom exception. The first fails because when raise_if_nothing_inferred is called after path_wrapper uses return to raise StopIteration, raise_if_nothing_inferred will raise InferenceError; and because raise_if_nothing_inferred is at the moment catching StopIterations in the other inference generators themselves. Neither of these behaviors can be easily duplicated at the level of the generators themselves. For the second, there are cases where path_wrapper is called after raise_if_nothing_inferred and vice versa, and meanwhile, there are also cases where the same function is wrapped by only one or both. This means that both path_wrapper and raise_if_nothing_inferred can potentially need to raise the custom exception for the other one.
I think this takes us back to the only practical solutions being the two I first proposed.
Original comment by BitBucket: ceridwenv, GitHub: ceridwenv:
One possible workaround when using StopIteration: create two versions of the decorators, one for use on Python < 3.3. and one for use on Python > 3.3. This would require using exec or doing a dynamic import, replacing the explicit raise StopIteration in one version with return in the other.
Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: PCManticore):
We could use StopIteration for now and change later on with a decorator implementation. Another thing is that when 3.7 comes out, we might consider dropping support for Python 2.7, depending how things evolve until then.
Originally reported by: BitBucket: ceridwenv, GitHub: ceridwenv
Several decorators, for instance scoped_nodes.remove_nodes and decorators.raise_if_nothing_inferred, currently raise InferenceErrors that provide no useful information for debugging at all. It's possible to write generic error messages, but that doesn't improve the situation much since, for instance, it's obvious from the stack trace that raise_if_nothing_inferred raised because the generator it's decorating returned an empty iterator, but that doesn't get at why the generator returned an empty iterator. There are really only two reasonable ways I can see to solve this problem.
yield from
in Python 3.3, using StopIteration values is the official method for returning values from a generator. (In fact, these decorators would be greatly simplified by the use ofyield from
in the first place, but maintaining Python 2 compatibility makes that impossible.) The idea is that when the generator terminates, it always adds some information to the StopIteration it raises. If the decorator decides there was an error condition, it uses that information to create a structured InferenceError to raise.I think the first option is better, primarily because it puts the responsibility for figuring out what arguments the InferenceError should have in the right place, but it is maybe more hackish.