zope.generations

Software captura de pantalla:
zope.generations
Detalles de software:
Versión: 4.0.0 Alpha 1
Fecha de carga: 15 Apr 15
Licencia: Libre
Popularidad: 37

Rating: nan/5 (Total Votes: 0)

zope.generations proporciona una forma de actualizar los objetos de la base de datos cuando los cambios en el esquema de aplicación & nbsp;. Un esquema de aplicación es esencialmente la estructura de los datos, la estructura de clases en el caso de ZODB o las descripciones de la tabla en el caso de una base de datos relacional.
Documentación detallada
Generaciones son una forma de actualizar objetos en la base de datos cuando cambia el esquema de aplicación. Un esquema de aplicación es esencialmente la estructura de los datos, la estructura de clases en el caso de ZODB o las descripciones de la tabla en el caso de una base de datos relacional.
Al cambiar las estructuras de datos de su aplicación, por ejemplo, cambia el significado semántico de un campo existente en una clase, tendrá un problema con las bases de datos que se crearon antes de su cambio. Para una discusión más a fondo y sus posibles soluciones, consulte http://wiki.zope.org/zope3/DatabaseGenerations
Vamos a utilizar la arquitectura de componentes, y vamos a necesitar una base de datos y una conexión:
& Nbsp; >>> import cgi
& Nbsp; >>> from pprint pprint importación
& Nbsp; >>> de implementos de importación zope.interface
& Nbsp; >>> from ZODB.tests.util importación DB
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.Open ()
& Nbsp; >>> root = conn.root ()
Imaginemos que nuestra aplicación es un oráculo: usted puede enseñar a reaccionar a las frases. Vamos a mantenerlo simple y almacenar los datos en un diccionario:
& Nbsp; >>> raíz ['respuestas'] = {'Hola': "¿Hola y ¿cómo se hace",
& Nbsp; ... '? Significado de la vida ":" 42 ",
& Nbsp; ... 'cuatro & Nbsp; >>> transacción de importación
& Nbsp; >>> transaction.Commit ()
Configuración inicial
Aquí hay un código generaciones específicas. Vamos a crear y registrar una SchemaManager. SchemaManagers son responsables de los cambios reales de la base de datos. Éste será sólo un maniquí. El punto aquí es hacer que las generaciones módulo conscientes de que nuestra aplicación es compatible con las generaciones.
La implementación por defecto de SchemaManager no es adecuado para esta prueba, ya que utiliza módulos de Python para gestionar generaciones. Por ahora, será más que suficiente, ya que no queremos que haga nada por el momento.
& Nbsp; >>> from zope.generations.interfaces importan ISchemaManager
& Nbsp; >>> from zope.generations.generations importan SchemaManager
& Nbsp; >>> zope.component importación
& Nbsp; >>> dummy_manager = SchemaManager (minimum_generation = 0, generación = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... dummy_manager, ISchemaManager, name = 'some.app')
'Some.app' es un identificador único. Usted debe usar un URI o el nombre de puntos de su paquete.
Al iniciar Zope y se abre una base de datos, se envía un IDatabaseOpenedWithRoot evento. Zope registra evolveMinimumSubscriber por defecto como un controlador de este evento. Vamos a simular esto:
& Nbsp; >>> DatabaseOpenedEventStub clase (objeto):
& Nbsp; ... def __init __ (self, base de datos):
& Nbsp; ... self.database = base de datos
& Nbsp; >>> evento = DatabaseOpenedEventStub (db)
& Nbsp; >>> from zope.generations.generations importan evolveMinimumSubscriber
& Nbsp; >>> evolveMinimumSubscriber (evento)
La consecuencia de esta acción es que ahora la base de datos contiene el hecho de que nuestro número de esquema actual es 0. Cuando nos ponemos al día el esquema, Zope3 tendrá una idea de lo que fue el punto de partida. Aquí, ¿ves?
& Nbsp; >>> from zope.generations.generations importan generations_key
& Nbsp; >>> raíz [generations_key] ['some.app']
& Nbsp; 0
En la vida real nunca debería tener que molestarse con esta clave directamente, pero usted debe ser consciente de que existe.
Actualizar escenario
Volviendo a la historia. Algún tiempo pasa y uno de nuestros clientes es hackeado porque nos olvidamos de escapar caracteres especiales HTML! El horror! Debemos solucionar este problema lo antes posible y sin perder ningún dato. Nos decidimos utilizar generaciones impresionar a nuestros compañeros.
Vamos a actualizar el gestor de esquema (deje caer el viejo e instalar una nueva costumbre uno):
& Nbsp; >>> from GLOBALregistry importación zope.component
& Nbsp; >>> gsm = globalregistry.getGlobalSiteManager ()
& Nbsp; >>> gsm.unregisterUtility (siempre = ISchemaManager, name = 'some.app')
& Nbsp; El verdadero
& Nbsp; >>> MySchemaManager clase (objeto):
& Nbsp; ... implementos (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generación = 2
& Nbsp; ...
& Nbsp; ... def evolucionar (sí, el contexto, la generación):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... respuestas = raíz ['respuestas']
& Nbsp; ... si == generación 1:
& Nbsp; ... para la pregunta, respuesta en answers.items ():
& Nbsp; ... respuestas [pregunta] = cgi.escape (respuesta)
& Nbsp; ... generación elif == 2:
& Nbsp; ... para la pregunta, respuesta en answers.items ():
& Nbsp; ... Del respuestas [pregunta]
& Nbsp; ... respuestas [cgi.escape (pregunta)] = respuesta
& Nbsp; ... else:
& Nbsp; ... elevar ValueError ("Charlatán")
& Nbsp; ... raíz ['respuestas'] = respuestas # ping persistencia
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> gerente = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (gerente, ISchemaManager, name = 'some.app')
Hemos establecido minimum_generation a 1. Esto significa que nuestra aplicación se negará a ejecutar con una base de datos mayor que la generación 1. El atributo generación se establece en 2, lo que significa que la última generación que esta SchemaManager conoce es 2.
evolucionar () es el caballo de batalla aquí. Su trabajo es conseguir que la base de datos de generación-1 en generación. Se pone un contexto que tiene la "conexión" atributo, que es una conexión con el ZODB. Puede usarlo para cambiar los objetos como en este ejemplo.
En esta generación implementación particular 1 escapa las respuestas (digamos, críticos, ya que se pueden introducir por cualquier persona!), La generación de 2 escapa a las preguntas (digamos, menos importantes, ya que pueden ser introducidos por personal autorizado personell solamente).
De hecho, usted realmente no necesita una implementación personalizada de ISchemaManager. Uno es disponible, lo hemos utilizado para un maniquí con anterioridad. Utiliza módulos de Python para la organización de las funciones de Evolver. Ver su cadena de documentación para obtener más información.
En la vida real que tendrá estructuras de objetos mucho más complejo que el de aquí. Para hacer la vida más fácil, hay dos funciones muy útiles disponibles en zope.generations.utility: findObjectsMatching () y findObjectsProviding (). Ellos cavar a través de contenedores de forma recursiva para ayudar a usted busca objetos antiguos que desea actualizar, por interfaz o por otros criterios. Son fáciles de entender, comprobar sus cadenas de documentación.
Generaciones en acción
Así, nuestro cliente furioso descarga nuestro último código y reinicia Zope. El evento se envía automáticamente una vez más:
& Nbsp; >>> evento = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (evento)
Shazam! El cliente es feliz otra vez!
& Nbsp; >>> pprint (root ['respuestas'])
& Nbsp; {'Hola': 'Hola y ¿cómo lo haces?',
& Nbsp; "sentido de la vida?": "42",
& Nbsp; "cuatro Debido evolveMinimumSubscriber es muy vago, que sólo actualiza la base de datos lo suficiente para que la aplicación pueda usarlo (a la minimum_generation, se entiende). De hecho, el marcador indica que la generación de base de datos ha sido golpeado a 1:
& Nbsp; >>> raíz [generations_key] ['some.app']
& Nbsp; 1
Vemos que las generaciones están trabajando, así que nos decidimos a dar el siguiente paso y evolucionar en generación 2. Vamos a ver cómo esto se puede hacer de forma manual:
& Nbsp; >>> from zope.generations.generations importan evolucionar
& Nbsp; >>> evolucionar (db)
& Nbsp; >>> pprint (root ['respuestas'])
& Nbsp; {'Hola': 'Hola y ¿cómo lo haces?',
& Nbsp; "sentido de la vida?": "42",
& Nbsp; "cuatro & Nbsp; >>> raíz [generations_key] ['some.app']
& Nbsp; 2
El comportamiento por defecto de las actualizaciones de evolucionar para la última generación proporcionada por el SchemaManager. Usted puede utilizar el argumento de la forma de evolucionar () cuando se quiere sólo para comprobar si necesita actualizar o si quieres ser perezoso como el abonado al que hemos denominado anteriormente.
Ordenamiento de los administradores de esquema
Frecuentes subsistemas utilizados para componer una aplicación depender de otros subsistemas para operar correctamente. Si ambos subsistemas proporcionan a los administradores de esquema, a menudo es útil saber el orden en que se invocarán los Evolvers. Esto permite un marco y es que los clientes puedan evolucionar en concierto, y los clientes pueden saber que el marco se desarrolló antes o después de la misma.
Esto se puede lograr mediante el control de los nombres de las utilidades Administrador de esquema. Los administradores de esquema se ejecutan en el orden determinado por la clasificación de sus nombres.
& Nbsp; >>> manager1 = SchemaManager (minimum_generation = 0, generación = 0)
& Nbsp; >>> Manager 2 = SchemaManager (minimum_generation = 0, generación = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager1, ISchemaManager, name = 'another.app')
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... Manager 2, ISchemaManager, name = 'another.app-extensión')
Observe cómo se utiliza el nombre del primer paquete para crear un espacio de nombres de paquetes dependientes. Esto no es un requisito del marco, sino un patrón conveniente para este uso.
Vamos a evolucionar la base de datos para establecer estas generaciones:
& Nbsp; >>> evento = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (evento)
& Nbsp; >>> raíz [generations_key] ['another.app']
& Nbsp; 0
& Nbsp; >>> raíz [generations_key] ['another.app-extension']
& Nbsp; 0
Supongamos que por alguna razón cada uno de estos subsistemas hay que añadir una generación, y que la generación 1 de 'another.app-extensión' depende de la generación 1 de 'another.app'. Vamos a tener que proporcionar a los administradores de esquema para cada uno ese registro que han sido corren para que podamos verificar el resultado:
& Nbsp; >>> gsm.unregisterUtility (siempre = ISchemaManager, name = 'another.app')
& Nbsp; El verdadero
& Nbsp; >>> gsm.unregisterUtility (
& Nbsp; ... siempre = ISchemaManager, name = 'another.app-extensión')
& Nbsp; El verdadero
& Nbsp; >>> clase FoundationSchemaManager (objeto):
& Nbsp; ... implementos (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generación = 1
& Nbsp; ...
& Nbsp; ... def evolucionar (sí, el contexto, la generación):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... pedido = root.get ('pedido', [])
& Nbsp; ... si == generación 1:
& Nbsp; ... ordering.append ('base 1')
& Nbsp; ... "generación de base 1 'print
& Nbsp; ... else:
& Nbsp; ... elevar ValueError ("Charlatán")
& Nbsp; ... raíz ['pedido'] = pedido # ping persistencia
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> DependentSchemaManager clase (objeto):
& Nbsp; ... implementos (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generación = 1
& Nbsp; ...
& Nbsp; ... def evolucionar (sí, el contexto, la generación):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... pedido = root.get ('pedido', [])
& Nbsp; ... si == generación 1:
& Nbsp; ... ordering.append ('dependiente 1')
& Nbsp; ... print 'generación dependiente 1'
& Nbsp; ... else:
& Nbsp; ... elevar ValueError ("Charlatán")
& Nbsp; ... raíz ['pedido'] = pedido # ping persistencia
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> manager1 = FoundationSchemaManager ()
& Nbsp; >>> Manager 2 = DependentSchemaManager ()
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager1, ISchemaManager, name = 'another.app')
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... Manager 2, ISchemaManager, name = 'another.app-extensión')
La evolución de la base de datos ahora siempre ejecutar el 'another.app' evolver antes de la 'another.app-extensión' Evolver:
& Nbsp; >>> evento = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (evento)
& Nbsp; la generación de fundación 1
& Nbsp; la generación dependiente 1
& Nbsp; >>> raíz ['pedido']
& Nbsp; ['base 1', 'dependiente 1']
Instalación
En el ejemplo anterior, hemos inicializado manualmente las respuestas. No deberíamos tener que hacerlo manualmente. La aplicación debe ser capaz de hacer eso automáticamente.
IInstallableSchemaManager extiende ISchemaManager, proporcionando un método de instalación para realizar una instalación intial de una aplicación. Esta es una mejor alternativa que registrarse suscriptores abierta de bases de datos.
Vamos a definir un nuevo administrador de esquema que incluye la instalación:
& Nbsp; >>> gsm.unregisterUtility (siempre = ISchemaManager, name = 'some.app')
& Nbsp; El verdadero
& Nbsp; >>> from zope.generations.interfaces importan IInstallableSchemaManager
& Nbsp; >>> MySchemaManager clase (objeto):
& Nbsp; ... implementos (IInstallableSchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generación = 2
& Nbsp; ...
& Nbsp; ... def instalar (self, contexto):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... raíz ['respuestas'] = {'Hola': "¿Hola y ¿cómo se hace",
& Nbsp; ... '? Significado de la vida ":" 42 ",
& Nbsp; ... 'cuatro & Nbsp; ... transaction.Commit ()
& Nbsp; ...
& Nbsp; ... def evolucionar (sí, el contexto, la generación):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... respuestas = raíz ['respuestas']
& Nbsp; ... si == generación 1:
& Nbsp; ... para la pregunta, respuesta en answers.items ():
& Nbsp; ... respuestas [pregunta] = cgi.escape (respuesta)
& Nbsp; ... generación elif == 2:
& Nbsp; ... para la pregunta, respuesta en answers.items ():
& Nbsp; ... Del respuestas [pregunta]
& Nbsp; ... respuestas [cgi.escape (pregunta)] = respuesta
& Nbsp; ... else:
& Nbsp; ... elevar ValueError ("Charlatán")
& Nbsp; ... raíz ['respuestas'] = respuestas # ping persistencia
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> gerente = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (gerente, ISchemaManager, name = 'some.app')
Ahora, vamos a abrir una nueva base de datos:
& Nbsp; >>> db.close ()
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.Open ()
& Nbsp; 'respuestas' >>> en conn.root ()
& Nbsp; Falso
& Nbsp; >>> evento = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (evento)
& Nbsp; >>> conn.sync ()
& Nbsp; >>> root = conn.root ()
& Nbsp; >>> pprint (root ['respuestas'])
& Nbsp; {'Hola': 'Hola y ¿cómo lo haces?',
& Nbsp; "sentido de la vida?": "42",
& Nbsp; "cuatro & Nbsp; >>> raíz [generations_key] ['some.app']
& Nbsp; 2
El registro de transacciones ZODB señala que nuestro script de instalación se ejecutó
& Nbsp; >>> [. It.description para ella en conn.db () storage.iterator ()] [- 2]
& Nbsp; u'some.app: correr instalar generación '
(Nota menor: no es el último registro porque hay dos confirmaciones: MySchemaManager realiza uno, y evolveMinimumSubscriber realiza la segunda MySchemaManager no necesita realmente a cometer.).

¿Qué hay de nuevo en esta versión:.

  • Se ha añadido soporte para Python 3.3
  • Sustituido obsoleto uso zope.interface.implements con decorador zope.interface.implementer equivalente.
  • abandonado el soporte para Python 2.4 y 2.5.

¿Qué hay de nuevo en la versión 3.7.1:

  • parte buildout Eliminado que fue utilizado durante el desarrollo, pero hace no compilar en Windows.
  • guiones Generación poner una nota transacción.

Requisitos :

  • Python

Otro software de desarrollador Zope Corporation and Contributors

zope.app.zapi
zope.app.zapi

12 May 15

zope.file
zope.file

14 Apr 15

zope.app.testing
zope.app.testing

14 Apr 15

zope.dublincore
zope.dublincore

12 May 15

Comentarios a la zope.generations

Comentarios que no se encuentran
Añadir comentario
A su vez en las imágenes!