Thursday, December 17, 2015

About configuring plugin attributes

I was wondering why the following code does not have the expected result (of setting start_year to 2014):

import datetime
from lino_cosi.projects.cosi1.settings import *

class Site(Site):
    ...

SITE = Site(globals())
SITE.plugins.accounting.configure(start_year=2014)

while this code worked:

import datetime
from lino_cosi.projects.cosi1.settings import *

class Site(Site):
    ...

    def setup_plugins(self):
        super(Site, self).setup_plugins()
        self.plugins.accounting.configure(start_year=2014)

SITE = Site(globals())

The explanation was not that the settings module would be getting imported twice (Ned Batchelder complained about this in 2011, django-extensions had an issue with it in August 2015, blueyed on pytest reported an issue in Januay 2015).

The explanation was that lino_cosi.projects.cosi1.settings.memory instantiated the Site a second time. It did:

from .demo import *

class Site(Site):
    verbose_name = Site.verbose_name + " (:memory:)"

SITE = Site(globals())

DATABASES['default']['NAME'] = ':memory:'

There are a few things to learn here:

  • we can indeed never guarantee that our SITE instance is actually being used. A solcal system admin can always decide to import our settings.py module and the reinstantiate our Site class. That’s part of our game with lino.core.site.Site and should not be forbidden.

  • I changed lino_cosi.projects.cosi1.settings.memory (and a first series of similar files) so that it no longer reinstantiates the SITE. Because that’s not necessary. A typical memory.py module in a settings package should have this content:

    from .demo import *
    SITE.verbose_name = SITE.verbose_name + " (:memory:)"
    DATABASES['default']['NAME'] = ':memory:'
    

A simple sales workflow with payment

I continued on #671, which is an important preparation for #143.

There was still a bug in a tricky part: the get_row_by_pk() method of lino_xl.lib.accounting.ui.ExpectedMovements. This part is tricky and hackerish because we need to re-create the volatile DueMovement objects for each selected row.

TODO: unregistering a BankStatement which had cleared an invoice does not yet restore the correct satisfied for the (now again unsatisfied) invoice.