MCPcopy
hub / github.com/python/mypy / SourceFinder

Class SourceFinder

mypy/find_sources.py:97–239  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

95
96
97class SourceFinder:
98 def __init__(self, fscache: FileSystemCache, options: Options) -> None:
99 self.fscache = fscache
100 self.explicit_package_bases = get_explicit_package_bases(options)
101 self.namespace_packages = options.namespace_packages
102 self.exclude = options.exclude
103 self.exclude_gitignore = options.exclude_gitignore
104 self.verbosity = options.verbosity
105
106 def is_explicit_package_base(self, path: str) -> bool:
107 assert self.explicit_package_bases
108 return normalise_package_base(path) in self.explicit_package_bases
109
110 def find_sources_in_dir(self, path: str) -> list[BuildSource]:
111 sources = []
112
113 seen: set[str] = set()
114 names = sorted(self.fscache.listdir(path), key=keyfunc)
115 for name in names:
116 # Skip certain names altogether
117 if name in ("__pycache__", "site-packages", "node_modules") or name.startswith("."):
118 continue
119 subpath = os.path.join(path, name)
120
121 if matches_exclude(subpath, self.exclude, self.fscache, self.verbosity >= 2):
122 continue
123 if self.exclude_gitignore and matches_gitignore(
124 subpath, self.fscache, self.verbosity >= 2
125 ):
126 continue
127
128 if self.fscache.isdir(subpath):
129 sub_sources = self.find_sources_in_dir(subpath)
130 if sub_sources:
131 seen.add(name)
132 sources.extend(sub_sources)
133 else:
134 stem, suffix = os.path.splitext(name)
135 if stem not in seen and suffix in PY_EXTENSIONS:
136 seen.add(stem)
137 module, base_dir = self.crawl_up(subpath)
138 sources.append(BuildSource(subpath, module, None, base_dir))
139
140 return sources
141
142 def crawl_up(self, path: str) -> tuple[str, str]:
143 """Given a .py[i] filename, return module and base directory.
144
145 For example, given "xxx/yyy/foo/bar.py", we might return something like:
146 ("foo.bar", "xxx/yyy")
147
148 If namespace packages is off, we crawl upwards until we find a directory without
149 an __init__.py
150
151 If namespace packages is on, we crawl upwards until the nearest explicit base directory.
152 Failing that, we return one past the highest directory containing an __init__.py
153
154 We won't crawl past directories with invalid package names.

Calls

no outgoing calls

Used in the wild real call sites across dependent graphs

searching dependent graphs…