From d4308379abf1eded23aef13e8b0d48d2c8e66811 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 30 Oct 2023 10:15:58 +0000 Subject: [PATCH 1/5] Fix type hint on `ProgressBar` --- ford/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ford/utils.py b/ford/utils.py index 958cb122..f9c85eee 100644 --- a/ford/utils.py +++ b/ford/utils.py @@ -26,7 +26,7 @@ import os.path import pathlib from types import TracebackType -from typing import Dict, Union, List, Any, Tuple, Optional, Sequence, cast, Sized, Type +from typing import Dict, Union, List, Any, Tuple, Optional, Iterable, cast, Sized, Type from io import StringIO import itertools from collections import defaultdict @@ -293,7 +293,7 @@ class ProgressBar: def __init__( self, description: str, - iterable: Optional[Sequence] = None, + iterable: Optional[Iterable] = None, total: Optional[int] = None, ): if total is None and hasattr(iterable, "__len__"): From 5464f2034bdbd990ba1e0d5793f1290741d1baa1 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 30 Oct 2023 10:18:05 +0000 Subject: [PATCH 2/5] Workaround for rich `Progress` breaking debuggers --- ford/utils.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ford/utils.py b/ford/utils.py index f9c85eee..c28b2ecf 100644 --- a/ford/utils.py +++ b/ford/utils.py @@ -23,6 +23,7 @@ # import re +import os import os.path import pathlib from types import TracebackType @@ -301,6 +302,13 @@ def __init__( else: self._total = total + # rich `Progress` breaks `pdb` and `breakpoint`, see: + # - https://github.com/Textualize/rich/issues/1053 + # - https://github.com/Textualize/rich/issues/1465 + # and maintainer seems uninterested in fixing. So, workaround + # by setting an env var to disable progress bar entirely + disable: bool = bool(os.environ.get("FORD_DEBUGGING", False)) + self._iterable = iterable self._progress = Progress( SpinnerColumn(), @@ -312,6 +320,7 @@ def __init__( TimeElapsedColumn(), TextColumn("{task.fields[current]}"), console=console, + disable=disable, ) self._progress.start() From fe4f6a150f346f0ae719afd2773a2c7fa009bf1e Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 30 Oct 2023 10:37:18 +0000 Subject: [PATCH 3/5] Fix unhelpful crash when ancestor module missing Now prints a more helpful error message Fixes #577 --- ford/fortran_project.py | 20 ++++++++++++-------- ford/sourceform.py | 1 + 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ford/fortran_project.py b/ford/fortran_project.py index 7e76bd09..2104ca84 100755 --- a/ford/fortran_project.py +++ b/ford/fortran_project.py @@ -238,10 +238,6 @@ def namelist_check(entity): self.files.append(new_file) - def warn(self, message): - if self.settings.warn: - warn(f"{message}") - @property def allfiles(self): """Instead of duplicating files, it is much more efficient to create the itterator on the fly""" @@ -298,14 +294,22 @@ def filter_modules(entity) -> List[FortranModule]: for mod in self.submodules: if type(mod.ancestor_module) is not FortranModule: - self.warn( - f"Could not identify ancestor MODULE of SUBMODULE '{mod.name}'. " + print("\n") + warn( + f"Could not identify ancestor module ('{mod.ancestor_module}') of submodule '{mod.name}' " + f"(in '{mod.filename}').\n" + f" This is usually because Ford hasn't found '{mod.ancestor_module}' " + "in any of the source directories.\n" ) continue if not isinstance(mod.parent_submodule, (FortranSubmodule, type(None))): - self.warn( - f"Could not identify parent SUBMODULE of SUBMODULE '{mod.name}'" + print("\n") + warn( + f"Could not identify parent submodule ('{mod.parent_submodule}') of submodule '{mod.name}' " + f"(in '{mod.filename}').\n" + f" This is usually because Ford hasn't found '{mod.parent_submodule}' " + "in any of the source directories.\n" ) mod.deplist = [ diff --git a/ford/sourceform.py b/ford/sourceform.py index 1d85c9f5..26b31d26 100644 --- a/ford/sourceform.py +++ b/ford/sourceform.py @@ -1584,6 +1584,7 @@ def _initialize(self, line: re.Match) -> None: self.private_list: List[str] = [] self.protected_list: List[str] = [] self.visible = True + self.deplist: List[FortranModule] = [] def _cleanup(self): """Create list of all local procedures. Ones coming from other modules From b890f12c5eb40e986b292d0d2dbe58aa4283eeff Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 30 Oct 2023 10:50:31 +0000 Subject: [PATCH 4/5] Fix for printing warnings during correlate step messing up info --- ford/__init__.py | 4 ++-- ford/fortran_project.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/ford/__init__.py b/ford/__init__.py index 2aa2f778..819a39b6 100755 --- a/ford/__init__.py +++ b/ford/__init__.py @@ -414,11 +414,11 @@ def main(proj_data: ProjectSettings, proj_docs: str): base_url = ".." if proj_data.relative else proj_data.project_url - print(" Correlating information from different parts of your project...", end="") + print(" Correlating information from different parts of your project...") correlate_time_start = time.time() project.correlate() correlate_time_end = time.time() - print(f" done in {correlate_time_end - correlate_time_start:5.3f}s") + print(f" ...done in {correlate_time_end - correlate_time_start:5.3f}s") # Setup Markdown object with any user-specified extensions aliases = copy.copy(proj_data.alias) diff --git a/ford/fortran_project.py b/ford/fortran_project.py index 2104ca84..85153e56 100755 --- a/ford/fortran_project.py +++ b/ford/fortran_project.py @@ -294,7 +294,6 @@ def filter_modules(entity) -> List[FortranModule]: for mod in self.submodules: if type(mod.ancestor_module) is not FortranModule: - print("\n") warn( f"Could not identify ancestor module ('{mod.ancestor_module}') of submodule '{mod.name}' " f"(in '{mod.filename}').\n" @@ -304,7 +303,6 @@ def filter_modules(entity) -> List[FortranModule]: continue if not isinstance(mod.parent_submodule, (FortranSubmodule, type(None))): - print("\n") warn( f"Could not identify parent submodule ('{mod.parent_submodule}') of submodule '{mod.name}' " f"(in '{mod.filename}').\n" From 26f51f37ac05f63be3d7bdaf00577fe74d0726e2 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 30 Oct 2023 10:55:58 +0000 Subject: [PATCH 5/5] Add warning if base type of extended derived type not found Also don't crash when tracing procedure call chains Fixes #577 --- ford/sourceform.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ford/sourceform.py b/ford/sourceform.py index 26b31d26..35c5ca1e 100644 --- a/ford/sourceform.py +++ b/ford/sourceform.py @@ -1450,6 +1450,8 @@ def get_label_item(context, label): # extended type extend_type = context while extend_type := getattr(extend_type, "extends", None): + if isinstance(extend_type, str): + break labels[extend_type.name.lower()] = extend_type # vars labels.update(getattr(context, "all_vars", {})) @@ -1983,6 +1985,16 @@ def correlate(self, project): # Match variables as needed (recurse) for v in self.variables: v.correlate(project) + + if self.extends and isinstance(self.extends, str): + warn( + f"Could not find base type ('{self.extends}') of derived type '{self.name}' " + f"(in '{self.filename}').\n" + f" If '{self.extends}' is defined in an external module, you may be " + "able to tell Ford about its documentation\n" + " with the `extra_mods` setting" + ) + # Get inherited public components inherited = [ var