A startup puzzle

Mike C. Fletcher mcfletch at rogers.com
Mon Sep 29 21:39:12 CEST 2003

Edward K. Ream wrote:

>I've just about convinced myself there is no good, clean solution to the
>following puzzle.  I wonder if you agree.
>1. My app has a module called leoGlobals that contains often-used global
>functions.  All of Leo's source files start with:
>from leoGlobals import *
>I don't want to discuss whether this is good style: it is simple and it
>works well for me :-)
Okay, we'll take that as a given then.

>2.  All code accesses the singleton application object using the app()
>method in leoGlobals.
Sure, implements late-binding via indirection.

>3.  To make the code cleaner looking, I would really like the code to be
>able to access an app global instead of the app() function.  This has
>nothing to do with speed: it's simply that there are lots of references to
>app() in the code, and there is soon going to be a lot more references to
>app.gui.x() and app.gui.y() etc.
>As a workaround, many methods and functions assign a = app(), but I would
>like to avoid this step.
This can be done by creating a built-in variable e.g. APPLICATION, which 
is an application-wide variable, like so:

    def __install( self ):
        """Install self into the builtin module"""
        __builtin__.APPLICATION = self

note that this *doesn't* help if there really are hidden dependencies in 
your modules on having the APPLICATION object defined, but given your 
description of the architecture, that doesn't appear to be the case.

>4. Alas, it does not seem possible to initialize an app global in
>leoGlobals.  The reason is simple:
>from leoGlobals import *
>caches the value of app at the time the  import is done.  But the startup
>code that creates the app "global" (really an attribute of the leoGlobals
>module) must do _other_ imports.
>For example, doing the following at the top of leoGlobals doesn't work:
>import leoApp
>app = leoApp.leoApp() # construct the app instance.
>Indeed, the leoApp module will be imported before the assignment of app.
>Moreover, the leoApp module does other imports, and all the app variables in
>those modules will be uninitialized.
>It would be horrible style to place detailed constraints on the order in
>which modules get imported, and I'm not sure even that would work.
Such constraints will exist.  Any module which relies on the existence 
of an initialised APPLICATION variable must be imported after the 
creation of that variable.  You construct the app so that the 
APPLICATION is created ASAP and that becomes a minimal restriction, 
since your code is working, it's already passed that level of 
restriction :) .

The alternatives to such restrictions are pretty grotty; defered 
execution of suites of code that would likely require Stackless Python 
and a decent masters thesis working out the calculus of dependency 
resolution (what with needing to defer or speculatively execute each 
path in the code dependant on the app object's operation).  Luckily 
that's all just academic for your project :) .

>Any ideas for a clean solution?  Thanks.
Cleanliness is in the eye of the beholder.  I don't really like the 
APPLICATION-object "pattern", but it is very convenient in many simple 
cases.  Just about everything else I've seen either requires something 
exotic (e.g. proxy objects implementing the late-binding indirection by 
pretending to be the app object (raising errors if anything attempts to 
use the object before it's bound)), or the solution you started with, 
i.e. using function's built-in late-binding to implement it.


  Mike C. Fletcher
  Designer, VR Plumber, Coder

More information about the Python-list mailing list