From 71906c4bf842bfa9ea65893ae9e3ddb2b61b0440 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Sat, 5 Jun 2021 21:29:18 +0200 Subject: typing: Fully annotate dependencies.cmake --- mesonbuild/dependencies/cmake.py | 128 +++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 59 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 3b332b9..0ce8dbd 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -27,19 +27,25 @@ import typing as T if T.TYPE_CHECKING: from ..environment import Environment - from ..mesonlib import MachineInfo + from ..envconfig import MachineInfo + +class CMakeInfo(T.NamedTuple): + module_paths: T.List[str] + cmake_root: str + archs: T.List[str] + common_paths: T.List[str] class CMakeDependency(ExternalDependency): # The class's copy of the CMake path. Avoids having to search for it # multiple times in the same Meson invocation. - class_cmakeinfo = PerMachine(None, None) + class_cmakeinfo: PerMachine[T.Optional[CMakeInfo]] = PerMachine(None, None) # Version string for the minimum CMake version class_cmake_version = '>=3.4' # CMake generators to try (empty for no generator) class_cmake_generators = ['', 'Ninja', 'Unix Makefiles', 'Visual Studio 10 2010'] - class_working_generator = None + class_working_generator: T.Optional[str] = None - def _gen_exception(self, msg): + def _gen_exception(self, msg: str) -> DependencyException: return DependencyException(f'Dependency {self.name} not found: {msg}') def _main_cmake_file(self) -> str: @@ -70,7 +76,7 @@ class CMakeDependency(ExternalDependency): # one module return module - def __init__(self, name: str, environment: 'Environment', kwargs, language: T.Optional[str] = None): + def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None: # Gather a list of all languages to support self.language_list = [] # type: T.List[str] if language is None: @@ -97,18 +103,18 @@ class CMakeDependency(ExternalDependency): self.is_libtool = False # Store a copy of the CMake path on the object itself so it is # stored in the pickled coredata and recovered. - self.cmakebin = None - self.cmakeinfo = None + self.cmakebin: T.Optional[CMakeExecutor] = None + self.cmakeinfo: T.Optional[CMakeInfo] = None # Where all CMake "build dirs" are located self.cmake_root_dir = environment.scratch_dir # T.List of successfully found modules - self.found_modules = [] + self.found_modules: T.List[str] = [] # Initialize with None before the first return to avoid # AttributeError exceptions in derived classes - self.traceparser = None # type: CMakeTraceParser + self.traceparser: T.Optional[CMakeTraceParser] = None # TODO further evaluate always using MachineChoice.BUILD self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent) @@ -146,14 +152,11 @@ class CMakeDependency(ExternalDependency): return self._detect_dep(name, package_version, modules, components, cm_args) - def __repr__(self): - s = '<{0} {1}: {2} {3}>' - return s.format(self.__class__.__name__, self.name, self.is_found, - self.version_reqs) + def __repr__(self) -> str: + return f'<{self.__class__.__name__} {self.name}: {self.is_found} {self.version_reqs}>' - def _get_cmake_info(self, cm_args): + def _get_cmake_info(self, cm_args: T.List[str]) -> T.Optional[CMakeInfo]: mlog.debug("Extracting basic cmake information") - res = {} # Try different CMake generators since specifying no generator may fail # in cygwin for some reason @@ -199,52 +202,52 @@ class CMakeDependency(ExternalDependency): def process_paths(l: T.List[str]) -> T.Set[str]: if is_windows(): # Cannot split on ':' on Windows because its in the drive letter - l = [x.split(os.pathsep) for x in l] + tmp = [x.split(os.pathsep) for x in l] else: # https://github.com/mesonbuild/meson/issues/7294 - l = [re.split(r':|;', x) for x in l] - l = [x for sublist in l for x in sublist] - return set(l) + tmp = [re.split(r':|;', x) for x in l] + flattened = [x for sublist in tmp for x in sublist] + return set(flattened) # Extract the variables and sanity check them - root_paths = process_paths(temp_parser.get_cmake_var('MESON_FIND_ROOT_PATH')) - root_paths.update(process_paths(temp_parser.get_cmake_var('MESON_CMAKE_SYSROOT'))) - root_paths = sorted(root_paths) - root_paths = list(filter(lambda x: os.path.isdir(x), root_paths)) - module_paths = process_paths(temp_parser.get_cmake_var('MESON_PATHS_LIST')) - rooted_paths = [] + root_paths_set = process_paths(temp_parser.get_cmake_var('MESON_FIND_ROOT_PATH')) + root_paths_set.update(process_paths(temp_parser.get_cmake_var('MESON_CMAKE_SYSROOT'))) + root_paths = sorted(root_paths_set) + root_paths = [x for x in root_paths if os.path.isdir(x)] + module_paths_set = process_paths(temp_parser.get_cmake_var('MESON_PATHS_LIST')) + rooted_paths: T.List[str] = [] for j in [Path(x) for x in root_paths]: - for i in [Path(x) for x in module_paths]: - rooted_paths.append(str(j / i.relative_to(i.anchor))) - module_paths = sorted(module_paths.union(rooted_paths)) - module_paths = list(filter(lambda x: os.path.isdir(x), module_paths)) + for p in [Path(x) for x in module_paths_set]: + rooted_paths.append(str(j / p.relative_to(p.anchor))) + module_paths = sorted(module_paths_set.union(rooted_paths)) + module_paths = [x for x in module_paths if os.path.isdir(x)] archs = temp_parser.get_cmake_var('MESON_ARCH_LIST') common_paths = ['lib', 'lib32', 'lib64', 'libx32', 'share'] for i in archs: common_paths += [os.path.join('lib', i)] - res = { - 'module_paths': module_paths, - 'cmake_root': temp_parser.get_cmake_var('MESON_CMAKE_ROOT')[0], - 'archs': archs, - 'common_paths': common_paths - } + res = CMakeInfo( + module_paths=module_paths, + cmake_root=temp_parser.get_cmake_var('MESON_CMAKE_ROOT')[0], + archs=archs, + common_paths=common_paths, + ) - mlog.debug(' -- Module search paths: {}'.format(res['module_paths'])) - mlog.debug(' -- CMake root: {}'.format(res['cmake_root'])) - mlog.debug(' -- CMake architectures: {}'.format(res['archs'])) - mlog.debug(' -- CMake lib search paths: {}'.format(res['common_paths'])) + mlog.debug(f' -- Module search paths: {res.module_paths}') + mlog.debug(f' -- CMake root: {res.cmake_root}') + mlog.debug(f' -- CMake architectures: {res.archs}') + mlog.debug(f' -- CMake lib search paths: {res.common_paths}') return res @staticmethod @functools.lru_cache(maxsize=None) - def _cached_listdir(path: str) -> T.Tuple[T.Tuple[str, str]]: + def _cached_listdir(path: str) -> T.Tuple[T.Tuple[str, str], ...]: try: return tuple((x, str(x).lower()) for x in os.listdir(path)) except OSError: - return () + return tuple() @staticmethod @functools.lru_cache(maxsize=None) @@ -273,7 +276,7 @@ class CMakeDependency(ExternalDependency): # Search in /(lib/|lib*|share) for cmake files def search_lib_dirs(path: str) -> bool: - for i in [os.path.join(path, x) for x in self.cmakeinfo['common_paths']]: + for i in [os.path.join(path, x) for x in self.cmakeinfo.common_paths]: if not self._cached_isdir(i): continue @@ -281,7 +284,7 @@ class CMakeDependency(ExternalDependency): cm_dir = os.path.join(i, 'cmake') if self._cached_isdir(cm_dir): content = self._cached_listdir(cm_dir) - content = list(filter(lambda x: x[1].startswith(lname), content)) + content = tuple(x for x in content if x[1].startswith(lname)) for k in content: if find_module(os.path.join(cm_dir, k[0])): return True @@ -289,7 +292,7 @@ class CMakeDependency(ExternalDependency): # /(lib/|lib*|share)/*/ # /(lib/|lib*|share)/*/(cmake|CMake)/ content = self._cached_listdir(i) - content = list(filter(lambda x: x[1].startswith(lname), content)) + content = tuple(x for x in content if x[1].startswith(lname)) for k in content: if find_module(os.path.join(i, k[0])): return True @@ -297,7 +300,7 @@ class CMakeDependency(ExternalDependency): return False # Check the user provided and system module paths - for i in module_path + [os.path.join(self.cmakeinfo['cmake_root'], 'Modules')]: + for i in module_path + [os.path.join(self.cmakeinfo.cmake_root, 'Modules')]: if find_module(i): return True @@ -316,7 +319,7 @@ class CMakeDependency(ExternalDependency): system_env += [i] # Check the system paths - for i in self.cmakeinfo['module_paths'] + system_env: + for i in self.cmakeinfo.module_paths + system_env: if find_module(i): return True @@ -324,17 +327,18 @@ class CMakeDependency(ExternalDependency): return True content = self._cached_listdir(i) - content = list(filter(lambda x: x[1].startswith(lname), content)) + content = tuple(x for x in content if x[1].startswith(lname)) for k in content: if search_lib_dirs(os.path.join(i, k[0])): return True # Mac framework support if machine.is_darwin(): - for j in ['{}.framework', '{}.app']: - j = j.format(lname) - if j in content: - if find_module(os.path.join(i, j[0], 'Resources')) or find_module(os.path.join(i, j[0], 'Version')): + for j in [f'{lname}.framework', f'{lname}.app']: + for k in content: + if k[1] != j: + continue + if find_module(os.path.join(i, k[0], 'Resources')) or find_module(os.path.join(i, k[0], 'Version')): return True # Check the environment path @@ -344,7 +348,7 @@ class CMakeDependency(ExternalDependency): return False - def _detect_dep(self, name: str, package_version: str, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]], args: T.List[str]): + def _detect_dep(self, name: str, package_version: str, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]], args: T.List[str]) -> None: # Detect a dependency with CMake using the '--find-package' mode # and the trace output (stderr) # @@ -373,7 +377,7 @@ class CMakeDependency(ExternalDependency): # Prepare options cmake_opts = [] cmake_opts += [f'-DNAME={name}'] - cmake_opts += ['-DARCHS={}'.format(';'.join(self.cmakeinfo['archs']))] + cmake_opts += ['-DARCHS={}'.format(';'.join(self.cmakeinfo.archs))] cmake_opts += [f'-DVERSION={package_version}'] cmake_opts += ['-DCOMPS={}'.format(';'.join([x[0] for x in comp_mapped]))] cmake_opts += args @@ -402,14 +406,14 @@ class CMakeDependency(ExternalDependency): try: self.traceparser.parse(err1) except CMakeException as e: - e = self._gen_exception(str(e)) + e2 = self._gen_exception(str(e)) if self.required: raise else: self.compile_args = [] self.link_args = [] self.is_found = False - self.reason = e + self.reason = e2 return # Whether the package is found or not is always stored in PACKAGE_FOUND @@ -515,7 +519,10 @@ class CMakeDependency(ExternalDependency): if self.env.coredata.options[OptionKey('b_vscrt')].value in {'mdd', 'mtd'}: is_debug = True else: - is_debug = self.env.coredata.get_option(OptionKey('debug')) + # Don't directly assign to is_debug to make mypy happy + debug_opt = self.env.coredata.get_option(OptionKey('debug')) + assert isinstance(debug_opt, bool) + is_debug = debug_opt if is_debug: if 'DEBUG' in cfgs: cfg = 'DEBUG' @@ -618,15 +625,18 @@ class CMakeDependency(ExternalDependency): return build_dir - def _call_cmake(self, args, cmake_file: str, env=None): + def _call_cmake(self, + args: T.List[str], + cmake_file: str, + env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, T.Optional[str], T.Optional[str]]: build_dir = self._setup_cmake_dir(cmake_file) return self.cmakebin.call(args, build_dir, env=env) @staticmethod - def get_methods(): + def get_methods() -> T.List[DependencyMethods]: return [DependencyMethods.CMAKE] - def log_tried(self): + def log_tried(self) -> str: return self.type_name def log_details(self) -> str: -- cgit v1.1