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.
Attachments
- rssresolver.py (1.2 kB) - added by anonymous 2 years ago.
- BagTimeResolver.py (0.7 kB) - added by anonymous 22 months ago.
- BagUserinfoResolver.py (1.0 kB) - added by anonymous 22 months ago.
