Skip to content

Draft Processor Exception Handling - #173

Open
ianjosephwilson wants to merge 4 commits into
t-strings:mainfrom
ianjosephwilson:ian/prep_for_custom_errors_part7
Open

ianjosephwilson wants to merge 4 commits into
t-strings:mainfrom
ianjosephwilson:ian/prep_for_custom_errors_part7

Conversation

@ianjosephwilson

Copy link
Copy Markdown
Collaborator
  • Added ProcessingError(s)
    • Recursive: Can occur in a template that was included in another template which was included in another template ... etc.
    • Once an exception occurs try to pack up a state that parallels each template in the recursive stack
      • Try to connect each "leaf" entrypoint with the nearest TNode
      • Try to connect the template and TTree (contains the template TNode root) to the exception
      • Try to catch regular exception in places where they might occur, ie. we try to call a user function, and then chain them with raise ProcessingError() from e
      • We also catch and chain a ParsingError to a ProcessingError
    • When we get back to TemplateProcessor.process() we should have a single ProcessingError that has a stack of error states that go down until we reach the lowest level Template where an error first occurred so we could print something LIKE this (TBD):
div > ... {nested_t}
    div > ... {slider_t}
        span > AttributeProcessingError: aria attribute must be dictionary
Error occurred in <span aria={('role','slider')}></span> at line 1 offset 15 in 

@ianjosephwilson

Copy link
Copy Markdown
Collaborator Author

@davepeck Excluding what was removed I think this is the last (!) part of #145. After this .. world wide fame and acclaim. You might have to run it to see the notes/chained exceptions to get a feel for it. There are a lot of small decisions we might still need to make. Maybe I can try to comment on the PR and point those out.

@davepeck

Copy link
Copy Markdown
Contributor

world wide fame and acclaim

richly deserved

Comment thread tdom/processor.py
iter_index=iter_index,
values_index=values_index,
)
for iter_index, v in enumerate(value)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

A lot of the exception handling only affects what happens after an exception has occurred but to track which value in a sequence actually failed here we need to know the index so we wrap it in enumerate. Depending on how we handle error reporting this could help us better track down the exact location of the error and fits in with the other tracking concepts but does add overhead (minimal though?).

Comment thread tdom/processor.py
tattrs = _resolve_t_attrs(attrs, template.interpolations)
except ProcessingError: # @TODO: Is there a native way to guard this?
raise
except Exception as e:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

When an exception "breaks through" in the processor the traceback is almost gibberish. So we just catch everything here and then chain it with from e. The chaining prevents us from masking/shadowing the original exception but still allows us to add more contextual info for error messages.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We try to keep the wrapping as close to the user code as possible so 1. we don't also chain our own bugs as if they were user bugs and 2. we can provide better contextual information about where the exception took place (ie. instead of in the Processor at line XYZ it is in attributes of component {LoginForm} in the template at line 3 offset 15 or whatever).

Comment thread tdom/processor.py
e.last_tnode = None
e.values_index = None
e.iter_index = None
raise

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Once we have wrapped an exception or started an exception we try to keep the SAME exception so we don't lose the traceback. This means we use it as a scratchpad to push/pop info as we go in and out of templates reversing our descent back up to the original html() call. We keep that info in a list. This has a few weird quirks but seems to work, like keeping the innermost tnode where the exception occurred.

Comment thread tdom/processor.py
except ProcessingError as e:
if e.last_tnode is None:
e.last_tnode = tnode
raise

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is subtle but we check if we set a tnode or not so that we only set this tnode one time getting the "innermost tnode". If we just set it everytime we'd overwrite that tnode as we ascending into each parent. We also don't want to pass the tnode down into every single leaf method, so we don't have the innermost tnode at the first raise, so we have to catch the exception on the way back up and tag the tnode on it so we can pull it off again once we are at the root of the template.

Comment thread tdom/processor.py
else:
starttag_pos_msg = "unknown location" # source_pos is optional right now

e.add_note(f"Error occurred at {starttag_repr} at {starttag_pos_msg}.")

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

One sort of confusing issue is how/if at all do we identify a template to the user of tdom? Templates can be "anonymous", ie. Template(""), which is useless for tracking but is there a way to get "identity" information from a static t-string? Sort of like using inspect(python_func) to find the code and the file name, etc.? I think I've asked this before but I don't remember what the answer was. We'd like to say "Error occurred at ... at ... in Template {TEMPLATE IDENTITY}".

@ianjosephwilson

Copy link
Copy Markdown
Collaborator Author

@davepeck I added some notes. Let me know what you think whenever you get a chance.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants