Skip to content

list command: add -l/--limit flag, deprecate limit plugin - #6985

Open
snejus wants to merge 5 commits into
masterfrom
add-limit-to-list
Open

list command: add -l/--limit flag, deprecate limit plugin#6985
snejus wants to merge 5 commits into
masterfrom
add-limit-to-list

Conversation

@snejus

@snejus snejus commented Sep 3, 2026

Copy link
Copy Markdown
Member

Closes #5076
Supersedes #6690

What changed

  • Added a built-in -l / --limit flag to the list command, so result limiting now lives in beets core instead of the limit plugin.
  • Threaded limit support through the main query path: beets.ui.commands.list -> Library.items() / Library.albums() -> dbcore._get_results().
  • Updated query execution so limits are applied in the database when possible, and after in-memory sorting when sorting depends on flexible or computed fields.
  • Refactored sort selection into model-level field_sort() logic, which also improves sorting for related database fields.
  • Deprecated LimitPlugin and updated docs/changelog to point users to beet ls -l <number>.

Architecture impact

  • This moves result limiting from optional plugin behavior into the main list command flow, making it a first-class CLI capability.
  • The database layer now has clearer responsibility for deciding whether LIMIT can be pushed into SQL or must be applied after slow sorting.
  • Sort handling is more centralized and model-aware, which reduces special-case logic in query parsing and improves support for related fields.

High-level outcome

  • Users get a simpler and more discoverable way to limit list results.
  • list now works correctly with limit even when sorting by flexible attributes or related fields.
  • The old limit plugin is being phased out in favor of a smaller, more integrated command path.
  • We can later add this flag to other commands such as modify, write and update.

@snejus
snejus requested a review from a team as a code owner September 3, 2026 13:14
Copilot AI lite review requested due to automatic review settings September 3, 2026 13:14
@github-actions github-actions Bot added the limit limit plugin label Sep 3, 2026
@snejus
snejus force-pushed the add-limit-to-list branch 2 times, most recently from d312797 to e1a1cbb Compare September 3, 2026 13:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

current SQL join building can produce invalid SQL when sorting by related fields, and limit handling has edge-case bugs (0/negative) plus ordering-sensitive tests.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

PR move list result limiting into beets core with new -l/--limit flag, so users no need limit plugin for simple cap. PR also change sort plumbing so db layer can decide when it safe to push LIMIT into SQL vs apply after slow (python) sort.

Changes:

  • Add -l/--limit to beet list, thread limit through Library.items()/albums() down into dbcore._get_results().
  • Refactor sort picking into model-level field_sort() and add sort field_names tracking to choose SQL vs post-sort limiting.
  • Deprecate limit plugin and update docs/changelog/tests.
File summaries
File Description
test/ui/commands/test_list.py Add coverage for -l limit and flex sort; adjust existing assertions for multiple items.
test/dbcore/test_sort.py Add sort coverage for related album field (artpath) and adjust test path normalization helper.
test/dbcore/test_db.py Update fixture model computed-field API to new getters classproperty.
docs/reference/cli.rst Document -l/--limit in list command usage and description.
docs/plugins/limit.rst Mark limit plugin deprecated in favor of beet ls -l.
docs/changelog.rst Note new list limit flag and plugin deprecation.
beetsplug/limit.py Emit user-facing deprecation notice for LimitPlugin.
beets/ui/commands/list.py Add -l/--limit option and pass limit into library query calls.
beets/test/fixtures.py Update fixture model computed-field API to getters classproperty.
beets/library/models.py Add field_sort() and migrate computed-field getter mapping to getters classproperty.
beets/library/library.py Add limit param to items()/albums() and _fetch().
beets/dbcore/sort.py Add field_names to sort types; refactor FieldSort field naming for table-qualified fields.
beets/dbcore/queryparse.py Delegate sort construction to model_cls.field_sort().
beets/dbcore/db.py Add limit support in results + SQL generation, and migrate computed-field getter access to getters.
.git-blame-ignore-revs Add ignore-rev entry for getters refactor commit.
Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread beets/dbcore/db.py Outdated
Comment thread beets/dbcore/db.py Outdated
Comment thread beets/dbcore/sort.py
Comment thread beets/ui/commands/list.py
Comment thread test/ui/commands/test_list.py Outdated
Comment thread test/ui/commands/test_list.py Outdated
@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.50746% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 77.24%. Comparing base (ba4787f) to head (bb77a1f).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
beets/dbcore/sort.py 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6985      +/-   ##
==========================================
+ Coverage   77.19%   77.24%   +0.04%     
==========================================
  Files         163      163              
  Lines       21789    21830      +41     
  Branches     3360     3367       +7     
==========================================
+ Hits        16820    16862      +42     
  Misses       4149     4149              
+ Partials      820      819       -1     
Files with missing lines Coverage Δ
beets/dbcore/db.py 94.57% <100.00%> (+0.12%) ⬆️
beets/dbcore/queryparse.py 100.00% <100.00%> (+2.53%) ⬆️
beets/library/library.py 93.68% <100.00%> (ø)
beets/library/models.py 87.44% <100.00%> (+0.19%) ⬆️
beets/ui/commands/list.py 100.00% <100.00%> (ø)
beetsplug/limit.py 84.90% <100.00%> (+1.23%) ⬆️
beets/dbcore/sort.py 92.56% <94.44%> (+0.03%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@snejus
snejus force-pushed the add-limit-to-list branch 2 times, most recently from 9ddf0c8 to 6c419ff Compare September 3, 2026 13:40
@snejus
snejus requested a lite review from Copilot September 3, 2026 13:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

grug see 2 real bugs in new sort path (bad isinstance check for SmartArtistSort, and python sorting break for table-qualified fields) that can make sorting wrong or silently skip sort parts.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread beets/dbcore/sort.py
Comment thread beets/library/models.py
Comment thread beets/dbcore/db.py Outdated
@semohr
semohr requested a lite review from Copilot September 3, 2026 14:15
@arsaboo

arsaboo commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for adding this....I was never a fan of '<N' approach.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

grug see 2 correctness bugs: field_sort() has dead isinstance check and can generate ambiguous SQL ORDER BY with joins, and slow-query + slow-sort still apply order-sensitive slow query before sort (can re-break old <N behavior).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

beets/library/models.py:123

  • grug see bug in field_sort. sort_cls is class from _sorts, so isinstance(sort_cls, sort.SmartArtistSort) always false, smart-artist field swap never run. also param name case_sensitive is lie: caller pass case_insensitive, and this value go straight into Sort as case_insensitive. last, when SQL add relation join for sorting by other table field, shared field like year can become ambiguous unless qualified (Item/Album share many fields). grug want simple and correct: use issubclass, rename param, and qualify shared fields with main table name.
    def field_sort(
        cls, field: str, is_ascending: bool, case_sensitive: bool
    ) -> FieldSort:
        if sort_cls := cls._sorts.get(field):
            if isinstance(sort_cls, sort.SmartArtistSort):
  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread beets/dbcore/db.py
@snejus
snejus force-pushed the add-limit-to-list branch 2 times, most recently from 904e127 to 08b0ca7 Compare September 4, 2026 22:41
@snejus
snejus requested a lite review from Copilot September 4, 2026 22:43
@snejus

snejus commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Removed the commit which cached getters - it wasn't a good idea since we need to wait for plugins to load before we can calculate them.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

db layer can still apply SQL LIMIT before slow-query filtering, so -l/--limit can return fewer matches than requested for flex/computed-field queries.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

beets/dbcore/db.py:1424

  • grug see limit push into SQL even when query is slow (like flex attr filter). then slow query match happen after SQL, so -l can return fewer row than asked. grug want: only push limit into SQL when query fully fast; else apply limit after python match/sort. also reject negative limit here, not just in list cmd.
        sql_limit = flex_limit = None
        if limit is not None:
            if sort.field_names - model_cls.all_db_fields:
                # sorting by at least one flexible attr.
                # Limit will be applied after slow field sort.
                flex_limit = limit
  • Files reviewed: 12/12 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread beets/library/models.py Outdated
Comment thread docs/changelog.rst Outdated
Comment thread docs/plugins/limit.rst Outdated
@snejus
snejus force-pushed the add-limit-to-list branch 2 times, most recently from 9b86730 to 155f2ac Compare September 5, 2026 00:00
@snejus
snejus requested a lite review from Copilot September 5, 2026 00:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

tests/docs and DB limit path have concrete correctness/perf issues that should be fixed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

test/ui/commands/test_list.py:18

  • same Path-vs-str problem for another_item setup. pass str via os.fspath so Item path type stay consistent (bytes in db).
        self.another_item = _common.item(
            path=self.lib_path / "another/path", flex=2
        )
  • Files reviewed: 12/12 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread beets/dbcore/db.py
Comment thread test/ui/commands/test_list.py Outdated
Comment thread docs/reference/cli.rst
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

limit limit plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Limit: issue with sorting by play_count (from lastimport)

3 participants