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
« 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
5from __future__ import annotations
7import os
8import sys
9from collections.abc import Sequence
10from re import Pattern
12from astroid import modutils
14from pylint.typing import ErrorDescriptionDict, ModuleDescriptionDict
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
21 return modutils.modpath_from_file_with_callback(
22 filename, path=path, is_package_cb=_is_package_cb
23 )
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.
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()
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)
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()
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
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