20130220¶
Why Django needs a populated signal¶
lino.projects.homeworkschool
had a problem with the new version,
caused by the Ross McFarland’s trick of having lino
as the last installed_app
and calling lino.Lino.startup
automatically from lino.models
.
The problem is that
lino.projects.homeworkschool
has apps which don’t import at first run.
The populate function in
django.db.models.loading
“postpones” them and gives them a second chance.
The order of installed applications is:
…lino.modlib.school
…lino.projects.homeworkschool
These two modules have the following interdependency:
homeworkschool defines the concrete implementation of contacts.Person (which is declared in
override_modlib_models
)school needs the concrete implementation of contacts.Person at module-level to define the Pupil and Teacher classes.
This means that school will get postponed until homeworkschool has been loaded.
All the above is rather trivial, but it took me a lot of time to understand the problem because of a “little bug”:
The
resolve_model
function may not use seed_cache=True (which causes Django to populate the models cache before looking for the model) since we want to have it usable at the top-level ofmodels
modules. Which is whatlino.projects.homeworkschool
did. This caused a recursive populate, leading to very confusing error messages.
Another piece of time went into finding out how to cope with this situation.
Which you can admire nor in lino.models
.
All this shows how regrettable it is that Django doesn’t provide a populated signal. It would be so easy, just two lines of code in /django/db/models/loading.py that wouldn’t hurt anybody:
populated = signals.Signal() # <<<<<<<<<<<<<<<<<<<<<<<<< first line
class AppCache(object):
...
def _populate(self):
if self.loaded:
return
imp.acquire_lock()
try:
if self.loaded:
return
for app_name in settings.INSTALLED_APPS:
if app_name in self.handled:
continue
self.load_app(app_name, True)
if not self.nesting_level:
for app_name in self.postponed:
self.load_app(app_name)
self.loaded = True
populated.send(sender=self) # <<<<<<<<<<<<< second line
finally:
imp.release_lock()
A test suite for watch_tim¶
A first bug in yesterday’s release occured. Here is my first reaction:
Patsch, der erste Bug in der neuen Version: diese Fehlermeldung kommt, wenn man in TIM einen Partner mit leerem PAR->IdUsr bearbeitet, der in Lino als Klient existiert und noch keine Begleitungen hat… Im vorliegenden Fall war es Partner Nummer 23633 (Kurt Sch.).
Die Unstabilität von watch_tim ist normal. Eigentlich müsste ich eine ganze Latte von unit tests schreiben. Das ist technisch nicht sehr kompliziert, würde aber viel Aufwand bedeuten, weil alle möglichen Normal- und Sonderfälle darin vorkommen müssten. Angesichts der Tatsache, dass watch_tim voraussichtlich bei euch schon bald Vergangenheit ist und auch garantiert nie bei irgendeinem anderen TIM-Benutzer jemals Verwendung finden wird finde ich, dass wir das einfach aushalten müssen…
After having written this, I nevertheless decided to start a unit test suite:
watchtim_tests
.
This took only 5 minutes, and at least this special case is now covered. I won’t invest much energy into getting everything covered for the said reasons, but who knows…
à propos test suite¶
Damit der obige Test in der Praxis taugt, müsste ich freilich erstmal die Testsuite wieder aufpäppeln, die ich in letzter Zeit vernachlässigt habe. Also ran an den Speck. Jetzt oder nie. Zumal ich vor dem Release heute abend sowieso nichts großes Neues anfangen will.
Eine zeitraubende Sache war folgendes:
In einem Demo-Test (test002
)
machte er eine Abfrage nach /api/cv/SoftSkillsByPerson.
Nun ist SoftSkillsByPerson
eine dynamische Tabelle, deren Titel und Inhalt von der SiteConfig abhängt.
Und die SiteConfig kriegt sinnvolle Werte erst wenn die Demo-Daten
eingelesen werden.
Wenn ich aber die gesamte Test-Suite laufen lasse,
wurde vorher
(quick_tests
)
schon das UI initialisiert, und zwar ohne Demo-Daten.
Und unsere dynamische Tabelle wurde natürlich nur ein einziges Mal pro Prozess
generiert: wenn man in den Site-Parametern eines der Felder
“Eigenschaftsgruppe Fähigkeiten”,
“Eigenschaftsgruppe Sozialkompetenzen”
oder
“Eigenschaftsgruppe Hindernisse”
verändert hätte, muss man anschließend den Server neustarten,
damit es aktiv wird.
So war das schon immer gewesen.
Wer will denn auch was Feineres.
Jawohl, unsere Testsuite will das.