zope.generations

Screenshot der Software:
zope.generations
Softwarebeschreibung:
Version: 4.0.0 Alpha 1
Upload-Datum: 15 Apr 15
Lizenz: Frei
Popularität: 37

Rating: nan/5 (Total Votes: 0)

zope.generations bietet eine Möglichkeit der Aktualisierung Objekten in der Datenbank, wenn die Anwendung von Schemaänderungen & nbsp;. Ein Anwendungsschema ist im wesentlichen die Struktur von Daten, die Struktur von Klassen im Falle ZODB oder die Tabellenbeschreibungen im Fall von eine relationale Datenbank.
Ausführliche Dokumentation
Generationen sind ein Weg für die Aktualisierung Objekten in der Datenbank, wenn die Anwendung Schemaänderungen. Ein Anwendungsschema ist im wesentlichen die Struktur von Daten, die Struktur von Klassen im Falle ZODB oder die Tabellenbeschreibungen im Fall einer relationalen Datenbank.
Wenn Sie Datenstrukturen der Anwendung ändern, zum Beispiel, die semantische Bedeutung eines vorhandenen Feld in einer Klasse ändern Sie, Sie ein Problem mit Datenbanken, die vor Ihrer Änderung erstellt wurden. Für eine gründlichere Diskussion und mögliche Lösungen finden http://wiki.zope.org/zope3/DatabaseGenerations
Wir werden mit den Komponenten-Architektur, und wir werden eine Datenbank und eine Verbindung benötigen:
& Nbsp; >>> import cgi
& Nbsp; >>> von pprint Import pprint
& Nbsp; >>> von zope.interface Importgeräte
& Nbsp; >>> von ZODB.tests.util Import DB
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.open ()
& Nbsp; >>> root = conn.root ()
Stellen Sie sich vor, dass unsere Anwendung ist ein Orakel: Sie können sie zu lehren, um Sätze zu reagieren. Lassen Sie es einfach halten und die Daten in einem dict speichern:
& Nbsp; >>> root ['Antworten'] = {'Hallo': 'Hallo & wie geht es Ihnen ",
& Nbsp; ... '? Sinn des Lebens': '42'
& Nbsp; ... 'vier & Nbsp; >>> import Transaktion
& Nbsp; >>> transaction.commit ()
Initial Setup
Hier einige Generationen spezifischen Code. Wir erstellen und registrieren eine Schemamanager. SchemaManagers sind für die aktuellen Updates der Datenbank verantwortlich. Dieser wird nur ein Dummy. Der Punkt hier ist, damit die Generationen Modul bewusst, dass unsere Anwendung unterstützt Generationen.
Die Standardimplementierung Schemamanager ist nicht geeignet für diesen Test, weil es nutzt Python-Module, um Generationen zu verwalten. Denn jetzt wird es gut sein, weil wir nicht wollen, dass es alles nur noch zu tun.
& Nbsp; >>> von zope.generations.interfaces importieren ISchemaManager
& Nbsp; >>> von zope.generations.generations importieren Schemamanager
& Nbsp; >>> import zope.component
& Nbsp; >>> dummy_manager = Schemamanager (minimum_generation = 0, Generation = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... dummy_manager, ISchemaManager, name = 'some.app')
'Some.app' ist eine eindeutige Kennung. Sie sollten eine URI oder die gepunktete Namen Ihres Paket.
Wenn Sie Zope zu starten und eine Datenbank geöffnet, wird ein Ereignis IDatabaseOpenedWithRoot gesendet. Zope registriert evolveMinimumSubscriber standardmäßig als Handler für dieses Ereignis. Lassen Sie uns dies zu simulieren:
& Nbsp; >>> Klasse DatabaseOpenedEventStub (Objekt):
& Nbsp; ... def init __ (self, Datenbank):
& Nbsp; ... self.database = Datenbank
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> von zope.generations.generations importieren evolveMinimumSubscriber
& Nbsp; >>> evolveMinimumSubscriber (event)
Die Folge dieser Aktion ist, dass jetzt die Datenbank, dass unsere aktuellen Schema Nummer ist 0. Wenn wir das Schema zu aktualisieren, wird Zope3 eine Vorstellung davon, was der Ausgangspunkt war zu haben. Hier finden?
& Nbsp; >>> von zope.generations.generations importieren generations_key
& Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 0
Im wirklichen Leben sollten Sie nie mit dieser Taste direkt die Mühe, aber man sollte wissen, dass es existiert.
Upgrade-Szenario
Zurück zur Geschichte. Einige Zeit vergeht und einen unserer Kunden gehackt wird, weil wir vergessen haben, HTML-Sonderzeichen zu entkommen! Der Horror! Wir müssen dieses Problem so schnell wie möglich ohne Datenverlust zu beheben. Wir entscheiden uns für Generationen verwenden, um unsere Kollegen beeindrucken.
Lassen Sie aktualisieren das Schema-Manager (Fall die alte und eine neue benutzerdefinierte eins):
& Nbsp; >>> von zope.component Importglobalregistry
& Nbsp; >>> gsm = globalregistry.getGlobalSiteManager ()
& Nbsp; >>> gsm.unregisterUtility (vorausgesetzt = ISchemaManager, name = 'some.app')
& Nbsp; Wahr
& Nbsp; >>> Klasse MySchemaManager (Objekt):
& Nbsp; ... Geräte (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... Generation = 2
& Nbsp; ...
& Nbsp; ... def entwickeln (self, Zusammenhang Generation):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... Antworten = root ['Antworten']
& Nbsp; ... wenn Generation == 1:
& Nbsp; ... zur Frage, Antwort in answers.items ():
& Nbsp; ... Antworten [Frage] = cgi.escape (Antwort)
& Nbsp; ... elif Generation == 2:
& Nbsp; ... zur Frage, Antwort in answers.items ():
& Nbsp; ... del Antworten [Frage]
& Nbsp; ... Antworten [cgi.escape (Frage)] = Antwort
& Nbsp; ... else:
& Nbsp; ... zu erhöhen Valueerror ("Schade")
& Nbsp; ... root ['Antworten'] = Antworten # ping Persistenz
& Nbsp; ... transaction.commit ()
& Nbsp; >>> Manager = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (Manager, ISchemaManager, name = 'some.app')
Wir haben minimum_generation auf 1. Das bedeutet, dass unsere Anwendung wird sich weigern, mit einer Datenbank, die älter als Generation 1. Generation Attribut auf 2 gesetzt ist, was bedeutet, dass die neueste Generation, die diese Schemamanager kennt 2 laufen soll.
entwickeln () ist das Arbeitspferd hier. Seine Aufgabe ist es, die Datenbank von Generation zu Generation-1 zu erhalten. Es wird ein Zusammenhang, der das Attribut "Verbindung", die eine Verbindung zum ZODB ist hat. Das können Sie verwenden, um Objekte wie in diesem Beispiel ändern.
In dieser speziellen Implementierung Generation 1 entweicht die Antworten (sagen wir, kritisch, da sie von jedermann eintragen!), Generation 2 entweicht die Fragen (sagen wir, weniger wichtig, da diese von autorisiertem Personal nur eingegeben werden).
In der Tat, müssen Sie nicht wirklich brauchen eine benutzerdefinierte Implementierung ISchemaManager. Einer ist, haben wir es für einen Dummy vorher verwendet haben. Es nutzt Python-Module bei der Organisation des Evolver-Funktionen. Siehe seine Docstring für weitere Informationen.
Im wirklichen Leben haben Sie sehr viel komplexer Objektstrukturen als die hier. Um Ihnen das Leben zu erleichtern, gibt es zwei sehr nützliche Funktionen in zope.generations.utility: findObjectsMatching () und findObjectsProviding (). Sie werden durch Container rekursiv zu graben, um Ihnen helfen, alte Gegenstände zu suchen, die Sie aktualisieren, indem Schnittstelle oder durch andere Kriterien wünschen. Sie sind leicht zu verstehen, überprüfen Sie ihre Docstrings.
Generationen in Aktion
Also, unsere wütende Kunden unsere neuesten Code herunterlädt und startet Zope. Das Ereignis wird automatisch erneut gesendet:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
Shazam! Der Kunde ist wieder glücklich!
& Nbsp; >>> pprint (root ['Antworten'])
& Nbsp; {"Hallo": "Hallo und wie geht es Ihnen?"
& Nbsp; "Sinn des Lebens? ':' 42 '
& Nbsp; "vier Da evolveMinimumSubscriber ist sehr faul, es aktualisiert nur die Datenbank gerade genug, damit Ihre Anwendung können es verwenden (auf die minimum_generation, das ist). Tatsächlich zeigt die Markierung, dass das Datenbankerzeugung auf 1 gestoßen worden:
& Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 1
Wir sehen, dass Generationen arbeiten, so dass wir beschließen, den nächsten Schritt zu tun und sich entwickeln zu Generation 2. Mal sehen, wie dies von Hand durchgeführt werden:
& Nbsp; >>> von zope.generations.generations importieren entwickeln
& Nbsp; >>> entwickeln (db)
& Nbsp; >>> pprint (root ['Antworten'])
& Nbsp; {"Hallo": "Hallo und wie geht es Ihnen?"
& Nbsp; "Sinn des Lebens? ':' 42 '
& Nbsp; "vier & Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 2
Standardverhalten von evolve Upgrades auf die neueste Generation von der Schemamanager vorgesehen. Sie können die, wie Argument zu entwickeln (), wenn Sie nur zu überprüfen, ob Sie aktualisieren müssen oder wenn Sie faul wie die Teilnehmer, die wir zuvor angerufen haben, um sein wollen.
Bestellung von Schema-Manager
Häufig Subsysteme, um eine Anwendung zu komponieren verlassen sich auf andere Teilsysteme einwandfrei. Wenn beide Subsysteme Schema Manager, ist es oft hilfreich, um die Reihenfolge, in der die Evolvers wird aufgerufen, wissen. Dies ermöglicht einen Rahmen und seine Kunden in der Lage, gemeinsam zu entwickeln, und die Kunden können wissen, dass die Rahmen wird vor oder nach selbst entwickelt werden.
Dies kann durch die Kontrolle, die Namen der Schema-Manager-Dienstprogramme ausgeführt werden. Die Schema-Manager sind in der durch die Sortierung ihre Namen festgelegten Reihenfolge ausgeführt werden.
& Nbsp; >>> manager1 = Schemamanager (minimum_generation = 0, Generation = 0)
& Nbsp; >>> Manager2 = Schemamanager (minimum_generation = 0, Generation = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager1, ISchemaManager, name = 'another.app')
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... Manager2, ISchemaManager, name = 'another.app-Erweiterung)
Beachten Sie, wie der Name des ersten Paket wird verwendet, um einen Namespace für abhängige Pakete erstellen. Dies ist keine Anforderung der Rahmen liegen, ein guter Muster für diese Verwendung.
Lassen Sie entwickeln die Datenbank, um diese Generationen zu etablieren:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
& Nbsp; >>> root [generations_key] ['another.app']
& Nbsp; 0
& Nbsp; >>> root [generations_key] ['another.app-Erweiterung']
& Nbsp; 0
Nehmen wir an, dass aus irgendeinem Grund jedes dieser Teilsysteme muss eine Generation hinzufügen und diese Generation 1 von 'another.app-Erweiterung' hängt von Generation 1 von 'another.app'. Wir müssen Schema-Manager für jede dieser Aufzeichnung, die sie schon seit laufen, so dass wir das Ergebnis zu überprüfen bieten:
& Nbsp; >>> gsm.unregisterUtility (vorausgesetzt = ISchemaManager, name = 'another.app')
& Nbsp; Wahr
& Nbsp; >>> gsm.unregisterUtility (
& Nbsp; ... bereitgestellt = ISchemaManager, name = 'another.app-Erweiterung)
& Nbsp; Wahr
& Nbsp; >>> Klasse FoundationSchemaManager (Objekt):
& Nbsp; ... Geräte (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... Generation = 1
& Nbsp; ...
& Nbsp; ... def entwickeln (self, Zusammenhang Generation):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... Bestell = root.get ('Bestellen', [])
& Nbsp; ... wenn Generation == 1:
& Nbsp; ... ordering.append ("Fundament 1 ')
& Nbsp; ... print 'Stiftung Generation 1'
& Nbsp; ... else:
& Nbsp; ... zu erhöhen Valueerror ("Schade")
& Nbsp; ... root ['Bestellung'] = Bestell # ping Persistenz
& Nbsp; ... transaction.commit ()
& Nbsp; >>> Klasse DependentSchemaManager (Objekt):
& Nbsp; ... Geräte (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... Generation = 1
& Nbsp; ...
& Nbsp; ... def entwickeln (self, Zusammenhang Generation):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... Bestell = root.get ('Bestellen', [])
& Nbsp; ... wenn Generation == 1:
& Nbsp; ... ordering.append ('abhängig 1')
& Nbsp; ... print 'abhängig Generation 1'
& Nbsp; ... else:
& Nbsp; ... zu erhöhen Valueerror ("Schade")
& Nbsp; ... root ['Bestellung'] = Bestell # ping Persistenz
& 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-Erweiterung)
Jetzt entwickelt sich die Datenbank wird immer der "another.app 'laufen evolver vor dem' another.app-Erweiterung" Evolver:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
& Nbsp; Grundlage Generation 1
& Nbsp; abhängig Generation 1
& Nbsp; >>> root ['Bestellen']
& Nbsp; ['Fundament 1 "," abhängig 1']
Installation
Im obigen Beispiel haben wir manuell initialisiert die Antworten. Wir sollten nicht zu dies manuell tun. Die Anwendung sollte in der Lage, das automatisch tun.
IInstallableSchemaManager erstreckt ISchemaManager und bietet eine Installation Verfahren zur Durchführung einer anfänglichen Installation einer Anwendung. Dies ist eine bessere Alternative als Datenbank-Registrierung geöffnet Abonnenten.
Wir definieren ein neues Schema-Manager, der Installation umfasst:
& Nbsp; >>> gsm.unregisterUtility (vorausgesetzt = ISchemaManager, name = 'some.app')
& Nbsp; Wahr
& Nbsp; >>> von zope.generations.interfaces importieren IInstallableSchemaManager
& Nbsp; >>> Klasse MySchemaManager (Objekt):
& Nbsp; ... Geräte (IInstallableSchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... Generation = 2
& Nbsp; ...
& Nbsp; ... def installieren (self, Kontext):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... root ['Antworten'] = {'Hallo': 'Hallo & wie geht es Ihnen ",
& Nbsp; ... '? Sinn des Lebens': '42'
& Nbsp; ... 'vier & Nbsp; ... transaction.commit ()
& Nbsp; ...
& Nbsp; ... def entwickeln (self, Zusammenhang Generation):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... Antworten = root ['Antworten']
& Nbsp; ... wenn Generation == 1:
& Nbsp; ... zur Frage, Antwort in answers.items ():
& Nbsp; ... Antworten [Frage] = cgi.escape (Antwort)
& Nbsp; ... elif Generation == 2:
& Nbsp; ... zur Frage, Antwort in answers.items ():
& Nbsp; ... del Antworten [Frage]
& Nbsp; ... Antworten [cgi.escape (Frage)] = Antwort
& Nbsp; ... else:
& Nbsp; ... zu erhöhen Valueerror ("Schade")
& Nbsp; ... root ['Antworten'] = Antworten # ping Persistenz
& Nbsp; ... transaction.commit ()
& Nbsp; >>> Manager = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (Manager, ISchemaManager, name = 'some.app')
Nun können öffnen Sie eine neue Datenbank:
& Nbsp; >>> db.close ()
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.open ()
& Nbsp; >>> "Antworten" in conn.root ()
& Nbsp; Falsch
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
& Nbsp; >>> conn.sync ()
& Nbsp; >>> root = conn.root ()
& Nbsp; >>> pprint (root ['Antworten'])
& Nbsp; {"Hallo": "Hallo und wie geht es Ihnen?"
& Nbsp; "Sinn des Lebens? ':' 42 '
& Nbsp; "vier & Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 2
Die ZODB Transaktionsprotokoll stellt fest, dass unsere Installationsskript ausgeführt wurde
& Nbsp; >>> [. It.description dafür in conn.db () storage.iterator ()] [- 2]
& Nbsp; u'some.app: Laufen installieren Generation "
(Minor Hinweis: es ist nicht die letzte Platte, weil es zwei Commits: MySchemaManager führt eine, und evolveMinimumSubscriber führt die zweite MySchemaManager nicht wirklich brauchen, um zu begehen..)

Was ist neu , in dieser Pressemitteilung:.

  • Unterstützung für Python 3.3
  • Ersetzte veraltet zope.interface.implements Nutzung mit gleichwertigen zope.interface.implementer Dekorateur.
  • Dropped Unterstützung für Python 2.4 und 2.5.

Was ist neu in Version 3.7.1:

  • Entfernt Ausbau-Teil, der während der Entwicklung verwendet wurde, sondern tut nicht unter Windows kompilieren.
  • Generation Skripte hinzufügen, eine Transaktion zur Kenntnis.

Anforderungen :

  • Python

Andere Software von Entwickler Zope Corporation and Contributors

cipher.background
cipher.background

20 Feb 15

zope.app.container
zope.app.container

14 Apr 15

zope.app.locales
zope.app.locales

14 Apr 15

zope.html
zope.html

14 Apr 15

Kommentare zu zope.generations

Kommentare nicht gefunden
Kommentar hinzufügen
Schalten Sie auf die Bilder!