refactor: convert f-string logging to lazy %-style format (G004)

Sweep all 1676 G004 violations across 112 files, converting
`logger.<level>(f"…{x}…")` to `logger.<level>("…%s…", x)`.

Why: ruff rule G004 was added to pyproject.toml to enforce lazy
%-style logging — defers formatting until the log level is enabled
and lets structured log tooling match the unformatted template.

Conversion preserves rendered output byte-for-byte:
- `{x}` → `%s` + `x`
- `{x!r}` / `{x!s}` / `{x!a}` → `%r` / `%s` / `%a`
- Format specs (`{x:.2f}`, `{x:>10}`) → `%s` + `format(x, 'spec')`
  (printf-style specs aren't 1:1 with Python format specs, so we
  delegate to `format()` to keep identical output)
- Literal `%` → `%%`
- Concatenated f-strings (`f"a {x} " "b"`) flattened
- Trailing kwargs (`exc_info=True`) preserved

Verified:
- `uv run ruff check --select G004` → 0 violations
- `uv run ty check -- nextcloud_mcp_server` → passes
- `uv run pytest tests/unit/` → 1010 passed

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-05-13 01:12:17 +02:00
co-authored by Claude Opus 4.7
parent a4e6125d28
commit 665cb9b1eb
112 changed files with 2534 additions and 1859 deletions
+15 -15
View File
@@ -25,7 +25,7 @@ async def test_deck_mcp_connectivity(nc_mcp_client: ClientSession):
assert expected_tool in tool_names, (
f"Expected deck tool '{expected_tool}' not found in available tools"
)
logger.info(f"Found expected deck tool: {expected_tool}")
logger.info("Found expected deck tool: %s", expected_tool)
# List available resource templates
templates = await nc_mcp_client.list_resource_templates()
@@ -40,7 +40,7 @@ async def test_deck_mcp_connectivity(nc_mcp_client: ClientSession):
assert expected_template in template_uris, (
f"Expected deck template '{expected_template}' not found"
)
logger.info(f"Found expected deck resource template: {expected_template}")
logger.info("Found expected deck resource template: %s", expected_template)
# List available resources
resources = await nc_mcp_client.list_resources()
@@ -55,7 +55,7 @@ async def test_deck_mcp_connectivity(nc_mcp_client: ClientSession):
assert expected_resource in resource_uris, (
f"Expected deck resource '{expected_resource}' not found"
)
logger.info(f"Found expected deck resource: {expected_resource}")
logger.info("Found expected deck resource: %s", expected_resource)
async def test_deck_board_crud_workflow_mcp(
@@ -68,7 +68,7 @@ async def test_deck_board_crud_workflow_mcp(
board_color = "0000FF" # Blue
# 1. Create board via MCP
logger.info(f"Creating board via MCP: {board_title}")
logger.info("Creating board via MCP: %s", board_title)
create_result = await nc_mcp_client.call_tool(
"deck_create_board",
{"title": board_title, "color": board_color},
@@ -81,7 +81,7 @@ async def test_deck_board_crud_workflow_mcp(
created_board_response = json.loads(created_board_json)
board_id = created_board_response["id"]
logger.info(f"Board created via MCP with ID: {board_id}")
logger.info("Board created via MCP with ID: %s", board_id)
assert created_board_response["title"] == board_title
assert created_board_response["color"] == board_color
@@ -94,7 +94,7 @@ async def test_deck_board_crud_workflow_mcp(
logger.info("Board creation verified via direct client")
# 3. Read board via MCP resource
logger.info(f"Reading board via MCP resource: {board_id}")
logger.info("Reading board via MCP resource: %s", board_id)
read_result = await nc_mcp_client.read_resource(f"nc://Deck/boards/{board_id}")
assert len(read_result.contents) == 1, "Expected exactly one content item"
read_board_data = json.loads(read_result.contents[0].text)
@@ -104,7 +104,7 @@ async def test_deck_board_crud_workflow_mcp(
logger.info("Board read via MCP resource successfully")
# 4. Verify board via direct read of resource
logger.info(f"Verifying board via resource read: {board_id}")
logger.info("Verifying board via resource read: %s", board_id)
# This was already done in step 3, so we'll just log confirmation
logger.info("Board structure verified successfully")
@@ -124,7 +124,7 @@ async def test_deck_board_crud_workflow_mcp(
# Clean up - delete board
await nc_client.deck.delete_board(board_id)
logger.info(f"Cleaned up board ID: {board_id}")
logger.info("Cleaned up board ID: %s", board_id)
async def test_deck_board_operations_error_handling_mcp(nc_mcp_client: ClientSession):
@@ -143,7 +143,7 @@ async def test_deck_board_operations_error_handling_mcp(nc_mcp_client: ClientSes
logger.info("Invalid board creation correctly failed via MCP tool")
# Test read non-existent board via MCP resource
logger.info(f"Testing read non-existent board via MCP resource: {non_existent_id}")
logger.info("Testing read non-existent board via MCP resource: %s", non_existent_id)
try:
read_result = await nc_mcp_client.read_resource(
f"nc://Deck/boards/{non_existent_id}"
@@ -153,7 +153,7 @@ async def test_deck_board_operations_error_handling_mcp(nc_mcp_client: ClientSes
"Expected empty content for non-existent board"
)
except Exception as e:
logger.info(f"Read non-existent board correctly failed via MCP resource: {e}")
logger.info("Read non-existent board correctly failed via MCP resource: %s", e)
async def test_deck_board_creation_validation_mcp(nc_mcp_client: ClientSession):
@@ -185,11 +185,11 @@ async def test_deck_board_creation_success_mcp(
assert create_result.isError is False, "Valid board creation should succeed"
created_board = json.loads(create_result.content[0].text)
board_id = created_board["id"]
logger.info(f"Valid board created successfully with ID: {board_id}")
logger.info("Valid board created successfully with ID: %s", board_id)
# Clean up - delete board
await nc_client.deck.delete_board(board_id)
logger.info(f"Cleaned up board ID: {board_id}")
logger.info("Cleaned up board ID: %s", board_id)
async def test_deck_workflow_integration_mcp(
@@ -202,7 +202,7 @@ async def test_deck_workflow_integration_mcp(
board_title = board_data["title"]
# 1. Read board via MCP to verify the structure
logger.info(f"Reading board via MCP resource: {board_id}")
logger.info("Reading board via MCP resource: %s", board_id)
read_result = await nc_mcp_client.read_resource(f"nc://Deck/boards/{board_id}")
board_mcp_data = json.loads(read_result.contents[0].text)
@@ -219,7 +219,7 @@ async def test_deck_workflow_integration_mcp(
logger.info("Board found in boards list")
# 3. Verify board data matches via resource (already done in step 1)
logger.info(f"Board data verification completed for board: {board_id}")
logger.info("Board data verification completed for board: %s", board_id)
logger.info("Board structure and data verified successfully")
@@ -250,7 +250,7 @@ async def test_deck_card_comment_crud_workflow_mcp(
assert comment["objectId"] == card_id
assert comment["message"] == "Initial comment"
assert comment["replyTo"] is None
logger.info(f"Created comment ID {comment_id} on card {card_id}")
logger.info("Created comment ID %s on card %s", comment_id, card_id)
# 2. List comments via MCP — verify the new comment is present
list_result = await nc_mcp_client.call_tool(