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

1from .utils import _toposort, groupby 

2 

3class AmbiguityWarning(Warning): 

4 pass 

5 

6 

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)) 

10 

11 

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))) 

17 

18 

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)) 

22 

23 

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)} 

32 

33 

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) 

38 

39 return [max([type.mro(sig[i]) for sig in signatures], key=len)[0] 

40 for i in range(n)] 

41 

42 

43def edge(a, b, tie_breaker=hash): 

44 """ A should be checked before B 

45 

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 

54 

55 

56def ordering(signatures): 

57 """ A sane ordering of signatures to check, first to last 

58 

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)