ViUR3 Monkey-Patches¶
viur-testing betreibt einen ViUR3-/viur-core-Prozess gegen eine benannte
Datastore-Datenbank (Standard viur-tests) und einen optionalen Namespace.
Weder viur-core noch google-cloud-datastore unterstützen das vollständig out
of the box — der Test-Modus überbrückt das mit einer Reihe von
Laufzeit-Patches.
Alle Patches teilen zwei Eigenschaften:
- Nur Dev-Server — installiert über
activate(); einzige Ausnahme ist der Production-Guard, denprotect()in jeder Umgebung installiert. - Idempotent — eine erneute Aktivierung (Test-Re-Entry) ersetzt den Wrapper, statt Schichten zu stapeln.
1. Datastore-Client-Tausch¶
Ziel: viur.core.db.transport.__client__
Wofür: viur-core bindet beim Import einen einzigen modulweiten
datastore.Client() an die Default-Datenbank. Der Test-Modus muss stattdessen
mit der benannten Test-Datenbank sprechen.
Was er macht: activate() baut einen
datastore.Client(database=…, namespace=…), weist ihn per Schreib-Lese-Probe
nach und ersetzt transport.__client__ damit — vor jedem weiteren
viur-core-Import, sodass alle späteren Verbraucher den getauschten Client sehen.
Deshalb muss activate() ganz oben in main.py laufen, bevor
viur.core.db.transport importiert wird.
2. Key-Factory — Datenbank & Namespace injizieren¶
Ziel: viur.core.db.types.Key.__init__
Wofür: viur-cores Key reicht nur project= an
google.cloud.datastore.Key weiter, nie database= oder namespace=. Gegen
einen Client mit benannter Datenbank scheitert dadurch jeder Aufruf mit
InvalidArgument: 400 mismatched databases within request. Beim Namespace
dasselbe Problem — Schreibvorgänge landen im Default-Namespace, während Lesungen
aus dem Test-Namespace kommen (still leere Ergebnisse).
Was er macht: umhüllt Key.__init__ so, dass die Argumente database und
namespace standardmäßig auf die Werte des aktiven Clients gesetzt werden;
explizit übergebene Argumente gewinnen weiterhin. Das originale __init__ wird
am Wrapper hinterlegt, sodass eine erneute Aktivierung zuerst auspackt und dann
neu umhüllt (kein Stapeln).
3. Legacy-urlsafe-Keys für benannte Datenbanken¶
Ziel: google.cloud.datastore.key.Key.to_legacy_urlsafe
Wofür: die Originalmethode wirft ValueError("to_legacy_urlsafe only
supports the default database") bei jedem Key mit gesetzter database.
Was er macht: umhüllt die Google-Methode so, dass self._database rund um
den Originalaufruf temporär geleert und im finally wiederhergestellt wird. Der
resultierende urlsafe-String trägt Projekt + Namespace + Pfad (die Datenbank-ID
entfällt) — im Test-Prozess unbedenklich, da jeder Key dieselbe Datenbank
adressiert, die der Key-Factory-Patch (#2) beim Parsen wieder einsetzt. Gepatcht
wird an der Wurzel (die Google-Methode) statt an viur-cores __str__, sodass es
viur-core-Änderungen übersteht und jede Aufrufstelle abdeckt.
4. Boot-Banner — die aktive Datenbank anzeigen¶
Ziel: viur.core.setup
Wofür: beim Hochfahren des Dev-Servers ist die wichtigste Information,
welcher Datastore mit dem Prozess verdrahtet ist (Prod-Default vs.
viur-tests).
Was er macht: umhüllt viur.core.setup() so, dass während der Ausführung
builtins.print temporär durch einen Sniffer ersetzt wird, der viur-cores
Banner LOCAL DEVELOPMENT SERVER IS UP AND RUNNING erkennt und direkt vor dem
Banner-Abschluss die Zeilen database = … (und namespace = …, falls gesetzt)
in passender Breite und Stilistik einfügt. Das originale print wird
wiederhergestellt, sobald setup() zurückkehrt — außerhalb des Banner-Fensters
bleibt also nichts betroffen. Breite und Abschlusszeile werden zur Laufzeit
erkannt, sodass eine künftige Banner-Änderung in viur-core sauber degradiert.
5. Request-Validatoren¶
Ziel: viur.core.request.Router.requestValidators
Zwei Validatoren werden an die klassenweite Liste des Routers angehängt:
TokenValidator— installiert vonactivate()(Dev/Test). Weist jede Nicht-Bootstrap-Anfrage ab, der ein passendesviur-test-token-Cookie fehlt (konstantzeitiger Vergleich). Die Bootstrap-Pfade/_test/config/status,/_test/config/enterund/_test/config/finishumgehen ihn, damit Runner und manuelle Navigation eine Session öffnen können, bevor ein Cookie existiert.ProductionGuardValidator— installiert vonprotect()in jeder Umgebung; überwacht dasviur-test-token-Cookie als Stolperdraht: Auf einem Nicht-Dev-Server beantwortet er jede Anfrage mit diesem Cookie mit 403, unabhängig vom Wert; in Dev ist er ein No-op (dort besitzt derTokenValidatordas Cookie). Ein Test-Cookie darf Produktion nie erreichen, der Guard weist es also laut ab, statt es durchfallen zu lassen. Siehe Validatoren.
6. Closed-System-Allowlist¶
Ziel: conf.security.closed_system_allowed_paths
Wofür: viele Projekte laufen mit conf.security.closed_system = True, was
jede Anfrage mit nicht freigegebenem Pfad mit 401 beantwortet — noch vor dem
Routing. Der /_test/-Bootstrap und projektseitig registrierte
Fixture-Submodule wären selbst mit gültigem Token blockiert.
Was er macht: activate() erweitert die Liste um die Wildcards _test/*
und */_test/* (deckt jedes Render-Präfix und registrierte Fixtures ab). Die
Zugriffskontrolle auf diesen Pfaden übernimmt weiterhin der TokenValidator —
die Allowlist bringt die Anfrage nur am Closed-System-Gate vorbei.