3.1 - BagResolver

The idea at the basis of dynamic bags is to hide function calls 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 the cacheTime is specified in the args, else it's considered 0. The 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).

3.1.1 - Examples

3.1.1.1 - Ex.1 TimeResolver

For example, there are several ways to create a Bag with an item labeled now that always returns current time. First of all we can define a class TimeResolver that inherits from BagResolver:

from datetime import datetime

class TimeResolver(BagResolver):
    def __call__(self):
        return datetime.now()
    

Defining a BagResolver's sublass requires the reimplementation of the __call__() function.

Now we can set an instance of TimeResolver as now:

mybag=Bag()
mybag['now']=TimeResolver()

>>> print mybag['now']
resolving now: <__main__.TimeResolver object at 0x6a870>
2006-10-04 10:27:16.231559

As we can see, there's no need to import the module datetime because it was already imported in the class definition.

If we want the now item to be updated every 100 ms, we can use the TimeResolver? class with a cacheTime value.

The mybag['now'] value will be updated every 100 ms:

ct=100
mybag['now']=TimeResolver(cacheTime=ct)

>>> print mybag['now']
resolving now: <__main__.TimeResolver object at 0x6a370>
2006-10-04 10:27:18.221551

3.1.1.2 - Ex.2 UserInfoResolver

The following example defines a resolver that prepares a Bag containing some information about the computer (e.g. hostname, IP, PID, user):

from gnr.core.gnrbag import Bag, BagResolver
import socket, os

class UserInfoResolver(BagResolver):
    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

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

3.1.1.3 - Ex.3 RssFeedResolver

In the following example the 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:

class RssFeedResolver(BagResolver):
    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(' ','_'), # label 
                         description,                               # values
                         link=link, date=pubDate, title=title)      # attributes
        result['news']=news
        return result
    

Here is how the resolver works:

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

The resulting Bag is structured as shown below:

Item value
title washingtonpost.com - World News and Analysis From The Washington Post
description 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.
link http://www.washingtonpost.com/wp-dyn/content/world/index.html?nav=rss_world
language EN-US
copyright None
news Bag of News

Each news item is a bag node structured as follows:

label value attributes
In_Russia,_A_Secretive_Force_Widens_ MOSCOW -- On Nov. 15, the Russian Interior Ministry and Gazprom, the state-controlled energy giant, announced... link, date, title

3.1.2 - Shortcuts

If the dynamic value is simply a function call, you can avoid a new resolver definition by using an instance of BagCbResolver, that is a generic BagResolver for callback functions.

from gnr.bag.gnrbag import Bag, BagCbResolver

>>> mybag['now']=BagCbResolver(datetime.now)

>>> print mybag['now']
resolving now: <gnr.bag.gnrbag.BagCbResolver object at 0x56cd0>
2006-12-12 12:41:33.603008

This can work for every function:

def sayHello():
     return 'Hello World!'

>>> mybag['hello']=BagCbResolver(sayHello)

>>> print mybag['hello']
resolving hello: <gnr.bag.gnrbag.BagCbResolver object at 0x56f90>
Hello World!

Alternative syntax:

>>> mybag.setCallBackItem('hello', sayHello)

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


Error: Failed to load processor FooterNavLinks
No macro or processor named 'FooterNavLinks' found

Attachments