On Tue, 2007-02-27 at 15:13 +1100, Edward d'Auvergne wrote:
> On 2/27/07, Chris MacRaild <[EMAIL PROTECTED]> wrote:
> > On Mon, 2007-02-26 at 23:32 +1100, Edward d'Auvergne wrote:
> > > I've been spending some time thinking about the problem and all the
> > > required changes. Gary, what do you think about the following
> > > proposal? The debug, warn, and pedantic flags could be stored in
> > > self.relax rather than __builtin__ (or could be passed the relevant
> > > functions, methods, or classes). The RelaxErrors could be changed so
> > > that they are not nested and individual RelaxErrors could be imported
> > > by the module requiring the error class (rather than importing *).
> > > The RelaxWarnings could be similarly modified and shifted into the new
> > > module 'warnings.py'.
> >
> > I agree that this looks like the best approach to the problem.
> >
> > > The issue with this approach is that the debug
> > > flag is used by the individual RelaxErrors. These objects are normal
> > > python error objects (subclassed from the Exception class) which are
> > > called with the following syntax:
> > >
> > > if bad:
> > > raise RelaxError, "This is a bad error."
> > >
> > > This instantiates the class, executing the self.__init__() function.
> > > To get access to the debug flag in this function we could set a global
> > > 'Debug' flag within the 'error.py' module (which defaults to 0 or
> > > False). This flag can then be set by the 'Relax' class within the
> > > file 'relax' when parsing the command line arguments.
> >
> > We need to do more than just make the debug flag availible, because the
> > relax exceptions need access to the interpreter in order to save state.
> > The solution is a simple function in errors.py that drops the Relax
> > instance into BaseError, then each relax exception will inherit from
> > there. Something like:
> >
> > def setupErrors(relax):
> > mod = sys.modules[__name__]
> > setattr(mod.BaseError, '_relax', relax)
> >
> >
> > Alternatively relax could be stored in a variable of the module:
> >
> > _relax
> > def setupErrors(relax):
> > global relax
> > _relax = relax
>
> The problem for the unit tests is that there will be no relax instance
> in the first place.
I don't think that is an issue. The Relax instance is not needed within
(most) unit tests, and it will never make sense to save state in a
stand-alone unit test (state == relax, so if there is no relax, there is
no state to save!). Furthermore, Debug==False for all stand-alone unit
test contexts, so the BaseError.save_state() will never be called.
In any case the general solution to problems of this type is to create a
dummy object which serves the purposes required of the unit test in
question.
> We could take the second approach but set the
> global 'relax' variable to None. Then we can use if statements to set
> up a dummy self.save_state() function in BaseError. I would try a
> different approach which utilises much of the current code. I don't
> think a setup function, similar to my kludgy self.__init__() code of
> the RelaxErrors class in which all other RelaxErrors are nested, is
> necessary and detracts from the simplicity of importing a specific
> RelaxError. My suggestion would be:
>
> -----
>
> relax = None
> Debug = False
>
>
> # Base class for all errors.
> ############################
>
> class BaseError(Exception):
> def __str__(self):
> return ("RelaxError: " + self.text + "\n")
>
>
> def save_state(self):
> """Function for saving the program state."""
>
> # Dummy function.
> if not relax:
> return
>
> # Append the date and time to the save file.
> now = time.localtime()
> file_name = "relax_state_%i%02i%02i_%02i%02i%02i" % (now[0],
> now[2], now[1], now[3], now[4], now[5])
>
> # Save the program state.
> relax.interpreter._State.save(file_name)
>
>
> # Standard errors.
> ##################
>
> class RelaxError(BaseError):
> ...
>
> -----
>
> I'll make a branch from the 1.3 line to test this code.
>
>
> > The much bigger issue is the question of whether it is appropriate to be
> > passing the Relax instance about as we do. That, I suspect, is a debate
> > for another day ...
>
> It isn't the Relax instance which is passed as a copy but rather a
> pointer to it. Having 'self.relax' as a pointer to the Relax instance
> within most of relax allows access to the methods and data storage
> structures from anywhere within relax. I don't know if this is an
> anti-pattern (http://en.wikipedia.org/wiki/Anti-pattern or
> https://mail.gna.org/public/relax-devel/2007-01/msg00015.html,
> Message-id: <[EMAIL PROTECTED]>),
> but it does work well. It allows the code in 'generic_fns' and
> 'specific_fns' to access or modify the relax data structures.
>
The alternative as I see it is to have program state discretely stored
in its own object, with appropriate get and set functions to allow the
rest of the code to interact. This ensures both the data, and control
over changes to the data, can be managed centrally. Admitedly, this is
not currently a big issue, but any sort of threading or multi-processor
operation will be much easier to organise with this sort of design.
> We could change this behaviour so that only the data currently in
> 'self.relax.data' is passed to all the necessary relax classes and
> then we could use import statements for all the cross talk. I would
> however suggest we sit on the idea until the redesign
> (https://mail.gna.org/public/relax-devel/2006-10/msg00053.html,
> Message-id: <[EMAIL PROTECTED]>)
> has been completed. The breakages that this would incur would be
> significant and core parts of the program would need to be redesigned.
> Any changes will require significant planning.
>
Agreed. As I say, its a debate for another day. Nonetheless the ideas
are still worth keeping in mind now.
> Cheers,
>
> Edward
>
Chris
_______________________________________________
relax (http://nmr-relax.com)
This is the relax-devel mailing list
[email protected]
To unsubscribe from this list, get a password
reminder, or change your subscription options,
visit the list information page at
https://mail.gna.org/listinfo/relax-devel