mailRe: r2540 - in /branches/warning: errors.py generic_fns/pdb.py relax


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by Chris MacRaild on August 30, 2006 - 12:59:
On Wed, 2006-08-30 at 20:07 +1000, Edward d'Auvergne wrote:
+        # Format warning messages.
+        def format(message, category, filename, lineno):

Should this function be indented so that it is located within
self.__init__() or should it be referred to as self.function()?  I'd
prefer to stay away from functions nested within other functions.
This nesting is very rare in relax and I'm slowly trying to eliminate
all instances of it.


Fine.

I was just unsure as to what calls this function and whether it was
supposed to be nested.

I wrote it that way only because there is no need for it to be a class
method. But I do see that nested functions can quickly lead to confusing
code, so I'm happy to avoid them. The function is not explicitly called
by relax, but rather is used to rebind warnings.formatwarning in order
to customise the format of the relax warnings (ie. it is called by the
python warnings system whenever a warning is thrown within relax). I'll
bump it out of __init__ and into the class body.



+            if issubclass(category, self.BaseWarning):
+                message = "RelaxWarning: %s\n\n" % message
+
+            if Debug:
+                tb = ""
+                for frame in inspect.stack()[4:]:

It's probably worth trimming the other side of the stack as well, see 
below.

+                    file = frame[1]
+                    lineNo = frame[2]
+                    func = frame[3]
+                    tb_frame = '  File "%s", line %i, in %s\n' % 
(file, lineNo, func)
+                    try:
+                        context = frame[4][frame[5]]
+                    except TypeError:
+                        pass
+                    else:
+                        tb_frame = '%s    %s\n' % (tb_frame, 
context.strip())
+                    tb = tb_frame + tb
+                tb = "Traceback (most recent call last):\n%s" % tb
+                message = tb + message
+
+            return message
+
+        warnings.formatwarning = format

I had a very similar logic in the code which was rolled back at
https://mail.gna.org/public/relax-commits/2006-08/msg00010.html
(Message-id: <E1GDk40-0003vf-Do@xxxxxxxxxxxxxxxxxx>) and discussed at
the thread starting at
https://mail.gna.org/public/relax-devel/2006-08/msg00052.html
(Message-id: 
<7f080ed10608100336r3dc92d80h1ce3251e55b49347@xxxxxxxxxxxxxx>).
 However I used the 'extract_stack' function to get the stack instead
and then used the 'format_list' function to do the formatting similar
to that which you have coded.  The relevant code was in the traceback
function which I've reproduced below.  Some of the ideas in the code
may be useful to further customise the traceback message.

Do you have anything specific in mind? Clearly your code is more
generally flexible, but is there anything you would like to apply that
flexibility to? If so feel free to modify/replace my suggestions.

It's not necessarily more flexible.  The only idea that's interesting
is the trimming of both sides of the stack.  For example when in
scripting mode then everything before, and including, the
interact_script() function and everything after the RelaxError or
RelaxWarning is of no use.  However I don't currently have test case
data to see if there is anything after these points in the stack.


My intention in coding this was to have a warning traceback that looks
just like an exception traceback from the same point. I trim the bottom
of the stack to remove the python warning handling machinery from the
trace, because that would not appear if an exception had been thrown,
and in my opinion could only have confused matters. On the other hand,
the stuff at the top of the traceback would be present if an exception
had been thrown rather than a warning. Note that this particular code is
only used to print additional warning info in debug mode. As such it is
only likely to be used by people used to staring at python tracebacks.

From my test data, the traceback resulting from this code looks
something like:

Traceback (most recent call last):
  File "warnings/relax", line 435, in ?
    Relax()
  File "warnings/relax", line 162, in __init__
    self.interpreter.run()
  File "/home/chris/relax_devel/warnings/prompt/interpreter.py", line
213, in run
    run_script(intro=self.relax.intro_string, local=self.local,
script_file=self.relax.script_file, quit=1)
  File "/home/chris/relax_devel/warnings/prompt/interpreter.py", line
388, in run_script
    console.interact(intro, local, script_file, quit)
  File "/home/chris/relax_devel/warnings/prompt/interpreter.py", line
340, in interact_script
    execfile(script_file, local)
  File "test_m5.py", line 38, in ?
    pdb(name, 'test_data/test.pdb', proton='HN')
  File "/home/chris/relax_devel/warnings/prompt/pdb.py", line 129, in
pdb
    self.relax.generic.pdb.load(run=run, file=file, dir=dir,
model=model, heteronuc=heteronuc, proton=proton, load_seq=load_seq)
  File "/home/chris/relax_devel/warnings/generic_fns/pdb.py", line 195,
in load
    self.vectors()
  File "/home/chris/relax_devel/warnings/generic_fns/pdb.py", line 242,
in vectors
    warn(RelaxNoAtomWarning(self.proton,
self.relax.data.res[self.run][j].num))
RelaxWarning: The atom HN could not be found for residue 15

+    # Base class for all warnings.
+    ############################
+
+    class BaseWarning(Warning, RelaxErrors.BaseError):
+        def __str__(self):
+            return self.text

Does this need to be a subclass of RelaxErrors.BaseError?

I thought this was the best way to do it, but I'm happy to consider
other arguments. My logic was that if a warning is upgraded to an
exception, then it should be treated like any other relax error. This
means that when we need to catch all relax errors (eg. for UI specific
error handling) then we just need 'except BaseError' to do that. Are
there any reasons you are uncomfortable with this approach?

I didn't see that - I didn't realise that testing against the subclass
would catch it.  Maybe if BaseError was renamed to RelaxBaseError it
will be automatically placed into __builtin__ (otherwise it could be
placed in there manually).  This could then replace the
'AllRelaxErrors' data structure and all the tests for
'AllRelaxErrors'.  That's a much more logical approach than mine.

Edward





Related Messages


Powered by MHonArc, Updated Wed Aug 30 18:41:21 2006