163 lines
5.0 KiB
Python
163 lines
5.0 KiB
Python
from __future__ import annotations
|
|
|
|
import ast
|
|
from pathlib import Path
|
|
|
|
from mdpolish import Pipeline, RunStatus
|
|
from mdpolish.components import (
|
|
ArxivSubmissionStampComponent,
|
|
HtmlTableDoubleEscapeComponent,
|
|
HtmlTableLayoutComponent,
|
|
ManuscriptLineNumberComponent,
|
|
PageBreakWordJoinComponent,
|
|
ReferenceSpacingComponent,
|
|
RepeatedRunningHeaderComponent,
|
|
WordReviewCommentComponent,
|
|
)
|
|
|
|
STAMP = "arXiv:2104.12345v2 [stat.ME] 31 Dec 2021"
|
|
HEADER = "## Repeated Paper Header"
|
|
MAPPINGS = (
|
|
("medi-", "cal", "medical"),
|
|
("possi-", "bly", "possibly"),
|
|
("cre-", "ated", "created"),
|
|
("SOFA-", "based", "SOFA-based"),
|
|
("life-", "threatening", "life-threatening"),
|
|
("threshold.", "olds", "thresholds"),
|
|
)
|
|
|
|
|
|
def _build_pipeline() -> Pipeline:
|
|
return Pipeline(
|
|
[
|
|
WordReviewCommentComponent(),
|
|
ManuscriptLineNumberComponent(),
|
|
ArxivSubmissionStampComponent(),
|
|
RepeatedRunningHeaderComponent(),
|
|
PageBreakWordJoinComponent(MAPPINGS),
|
|
HtmlTableDoubleEscapeComponent(),
|
|
HtmlTableLayoutComponent(),
|
|
ReferenceSpacingComponent(),
|
|
]
|
|
)
|
|
|
|
|
|
def _numbered_manuscript() -> list[str]:
|
|
return [
|
|
f"## {number} Section {number}" if number in {5, 15} else f"{number} body {number}"
|
|
for number in range(1, 21)
|
|
]
|
|
|
|
|
|
def _combined_markdown() -> str:
|
|
return "\n".join(
|
|
(
|
|
"1 Affiliation",
|
|
"## Abstract",
|
|
*_numbered_manuscript(),
|
|
"Commented [A1]: remove this",
|
|
"",
|
|
STAMP,
|
|
"Sentence continues in",
|
|
"",
|
|
HEADER,
|
|
"",
|
|
"the next line.",
|
|
"A word is possi-",
|
|
"",
|
|
"bly split.",
|
|
"<table><tr><td>&lt;5</td></tr><tr><td>B</td></tr></table>",
|
|
"## References",
|
|
"",
|
|
"1. First",
|
|
"",
|
|
"2. Second",
|
|
"",
|
|
HEADER,
|
|
"",
|
|
"3. Third",
|
|
"4. Fourth",
|
|
)
|
|
)
|
|
|
|
|
|
def test_script_builds_frozen_component_order_and_parameters() -> None:
|
|
script_path = Path(__file__).parents[1] / "scripts" / "run_clindb_first_batch_experiment.py"
|
|
module = ast.parse(script_path.read_text(encoding="utf-8"))
|
|
build_function = next(
|
|
node for node in module.body if isinstance(node, ast.FunctionDef) and node.name == "build_pipeline"
|
|
)
|
|
component_names = [
|
|
call.func.id
|
|
for node in ast.walk(build_function)
|
|
if isinstance(node, ast.List)
|
|
for call in node.elts
|
|
if isinstance(call, ast.Call) and isinstance(call.func, ast.Name)
|
|
]
|
|
mapping_assignment = next(
|
|
node
|
|
for node in module.body
|
|
if isinstance(node, ast.Assign)
|
|
and any(isinstance(target, ast.Name) and target.id == "CLINDB_WORD_JOIN_MAPPINGS" for target in node.targets)
|
|
)
|
|
assert component_names == [
|
|
"WordReviewCommentComponent",
|
|
"ManuscriptLineNumberComponent",
|
|
"ArxivSubmissionStampComponent",
|
|
"RepeatedRunningHeaderComponent",
|
|
"PageBreakWordJoinComponent",
|
|
"HtmlTableDoubleEscapeComponent",
|
|
"HtmlTableLayoutComponent",
|
|
"ReferenceSpacingComponent",
|
|
]
|
|
assert ast.literal_eval(mapping_assignment.value) == MAPPINGS
|
|
|
|
pipeline = _build_pipeline()
|
|
result = pipeline.transform("")
|
|
|
|
assert [component.component_id for component in result.components] == [
|
|
"paper.word_review_comment",
|
|
"paper.manuscript_line_number",
|
|
"paper.arxiv_submission_stamp",
|
|
"paper.repeated_running_header",
|
|
"paper.page_break_word_join",
|
|
"markdown.html_table_double_escape",
|
|
"markdown.html_table_layout",
|
|
"paper.reference_spacing",
|
|
]
|
|
assert len(MAPPINGS) == 6
|
|
|
|
|
|
def test_full_pipeline_is_audited_stable_and_idempotent() -> None:
|
|
pipeline = _build_pipeline()
|
|
first = pipeline.transform(_combined_markdown())
|
|
|
|
assert first.status is RunStatus.SUCCESS
|
|
assert first.output_markdown is not None
|
|
assert first.residual_proposals == ()
|
|
counts: dict[str, int] = {}
|
|
for change in first.changes:
|
|
counts[change.component_id] = counts.get(change.component_id, 0) + 1
|
|
assert counts == {
|
|
"paper.word_review_comment": 1,
|
|
"paper.manuscript_line_number": 20,
|
|
"paper.arxiv_submission_stamp": 1,
|
|
"paper.repeated_running_header": 2,
|
|
"paper.page_break_word_join": 1,
|
|
"markdown.html_table_double_escape": 1,
|
|
"markdown.html_table_layout": 1,
|
|
"paper.reference_spacing": 1,
|
|
}
|
|
|
|
second = pipeline.transform(first.output_markdown)
|
|
assert second.status is RunStatus.SUCCESS
|
|
assert second.output_markdown == first.output_markdown
|
|
assert second.changes == ()
|
|
|
|
|
|
def test_business_components_are_not_exported_from_core_namespace() -> None:
|
|
import mdpolish
|
|
|
|
assert not hasattr(mdpolish, "WordReviewCommentComponent")
|
|
assert not hasattr(mdpolish, "HtmlTableLayoutComponent")
|