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:
co-authored by
Claude Opus 4.7
parent
a4e6125d28
commit
665cb9b1eb
@@ -93,13 +93,14 @@ class NotesClient(BaseNextcloudClient):
|
||||
for note in response_data:
|
||||
note_id = note.get("id")
|
||||
if note_id is None:
|
||||
logger.warning(f"Skipping note without ID: {note}")
|
||||
logger.warning("Skipping note without ID: %s", note)
|
||||
continue
|
||||
|
||||
# Skip duplicates (API returns all IDs in last chunk for deletion detection)
|
||||
if note_id in seen_ids:
|
||||
logger.debug(
|
||||
f"Skipping duplicate note {note_id} (pruned version in last chunk)"
|
||||
"Skipping duplicate note %s (pruned version in last chunk)",
|
||||
note_id,
|
||||
)
|
||||
continue
|
||||
|
||||
@@ -152,10 +153,10 @@ class NotesClient(BaseNextcloudClient):
|
||||
if category is not None:
|
||||
old_note = await self.get_note(note_id)
|
||||
old_category = old_note.get("category", "")
|
||||
logger.info(f"Current category for note {note_id}: '{old_category}'")
|
||||
logger.info("Current category for note %s: '%s'", note_id, old_category)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Could not fetch current note {note_id} details before update: {e}"
|
||||
"Could not fetch current note %s details before update: %s", note_id, e
|
||||
)
|
||||
old_note = None
|
||||
|
||||
@@ -169,7 +170,7 @@ class NotesClient(BaseNextcloudClient):
|
||||
body["category"] = category
|
||||
|
||||
logger.info(
|
||||
f"Attempting to update note {note_id} with etag {etag}. Body: {body}"
|
||||
"Attempting to update note %s with etag %s. Body: %s", note_id, etag, body
|
||||
)
|
||||
|
||||
response = await self._make_request(
|
||||
@@ -180,7 +181,7 @@ class NotesClient(BaseNextcloudClient):
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"Update response for note {note_id}: Status {response.status_code}"
|
||||
"Update response for note %s: Status %s", note_id, response.status_code
|
||||
)
|
||||
updated_note = _expect_note_object(response.json(), operation="update_note")
|
||||
|
||||
@@ -191,7 +192,9 @@ class NotesClient(BaseNextcloudClient):
|
||||
and old_note.get("category", "") != category
|
||||
):
|
||||
logger.info(
|
||||
f"Category changed from '{old_note.get('category', '')}' to '{category}' - cleaning up old attachment directory"
|
||||
"Category changed from '%s' to '%s' - cleaning up old attachment directory",
|
||||
old_note.get("category", ""),
|
||||
category,
|
||||
)
|
||||
try:
|
||||
webdav_client = WebDAVClient(self._client, self.username)
|
||||
@@ -200,7 +203,9 @@ class NotesClient(BaseNextcloudClient):
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Error cleaning up old attachment directory for note {note_id}: {e}"
|
||||
"Error cleaning up old attachment directory for note %s: %s",
|
||||
note_id,
|
||||
e,
|
||||
)
|
||||
|
||||
return updated_note
|
||||
@@ -220,20 +225,23 @@ class NotesClient(BaseNextcloudClient):
|
||||
potential_categories.append("") # Empty category
|
||||
|
||||
logger.info(
|
||||
f"Note {note_id} has category: '{category}', will check attachment directories in: {potential_categories}"
|
||||
"Note %s has category: '%s', will check attachment directories in: %s",
|
||||
note_id,
|
||||
category,
|
||||
potential_categories,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Could not fetch note {note_id} details before deletion: {e}"
|
||||
"Could not fetch note %s details before deletion: %s", note_id, e
|
||||
)
|
||||
potential_categories = ["", "Unknown"] # Try common categories
|
||||
|
||||
# Delete the note via API
|
||||
logger.info(f"Deleting note {note_id} via API")
|
||||
logger.info("Deleting note %s via API", note_id)
|
||||
response = await self._make_request(
|
||||
"DELETE", f"/apps/notes/api/v1/notes/{note_id}"
|
||||
)
|
||||
logger.info(f"Note {note_id} deleted successfully via API")
|
||||
logger.info("Note %s deleted successfully via API", note_id)
|
||||
json_response = response.json()
|
||||
|
||||
# Clean up attachment directories
|
||||
@@ -245,16 +253,16 @@ class NotesClient(BaseNextcloudClient):
|
||||
await webdav_client.cleanup_note_attachments(note_id, cat)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Failed to cleanup attachments for category '{cat}': {e}"
|
||||
"Failed to cleanup attachments for category '%s': %s", cat, e
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error during attachment cleanup: {e}")
|
||||
logger.warning("Error during attachment cleanup: %s", e)
|
||||
|
||||
return json_response
|
||||
|
||||
async def append_content(self, note_id: int, content: str) -> Dict[str, Any]:
|
||||
"""Append content to an existing note with a separator."""
|
||||
logger.info(f"Appending content to note {note_id}")
|
||||
logger.info("Appending content to note %s", note_id)
|
||||
|
||||
# Get current note
|
||||
current_note = await self.get_note(note_id)
|
||||
@@ -270,7 +278,9 @@ class NotesClient(BaseNextcloudClient):
|
||||
new_content = content # No separator needed for empty notes
|
||||
|
||||
logger.info(
|
||||
f"Combining existing content ({len(existing_content)} chars) with new content ({len(content)} chars)"
|
||||
"Combining existing content (%s chars) with new content (%s chars)",
|
||||
len(existing_content),
|
||||
len(content),
|
||||
)
|
||||
|
||||
# Update with combined content
|
||||
|
||||
Reference in New Issue
Block a user