======================== Thursday, March 24, 2016 ======================== :func:`super` in the :meth:`__str__` of a `python_2_unicode_compatible` ======================================================================== Here is now how to reproduce :ticket:`844`. The following code snippet was used to reproduce :ticket:`844`: >>> from lino import startup >>> startup('lino_welfare.projects.std.settings.doctests') >>> from lino.api.doctest import * >>> obj = households.Member() >>> print(obj) Member object Explanation starts in :mod:`lino_xl.lib.households.models` which defines:: @python_2_unicode_compatible class Member(mixins.DatePeriod): def __str__(self): if self.person_id is None: return super(Member, self).__str__() if self.role is None: return unicode(self.person) return u"%s (%s)" % (self.person, self.role) This code, on its own, is not problematic. The problem comes only when Lino Welfare extends the `Member` model. In :mod:`lino_welfare.modlib.households.models` it says:: class Member(Member, mixins.Human, mixins.Born): ... And in :mod:`lino.mixins.human` we have:: from lino_xl.lib.households.models import * @python_2_unicode_compatible class Human(model.Model): def __str__(self): return self.get_full_name(nominative=True) The rule of thumb is: **Don't use :func:`super` in the :meth:`__str__` method of a `python_2_unicode_compatible` model.** My explanation is that `python_2_unicode_compatible` causes something to get messed up with the *mro* for the :meth:`__str__` method, but I wont't dive deeper into this right now because my problem was fixed by changing the relevant line:: return super(Member, self).__str__() into an explicit copy of the code which I want to run there (defined in the :func:`super` of Django's :class:`Model` class):: return str('%s object' % self.__class__.__name__) I added a section about "Member objects" in :ref:`welfare.specs.households` to cover it. Moving from `fabric` to `invoke` ================================ I wanted to get the Lino test suite pass on Travis CI. It took me almost the whole day. Lots of subtle changes in :mod:`atelier`. The main problem was to understand `how invoke does configuration `_ and to decide how to store `current_project` and how to define configration variables. I added an `invoke.yaml` to most projects. Many more :cmd:`inv` commands now work. :cmd:`fab bd` was the easiest: it simply wasn't yet imported into the :mod:`atelier.tasks` module. There was a bug in :func:`atelier.utils.confirm` which made it fail under Python 2 when the prompt was a unicode string with non-ascii characters. .. literalinclude:: 0324.py Above script gives:: Traceback (most recent call last): File "0324.py", line 4, in confirm("Ein schöner Tag?") File "/atelier/atelier/utils.py", line 213, in confirm ln = input(prompt) UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 7: ordinal not in range(128) A simplified version: .. literalinclude:: 0324.py But finally I can not do:: $ pp inv clean $ pp inv prep test bd pd I released Atelier 0.0.20 to PyPI (needed because Travis CI uses the released version) And the reward: the Lino test suite now `passes on Travis CI `_ using `invoke` instead of `fabric`! At least for Python 2.