zope.generations

Screenshot Software:
zope.generations
Szczegóły programowe:
Wersja: 4.0.0 Alpha 1
Filmu: 15 Apr 15
Licencja: Wolny
Popularność: 37

Rating: nan/5 (Total Votes: 0)

zope.generations przedstawia sposób aktualizacji obiektów w bazie danych, gdy zmiana schematu zastosowania i nbsp;. Schema zastosowanie zasadniczo struktura danych struktury klas w przypadku ZODB lub opisach stołowych w przypadku relacyjnej bazy danych.
Szczegółowe Dokumentacja
Pokolenia są sposobem aktualizacji obiektów, gdy zmiany schematu aplikacji bazy danych. Schemat zastosowanie zasadniczo struktura danych struktury klas w przypadku ZODB lub opisach stołowych w przypadku relacyjnej bazie danych.
Po zmianie struktury danych swojej aplikacji, na przykład zmiany semantyczne znaczenie istniejącego pola w klasie, będzie mieć problem z baz danych, które zostały utworzone przed zmianą. Dla bardziej wnikliwej dyskusji i możliwych rozwiązań, patrz http://wiki.zope.org/zope3/DatabaseGenerations
Będziemy używać architektury komponentów, a my potrzebujemy bazy danych i połączenia:
& Nbsp; >>> import cgi
& Nbsp; >>> z pprint importu pprint
& Nbsp; >>> z zope.interface narzędzi importu
& Nbsp; >>> import DB z ZODB.tests.util
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.open ()
& Nbsp; >>> root = conn.root ()
Wyobraź sobie, że nasza aplikacja jest wyrocznią: można nauczyć go reagować na zwrotów. Trzymajmy to proste i zapisać dane w dict:
& Nbsp; >>> korzeniowe ['odpowiedzi'] = {"Cześć": "Cześć i jak to zrobić",
& Nbsp; ...? "Sens życia": "42",
& Nbsp; ... "cztery & Nbsp; >>> transakcji importu
& Nbsp; >>> transaction.commit ()
Ustawienia domyślne
Oto niektóre specyficzne Kod pokolenia. Stworzymy i zarejestrować SchemaManager. SchemaManagers są odpowiedzialne za rzeczywistych aktualizacji bazy danych. Ten będzie po prostu obojętne. Chodzi o to, aby pokolenia modułu świadomi, że nasza aplikacja obsługuje pokoleń.
Domyślna implementacja SchemaManager nie nadaje się do tego testu, ponieważ korzysta z modułów Pythona do zarządzania pokoleń. Na razie, to będzie dobrze, ponieważ nie chcemy, to do niczego jeszcze.
& Nbsp; >>> z zope.generations.interfaces importować ISchemaManager
& Nbsp; >>> z zope.generations.generations importować SchemaManager
& Nbsp; >>> import zope.component
& Nbsp; >>> dummy_manager = SchemaManager (minimum_generation = 0, pokolenie = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... dummy_manager, ISchemaManager, name = "some.app")
"Some.app" jest unikalny identyfikator. Należy użyć URI lub przerywaną nazwę pakietu.
Po uruchomieniu Zope i baza danych jest otwarta, IDatabaseOpenedWithRoot wysłaniu zdarzenia. Zope rejestruje evolveMinimumSubscriber domyślnie jako obsługi dla tego zdarzenia. Miejmy symulacji to:
& Nbsp; >>> klasy DatabaseOpenedEventStub (obiekt):
& Nbsp; ... def __init __ (self, bazy danych):
& Nbsp; ... self.database = baza danych
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> z zope.generations.generations importować evolveMinimumSubscriber
& Nbsp; >>> evolveMinimumSubscriber (wydarzenie)
Konsekwencją tego działania jest to, że teraz baza danych zawiera fakt, że nasz aktualny numer schematu jest 0. Kiedy zaktualizować schemat, Zope3 będzie miał pomysł, co Punktem wyjścia była. Tutaj, widzisz?
& Nbsp; >>> z zope.generations.generations importować generations_key
& Nbsp; >>> główny [generations_key] ['some.app']
& Nbsp; 0
W prawdziwym życiu nigdy nie powinno mieć męczyć się z tego klucza bezpośrednio, ale należy pamiętać, że istnieje.
Upgrade scenariusz
Powrót do historii. Jakiś czas mija, a jeden z naszych klientów dostaje włamał bo zapomniał uciec HTML znaków specjalnych! Horror! Musimy rozwiązać ten problem jak najszybciej bez utraty danych. Postanawiamy skorzystać pokolenia zaimponować naszych rówieśników.
Miejmy zaktualizować menedżera schematów (spadek stary i zainstalować nowy zwyczaj jeden):
& Nbsp; >>> z zope.component importu globalregistry
& Nbsp; >>> gsm = globalregistry.getGlobalSiteManager ()
& Nbsp; >>> gsm.unregisterUtility (pod warunkiem = ISchemaManager, name = "some.app")
& Nbsp; prawda
& Nbsp; >>> klasy MySchemaManager (obiekt):
& Nbsp; ... przyrządy (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generacji = 2
& Nbsp; ...
& Nbsp; ... def ewoluować (self, kontekst, generacji):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... Odpowiedzi = root ['odpowiedzi']
& Nbsp; ... jeśli generacji == 1:
& Nbsp; ... na pytanie, odpowiedź w answers.items ():
& Nbsp; ... odpowiedzi [Pytanie] = cgi.escape (odpowiedź)
& Nbsp; ... Elif generacji == 2:
& Nbsp; ... na pytanie, odpowiedź w answers.items ():
& Nbsp; ... del odpowiedzi [Pytanie]
& Nbsp; ... odpowiedzi [cgi.escape (pytanie)] = odpowiedź
& Nbsp; ... jeszcze:
& Nbsp; ... podnieść ValueError ("wpadki")
& Nbsp; ... korzeniowe ['odpowiedzi'] = odpowiedzi # ping wytrwałości
& Nbsp; ... transaction.commit ()
& Nbsp; >>> manager = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (kierownik, ISchemaManager, name = "some.app")
Stworzyliśmy minimum_generation do 1. Oznacza to, że nasza aplikacja będzie odmówić uruchomić z bazy danych starszej niż pokolenia 1. atrybut generacji jest ustawiony na 2, co oznacza, że ​​najnowsza generacja że SchemaManager wie o 2.
ewoluować () jest siłą napędową tutaj. Jego zadaniem jest dostać się do bazy danych z pokolenia na pokolenie-1. To staje się kontekst, który ma "związek" atrybut, który jest podłączenie do ZODB. Możesz używać, aby zmienić obiekty jak w tym przykładzie.
W tym szczególnym generacji realizacji 1 ucieka odpowiedzi (powiedzmy, krytyczne, ponieważ mogą one być wprowadzone przez nikogo!), Generacja 2 ucieka pytania (powiedzmy, mniej ważne, ponieważ mogą one być wprowadzone przez upoważnione kadrze tylko).
W rzeczywistości, tak naprawdę nie potrzebuję niestandardową implementację ISchemaManager. Jednym z nich jest dostępna, użyliśmy go na manekinie wcześniej. Używa modułów Pythona dla organizacji funkcji EVOLVER. Zobacz swoje docstring uzyskać więcej informacji.
W prawdziwym życiu będzie miał dużo więcej skomplikowanych struktur obiektów niż ten tutaj. Aby ułatwić sobie życie, są dwie bardzo przydatne funkcje dostępne w zope.generations.utility: findObjectsMatching () i findObjectsProviding (). Będą kopać przez pojemnikach rekurencyjnie, aby pomóc Ci odszukać stare przedmioty, które chcesz zaktualizować, przez interfejs lub innych kryteriów. Są one łatwe do zrozumienia, sprawdzić swoje docstrings.
Pokolenia w akcji
Tak, nasz wściekły klient pobiera nasz najnowszy kod i restartuje Zope. Impreza zostanie automatycznie wysłany ponownie:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (wydarzenie)
Shazam! Klient jest zadowolony ponownie!
& Nbsp; >>> pprint (korzeniowe [']) odpowiedzi "
& Nbsp; {"Cześć": "Cześć i jak to zrobić?",
& Nbsp; "sens życia?": "42",
& Nbsp; "cztery Ponieważ evolveMinimumSubscriber jest bardzo leniwy, tylko aktualizuje bazę danych tylko na tyle, że aplikacja może go używać (do minimum_generation, że jest). Istotnie, marker oznacza, że ​​generacja bazie został wpadł do 1:
& Nbsp; >>> główny [generations_key] ['some.app']
& Nbsp; 1
Widzimy, że pokolenia pracują, więc zdecydujemy się zrobić następny krok i rozwijać na pokolenie 2. Zobaczmy, jak można to zrobić ręcznie:
& Nbsp; >>> z zope.generations.generations importować ewoluują
& Nbsp; >>> ewoluować (db)
& Nbsp; >>> pprint (korzeniowe [']) odpowiedzi "
& Nbsp; {"Cześć": "Cześć i jak to zrobić?",
& Nbsp; "sens życia?": "42",
& Nbsp; "cztery & Nbsp; >>> główny [generations_key] ['some.app']
& Nbsp; 2
Domyślne zachowanie Evolve aktualizacji do najnowszej generacji dostarczonych przez SchemaManager. Możesz użyć argumentu jak się rozwijać (), gdy chcesz po prostu sprawdzić, jeśli chcesz zaktualizować lub jeśli chcesz być leniwy jak abonenta, który nazwaliśmy wcześniej.
Kolejność menedżerów schematu
Najczęściej podsystemów wykorzystywane do komponowania aplikacji polegać na innych podsystemów, aby działać poprawnie. Jeśli oba podsystemy dostarczyć menedżerów schematu, często jest to, by wiedzieć, w jakiej kolejności będą się evolvers wywoływany. Pozwala to ramy i to klienci mogli się rozwijać w koncercie, a klienci mogą wiedzieć, że ramy będą ewoluowały przed lub po sobie.
Może to być osiągnięte przez sterowanie nazwy narzędzi menedżera schematu. Menedżerowie schematu są uruchamiane w kolejności ustalonej przez sortowanie ich nazwy.
& Nbsp; >>> Manager1 = SchemaManager (minimum_generation = 0, pokolenie = 0)
& Nbsp; >>> manager2 = SchemaManager (minimum_generation = 0, pokolenie = 0)
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... Manager1, ISchemaManager, name = "another.app")
& Nbsp; >>> zope.component.provideUtility (
& Nbsp; ... manager2, ISchemaManager, name = "another.app-extension)
Zauważ, jak nazwa pierwszego pakietu jest używany do tworzenia nazw dla pakietów zależnych. To nie jest wymogiem w ramach, ale wygodne wzór dla tego zastosowania.
Niech rozwija bazę danych w celu ustalenia tych pokoleń:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (wydarzenie)
& Nbsp; >>> główny [generations_key] ['another.app']
& Nbsp; 0
& Nbsp; >>> główny [generations_key] ['another.app-extension']
& Nbsp; 0
Załóżmy, że z jakiegoś powodu każdego z tych podsystemów musi dodać pokolenie i to pokolenie 1 'another.app-extension "zależy od generacji 1' another.app". Musimy zapewnić menedżerów dla każdego schematu tej płyty, że już uruchomić, abyśmy mogli zweryfikować wynik:
& Nbsp; >>> gsm.unregisterUtility (pod warunkiem = ISchemaManager, name = "another.app")
& Nbsp; prawda
& Nbsp; >>> gsm.unregisterUtility (
& Nbsp; ... pod warunkiem = ISchemaManager, name = "another.app-extension)
& Nbsp; prawda
& Nbsp; >>> klasy FoundationSchemaManager (obiekt):
& Nbsp; ... przyrządy (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generacji = 1
& Nbsp; ...
& Nbsp; ... def ewoluować (self, kontekst, generacji):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... zamawianie = root.get ("Zamawiający", [])
& Nbsp; ... jeśli generacji == 1:
& Nbsp; ... ordering.append ("fundacja 1")
& Nbsp; ... "generacji fundacja 1 'do druku
& Nbsp; ... jeszcze:
& Nbsp; ... podnieść ValueError ("wpadki")
& Nbsp; ... główny ["Zamawiający"] = zamawiania # ping wytrwałość
& Nbsp; ... transaction.commit ()
& Nbsp; >>> klasy DependentSchemaManager (obiekt):
& Nbsp; ... przyrządy (ISchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generacji = 1
& Nbsp; ...
& Nbsp; ... def ewoluować (self, kontekst, generacji):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... zamawianie = root.get ("Zamawiający", [])
& Nbsp; ... jeśli generacji == 1:
& Nbsp; ... ordering.append ("zależne 1")
& Nbsp; ... print "pokolenie uzależnione 1"
& Nbsp; ... jeszcze:
& Nbsp; ... podnieść ValueError ("wpadki")
& Nbsp; ... główny ["Zamawiający"] = zamawiania # ping wytrwałość
& 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)
Ewoluuje bazę teraz będzie zawsze uruchomić "another.app" Evolver przed "another.app-extension" EVOLVER:
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (wydarzenie)
& Nbsp; generacji fundacja 1
& Nbsp; generacji uzależniona 1
& Nbsp; >>> główny ["Zamawiający"]
& Nbsp; ["fundacja 1 ',' zależna 1 ']
instalacji
W powyższym przykładzie, możemy ręcznie zainicjowany odpowiedzi. Nie powinniśmy tego robić ręcznie. Wniosek powinien być w stanie to zrobić automatycznie.
IInstallableSchemaManager rozciąga ISchemaManager, zapewniając metodę instalacji do wykonywania intial instalację aplikacji. Jest to lepsze rozwiązanie niż abonentów bazy danych rejestracji otwarty.
Zdefiniujmy nowego menedżera, który obejmuje instalację schematu:
& Nbsp; >>> gsm.unregisterUtility (pod warunkiem = ISchemaManager, name = "some.app")
& Nbsp; prawda
& Nbsp; >>> z zope.generations.interfaces importować IInstallableSchemaManager
& Nbsp; >>> klasy MySchemaManager (obiekt):
& Nbsp; ... przyrządy (IInstallableSchemaManager)
& Nbsp; ...
& Nbsp; ... minimum_generation = 1
& Nbsp; ... generacji = 2
& Nbsp; ...
& Nbsp; ... def zainstalować (self, kontekst):
& Nbsp; ... root = context.connection.root ()
& Nbsp; ... korzeń ['odpowiedzi'] = {"Cześć": "Cześć i jak to zrobić",
& Nbsp; ...? "Sens życia": "42",
& Nbsp; ... "cztery & Nbsp; ... transaction.commit ()
& Nbsp; ...
& Nbsp; ... def ewoluować (self, kontekst, generacji):
& Nbsp; ... root = context.connection.root ()
& nbsp; ... Odpowiedzi = root ['odpowiedzi']
& Nbsp; ... jeśli generacji == 1:
& Nbsp; ... na pytanie, odpowiedź w answers.items ():
& Nbsp; ... odpowiedzi [Pytanie] = cgi.escape (odpowiedź)
& Nbsp; ... Elif generacji == 2:
& Nbsp; ... na pytanie, odpowiedź w answers.items ():
& Nbsp; ... del odpowiedzi [Pytanie]
& Nbsp; ... odpowiedzi [cgi.escape (pytanie)] = odpowiedź
& Nbsp; ... jeszcze:
& Nbsp; ... podnieść ValueError ("wpadki")
& Nbsp; ... korzeniowe ['odpowiedzi'] = odpowiedzi # ping wytrwałości
& Nbsp; ... transaction.commit ()
& Nbsp; >>> manager = MySchemaManager ()
& Nbsp; >>> zope.component.provideUtility (kierownik, ISchemaManager, name = "some.app")
Teraz, pozwala otworzyć nową bazę danych:
& Nbsp; >>> db.close ()
& Nbsp; >>> db = DB ()
& Nbsp; >>> conn = db.open ()
& Nbsp; >>> "odpowiedzi" w conn.root ()
& Nbsp; Fałsz
& Nbsp; >>> event = DatabaseOpenedEventStub (db)
& Nbsp; >>> evolveMinimumSubscriber (wydarzenie)
& Nbsp; >>> conn.sync ()
& Nbsp; >>> root = conn.root ()
& Nbsp; >>> pprint (korzeniowe [']) odpowiedzi "
& Nbsp; {"Cześć": "Cześć i jak to zrobić?",
& Nbsp; "sens życia?": "42",
& Nbsp; "cztery & Nbsp; >>> główny [generations_key] ['some.app']
& Nbsp; 2
Dziennik transakcji ZODB zauważa, że ​​nasza instalacja skrypt został wykonany
& Nbsp; >>> [. It.description go w conn.db () storage.iterator ()] [- 2]
& Nbsp; u'some.app: prowadzenie instalacji generacji "
(Minor uwaga: to nie jest ostatni rekord, ponieważ istnieją dwa Zobowiązuje: MySchemaManager wykonuje jedną i evolveMinimumSubscriber wykonuje drugi MySchemaManager naprawdę nie trzeba się zaangażować.).

Co nowego w tym wydaniu:.

  • Dodano wsparcie dla Pythona 3.3
  • Zastąpiony przestarzałe zope.interface.implements Wykorzystanie o równoważnym zope.interface.implementer dekoratora.
  • Usunięto wsparcie dla Pythona 2.4 i 2.5.

Co nowego w wersji 3.7.1:

  • Usunięto część buildout który był używany w trakcie rozwoju, ale nie nie skompilować na Windows.
  • skrypty Generation dodać notatkę transakcji.

Wymagania :

  • Python

Inne programy z deweloperem Zope Corporation and Contributors

zope.app.http
zope.app.http

11 May 15

zope.app.server
zope.app.server

11 May 15

zope.errorview
zope.errorview

11 May 15

Komentarze do zope.generations

Komentarze nie znaleziono
Dodaj komentarz
Włącz zdjęć!