spacr.qt.ask_for_the_path

Ask the user for a folder or database column that path resolution missed.

These dialogs are fallbacks. The ordinary resolution runs first every time, and a dialog is shown only after it has failed, so a run whose paths resolve normally never shows one.

Without a dialog, each of these cases stops with a message naming the missing item, and that item is information the user has and the program does not. A dialog asks for it instead, at the cost of one prompt rather than one aborted run.

Every prompt follows these rules, which this module enforces for its callers:

  • it states what was tried first, so a typo in a setting can be told apart from a missing folder;

  • it validates the answer before accepting it – a chosen folder with nothing in it would fail one step later;

  • it asks once per run, not once per image, per well or per plate;

  • it returns a sentence naming the value that will be used, for the caller to write back and report;

  • it can be cancelled: cancelling stops the run with the original error;

  • it is never shown without a user present. In a script, a test or a batch run somebody_is_there() returns False and the original error is returned instead of a dialog that would block the run. This check runs before anything else.

Functions

a_folder_holding(→ Callable[[str], Optional[str]])

A validator: the folder must hold at least one file with a suffix.

ask_for_a_database_column(→ Tuple[Optional[Tuple[str, ...)

Ask for a database, a table within it, and a column within that.

ask_for_a_folder(→ Tuple[Optional[str], str])

Ask for a folder after the usual resolution has failed.

columns_in(→ list)

Every column of one table, in the order the table declares them.

forget(→ None)

Drop every remembered answer. For tests, and for a new run.

remembered(→ Optional[str])

What was already answered for key, if anything.

somebody_is_there(→ bool)

Whether there is a person who could answer a dialog.

tables_in(→ list)

Every table in a SQLite file, or an empty list if it is not one.

Module Contents

spacr.qt.ask_for_the_path.a_folder_holding(*suffixes: str) → Callable[[str], str | None][source]

A validator: the folder must hold at least one file with a suffix.

A chosen folder without such a file would fail one step later, so it is rejected before it is accepted.

spacr.qt.ask_for_the_path.ask_for_a_database_column(key: str, *, tried: str, what: str = 'Coordinate column', parent=None, chooser: Callable[..., str] | None = None, pick: Callable[..., str | None] | None = None) → Tuple[Tuple[str, str, str] | None, str][source]

Ask for a database, a table within it, and a column within that.

The coordinate stream needs all three. They are asked one at a time so that the tables offered are the ones the chosen database holds, and the columns offered are the ones that table holds; the user never has to type a name the program can read.

Parameters:
  • key – what is being asked for; the answer is remembered under it.

  • tried – what was tried and did not work, shown in each title.

  • chooser – injected for tests; defaults to a real file dialog.

  • pick – injected for tests; defaults to a real list dialog. Called (title, prompt, options) and returns the choice or None.

Returns:

((database, table, column), why), or (None, why). why names the value used, or the reason for None: no user present to answer, or the file dialog cancelled. A database with no tables, a table with no columns or a cancelled list choice asks again rather than returning.

Backing out of a later step returns to the earlier one rather than abandoning the whole form, so choosing the wrong database costs one click instead of the run.

spacr.qt.ask_for_the_path.ask_for_a_folder(key: str, *, tried: str, what: str, validate: Callable[[str], str | None] | None = None, parent=None, chooser: Callable[..., str] | None = None) → Tuple[str | None, str][source]

Ask for a folder after the usual resolution has failed.

Parameters:
  • key – what is being asked for. The answer is remembered under it, so the second image of a run does not ask again.

  • tried – what was tried and did not work, said before the chooser so the user knows why they are being asked.

  • what – a short name for the thing wanted, for the dialog title.

  • validate – given a chosen path, returns None when it is usable or a sentence saying why it is not. The dialog stays open on a refusal.

  • chooser – injected for tests. Defaults to a real folder dialog.

Returns:

(path, why). path is None when nobody answered, when the user cancelled, or when there is nobody there – and why always says which, because those are three different situations.

spacr.qt.ask_for_the_path.columns_in(database: str, table: str) → list[source]

Every column of one table, in the order the table declares them.

PRAGMA takes no bound parameters, so the table name is quoted here. SQLite escapes a quote inside a quoted identifier by doubling it, and a table really can be named cell"s – unescaped, the identifier ends early and the whole table reads as having no columns at all.

Parameters:
  • database – path to the SQLite file, opened read-only; any failure yields an empty list.

  • table – name of the table whose columns are listed; embedded double quotes are escaped before it is quoted into the PRAGMA.

spacr.qt.ask_for_the_path.forget() → None[source]

Drop every remembered answer. For tests, and for a new run.

spacr.qt.ask_for_the_path.remembered(key: str) → str | None[source]

What was already answered for key, if anything.

Parameters:

key – the key an ask_for_... call remembered its answer under. Returns None when nothing was answered for it in this run.

spacr.qt.ask_for_the_path.somebody_is_there() → bool[source]

Whether there is a person who could answer a dialog.

False under pytest, with no display, or before a QApplication exists. Checked before anything else, because a modal dialog with no one to answer it blocks the run indefinitely.

spacr.qt.ask_for_the_path.tables_in(database: str) → list[source]

Every table in a SQLite file, or an empty list if it is not one.

Never raises: a path the user chose may be any file, and the form reports an empty list as “holds no tables” instead of handling an exception.

Parameters:

database – path to the file to read, opened read-only as SQLite. Any failure to open or query it yields an empty list.

Nested helpers

a_folder_holding.check(path: str) → str | None

Say what is wrong with a path, or None when it will do.

Returns the reason as a sentence rather than a bool, so the caller can show why the path was refused.

spacr/qt/ask_for_the_path.py:132

ask_for_a_database_column.chooser(title, start='')

Open the database file dialog. Injected for testing.

spacr/qt/ask_for_the_path.py:246

ask_for_a_database_column.pick(title, prompt, options)

Ask which column, from the ones the database actually has.

spacr/qt/ask_for_the_path.py:255

ask_for_a_folder.chooser(title, start='')

Open the folder dialog. Injected so the flow can be tested.

spacr/qt/ask_for_the_path.py:108