Skip to content
This repository was archived by the owner on Apr 10, 2022. It is now read-only.

use real code to generate output for the examples. A few other edits #16

Merged
merged 3 commits into from
Feb 7, 2021

Conversation

iritkatriel
Copy link
Member

No description provided.

@iritkatriel
Copy link
Member Author

The POC is not very stable, I'm debugging some crashes. But it's good enough to run small examples like the ones we have in the PEP.

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point I recommend that you go over the text looking for all occurrences of "would" (and perhaps some similar verbs) and remove them. The specification should be written in a more direct tense (I have no idea what all these tenses are called :-) -- which in some parts you are using (e.g. "The interpreter creates ...").

other size:

```python
>>> other_errors.split(lambda e: isinstance(e, SyntaxError))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forget where we landed on copying or preserving the original if possible in this case. I think we ended up always copying? Might be worth pointing out that other_errors.split(SyntaxError) is not other_errors (even though they have the same repr()).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the POC at the moment we don't copy an EG if we don't need to, and we never copy a simple (leaf) exception. Should we change that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I forgot. This is fine but should be called out in the PEP -- because it means that people should be wary of mutating the list of exceptions (you already say that the naked exceptions themselves are shared).

except_star.md Outdated
Comment on lines 253 to 254
### Overview

Copy link
Member

@gvanrossum gvanrossum Feb 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just read the text below carefully. Maybe you should call out that one big difference with classic try/except is that if there are multiple except * blocks, several of them may be executed? That's clear from the description, but I would still call it out as a key difference.

except_star.md Outdated
Comment on lines 380 to 381
executed). These exceptions are removed from the "incoming" group so
that they will be excluded from matching additional clauses.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is removing some exceptions from the incoming group an efficient operation? It looks like this is best done using .split() or .subgroup(); is that how you do it? If there are N except * clauses that match, is this process O(N), better or worse?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done with a split. Each except* is one split operation (so N*size_of_EG in total).

At the end there is another step where we construct the EG to propagate on. I did it like this:
We have the original EG that was raised, the remaining part of it that was never matched, and a list of all the exceptions that were raised or reraised from except* blocks.

  1. Iterate over the list, and use the metadata to determine whether these are reraises (same metadata) or raises of new exceptions. O(N)
  2. Start with original EG and split off all the reraised exceptions and then also the unhandled exception. What's left is the part of the original EG that was swallowed by the excepts. O(Nsize_of_EG)
  3. Split the swallowed part off the original EG, now we have all the reraised exceptins in the right structure. O(size_of_EG)
  4. Merge that with the rasied exceptions into a new EG and raise that. O(1)

(and handle special cases where some of these steps are empty/trivial/skipped).

However - I don't know how much of the implementation details of the POC should go into the PEP. There may be other possible implementations.

Copy link
Member Author

@iritkatriel iritkatriel Feb 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example - ~I didn't use two lists or raised/reraised exceptions as it says above, because I wrapped the body of each except* with another try-except which catches the exception and stashes it in the one list. (At the point where it is caught I don't know whether it was a raise or a reraise - I figure out later by comparing the metadata).

There could perhaps be a different implementation where the raise is intercepted as it happens and then you do know which one it is. The semantics are the same.

Do we propose an implementation in the PEP, or leave it open and just stick to semantics?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am mostly concerned about the semantics. The user code cannot tell whether you use a list or not. I am also not really concerned about perf (nobody has 100 except clauses). But sometimes the semantics are clearer if you describe them in terms other operations that you have already described. And sometimes pseudo-code is more readable than English text. So if the steps 1-4 above could be expressed simply in pseudo-Python that might be helpful (even if you keep the English text as well).

In any case I'm a little unclear about what you call "the metadata". Is that user-visible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

metadata is (context, cause, traceback). If an exception came from raise e inside an except* clause it has different metadata than the original EG, but if it came from a naked raise then it is the same.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. If you use this term in the document I would explain it first (I don't think it's standard).

except_star.md Outdated
* After there are no more `except*` clauses to evaluate, there are the
following possibilities:
* After all `except*` clause were evaluated, there are the following
possibilities:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading the numbered items carefully, they seem not exclusive -- it's more like there are three steps that are carried out in order? (To me, "possibilities" makes me anticipate three exclusive situations.)

Co-authored-by: Guido van Rossum <guido@python.org>
@iritkatriel
Copy link
Member Author

The POC is not very stable, I'm debugging some crashes. But it's good enough to run small examples like the ones we have in the PEP.

I've fixed a few bugs and added more tests so it's better now.
iritkatriel/cpython#8

Still need to fix the "except*:" (no type) case.

@Zac-HD
Copy link

Zac-HD commented Feb 4, 2021

Still need to fix the except*: (no type) case.

I wouldn't mind if this was unsupported, i.e. you have to write except *BaseException: if that's what you mean (or except *Exception:, in the common case). Bare except: is a convenient but dangerous trap for naive - most! - users.

@gvanrossum
Copy link
Member

Still need to fix the except*: (no type) case.

I wouldn't mind if this was unsupported, i.e. you have to write except *BaseException: if that's what you mean (or except *Exception:, in the common case). Bare except: is a convenient but dangerous trap for naive - most! - users.

+1

@iritkatriel
Copy link
Member Author

Still need to fix the except*: (no type) case.

I wouldn't mind if this was unsupported, i.e. you have to write except *BaseException: if that's what you mean (or except *Exception:, in the common case). Bare except: is a convenient but dangerous trap for naive - most! - users.

+1

Oh, in that case I think the POC is feature-complete. Yay.

@iritkatriel
Copy link
Member Author

I redid the semantics section to make it a gradual exposition of the features rather than dumping the whole complex algorithm on the reader in the first 3 paragraphs. I think it's easier to follow this way.

I'm not sure we need pseudo code, but if we do then perhaps that can go in the "reference implementation" section.

@iritkatriel
Copy link
Member Author

I think that
(1) the "Design Considerations" section should be rolled into "Rejected Ideas", and it is at the moment too focused on the asyncio use case.

(2) the "Adoption of try..except* syntax" section belongs in a future PEP about changing asyncio to use except* and ExceptionGroups, so should be removed from here.

Would you agree?

@gvanrossum
Copy link
Member

I think that
(1) the "Design Considerations" section should be rolled into "Rejected Ideas", and it is at the moment too focused on the asyncio use case.

Hm, that seems odd, since nothing in there is rejected. Maybe it's just redundant? It would seem to belong in Motivation. I don't mind that it's focused on asyncio, that's still an important case (also historically).

(2) the "Adoption of try..except* syntax" section belongs in a future PEP about changing asyncio to use except* and ExceptionGroups, so should be removed from here.

Yeah, that section looks a bit disconnected from the rest of the PEP; on the other hand it could also make sense to propose this change at the same time, and then it should be fleshed out and go into Specification.

@iritkatriel
Copy link
Member Author

iritkatriel commented Feb 6, 2021

I think that
(1) the "Design Considerations" section should be rolled into "Rejected Ideas", and it is at the moment too focused on the asyncio use case.

Hm, that seems odd, since nothing in there is rejected. Maybe it's just redundant? It would seem to belong in Motivation. I don't mind that it's focused on asyncio, that's still an important case (also historically).

I’ll create a separate PR to work on that section.

(2) the "Adoption of try..except* syntax" section belongs in a future PEP about changing asyncio to use except* and ExceptionGroups, so should be removed from here.

Yeah, that section looks a bit disconnected from the rest of the PEP; on the other hand it could also make sense to propose this change at the same time, and then it should be fleshed out and go into Specification.

I don’t know enough about asyncio to implement and spec this, so it would be up to @1st1 , @aeros, @njsmith, @ambv to say whether they want to add it to this PEP.

My feeling is that, unless this is relatively straightforward and can fit in a couple of paragraphs, it might be too big a scope for one PEP.

@gvanrossum
Copy link
Member

Makes sense on both points.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants