The old version of the `ftintitle.contains_feat` function could lead to
false positives by matching words like "and" and "with" in the title,
even if there was no "feat. X" part.
With this commit, the `for_artist` keyword is explicitly passed to the
`plugins.feat_tokens` function to disable these matches when matching a
title (and not an artist).
The previous version of the `plugins.feat_tokens` regular expression
only matched "feat. X" parts if preceded by a space. This caused missed
detections in the `ftintitle.contains_feat` function.
This commit adds unit tests for the updated regex that also matches
"feat. X" parts within parentheses and brackets
When checking whether a title or artist contains a feature, it now also
detects them when they are in parentheses or brackets, i.e., "Song Name
(feat. XYZ)" will return true.
#### Context
I noticed one of recently merged PRs used `unittest` assertions that we
are migrating from. Thus, I thought it would be a good idea to configure
our linting to catch such issues in the future. Since I was here, I
replaced our multiple linting and formatting tools with a single tool,
Ruff, to simplify and speed up our development workflow.
#### Summary
This PR migrates the codebase from using isort, Black and Flake8 to Ruff
for code formatting and linting. The changes include updates to the
GitHub Actions workflow, pre-commit configuration, and documentation to
reflect the new tooling.
#### Changes
1. **GitHub Actions Workflow**
- Updated `.github/workflows/lint.yml` to use `poetry install
--only=lint` and `poe lint --output-format=github`.
2. **Pre-commit Configuration**
- Replaced Black and Isort with Ruff in `.pre-commit-config.yaml`.
3. **Documentation**
- Updated `CONTRIBUTING.rst` to reflect the use of Ruff for formatting
and linting.
- Modified instructions for running tests and handling external API
requests.
4. **Poetry Configuration**
- Removed Black, Isort, Flake8, and related dependencies from
`poetry.lock` and `pyproject.toml`.
- Added Ruff as the new linter and formatter in `pyproject.toml`.
5. **Setup Configuration**
- Removed Flake8 configuration from `setup.cfg`.
6. **Git blame**
- Introduced `.git-blame-ignore-revs` file to keep git blame clean from
formatting
changes. Configure your local `beets` repository to use this file by
running:
```fish
$ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
```
#### Benefits
- **Performance**: Ruff is known for its speed and efficiency, which
should improve the developer experience.
- **Consolidation**: Using a single tool for both formatting and linting
simplifies the development workflow.
#### How to Test
1. **Linting and Formatting**
- Run `poe check-format` to check for formatting issues.
- Run `poe format` to format the codebase.
- Run `poe lint` to check for linting issues.
2. **Pre-commit Hooks**
- Ensure pre-commit hooks are working correctly by running `pre-commit
run --all-files`.
3. **CI Pipeline**
- Verify that the GitHub Actions workflow completes successfully.
#### Notes
- Contributions migrating existing tests from `unittest` to `pytest` are
welcome.
- External API requests should be mocked using `requests_mock` and
tested weekly in the integration test suite.
#### References
- [Ruff Documentation](https://docs.astral.sh/ruff/)
- [Pre-commit Hooks](https://pre-commit.com/hooks.html)
---
This PR aims to streamline our development process by adopting Ruff, a
modern and efficient tool for Python code formatting and linting.
This commit introduces a `.git-blame-ignore-revs` file to the
repository. The purpose of this file is to list specific commit hashes
that should be ignored when using the `git blame` command. This is
useful for ignoring commits that involve large-scale formatting changes,
refactoring, or other non-functional changes that would otherwise
clutter the blame history.
I added a couple of previous commit hashes which reformatted the code.
Configure this repository to use this file:
git config --local blame.ignoreRevsFile .git-blame-ignore-revs
The variable in `test_ordered_enum` was flagged for naming issues, and
I noticed that `OrderedEnum` is essentially `enum.IntEnum`.
I guess `OrderedEnum` exists because it was created before
`enum.IntEnum` was made available in Python 3.4. We do not need it
anymore though, so it's now gone.
* Replace `noqa` comments in `assert...` method definitions with
a configuration option to ignore these names.
* Use the `__all__` variable to specify importable items from the
module, replacing `*` imports and `noqa` comments for unused imports.
* Address issues with poorly named variables and methods by renaming
them appropriately.
- Fix imports
- Fix pytest issues
- Do not assign lambda as variable
- Use isinstance instead of type to check type
- Rename ambiguously named variables
- Name custom errors with Error suffix
This PR is Part 1 of the work #5215 that fixes typing issues in
`beets.util.__init__` module.
It addresses simple-to-fix / most of the issues in this module.
## Description
This PR adds gracefully handling requests error in teh Deezer plugin. Right now, it errors out when it receives error:
```bash
Traceback (most recent call last):
File "/home/arsaboo/.local/bin/beet", line 8, in <module>
sys.exit(main())
^^^^^^
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/ui/__init__.py", line 1865, in main
_raw_main(args)
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/ui/__init__.py", line 1852, in _raw_main
subcommand.func(lib, suboptions, subargs)
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/ui/commands.py", line 1395, in import_func
import_files(lib, paths, query)
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/ui/commands.py", line 1326, in import_files
session.run()
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/importer.py", line 360, in run
pl.run_parallel(QUEUE_SIZE)
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/util/pipeline.py", line 447, in run_parallel
raise exc_info[1].with_traceback(exc_info[2])
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/util/pipeline.py", line 312, in run
out = self.coro.send(msg)
^^^^^^^^^^^^^^^^^^^
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/util/pipeline.py", line 195, in coro
func(*(args + (task,)))
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/importer.py", line 1497, in lookup_candidates
task.lookup_candidates()
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/importer.py", line 688, in lookup_candidates
artist, album, prop = autotag.tag_album(
^^^^^^^^^^^^^^^^^^
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/autotag/match.py", line 548, in tag_album
for matched_candidate in hooks.album_candidates(
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/plugins.py", line 593, in decorated
for v in generator(*args, **kwargs):
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/autotag/hooks.py", line 759, in album_candidates
yield from plugins.candidates(items, artist, album, va_likely, extra_tags)
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/plugins.py", line 390, in candidates
yield from plugin.candidates(
^^^^^^^^^^^^^^^^^^
File "/home/arsaboo/.local/lib/python3.12/site-packages/beets/plugins.py", line 772, in candidates
results = self._search_api(query_type="album", filters=query_filters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/arsaboo/.local/lib/python3.12/site-packages/beetsplug/deezer.py", line 282, in _search_api
response.raise_for_status()
File "/home/arsaboo/.local/lib/python3.12/site-packages/requests/models.py", line 1024, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://api.deezer.com/search/album?q=album%3A%22Y+Hate+%3F%22+artist%3A%22Parmish+Verma%22
```
## To Do
- [ ] Documentation. (If you've added a new command-line flag, for example, find the appropriate page under `docs/` to describe it.)
- [x] Changelog. (Add an entry to `docs/changelog.rst` to the bottom of one of the lists near the top of the document.)
- [ ] Tests. (Very much encouraged but not strictly required.)
See my comment under #5406 for context
> The build on win32 is failing to install reflink because it's [only
supported until Python
3.7](https://gitlab.com/rubdos/pyreflink/-/blob/master/setup.py?ref_type=heads).
>
> I will address this in a separate PR and rebase this one accordingly
once the fix is merged.
>
> Note: this issue popped up now because I added a new requests-mock
dependency which invalidated cached dependencies.
## Description
This creates a new template function that capitalizes the text (make the
first character have upper case and the rest lower case). Example:
```console
beet list -f '%capitalize{$title}'
```
This does not do the same as the *%title* function.
(...)
## To Do
<!--
- If you believe one of below checkpoints is not required for the change
you
are submitting, cross it out and check the box nonetheless to let us
know.
For example: - [x] ~Changelog~
- Regarding the changelog, often it makes sense to add your entry only
once
reviewing is finished. That way you might prevent conflicts from other
PR's in
that file, as well as keep the chance high your description fits with
the
latest revision of your feature/fix.
- Regarding documentation, bugfixes often don't require additions to the
docs.
- Please remove the descriptive sentences in braces from the enumeration
below,
which helps to unclutter your PR description.
-->
- [x] Documentation.
- [x] Changelog.
- [x] Tests.
I believe this fixes#4785, but I might be misunderstanding the
description and it might already be fixed.
Tagging @JOJ0 since they created both the bug linked above, and
5bf4e3d92f which mentions it.
Utilize a [new way of declaring
NamedTuples](https://docs.python.org/3/library/typing.html#typing.NamedTuple),
which allows for typechecking as well. Maybe the latter is now redundant
in other places, but I'm not that familiar with the codebase yet, so I
just changed the declarations (and hopefully used the correct types).
While I was at it, I also ran `poetry update`, but I'll revert
poetry.lock in case I wasn't supposed to do that. This is my first
commit here, so I hope I didn't do anything wrong...