#! /usr/bin/env python
'''

This program ("Snapper", previously "Wiki Snapper") generates a set of
web pages (on local disk) in proper W3C Tech Report (TR) format from a
set of MediaWiki pages (or similar Web page).  Well, that is the idea;
it is pretty configurable.

It is guided by RDF data about the group, the particular snapshot you
want to take, and the pages to be included in that snapshot.

'''
__version__ = "$Revision: 1.2 $"

from debugtools import debug

class PropertyStack:
    """Present the python dictionary interface (getitem, etc) to a bunch of
    information objects.   This is useful for python %(foo)
    substitution, which we use.   It can access all attributes of these
    objects unless they start with an underscore.   It also tries a
    _compute_foo(self) function of each (missing) property foo.

    Also supports the attr interface, to the same stack.

      > m = PropertyStack([obj1, obj2, obj3, obj4])

      >  m['foo']
      looks for obj1.foo
                obj1._compute_foo(m)  
                obj2.foo
                obj2._computer_foo(m)  ... etc

                
    """

    def __init__(self, stack):
       self.stack = stack
       
    def __getitem__(self, key):

       debug('PropertyStack(', 'get(', key, ')')
       for obj in self.stack:

           debug('PropertyStack', 'looking in', obj)
           try:
               value = getattr(obj, key)
               debug('PropertyStack)', 'value=', value)
               return value
           except AttributeError:
               pass

           try:
               # pass them this 'dict' so they can be nicely opaque
               value = getattr(obj, "_compute_"+key)(self)
               debug('PropertyStack)', 'computed=', value)
               return value
           except AttributeError:
               pass

       raise KeyError(key)
       
    def __setitem__(self, key, value):
        raise RuntimeError, 'not mutable this way; change the underlying objects instead'

    def __iter__(self):
        return self.iterkeys()

    def iterkeys(self):

        for obj in stack:
            for key in obj.__dict__.iterkeys():
                if key.startswith("_"):
                    if key.startswith("_compute_"):
                        yield key[len("_compute_")-1:]
                    else:
                        pass
                else:
                    yield key

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(name)

