mailRe: RelaxWarnings


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

Header


Content

Posted by Edward d'Auvergne on August 16, 2006 - 18:17:
> The non-Python warning system would however be difficult to escalate
> into an error.  Then again using the Python warning system would also
> be complex due to it's non-trivial implementation.

I think it can be done either way, both have disadvantages. For the
non-Python system, it will require something like:

if pedantic:
    raise RelaxError, msg

in the RelaxWarning.__call__() function. The disadvantage here is that
the error will be raised from the warning, not from the point in the
code where the warning was trigered. Therefore the traceback will not be
as clear as it might be. There is also a risk that the RelaxError might
be accidentally caught elswhere in the code, and misinterpreted. One way
around that would be to use a specific class of Exception for upgraded
warnings (RelaxPedanticError, eg.). Of course this could be subclassed
to give more specific behaviour, and could be caught if UI issues
demanded.

The error could be raised with a function called by __call__(), caught, the traceback trimmed, and then reraised. The trimming part may not be feasible though. I like the idea of retaining the names RelaxWarning, etc. RelaxPedanticError (or maybe RelaxWarningError) could be raised, the warning message passed to it, and it prints out 'RelaxWarning: ' + message.


Escalation of Warnings in the Python system should also be quite easy,
by setting appropriate filters at a high level in the code
(prompt/interpreter.py might be the spot, or maybe even the relax main
script?). The code would look something like:

if pedantic:
    warnings.filterwarnings('error', category=RelaxWarning)
else:
    warnings.filterwarnings('always', category=RelaxWarning)

Then all warning classes that are subclasses of RelaxWarning will be
raised as an exception if pedantic, otherwise the warning will be
printed and execution will continue.

Are you sure we wouldn't need to do this for all the specific RelaxWarnings? This is probably dependent upon how we implement the system.

This approach has none of the
drawbacks of the the custom warning system described above, but does
suffer from the general obscurity of the python warnings system. I
suspect it should be possible to subclass from BaseError as well,
meaning that exceptions raised by escalation of a warning will be easily
treated by the UI specific try statements and will have the same nice
debuging features as we put into the other RelaxErrors.

I guess I'm begining to favour the Python warnings system, because I
think it will lead to clearer results for the user, even though it might
make life a bit more complicated for the developers. This is not a
strong preference, though, so if anyone else feels strongly otherwise,
I'm happy either way.

I prefer the Python warning system as well but I have to say - surely they could have come up with a better solution? That system is convoluted and poorly documented, I wouldn't be surprised if the entire thing becomes depreciated and replaced by something a bit more logical in future Python versions. For example the description of category in the warnings filters is:

category is a class (a subclass of Warning) of which the warning
category must be a subclass in order to match.

The 'category' keyword is for matching but what exactly is matched?
If RelaxZeroVectorWarning is a subclass of BaseWarning (i.e.
RelaxZeroVectorWarning(BaseWarning)), does category='BaseWarning'
actually match RelaxZeroVectorWarning???  The description is terrible!
Firstly 'category' is both the keyword used by the 'filterwarnings()'
function and the class object within the filter list that you supply
through that keyword.  Here is some more bizarre and dodgy behaviour:

relax> import warnings
relax> def format(message, category, filename, lineno):
relax|     return "RelaxWarning: %s\n" % message
relax|
relax> warnings.formatwarning = format
relax> warnings.warn('Hello')
RelaxWarning: Hello
relax> help(warnings.formatwarning)
relax> warnings.warn('Hello')
relax>

Huh???  Where did RelaxWarning disappear to??? Same thing happens if
you use the real Python help function on any 'warnings' objects,
including itself???  I'm pretty sure this should not happen!

If there are too many problems caused by bugs in the Python warning
system we can write our own warning system in the future.  Anyway,
enough bashing of the Python warning system.

A problem that needs to be solved is how do we implement specific
warnings?  For example if two distant areas of relax test for zero
length XH bond vectors, there should be one function which takes the
residue number and formats a standard message for that warning.
However the 'warn()' function expects a message?  What if we have a
class object called RelaxZeroLengthWarning which has a __call__()
method which returns the formatted string?  You could then, from
within different parts of relax, generate an error by having the code:

if len(xh) == 0.0:
   warn(RelaxZeroLengthWarning(res))

where warn was placed into __builtin__ by relax (see the
'nan_catch_test' branch) and 'res' is the residue number.  There
might, however, be a much better way to implement specific warnings.
The rest of the system could be setup as in the 'nan_catch_test'
branch.

Edward



Related Messages


Powered by MHonArc, Updated Wed Aug 16 19:20:43 2006