This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author iritkatriel
Recipients alonho, benjamin.peterson, chris.jerdonek, hniksic, iritkatriel, martin.panter, ncoghlan, nikratio, njs
Date 2021-04-07.17:50:29
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1617817829.65.0.914471407227.issue18861@roundup.psfhosted.org>
In-reply-to
Content
For the issue of which contexts need to be suppressed when __suppress_context__ is true, I think we don't need to keep the whole tree of exceptions. It might be enough to save the dynamic "nesting depth of the try-excepts".  Here is a solution with two integers per exception, plus one on the thread state. Would it work?


We add an int field called except_depth to the thread state (incremented in ceval just before the try of a try-except and decremented after the last except: block).

Whenever an exception is caught, this value is copied to it (to a new int we put on BaseException, call it depth).

The __suppress_context__ field we change from bool to int (alternatively: add a new field and leave this one alone). Instead of setting it to True when there is __cause__, we set it to the except-depth of the raise...from that raised it.

Then the code displaying the traceback can use the depths information to determine which contexts to suppress (the ones up to and not including the first one with depth < the suppress_context value).

Returning to Nick's examples from 2013-11-08 14:34:

  # No context on Exception3 is exactly what we want
  try:
      try:
          raise Exception1
      except Exception1:
          raise Exception2
  except Exception2 as exc
      raise Exception3 from Exception2

Exception1 - depth = 2
Exception2 - depth = 1
Exception3 - depth = ?  suppress_context = 1
(suppress both Exception1 and Exception2, they have depths >= 1)


  # Not seeing Exception1 as the context for Exception3 is surprising!
  try:
      raise Exception1
  except Exception1:
      try:
          raise Exception2
      except Exception2 as exc
          raise Exception3 from Exception2
		  		  
Exception1 - depth = 1
Exception2 - depth = 2
Exception3 - depth = ?  suppress_context = 2
(suppress only Exception2, Exception1 is too shallow)
		  

To consider more elaborate nesting:

  try:
      try:
          raise Exception0
      except T: # Does not catch Exception0
          pass
  except Exception1:
      try:
          raise Exception2
      except Exception2 as exc
          raise Exception3 from Exception2

Whatever happens in the topmost try-block, if Exception0 is the context of anything raised inside the "except Exception1" block, then its depth is 1 because it was caught by this except. So it won't be suppressed by anything raised at a deeper level.
History
Date User Action Args
2021-04-07 17:50:29iritkatrielsetrecipients: + iritkatriel, ncoghlan, hniksic, benjamin.peterson, njs, nikratio, chris.jerdonek, alonho, martin.panter
2021-04-07 17:50:29iritkatrielsetmessageid: <1617817829.65.0.914471407227.issue18861@roundup.psfhosted.org>
2021-04-07 17:50:29iritkatriellinkissue18861 messages
2021-04-07 17:50:29iritkatrielcreate