Skip to content

Commit 43b601a

Browse files
Read a function's Doxygen from its MEOS twin, in one order on every machine
doxygen_sources lists each tree it reads sorted, with every <name>_meos.c file before the other files of its tree. A function defined both in the file the PostgreSQL extension compiles and in the MEOS twin that replaces it in the MEOS build, as route_exists and route_geom are in meos/src/npoint/ways.c and ways_meos.c, is then documented by the twin MEOS compiles, and the brief, the parameter descriptions, the nullability and the output parameters every reader keeps from the first block it meets come from that block on every machine. Why. The list was in the order glob returns, which is the order the filesystem lists a directory in, so the brief of route_exists read "the ways cache" on one machine and "the edge table" on another from the same MobilityDB commit, and a consumer that generates from the catalog on one machine and checks it on another reads a difference neither its code nor MobilityDB causes: MobilityDB/MobilityAPI-Python#19 is the case. Measured. Over MobilityDB 93e1d279be the catalog this derives on a machine whose filesystem lists ways_meos.c first is the same as before, all 6625 functions; the GitHub runner, which listed ways.c first, read the edge-table briefs. Witness. tests/test_nullable.py::test_the_meos_twin_documents_a_function_defined_twice lists ways.c and ways_meos.c in both orders and reads the twin's brief for route_exists each time; with the previous order the listing that puts ways.c first reads the edge-table brief and the test fails. The suite passes with the MobilityDB sources present: 578 tests, 98 skipped.
1 parent 1c14d4f commit 43b601a

2 files changed

Lines changed: 35 additions & 4 deletions

File tree

‎parser/outparam.py‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,22 @@ def doxygen_sources(meos_root: str | Path) -> list[str]:
2828
``meos/`` and documents them on its ``.c`` definitions (mirrors doxygroup/run.py
2929
pgtypes). Every ``@param`` reader, here and in #extract_nullable, scans this one
3030
list, so a function documented in ``pgtypes/`` states its parameters to all of them
31-
alike."""
31+
alike.
32+
33+
The list is in one order on every machine: each tree sorted, with a ``<name>_meos.c``
34+
file before every other file of its tree. A function defined both in the file the
35+
PostgreSQL extension compiles (``ways.c``) and in its MEOS twin (``ways_meos.c``) is
36+
then documented by the twin MEOS compiles, and every reader keeping the first block
37+
it meets (#extract_briefs among them) reads that block."""
3238
root = Path(meos_root)
33-
files = glob.glob(str(root / "src/**/*.c"), recursive=True)
34-
files += glob.glob(str(root / "include/**/*.h"), recursive=True)
35-
files += glob.glob(str(root.parent / "pgtypes/**/*.c"), recursive=True)
39+
40+
def tree(pattern: str) -> list[str]:
41+
found = glob.glob(pattern, recursive=True)
42+
return sorted(found, key=lambda f: (not f.endswith("_meos.c"), f))
43+
44+
files = tree(str(root / "src/**/*.c"))
45+
files += tree(str(root / "include/**/*.h"))
46+
files += tree(str(root.parent / "pgtypes/**/*.c"))
3647
return files
3748

3849

‎tests/test_nullable.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
88
Plain unittest, no pytest dependency; writes a tiny synthetic source tree.
99
"""
10+
import glob
1011
import tempfile
1112
import unittest
1213
from pathlib import Path
14+
from unittest import mock
1315

1416
from parser.nullable import (attach_function_docs, extract_briefs, extract_nullable,
1517
extract_param_docs, merge_nullable)
@@ -106,6 +108,24 @@ def test_reads_the_tag_inside_the_param_entry(self):
106108
self.assertNotIn("create", nul["jsonb_set_lax"])
107109
self.assertNotIn("jb", nul["jsonb_set_lax"])
108110

111+
def test_the_meos_twin_documents_a_function_defined_twice(self):
112+
"""A function defined in the file the extension compiles and in its MEOS
113+
twin keeps the twin's brief, whichever file the filesystem lists first, as
114+
#test_briefs_read_the_brief_of_each_block reads the brief of one block."""
115+
src = Path(self.tmp.name) / "src"
116+
block = "/**\n * @brief {}\n */\nbool\nroute_exists(int64 rid)\n{{\n}}\n"
117+
(src / "ways.c").write_text(
118+
block.format("Return true if the edge table contains a route"))
119+
(src / "ways_meos.c").write_text(
120+
block.format("Return true if the ways cache contains a route"))
121+
real_glob = glob.glob
122+
for listed in (sorted, lambda files: sorted(files, reverse=True)):
123+
with self.subTest(listed=listed), mock.patch(
124+
"parser.outparam.glob.glob",
125+
lambda pattern, **kw: listed(real_glob(pattern, **kw))):
126+
self.assertEqual(extract_briefs(self.tmp.name)["route_exists"],
127+
"Return true if the ways cache contains a route")
128+
109129
def test_param_docs_leave_out_the_tag(self):
110130
"""The description #test_extracts_only_tagged_params reads, without the
111131
tag."""

0 commit comments

Comments
 (0)