Last active
August 29, 2015 14:05
-
-
Save naftaliharris/68b4a09af50df8c15381 to your computer and use it in GitHub Desktop.
Finding intransitive subclass relationships in python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
transitivity.py | |
Author: Naftali Harris | |
Run this in a clean virtualenv to only find intransitive triples in the stdlib. | |
""" | |
import pkgutil | |
import inspect | |
import collections | |
from importlib import import_module | |
def all_classes(module): | |
return set([x[1] for x in inspect.getmembers(module, inspect.isclass)]) | |
def all_python_classes(): | |
res = set() | |
for module_loader, name, ispkg in pkgutil.walk_packages(): | |
try: | |
module = import_module(name) | |
except: | |
print name | |
else: | |
res |= all_classes(module) | |
res |= all_classes(__builtins__) | |
return res | |
def short_name(A): | |
return A.__module__ + "." + A.__name__ | |
def get_bad_triplets(types): | |
counts = collections.defaultdict(int) | |
for t1 in types: | |
for t2 in types: | |
if not issubclass(t1, t2): | |
continue | |
for t3 in types: | |
if issubclass(t2, t3): | |
counts["eligible"] += 1 | |
if not issubclass(t1, t3): | |
counts["intransitive"] += 1 | |
counts[("_", short_name(t2), short_name(t3))] += 1 | |
return counts | |
if __name__ == "__main__": | |
types = all_python_classes() | |
counts = get_bad_triplets(types) | |
for triplet, count in sorted(counts.items(), key=lambda x: -x[1]): | |
print ("%d\t%s" % (count, triplet)).replace("'", '') | |
print len(types) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment