Skip to content

Commit 201dba6

Browse files
committed
enable excluding files
1 parent fba8efa commit 201dba6

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ fortran_sources = [
3838
"../example/*.f90", # glob pattern
3939
]
4040

41+
# Exclude sources from parsing (directories, files, or glob patterns)
42+
fortran_sources_exclude = [
43+
"../example/legacy", # directory
44+
"../example/skip_this.f90", # file
45+
"../example/**/generated_*.f90", # glob
46+
]
47+
4148
# Select a lexer (built-in: "regex")
4249
fortran_lexer = "regex"
4350

src/sphinx_fortran_domain/__init__.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ def _doc_markers_from_config(app: Sphinx) -> List[str]:
158158
def _collect_fortran_files(app: Sphinx) -> List[str]:
159159
exts = {e.lower() for e in _as_list(getattr(app.config, "fortran_file_extensions", []))}
160160
roots = _as_list(getattr(app.config, "fortran_sources", []))
161+
excludes = _as_list(getattr(app.config, "fortran_sources_exclude", []))
161162
if not roots:
162163
return []
163164

@@ -183,6 +184,43 @@ def _collect_fortran_files(app: Sphinx) -> List[str]:
183184
if not exts or p.suffix.lower() in exts:
184185
files.append(str(p))
185186

187+
if excludes:
188+
def _norm(s: str) -> str:
189+
try:
190+
return os.path.normcase(str(Path(s).resolve()))
191+
except Exception:
192+
return os.path.normcase(str(Path(s)))
193+
194+
exclude_files: set[str] = set()
195+
confdir = Path(app.confdir)
196+
for raw in excludes:
197+
pat = str(raw)
198+
# Glob patterns
199+
if any(ch in pat for ch in "*?["):
200+
pattern = str(confdir / pat)
201+
for match in glob.glob(pattern, recursive=True):
202+
p = Path(match)
203+
if p.is_dir():
204+
for child in p.rglob("*"):
205+
if child.is_file() and (not exts or child.suffix.lower() in exts):
206+
exclude_files.add(_norm(str(child)))
207+
elif p.is_file() and (not exts or p.suffix.lower() in exts):
208+
exclude_files.add(_norm(str(p)))
209+
continue
210+
211+
p = Path(pat)
212+
if not p.is_absolute():
213+
p = confdir / p
214+
if p.is_dir():
215+
for child in p.rglob("*"):
216+
if child.is_file() and (not exts or child.suffix.lower() in exts):
217+
exclude_files.add(_norm(str(child)))
218+
elif p.is_file() and (not exts or p.suffix.lower() in exts):
219+
exclude_files.add(_norm(str(p)))
220+
221+
if exclude_files:
222+
files = [f for f in files if _norm(f) not in exclude_files]
223+
186224
# Deterministic order
187225
return sorted(set(files))
188226

@@ -224,6 +262,7 @@ def setup(app: Sphinx):
224262
app.add_domain(FortranDomain)
225263

226264
app.add_config_value("fortran_sources", default=[], rebuild="env")
265+
app.add_config_value("fortran_sources_exclude", default=[], rebuild="env")
227266
app.add_config_value("fortran_lexer", default="regex", rebuild="env")
228267
app.add_config_value("fortran_doc_chars", default=[">"], rebuild="env")
229268
app.add_config_value(

src/sphinx_fortran_domain/directives.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def _collect_fortran_files_from_env(env) -> list[str]:
6565
confdir = Path(getattr(app, "confdir", os.getcwd()))
6666
config = getattr(app, "config", None)
6767
roots = _as_list(getattr(config, "fortran_sources", []))
68+
excludes = _as_list(getattr(config, "fortran_sources_exclude", []))
6869
exts = {e.lower() for e in _as_list(getattr(config, "fortran_file_extensions", []))}
6970
if not roots:
7071
return []
@@ -91,6 +92,41 @@ def _collect_fortran_files_from_env(env) -> list[str]:
9192
if p.is_file() and (not exts or p.suffix.lower() in exts):
9293
files.append(str(p))
9394

95+
if excludes:
96+
def _norm(s: str) -> str:
97+
try:
98+
return os.path.normcase(str(Path(s).resolve()))
99+
except Exception:
100+
return os.path.normcase(str(Path(s)))
101+
102+
exclude_files: set[str] = set()
103+
for raw in excludes:
104+
pat = str(raw)
105+
if any(ch in pat for ch in "*?["):
106+
pattern = str(confdir / pat)
107+
for match in glob.glob(pattern, recursive=True):
108+
p = Path(match)
109+
if p.is_dir():
110+
for child in p.rglob("*"):
111+
if child.is_file() and (not exts or child.suffix.lower() in exts):
112+
exclude_files.add(_norm(str(child)))
113+
elif p.is_file() and (not exts or p.suffix.lower() in exts):
114+
exclude_files.add(_norm(str(p)))
115+
continue
116+
117+
p = Path(pat)
118+
if not p.is_absolute():
119+
p = confdir / p
120+
if p.is_dir():
121+
for child in p.rglob("*"):
122+
if child.is_file() and (not exts or child.suffix.lower() in exts):
123+
exclude_files.add(_norm(str(child)))
124+
elif p.is_file() and (not exts or p.suffix.lower() in exts):
125+
exclude_files.add(_norm(str(p)))
126+
127+
if exclude_files:
128+
files = [f for f in files if _norm(f) not in exclude_files]
129+
94130
# Deterministic order
95131
return sorted(set(files))
96132

tests/test_sources_exclude.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from __future__ import annotations
2+
3+
from types import SimpleNamespace
4+
5+
6+
class _DummyApp:
7+
def __init__(self, *, confdir: str, config) -> None:
8+
self.confdir = confdir
9+
self.config = config
10+
11+
12+
def test_fortran_sources_exclude_file_dir_and_glob(tmp_path) -> None:
13+
# Layout under the Sphinx confdir
14+
src = tmp_path / "src"
15+
sub = src / "sub"
16+
src.mkdir()
17+
sub.mkdir()
18+
19+
(src / "a.f90").write_text("module a\nend module a\n", encoding="utf-8")
20+
(src / "b.f90").write_text("module b\nend module b\n", encoding="utf-8")
21+
(src / "skip_me.f90").write_text("module s\nend module s\n", encoding="utf-8")
22+
(sub / "c.f90").write_text("module c\nend module c\n", encoding="utf-8")
23+
24+
config = SimpleNamespace(
25+
fortran_sources=["src"],
26+
fortran_sources_exclude=[
27+
"src/b.f90", # exclude individual file
28+
"src/sub", # exclude directory
29+
"src/*skip*.f90", # exclude via glob
30+
],
31+
fortran_file_extensions=[".f90"],
32+
)
33+
app = _DummyApp(confdir=str(tmp_path), config=config)
34+
35+
from sphinx_fortran_domain import _collect_fortran_files
36+
37+
files = _collect_fortran_files(app)
38+
39+
# Only a.f90 should remain.
40+
assert len(files) == 1
41+
assert files[0].replace("\\", "/").endswith("/src/a.f90")

0 commit comments

Comments
 (0)