Commit graph

13815 commits

Author SHA1 Message Date
J0J0 Todos
b3e77d50d5 Changelog for extra_debug tool 2026-03-17 07:02:05 +01:00
J0J0 Todos
870845d9c7 lastgenre: Polish method grouping comments wording 2026-03-17 06:52:30 +01:00
J0J0 Todos
af8cbc179c lastgenre: Adapt test to canon helpers move 2026-03-17 06:52:30 +01:00
J0J0 Todos
9747d91557 lastgenre: Group all tree processing helpers together 2026-03-17 06:52:30 +01:00
J0J0 Todos
71a104bbdc lastgenre: Named types Whitelist and CanonTree 2026-03-17 06:52:30 +01:00
J0J0 Todos
ffc6f23407 lastgenre: Adapt test to last.fm client separation 2026-03-17 06:52:30 +01:00
J0J0 Todos
c928c04ac2 lastgenre: Move fetching to client module 2026-03-17 06:52:30 +01:00
J0J0 Todos
84111aa8ee Add extra_debug utility to beets.logging 2026-03-17 06:52:30 +01:00
Šarūnas Nejus
4b93413851
Fix Windows fallback for beet config -e when no editor is set (#6445)
Fixes #6436.

On Windows, `beet config -e` falls back to `open_anything()` when
`VISUAL`/`EDITOR` are unset. That fallback returned `start`, but `start`
is a `cmd.exe` builtin (not an executable), so `os.execlp()` raised
`FileNotFoundError`.

This changes the Windows fallback command to `cmd /c start ""` so the
builtin is invoked via the shell and file opening works as intended.

## Changes

- Update `open_anything()` Windows fallback to `cmd /c start ""`.
- Add regression test for `interactive_open()` with the Windows fallback
command.
- Add regression test for `beet config -e` on simulated Windows with no
editor env vars.
- Add changelog entry under Unreleased bug fixes.
2026-03-16 21:25:04 +00:00
Aditya Inamdar
886bb8626d Remove implementation-focused tests per review 2026-03-16 21:19:12 +00:00
Aditya Inamdar
e711ad1cdb Format changelog entry for docs check 2026-03-16 21:19:12 +00:00
Aditya Inamdar
518a4a83fa Fix Windows fallback for config editor command 2026-03-16 21:19:12 +00:00
Šarūnas Nejus
fd0760f4c5
play: Add -R/--randomize option to play plugin (#6424)
I really wanted to combine `random` with `play` to shuffle tracks in a
temporary playlist, but couldn't find easy way to do it. I'd like to
introduce a new flag `-R / --randomize` to the `play` plugin to shuffle
tracks before passing them to the player.

I couldn't really decide between `-r` and `-R`, not sure if there's any
rule there. If you believe lower case would be better, just let me know.
2026-03-16 19:36:35 +00:00
Andrejs Mivreniks
f9f4af874b feat(play): Add -R/--randomize option to play plugin 2026-03-16 20:33:23 +02:00
Šarūnas Nejus
4b9cff3e0e
Fixups after utils move (#6446)
### Key changes

- **`get_model_changes` signature tightened**: The `old` parameter is no
longer optional — callers must pass an explicit model. The
`None`-fallback logic (`old or new.get_fresh_from_db()`) is pushed up to
`show_model_changes`, which is the appropriate place for that default
behaviour.
- **Changelog updated**: Plugin developers are notified to update their
imports.
2026-03-16 07:45:27 +00:00
Šarūnas Nejus
0b619c8b83
Add a note to the changelog 2026-03-16 07:38:22 +00:00
Šarūnas Nejus
286bce13c9
Fix show_model_changes 2026-03-16 07:38:21 +00:00
Šarūnas Nejus
2565a74ad7
Change missing plugin to allow for filtering albums by release type (#5587)
Addresses #2661.  

Currently, the missing plugin when ran in album mode only allows for
getting all release groups attached to a single artist. Users may want
to restrict this search to only show releases of a specific type (such
as albums or compilations). This CR adds a new `--release-type` flag to
the missing plugin. If users want to filter to a specific type (or set
of types), they simply need to provide this flag for every release type
that they want included.

As part of this change, the default behavior has been shifted to only
select `album` type releases as is suggested in the issue- to avoid
breaking default behavior I could easily switch this back. I am also
wondering if it might make sense to address the following idea
(https://github.com/beetbox/beets/discussions/5101) in a follow-up.
Bug fix: This change also fixes a bug where `--album` mode incorrectly
reported albums already in the library as missing. The original code
compared release group IDs from MusicBrainz against `Album` objects
(which never matched). This now correctly compares against
`mb_releasegroupid`.
2026-03-16 06:58:12 +00:00
Brock Grassy
d21470042a Address comments 2026-03-16 06:52:35 +00:00
Brock Grassy
e36c09d69d Fix lint 2026-03-16 06:52:35 +00:00
Brock Grassy
2c60c3eb49 Address comments and add new test case 2026-03-16 06:52:35 +00:00
Brock Grassy
c51f68be15 Fix rebase in tests 2026-03-16 06:52:35 +00:00
Brock Grassy
a3b7cfa1b3 Add IOMixin to fix failures 2026-03-16 06:52:35 +00:00
Brock Grassy
4cef8c4093 Address review comments 2026-03-16 06:52:35 +00:00
Brock Grassy
7027060a0b Fix lint and mypy 2026-03-16 06:52:35 +00:00
Brock Grassy
6b62380b62 Change missing plugin to allow for filtering albums by release type 2026-03-16 06:52:35 +00:00
Šarūnas Nejus
0dd6df849d
Move utils from ui to util (#6440)
## Refactor: Extract UI utilities into `beets/util`

This PR decouples terminal/display utilities from `beets/ui` by moving
them into focused modules under `beets/util`. No user-facing behaviour
changes.

### What moved where

| Utility | From | To |
|---|---|---|
| `colorize`, `uncolorize`, `color_len`, `color_split`, ANSI constants |
`beets/ui/__init__.py` | `beets/util/color.py` |
| `colordiff`, `_field_diff`, `get_model_changes` |
`beets/ui/__init__.py` | `beets/util/diff.py` |
| `indent`, `split_into_lines`, `print_column_layout`,
`print_newline_layout` | `beets/ui/__init__.py` | `beets/util/layout.py`
|

### Notable design change in `layout.py`

`print_column_layout` / `print_newline_layout` previously called
`ui.print_()` internally, creating a hard dependency on `beets.ui`. They
are now renamed to `get_column_layout` / `get_newline_layout` and
converted to **generators**, yielding lines instead of printing them.
The caller (`display.py`) is responsible for printing via `ui.print_()`.

### New public API

`get_model_changes` is introduced in `beets/util/diff.py` as the pure,
testable function for computing field-level diffs. `show_model_changes`
in `beets/ui` now delegates to it.

### Tests

- Moved alongside the code: `test/util/test_color.py`,
`test/util/test_diff.py`, `test/util/test_layout.py`.
- Removed duplicate `ShowModelChangeTest` from `test/ui/test_ui.py` —
coverage is preserved in `test/util/test_diff.py`.
2026-03-16 01:28:40 +00:00
Šarūnas Nejus
41c835d9e9
Add types to moved utils 2026-03-14 14:08:51 +00:00
Šarūnas Nejus
3aaa4d0ce9
Add commits to .git-ignore-blame-revs 2026-03-14 12:02:31 +00:00
Šarūnas Nejus
72eaa98eaf
Refactor layout to remove dependency on ui 2026-03-14 12:02:30 +00:00
Šarūnas Nejus
ffb4329006
Fix layout references 2026-03-14 12:02:30 +00:00
Šarūnas Nejus
6a93bf54af
Move layout utils to beets/util/layout.py 2026-03-14 12:02:30 +00:00
Šarūnas Nejus
fc39ab791c
Create a dedicated get_model_changes function in beets/util/diff.py
- Add `get_model_changes` as the public API for computing diffs
- Remove tests for `show_model_changes` as test_diff.py fully covers them.
2026-03-14 12:02:30 +00:00
Šarūnas Nejus
1d54f2bf66
Fix diff references 2026-03-14 12:02:30 +00:00
Šarūnas Nejus
756d5c9921
Move diff utils to beets/util/diff.py 2026-03-14 11:58:04 +00:00
Šarūnas Nejus
a6fcb7ba0f
Fix references to color utils 2026-03-14 11:57:18 +00:00
Šarūnas Nejus
aa52aaca56
Move colorisation to beets/util/color.py 2026-03-14 11:57:18 +00:00
Šarūnas Nejus
3bcc539b2c
Feat: Smartplaylist: Add dest_regen option for regenerating destination path (#5621)
## Problem

1. When items are imported into the library in a don't copy-move mode
(`-C -M` options), they will be registered inside the Beets database
using their **original paths**. However, during subsequent processing
(*e.g.*, a `convert` operation), a path following the Beets path format
can be generated.
2. When generating playlists using `smartplaylist` plugin, only the path
registered inside the Beets database (the **original path**) can be use
inside the output playlist. This block the compatibility with other
plugins.

## Solution

I added a a new optional configuration option known as ``dest_regen``
(as well as its equivalent ``dest-regen`` on the CLI) to regenerate
items' path in the generated playlist instead of using the ones of the
library, just like a `convert` or a `move` operation would have done.
This operation will happen before the ``relative_to`` and ``prefix``
options, which makes sense to do so and not in another order, otherwise
this new option (``dest_regen``)) would overwrite the desired behavior
of the other mentioned options (``relative_to`` and ``prefix``). It is
then helpful to generate playlists compatible with the ``convert``
plugin.
2026-03-14 09:11:51 +00:00
Pierre Ayoub
78bc2d9d5e
chore(changelog): Move new feature under Unreleased section 2026-03-14 09:56:02 +01:00
Pierre Ayoub
49cb2f5544 chore(test_smartplaylist): Add future TODO about Mocks usage 2026-03-13 19:17:56 +00:00
Pierre Ayoub
074f4d4281 chore(changelog): Foramt with docstrfmt 2026-03-13 19:17:56 +00:00
Pierre Ayoub
fae242249a Update docs/changelog.rst
Rephrasing by Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-13 19:17:56 +00:00
Pierre Ayoub
5157ba6021 Update docs/plugins/smartplaylist.rst
Styling by Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-13 19:17:56 +00:00
Pierre Ayoub
1393cd0ae7 fix(test_smartplaylist.py): mypy type error as commit 002a051d0 2026-03-13 19:17:56 +00:00
Pierre Ayoub
7dfed4429f chore(docs): Lint double backquotes 2026-03-13 19:17:56 +00:00
Pierre Ayoub
523e504f5e fix(test_smartplaylist): Adapt to changes from commit d01727019
The aforementioned commits introduced a nmuber of changes since I
implemented this test:
- The syntax `self.assertExists(m3u_filepath)` was an old and now invalid
  way of checking existence of a path using assertion, change to `assert
  m3u_filepath.exists()` which now use string instead of bytes
- Use of `Path()` and strings instead of `path.join` and bytes for
  handling directory path
2026-03-13 19:17:56 +00:00
Pierre Ayoub
b798465a55 chore(docs): Format with docstrfmt 2026-03-13 19:17:56 +00:00
Pierre Ayoub
f5a08712b1 chore(test): Lint test_smartplaylist.py 2026-03-13 19:17:56 +00:00
Pierre Ayoub
e80fa746af chore(test): Format test_smartplaylist.py 2026-03-13 19:17:56 +00:00
Pierre Ayoub
2dcd8f4066 fix(test): Linting issues in smartplaylist 2026-03-13 19:17:56 +00:00