#coding: utf8

# formateado por http://www.sweetapp.com/cgi-bin/cgi-styler-form.py

from itertools import count
import copy


###########################################################
# Acceso a atributos

class C (object):
	def __init__(self):
		self.y = 0

	def __getattribute__(self, name):
		print 'getattribute', name
		return object.__getattribute__(self, name)

	def getx(self):
		print 'getx'
		return self.y

	x = property(fget = getx)

	def __getattr__(self, name):
		print 'getattr', name
		raise AttributeError



###########################################################
# Interfaz de iteración

def myloop(f, l):
	it = l.__iter__()
	try:
		while True:
			i = it.next()
			f(i)
	except StopIteration:
		return
	return


class EneVecesUno (object):
	def __init__(self, n):
		self.count = 0
		self.n = n

	def __iter__(self):
		return self

	def next(self):
		self.count += 1
		if self.count <= self.n:
			return 1
		else:
			raise StopIteration



###########################################################
# Generators

# La papa, el mágico Erastotenes
def sieve(gen):
	x = gen.next()
	yield x

	for n in sieve(y for y in gen if y % x > 0):
		yield n

# En primos tenemos TODOS los primos!
primos = sieve(count(2))


# Ping pong, como el deporte
def mandar(msg):
	v = yield msg
	while v != 'fin':
		print v
		v = yield msg

ping = mandar('ping')
pong = mandar('pong')

def pingpong(n):
	po = pong.next()
	pi = ping.next()
	for i in range(n):
		po = pong.send(pi)
		pi = ping.send(po)



###########################################################
# Decorators

def logcall(f):
	mod = f.__module__
	fname = f.func_name
	file = f.func_code.co_filename
	line = f.func_code.co_firstlineno

	def new_f(*args, **kwargs):
		print "%s  (%s) in %s:%d\n" % (fname, mod, file, line)
		return f(*args, **kwargs)
	return new_f


@logcall
def f(x):
	return x ** 2


@dataflow
def query(q):
	# ...
	# r = db.query(...)
	# ...
	return r

res = query("select ...")


@wait_for("evento")
def query(q):
	# ...
	return r


@checkaccess(nivel)
def operacion():
	# ...
	return r



###########################################################
# with statement

class Protegido (object):
	def __init__(self, val):
		self.x = val
		self.prev = None

	def __enter__(self):
		self.prev = copy.copy(self.x)
		return self.x

	def __exit__(self, type, val, tb):
		if type:
			self.x = self.prev
			raise
		else:
			self.prev = None

o = Protegido([1, 2, 3])
with o as i:
	i.append(4)
	# ...



###########################################################
# Fin!

