zope.generations

Logiciel capture d'écran:
zope.generations
Détails logiciels:
Version: 4.0.0 Alpha 1
Date de transfert: 15 Apr 15
Licence: Gratuit
Popularité: 37

Rating: nan/5 (Total Votes: 0)

zope.generations fournit un moyen de mettre à jour des objets dans la base de données lorsque les changements de schéma d'application. & Nbsp; Un schéma d'application est essentiellement la structure des données, la structure des classes dans le cas de ZODB ou les descriptions de table dans le cas de une base de données relationnelle.
Documentation détaillée
Les générations sont un moyen de mettre à jour des objets dans la base de données lorsque les variations de schéma d'application. Un schéma d'application est essentiellement la structure des données, la structure des classes dans le cas de ZODB ou les descriptions de table dans le cas d'une base de données relationnelle.
Lorsque vous changez les structures de données de votre application, par exemple, vous changez la signification sémantique d'un champ existant dans une classe, vous aurez un problème avec les bases de données qui ont été créés avant votre changement. Pour une discussion plus approfondie et des solutions possibles, voir http://wiki.zope.org/zope3/DatabaseGenerations
Nous allons utiliser l'architecture des composants, et nous aurons besoin d'une base de données et une connexion:
& Nbsp; >>> cgi d'importation
& Nbsp; >>> from pprint importation pprint
& Nbsp; >>> à partir des outils d'importation zope.interface
& Nbsp; >>> from ZODB.tests.util importation DB
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.Open ()
& Nbsp; >>> root = conn.root ()
Imaginez que notre application est un oracle: vous pouvez lui apprendre à réagir à des phrases. Gardons ça simple et stocker les données dans un dict:
& Nbsp; >>> profondes ['réponses'] = {'Bonjour': '? Salut et comment faites-vous',
& Nbsp; ... '? Sens de la vie »:« 42 »,
& Nbsp; ... «quatre & Nbsp; >>> opération d'importation
& Nbsp; >>> transaction.Commit ()
La configuration initiale
Voici un code-spécifiques générations. Nous allons créer et enregistrer un SchemaManager. SchemaManagers sont responsables de la mise à jour de la base de données réelles. Celui-ci sera juste un mannequin. Le point ici est de rendre les générations module conscients que notre application prend en charge les générations.
L'implémentation par défaut de SchemaManager ne est pas adapté pour ce test, car il utilise des modules Python pour gérer générations. Pour l'instant, ce sera très bien, puisque nous ne voulons pas de faire quelque chose tout de suite.
& Nbsp; >>> from zope.generations.interfaces importer ISchemaManager
& Nbsp; >>> from zope.generations.generations importer SchemaManager
& Nbsp; >>> zope.component d'importation
& Nbsp; >>> dummy_manager = SchemaManager (minimum_generation = 0, la génération = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... dummy_manager, ISchemaManager, name = 'some.app')
'Some.app' est un identificateur unique. Vous devez utiliser un URI ou le nom de votre colis en pointillés.
Lorsque vous démarrez Zope et une base de données est ouvert, un IDatabaseOpenedWithRoot d'événement est envoyé. Zope enregistre evolveMinimumSubscriber par défaut comme un gestionnaire pour cet événement. Disons simuler ceci:
& Nbsp; >>> DatabaseOpenedEventStub de classe (objet):
& Nbsp; ... def __init __ (self, base de données):
& Nbsp; ... self.database = base de données
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> from zope.generations.generations importer evolveMinimumSubscriber
& Nbsp; >>> evolveMinimumSubscriber (événement)
La conséquence de cette action est que maintenant la base de données contient le fait que notre numéro de schéma actuel est 0. Lorsque nous mettons à jour le schéma, Zope3 aura une idée de ce que le point de départ était. Ici, vous voyez?
& Nbsp; >>> from zope.generations.generations importer generations_key
& Nbsp; >>> racine [generations_key] ['some.app']
& Nbsp; 0
Dans la vraie vie, vous ne devriez jamais avoir à se embêter avec cette touche directement, mais vous devez être conscient qu'il existe.
Mettre à niveau scénario
Retour à l'histoire. Certains le temps passe et l'un de nos clients est piratée, car nous avons oublié de se échapper les caractères spéciaux HTML! L'horreur! Nous devons résoudre ce problème le plus tôt possible sans perdre de données. Nous décidons d'utiliser des générations d'impressionner nos pairs.
Mettons à jour le gestionnaire de schéma (chute de l'ancien et installer une personnalisée):
& Nbsp; >>> from zope.component GLOBALregistry d'importation
& Nbsp; >>> GSM = globalregistry.getGlobalSiteManager ()
& Nbsp; >>> gsm.unregisterUtility (fourni = ISchemaManager, name = 'some.app')
& Nbsp; Vrai
& Nbsp; >>> MySchemaManager de classe (objet):
& Nbsp; ... instruments (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... la génération = 2
& Nbsp; ...
& Nbsp; ... def évoluer (auto, contexte, génération):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... = réponses profondes [«réponses»]
& Nbsp; ... si la génération == 1:
& Nbsp; ... pour la question, réponse dans answers.items ():
& Nbsp; ... réponses [question] = cgi.escape (réponse)
& Nbsp; ... la génération elif == 2:
& Nbsp; ... pour la question, réponse dans answers.items ():
& Nbsp; ... del réponses [question]
& Nbsp; ... réponses [cgi.escape (question)] = réponse
& Nbsp; ... else:
& Nbsp; ... générer ValueError ("Bummer")
& Nbsp; ... profondes ['réponses'] = réponses # ping persistance
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> gestionnaire = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (gestionnaire, ISchemaManager, name = 'some.app')
Nous avons mis en minimum_generation à 1. Cela signifie que notre demande sera refusera de se exécuter avec une base de plus que la génération 1. L'attribut de génération est fixé à 2, ce qui signifie que la dernière génération que ce SchemaManager sait est d'environ 2.
évoluer () est le cheval de bataille ici. Son travail consiste à obtenir la base de données de génération en génération-1. Il obtient un contexte qui possède l'attribut «connexion», qui est une connexion à la ZODB. Vous pouvez l'utiliser pour modifier les objets comme dans cet exemple.
Dans cette génération de mise en œuvre notamment une échappe les réponses (disons, critiques, parce qu'ils peuvent être saisis par ne importe qui!), La génération 2 échappe aux questions (disons, moins importantes, car elles peuvent être introduites par des personnes autorisées personell seulement).
En fait, vous ne avez pas vraiment besoin d'une mise en œuvre personnalisée de ISchemaManager. Un est disponible, nous avons utilisé pour un mannequin précédemment. Il utilise des modules Python pour l'organisation des fonctions de Evolver. Voir son docstring pour plus d'informations.
Dans la vraie vie, vous aurez beaucoup plus de structures d'objets complexes que celle d'ici. Pour vous faciliter la vie, il ya deux fonctions très utiles disponibles dans zope.generations.utility: findObjectsMatching () et findObjectsProviding (). Ils vont creuser à travers des conteneurs de manière récursive pour vous aider à rechercher des objets anciens que vous souhaitez mettre à jour, par l'interface ou par d'autres critères. Ils sont faciles à comprendre, vérifier leurs docstrings.
Des générations en action
Donc, notre client furieux télécharge notre dernier code et redémarre Zope. L'événement est automatiquement envoyé à nouveau:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (événement)
Shazam! Le client est heureux à nouveau!
& Nbsp; >>> pprint (root ['réponses'])
& Nbsp; {'Bonjour': 'Salut et comment faites-vous? »,
& Nbsp; »Sens de la vie? ':' 42 ',
& Nbsp; »quatre Parce evolveMinimumSubscriber est très paresseux, il ne met à jour la base de données juste assez pour que votre application peut utiliser (à l'minimum_generation, qui est). En effet, le marqueur indique que la génération de base de données a été heurté à 1:
& Nbsp; >>> racine [generations_key] ['some.app']
& Nbsp; 1
Nous voyons que les générations travaillent, donc nous décidons de prendre la prochaine étape et d'évoluer en génération 2. Voyons comment cela peut se faire manuellement:
& Nbsp; >>> from zope.generations.generations importer évoluer
& Nbsp; >>> évoluer (db)
& Nbsp; >>> pprint (root ['réponses'])
& Nbsp; {'Bonjour': 'Salut et comment faites-vous? »,
& Nbsp; »Sens de la vie? ':' 42 ',
& Nbsp; »quatre & Nbsp; >>> racine [generations_key] ['some.app']
& Nbsp; 2
Le comportement par défaut de mises à jour évoluer pour la dernière génération fournis par le SchemaManager. Vous pouvez utiliser l'argument de la façon d'évoluer () quand vous voulez juste pour vérifier si vous avez besoin de mettre à jour ou si vous voulez être paresseux comme l'abonné que nous avons appelé précédemment.
Commande de gestionnaires de schéma
Foire sous-systèmes utilisés pour composer une application compter sur d'autres sous-systèmes pour fonctionner correctement. Si les deux sous-systèmes fournissent aux gestionnaires de schéma, il est souvent utile de connaître l'ordre dans lequel les Evolueurs seront invoqués. Cela permet à un cadre et ce est aux clients d'être en mesure d'évoluer de concert, et les clients peuvent savoir que le cadre sera évolué avant ou après lui-même.
Ceci peut être accompli en contrôlant les noms des services de gestionnaire de schéma. Les gestionnaires de schéma sont exécutés dans l'ordre déterminé par le tri de leurs noms.
& Nbsp; >>> manager1 = SchemaManager (minimum_generation = 0, la génération = 0)
& Nbsp; >>> Manager2 = SchemaManager (minimum_generation = 0, la génération = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager1, ISchemaManager, name = 'another.app')
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... Manager2, ISchemaManager, name = 'another.app-extension')
Remarquez comment le nom du premier paquet est utilisé pour créer un espace de noms pour les packages dépendants. Ce ne est pas une exigence du cadre, mais une configuration pratique pour cet usage.
Faisons évoluer la base de données pour établir ces générations:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (événement)
& Nbsp; >>> racine [generations_key] ['another.app']
& Nbsp; 0
& Nbsp; >>> racine [generations_key] ['another.app-extension']
& Nbsp; 0
Supposons que pour une raison chacun de ces sous-systèmes doit ajouter une génération, et que la génération de 1 'another.app-extension' dépend de la génération 1 de «another.app '. Nous aurons besoin de fournir aux gestionnaires de schéma pour chaque ce dossier qu'ils ont été exécutés afin que nous puissions vérifier le résultat:
& Nbsp; >>> gsm.unregisterUtility (fourni = ISchemaManager, name = 'another.app')
& Nbsp; Vrai
& Nbsp; >>> gsm.unregisterUtility (
& Nbsp; ... à condition = ISchemaManager, name = 'another.app-extension')
& Nbsp; Vrai
& Nbsp; >>> classe FoundationSchemaManager (objet):
& Nbsp; ... instruments (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... la génération = 1
& Nbsp; ...
& Nbsp; ... def évoluer (auto, contexte, génération):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... commande = root.get («commande», [])
& Nbsp; ... si la génération == 1:
& Nbsp; ... ordering.append («fondation 1 ')
& Nbsp; ... «génération de fondation 1 'd'impression
& Nbsp; ... else:
& Nbsp; ... générer ValueError ("Bummer")
& Nbsp; ... racine ['commande'] = # commande ping persistance
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> DependentSchemaManager de classe (objet):
& Nbsp; ... instruments (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... la génération = 1
& Nbsp; ...
& Nbsp; ... def évoluer (auto, contexte, génération):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... commande = root.get («commande», [])
& Nbsp; ... si la génération == 1:
& Nbsp; ... ordering.append («à charge 1 ')
& Nbsp; ... print 'génération dépendante 1'
& Nbsp; ... else:
& Nbsp; ... générer ValueError ("Bummer")
& Nbsp; ... racine ['commande'] = # commande ping persistance
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> manager1 = FoundationSchemaManager ()
& Nbsp; >>> Manager2 = DependentSchemaManager ()
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager1, ISchemaManager, name = 'another.app')
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... Manager2, ISchemaManager, name = 'another.app-extension')
L'évolution de la base de données maintenant sera toujours exécuter le 'another.app' Evolver avant la 'another.app-extension' Evolver:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (événement)
& Nbsp; la génération de fondation 1
& Nbsp; une génération dépendante
& Nbsp; >>> racine ['commande']
& Nbsp; [«fondation 1», «dépend 1 ']
Installation
Dans le l'exemple précédent, nous avons initialisé manuellement les réponses. Nous ne devrions pas avoir à le faire manuellement. L'application devrait être en mesure de le faire automatiquement.
IInstallableSchemaManager étend ISchemaManager, fournissant une méthode d'installation pour effectuer une installation intial d'une application. Ce est une meilleure alternative que d'enregistrer les abonnés de base de données ouvert.
Nous allons définir un nouveau gestionnaire de schéma qui inclut l'installation:
& Nbsp; >>> gsm.unregisterUtility (fourni = ISchemaManager, name = 'some.app')
& Nbsp; Vrai
& Nbsp; >>> from zope.generations.interfaces importer IInstallableSchemaManager
& Nbsp; >>> MySchemaManager de classe (objet):
& Nbsp; ... instruments (IInstallableSchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... la génération = 2
& Nbsp; ...
& Nbsp; ... installer def (auto, contexte):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... racine ['réponses'] = {'Bonjour': '? Salut et comment faites-vous',
& Nbsp; ... '? Sens de la vie »:« 42 »,
& Nbsp; ... «quatre & Nbsp; ... transaction.Commit ()
& Nbsp; ...
& Nbsp; ... def évoluer (auto, contexte, génération):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... = réponses profondes [«réponses»]
& Nbsp; ... si la génération == 1:
& Nbsp; ... pour la question, réponse dans answers.items ():
& Nbsp; ... réponses [question] = cgi.escape (réponse)
& Nbsp; ... la génération elif == 2:
& Nbsp; ... pour la question, réponse dans answers.items ():
& Nbsp; ... del réponses [question]
& Nbsp; ... réponses [cgi.escape (question)] = réponse
& Nbsp; ... else:
& Nbsp; ... générer ValueError ("Bummer")
& Nbsp; ... profondes ['réponses'] = réponses # ping persistance
& Nbsp; ... transaction.Commit ()
& Nbsp; >>> gestionnaire = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (gestionnaire, ISchemaManager, name = 'some.app')
Maintenant, permet d'ouvrir une nouvelle base de données:
& Nbsp; >>> db.close ()
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.Open ()
& Nbsp; >>> «réponses» dans conn.root ()
& Nbsp; False
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (événement)
& Nbsp; >>> conn.sync ()
& Nbsp; >>> root = conn.root ()
& Nbsp; >>> pprint (root ['réponses'])
& Nbsp; {'Bonjour': 'Salut et comment faites-vous? »,
& Nbsp; »Sens de la vie? ':' 42 ',
& Nbsp; »quatre & Nbsp; >>> racine [generations_key] ['some.app']
& Nbsp; 2
Le journal des transactions ZODB note que notre script d'installation a été exécuté
& Nbsp; >>> [. It.description pour elle dans conn.db () storage.iterator ()] [- 2]
& Nbsp; u'some.app: lançant install génération »
(Note mineure: ce ne est pas le dernier enregistrement parce qu'il ya deux commits: MySchemaManager effectue une et evolveMinimumSubscriber effectue le second MySchemaManager n'a pas vraiment besoin de commettre..)

Quoi de neuf dans cette version:.

  • Ajout du support pour Python 3.3
  • Remplacé obsolète l'utilisation de zope.interface.implements avec zope.interface.implementer décorateur équivalent.
  • supprimé le support pour Python 2.4 et 2.5.

Ce qui est nouveau dans la version 3.7.1:

  • Retiré partie détachable qui a été utilisé au cours du développement, mais ne pas compiler sous Windows.
  • son Generation Ajouter une note d'opération.

Exigences :

  • Python

D'autres logiciels de développeur Zope Corporation and Contributors

zope.schema
zope.schema

14 Apr 15

zope.app.rotterdam
zope.app.rotterdam

14 Apr 15

zope.contenttype
zope.contenttype

11 May 15

Commentaires à zope.generations

Commentaires non trouvées
Ajouter un commentaire
Tourner sur les images!