diff options
author | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
commit | a73a964e51247ed169d322c725a3a18859f109a3 (patch) | |
tree | 3f752d117274d444bda44e85609aeac1acf313f3 /sys/src/cmd/python/Demo/metaclasses/Eiffel.py | |
parent | e64efe273fcb921a61bf27d33b230c4e64fcd425 (diff) |
python, hg: tow outside the environment.
they've served us well, and can ride off into the sunset.
Diffstat (limited to 'sys/src/cmd/python/Demo/metaclasses/Eiffel.py')
-rw-r--r-- | sys/src/cmd/python/Demo/metaclasses/Eiffel.py | 113 |
1 files changed, 0 insertions, 113 deletions
diff --git a/sys/src/cmd/python/Demo/metaclasses/Eiffel.py b/sys/src/cmd/python/Demo/metaclasses/Eiffel.py deleted file mode 100644 index 24fac148d..000000000 --- a/sys/src/cmd/python/Demo/metaclasses/Eiffel.py +++ /dev/null @@ -1,113 +0,0 @@ -"""Support Eiffel-style preconditions and postconditions. - -For example, - -class C: - def m1(self, arg): - require arg > 0 - return whatever - ensure Result > arg - -can be written (clumsily, I agree) as: - -class C(Eiffel): - def m1(self, arg): - return whatever - def m1_pre(self, arg): - assert arg > 0 - def m1_post(self, Result, arg): - assert Result > arg - -Pre- and post-conditions for a method, being implemented as methods -themselves, are inherited independently from the method. This gives -much of the same effect of Eiffel, where pre- and post-conditions are -inherited when a method is overridden by a derived class. However, -when a derived class in Python needs to extend a pre- or -post-condition, it must manually merge the base class' pre- or -post-condition with that defined in the derived class', for example: - -class D(C): - def m1(self, arg): - return arg**2 - def m1_post(self, Result, arg): - C.m1_post(self, Result, arg) - assert Result < 100 - -This gives derived classes more freedom but also more responsibility -than in Eiffel, where the compiler automatically takes care of this. - -In Eiffel, pre-conditions combine using contravariance, meaning a -derived class can only make a pre-condition weaker; in Python, this is -up to the derived class. For example, a derived class that takes away -the requirement that arg > 0 could write: - - def m1_pre(self, arg): - pass - -but one could equally write a derived class that makes a stronger -requirement: - - def m1_pre(self, arg): - require arg > 50 - -It would be easy to modify the classes shown here so that pre- and -post-conditions can be disabled (separately, on a per-class basis). - -A different design would have the pre- or post-condition testing -functions return true for success and false for failure. This would -make it possible to implement automatic combination of inherited -and new pre-/post-conditions. All this is left as an exercise to the -reader. - -""" - -from Meta import MetaClass, MetaHelper, MetaMethodWrapper - -class EiffelMethodWrapper(MetaMethodWrapper): - - def __init__(self, func, inst): - MetaMethodWrapper.__init__(self, func, inst) - # Note that the following causes recursive wrappers around - # the pre-/post-condition testing methods. These are harmless - # but inefficient; to avoid them, the lookup must be done - # using the class. - try: - self.pre = getattr(inst, self.__name__ + "_pre") - except AttributeError: - self.pre = None - try: - self.post = getattr(inst, self.__name__ + "_post") - except AttributeError: - self.post = None - - def __call__(self, *args, **kw): - if self.pre: - apply(self.pre, args, kw) - Result = apply(self.func, (self.inst,) + args, kw) - if self.post: - apply(self.post, (Result,) + args, kw) - return Result - -class EiffelHelper(MetaHelper): - __methodwrapper__ = EiffelMethodWrapper - -class EiffelMetaClass(MetaClass): - __helper__ = EiffelHelper - -Eiffel = EiffelMetaClass('Eiffel', (), {}) - - -def _test(): - class C(Eiffel): - def m1(self, arg): - return arg+1 - def m1_pre(self, arg): - assert arg > 0, "precondition for m1 failed" - def m1_post(self, Result, arg): - assert Result > arg - x = C() - x.m1(12) -## x.m1(-1) - -if __name__ == '__main__': - _test() |