On Tue, Jun 1, 2010 at 3:14 PM, Vinay Sajip <vinay_sa...@yahoo.co.uk> wrote:
>
> On Jun 1, 3:07 am, Russell Keith-Magee <russ...@keith-magee.com>
> wrote:
>>
>> My concern here is YAGNI. Can you suggest a specific use case where
>> this will actually be required?
>
> I agree with the YAGNI principle generally, but to my mind it's
> something to bear in mind if one were implementing a new feature with
> a fair amount of additional code. In this case, we're talking about a
> choice between (using pseudo-names for the functions)
>
>    # in Django code after importing settings
>    configure_logging_from_dict(settings.LOGGING) # your proposal
>
> versus
>
>    # in Django code after importing settings
>    settings_callback() # my proposal
>
> # in settings.py
> def settings_callback():
>    configure_logging_from_dict(LOGGING) # the normal case
>
> which has the advantage that I can replace the "normal case" with any
> specific stuff that I want. For example, pick between different
> configurations depending on some other value in settings.py:
>
> # in settings.py
> def settings_callback():
>    if DEBUG:
>        logging_config = DEV_LOGGING
>    else:
>        logging_config = PROD_LOGGING
>    configure_logging_from_dict(logging_config)
>
> I don't think this use case would be uncommon. Now I'm not saying you
> couldn't do this any other way, but the above seems a reasonably
> natural way of doing it.

IMHO, that use case would be better handled with two different
settings files -- one with DEBUG=True and debug logging, and one with
DEBUG=False and production logging. Having multiple settings files
isn't an unusual deployment arrangement; there are many guides to
Django deployment that will advise that approach.

Your proposal also requires that we start recommending that users put
logic into their settings.py, and I'm not comfortable making that a
recommended practice. Nothing else in a Django settings file is a
callable; I don't see why logging needs to break that trend.

My YAGNI objection is grounded in the fact that I can't see why lots
of flexibility is required in the logging configuration process. For
all the example cases I can envisage, there is exactly 1 function call
that the logging setup process needs to make, and the value passed to
that function is a configuration dictionary that can live in settings.

*If* we were to accept the use case that configurable logging setup
function is required, I'd be much more inclined to have a
LOGGING_SETUP = 'path.to.my.setup_function', with a default value that
points to an implementation that just calls
configure_logging_from_dict(). However, we can also add this later in
an entirely backwards compatible way if it turns out to be a common
requirement.

> To quote Simon Willison
> [1]:
>
> "The problem is that Django's startup execution order is poorly
> defined - stuff relating to settings is lazily evaluated the first
> time it's needed, and there's no real documented place to put code
> that needs to be executed once (the fact so many registration things
> end up being called from urls.py is a good indicator that this is a
> problem)."

This is exactly why startup.py is being proposed. We need to have a
place to reliably register signal handlers, search callbacks, and
anything else that has historically been put in urls.py.

> But having the
> more general mechanism also makes harder things possible at almost no
> extra cost, and in my view that's a good thing.

"No extra cost" isn't a very good argument, because there is always a
cost. In this case, it's not the cost of implementation or execution
that concerns me - it's the cost of having a public API that we need
to maintain, and a point of backwards compatibility that needs to be
maintained if we ever modify the model loading infrastructure
(something that the GSoC is working on, for example).

>> startup process, I don't see that this is something that requires a
>> callback system independent of Django's existing signals framework.
>> Again, if you can provide a specific use case to prove otherwise, I'm
>> willing to be convinced.
>
> It's hardly a "callback system independent of Django's existing
> signals framework", by which I mean it's hardly worthy of calling it a
> "system" as it's a lot simpler. Basically, just something like
>
>    if hasattr(settings, 'PRE_MODEL_CALLBACKS'):
>        callbacks = settings.PRE_MODEL_CALLBACKS
>        for callback in callbacks:
>            callback()
>
> which is pretty darn simple, to my mind and hardly a competing
> framework to the signals stuff. If you think the names would cause
> confusion (e.g. BOOTSTRAP, CALLBACK, then those can easily be changed.

It's not about the names, it's about the pattern that is being
reimplemented. Your proposal may well be simple, but it doesn't change
the fact that "callbacks" are essentially a reimplementation of
exactly what signals do, but with less flexibility. A signal is just
an agreement to call a bunch of functions -- exactly like the callback
you describe, except that signals allow for a generic registration
(rather than using a setting), and signals can be filtered based on
the arguments with which the callback was invoked.

As your quote from Simon indicates, there is a need to provide a
reliable location that can be used for registrations, installing
signal handlers, and other 'on startup' behaviors. This can't be a
signal because you need to have somewhere to install the first signal
handler. So, startup.py needs to use a different approach, and needs
to happen as early as possible in the process. Right after logging is
configured is as good a place as any. The only operational difference
between startup.py and your PRE_MODEL_CALLBACKS list is that
startup.py doesn't require any new settings in order to work -- you
just drop a startup.py in your app, and you're done.

However, once this initial startup has been invoked, any other
callback that is required can be handled by signals. There is no
operational difference between the POST_MODEL_CALLBACKS and a
'models_loaded' signal; but again, the signal approach doesn't require
any new settings. All we are arguing about is the need for this signal
at all.

Your comment about avoiding the model loading race condition is
certainly a valid one, and that's probably enough to get me over the
line on the need for this signal. My only concern is whether there is
anything else that a "models_loaded" signal should be 'after'. If
we're going to introduce a "we've finished setup" signal, I want to
make sure that the place we emit it is a point at which we can
guarantee that we've actually finished the setup :-)

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to