bpo-37757: https://bugs.python.org/issue37757 This issue describes some corner cases in PEP 572 (assignment expressions) syntax that haven’t been implemented yet. The PEP currently says: "The two invalid cases listed above raise TargetScopeError, a new subclass of SyntaxError (with the same signature).” The PEP doesn’t really go into the rationale for why a new exception is being defined, and in the issue I’ve argued that we should just raise SyntaxError in those cases. To me, “TargetScopeError” is pretty obscure and doesn’t give users an obvious clue as to what’s going wrong, without searching the interwebs. Nick argues (apologies if I’m misrepresenting you!): "I believe our main motivation for separating it out was the fact that even though TargetScopeError is a compile-time error, the affected code is syntactically fine - there are just issues with unambiguously inferring the intended read/write location for the affected target names. (Subclassing SyntaxError is then a pragmatic concession to the fact that "SyntaxError" also de facto means "CompilationError”)” Serhiy points out that we have IndentationError and TabError subclasses of SyntaxError, but those feel different to me because the exception names themselves are clear and descriptive, and lead to obvious actionable remedies. Guido then suggests we take the discussion here, thus this email. It would be a very minor update to the PEP, but I think it’s useful to resolve before the last push for PEP 572 implementation gets completed. Rather than just a vote, if you have a rationale for one over the other, I’d love to hear it. Feel free to weigh in here or on the issue. Cheers, -Barry
[Barry Warsaw <barry@python.org>]
bpo-37757: https://bugs.python.org/issue37757
Really couldn't care less whether it's TargetScopeError or SyntaxError, but don't understand the only rationale given here for preferring the latter:
To me, “TargetScopeError” is pretty obscure and doesn’t give users an obvious clue as to what’s going wrong, without searching the interwebs.
Whereas SyntaxError would give no clue whatsoever, and nothing useful to search for. In contrast, a search for TargetScopeError would presumably find a precisely relevant explanation as the top hit (indeed, it already does today). I don't care because it's unlikely an error most people will make at all - or, for those too clever for their own good, make more than once ;-)
On Aug 8, 2019, at 10:41, Tim Peters <tim.peters@gmail.com> wrote:
Whereas SyntaxError would give no clue whatsoever, and nothing useful to search for. In contrast, a search for TargetScopeError would presumably find a precisely relevant explanation as the top hit (indeed, it already does today).
I don't care because it's unlikely an error most people will make at all - or, for those too clever for their own good, make more than once ;-)
I agree it’s probably going to be a rare occurrence. I suppose it just bothers me that when it does happen, we’ll present an obscurely named exception that will essentially force users to search for it. But maybe they’ll have to anyway. OTOH, maybe we can find an even better name, like EggManError or KooKooKaChooError. I-am-the-Walrus-lyrics-won’t-help-you-at-all-ly y’rs, -Barry
On Fri, Aug 9, 2019 at 4:00 AM Barry Warsaw <barry@python.org> wrote:
On Aug 8, 2019, at 10:41, Tim Peters <tim.peters@gmail.com> wrote:
Whereas SyntaxError would give no clue whatsoever, and nothing useful to search for. In contrast, a search for TargetScopeError would presumably find a precisely relevant explanation as the top hit (indeed, it already does today).
I don't care because it's unlikely an error most people will make at all - or, for those too clever for their own good, make more than once ;-)
I agree it’s probably going to be a rare occurrence. I suppose it just bothers me that when it does happen, we’ll present an obscurely named exception that will essentially force users to search for it. But maybe they’ll have to anyway. OTOH, maybe we can find an even better name, like EggManError or KooKooKaChooError.
ConfusedWalrusError? :) I think it's good to have a subclass of SyntaxError for this. It's way easier to recognize what's going on when the exception name makes it clear that this isn't a typo. Trying to be too descriptive in the name will just make it too long, but maybe AmbiguousScopeError would be better? ChrisA
On 08.08.2019 20:54, Barry Warsaw wrote:
On Aug 8, 2019, at 10:41, Tim Peters <tim.peters@gmail.com> wrote:
Whereas SyntaxError would give no clue whatsoever, and nothing useful to search for. In contrast, a search for TargetScopeError would presumably find a precisely relevant explanation as the top hit (indeed, it already does today).
I don't care because it's unlikely an error most people will make at all - or, for those too clever for their own good, make more than once ;-) I agree it’s probably going to be a rare occurrence. I suppose it just bothers me that when it does happen, we’ll present an obscurely named exception that will essentially force users to search for it. But maybe they’ll have to anyway. OTOH, maybe we can find an even better name, like EggManError or KooKooKaChooError.
It looks like you are forgetting that an exception presented to the user is accompanied with an explanation text. Something like "Cannot assign `i` because this name is already used as a comprehension's loop variable" would clarify what exactly they did wrong.
I-am-the-Walrus-lyrics-won’t-help-you-at-all-ly y’rs, -Barry
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/SSPDFUPP...
-- Regards, Ivan
I agree that it should be a SyntaxError as it's a semantic issue regarded to syntax. For instance, we already use SyntaxError for when a `return` statement is outside of a function and I view this as the same sort of error. And I think with an appropriately descriptive message like Ivan pointed out will handle any confusion, especially since this exception will very rarely be caught and if it is it very likely won't be caught _just_ for the walrus operator and no other syntax-related error.
Barry Warsaw wrote:
The PEP doesn’t really go into the rationale for why a new exception is being defined, and in the issue I’ve argued that we should just raise SyntaxError in those cases. To me, “TargetScopeError” is pretty obscure and doesn’t give users an obvious clue as to what’s going wrong, without searching the interwebs.
Barry Warsaw wrote:
Serhiy points out that we have IndentationError and TabError subclasses of SyntaxError, but those feel different to me because the exception names themselves are clear and descriptive, and lead to obvious actionable remedies.
I find myself in agreement that SyntaxError should be raised for the above reasons, as long as the error message can adequately explain to the user that it's an issue with the scope they're referring to: ``SyntaxError: Invalid scope defined by walrus operator: 'i := 10 for i in range(5)'`` To make it a bit more more succinct, "by walrus operator" could be potentially removed. I don't think there's anything inherently wrong with the users looking up the name of the exception for more information, but it should not be required to gain a basic understanding of what the error is referring to. Also, I'm not entirely convinced that this would be a frequent enough occurrence to justify creating a subclass of SyntaxError instead of simply using a custom message to describe the issue.
On Thu, Aug 08, 2019 at 10:00:01AM -0700, Barry Warsaw wrote:
"The two invalid cases listed above raise TargetScopeError, a new subclass of SyntaxError (with the same signature).”
The PEP doesn’t really go into the rationale for why a new exception is being defined, and in the issue I’ve argued that we should just raise SyntaxError in those cases. To me, “TargetScopeError” is pretty obscure and doesn’t give users an obvious clue as to what’s going wrong, without searching the interwebs.
It's not a syntax error. There's nothing wrong with the syntax per-say: we still have ``target := expression``. There's a problem with the *semantics* not the syntax. The name is perfectly self-descriptive: TargetScopeError means that there's an error with the scope of the target. What else could it mean? What's wrong with having to look up an unfamiliar exception by searching the interwebs? The first few times I hit KeyError, I had no idea what a "key" was (I was a beginner) and if I had internet access, I would have looked it up on the web. I didn't, so I looked it up in the book I was reading. The first times I hit UnboundLocalError, I did have internet access, so I googled it. Once I understood that it meant that the local I was trying to use was unbound, and that "unbound" mean "undefined", all was clear. (Well, not all, I still had to work out why it was undefined. But at least the exception name was more clear.) One of the frustrations I have is that it's near to impossible to programmatically distinguish wrong number of arguments from bad keyword arguments from providing the wrong type of argument without relying on the error message. (And yes, I have needed to do this.) All of these raise the same TypeError, even though only one of them is an actual error with the type: len(1) # An actual TypeError len([], None) # The type of the argument is fine. len(spam=[]) # The type of the argument is fine. Please let's not use SyntaxError for something that's not an error with the syntax. -- Steven
On Aug 8, 2019, at 14:58, Steven D'Aprano <steve@pearwood.info> wrote:
It's not a syntax error. There's nothing wrong with the syntax per-say: we still have ``target := expression``. There's a problem with the *semantics* not the syntax.
I’m not sure that distinction is meaningful though. What you wrote is disallowed, so you have to change your code (i.e. syntax) to avoid the error.
The name is perfectly self-descriptive: TargetScopeError means that there's an error with the scope of the target. What else could it mean?
What’s the scope? What’s *a* scope (in this context)? What’s the target? Nothing about the exception name tells you that it’s a problem with the assignment expression you wrote.
What's wrong with having to look up an unfamiliar exception by searching the interwebs? The first few times I hit KeyError, I had no idea what a "key" was (I was a beginner) and if I had internet access, I would have looked it up on the web. I didn't, so I looked it up in the book I was reading.
But remember that assignment expressions are a relatively advanced topic. Once you learned what a key was — and you have to do that pretty early on in your Python experience — KeyError is perfectly descriptive. So let’s imagine what the user experience would be like with a better named exception to see whether a subclass is worth it. For now let’s call it AssignmentExpressionDisallowedError. If you saw that it would definitely be more descriptive. Is that valuable in the error output? Is it still valuable when you have useful descriptive text?
Please let's not use SyntaxError for something that's not an error with the syntax.
PEP 572 does propose TargetScopeError as a subclass of SyntaxError, so you’re getting a SyntaxError anyway. -Barry
On 8/8/2019 7:28 PM, Barry Warsaw wrote:
On Aug 8, 2019, at 14:58, Steven D'Aprano <steve@pearwood.info> wrote:
It's not a syntax error. There's nothing wrong with the syntax per-say: we still have ``target := expression``. There's a problem with the *semantics* not the syntax.
I’m not sure that distinction is meaningful though. What you wrote is disallowed, so you have to change your code (i.e. syntax) to avoid the error.
I agree with Barry here. For all practical purposes, it's a syntax error. And if we had a more powerful parser, maybe it really would be a syntax error. See Guido's recent PEG parser articles (https://medium.com/@gvanrossum_83706/peg-parsers-7ed72462f97c) where he discusses raising SyntaxError after the parser is finished, in a subsequent pass. Is it really a syntax error if pgen doesn't object to it? In current CPython, the answer is yes. But to the original point: I think the real reason to make this just a SyntaxError, and not a subclass (TargetScopeError) is this: would you ever catch TargetScopeError? If not, why would it need to be its own class? It should just be SyntaxError with a descriptive enough text that the user can figure out what's wrong. I don't see anyone ever writing: try: .. something .. except TargetScopeError: .. handle this .. except SyntaxError: .. handle this differently .. Eric
On 09.08.19 03:53, Eric V. Smith wrote:
On 8/8/2019 7:28 PM, Barry Warsaw wrote:
On Aug 8, 2019, at 14:58, Steven D'Aprano <steve@pearwood.info> wrote:
It's not a syntax error. There's nothing wrong with the syntax per-say: we still have ``target := expression``. There's a problem with the *semantics* not the syntax.
I’m not sure that distinction is meaningful though. What you wrote is disallowed, so you have to change your code (i.e. syntax) to avoid the error.
I agree with Barry here. For all practical purposes, it's a syntax error. And if we had a more powerful parser, maybe it really would be a syntax error. See Guido's recent PEG parser articles (https://medium.com/@gvanrossum_83706/peg-parsers-7ed72462f97c) where he discusses raising SyntaxError after the parser is finished, in a subsequent pass. Is it really a syntax error if pgen doesn't object to it? In current CPython, the answer is yes.
... OT: Thanks for the interesting read! I am excited which way it will continue. -- Christian Tismer :^) tismer@stackless.com Software Consulting : http://www.stackless.com/ Karl-Liebknecht-Str. 121 : https://github.com/PySide 14482 Potsdam : GPG key -> 0xFB7BEE0E phone +49 173 24 18 776 fax +49 (30) 700143-0023
On Thu, Aug 08, 2019 at 04:28:28PM -0700, Barry Warsaw wrote:
On Aug 8, 2019, at 14:58, Steven D'Aprano <steve@pearwood.info> wrote:
It's not a syntax error. There's nothing wrong with the syntax per-say: we still have ``target := expression``. There's a problem with the *semantics* not the syntax.
I’m not sure that distinction is meaningful though. What you wrote is disallowed, so you have to change your code (i.e. syntax) to avoid the error.
I find it difficult to imagine a more meaningful distinction than that between syntax and semantics. I can write something with invalid syntax that you can nevertheless predict the intended semantics: ipmort sys and write something with correct syntax that is almost impossible to determine the semantics without a huge amount of effort: https://github.com/davekch/b/blob/master/b.py (and they say you can't write one-liners in Python...) Should x/0 be a SyntaxError? It too is "disallowed", and we have to change our code. Should None[x] be a SyntaxError? It too is "disallowed", and we have to change our code. I cannot think of a single programming error that doesn't require us to "change your code (i.e. syntax) to avoid the error".
The name is perfectly self-descriptive: TargetScopeError means that there's an error with the scope of the target. What else could it mean?
What’s the scope? What’s *a* scope (in this context)? What’s the target? Nothing about the exception name tells you that it’s a problem with the assignment expression you wrote.
It isn't a requirement for the exception *type* _alone_ to give a complete and detailed explanation of the error and all the background knowledge you need to make sense of it. No other exception lives up to that high standard. Not even ValueError. (If you think "value" is easy enough, you ought to read some of the debates on comp.lang.python.) What's "syntax" mean in the context of programming? (If you can assume the reader doesn't know what scope and target mean, I can assume the reader doesn't know what syntax is.) What's wrong with the syntax? (Nothing. The syntax is fine. Its the semantics we are prohibiting.) [...]
Once you learned what a key was — and you have to do that pretty early on in your Python experience — KeyError is perfectly descriptive.
You can cross out "key" and replace it with "(assignment) target" and "scope", and your comment still applies. These are basic, simple terms in common use, like assignment, global and class. "Scope" is used in the tutorial's fourth chapter: https://docs.python.org/3/tutorial/controlflow.html "Key" in the sense of a dict not until the fifth: https://docs.python.org/3/tutorial/datastructures.html We're not talking about obscure terminology known only to a tiny handful of specialists here.
So let’s imagine what the user experience would be like with a better named exception to see whether a subclass is worth it. For now let’s call it AssignmentExpressionDisallowedError. If you saw that it would definitely be more descriptive.
It's certainly *longer*, but I'm not so sure it describes the problem better. The assignment expression is disallowed. That's implied by the fact that we have an exception in the first place. The important question is why it has been disallowed? - Because it's Tuesday, and they are never allowed on Tuesdays? - Because the assignment target is a read-only name binding? (Python doesn't have those, but a beginner might not know that.) - Because access controls have prevented the assignment? - Or because there's a problem with the scope of the assignment target?
Is that valuable in the error output?
Its certainly more valuable than SyntaxError. I wouldn't choose "Assignment Disallowed" over "Target Scope", but let's go with it. Which conveys more information about the error? "I'm getting a syntax error." "I'm getting an assignment disallowed error." I'm a beginner, my google-fu is not strong, and I get this exception. If I google for SyntaxError without the error message, will I get good quality results? How about if I google for AssignmentDisallowedError?
Please let's not use SyntaxError for something that's not an error with the syntax.
PEP 572 does propose TargetScopeError as a subclass of SyntaxError, so you’re getting a SyntaxError anyway.
I know, and I'm not super happy about that, but at least it's a subclass with a descriptive name. -- Steven
On 09/08/2019 12:50:14, Steven D'Aprano wrote:
On Thu, Aug 08, 2019 at 04:28:28PM -0700, Barry Warsaw wrote: I find it difficult to imagine a more meaningful distinction than that between syntax and semantics. The distinction between syntax and semantics can sometimes be blurred. Certainly in spoken languages. What about program code?
Should x/0 be a SyntaxError? It too is "disallowed", and we have to change our code. No, because x might be an instance of a class (extended numbers?) that allows division by zero.
Should None[x] be a SyntaxError? It too is "disallowed", and we have to change our code.
It's allowable syntax with defined runtime semantics: raise a TypeError if x exists, and a NameError if it isn't. Conceivably some programmer might find a use for it. But since it always raises an exception, it would probably be more helpful in the long run if it *were* a SyntaxError. It *isn't*, because (I assume) detecting this and similar idioms, e.g. {}[0] , would complicate the parser/compiler too much. Your examples show, I claim, that even in program code the distinction between syntax and semantics is not always obvious. I suggest the only watertight definition of a syntax error is something which raises an exception at compile time. Obviously this can depend not only on the code, but also on the compiler. Rob Cliffe
I don't see how this debate can avoid a vote in the Steering Council. -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
[Guido]
I don't see how this debate can avoid a vote in the Steering Council.
FWIW, I found Nick's last post wholly persuasive: back off to SyntaxError for now, and think about adding a more specific exception later for _all_ cases (not just walrus) in which a scope conflict isn't allowed (e.g., his example of declaring a function's formal argument `global` in the function).
On 8/9/2019 11:41 AM, Tim Peters wrote:
[Guido]
I don't see how this debate can avoid a vote in the Steering Council.
FWIW, I found Nick's last post wholly persuasive: back off to SyntaxError for now, and think about adding a more specific exception later for _all_ cases (not just walrus) in which a scope conflict isn't allowed (e.g., his example of declaring a function's formal argument `global` in the function).
Also FWIW: I agree with Nick, except I don't see the point of having an exception that likely no one is ever going to catch. What's the scenario under which you'd want to catch a ScopeConflictException? If it only exists to give more info to a human, just improve the message that goes with SyntaxError in that case. But to answer Guido's question: I think this is a fine issue for the SC to vote on. Eric
On Sat, 10 Aug 2019 at 02:05, Eric V. Smith <eric@trueblade.com> wrote:
On 8/9/2019 11:41 AM, Tim Peters wrote:
[Guido]
I don't see how this debate can avoid a vote in the Steering Council.
FWIW, I found Nick's last post wholly persuasive: back off to SyntaxError for now, and think about adding a more specific exception later for _all_ cases (not just walrus) in which a scope conflict isn't allowed (e.g., his example of declaring a function's formal argument `global` in the function).
Also FWIW: I agree with Nick, except I don't see the point of having an exception that likely no one is ever going to catch. What's the scenario under which you'd want to catch a ScopeConflictException? If it only exists to give more info to a human, just improve the message that goes with SyntaxError in that case.
It's mainly the idea of being able to attach the variable name to the exception as structured data, which an IDE could then use to highlight the offending name without needing to parse the human-readable exception string. Actually making the change would require IDE authors agreeing that it would be helpful to them, though, and they may not need it if they already have their own symbol analysers running. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
Nick and I are now on the same page, so I don’t think we *have* to have a formal SC vote. Cheers, -Barry
On Aug 9, 2019, at 08:28, Guido van Rossum <guido@python.org> wrote:
I don't see how this debate can avoid a vote in the Steering Council.
-- --Guido van Rossum (python.org/~guido) Pronouns: he/him/his (why is my pronoun here?) _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/PLOQMIQY...
On Fri, Aug 9, 2019 at 11:06 AM Barry Warsaw <barry@python.org> wrote:
Nick and I are now on the same page, so I don’t think we *have* to have a formal SC vote.
OK, I agree. Let's remove TargetScopeError from the PEP and from the implementation. Since that makes three SC members in favor the motion passes. I hope Chris A (the third PEP author) can live with this -- in his last post on the subject that I can find he was still in favor of a subclass of SyntaxError (in any case he's outvoted by the other two PEP authors :-). -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
On Sat, Aug 10, 2019 at 12:56 PM Guido van Rossum <guido@python.org> wrote:
On Fri, Aug 9, 2019 at 11:06 AM Barry Warsaw <barry@python.org> wrote:
Nick and I are now on the same page, so I don’t think we *have* to have a formal SC vote.
OK, I agree. Let's remove TargetScopeError from the PEP and from the implementation. Since that makes three SC members in favor the motion passes. I hope Chris A (the third PEP author) can live with this -- in his last post on the subject that I can find he was still in favor of a subclass of SyntaxError (in any case he's outvoted by the other two PEP authors :-).
I was at the time, but it was only a weak recommendation. And having seen other examples (eg a global statement doubling a function argument) that just use SyntaxError, I'm totally fine with just making it SyntaxError with a useful text message. So go for it! Remove TargetScopeError. (That said, though: it may be helpful to have some metadata attached to the exception, like the name that's being assigned to. Not sure how easy/hard that'll be.) ChrisA
On Fri, Aug 9, 2019 at 8:07 PM Chris Angelico <rosuav@gmail.com> wrote:
On Sat, Aug 10, 2019 at 12:56 PM Guido van Rossum <guido@python.org> wrote:
On Fri, Aug 9, 2019 at 11:06 AM Barry Warsaw <barry@python.org> wrote:
Nick and I are now on the same page, so I don’t think we *have* to have
a formal SC vote.
OK, I agree. Let's remove TargetScopeError from the PEP and from the
implementation. Since that makes three SC members in favor the motion passes. I hope Chris A (the third PEP author) can live with this -- in his last post on the subject that I can find he was still in favor of a subclass of SyntaxError (in any case he's outvoted by the other two PEP authors :-).
I was at the time, but it was only a weak recommendation. And having seen other examples (eg a global statement doubling a function argument) that just use SyntaxError, I'm totally fine with just making it SyntaxError with a useful text message.
So go for it! Remove TargetScopeError.
(That said, though: it may be helpful to have some metadata attached to the exception, like the name that's being assigned to. Not sure how easy/hard that'll be.)
We don't do that for any of the other scope-related SyntaxErrors, so I don't think it's important. (Again, this is not an error people are likely to make unless they are *looking* for edge cases of the walrus operator.) -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Steven D'Aprano wrote:
I find it difficult to imagine a more meaningful distinction than that between syntax and semantics.
That may be so, but when specifying a programming language, there is often some flexibility as to whether language rules are considered part of the syntax or the semantics. An extreme example of this is the formalism used to specify Algol 68, where, believe it or not, things such as the fact that identifiers must be declared in an enclosing scope are expressed in the *grammar*. Strictly speaking, anything that makes a particular sequence of symbols not be a valid program, that could in principle be determined by static analysis, can be considered a syntactic issue. So classifying a TargetScopeError as a kind of SyntaxError isn't necessarily wrong. There's actually a precedent for this in Python already:
def f(): ... nonlocal x ... x = 5 ... File "<stdin>", line 2 SyntaxError: no binding for nonlocal 'x' found
We seem to be happy to use a plain SyntaxError for that, not even bothering with a subclass. So I'm inclined to agree that TargetScopeError is not necessary. -- Greg
On 08/08/2019 22:58:15, Steven D'Aprano wrote:
On Thu, Aug 08, 2019 at 10:00:01AM -0700, Barry Warsaw wrote:
"The two invalid cases listed above raise TargetScopeError, a new subclass of SyntaxError (with the same signature).”
The PEP doesn’t really go into the rationale for why a new exception is being defined, and in the issue I’ve argued that we should just raise SyntaxError in those cases. To me, “TargetScopeError” is pretty obscure and doesn’t give users an obvious clue as to what’s going wrong, without searching the interwebs. It's not a syntax error. There's nothing wrong with the syntax per-say: we still have ``target := expression``. There's a problem with the *semantics* not the syntax.
The name is perfectly self-descriptive: TargetScopeError means that there's an error with the scope of the target. What else could it mean? That's easy for an experienced programmer to say. IMHO it's about as helpful to a newbie as saying GrobKunkError means that there's an error with the kunk of the grob.
I think AmbiguousScopeError is somewhat better than TargetScopeError, but perhaps someone will think of something even better. (ScopeConflictError? InvalidVariableReuse? I dunno.)
What's wrong with having to look up an unfamiliar exception by searching the interwebs? The first few times I hit KeyError, I had no idea what a "key" was (I was a beginner) and if I had internet access, I would have looked it up on the web. I didn't, so I looked it up in the book I was reading.
The first times I hit UnboundLocalError, I did have internet access, so I googled it. Once I understood that it meant that the local I was trying to use was unbound, and that "unbound" mean "undefined", all was clear.
(Well, not all, I still had to work out why it was undefined. But at least the exception name was more clear.) Sure, people should be encouraged to look things up on the web (if they haven't already acquired the habit). But that doesn't mean we shouldn't make things as clear as reasonably possible in the first place.
One of the frustrations I have is that it's near to impossible to programmatically distinguish wrong number of arguments from bad keyword arguments from providing the wrong type of argument without relying on the error message. (And yes, I have needed to do this.) All of these raise the same TypeError, even though only one of them is an actual error with the type:
len(1) # An actual TypeError
len([], None) # The type of the argument is fine.
len(spam=[]) # The type of the argument is fine.
Please let's not use SyntaxError for something that's not an error with the syntax. (For reference the error messages are, depending a bit on the Python version, respectively object of type 'int' has no len() len() takes exactly one argument (2 given) len() takes no keyword arguments . .) I'm mildly curious as to why you couldn't rely on the error message, but I'm sure you had a good reason. FWIW IMHO the last two ought to produce an exception called ArgumentError or ParameterError or some such or even more specific names such as TooManyArguments and KeywordArgumentsDisallowed. I guess I'm agreeing with you to the extent that I'm proposing more (specific) exceptions. Rob Cliffe
On Fri, Aug 09, 2019 at 01:16:16AM +0100, Rob Cliffe via Python-Dev wrote:
The name is perfectly self-descriptive: TargetScopeError means that there's an error with the scope of the target. What else could it mean?
That's easy for an experienced programmer to say.
Correct. Why should we be embarrassed to be experienced programmers? For the record, I'm not a professional programmer, so my experience is probably a thousandth or less of that of some of the people here.
IMHO it's about as helpful to a newbie as saying GrobKunkError means that there's an error with the kunk of the grob.
To a programmer who is not a native English speaker, "ValueError" and "SyntaxError" makes as much sense as PHP's PAAMAYIM NEKUDOTAYIM operator makes to non-Hebrew speakers. If they can cope with learning what "Value" means, I'm sure we English-speakers can learn what "Target" and "Scope" mean. Developers are newbies for a tiny fraction of their programming life. Why should we ban technical terms because somebody in the first month of their programming life doesn't know the terms? They're going to learn them, and pretty quickly, as soon as they start talking to more experienced programmers, or reading answers on Stackoverflow, etc. "Scope" and "target" are standard terms of art, like class, function, variable, etc. Saying that we shouldn't use them makes as little sense as saying that chefs shouldn't use the terms "sauté", "braise" or "blanche" because newbie cooks don't know what they are. Of course they don't. Not knowing the things they need to know is the very definition of a newbie. Here are some exceptions which "make as much sense to a newbie as..." - BrokenPipeError (is my plumbing leaking? what do pipes have to do with programming?) - ChildProcessError (Child? Process?) - FutureWarning (something to do with Marty McFly or the Terminator?) - the confusingly named UnicodeDecodeError and UnicodeEncodeError which differ by two letters but mean completely different things, the complete opposite of each other. to mention only a few.
I think AmbiguousScopeError is somewhat better than TargetScopeError,
I would be fine with AmbiguousScopeError too, except for the unfortunately double s. But now we're bike-shedding. Either name is much more informative than "syntax error". [...]
One of the frustrations I have is that it's near to impossible to programmatically distinguish wrong number of arguments from bad keyword arguments from providing the wrong type of argument without relying on the error message. [...]
I'm mildly curious as to why you couldn't rely on the error message, but I'm sure you had a good reason.
Error messages are not part of the API and could change at any time, including in bug fix releases. Over the last few years, we've made a lot of progress in making error messages more informative: python2.4 -c "len(None)" TypeError: len() of unsized object python2.7 -c "len(None)" TypeError: object of type 'NoneType' has no len() and they could easily continue to change in the future: python4000 -c "len(None)" TypeError: 'None' has no length -- Steven
08.08.19 20:00, Barry Warsaw пише:
Rather than just a vote, if you have a rationale for one over the other, I’d love to hear it. Feel free to weigh in here or on the issue.
I do not have arguments for SyntaxError but the rationale for TargetScopeError does not look strong to me. IndentationError and TabError are special enough. Don't count me as advocating for TargetScopeError.
Short version of my more detailed answer below: While my rationale is different from Barry's, I've convinced myself that the right thing to do for Python 3.8 is to remove the new TargetScopeError and have these cases all just raise SyntaxError. I do still see potential value in a new "AssignmentScopeError" subclass, but it would apply to more than just these new exceptions, and can be considered on a more leisurely basis for Python 3.9. On Fri, 9 Aug 2019 at 03:07, Barry Warsaw <barry@python.org> wrote:
bpo-37757: https://bugs.python.org/issue37757
This issue describes some corner cases in PEP 572 (assignment expressions) syntax that haven’t been implemented yet. The PEP currently says:
"The two invalid cases listed above raise TargetScopeError, a new subclass of SyntaxError (with the same signature).”
The PEP doesn’t really go into the rationale for why a new exception is being defined, and in the issue I’ve argued that we should just raise SyntaxError in those cases. To me, “TargetScopeError” is pretty obscure and doesn’t give users an obvious clue as to what’s going wrong, without searching the interwebs.
Nick argues (apologies if I’m misrepresenting you!):
"I believe our main motivation for separating it out was the fact that even though TargetScopeError is a compile-time error, the affected code is syntactically fine - there are just issues with unambiguously inferring the intended read/write location for the affected target names. (Subclassing SyntaxError is then a pragmatic concession to the fact that "SyntaxError" also de facto means "CompilationError”)”
This accurately conveys what I wrote on the PR and issue, but what I wrote there didn't capture the full background for when TargetScopeError gets raised. The main motivating case that led to the new exception being defined is the one that was already implemented as part of the initial PR adding assignment expressions: the fact we can't readily make PEP 572's parent local scoping for comprehensions work when that parent scope is a class scope. Hence, the TargetScopeError raised in this case: >>> class C: ... [x := 10 for i in range(5)] ... File "<stdin>", line 2 TargetScopeError: named expression within a comprehension cannot be used in a class body Syntactically, the individual pieces of this code are perfectly fine - the problem is that the calculated target for "x" would be in the class body, and there isn't currently a way for the compiler to make that name accessible both in the class scope and in the comprehension body. (We're only able to make zero-arg super work because we don't need to make `__class__` accessible while the class is executing). The new PR then adds the additional checks to disallow the cases where we don't want to enshrine "What CPython's current implementation handles this code" as "The way this code must behave in all Python implementations": >>> [i := 10 for i in range(5)] File "<stdin>", line 1 TargetScopeError: named expression cannot rebind comprehension iteration variable >>> [True for i in range(5) if (j := True) for j in range(5)] File "<stdin>", line 1 TargetScopeError: comprehension inner loop cannot rebind named expression target >>> [True for i in (iterable := range(5))] File "<stdin>", line 1 TargetScopeError: named expression cannot be used in comprehension iterable expression I agree that it's a problem that "Assignment" doesn't appear anywhere in the exception name - if we're going to have a specific name for this, then something like "AssignmentScopeError" would be better. The main counterargument to this approach would be that other similar scoping issues currently just raise SyntaxError: >>> def f(x): global x ... File "<stdin>", line 1 SyntaxError: name 'x' is parameter and global >>> def f(x): nonlocal x ... File "<stdin>", line 1 SyntaxError: name 'x' is parameter and nonlocal >>> def f(): global x; nonlocal x ... File "<stdin>", line 1 SyntaxError: name 'x' is nonlocal and global >>> def f(): nonlocal x ... File "<stdin>", line 1 SyntaxError: no binding for nonlocal 'x' found (Those also highlight that I should tweak the new name specific binding conflict errors to mention the variable name) With a revised exception name though, I think even those existing errors would be improved by switching them over to the subclass: >>> def f(x): global x ... File "<stdin>", line 1 AssignmentScopeError: name 'x' is parameter and global >>> def f(x): nonlocal x ... File "<stdin>", line 1 AssignmentScopeError: name 'x' is parameter and nonlocal >>> def f(): global x; nonlocal x ... File "<stdin>", line 1 AssignmentScopeError: name 'x' is nonlocal and global >>> def f(): nonlocal x ... File "<stdin>", line 1 AssignmentScopeError: no binding for nonlocal 'x' found However, a change like that would make the most sense when considered independently of the specific case of assignment expressions - instead, we would want to ask "What kinds of exceptions does the symbol table analysis pass raise?", and then consider whether it might make sense to define subclasses of syntax error for them. Given the naming issue, and the fact that a potential new SyntaxError subclass would be relevant for more than just the new PEP 572 exceptions, I think the right near term approach is to go with the generic SyntaxError as Barry suggests. I'll update my PRs accordingly. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
On 09.08.19 15:44, Nick Coghlan wrote: ...
However, a change like that would make the most sense when considered independently of the specific case of assignment expressions - instead, we would want to ask "What kinds of exceptions does the symbol table analysis pass raise?", and then consider whether it might make sense to define subclasses of syntax error for them.
Given the naming issue, and the fact that a potential new SyntaxError subclass would be relevant for more than just the new PEP 572 exceptions, I think the right near term approach is to go with the generic SyntaxError as Barry suggests. I'll update my PRs accordingly.
Totally agree. It is fine to have SyntaxError now and go for one or more new subclasses for a whole bunch of errors at a later time, fixing more things in a more consistent way. -- Christian Tismer :^) tismer@stackless.com Software Consulting : http://www.stackless.com/ Karl-Liebknecht-Str. 121 : https://github.com/PySide 14482 Potsdam : GPG key -> 0xFB7BEE0E phone +49 173 24 18 776 fax +49 (30) 700143-0023
Thanks Nick. I find yours (and Eric’s) argument compelling. I’m totally aligned with using SyntaxError in 3.8 and thinking through the more general problem for 3.9. Cheers, -Barry
On Aug 9, 2019, at 06:44, Nick Coghlan <ncoghlan@gmail.com> wrote:
Short version of my more detailed answer below:
While my rationale is different from Barry's, I've convinced myself that the right thing to do for Python 3.8 is to remove the new TargetScopeError and have these cases all just raise SyntaxError.
I do still see potential value in a new "AssignmentScopeError" subclass, but it would apply to more than just these new exceptions, and can be considered on a more leisurely basis for Python 3.9.
I just read your e-mail (before reading any follow up here), fired up Python 3.8 and typed in what I thought would be an ambiguous or confuse case, withut checking the PEP. the result: ``` Python 3.8.0b3+ (heads/3.8:ef0b81927a, Aug 6 2019, 20:30:57) Type 'copyright', 'credits' or 'license' for more information IPython 7.7.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: class A: ...: b = 0 ...: any((b:= i, 0)[1] for i in range(10)) File "<ipython-input-1-22c303b71775>", line 3 any((b:= i, 0)[1] for i in range(10)) ^ TargetScopeError: named expression within a comprehension cannot be used in a class body ``` So, while the name "TargetScopeError" can sound confusing, I think the extended error message could not be more clear and unambiguous. It seems just fine as it is. On Thu, 8 Aug 2019 at 14:02, Barry Warsaw <barry@python.org> wrote:
bpo-37757: https://bugs.python.org/issue37757
This issue describes some corner cases in PEP 572 (assignment expressions) syntax that haven’t been implemented yet. The PEP currently says:
"The two invalid cases listed above raise TargetScopeError, a new subclass of SyntaxError (with the same signature).”
The PEP doesn’t really go into the rationale for why a new exception is being defined, and in the issue I’ve argued that we should just raise SyntaxError in those cases. To me, “TargetScopeError” is pretty obscure and doesn’t give users an obvious clue as to what’s going wrong, without searching the interwebs.
Nick argues (apologies if I’m misrepresenting you!):
"I believe our main motivation for separating it out was the fact that even though TargetScopeError is a compile-time error, the affected code is syntactically fine - there are just issues with unambiguously inferring the intended read/write location for the affected target names. (Subclassing SyntaxError is then a pragmatic concession to the fact that "SyntaxError" also de facto means "CompilationError”)”
Serhiy points out that we have IndentationError and TabError subclasses of SyntaxError, but those feel different to me because the exception names themselves are clear and descriptive, and lead to obvious actionable remedies.
Guido then suggests we take the discussion here, thus this email.
It would be a very minor update to the PEP, but I think it’s useful to resolve before the last push for PEP 572 implementation gets completed.
Rather than just a vote, if you have a rationale for one over the other, I’d love to hear it. Feel free to weigh in here or on the issue.
Cheers, -Barry
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/FXVSYCTQ...
participants (15)
-
Barry Warsaw
-
Brett Cannon
-
Chris Angelico
-
Christian Tismer
-
Eric V. Smith
-
Greg Ewing
-
Guido van Rossum
-
Ivan Pozdeev
-
Joao S. O. Bueno
-
Kyle Stanley
-
Nick Coghlan
-
Rob Cliffe
-
Serhiy Storchaka
-
Steven D'Aprano
-
Tim Peters