[Python-ideas] Pre-conditions and post-conditions

Eric Fahlgren ericfahlgren at gmail.com
Wed Aug 29 18:39:54 EDT 2018


On Wed, Aug 29, 2018 at 3:07 PM Marko Ristin-Kaufmann <
marko.ristin at gmail.com> wrote:

> Could you please elaborate a bit? I don't see how the annotations would
> make the contracts invoked on inheritance. Consider this simple case:
>
> class A:
>     @icontract.pre(lambda x: x > 0)
>     def some_method(self, x: int)->None:
>         pass
>
> class B(A):
>     # Precondition should be inherited here.
>     def some_method(self, x: int) -> None:
>         pass
>
> You would still need to somehow decorate manually the overridden methods
> even though you would not specify any new contracts, right? Is there a
> mechanism in Python that I am not aware of that would allow us to
> accomplish that?
>

A metaclass does this pretty easily.  I have a thing I wrote years ago
called MIS (Multi-Inheritance Safety) that is used to ensure you don't do
anything stupid in our physics-modeling database.  The database is a
collection of ~200 Python classes/mixins all deriving madly from each other
to get various behaviors (Has mass? You'll need this.  Has moments?  You'll
need this.  Has physical extent, i.e., can be seen?  You'll need these...).

Anyhow, the basemost class has the metaclass, which traverses all the
methods in the subclasses and makes sure you don't have methods with the
same name in two distinct superclass trees and such things.  It also forces
you to be explicit when you overload a method from a base class (among
other things, but this one is easy to illustrate).

class MIS(type):
    def __init__(cls, name, bases, namespace):
        mro = cls.mro()[1:-1]  # All the stuff between new class and
'object'
        for method_name, method in namespace.items():
            if isinstance(method, executable_types):
                if not getattr(method, '_its_ok', False):
                    # Make sure it's not in any baser class.
                # Could easily check for decorated pre/post properties and
copy them...

def override(func):
    # Mark the function as a valid override...
    func._its_ok = True
    return func

class Base(metaclass=MIS):
    def something(self):
        pass

class Derived(Base):
    @override # Signal that this is ok, otherwise we get an error.
    def something(self): ...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180829/fc18e417/attachment.html>


More information about the Python-ideas mailing list