[Tutor] Do not understand code snippet from "26.8. test — Regression tests package for Python"

boB Stepp robertvstepp at gmail.com
Mon Apr 17 22:49:12 EDT 2017


Ah, Peter, if only I could achieve your understanding and mastery!

On Mon, Apr 17, 2017 at 3:37 AM, Peter Otten <__peter__ at web.de> wrote:

> Perhaps it becomes clearer if we build our own class discovery / method
> runner system. Given T as the baseclass for classes that provide foo_...()
> methods that we want to run, and M as the mix-in that provides such methods
> but isn't itself a subclass of T...
>

[snip]

> As you can see, to the discovery algorithm it doesn't matter where the
> method is defined, it suffices that it's part of the class and can be found
> by dir() or vars().
>

[snip]

>
> $ cat discovery6.py
> class T:
>     pass
>
> class M:
>     def foo_one(self):
>         print(self.__class__.__name__, "one")
>     def foo_two(self):
>         print(self.__class__.__name__, "two")
>
> class X(T):
>     def foo_x(self):
>         print(self.__class__.__name__, "x")
>
> class Y(M, T):
>     pass
>
> def safe_issubclass(S, B):
>     try:
>         return issubclass(S, B)
>     except TypeError:
>         return False
>
> def discover_Ts():
>     for C in globals().values():
>         if safe_issubclass(C, T) and C is not T:
>             print("found", C, "with foo_... methods")
>             for name in dir(C):
>                 if name.startswith("foo_"):
>                     yield C, name

So your discover function does not need to instantiate any objects; it
just searches the module's global namespace for class names.  Cool!
And dir(C) gives all attributes of C including _inherited_ attributes!
 This clarifies so much.  Many thanks, Peter!

> def run_method(cls, methodname):
>     inst = cls()
>     method = getattr(inst, methodname)
>     method()
>
> def main():
>     for cls, methodname in discover_Ts():
>         run_method(cls, methodname)
>
> if __name__ == "__main__":
>     main()
> $ python3 discovery6.py
> found <class '__main__.Y'> with foo_... methods
> Y one
> Y two
> found <class '__main__.X'> with foo_... methods
> X x
>
> That was easy. We have replicated something similar to the unit test
> framework with very little code.
>
> Now you can go and find the equivalent parts in the unittest source code :)

But not tonight ~(:>))


-- 
boB


More information about the Tutor mailing list