2929 Tuple ,
3030 Union ,
3131)
32+
3233from typing_extensions import TypeAlias as _TypeAlias
3334
3435from mypy import defaults
@@ -229,6 +230,28 @@ def split_commas(value: str) -> list[str]:
229230)
230231
231232
233+ def _find_pyproject () -> list [str ]:
234+ """Search for file pyproject.toml in the parent directories recursively.
235+
236+ It resolves symlinks, so if there is any symlink up in the tree, it does not respect them
237+ """
238+ # We start from the parent dir, since 'pyproject.toml' is already parsed
239+ current_dir = os .path .abspath (os .path .join (os .path .curdir , os .path .pardir ))
240+ is_root = False
241+ while not is_root :
242+ for pyproject_name in defaults .PYPROJECT_CONFIG_FILES :
243+ config_file = os .path .join (current_dir , pyproject_name )
244+ if os .path .isfile (config_file ):
245+ return [os .path .abspath (config_file )]
246+ parent = os .path .abspath (os .path .join (current_dir , os .path .pardir ))
247+ is_root = current_dir == parent or any (
248+ os .path .isdir (os .path .join (current_dir , cvs_root )) for cvs_root in (".git" , ".hg" )
249+ )
250+ current_dir = parent
251+
252+ return []
253+
254+
232255def parse_config_file (
233256 options : Options ,
234257 set_strict_flags : Callable [[], None ],
@@ -248,7 +271,9 @@ def parse_config_file(
248271 if filename is not None :
249272 config_files : tuple [str , ...] = (filename ,)
250273 else :
251- config_files_iter : Iterable [str ] = map (os .path .expanduser , defaults .CONFIG_FILES )
274+ config_files_iter : Iterable [str ] = map (
275+ os .path .expanduser , defaults .CONFIG_FILES + _find_pyproject ()
276+ )
252277 config_files = tuple (config_files_iter )
253278
254279 config_parser = configparser .RawConfigParser ()
0 commit comments