zope.generations

Software skärmdump:
zope.generations
Mjukvaruinformation:
Version: 4.0.0 Alpha 1
Ladda upp dagen: 15 Apr 15
Licens: Gratis
Popularitet: 2

Rating: nan/5 (Total Votes: 0)

zope.generations ger ett sätt att uppdatera objekt i databasen när ändringar applikationsschemat. & Nbsp; En ansökan schema är i huvudsak strukturen av data, struktur klasser i fallet ZODB eller tabellbeskrivningar i fråga om en relationsdatabas.
Detaljerad dokumentation
Generationer är en metod för att uppdatera objekt i databasen vid ändringar applikationsschemat. En ansökan schema är i huvudsak strukturen av data, struktur klasser i fallet ZODB eller tabellbeskrivningar i fallet med en relationsdatabas.
När du ändrar din ansökan datastrukturer, till exempel, du ändra semantiska innebörden av en befintlig fält i en klass, har du ett problem med databaser som skapats före ändringen. För en mer grundlig diskussion och möjliga lösningar, se http://wiki.zope.org/zope3/DatabaseGenerations
Vi kommer att använda komponentarkitektur, och vi kommer att behöva en databas och en anslutning:
& Nbsp; >>> import cgi
& Nbsp; >>> från pprint import pprint
& Nbsp; >>> från zope.interface import redskap
& Nbsp; >>> från ZODB.tests.util import DB
& Nbsp; >>> db = DB ()
& Nbsp; >>> uppk = db.open ()
& Nbsp; >>> root = conn.root ()
Tänk dig att vår ansökan är ett orakel: kan du lära den att reagera på fraser. Låt oss hålla det enkelt och lagra data i en dict:
& Nbsp; >>> root [svar '] = {' Hej ':'? Hi & hur gör man ",
& Nbsp; ... "? Meningen med livet": "42",
& Nbsp; ... "fyra & Nbsp; >>> importtransaktion
& Nbsp; >>> transaction.commit ()
Inledande installation
Här är några generationer specifik kod. Vi kommer att skapa och registrera ett SchemaManager. SchemaManagers är ansvariga för de verkliga uppdateringar av databasen. Den här kommer att bli bara en dummy. Poängen här är att göra generationerna modul medvetna om att vår ansökan stöder generationer.
Standard genomföra SchemaManager är inte lämplig för detta test, eftersom den använder Python moduler för att hantera generationer. För nu blir det bara bra, eftersom vi inte vill att det ska göra något ännu.
& Nbsp; >>> från zope.generations.interfaces importera ISchemaManager
& Nbsp; >>> från zope.generations.generations importera 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" är en unik identifierare. Du bör använda en URI eller den streckade namn ditt paket.
När du startar Zope och en databas öppnas, en händelse IDatabaseOpenedWithRoot skickats. Zope registrerar evolveMinimumSubscriber som standard som en hanterare för den här händelsen. Låt oss simulera detta:
& Nbsp; >>> klass DatabaseOpenedEventStub (objekt):
& Nbsp; ... def __init __ (self, databas):
& Nbsp; ... self.database = databas
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> från zope.generations.generations importera evolveMinimumSubscriber
& Nbsp; >>> evolveMinimumSubscriber (event)
Konsekvensen av denna åtgärd är att nu databasen innehåller det faktum att vår nuvarande schema numret är 0. När vi uppdaterar schemat, kommer Zope3 ha en uppfattning om vad utgångspunkten var. Här ser?
& Nbsp; >>> från zope.generations.generations importera generations_key
& Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 0
I verkliga livet bör du aldrig behöva bry sig om denna nyckel direkt, men du bör vara medveten om att den existerar.
Uppgradera scenario
Tillbaka till historien. Någon tiden går och en av våra kunder blir hackat eftersom vi glömde att fly HTML specialtecken! Den fasa! Vi måste åtgärda problemet ASAP utan att förlora några data. Vi väljer att använda generationer att imponera våra kamrater.
Låt oss uppdatera schemat manager (släppa det gamla och installera en ny anpassad en):
& Nbsp; >>> från zope.component import globalregistry
& Nbsp; >>> gsm = globalregistry.getGlobalSiteManager ()
& Nbsp; >>> gsm.unregisterUtility (förutsatt = ISchemaManager, name = 'some.app')
& Nbsp; Sann
& Nbsp; >>> klass MySchemaManager (objekt):
& Nbsp; ... redskap (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generation = 2
& Nbsp; ...
& Nbsp; ... def utvecklas (själv, sammanhang generationen):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... Svar = root [svar ']
& Nbsp; ... om generation == 1:
& Nbsp; ... för fråga, svara i answers.items ():
& Nbsp; ... svar [fråga] = cgi.escape (svar)
& Nbsp; ... Elif generationen == 2:
& Nbsp; ... för fråga, svara i answers.items ():
& Nbsp; ... del svar [fråga]
& Nbsp; ... svar [cgi.escape (fråga)] = svar
& Nbsp; ... annars:
& Nbsp; ... höja ValueError ("Bummer")
& Nbsp; ... root [svar '] = svar # ping uthållighet
& Nbsp; ... transaction.commit ()
& Nbsp; >>> manager = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (manager, ISchemaManager, name = 'some.app')
Vi har satt minimum_generation till 1. Det innebär att vår ansökan kommer att vägra att köra med en databas som är äldre än generation 1. generation attributet är satt till 2, vilket innebär att den senaste generationen att denna SchemaManager vet om är 2.
utvecklas () är arbetshästen här. Dess uppgift är att få databasen från generation-1 till generation. Det blir ett sammanhang som har attributet "anslutning", som är en anslutning till ZODB. Du kan använda det för att byta föremål som i det här exemplet.
I just det här generationen implementering 1 flyr svaren (säg, kritiska, eftersom de kan anges av vem som helst!), Generation 2 flyr frågorna (säg, mindre viktiga, eftersom dessa kan skrivas in av auktoriserad Personal enbart).
I själva verket behöver du inte verkligen behöver en anpassad tillämpning av ISchemaManager. En är tillgänglig, vi har använt den för en dummy tidigare. Den använder Python-moduler för organisering av Evolver funktioner. Se dess docstring för mer information.
I verkliga livet kommer du att ha mycket mer komplexa objektstrukturer än den här. För att göra ditt liv enklare, det finns två mycket användbara funktioner som finns i zope.generations.utility: findObjectsMatching () och findObjectsProviding (). De kommer att gräva igenom containrar rekursivt för att hjälpa dig söka upp gamla föremål som du vill uppdatera, genom gränssnittet eller av några andra kriterier. De är lätta att förstå, kontrollera sina docstrings.
Generationer i aktion
Så hämtar vår rasande klient vårt senaste koden och startar Zope. Händelsen skickas automatiskt igen:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
Shazam! Beställare är glad igen!
& Nbsp; >>> pprint (root [svar '])
& Nbsp; {'Hej': 'Hej & hur gör man? ",
& Nbsp; "meningen med livet?": "42",
& Nbsp; 'fyra Eftersom evolveMinimumSubscriber är väldigt lat, bara det uppdaterar databasen bara tillräckligt så att din ansökan kan använda den (till minimum_generation, alltså). Faktum indikerar markör som databas generation har varit stötte till 1:
& Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 1
Vi ser att generationer arbetar, så vi beslutar att ta nästa steg och utvecklas till generation 2. Låt oss se hur detta kan göras manuellt:
& Nbsp; >>> från zope.generations.generations importera utvecklas
& Nbsp; >>> utvecklas (db)
& Nbsp; >>> pprint (root [svar '])
& Nbsp; {'Hej': 'Hej & hur gör man? ",
& Nbsp; "meningen med livet?": "42",
& Nbsp; 'fyra & Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 2
Standard beteende Evolve uppgraderingar till den senaste generationen som tillhandahålls av SchemaManager. Du kan använda hur argumentet att utvecklas () när du vill bara kolla om du behöver uppdatera eller om du vill vara lata som abonnenten som vi har kallat tidigare.
Beställning av schema chefer
Ofta delsystem används för att komponera ett program förlita sig på andra delsystem för att fungera korrekt. Om båda delsystemen ger schema chefer, är det ofta bra att veta i vilken ordning de evolvers kommer att åberopas. Detta gör att en ram och det är kunderna att kunna utvecklas i samförstånd, och klienterna kan veta att ramverket ska utvecklas före eller efter själva.
Detta kan åstadkommas genom att styra namnen på de schema manager verktyg. De schema chefer drivs i ordning bestäms genom sortering deras namn.
& 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-förlängning ")
Lägg märke till hur namnet av det första paketet används för att skapa ett namnområde för beroende paket. Detta är inte ett krav av ramverket, men en bekväm mönster för denna användning.
Låt oss utvecklas databasen för att fastställa dessa generationer:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
& Nbsp; >>> root [generations_key] ['another.app']
& Nbsp; 0
& Nbsp; >>> root [generations_key] ['another.app-förlängning "]
& Nbsp; 0
Låt oss anta att av någon anledning varje sådant delsystem måste lägga till en generation, och den generationen 1 av "another.app-förlängning" beror på generation 1 av "another.app". Vi måste ge schemaansvariga för varje som spelar in att de har körts så att vi kan verifiera resultatet:
& Nbsp; >>> gsm.unregisterUtility (förutsatt = ISchemaManager, name = 'another.app')
& Nbsp; Sann
& Nbsp; >>> gsm.unregisterUtility (
& Nbsp; ... förutsatt = ISchemaManager, name = 'another.app-förlängning ")
& Nbsp; Sann
& Nbsp; >>> klass FoundationSchemaManager (objekt):
& Nbsp; ... redskap (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generation = 1
& Nbsp; ...
& Nbsp; ... def utvecklas (själv, sammanhang generationen):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... beställning = root.get ('beställning', [])
& Nbsp; ... om generation == 1:
& Nbsp; ... ordering.append ('stiftelse 1')
& Nbsp; ... print "foundation generation 1 '
& Nbsp; ... annars:
& Nbsp; ... höja ValueError ("Bummer")
& Nbsp; ... root ['beställning'] = beställnings # ping uthållighet
& Nbsp; ... transaction.commit ()
& Nbsp; >>> klass DependentSchemaManager (objekt):
& Nbsp; ... redskap (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generation = 1
& Nbsp; ...
& Nbsp; ... def utvecklas (själv, sammanhang generationen):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... beställning = root.get ('beställning', [])
& Nbsp; ... om generation == 1:
& Nbsp; ... ordering.append ("beroende 1 ')
& Nbsp; ... print "beroende generation 1 '
& Nbsp; ... annars:
& Nbsp; ... höja ValueError ("Bummer")
& Nbsp; ... root ['beställning'] = beställnings # ping uthållighet
& 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-förlängning ")
Utvecklas databasen nu kommer alltid köra "another.app" evolver innan "another.app-förlängning" evolver:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
& Nbsp; foundation generation 1
& Nbsp; beroende generation 1
& Nbsp; >>> rot ['beställning']
& Nbsp; ['fundament 1', 'beroende 1']
Installation
I exemplet ovan, initieras vi manuellt svaren. Vi ska inte behöva göra det manuellt. Ansökan ska kunna göra det automatiskt.
IInstallableSchemaManager utökar ISchemaManager, ger en installationsmetod för att utföra en intial installation av ett program. Detta är ett bättre alternativ än att registrera databas öppnade prenumeranter.
Låt oss definiera ett nytt schema chef som inkluderar installation:
& Nbsp; >>> gsm.unregisterUtility (förutsatt = ISchemaManager, name = 'some.app')
& Nbsp; Sann
& Nbsp; >>> från zope.generations.interfaces importera IInstallableSchemaManager
& Nbsp; >>> klass MySchemaManager (objekt):
& Nbsp; ... redskap (IInstallableSchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generation = 2
& Nbsp; ...
& Nbsp; ... def installera (själv, kontext):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... root [svar '] = {' Hej ':'? Hi & hur gör man ",
& Nbsp; ... "? Meningen med livet": "42",
& Nbsp; ... "fyra & Nbsp; ... transaction.commit ()
& Nbsp; ...
& Nbsp; ... def utvecklas (själv, sammanhang generationen):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... Svar = root [svar ']
& Nbsp; ... om generation == 1:
& Nbsp; ... för fråga, svara i answers.items ():
& Nbsp; ... svar [fråga] = cgi.escape (svar)
& Nbsp; ... Elif generationen == 2:
& Nbsp; ... för fråga, svara i answers.items ():
& Nbsp; ... del svar [fråga]
& Nbsp; ... svar [cgi.escape (fråga)] = svar
& Nbsp; ... annars:
& Nbsp; ... höja ValueError ("Bummer")
& Nbsp; ... root [svar '] = svar # ping uthållighet
& Nbsp; ... transaction.commit ()
& Nbsp; >>> manager = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (manager, ISchemaManager, name = 'some.app')
Nu låter öppna en ny databas:
& Nbsp; >>> db.close ()
& Nbsp; >>> db = DB ()
& Nbsp; >>> uppk = db.open ()
& Nbsp; >>> "svar" i conn.root ()
& Nbsp; Falskt
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (event)
& Nbsp; >>> conn.sync ()
& Nbsp; >>> root = conn.root ()
& Nbsp; >>> pprint (root [svar '])
& Nbsp; {'Hej': 'Hej & hur gör man? ",
& Nbsp; "meningen med livet?": "42",
& Nbsp; 'fyra & Nbsp; >>> root [generations_key] ['some.app']
& Nbsp; 2
Loggen ZODB transaktionen noterar att vårt installera skript avrättades
& Nbsp; >>> [. It.description för det i conn.db () storage.iterator ()] [- 2]
& Nbsp; u'some.app: kör installera generation "
(Minor anmärkning: det är inte den sista posten eftersom det finns två åtar: MySchemaManager utför en, och evolveMinimumSubscriber utför andra MySchemaManager egentligen inte behöver begå..)

Vad är nytt i den här versionen:.

  • Utökat stöd för Python 3.3
  • Ersatt föråldrat zope.interface.implements användning med likvärdig zope.interface.implementer dekoratör.
  • Tappat stöd för Python 2.4 och 2.5.

Vad är nytt i version 3.7.1:

  • Bortutbyggnadsdelen som användes under utvecklingen men gör inte kompilera i Windows.
  • Generation skript lägga till en avräkningsnota.

Krav :

  • Python

Annan programvara för utvecklare Zope Corporation and Contributors

grokui.admin
grokui.admin

14 Apr 15

zope.tales
zope.tales

14 Apr 15

Kommentarer till zope.generations

Kommentarer hittades inte
Kommentar
Slå på bilder!