meta_package_manager.tables module¶
Table-output vocabulary and rendering plumbing shared by the subcommands.
The mpm subcommands render heterogeneous tables (different columns per command) but share the same output machinery. This module owns all of it:
SortableField, the vocabulary of the globalmpm --sort-byselector. The selector itself is click-extra’s field-vocabularySortByOption, and the per-table resolution (sort by the selected fields the table carries, keep the original row order when it carries none) happens insideclick_extra.table.print_table(), from the field each header pairs with its column in the registries below.The per-command column registries, each pairing a click-extra
ColumnSpec(whose ID addresses the column from--columns) with theSortableFieldthe column carries (Nonefor a column that cannot drive the sort). A registry is the single source of truth for its command: the same tuple feeds the@columns_optiondeclaration (which validates the user selection) andprint_projected_table()(which projects headers and rows before rendering).print_projected_table()andprint_serialized(), the human-friendly and machine-friendly rendering paths every table-producing subcommand goes through. The read commands serialize throughprint_serialized_and_exit(), which stops the command there.
- class meta_package_manager.tables.SortableField(*values)[source]¶
Bases:
StrEnumFields IDs allowed to be sorted.
- MANAGER_ID = 'manager_id'¶
- MANAGER_NAME = 'manager_name'¶
- PACKAGE_ID = 'package_id'¶
- PACKAGE_NAME = 'package_name'¶
- VERSION = 'version'¶
- class meta_package_manager.tables.PackageOutcome(*values)[source]¶
Bases:
StrEnumWhat a command did to one package, as the
statuscolumn ofCHANGE_REPORT_COLUMNSspells it.Classified by
meta_package_manager.cli.package_outcomes()from the inventory a manager reports before and after the command changes it. The values are the words the serialized payload carries and the trail line counts (1 upgraded, 2 cooldown), so a member reads as a word rather than as an identifier. The table shows each one as itslabel.- UPGRADED = 'upgraded'¶
The installed version moved to a newer release, or in a direction that
mpmcannot tell.
- DOWNGRADED = 'downgraded'¶
The installed version moved back to an older release.
- INSTALLED = 'installed'¶
Absent before the command: a package it installed, or a dependency it pulled in.
- REMOVED = 'removed'¶
Present before the command, gone after it.
- COOLDOWN = 'cooldown'¶
Still outdated because the release-age cooldown holds it back.
The word the trail already tags such a package with, so one word names the hold on the trail, in the table and in the serialized payload.
- STILL_OUTDATED = 'still outdated'¶
Still outdated for any other reason: a failed build, a pinned package, or one the native command leaves alone.
- property label: str¶
The outcome as the report table shows it: its glyph from
PACKAGE_OUTCOME_GLYPHS, then its word.
- meta_package_manager.tables.PACKAGE_OUTCOME_GLYPHS: dict[PackageOutcome, str] = {PackageOutcome.COOLDOWN: '⏸️', PackageOutcome.DOWNGRADED: '⏪', PackageOutcome.INSTALLED: '🆕', PackageOutcome.REMOVED: '🗑️', PackageOutcome.STILL_OUTDATED: '⏳', PackageOutcome.UPGRADED: '🆙'}¶
The glyph leading each
PackageOutcomein the report table.All but one come from the legend repomatic’s dependency reports use for the same moves (🆙 updated, ⏪ stepped back, 🆕 new, 🗑️ removed, ⏸️ held back by cooldown), so a reader of both reads one legend.
still outdatedhas no counterpart there: ⏳ marks a package whose upgrade is still pending, whatever the cause.Only the table carries them. The serialized report and the trail line keep the bare word, which is what a script matches.
- meta_package_manager.tables.TColumn¶
One column of a registry: its spec, and the field it sorts on, if any.
alias of
tuple[ColumnSpec, SortableField | None]
- meta_package_manager.tables.PACKAGE_ID_COLUMN: tuple[ColumnSpec, SortableField | None] = (ColumnSpec(id='package_id', label='Package ID', description="Package's identifier.", max_width=None, optional=False, sortable=True), SortableField.PACKAGE_ID)¶
The
package_idcolumn every package table opens on.Deliberately the one column of every package table left uncapped, and the rule holds wherever it is reused. It is the value the user copies back into an
mpm install,mpm removeormpm upgradeinvocation, and a cell wrapped over two lines cannot be selected in one go. So it never wraps, and the shrinking falls on its neighbors instead: the name is free prose, and a version is read rather than retyped.The trade is explicit. A package ID wider than the terminal on its own still pushes the table past the edge, because the alternative is handing the user a broken identifier. Both halves of the trade are real here:
vim-packnames its plugins by GitHub URL (50 characters), and Homebrew Cask reports versions like1.26832.0,056ee2be623b207f6a4d24dfb1b2fb5a82db0ecf.
- meta_package_manager.tables.PACKAGE_NAME_COLUMN: tuple[ColumnSpec, SortableField | None] = (ColumnSpec(id='package_name', label='Name', description="Package's common name.", max_width='auto', optional=False, sortable=True), SortableField.PACKAGE_NAME)¶
The
package_namecolumn followingPACKAGE_ID_COLUMNin every package table, wrapping inside its own cell.
- meta_package_manager.tables.MANAGERS_COLUMNS: tuple[tuple[ColumnSpec, SortableField | None], ...] = ((ColumnSpec(id='manager_id', label='Manager ID', description="Manager's identifier.", max_width=None, optional=False, sortable=True), SortableField.MANAGER_ID), (ColumnSpec(id='manager_name', label='Name', description="Manager's common name.", max_width=None, optional=False, sortable=True), SortableField.MANAGER_NAME), (ColumnSpec(id='supported', label='Supported', description='Support status on the current platform.', max_width='auto', optional=False, sortable=True), None), (ColumnSpec(id='cli', label='CLI', description="Location of the manager's binary on the system.", max_width='auto', optional=False, sortable=True), None), (ColumnSpec(id='executable', label='Executable', description='Whether the binary is executable.', max_width=None, optional=False, sortable=True), None), (ColumnSpec(id='version', label='Version', description="Manager's self-reported version, and the unsatisfied requirement when stale.", max_width=None, optional=False, sortable=True), SortableField.VERSION))¶
Columns of the
mpm managerstable.supportedandcliare the two whose content no manager bounds: the first enumerates every platform a manager runs on when they do not collapse to a group name, the second holds a filesystem path. Both takeAUTO_WIDTHso they share whatever the fixed columns leave on the terminal and wrap inside their own cell, instead of stretching the table past the edge and mangling every border.
- meta_package_manager.tables.MANAGERS_DETECTED_COLUMNS: tuple[str, ...] = ('manager_id', 'manager_name', 'cli', 'version')¶
Columns kept by the default, detected-only view of the
mpm managerstable.A detected manager is by definition supported on this platform, found and executable, so
supportedandexecutablerender the same âś“ on every row and carry no information. Both come back in the wider views, where an unsupported platform or a missing binary makes them vary again. Only the default selection narrows:--columnsstill addresses every column ofMANAGERS_COLUMNS.
- meta_package_manager.tables.INSTALLED_COLUMNS: tuple[tuple[ColumnSpec, SortableField | None], ...] = ((ColumnSpec(id='package_id', label='Package ID', description="Package's identifier.", max_width=None, optional=False, sortable=True), SortableField.PACKAGE_ID), (ColumnSpec(id='package_name', label='Name', description="Package's common name.", max_width='auto', optional=False, sortable=True), SortableField.PACKAGE_NAME), (ColumnSpec(id='manager_id', label='Manager', description='Manager reporting the package.', max_width=None, optional=False, sortable=True), SortableField.MANAGER_ID), (ColumnSpec(id='installed_version', label='Installed version', description='Version currently installed.', max_width='auto', optional=False, sortable=True), SortableField.VERSION))¶
Columns of the
mpm installedtable, and of thempm orphansone.The width policy is the one
PACKAGE_ID_COLUMNdocuments: the ID never wraps, every other column does.
- meta_package_manager.tables.OUTDATED_COLUMNS: tuple[tuple[ColumnSpec, SortableField | None], ...] = ((ColumnSpec(id='package_id', label='Package ID', description="Package's identifier.", max_width=None, optional=False, sortable=True), SortableField.PACKAGE_ID), (ColumnSpec(id='package_name', label='Name', description="Package's common name.", max_width='auto', optional=False, sortable=True), SortableField.PACKAGE_NAME), (ColumnSpec(id='manager_id', label='Manager', description='Manager reporting the package.', max_width=None, optional=False, sortable=True), SortableField.MANAGER_ID), (ColumnSpec(id='installed_version', label='Installed version', description='Version currently installed.', max_width='auto', optional=False, sortable=True), SortableField.VERSION), (ColumnSpec(id='latest_version', label='Latest version', description='Version available for upgrade.', max_width='auto', optional=False, sortable=True), None))¶
Columns of the
mpm outdatedtable.Inherits the width policy documented on
PACKAGE_ID_COLUMN: the second version column wraps like the first,package_idstill does not.
- meta_package_manager.tables.SEARCH_COLUMNS: tuple[tuple[ColumnSpec, SortableField | None], ...] = ((ColumnSpec(id='package_id', label='Package ID', description="Package's identifier.", max_width=None, optional=False, sortable=True), SortableField.PACKAGE_ID), (ColumnSpec(id='package_name', label='Name', description="Package's common name.", max_width='auto', optional=False, sortable=True), SortableField.PACKAGE_NAME), (ColumnSpec(id='manager_id', label='Manager', description='Manager reporting the match.', max_width=None, optional=False, sortable=True), SortableField.MANAGER_ID), (ColumnSpec(id='latest_version', label='Latest version', description='Latest version available.', max_width='auto', optional=False, sortable=True), SortableField.VERSION), (ColumnSpec(id='description', label='Description', description='Package description, for managers that provide one. Out of the default selection: select it explicitly or pass --description.', max_width='auto', optional=False, sortable=True), None))¶
Columns of the
mpm searchtable.The
descriptioncolumn exists in the registry (so--columnscan select it) but stays out of the default selection unless--description(or--extended, which searches descriptions) is passed.It is the column holding the longest free prose, of a length no manager bounds: a single verbose match used to stretch the table far past the terminal and wrap every row at the edge, mangling the borders.
AUTO_WIDTHcaps it at whatever the other columns leave on the terminal, so the description wraps inside its own cell. The name and version columns share that treatment, andpackage_idis exempt from it, per the width policy documented onPACKAGE_ID_COLUMN.
- meta_package_manager.tables.COOLDOWN_COLUMNS: tuple[tuple[ColumnSpec, SortableField | None], ...] = ((ColumnSpec(id='released', label='Released', description='Publication date of the release the cooldown holds back.', max_width=None, optional=False, sortable=True), None), (ColumnSpec(id='eligible', label='Eligible', description='Date that release clears the cooldown window.', max_width=None, optional=False, sortable=True), None))¶
The two columns dating a package the release-age cooldown holds back, closing
CHANGE_REPORT_COLUMNS.Named after the columns of repomatic’s
Held back by cooldowntable, for the reasonPACKAGE_OUTCOME_GLYPHSborrows its legend. Only acooldownrow whose release could be dated fills them, so they join the default selection of a report when one of its rows does: seemeta_package_manager.cli.print_change_report().--columnsselects them whatever the rows carry.
- meta_package_manager.tables.CHANGE_REPORT_COLUMNS: tuple[tuple[ColumnSpec, SortableField | None], ...] = ((ColumnSpec(id='package_id', label='Package ID', description="Package's identifier.", max_width=None, optional=False, sortable=True), SortableField.PACKAGE_ID), (ColumnSpec(id='package_name', label='Name', description="Package's common name.", max_width='auto', optional=False, sortable=True), SortableField.PACKAGE_NAME), (ColumnSpec(id='manager_id', label='Manager', description='Manager whose inventory changed.', max_width=None, optional=False, sortable=True), SortableField.MANAGER_ID), (ColumnSpec(id='from_version', label='From', description='Version installed before the command.', max_width='auto', optional=False, sortable=True), None), (ColumnSpec(id='to_version', label='To', description='Version installed after the command, or the one still available for a package that did not move.', max_width='auto', optional=False, sortable=True), None), (ColumnSpec(id='status', label='Status', description='What the command did to the package: upgraded, downgraded, installed, removed, cooldown, still outdated.', max_width=None, optional=False, sortable=True), None), (ColumnSpec(id='released', label='Released', description='Publication date of the release the cooldown holds back.', max_width=None, optional=False, sortable=True), None), (ColumnSpec(id='eligible', label='Eligible', description='Date that release clears the cooldown window.', max_width=None, optional=False, sortable=True), None))¶
Columns of the change report closing every command that changes the installed inventory:
install,remove,upgrade,restoreandcleanup --orphans.One row per package the command moved or should have, each carrying one
PackageOutcome; seemeta_package_manager.cli.package_outcomes()for how a row is classified. The version columns wrap like every other table’s, andpackage_iddoes not, perPACKAGE_ID_COLUMN. Neither version column drives--sort-by: a report sorts by what moved, not by how far. The twoCOOLDOWN_COLUMNSclose the registry.
- meta_package_manager.tables.WHICH_COLUMNS: tuple[tuple[ColumnSpec, SortableField | None], ...] = ((ColumnSpec(id='manager_id', label='Manager ID', description='Manager whose search path found the binary.', max_width=None, optional=False, sortable=True), SortableField.MANAGER_ID), (ColumnSpec(id='priority', label='Priority', description="Rank of the match in the manager's search path.", max_width=None, optional=False, sortable=True), None), (ColumnSpec(id='cli_path', label='CLI path', description='Location of the matched binary.', max_width=None, optional=False, sortable=True), None), (ColumnSpec(id='symlink', label='Symlink destination', description='Resolved target when the match is a symlink.', max_width=None, optional=False, sortable=True), None))¶
Columns of the
mpm whichtable.
- meta_package_manager.tables.column_specs(columns)[source]¶
Extract the bare
ColumnSpectuple from a column registry.- Return type:
- meta_package_manager.tables.sort_header(spec, field)[source]¶
The header
specrenders under, keyed by the field it sorts on.click-extra reads a header’s ID as the field
--sort-byaddresses. For mpm that is theSortableFieldthe column carries, not the column’s own ID:installed_versionsorts onversion. A column carrying no field keeps its own ID and declaressortable=False, which drops it from the selection.The spec carries its own
max_width, which click-extra reads off the header to size the column.- Return type:
- meta_package_manager.tables.print_projected_table(ctx, columns, rows, default_ids=None)[source]¶
Render dict
rowsas a table projected through--columns.The
--columnsselection restricts and reorders the rendering, SQL-SELECT-style; click-extra’sColumnsOptionalready validated it against the samecolumnsregistry, so unknown IDs never reach this point.default_idsis the selection applied when the user passed none (searchuses it to hide the description column unless--description);Nonekeeps every column in canonical order.Sorting stays on mpm’s global
--sort-by: each header pairs its label with the sortable field the column carries, and click-extra’sprint_table()reads the selection (with the--table-formatone) from the shared contextmetaand resolves it per table. A sort field whose column is projected out is simply skipped, and a table carrying none of the selected fields keeps its original row order.Note
A rendered header addresses its column by the field it sorts on, not by the ID
--columnsselects it with: the two can differ, and a column may sort on nothing at all.sort_header()builds each one.- Return type:
- meta_package_manager.tables.print_serialized(ctx, data)[source]¶
Render
datain the active serialization format, if one is active.When the global
--table-formatresolves to one of the structured serialization formats (JSON, YAML, TOML, XML, …), serializedataunder the sharedmpmroot element and returnTrue. Otherwise print nothing and returnFalse, so the caller falls through to its human-friendly rendering.- Return type:
- meta_package_manager.tables.print_serialized_and_exit(ctx, data)[source]¶
Render
datain the active serialization format, then exit.The read commands’ variant of
print_serialized(): their serialized document is their whole output, so the command stops there. Otherwise return, so the caller falls through to its human-friendly table rendering.- Return type: