Coverage for C:\Repos\ekr-pylint\pylint\lint\expand_modules.py: 15%

72 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-24 10:21 -0500

1# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html 

2# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE 

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

4 

5from __future__ import annotations 

6 

7import os 

8import sys 

9from collections.abc import Sequence 

10from re import Pattern 

11 

12from astroid import modutils 

13 

14from pylint.typing import ErrorDescriptionDict, ModuleDescriptionDict 

15 

16 

17def _modpath_from_file(filename: str, is_namespace: bool, path: list[str]) -> list[str]: 

18 def _is_package_cb(inner_path: str, parts: list[str]) -> bool: 

19 return modutils.check_modpath_has_init(inner_path, parts) or is_namespace 

20 

21 return modutils.modpath_from_file_with_callback( 

22 filename, path=path, is_package_cb=_is_package_cb 

23 ) 

24 

25 

26def get_python_path(filepath: str) -> str: 

27 """TODO This get the python path with the (bad) assumption that there is always 

28 an __init__.py. 

29 

30 This is not true since python 3.3 and is causing problem. 

31 """ 

32 dirname = os.path.realpath(os.path.expanduser(filepath)) 

33 if not os.path.isdir(dirname): 

34 dirname = os.path.dirname(dirname) 

35 while True: 

36 if not os.path.exists(os.path.join(dirname, "__init__.py")): 

37 return dirname 

38 old_dirname = dirname 

39 dirname = os.path.dirname(dirname) 

40 if old_dirname == dirname: 

41 return os.getcwd() 

42 

43 

44def _is_in_ignore_list_re(element: str, ignore_list_re: list[Pattern[str]]) -> bool: 

45 """Determines if the element is matched in a regex ignore-list.""" 

46 return any(file_pattern.match(element) for file_pattern in ignore_list_re) 

47 

48 

49def expand_modules( 

50 files_or_modules: Sequence[str], 

51 ignore_list: list[str], 

52 ignore_list_re: list[Pattern[str]], 

53 ignore_list_paths_re: list[Pattern[str]], 

54) -> tuple[list[ModuleDescriptionDict], list[ErrorDescriptionDict]]: 

55 """Take a list of files/modules/packages and return the list of tuple 

56 (file, module name) which have to be actually checked. 

57 """ 

58 result: list[ModuleDescriptionDict] = [] 

59 errors: list[ErrorDescriptionDict] = [] 

60 path = sys.path.copy() 

61 

62 for something in files_or_modules: 

63 basename = os.path.basename(something) 

64 if ( 

65 basename in ignore_list 

66 or _is_in_ignore_list_re(os.path.basename(something), ignore_list_re) 

67 or _is_in_ignore_list_re(something, ignore_list_paths_re) 

68 ): 

69 continue 

70 module_path = get_python_path(something) 

71 additional_search_path = [".", module_path] + path 

72 if os.path.exists(something): 

73 # this is a file or a directory 

74 try: 

75 modname = ".".join( 

76 modutils.modpath_from_file(something, path=additional_search_path) 

77 ) 

78 except ImportError: 

79 modname = os.path.splitext(basename)[0] 

80 if os.path.isdir(something): 

81 filepath = os.path.join(something, "__init__.py") 

82 else: 

83 filepath = something 

84 else: 

85 # suppose it's a module or package 

86 modname = something 

87 try: 

88 filepath = modutils.file_from_modpath( 

89 modname.split("."), path=additional_search_path 

90 ) 

91 if filepath is None: 

92 continue 

93 except (ImportError, SyntaxError) as ex: 

94 # The SyntaxError is a Python bug and should be 

95 # removed once we move away from imp.find_module: https://bugs.python.org/issue10588 

96 errors.append({"key": "fatal", "mod": modname, "ex": ex}) 

97 continue 

98 filepath = os.path.normpath(filepath) 

99 modparts = (modname or something).split(".") 

100 try: 

101 spec = modutils.file_info_from_modpath( 

102 modparts, path=additional_search_path 

103 ) 

104 except ImportError: 

105 # Might not be acceptable, don't crash. 

106 is_namespace = False 

107 is_directory = os.path.isdir(something) 

108 else: 

109 is_namespace = modutils.is_namespace(spec) 

110 is_directory = modutils.is_directory(spec) 

111 if not is_namespace: 

112 result.append( 

113 { 

114 "path": filepath, 

115 "name": modname, 

116 "isarg": True, 

117 "basepath": filepath, 

118 "basename": modname, 

119 } 

120 ) 

121 has_init = ( 

122 not (modname.endswith(".__init__") or modname == "__init__") 

123 and os.path.basename(filepath) == "__init__.py" 

124 ) 

125 if has_init or is_namespace or is_directory: 

126 for subfilepath in modutils.get_module_files( 

127 os.path.dirname(filepath), ignore_list, list_all=is_namespace 

128 ): 

129 if filepath == subfilepath: 

130 continue 

131 if _is_in_ignore_list_re( 

132 os.path.basename(subfilepath), ignore_list_re 

133 ) or _is_in_ignore_list_re(subfilepath, ignore_list_paths_re): 

134 continue 

135 

136 modpath = _modpath_from_file( 

137 subfilepath, is_namespace, path=additional_search_path 

138 ) 

139 submodname = ".".join(modpath) 

140 result.append( 

141 { 

142 "path": subfilepath, 

143 "name": submodname, 

144 "isarg": False, 

145 "basepath": filepath, 

146 "basename": modname, 

147 } 

148 ) 

149 return result, errors