spacr.gate_library

Named gating strategies, saved with the project rather than in a file dialog.

The Gate Editor can write a strategy to a path and read one back, but only through a file chooser, which makes reuse depend on remembering where it was saved. A screen is gated the same way over and over – “live singlets”, “infected cells”, “the debris filter I always apply” – and those reusable strategies form a library.

So a strategy has a NAME and lives under <project>/gates/<name>.json. The Gate Editor lists what is there, applies one by name, and saves the current gates under a name.

Qt-free on purpose, like spacr.filters: the library is a directory of JSON files, and everything here is testable without a display.

A name is not a path. save(project, "../../etc/passwd", gates) must not write outside the project. A slash is treated as unsafe punctuation and replaced rather than becoming a subdirectory; slugify() is the whole of that rule and every entry point goes through it.

Exceptions

GateLibraryError

A strategy that cannot be saved or read, and why.

Functions

delete(→ bool)

Remove the strategy called name. False if there was none.

describe(→ Tuple[int, Optional[str]])

(gate count, error) for one saved strategy, without applying it.

library_dir(→ str)

The library directory for project. Not created.

list_strategies(→ List[str])

Every saved strategy in project, by name, sorted.

load(→ Any)

Read the strategy called name.

path_for(→ str)

Where the strategy called name lives.

save(→ str)

Write payload as the strategy called name.

slugify(→ str)

The filename for name, with no way out of the library directory.

Module Contents

exception spacr.gate_library.GateLibraryError[source]

Bases: ValueError

A strategy that cannot be saved or read, and why.

Initialize self. See help(type(self)) for accurate signature.

spacr.gate_library.delete(project: str, name: str) → bool[source]

Remove the strategy called name. False if there was none.

Parameters:
  • project – project root that owns the saved gate library.

  • name – display name of the strategy to remove.

Returns:

True when a file was removed, or False when it did not exist.

Raises:

GateLibraryError – if the name is unusable or deletion fails for a reason other than absence.

spacr.gate_library.describe(project: str, name: str) → Tuple[int, str | None][source]

(gate count, error) for one saved strategy, without applying it.

Parameters:
  • project – project root that owns the saved gate library.

  • name – display name of the strategy to inspect.

Returns:

(gate_count, None) for a readable strategy, or (0, error) when it cannot be read or does not resemble a strategy.

What a list needs to show next to a name. A strategy that will not read reports its error rather than a count, so a broken file is visible in the list instead of at the moment someone applies it.

spacr.gate_library.library_dir(project: str) → str[source]

The library directory for project. Not created.

Parameters:

project – project root that owns the saved gate library.

Returns:

path to the project’s gate-library directory.

spacr.gate_library.list_strategies(project: str) → List[str][source]

Every saved strategy in project, by name, sorted.

Parameters:

project – project root whose gate library is listed.

Returns:

sorted strategy names without their .json suffixes, or an empty list when the library cannot be read.

An unreadable directory is an empty library rather than an error: a dropdown that cannot be filled is not a reason to refuse to open a screen.

spacr.gate_library.load(project: str, name: str) → Any[source]

Read the strategy called name.

Parameters:
  • project – project root that owns the saved gate library.

  • name – display name of the strategy to read.

Returns:

decoded JSON strategy payload.

Raises:

GateLibraryError – no such strategy, or the file is not readable JSON. Both name the strategy, because “expecting value: line 1” on its own tells a user nothing about which one to fix.

spacr.gate_library.path_for(project: str, name: str) → str[source]

Where the strategy called name lives.

Parameters:
  • project – project root that owns the saved gate library.

  • name – display name of the strategy to locate.

Returns:

safe JSON path inside the project’s gate library.

Raises:

GateLibraryError – if name has no usable characters.

Always inside the library directory: the name is slugified first, so a name carrying / or .. cannot climb out of it.

spacr.gate_library.save(project: str, name: str, payload: Any) → str[source]

Write payload as the strategy called name.

Parameters:
  • project – project directory whose gates library receives the strategy.

  • name – display name converted to a safe .json filename by slugify(); it cannot escape the project library.

  • payload – whatever GateSet.to_json-shaped structure the caller holds. Serialised here rather than accepting a pre-made string so a caller cannot store something that will not read back.

Returns:

the path written.

Raises:

GateLibraryError – the name is unusable, the payload will not serialize, or the library/file cannot be created or written.

spacr.gate_library.slugify(name: str) → str[source]

The filename for name, with no way out of the library directory.

Parameters:

name – user-facing strategy name to make safe for one filename.

Returns:

cleaned filename stem; separators and other unsafe punctuation become hyphens and whitespace is collapsed.

Raises:

GateLibraryError – a name that is empty once cleaned. Writing it would produce .json, an invisible file the list would then show with no name.