Ensure we don't infinitely recurse while saving CounterFields

Review Request #9843 — Created March 28, 2018 and submitted — Latest diff uploaded

Information

Djblets
release-2.0.x
be1b3f7...

Reviewers

If a model (1) defines a CounterField and (2) inherits from an
abstract model that defines a CounterField, then the magic that
CounterField does to replace _do_update on the model instance won't
work. It will call the equivalent of
super(type(model), model)._do_update, which, due to MRO, will resolve
to the method on the abstract model. However, that method has been
replaced by CounterField and it will have the same behaviour. Calling
super() this way only ever can take one step up the MRO chain (since
type(model) will never be the base class) and we therefore end up in a
loop of calling CounterField._do_update infinitely, which will blow
the stack.

We now reach directly to Model._do_update, avoiding the issues with
the MRO chain entirely, which results in the models being saved
successfully.

A unit test has been added (which, with this patch not applied, blows
the stack) to keep track of this edge case.

Ran unit tests.
Ran unit tests on /r/9609/ without blowing the stack.