devboard
¤
Devboard package.
A development dashboard for projects, issues, pull requests, and other work.
Classes:
-
Board–A set of columns and the policies used to refresh their items.
-
Checkbox–A checkbox, added to rows to make them selectable.
-
Column–A Devboard column.
-
DataTable–A Devboard data table.
-
Devboard–The Devboard application.
-
Modal–A modal screen.
-
ModalMixin–Mixin class to add a modal method.
-
NotifyMixin–Mixin class to add notify methods.
-
Project–A class representing development projects.
-
Row–A Devboard row.
-
SelectableRow–A selectable row.
-
SelectableRowsDataTable–Data table with selectable rows.
-
Status–Git status data.
Functions:
-
get_parser–Return the CLI argument parser.
-
main–Run the main program.
-
row_action–Adapt a row callback into a Textual action.
-
rows_action–Adapt a batch callback into a Textual action.
Board
¤
Board(
columns: Iterable[Column | type[Column]],
*,
bindings: Iterable[BindingType] | None = None,
force_refresh_on_startup: bool = False,
)
A set of columns and the policies used to refresh their items.
Parameters:
-
(columns¤Iterable[Column | type[Column]]) –Column instances or classes displayed by the board.
-
(bindings¤Iterable[BindingType] | None, default:None) –Application bindings that extend the inherited
BINDINGS. Bindings override earlier entries for the same key. Omit this argument or pass an empty iterable to keep the defaults. -
(force_refresh_on_startup¤bool, default:False) –Whether startup uses the forced item hook.
Methods:
-
force_refresh_item–Prepare one item for a forced scan.
-
matches_filter–Match filter text against displayed cells, ignoring case.
-
refresh_item–Prepare one item for a normal scan.
Attributes:
-
BINDINGS(ClassVar) –Application bindings extended or overridden by subclasses and constructor bindings.
-
bindings(tuple[BindingType, ...]) –Application bindings after combining defaults, subclass bindings, and constructor bindings.
-
columns(tuple[Column | type[Column], ...]) –Column instances or classes displayed by the board.
-
force_refresh_on_startup(bool) –Whether startup uses the forced item hook.
Source code in src/devboard/_internal/board.py
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | |
BINDINGS
class-attribute
instance-attribute
¤
BINDINGS: ClassVar = [
Binding("question_mark", "show_help", "Help"),
Binding("ctrl+c", "exit", "Exit", priority=True),
Binding("escape", "exit", "Exit"),
Binding(
"ctrl+r",
"refresh_board",
"Refresh board",
show=False,
),
Binding(
"ctrl+f5",
"force_refresh_board",
"Force refresh board",
show=False,
),
Binding(
"ctrl+f", "filter_board", "Filter board", show=False
),
]
Application bindings extended or overridden by subclasses and constructor bindings.
bindings
instance-attribute
¤
bindings: tuple[BindingType, ...] = tuple(
{
binding.key: binding
for binding in Binding.make_bindings(binding_specs)
}.values()
)
Application bindings after combining defaults, subclass bindings, and constructor bindings.
columns
instance-attribute
¤
Column instances or classes displayed by the board.
force_refresh_on_startup
instance-attribute
¤
force_refresh_on_startup: bool = force_refresh_on_startup
Whether startup uses the forced item hook.
force_refresh_item
¤
force_refresh_item(item: Any) -> None
Prepare one item for a forced scan.
Source code in src/devboard/_internal/board.py
656 657 658 | |
matches_filter
¤
Match filter text against displayed cells, ignoring case.
Override this method to match source items instead. For example, a
backlog board can compare row.item.repository with value.
An empty filter shows every row.
Source code in src/devboard/_internal/board.py
660 661 662 663 664 665 666 667 | |
Checkbox
dataclass
¤
Checkbox(checked: bool = False)
A checkbox, added to rows to make them selectable.
Methods:
Attributes:
check
¤
check() -> None
Uncheck the checkbox.
Source code in src/devboard/_internal/datatable.py
55 56 57 | |
toggle
¤
toggle() -> bool
Toggle the checkbox.
Source code in src/devboard/_internal/datatable.py
63 64 65 66 | |
uncheck
¤
uncheck() -> None
Uncheck the checkbox.
Source code in src/devboard/_internal/datatable.py
59 60 61 | |
Column
¤
Bases: Container, ModalMixin, NotifyMixin, Generic[_ItemT]
A Devboard column.
Methods:
-
action_toggle_collapse–Collapse or expand the column.
-
action_toggle_maximize–Maximize the column or restore the layout from before it was maximized.
-
compose–Compose column widgets.
-
deserialize_cell–Restore a cell value loaded from the cache.
-
filter_rows–Show matching rows, or clear this column's filter with
None. -
item_key–Return the identity used to share and cache an item.
-
list_items–List the items to scan for this column.
-
modal–Ask the UI thread to show text or a Rich renderable in a modal.
-
notify_error–Notify error.
-
notify_info–Notify information.
-
notify_success–Notify success.
-
notify_warning–Notify warning.
-
populate_rows–Build table rows for an item.
-
report_progress–Show progress on the left of the footer.
-
serialize_cell–Convert a cell value to data that the cache can store.
-
update–Update the column (ask the app to recompute its data).
Attributes:
-
BINDINGS(ClassVar) –Column key bindings.
-
CACHE_VERSION(int) –Version of the column's serialized cell format.
-
DEFAULT_CLASSES–Textual CSS classes.
-
DEFAULT_CSS–Styles owned by the reusable column widget.
-
HEADERS(tuple[str, ...]) –The data table headers.
-
THREADED(bool) –Whether synchronous row actions run in background threads.
-
TITLE(str) –The title of the column.
-
app(App) –Textual application.
-
is_cached(Reactive[bool]) –Whether the column displays cached data.
-
is_collapsed(Reactive[bool]) –Whether the column is collapsed.
-
table(DataTable[_ItemT]) –Data table.
BINDINGS
class-attribute
instance-attribute
¤
BINDINGS: ClassVar = [
Binding(
"ctrl+e",
"toggle_collapse",
"Collapse/expand column",
show=False,
),
Binding(
"ctrl+x",
"toggle_maximize",
"Maximize/unmaximize column",
show=False,
),
]
Column key bindings.
CACHE_VERSION
class-attribute
instance-attribute
¤
CACHE_VERSION: int = 1
Version of the column's serialized cell format.
DEFAULT_CSS
class-attribute
instance-attribute
¤
DEFAULT_CSS = "\n Column .column-header {\n height: 1;\n }\n\n Column .column-title {\n width: 1fr;\n padding: 0 1;\n text-wrap: nowrap;\n text-overflow: ellipsis;\n }\n\n Column .column-count {\n width: auto;\n padding: 0 1;\n color: $text-muted;\n }\n\n Column.-collapsed {\n width: 3;\n }\n\n Column.-collapsed .column-header {\n height: auto;\n }\n\n Column.-collapsed .column-title {\n padding: 0;\n text-wrap: wrap;\n text-overflow: fold;\n text-style: bold;\n }\n\n Column.-collapsed .column-count {\n display: none;\n }\n\n Column.-collapsed DataTable {\n display: none;\n }\n "
Styles owned by the reusable column widget.
THREADED
class-attribute
instance-attribute
¤
THREADED: bool = True
Whether synchronous row actions run in background threads.
is_cached
class-attribute
instance-attribute
¤
Whether the column displays cached data.
is_collapsed
class-attribute
instance-attribute
¤
is_collapsed: Reactive[bool] = reactive(
default=False,
init=False,
layout=True,
toggle_class="-collapsed",
)
Whether the column is collapsed.
action_toggle_collapse
¤
action_toggle_collapse() -> None
Collapse or expand the column.
Source code in src/devboard/_internal/board.py
274 275 276 277 | |
action_toggle_maximize
¤
action_toggle_maximize() -> None
Maximize the column or restore the layout from before it was maximized.
Source code in src/devboard/_internal/board.py
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | |
compose
¤
compose() -> ComposeResult
Compose column widgets.
Source code in src/devboard/_internal/board.py
231 232 233 234 235 236 | |
deserialize_cell
¤
Restore a cell value loaded from the cache.
Source code in src/devboard/_internal/board.py
439 440 441 | |
filter_rows
¤
Show matching rows, or clear this column's filter with None.
The predicate receives each row, including its source item and display cells. It also applies after refreshes. Call this method on the UI thread.
Source code in src/devboard/_internal/board.py
411 412 413 414 415 416 417 418 419 420 421 | |
item_key
¤
item_key(item: _ItemT) -> Hashable
Return the identity used to share and cache an item.
Keys must be hashable and unique across the board.
Objects can expose a devboard_key attribute to provide a stable
identity. Hashable objects otherwise use their own identity. Unhashable
objects use their process-local identity and should override this method
if their rows need to be restored from the on-disk cache.
Source code in src/devboard/_internal/board.py
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | |
list_items
¤
list_items() -> Iterable[_ItemT]
List the items to scan for this column.
Source code in src/devboard/_internal/board.py
508 509 510 | |
modal
¤
modal(text: RenderableType) -> None
Ask the UI thread to show text or a Rich renderable in a modal.
Source code in src/devboard/_internal/modal.py
63 64 65 | |
notify_error
¤
Notify error.
Source code in src/devboard/_internal/notifications.py
40 41 42 | |
notify_info
¤
Notify information.
Source code in src/devboard/_internal/notifications.py
28 29 30 | |
notify_success
¤
Notify success.
Source code in src/devboard/_internal/notifications.py
32 33 34 | |
notify_warning
¤
Notify warning.
Source code in src/devboard/_internal/notifications.py
36 37 38 | |
populate_rows
¤
Build table rows for an item.
Source code in src/devboard/_internal/board.py
528 529 530 | |
report_progress
¤
report_progress(description: str | None = None) -> None
Show progress on the left of the footer.
Devboard automatically clears progress associated with a worker when that worker finishes or is cancelled.
Parameters:
-
(description¤str | None, default:None) –Progress text. Omit the text to clear the current progress.
Source code in src/devboard/_internal/board.py
423 424 425 426 427 428 429 430 431 432 433 | |
serialize_cell
¤
Convert a cell value to data that the cache can store.
Source code in src/devboard/_internal/board.py
435 436 437 | |
update
¤
update() -> None
Update the column (ask the app to recompute its data).
Source code in src/devboard/_internal/board.py
405 406 407 408 409 | |
DataTable
¤
Bases: SelectableRowsDataTable[_ItemT], Generic[_ItemT]
A Devboard data table.
Methods:
-
action_reverse_select–Reverse selection.
-
action_toggle_select_all–Toggle-select all rows.
-
action_toggle_select_down–Toggle selection down.
-
action_toggle_select_row–Toggle-select current row.
-
action_toggle_select_up–Toggle selection up.
-
add_row–Add a row and update the column's row count.
-
add_rows–Add rows.
-
clear–Clear the table and update the column's row count.
-
filter_rows–Filter rows and update the column's visible row count.
-
force_refresh–Force refresh table.
-
get_row–Return row cells, including cells retained while a row is hidden.
-
remove_row–Remove a row and report when the table becomes empty.
-
sort–Sort all rows and retain the active filter.
Attributes:
-
BINDINGS(ClassVar) –Key bindings for selecting rows.
-
ROW–The class to instantiate rows.
-
all_rows(Iterator[Row[_ItemT]]) –All Devboard rows, including rows hidden by a filter.
-
current_row(Row[_ItemT]) –Currently selected row.
-
selectable_rows(Iterator[Row[_ItemT]]) –Rows, as Devboard rows.
-
selected_rows(Iterator[Row[_ItemT]]) –Selected Devboard rows.
Source code in src/devboard/_internal/datatable.py
182 183 184 185 186 187 188 189 190 | |
BINDINGS
class-attribute
instance-attribute
¤
BINDINGS: ClassVar = [
Binding(
"space",
"toggle_select_row",
"Toggle select",
show=False,
),
Binding(
"ctrl+a, *",
"toggle_select_all",
"Toggle select all",
show=False,
),
Binding(
"exclamation_mark",
"reverse_select",
"Reverse selection",
show=False,
),
Binding(
"shift+up",
"toggle_select_up",
"Expand selection up",
show=False,
),
Binding(
"shift+down",
"toggle_select_down",
"Expand selection down",
show=False,
),
]
Key bindings for selecting rows.
all_rows
property
¤
All Devboard rows, including rows hidden by a filter.
action_reverse_select
¤
action_reverse_select() -> None
Reverse selection.
Source code in src/devboard/_internal/datatable.py
311 312 313 314 315 | |
action_toggle_select_all
¤
action_toggle_select_all() -> None
Toggle-select all rows.
Source code in src/devboard/_internal/datatable.py
300 301 302 303 304 305 306 307 308 309 | |
action_toggle_select_down
¤
action_toggle_select_down() -> None
Toggle selection down.
Source code in src/devboard/_internal/datatable.py
329 330 331 332 333 334 335 336 337 338 339 | |
action_toggle_select_row
¤
action_toggle_select_row() -> None
Toggle-select current row.
Source code in src/devboard/_internal/datatable.py
291 292 293 294 295 296 297 298 | |
action_toggle_select_up
¤
action_toggle_select_up() -> None
Toggle selection up.
Source code in src/devboard/_internal/datatable.py
317 318 319 320 321 322 323 324 325 326 327 | |
add_row
¤
add_row(
*cells: Any,
height: int | None = 1,
key: str | None = None,
label: Any | None = None,
) -> RowKey
Add a row and update the column's row count.
Source code in src/devboard/_internal/board.py
116 117 118 119 120 | |
add_rows
¤
Add rows.
Automatically insert a column with checkboxes in position 0.
Source code in src/devboard/_internal/datatable.py
220 221 222 223 224 225 | |
clear
¤
Clear the table and update the column's row count.
Source code in src/devboard/_internal/board.py
122 123 124 125 126 | |
filter_rows
¤
filter_rows(
predicate: Callable[[SelectableRow[_ItemT]], bool]
| None,
) -> None
Filter rows and update the column's visible row count.
Source code in src/devboard/_internal/board.py
135 136 137 138 | |
force_refresh
¤
force_refresh() -> None
Force refresh table.
Source code in src/devboard/_internal/datatable.py
412 413 414 415 | |
get_row
¤
Return row cells, including cells retained while a row is hidden.
Source code in src/devboard/_internal/datatable.py
252 253 254 255 256 257 | |
remove_row
¤
Remove a row and report when the table becomes empty.
Source code in src/devboard/_internal/board.py
128 129 130 131 132 133 | |
sort
¤
sort(
*columns: Any,
key: Callable[[Any], Any] | None = None,
reverse: bool = False,
) -> SelectableRowsDataTable[_ItemT]
Sort all rows and retain the active filter.
Source code in src/devboard/_internal/datatable.py
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | |
Devboard
¤
Devboard(
*args: Any,
board: str | Path | None = None,
background_tasks: bool = True,
workers: int | None = None,
**kwargs: Any,
)
Bases: App, ModalMixin
The Devboard application.
Parameters:
-
(board¤str | Path | None, default:None) –The board to display (name or file path).
-
(background_tasks¤bool, default:True) –Whether to run forced startup hooks and use the on-disk cache. Disable this option for deterministic tests and screenshots.
-
(workers¤int | None, default:None) –How many items to scan concurrently. Overrides the
workersconfig setting.
Methods:
-
action_exit–Exit application.
-
action_filter_board–Prompt for a filter to apply to all columns.
-
action_filter_column–Prompt for a filter to apply to the focused column.
-
action_force_refresh_board–Force-refresh all columns.
-
action_force_refresh_column–Force-refresh the focused column.
-
action_force_refresh_item–Force-refresh the item under the cursor in every column that lists it.
-
action_refresh_board–Refresh all columns.
-
action_refresh_column–Refresh the focused column.
-
action_refresh_item–Refresh the item under the cursor in every column that lists it.
-
action_show_help–Show help.
-
action_show_help_panel–Show widget help and grouped bindings for the focused column.
-
action_toggle_help_panel–Show or hide Textual's keys and widget help panel.
-
compose–Compose the layout.
-
filter_rows–Filter specific columns, or all columns when none are specified.
-
force_refresh_board–Refresh columns after forcing their items to update external state.
-
get_system_commands–Add refresh and filtering actions to the command palette.
-
modal–Ask the UI thread to show text or a Rich renderable in a modal.
-
on_mount–Populate columns when the application starts.
-
refresh_board–Refresh columns without forcing their items to update external state.
-
scan–Recompute columns data in the background.
Attributes:
-
BINDINGS(ClassVar) –Application shortcuts extended or overridden by board bindings.
-
CSS_PATH–Path to the CSS file.
-
app(App) –Textual application.
-
board(Board) –The loaded board definition.
Source code in src/devboard/_internal/app.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
BINDINGS
class-attribute
instance-attribute
¤
BINDINGS: ClassVar = [
Binding("ctrl+k", "toggle_help_panel", "Keys"),
Binding(
"ctrl+p",
"command_palette",
"Palette",
show=False,
priority=True,
tooltip="Open the command palette",
),
]
Application shortcuts extended or overridden by board bindings.
CSS_PATH
class-attribute
instance-attribute
¤
CSS_PATH = Path(__file__).parent / 'devboard.tcss'
Path to the CSS file.
action_exit
¤
action_exit() -> None
Exit application.
Source code in src/devboard/_internal/app.py
253 254 255 256 257 | |
action_filter_board
¤
action_filter_board() -> None
Prompt for a filter to apply to all columns.
Source code in src/devboard/_internal/app.py
244 245 246 | |
action_filter_column
¤
action_filter_column() -> None
Prompt for a filter to apply to the focused column.
Source code in src/devboard/_internal/app.py
248 249 250 251 | |
action_force_refresh_board
¤
action_force_refresh_board() -> None
Force-refresh all columns.
Source code in src/devboard/_internal/app.py
222 223 224 | |
action_force_refresh_column
¤
action_force_refresh_column() -> None
Force-refresh the focused column.
Source code in src/devboard/_internal/app.py
231 232 233 234 | |
action_force_refresh_item
¤
action_force_refresh_item() -> None
Force-refresh the item under the cursor in every column that lists it.
Source code in src/devboard/_internal/app.py
240 241 242 | |
action_refresh_board
¤
action_refresh_board() -> None
Refresh all columns.
Source code in src/devboard/_internal/app.py
218 219 220 | |
action_refresh_column
¤
action_refresh_column() -> None
Refresh the focused column.
Source code in src/devboard/_internal/app.py
226 227 228 229 | |
action_refresh_item
¤
action_refresh_item() -> None
Refresh the item under the cursor in every column that lists it.
Source code in src/devboard/_internal/app.py
236 237 238 | |
action_show_help
¤
action_show_help() -> None
Show help.
Source code in src/devboard/_internal/app.py
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | |
action_show_help_panel
¤
action_show_help_panel() -> None
Show widget help and grouped bindings for the focused column.
Source code in src/devboard/_internal/app.py
206 207 208 209 | |
action_toggle_help_panel
¤
action_toggle_help_panel() -> None
Show or hide Textual's keys and widget help panel.
Source code in src/devboard/_internal/app.py
211 212 213 214 215 216 | |
compose
¤
compose() -> ComposeResult
Compose the layout.
Source code in src/devboard/_internal/app.py
123 124 125 126 127 128 129 130 131 132 | |
filter_rows
¤
Filter specific columns, or all columns when none are specified.
Use the board's matches_filter() hook to select rows. A nonempty value
replaces each target column's filter. None or an empty string clears it.
Filtering preserves hidden rows and does not scan items or write the cache.
Call this method on the UI thread.
Source code in src/devboard/_internal/app.py
311 312 313 314 315 316 317 318 319 320 321 322 | |
force_refresh_board
¤
Refresh columns after forcing their items to update external state.
Source code in src/devboard/_internal/app.py
307 308 309 | |
get_system_commands
¤
get_system_commands(
screen: Screen,
) -> Iterable[SystemCommand]
Add refresh and filtering actions to the command palette.
Source code in src/devboard/_internal/app.py
134 135 136 137 138 | |
modal
¤
modal(text: RenderableType) -> None
Ask the UI thread to show text or a Rich renderable in a modal.
Source code in src/devboard/_internal/modal.py
63 64 65 | |
on_mount
¤
on_mount() -> None
Populate columns when the application starts.
Source code in src/devboard/_internal/app.py
140 141 142 143 | |
refresh_board
¤
Refresh columns without forcing their items to update external state.
Source code in src/devboard/_internal/app.py
303 304 305 | |
scan
¤
scan(
columns: Iterable[Column] | None = None,
*,
initial: bool = False,
force: bool = False,
) -> None
Recompute columns data in the background.
A single scan feeds all columns: each item is read once, by a small pool of threads, and the resulting rows are dispatched to every column as they arrive. Each completed scan saves the displayed board to the cache when background tasks are enabled.
Parameters:
-
(columns¤Iterable[Column] | None, default:None) –The columns to update (all of them by default).
-
(initial¤bool, default:False) –Whether this is the initial scan, which can display cached data.
-
(force¤bool, default:False) –Whether to use the board's forced item hook.
Source code in src/devboard/_internal/app.py
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | |
Modal
¤
Modal(*args: Any, text: RenderableType, **kwargs: Any)
Bases: ModalScreen
A modal screen.
Methods:
Attributes:
-
text–Text content.
Source code in src/devboard/_internal/modal.py
37 38 39 40 41 42 43 44 | |
compose
¤
compose() -> ComposeResult
Screen composition.
Source code in src/devboard/_internal/modal.py
46 47 48 | |
ModalMixin
¤
Mixin class to add a modal method.
Methods:
-
modal–Ask the UI thread to show text or a Rich renderable in a modal.
Attributes:
modal
¤
modal(text: RenderableType) -> None
Ask the UI thread to show text or a Rich renderable in a modal.
Source code in src/devboard/_internal/modal.py
63 64 65 | |
NotifyMixin
¤
Mixin class to add notify methods.
Methods:
-
notify_error–Notify error.
-
notify_info–Notify information.
-
notify_success–Notify success.
-
notify_warning–Notify warning.
Attributes:
notify_error
¤
Notify error.
Source code in src/devboard/_internal/notifications.py
40 41 42 | |
notify_info
¤
Notify information.
Source code in src/devboard/_internal/notifications.py
28 29 30 | |
notify_success
¤
Notify success.
Source code in src/devboard/_internal/notifications.py
32 33 34 | |
notify_warning
¤
Notify warning.
Source code in src/devboard/_internal/notifications.py
36 37 38 | |
Project
¤
Project(path: Path)
A class representing development projects.
It is instantiated with a path, and then provides many utility properties and methods.
Methods:
-
__lt__–Ordering is based on the project name.
-
checkout–Checkout branch, restore previous one when exiting.
-
delete–Delete branch.
-
fetch–Fetch.
-
fetch_locked–Fetch the project if no other path operation is running.
-
lock–Try to lock the project path without waiting.
-
locked–Try to lock the project path and release it when the context exits.
-
pull–Pull branch.
-
push–Push branch.
-
unlock–Unlock the project path.
-
unpulled–Number of unpulled commits (compared to the branch upstream), per branch.
-
unpushed–Number of unpushed commits (compared to the branch upstream), per branch.
-
unreleased–List unreleased commits (commits since the latest tag reachable from the branch).
Attributes:
-
DEFAULT_BRANCHES(tuple[str, ...]) –Name of common default branches. Mainly useful to compute unreleased commits.
-
LOCKS(dict[Path, Lock]) –Locks keyed by resolved project path, to avoid concurrent operations.
-
branch(Head) –Currently checked out branch.
-
default_branch(str) –Default branch (or main branch), as checked out when cloning.
-
devboard_key(Path) –Stable identity used to share this project between columns.
-
is_dirty(bool) –Whether the project is in a "dirty" state (uncommitted modifications).
-
latest_tag(TagReference) –Latest tag (by creation date).
-
name(str) –Name of the project.
-
path(Path) –Path of the project on the file-system.
-
repo(Repo) –GitPython's
Repoobject (cached per instance). -
status(Status) –Status of the project.
-
status_line(str) –Status of the project, as a string.
Source code in src/devboard/_internal/projects.py
68 69 70 | |
DEFAULT_BRANCHES
class-attribute
¤
Name of common default branches. Mainly useful to compute unreleased commits.
LOCKS
class-attribute
¤
LOCKS: dict[Path, Lock] = defaultdict(Lock)
Locks keyed by resolved project path, to avoid concurrent operations.
default_branch
property
¤
default_branch: str
Default branch (or main branch), as checked out when cloning.
devboard_key
property
¤
devboard_key: Path
Stable identity used to share this project between columns.
is_dirty
property
¤
is_dirty: bool
Whether the project is in a "dirty" state (uncommitted modifications).
latest_tag
property
¤
latest_tag: TagReference
status
property
¤
status: Status
Status of the project.
Computed from a single git status --porcelain call,
which is much cheaper than diffing index and work tree separately.
Each file is counted once, in the first matching category:
untracked, renamed, added, deleted, type-changed, modified.
__lt__
¤
Ordering is based on the project name.
Total ordering is implemented on projects so they can be sorted in the application tables.
Source code in src/devboard/_internal/projects.py
75 76 77 78 79 80 81 82 | |
checkout
¤
Checkout branch, restore previous one when exiting.
Source code in src/devboard/_internal/projects.py
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
delete
¤
delete(branch: str) -> None
Delete branch.
Source code in src/devboard/_internal/projects.py
228 229 230 | |
fetch
¤
fetch() -> None
Fetch.
Source code in src/devboard/_internal/projects.py
250 251 252 253 254 255 | |
fetch_locked
¤
fetch_locked() -> bool
Fetch the project if no other path operation is running.
Source code in src/devboard/_internal/projects.py
257 258 259 260 261 262 263 264 265 | |
lock
¤
lock() -> bool
Try to lock the project path without waiting.
Source code in src/devboard/_internal/projects.py
279 280 281 | |
locked
¤
Try to lock the project path and release it when the context exits.
Source code in src/devboard/_internal/projects.py
287 288 289 290 291 292 293 294 295 | |
pull
¤
pull(branch: str | None = None) -> None
Pull branch.
Source code in src/devboard/_internal/projects.py
218 219 220 221 | |
push
¤
push(branch: str | None = None) -> None
Push branch.
Source code in src/devboard/_internal/projects.py
223 224 225 226 | |
unlock
¤
unlock() -> None
Unlock the project path.
Source code in src/devboard/_internal/projects.py
283 284 285 | |
unpulled
¤
Number of unpulled commits (compared to the branch upstream), per branch.
Source code in src/devboard/_internal/projects.py
179 180 181 | |
unpushed
¤
Number of unpushed commits (compared to the branch upstream), per branch.
Source code in src/devboard/_internal/projects.py
175 176 177 | |
unreleased
¤
List unreleased commits (commits since the latest tag reachable from the branch).
Source code in src/devboard/_internal/projects.py
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
Row
dataclass
¤
Row(
table: SelectableRowsDataTable[_ItemT],
key: RowKey,
_snapshot: list | None = None,
_item_snapshot: _ItemT | object = _MISSING_ITEM,
)
Bases: SelectableRow[_ItemT], Generic[_ItemT]
A Devboard row.
Methods:
-
refresh–Request a refresh of this row's item in the specified columns.
-
remove–Ask the table to remove this row on the UI thread.
-
select–Select this row.
-
toggle_select–Toggle-select this row.
-
unselect–Unselect this row.
Attributes:
-
app(App) –Textual application.
-
checkbox(Checkbox) –Row checkbox.
-
data(list) –Row data (without checkbox).
-
index(int) –Row index.
-
item(_ItemT) –Item that produced this row.
-
key(RowKey) –The row key.
-
next(Row[_ItemT]) –Next Devboard row.
-
previous(Row[_ItemT]) –Previous Devboard row.
-
selected(bool) –Whether this row is selected.
-
table(SelectableRowsDataTable[_ItemT]) –The data table containing this row.
item
property
¤
item: _ItemT
table
instance-attribute
¤
table: SelectableRowsDataTable[_ItemT]
The data table containing this row.
refresh
¤
Request a refresh of this row's item in the specified columns.
Pass column instances or classes. Omit columns to refresh every column
that lists the item. This method is safe in background actions and after
remove() on an action's row snapshot. Requests wait for any active scan.
Set force=True to use the board's forced item hook.
Source code in src/devboard/_internal/board.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
remove
¤
remove() -> None
Ask the table to remove this row on the UI thread.
Source code in src/devboard/_internal/datatable.py
142 143 144 | |
select
¤
select() -> None
Select this row.
Source code in src/devboard/_internal/datatable.py
125 126 127 | |
toggle_select
¤
toggle_select() -> bool
Toggle-select this row.
Source code in src/devboard/_internal/datatable.py
133 134 135 | |
unselect
¤
unselect() -> None
Unselect this row.
Source code in src/devboard/_internal/datatable.py
129 130 131 | |
SelectableRow
dataclass
¤
SelectableRow(
table: SelectableRowsDataTable[_ItemT],
key: RowKey,
_snapshot: list | None = None,
_item_snapshot: _ItemT | object = _MISSING_ITEM,
)
Bases: Generic[_ItemT]
A selectable row.
Methods:
-
remove–Ask the table to remove this row on the UI thread.
-
select–Select this row.
-
toggle_select–Toggle-select this row.
-
unselect–Unselect this row.
Attributes:
-
app(App) –Textual application.
-
checkbox(Checkbox) –Row checkbox.
-
data(list) –Row data (without checkbox).
-
index(int) –Row index.
-
item(_ItemT) –Item that produced this row.
-
key(RowKey) –The row key.
-
next(SelectableRow[_ItemT]) –Next row (down).
-
previous(SelectableRow[_ItemT]) –Previous row (up).
-
selected(bool) –Whether this row is selected.
-
table(SelectableRowsDataTable[_ItemT]) –The data table containing this row.
item
property
¤
item: _ItemT
table
instance-attribute
¤
table: SelectableRowsDataTable[_ItemT]
The data table containing this row.
remove
¤
remove() -> None
Ask the table to remove this row on the UI thread.
Source code in src/devboard/_internal/datatable.py
142 143 144 | |
select
¤
select() -> None
Select this row.
Source code in src/devboard/_internal/datatable.py
125 126 127 | |
toggle_select
¤
toggle_select() -> bool
Toggle-select this row.
Source code in src/devboard/_internal/datatable.py
133 134 135 | |
unselect
¤
unselect() -> None
Unselect this row.
Source code in src/devboard/_internal/datatable.py
129 130 131 | |
SelectableRowsDataTable
¤
Bases: DataTable, Generic[_ItemT]
Data table with selectable rows.
Methods:
-
action_reverse_select–Reverse selection.
-
action_toggle_select_all–Toggle-select all rows.
-
action_toggle_select_down–Toggle selection down.
-
action_toggle_select_row–Toggle-select current row.
-
action_toggle_select_up–Toggle selection up.
-
add_row–Add a row with a checkbox and associate its source item, if set.
-
add_rows–Add rows.
-
clear–Clear rows and optionally columns.
-
filter_rows–Show matching rows, or show every row when the predicate is
None. -
force_refresh–Force refresh table.
-
get_row–Return row cells, including cells retained while a row is hidden.
-
remove_row–Remove a row and its source-item association.
-
sort–Sort all rows and retain the active filter.
Attributes:
-
BINDINGS(ClassVar) –Key bindings for selecting rows.
-
ROW–The class to instantiate selectable rows.
-
all_rows(Iterator[SelectableRow[_ItemT]]) –All rows in insertion order, including hidden rows.
-
current_row(SelectableRow[_ItemT]) –Currently selected row.
-
selectable_rows(Iterator[SelectableRow[_ItemT]]) –Rows, as selectable ones.
-
selected_rows(Iterator[SelectableRow[_ItemT]]) –Selected rows.
Source code in src/devboard/_internal/datatable.py
182 183 184 185 186 187 188 189 190 | |
BINDINGS
class-attribute
instance-attribute
¤
BINDINGS: ClassVar = [
Binding(
"space",
"toggle_select_row",
"Toggle select",
show=False,
),
Binding(
"ctrl+a, *",
"toggle_select_all",
"Toggle select all",
show=False,
),
Binding(
"exclamation_mark",
"reverse_select",
"Reverse selection",
show=False,
),
Binding(
"shift+up",
"toggle_select_up",
"Expand selection up",
show=False,
),
Binding(
"shift+down",
"toggle_select_down",
"Expand selection down",
show=False,
),
]
Key bindings for selecting rows.
ROW
class-attribute
instance-attribute
¤
ROW = SelectableRow
The class to instantiate selectable rows.
all_rows
property
¤
all_rows: Iterator[SelectableRow[_ItemT]]
All rows in insertion order, including hidden rows.
selectable_rows
property
¤
selectable_rows: Iterator[SelectableRow[_ItemT]]
Rows, as selectable ones.
action_reverse_select
¤
action_reverse_select() -> None
Reverse selection.
Source code in src/devboard/_internal/datatable.py
311 312 313 314 315 | |
action_toggle_select_all
¤
action_toggle_select_all() -> None
Toggle-select all rows.
Source code in src/devboard/_internal/datatable.py
300 301 302 303 304 305 306 307 308 309 | |
action_toggle_select_down
¤
action_toggle_select_down() -> None
Toggle selection down.
Source code in src/devboard/_internal/datatable.py
329 330 331 332 333 334 335 336 337 338 339 | |
action_toggle_select_row
¤
action_toggle_select_row() -> None
Toggle-select current row.
Source code in src/devboard/_internal/datatable.py
291 292 293 294 295 296 297 298 | |
action_toggle_select_up
¤
action_toggle_select_up() -> None
Toggle selection up.
Source code in src/devboard/_internal/datatable.py
317 318 319 320 321 322 323 324 325 326 327 | |
add_row
¤
add_row(
*cells: Any,
height: int | None = 1,
key: str | None = None,
label: Any | None = None,
) -> RowKey
Add a row with a checkbox and associate its source item, if set.
Source code in src/devboard/_internal/datatable.py
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | |
add_rows
¤
Add rows.
Automatically insert a column with checkboxes in position 0.
Source code in src/devboard/_internal/datatable.py
220 221 222 223 224 225 | |
clear
¤
clear(
columns: bool = True,
) -> SelectableRowsDataTable[_ItemT]
Clear rows and optionally columns.
When clearing columns, automatically re-add a column for checkboxes.
Source code in src/devboard/_internal/datatable.py
227 228 229 230 231 232 233 234 235 236 237 238 239 | |
filter_rows
¤
filter_rows(
predicate: Callable[[SelectableRow[_ItemT]], bool]
| None,
) -> None
Show matching rows, or show every row when the predicate is None.
Each call replaces the previous filter. Hidden rows retain their keys, cells, source items, and selections, but do not participate in row actions. The filter also applies to rows added later.
Source code in src/devboard/_internal/datatable.py
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | |
force_refresh
¤
force_refresh() -> None
Force refresh table.
Source code in src/devboard/_internal/datatable.py
412 413 414 415 | |
get_row
¤
Return row cells, including cells retained while a row is hidden.
Source code in src/devboard/_internal/datatable.py
252 253 254 255 256 257 | |
remove_row
¤
Remove a row and its source-item association.
Source code in src/devboard/_internal/datatable.py
241 242 243 244 245 246 247 248 249 250 | |
sort
¤
sort(
*columns: Any,
key: Callable[[Any], Any] | None = None,
reverse: bool = False,
) -> SelectableRowsDataTable[_ItemT]
Sort all rows and retain the active filter.
Source code in src/devboard/_internal/datatable.py
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | |
Status
dataclass
¤
Status(
added: list[Path],
deleted: list[Path],
modified: list[Path],
renamed: list[Path],
typechanged: list[Path],
untracked: list[Path],
)
get_parser
¤
get_parser() -> ArgumentParser
Return the CLI argument parser.
Returns:
-
ArgumentParser–An argparse parser.
Source code in src/devboard/_internal/cli.py
51 52 53 54 55 56 57 58 59 60 61 62 | |
main
¤
Run the main program.
This function is executed when you type devboard or python -m devboard.
Parameters:
Returns:
-
int–An exit code.
Source code in src/devboard/_internal/cli.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
row_action
¤
row_action(
method: Callable[
Concatenate[
_ActionColumnT, Row[Any], _ActionParamsT
],
Awaitable[None] | None,
],
) -> Callable[
Concatenate[_ActionColumnT, _ActionParamsT], None
]
Adapt a row callback into a Textual action.
Decorate an action_* method and use the suffix as the binding action. For example, bind open to a decorated
action_open method.
Declare the row as the first argument after self and make it positional-only: action_label(self, row, /, label).
Binding arguments follow the row. For example, label('feature') calls action_label(row, 'feature').
The decorated method receives each selected row, or the current row when no rows are selected. Devboard runs each
synchronous call in a background thread unless the column sets THREADED to false. Async methods run in async workers.
When caching is enabled, Devboard updates the cache once after the whole operation, including no-ops and failed calls.
Source code in src/devboard/_internal/board.py
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | |
rows_action
¤
rows_action(
method: Callable[
Concatenate[
_ActionColumnT, list[Row[Any]], _ActionParamsT
],
Awaitable[None] | None,
],
) -> Callable[
Concatenate[_ActionColumnT, _ActionParamsT], None
]
Adapt a batch callback into a Textual action.
Decorate an action_* method and use its suffix in a binding. The method receives one list of selected visible rows,
or a list containing the current row when none are selected. Empty tables do not call the method.
Declare the row list as the first argument after self and make it positional-only: action_label(self, rows, /, label).
Binding arguments follow the row list. For example, label('feature') calls action_label(rows, 'feature').
Rows are stable snapshots, with the same data, item, remove(), and refresh() API as row_action callbacks.
Synchronous methods run in one background thread unless the column sets THREADED to false. Async methods always
run in an async worker, so they can await self.app.push_screen_wait() to ask for shared input.
Use asyncio.to_thread() for blocking work inside an async method.
When caching is enabled, Devboard updates the cache once after the operation, including no-ops and failed calls.
Source code in src/devboard/_internal/board.py
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | |