Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/astroid/interpreter/dunder_lookup.py: 97%

29 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:53 +0000

1# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 

2# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE 

3# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt 

4 

5"""Contains logic for retrieving special methods. 

6 

7This implementation does not rely on the dot attribute access 

8logic, found in ``.getattr()``. The difference between these two 

9is that the dunder methods are looked with the type slots 

10(you can find more about these here 

11http://lucumr.pocoo.org/2014/8/16/the-python-i-would-like-to-see/) 

12As such, the lookup for the special methods is actually simpler than 

13the dot attribute access. 

14""" 

15import itertools 

16 

17import astroid 

18from astroid.exceptions import AttributeInferenceError 

19 

20 

21def _lookup_in_mro(node, name) -> list: 

22 attrs = node.locals.get(name, []) 

23 

24 nodes = itertools.chain.from_iterable( 

25 ancestor.locals.get(name, []) for ancestor in node.ancestors(recurs=True) 

26 ) 

27 values = list(itertools.chain(attrs, nodes)) 

28 if not values: 

29 raise AttributeInferenceError(attribute=name, target=node) 

30 

31 return values 

32 

33 

34def lookup(node, name) -> list: 

35 """Lookup the given special method name in the given *node*. 

36 

37 If the special method was found, then a list of attributes 

38 will be returned. Otherwise, `astroid.AttributeInferenceError` 

39 is going to be raised. 

40 """ 

41 if isinstance( 

42 node, (astroid.List, astroid.Tuple, astroid.Const, astroid.Dict, astroid.Set) 

43 ): 

44 return _builtin_lookup(node, name) 

45 if isinstance(node, astroid.Instance): 

46 return _lookup_in_mro(node, name) 

47 if isinstance(node, astroid.ClassDef): 

48 return _class_lookup(node, name) 

49 

50 raise AttributeInferenceError(attribute=name, target=node) 

51 

52 

53def _class_lookup(node, name) -> list: 

54 metaclass = node.metaclass() 

55 if metaclass is None: 

56 raise AttributeInferenceError(attribute=name, target=node) 

57 

58 return _lookup_in_mro(metaclass, name) 

59 

60 

61def _builtin_lookup(node, name) -> list: 

62 values = node.locals.get(name, []) 

63 if not values: 

64 raise AttributeInferenceError(attribute=name, target=node) 

65 

66 return values