Coverage for /usr/lib/python3/dist-packages/sympy/multipledispatch/conflict.py: 100%
31 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1from .utils import _toposort, groupby
3class AmbiguityWarning(Warning):
4 pass
7def supercedes(a, b):
8 """ A is consistent and strictly more specific than B """
9 return len(a) == len(b) and all(map(issubclass, a, b))
12def consistent(a, b):
13 """ It is possible for an argument list to satisfy both A and B """
14 return (len(a) == len(b) and
15 all(issubclass(aa, bb) or issubclass(bb, aa)
16 for aa, bb in zip(a, b)))
19def ambiguous(a, b):
20 """ A is consistent with B but neither is strictly more specific """
21 return consistent(a, b) and not (supercedes(a, b) or supercedes(b, a))
24def ambiguities(signatures):
25 """ All signature pairs such that A is ambiguous with B """
26 signatures = list(map(tuple, signatures))
27 return {(a, b) for a in signatures for b in signatures
28 if hash(a) < hash(b)
29 and ambiguous(a, b)
30 and not any(supercedes(c, a) and supercedes(c, b)
31 for c in signatures)}
34def super_signature(signatures):
35 """ A signature that would break ambiguities """
36 n = len(signatures[0])
37 assert all(len(s) == n for s in signatures)
39 return [max([type.mro(sig[i]) for sig in signatures], key=len)[0]
40 for i in range(n)]
43def edge(a, b, tie_breaker=hash):
44 """ A should be checked before B
46 Tie broken by tie_breaker, defaults to ``hash``
47 """
48 if supercedes(a, b):
49 if supercedes(b, a):
50 return tie_breaker(a) > tie_breaker(b)
51 else:
52 return True
53 return False
56def ordering(signatures):
57 """ A sane ordering of signatures to check, first to last
59 Topoological sort of edges as given by ``edge`` and ``supercedes``
60 """
61 signatures = list(map(tuple, signatures))
62 edges = [(a, b) for a in signatures for b in signatures if edge(a, b)]
63 edges = groupby(lambda x: x[0], edges)
64 for s in signatures:
65 if s not in edges:
66 edges[s] = []
67 edges = {k: [b for a, b in v] for k, v in edges.items()}
68 return _toposort(edges)