Modificación de pyContainer

Pablo Rey Sobral pabloreysobral en gmail.com
Sab Dic 18 02:22:33 CET 2004


Hola,

He estado dando vueltas con pyContainer y me parece muy interesante,
pero me he encontrado con una limitación que me parece salvable y me
gustaría que me dierais vuestra opinión sobre la solución y los
posibles efectos colaterales.

Estoy rehaciendo una aplicación que ya tenía en VB6. En VB6 tenía una
serie de variables globales(del tipo subcuentas, productos, etc...)
que se cargaban mediante otra variable global de conexión con la base
de datos. No quería adoptar esa chapuza en Python

Cuando he ido a implementarlo en pyContainer hago algo así, no puedo
cargar los datos en el __init__ de la clase debido a que a esas
alturas pyContainer no ha "inyectado" las dependencias
correspondientes.

Por otra parte, con la factoría estandar de pyContainer no puedo pasar
argumentos al init, y aunque se los pase, no me sirven de nada debido
a que no puedo acceder a la base de datos.

He pensado en la siguiente solución:

Crear la siguiente factoría:

class ArgsFactory (Factory):
	def getInstance (self, classpath, *args, **kwargs):
		return utils.getClass(classpath)()

Y modificar pyContainer de la siguiente forma:

	def getInstance (self, id_, *args, **kwargs):
		'''
		Returns an instance of a component. This method performs
		lazy instantiation - only components required for this component to
		be initialized properly are instantinated.
		@type id_: String
		@param id_: same thing as the 'id' attribute in the XML config file.
		@rtype: user-specified
		@return: an object of a class specified in config
		'''
		if self.classes.has_key(id_):
			if self.descriptions[id_].type_ == _Component.PROTOTYPE:
				if not self.instances.has_key(id_):
					self.instances[id_] = _Instance()
				instance = self.factories[self.descriptions[id_].factoryId].getInstance(self.classes[id_],
*args, **kwargs)
				if self.descriptions[id_].interceptors:
					instance = _Invocation(self, id_, instance)  # Wrap the instance
				self.instances[id_].private.append(instance)
				self.__updateInstanceProperties(id_)
				if hasattr(instance, '__init2__'): # SEGUNDO INIT PARA TENER LAS
DEPENDENCIAS CARGADAS
				      instance.__init2__ (args, kwargs) 
				return instance
			else:
				if not self.instances.has_key(id_):
					self.instances[id_] = _Instance()
					instance =
self.factories[self.descriptions[id_].factoryId].getInstance(self.classes[id_],
*args, **kwargs) # !!!
					if self.descriptions[id_].interceptors:
						instance = _Invocation(self, id_, instance)  # Wrap the instance
					self.instances[id_].singleton = instance
					self.__updateInstanceProperties(id_)
					if hasattr(instance, '__init2__'):  # SEGUNDO INIT PARA TENER LAS
DEPENDENCIAS CARGADAS
						instance.__init2__ (args, kwargs) 
					return instance
				else:
					return self.instances[id_].singleton
		elif self.parent:
		     return self.parent.getInstance(id_, *args, **kwargs)
		else:
			return None  # raise an exception?


Es decir al instanciar el componente por primera vez llamar a
__init2__ pasándole los argumentos correspondientes para que pueda
usar las dependencias inyectadas. Sería util en los casos que he
comentado como un componente que tiene que acceder a otro componente
al iniciarse y en el caso de que queramos pasarle argumentos al init,
por ejemplo:

Para tener una venta en blanco :   x = pycontainer.getInstance("venta")
Para tener una venta desde la base de datos:   x =
pycontainer.getInstance("venta", id="VENTA5889587")

¿Qué os parece la solución? ¿Habeis tenido algún problema similar?
¿Cómo lo habeis solucionado?

Un saludo.




Más información sobre la lista de distribución Python-es