Skip to content

Replace percent, string concat, format calls with f-strings #5890

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

snejus
Copy link
Member

@snejus snejus commented Jul 21, 2025

This PR modernizes the codebase by replacing all str.format() calls, % operator, and most of string concatenation with f-string literals.

Fixes #5293
Supersedes #5337

Once this is reviewed, I will squash all commits into one and add the hash to .git-blame-ignore-revs file.

@snejus snejus requested review from Copilot, semohr and wisp3rwind July 21, 2025 11:00
Copy link

Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR modernizes the codebase by replacing all str.format() calls, % operator, and most string concatenation with f-string literals, following modern Python best practices.

  • Replaces percentage string formatting (%) with f-strings
  • Replaces str.format() calls with f-strings
  • Updates string concatenation patterns to use f-strings where appropriate

Reviewed Changes

Copilot reviewed 87 out of 87 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/test_ui.py Replaces percentage formatting and string concatenation with f-strings
test/test_logging.py Converts string concatenation in logging calls to f-strings
test/test_library.py Updates percentage formatting to f-strings
test/test_dbcore.py Converts SQL query formatting to f-strings
test/test_datequery.py Replaces string concatenation with f-strings
test/test_art_resize.py Simplifies command construction with list unpacking
test/plugins/ Multiple plugin test files updated to use f-strings
docs/ Documentation examples updated to use f-strings
beetsplug/ Plugin modules updated to use f-strings throughout
beets/ Core module files updated with f-string formatting

@snejus snejus force-pushed the use-f-string branch 2 times, most recently from 90d5f7e to a05f9fc Compare July 21, 2025 19:54
@semohr
Copy link
Contributor

semohr commented Jul 30, 2025

I just took a quick look, and I strongly disagree with using f-strings for SQL transactions. Interpolating values directly into SQL queries using f-strings (or .format) exposes users to SQL injection vulnerabilities, which is a major security risk.

Instead, we should always use parameterized queries, like:

tx.query("INSERT INTO foo VALUES (%s, %s, %s, %s, %s)", (num, string, ...))
# or even
tx.query("INSERT INTO foo VALUES (?,?,?)", data)

fyi: this is also mentioned in the sqlite3 docs.

It might also be worth looking into backport templatestrings as they would fix this issue. https://docs.python.org/3.14/library/string.templatelib.html

Addition: It seems like we are good on that front and only use fstring for table names 👍 We should still add a note to the contribution guide, as at the moment it is a bit misleading.

@snejus
Copy link
Member Author

snejus commented Aug 2, 2025

I just took a quick look, and I strongly disagree with using f-strings for SQL transactions. Interpolating values directly into SQL queries using f-strings (or .format) exposes users to SQL injection vulnerabilities, which is a major security risk.

Instead, we should always use parameterized queries, like:

tx.query("INSERT INTO foo VALUES (%s, %s, %s, %s, %s)", (num, string, ...))
# or even
tx.query("INSERT INTO foo VALUES (?,?,?)", data)

fyi: this is also mentioned in the sqlite3 docs.

It might also be worth looking into backport templatestrings as they would fix this issue. https://docs.python.org/3.14/library/string.templatelib.html

Addition: It seems like we are good on that front and only use fstring for table names 👍 We should still add a note to the contribution guide, as at the moment it is a bit misleading.

My intention here was to replace .format calls, string concatenation and percent-based formatting by f-strings - thus keeping functionality unchanged.

Did I mistakenly replace SQLite args with an f-string somewhere?

Copy link

codecov bot commented Aug 2, 2025

Codecov Report

❌ Patch coverage is 50.00000% with 233 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (master@e3574a7). Learn more about missing BASE report.

Files with missing lines Patch % Lines
beetsplug/bpd/__init__.py 2.85% 34 Missing ⚠️
beetsplug/fish.py 0.00% 18 Missing ⚠️
beetsplug/chroma.py 0.00% 11 Missing ⚠️
beetsplug/beatport.py 16.66% 10 Missing ⚠️
beetsplug/lastimport.py 0.00% 9 Missing ⚠️
beetsplug/ipfs.py 11.11% 8 Missing ⚠️
beets/ui/__init__.py 72.00% 7 Missing ⚠️
beets/ui/commands.py 85.41% 7 Missing ⚠️
beetsplug/replaygain.py 56.25% 7 Missing ⚠️
beetsplug/discogs.py 25.00% 6 Missing ⚠️
... and 52 more
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@semohr
Copy link
Contributor

semohr commented Aug 2, 2025

Did I mistakenly replace SQLite args with an f-string somewhere?

I don't think you did, looks well done to me 👍

I was a bit worried because I read the docs changes first which are now a bit misleading. Would it be possible to add a single sentence to the dev docs? Something alike to:

  • ...make sure to properly escape user exposed query parameters using the ? format, to reduce the risk of sql injections see sqlite3 docs...

@snejus
Copy link
Member Author

snejus commented Aug 7, 2025

Did I mistakenly replace SQLite args with an f-string somewhere?

I don't think you did, looks well done to me 👍

I was a bit worried because I read the docs changes first which are now a bit misleading. Would it be possible to add a single sentence to the dev docs? Something alike to:

* ...make sure to properly escape user exposed query parameters using the `?` format, to reduce the risk of sql injections see sqlite3 docs...

Is it necessary? Plugin developers are expected to use our query wrappers instead of tinkering with SQL directly. I was looking at docs/dev/library.py to find a relevant place to add your suggestion, but it seems out of place given that it covers our abstractions.

@semohr
Copy link
Contributor

semohr commented Aug 7, 2025

I was thinking in the contribution guide, where we show the g.lib.transaction examples as this was why I was a bit scared/confused initially.

I guess at the end of the - Whenever you access the library database, do so through the provided... block should work?

Underneath it, we say use f-string, which might be misleading imo. But you are right, on the other hand we might be fine with just hoping everyone who goes this deep into our codebase knows what they are doing. We always have reviews to catch such issue.

@snejus
Copy link
Member Author

snejus commented Aug 7, 2025

@semohr I added a couple of more commits to standardise our logging calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update to use f-strings instead of .format now that Python 3.8 is supported
2 participants