from encaps import *
from lbind import IRef, localBind

import time

class A:
    x = 1
    def f(self):
        return self.x
    def fd(self):
        return self.x+1
    def emp(self):
        pass

def g(self, v):
    self.x = v

def h(self, v):
    self.x = self.x + v

class P:
    def __init__(self, info):
        self.info = info
    def __call__(self, obj, msg):
        print "%s: %s" % (self.info, `msg`)

def get(obj, attr):
    print "getAttr %s: %s = %s" % (`obj`, attr, getattr(obj, attr))

def set(obj, attr, val):
    print "setAttr %s: %s = %s" % (`obj`, attr, val)

print "INIT"
a = A()
print "a.f :", `a.f`
i = IRef(a, ['f', 'fd'], [])
print "i.f :", `i.__local__["iobj"].f`
print "     ", `getattr(i.__local__["iobj"].f.object, i.__local__["iobj"].f.key)`
j = IRef(None, [], ['f', 'fd', 'h'])
ma = encapsulation(a)
print "ma.f:", `ma._ms.f`
mi = encapsulation(i)
print "mi.f:", `mi._ms.f`
print "     ", `getattr(mi._ms.f.object, mi._ms.f.key)`
print

print "INSPECT"
print "ma:", `ma.inspect()`
print "mi:", `mi.inspect()`
print

print "ADDMETHOD"
ma.addMethod('g', g)
ma.addMethod('gd', g)
a.g(10)
print "ma:", `ma.inspect()`
print "mi:", `mi.inspect()`
print

print "ADDMETHOD META"
mi.addMethod('h', h)
mi.addMethod('hd', h)
print "ma:", `ma.inspect()`
print "mi:", `mi.inspect()`
print

print "LOCALBIND"
localBind(j, i)
j.h(5)
print "j.f():", j.f()
print "ma:", `ma.inspect()`
print "mi:", `mi.inspect()`
print

print "DELMETHOD"
ma.delMethod('gd')
ma.delMethod('fd', 1)
mi.delMethod('hd')
print "ma:", `ma.inspect()`
print "mi:", `mi.inspect()`
mi.delMethod('fd')
print "mi:", `mi.inspect()`
print

print "ADDPREMETHOD"
p1 = P("a.f1")
p2 = P("a.f2")
ma.addPreMethod('g', P("a.g"))
mi.addPreMethod('f', P("i.f"))
ma.addPreMethod('f', p1)
ma.addPreMethod('f', p2)
print "a.g(7):"
a.g(7)
print "x, y = a.f(), j.f():"
x, y = a.f(), j.f()
print "x =", x, "og y =", y
print

print "DELPREMETHOD"
ma.delPreMethods('f', p1)
mi.delPreMethods('f')
print "ma.delPreMethods('f', p1), mi.delPreMethods('f'):"
x, y = a.f(), j.f()
print "x =", x, "og y =", y
ma.delPreMethods('f')
print "ma.delPreMethods('f'):"
x, y = a.f(), j.f()
print "x =", x, "og y =", y
print

print "POSTMETHOD"
ma.addPostMethod('f', p1)
mi.addPostMethod('f', p2)
print "x, y = a.f(), j.f():"
x, y = a.f(), j.f()
print "x =", x, "og y =", y
ma.delPostMethods('f')
mi.delPostMethods('f')
print "x, y = a.f(), j.f():"
x, y = a.f(), j.f()
print "x =", x, "og y =", y
print

print "GETATTR"
ma.addGetAttr('x', get)
print "a.x:", a.x
ma.delGetAttr('x')
print "a.x:", a.x
print

print "SETATTR"
ma.addSetAttr('x', set)
print "a.x = 23"
a.x = 23
ma.delSetAttr('x', set)
print "a.x = 12"
a.x = 12
print


# Some measurements
a = A()
a.x = 0
r = 10000
t = time.time()
for x in xrange(r):
    a.emp()
d = time.time() - t
print "f directly  (calls per second):", r/d, ",  %1.8f" % (d/r)

t = time.time()
for x in xrange(r):
    x = a.x
d = time.time() - t
print "x directly  (calls per second):", r/d, ",  %1.8f" % (d/r)

t = time.time()
for x in xrange(r):
    a.x = 1
d = time.time() - t
print "x directly  (calls per second):", r/d, ",  %1.8f" % (d/r)

e = encapsulation(a)
print 

t = time.time()
for x in xrange(r):
    a.emp()
d = time.time() - t
print "f with meta (calls per second): ", r/d, ", %1.8f" % (d/r)

t = time.time()
for x in xrange(r):
    x = a.x
d = time.time() - t
print "x with meta (calls per second): ", r/d, ", %1.8f" % (d/r)

t = time.time()
for x in xrange(r):
    a.x = 1
d = time.time() - t
print "x with meta (calls per second): ", r/d, ", %1.8f" % (d/r)
