diff options
author | Jason Madden <jamadden@gmail.com> | 2017-09-11 10:15:13 -0500 |
---|---|---|
committer | Jason Madden <jamadden@gmail.com> | 2017-09-11 10:20:36 -0500 |
commit | 408c2912c4bce039944f62760ab6bba9e091e871 (patch) | |
tree | 6bf3fdb808000ee38bdc1597de28677edfcfc098 | |
parent | d97f1b37d541554ad85e15dd824a84d3e3883f4c (diff) | |
download | zope-exceptions-408c2912c4bce039944f62760ab6bba9e091e871.tar.gz |
Update narrative docs; be sure rendering works as expected via testsissue8
Also provide more motivation and differentiation between the various
forms of annotating.
Fixes #8.
-rw-r--r-- | .travis.yml | 2 | ||||
-rw-r--r-- | docs/narr.rst | 132 |
2 files changed, 95 insertions, 39 deletions
diff --git a/.travis.yml b/.travis.yml index 19a4c83..61d4409 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ python: - 3.4 - 3.5 - 3.6 - - pypy-5.4.1 + - pypy install: - pip install -U pip setuptools - pip install -U coverage coveralls diff --git a/docs/narr.rst b/docs/narr.rst index 6c79cd3..a61ec72 100644 --- a/docs/narr.rst +++ b/docs/narr.rst @@ -1,22 +1,66 @@ -Using :mod:`zope.exceptions` -============================ +============================== + Using :mod:`zope.exceptions` +============================== This module extends the standard library's :mod:`traceback` module, allowing application code to add additional information to the formatted tracebacks using specially-named variables in the scope of a given frame. +We will use examples of a rendering function that's meant to produce +some output given a template and a set of options. But this rendering +function is quite broken and produces a useless exception, so when we +call it we'd like to be able to provide some more contextual information. + +.. doctest:: + + >>> import sys + >>> def render(source, options): + ... raise Exception("Failed to render") Annotating Application Code ---------------------------- +=========================== -:py:data:`__traceback_supplement__` -+++++++++++++++++++++++++++++++++++ +:py:data:`__traceback_info__` +----------------------------- + +This variable can only be defined at local scope. It will be converted to a +string when added to the formatted traceback. + +.. doctest:: + + >>> def render_w_info(template_file, options): + ... with open(template_file) as f: + ... source = f.read() + ... __traceback_info__ = '%s\n\n%s' % (template_file, source) + ... render(source, options) + + +This is convenient for quickly adding context information in an +unstructured way, especially if you already have a string, or an +object with a custom ``__str__`` or ``__repr__`` that provides the +information you need (tuples of multiple such items also work well). +However, if you need to format a string to produce readable +information, as in the example above, this may have an undesirable +runtime cost because it is calculated even when no traceback is +formatted. For such cases, ``__traceback_supplement__`` may be helpful. -This variable can be defined either at either local or global scope. -The formatting functions treat objects with this name as though they support -the :py:class:`~zope.exceptions.interfaces.ITracebackSupplement` interface. -The various attributes (all optional) of that interface will be used to -add structured information to the formatted traceback. +:py:data:`__traceback_supplement__` +----------------------------------- + +This variable can be defined either at either local or global (module) +scope. Unlike ``__traceback__info__`` this is structured data. It must +consist of a sequence containing a function and the arguments to pass +to that function. At runtime, only if a traceback needs to be +formatted will the function be called, with the arguments, to produce +a *supplement object*. Because the construction of the object is +delayed until needed, this can be a less expensive way to produce +lots of useful information with minimal runtime overhead. + +The formatting functions treat the resulting supplement object as if +it supports the +:py:class:`~zope.exceptions.interfaces.ITracebackSupplement` +interface. The various attributes (all optional) of that interface +will be used to add structured information to the formatted traceback. For example, assuming your code renders a template: @@ -24,58 +68,61 @@ For example, assuming your code renders a template: >>> import os >>> class Supplement(object): - ... def __init__(self, template_file, source): + ... def __init__(self, template_file, options): ... self.source_url = 'file://%s' % os.path.abspath(template_file) - ... self.source = source + ... self.options = options + ... self.expression = 'an expression' ... def getInfo(self): - ... return self.source + ... return "Options: " + str(self.options) >>> def render_w_supplement(template_file, options): - ... source = open(template_file).read() - ... __traceback_supplement__ = Supplement(template_file, source) + ... with open(template_file) as f: + ... source = f.read() + ... __traceback_supplement__ = Supplement, template_file, options + ... render(source, options) -Here, the filename and source of the template will be rendered as part of +Here, the filename and options of the template will be rendered as part of the traceback. - -:py:data:`__traceback_info__` -+++++++++++++++++++++++++++++ - -This variable can only be defined at local scope. It will be converted to a -string when added to the formatted traceback. - -.. doctest:: - - >>> def render_w_info(template_file, options): - ... source = open(template_file).read() - ... __traceback_info__ = '%s\n\n%s' % (template_file, source) +.. note:: If there is an exception calling the constructor function, + no supplement will be formatted, and (by default) the + exception will be printed on ``sys.stderr``. API Functions -------------- +============= Three API functions support these features when formatting Python exceptions and their associated tracebacks: :py:func:`~zope.exceptions.exceptionformatter.format_exception` -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +--------------------------------------------------------------- -Use this API to format an exception and traceback as a string, using +Use this API to format an exception and traceback as a list of strings, using the special annotations. E.g.: .. doctest:: - >>> import sys + >>> from zope.exceptions import format_exception >>> try: - ... raise ValueError('demo') + ... render_w_info('docs/narr.rst', {}) ... except: ... t, v, tb = sys.exc_info() ... report = format_exception(t, v, tb) ... del tb # avoid a leak ... # Now do something with report, e.g., send e-mail. + >>> print('\n'.join(report)) + Traceback (most recent call last): + <BLANKLINE> + Module <doctest default[1]>, line 2, in <module> + render_w_info('docs/narr.rst', {}) + <BLANKLINE> + Module <doctest default[0]>, line 5, in render_w_info + - __traceback_info__: docs/narr.rst + ... :py:func:`~zope.exceptions.exceptionformatter.print_exception` -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +-------------------------------------------------------------- Use this API to write the formated exception and traceback to a file-like object, using the special annotations. E.g.: @@ -84,15 +131,24 @@ object, using the special annotations. E.g.: >>> from zope.exceptions import print_exception >>> try: - ... raise ValueError('demo') + ... render_w_supplement('docs/narr.rst', {}) ... except: ... t, v, tb = sys.exc_info() - ... print_exception(t, v, tb, file=sys.stderr) + ... print_exception(t, v, tb, file=sys.stdout) ... del tb # avoid a leak - + Traceback (most recent call last): + File "<doctest default[1]>", line 2, in <module> + render_w_supplement('docs/narr.rst', {}) + File "<doctest default[2]>", line 5, in render_w_supplement + - file:///... + - Expression: an expression + Options: {} + File "<doctest default[1]>", line 2, in render + render_w_supplement('docs/narr.rst', {}) + Exception: Failed to render :py:func:`~zope.exceptions.exceptionformatter.extract_stack` -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +------------------------------------------------------------ Use this API to format just the traceback as a list of string,s using the special annotations. E.g.: |