research_helpers.prose

This module tracks every number a document states in prose and links it to the data that supports it, as well as auditing the prose for untracked numbers. See numbers in the prose.

research_helpers.prose.normalise_prose(text)[source]

Return a manuscript as the registry matches against it: comments removed, whitespace collapsed.

A sentence that has been commented out no longer counts as printed.

Return type:

str

Parameters:

text (str)

class research_helpers.prose.ProseNumber(key, template, values, source='', section='', document='paper')[source]

Bases: object

One fragment of a sentence as the document prints it, and how to compute its numbers.

‘template’ is the fragment with ‘{}’ where each number goes and doubled braces for literal ones, so ‘(Q_{{ov}} = {})’. Whitespace is immaterial: the fragment and the document are both compared with every run of whitespace collapsed to one space.

Parameters:
property placeholders: int

Return the count of numbers the template takes.

expected()[source]

Return the fragment with the numbers from the data.

Raises:

ValueError – if the values do not fill the template exactly.

Return type:

str

pattern()[source]

Return a pattern matching the fragment whatever numbers it carries.

Used to find what the document prints when it does not print what the data contains. A number is matched as a run without whitespace, so a sentence that now says something else entirely does not pass for the same sentence with different numbers.

Return type:

Pattern[str]

longest_literal()[source]

Return the longest stretch of fixed text, which must appear for the sentence to count as there.

Return type:

str

class research_helpers.prose.Mismatch(key, section, expected, printed)[source]

Bases: NamedTuple

A fragment the document does not print as is in the data.

Parameters:
  • key (str)

  • section (str)

  • expected (str)

  • printed (str | None)

key: str

Alias for field number 0

section: str

Alias for field number 1

expected: str

Alias for field number 2

printed: str | None

Alias for field number 3

class research_helpers.prose.ProseCheck(checked, stale, vanished, fixed, orphaned, failed, open_discrepancies)[source]

Bases: NamedTuple

What a check of the registry against its documents found.

Parameters:
checked: int

Alias for field number 0

stale: list[Mismatch]

Alias for field number 1

vanished: list[Mismatch]

Alias for field number 2

fixed: list[str]

Alias for field number 3

orphaned: list[str]

Alias for field number 4

failed: list[tuple[str, str]]

Alias for field number 5

open_discrepancies: int

Alias for field number 6

class research_helpers.prose.Occurrence(line, token, context, category, detail='', start=0)[source]

Bases: object

One numeric token in a document’s prose, and what accounts for it.

Parameters:
class research_helpers.prose.ProseRegistry(*, known_discrepancies=None, untraced=None, parameter_symbols=())[source]

Bases: object

The numbers a project’s documents state in prose, and their checks.

Parameters:
  • known_discrepancies (Mapping[str, str] | None)

  • untraced (Mapping[str, str] | None)

  • parameter_symbols (Collection[str])

add(*entries)[source]

Register entries built directly.

Raises:

ValueError – if a key is already registered.

Return type:

None

Parameters:

entries (ProseNumber)

register(key, template, *, source='', section='', document=PAPER_DOCUMENT)[source]

Register the decorated function that computes the numbers of a fragment.

Parameters:
  • key (str) – a short, unique name for the entry.

  • template (str) – the fragment as printed, ‘{}’ for each number.

  • source (str, default: '') – where the numbers come from.

  • section (str, default: '') – where the sentence is.

  • document (str, default: PAPER_DOCUMENT) – the document.

Return type:

Callable[[TypeVar(ValuesT, bound= Callable[[], Sequence[Any]])], TypeVar(ValuesT, bound= Callable[[], Sequence[Any]])]

Returns:

The decorator, which returns the function unchanged.

property documents: list[str]

Return the documents the entries name, in the order first named.

check(paths=None, *, document=None)[source]

Compare every entry against the document that prints it.

Parameters:
  • paths (Mapping[str, Path | str] | None, default: None) – document name to manuscript, for any document not to be taken from the project’s wiring.

  • document (str | None, default: None) – check only the entries this document prints.

Return type:

ProseCheck

Returns:

What was found or falsy when every entry holds.

Raises:
  • FileNotFoundError – if a manuscript does not exist, or a document is configured without one.

  • KeyError – if an entry names a document the project does not configure.

report(found)[source]

Return a description of what the check found.

Return type:

str

Parameters:

found (ProseCheck)

audit(document=PAPER_DOCUMENT, path=None)[source]

Classify every numeric token in a document’s prose.

Parameters:
  • document (str, default: PAPER_DOCUMENT) – target document.

  • path (Path | str | None, default: None) – its manuscript, if not to be taken from the project’s wiring.

Return type:

list[Occurrence]

Returns:

Every token, in document order.

Raises:

FileNotFoundError – if no ‘path’ is given and the document is configured without a manuscript.

main(argv=None)[source]

Run the prose command line.

Parameters:

argv (list[str] | None, default: None) – command line arguments, or None to read ‘sys.argv’.

Return type:

int

Returns:

A process exit status – 0 on success, 1 if the check found anything.

research_helpers.prose.audit(text, entries=(), *, tables_dir=None, parameter_symbols=())[source]

Classify every numeric token in a manuscript’s prose.

Each token falls in the first category that accounts for it:

  1. registered: it lies inside a fragment one of the entries describes.

  2. notation: it is a constant of an inline formula, or a parameter’s value in one that assigns a declared parameter symbol. Not a result.

  3. cited-float: it appears in a generated table the same paragraph cites, which carries it.

  4. other-float: it appears in a generated table the paragraph does not cite.

  5. untraced: none of the above. These are the numbers to pin.

Numbers in the preamble, comments, display math, citations, labels, references and the arguments of ‘input’ and ‘includegraphics’ are not prose and are skipped.

Parameters:
  • text (str) – the manuscript, as written.

  • entries (Sequence[ProseNumber], default: ()) – the registry entries for this manuscript.

  • tables_dir (Path | str | None, default: None) – where its generated tables are, named by label without the ‘tab:’ prefix.

  • parameter_symbols (Collection[str], default: ()) – see ‘ProseRegistry’.

Return type:

list[Occurrence]

Returns:

Every token, in document order.

research_helpers.prose.audit_report(occurrences, *, title='Prose-number audit')[source]

Render an audit as Markdown, untraced numbers first.

Parameters:
  • occurrences (Sequence[Occurrence]) – what ‘audit’ found.

  • title (str, default: 'Prose-number audit') – the heading.

Return type:

str

Returns:

The report.