BagResolver

The idea at the basis of dynamic bags is to hide the calls to databases, webservices treating their results as they were a static items of the bag. BagResolver is an interface for defining objects that implement this 'reification'. A resolver overrides the primitive call, wich is the one that intercepts any round-brackets call, and must implements the method load(). When a resolver is called my_resolver(), it calls its method load(). A resolver may have a cache, if it inherits from the subclass BagCachedResolver?. Thee cache stores the retrieved value and keeps it for a lapse of time called cacheTime. Each resolver implements the method load() that reads the result from cache, if cacheTime isn't elapsed, or takes it from its remote source. The call my_resolver can receive some kwargs. A resolver is set in a node by the BagNode?'s method setResolver(my_resolver).

Here follows some examples of BagResolver.

ex.1: Time and Day Resolver

class TimeResolver(BagResolver):
    def __call__(self):
        return datetime.now()
    
class DayResolver(BagCachedResolver):
    def load(self):
        return datetime.now().date()

If your resolver inherits from BagCachedResolver? you ought to implement the method load, else if it inherits directly from BagResolver must be implemented the method call. Now let's see how do they work in a bag.

time=Bag()
time['now']=TimeResolver()
time['today']= DayResolver()

>>> print time['now']
2006-10-04 10:27:16.231559

>>> print time['today']
2006-10-04

Ex.2 CallBackResolver

class BagCbResolver(BagCachedResolver):
    """This is a standard resolver. It calls a callback method, passing its kwargs parameters
    """
    def init(self, method, **kwargs):
        self.method = method
        self.kwargs = kwargs
        
    def load(self):
        return self.method(**self.kwargs)

Ex.3 UserInfoResolver

from gnr.bag.gnrbag import Bag, BagCachedResolver
import socket, os

class UserInfoResolver(BagCachedResolver):
    def load(self):
        result = Bag()
        try:
            result['hostname']=socket.gethostname()
            result['ip']=socket.gethostbyname(result['hostname'])
        except:
            result['hostname']='localhost'
            result['ip']='unknown'

        result['pid']=os.getpid()
        result['user']=os.getenv('USER')
        result['ID']=result['ip']+'-'+str(result['pid'])+'-'+result['user']
        return result

This resolver returns a bag that contains some information about the current user: Here is how the resolver works:

mybag= Bag()
mybag['info']= InfoResolver()
info=mybag['info']
template="This is the process %s. \n You are user %s, from the host %s at the address %s"
>>> print template %(mybag['info.pid'],mybag['info.user'],mybag['info.hostname'], mybag['info.ip'])
This is the process 7296. 
 You are user foo_user, from the host ikid.local at the address 192.168.1.53

Ex.4 RssFeedResolver

class RssFeedResolver(BagCachedResolver):
    def init(self, feed):
        self.feed=feed
        
    def load(self):
        feed= Bag(self.feed)['rss.channel']
        result= Bag()
        result['title']= feed.pop('title')
        result['description']= feed.pop('description')
        result['link']= feed.pop('link')
        result['language']= feed.pop('language')
        result['copyright']= feed.pop('copyright')
        dig= feed.digest('#v.title, #v.description, #v.pubDate, #v.link')
        news=Bag()
        for title, description, pubDate, link in dig:
            news.setItem(title.replace('.', '\.').replace(' ','_'), description, link=link, date=pubDate, title=title)
        result['news']=news
        return result
    

This resolver receives the URL of a RSS feed of the web, and since a Bag can be created starting from an XML it's very easy to have all the news in our bag.

mybag['feeds.washingtonpost']= RssFeedResolver('http://www.washingtonpost.com/wp-dyn/rss/world/index.xml')

>>> print 'Gnr Bag presents %s' %mybag['feeds.washingtonpost.desctiption']
Gnr Bag presents World news headlines from the Washington Post,including international news and opinion from Africa,North/South America,Asia,Europe and Middle East. Features include world weather,news in Spanish,interactive maps,daily Yomiuri and Iraq coverage.

>>> print mybag['feeds.washingtonpost.news.#5.?a:title']
N. Korean Move Comes Amid Bid for Talks 

In the next chapter we'll se in detail a particular built-in resolver called BagFormula.