spacr.qt.help_index

Build and rank the index of everything in spaCR that is addressable by name.

The index backs the search field beside the Help menu, so a user who knows what a thing is called can reach it without knowing which module owns it or which collapsed heading it is filed under.

The index is not maintained by hand. Every row is derived from an existing source:

kind

where the rows come from

module

spacr.qt.app.APPS, the live app registry

setting

resolve_default_settings() and categories_for_app() per module, described by get_tooltips()

api

API_ENTRIES in spacr.qt.help_api_index, generated from the published API manifest

preference

PREFERENCE_ENTRIES, walked out of the source of the preferences dialog

A setting that cannot be found therefore points to a defect in a generator, not to a hand-written row that was never added.

A new kind is added by registering a provider, not by editing a switch. A provider is () -> Iterable[HelpEntry]; register_provider() adds one and build_index() calls each of them behind its own guard, so a provider that raises loses only its own rows. What a result does when it is opened is registered the same way, in spacr.qt.help_search.

Importing this module is cheap; building the index takes about a second. Every registry is imported inside the provider that reads it, so the module itself imports neither Qt nor spacr.settings. Building the index took 1.1 s and produced 13,000 rows on this tree, which is too slow for the GUI thread – spacr.qt.help_search runs build_index() on a worker and this module stays testable without a display.

Classes

HelpEntry

One addressable thing, and what it takes to get back to it.

Functions

api_entries(→ List[HelpEntry])

One entry per public API symbol, saying which settings it reads.

build_index(→ List[HelpEntry])

Run every provider and collect what they know.

module_entries(→ List[HelpEntry])

One entry per module in the live registry.

preference_entries(→ List[HelpEntry])

One entry per labelled row of the preferences dialog.

provider_names(→ Tuple[str, ...])

The registered providers, in registration order.

register_provider(→ None)

Add or replace a source of entries.

rendered_description(→ str)

An entry's description in the reader's language.

rendered_subtitle(→ str)

An entry's subtitle in the reader's language.

score(→ Optional[float])

The entry's score for a whole query, or None when a term misses.

search(→ List[HelpEntry])

The best matches for query, best first.

setting_entries(→ List[HelpEntry])

One entry per module a setting appears in, plus its API consumers.

Module Contents

class spacr.qt.help_index.HelpEntry[source]

One addressable thing, and what it takes to get back to it.

Variables:
  • kind – which provider produced it; also which opener knows what to do with it. One of KIND_ORDER, or a kind a caller registered.

  • title – the identifier a user would type – a setting key, a module name, a dotted API symbol, a preference label.

  • subtitle – where it lives. “in Mask ▸ Cell Segmentation” for a setting, “Preferences ▸ Animation” for a preference.

  • description – a plain-language description of what it does. It is matched on, which is what makes “touching” find merge_edge_pathogen_cells.

  • payload – what the opener needs and nothing more – an app key, a setting key, a dotted symbol, a tab object name.

  • subtitle_source – the English TEMPLATE subtitle was rendered from, when the words in it are this module’s own rather than a name taken from a registry. "" when there is nothing to translate.

  • subtitle_values – what to substitute into that template, as (name, value) pairs – a tuple, because the entry is frozen and hashable and a dict would be neither.

  • description_source – the same for description.

  • description_values – the same for description.

Templates are stored instead of finished strings. subtitle and description are what the search matches on, so they stay English: the query and the haystack must be in one language, and the index is built once per session while the interface language can change afterwards. The text shown to the user is rendered from the template when a row is drawn, by rendered_subtitle() and rendered_description() with spacr.qt.i18n.tr() passed in, so a language change takes effect at the next keystroke and this module imports neither Qt nor a catalog. “API reference” is the subtitle of about ten thousand rows; storing it as a finished English string would show those rows in English in every interface language.

property haystack: str[source]

Title, subtitle and description, lowercased, for matching.

spacr.qt.help_index.api_entries() → List[HelpEntry][source]

One entry per public API symbol, saying which settings it reads.

The settings half is what makes an API row findable by the name of a setting: searching cell_diameter offers the setting’s own row in each module that exposes it AND the entry of each function that takes it, which is what a setting query returns.

Returns:

kind="api" entries carrying {"symbol": dotted name}, and "reads" when the symbol consumes settings.

spacr.qt.help_index.build_index(names: Sequence[str] | None = None) → List[HelpEntry][source]

Run every provider and collect what they know.

Each provider is guarded on its own: a provider that raises (for example because the API manifest cannot be read) is logged and skipped, and the other kinds are still returned.

Parameters:

names – providers to run; all of them when None.

Returns:

every entry, in provider order.

spacr.qt.help_index.module_entries() → List[HelpEntry][source]

One entry per module in the live registry.

Returns:

kind="module" entries carrying {"app": key}.

spacr.qt.help_index.preference_entries() → List[HelpEntry][source]

One entry per labelled row of the preferences dialog.

Returns:

kind="preference" entries carrying {"tab", "label"}, where tab is the page’s object name.

spacr.qt.help_index.provider_names() → Tuple[str, ...][source]

The registered providers, in registration order.

spacr.qt.help_index.register_provider(name: str, provider: Provider) → None[source]

Add or replace a source of entries.

Parameters:
  • name – the provider’s name; registering the same name twice replaces the first, which is what lets a test swap a cheap provider in for an expensive one.

  • provider – () -> Iterable[HelpEntry].

spacr.qt.help_index.rendered_description(entry: HelpEntry, translate: Callable[..., str] | None = None) → str[source]

An entry’s description in the reader’s language.

An API summary inside it is a docstring and stays as it was written; what this translates is the sentence spaCR wraps around it.

Parameters:
Returns:

the line for the row’s tooltip.

spacr.qt.help_index.rendered_subtitle(entry: HelpEntry, translate: Callable[..., str] | None = None) → str[source]

An entry’s subtitle in the reader’s language.

Parameters:
Returns:

what the row should show under or beside the title.

spacr.qt.help_index.score(entry: HelpEntry, terms: Sequence[str]) → float | None[source]

The entry’s score for a whole query, or None when a term misses.

Terms are ANDed, the same rule the per-module settings search uses, so each additional word narrows the results.

Parameters:
  • entry – the candidate.

  • terms – lowercased query terms.

Returns:

the summed score plus the kind tiebreak, or None.

spacr.qt.help_index.search(index: Sequence[HelpEntry], query: str, limit: int = 40, per_kind: int | None = PER_KIND_LIMIT) → List[HelpEntry][source]

The best matches for query, best first.

Parameters:
  • index – what build_index() returned.

  • query – raw text from the search box.

  • limit – how many rows to return in total.

  • per_kind – how many rows of one kind may be returned; None lifts the cap, which is what a test asking “is it in there at all” wants.

Returns:

matching entries, highest score first; ties are broken by kind and then by title, so the same query always lists the same way.

spacr.qt.help_index.setting_entries() → List[HelpEntry][source]

One entry per module a setting appears in, plus its API consumers.

One row per module: a setting in four modules gives four rows, each naming its module and the category it sits under, so the module can be chosen from the list without a second click.

API rows for a setting are not emitted here. SETTING_CONSUMERS names every addressable function that reads a key, and api_entries() folds that into the API row for each of those functions – one row per symbol, saying which settings it reads. Emitting them from both providers would list a function such as spacr.io.preprocess_img_data once for itself and once for every setting it reads (eleven identical rows in one result list).

Returns:

kind="setting" entries carrying {"app", "key", "category"}.