# HG changeset patch # User "Rex Tsai " # Date 1225557038 -28800 # Node ID 278bd36708e89198e975d7706c324cf9c40a7598 # Parent eff35293a058c954fc0c33ea5c384cab9d15d0ef# Parent 1507c2d16b35a9b15ee189f4f94b49f476a11c87 merged. diff -r eff35293a058 -r 278bd36708e8 pyikriam/__init__.py --- a/pyikriam/__init__.py Sat Nov 01 15:43:07 2008 +0800 +++ b/pyikriam/__init__.py Sun Nov 02 00:30:38 2008 +0800 @@ -4,23 +4,44 @@ import os import urllib2 import urllib +from utils import dyna_prog, decorator + +class fake_moz(object): + __metaclass__ = decorator + + def __init__(self): + super(fake_moz, self).__init__() + cookie_jar = cookielib.LWPCookieJar() + cookie_proc = urllib2.HTTPCookieProcessor(cookie_jar) + opener = urllib2.build_opener(cookie_proc) + opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.8.1.12pre) Gecko/20071220 BonEcho/2.0.0.12pre')] + fake_moz.set_backend(self, opener) + self.cookie_jar = cookie_jar + pass + pass + + class Ikariam: cities = {} + COOKIEFILE = '/tmp/ikariam.lwp' def __init__(self): - self.COOKIEFILE = '/tmp/ikariam.lwp' + browser = fake_moz() + self.browser = browser + self._cookie_jar = browser.cookie_jar + + if os.path.isfile(self.COOKIEFILE): + self._cookie_jar.load(self.COOKIEFILE) + pass + + urllib2.install_opener(browser) + self.confdata=LoadConfigfile().cd self.baseurl='http://'+self.confdata['server'] - self.cj = cookielib.LWPCookieJar() - if os.path.isfile(self.COOKIEFILE): - self.cj.load(self.COOKIEFILE) - - opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj)) - opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.8.1.12pre) Gecko/20071220 BonEcho/2.0.0.12pre')] - urllib2.install_opener(opener) self.login() + pass def login(self): print "login to %s...." % self.confdata['server'] @@ -28,27 +49,51 @@ "name":self.confdata['user'], \ "password":self.confdata['pass']} ret = c(self.baseurl+'/index.php?action=loginAvatar&function=login').get(params).get_content() - self.cj.save(self.COOKIEFILE) - + self._cookie_jar.save(self.COOKIEFILE) + pass + def logout(self): print "logut from %s...." % self.confdata['server'] c(self.baseurl+'/index.php?action=loginAvatar&function=logout') os.remove(self.COOKIEFILE) - + pass + + ## + # \note We can cache data with decorator 'dynamic programming'. + # + @dyna_prog def city(self, id): - return self.cities.get(id, IkariamCity(id=id, core=self) ) - + return IkariamCity(id=id, core=self) + pass + class IkariamCity: - + data_patterns = { + 'gold': '/div[@id=\'globalResources\']/ul/li/a/span[@id=\'value_gold\']/text()', + 'inhabitants': '/div[@id=\'cityResources\']/ul/li/span[@id=\'value_inhabitants\']/text()', + 'wood': '/div[@id=\'cityResources\']/ul/li/span[@id=\'value_wood\']/text()', + 'wine': '/div[@id=\'cityResources\']/ul/li/span[@id=\'value_wine\']/text()', + 'marble': '/div[@id=\'cityResources\']/ul/li/span[@id=\'value_marble\']/text()', + 'crystal': '/div[@id=\'cityResources\']/ul/li/span[@id=\'value_crystal\']/text()', + 'sulfur': '/div[@id=\'cityResources\']/ul/li/span[@id=\'value_sulfur\']/text()' + } def __init__(self, id, core ): self.core = core self.id = id self.params = {'view':'city','id':id} def sync(self): + from lxml import etree + from StringIO import StringIO + print "pull datas of the city %s" % self.id - xpath_globalinfo = "/html/body[@id='city']/div[@id='container']/div[@id='container2']/div[@id='globalResources']/ul" + xpath_globalinfo = "/html/body[@id='city']/div[@id='container']/div[@id='container2']" - xpath_gold = xpath_globalinfo + "/li[2]/a/span[@id='value_gold']/text()" - self.gold = c(self.core.baseurl).get(self.params).find(xpath_gold).get_content()[0] - + page = c(self.core.baseurl).get(self.params).get_content() + parser = etree.HTMLParser(encoding='utf8') + page_dom = etree.parse(StringIO(page), parser) + for name, path in self.data_patterns.items(): + xpath = xpath_globalinfo + path + value = page_dom.xpath(xpath)[0] + setattr(self, name, value) + pass + pass diff -r eff35293a058 -r 278bd36708e8 pyikriam/example.py --- a/pyikriam/example.py Sat Nov 01 15:43:07 2008 +0800 +++ b/pyikriam/example.py Sun Nov 02 00:30:38 2008 +0800 @@ -3,4 +3,12 @@ i = Ikariam() city = i.city(117261) city.sync() -print 'gold is'+city.gold +print 'gold is ' + city.gold +print 'inhabitants is ' + city.inhabitants +print 'wood is ' + city.wood +print 'wine is ' + city.wine +print 'marble is ' + city.marble +print 'crystal is ' + city.crystal +print 'sulfur is ' + city.sulfur + + diff -r eff35293a058 -r 278bd36708e8 pyikriam/lconf.py --- a/pyikriam/lconf.py Sat Nov 01 15:43:07 2008 +0800 +++ b/pyikriam/lconf.py Sun Nov 02 00:30:38 2008 +0800 @@ -1,15 +1,33 @@ -import os,string +import os, string +import re + +_user_home = os.environ['HOME'] +dfl_profile = os.path.join(_user_home, '.eagleeye.pm') +_reo_assign = re.compile('^\\$::([_a-zA-Z][_a-zA-Z0-9]+) *= *([\'"][^"]*[\'"]).*$') + +def _real_load_conf(conf_o): + confs = [_reo_assign.match(line) + for line in conf_o + if line.startswith('$::')] + cd = dict([(mo.group(1), eval(mo.group(2))) + for mo in confs if mo]) + return cd + class LoadConfigfile(object): - def __init__(self): - profile = os.environ["HOME"]+'/.eagleeye.pm' - self.cd={} - if os.path.isfile(profile): - print "Loading Config file." - cfile=open(profile,'r') - for line in cfile.xreadlines(): - if line[0:3]=='$::': - con=string.split(line[3:-2]) - self.cd[con[0]]=con[2][1:-1] - else: - print "File don't exist." + def __init__(self, profile=dfl_profile): + prof_o = open(profile, 'r') + self.cd = _real_load_conf(prof_o) + pass + pass +if __name__ == '__main__': + from StringIO import StringIO + conf = ''' +$::user = "alsfjsf"; #lsfjslf +$::server = "fkljalfasf"; # sfjslf +$::pass = "lsfjslfsf"; +''' + conf_o = StringIO(conf) + cd = _real_load_conf(conf_o) + print cd + pass diff -r eff35293a058 -r 278bd36708e8 pyikriam/utils.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyikriam/utils.py Sun Nov 02 00:30:38 2008 +0800 @@ -0,0 +1,80 @@ +## \brief decorator is a class decorate another of another object. +# +# Access of attributes/methods that can not be found in an instance +# of a class of this meta-class, decorator, are delegated to the backend +# of the instance. +# +# A backend object always passed as first parameter when +# instantiate an instance of a class with decorator as meta-class. +# For example, +# \code +# class foo(object): +# __metaclass__ = decorator +# +# backend.data = 3 +# obj = foo(backend) +# print obj.data +# backend.data = 4 +# print obj.data +# \endcode +# it print out 3 and 4 respectively. +# +class decorator(type): + def __init__(clz, name, base, dict): + super(decorator, clz).__init__(name, base, dict) + clz.__getattr__ = decorator.__dele_getattr + pass + + @staticmethod + def set_backend(obj, backend): + obj.__backend = backend + pass + + @staticmethod + def __dele_getattr(obj, name): + return getattr(obj.__backend, name) + pass + + +## \brief Decorator to make functions or methods dynamic programming. +# +# dyna_prog result of functions or methods with their arguments as key. +# It supposes result of a function always the same if the same arguments +# are passed. It cache result of cached function to avoid really calling +# function every time. +class dyna_prog(object): + class functor(object): + def __init__(self, instance, method): + self._method = method + self._instance = instance + self._cache = {} + pass + + def __call__(self, *args): + try: + return self._cache[args] + except KeyError: + pass + instance = self._instance + result = self._method(instance, *args) + return self._cache.setdefault(args, result) + + def clear(self): + self._cache.clear() + pass + + def __init__(self, method): + super(dyna_prog, self).__init__() + self._method = method + self._functors = {} + pass + + def __get__(self, instance, owner): + try: + return self._functors[instance] + except KeyError: + pass + functor_o = dyna_prog.functor(instance, self._method) + return self._functors.setdefault(instance, functor_o) + pass +