-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Improved beets/logging.py typing
#6032
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
Conversation
Reviewer's GuideThis PR refactors beets.logging.py to introduce precise type annotations (including overloads for getLogger, generics for log-safe conversion, and detailed signatures on StrFormatLogger methods) and modernizes test coverage by switching to pytest with parametrized inputs and caplog-based assertions. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
beets.logging.py typingbeets/logging.py typing
There was a problem hiding this 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 enhances the beets.logging.py module with improved typing annotations and modernizes the test suite. The primary purpose is to provide better type safety for developers using the beets logging system.
Key changes:
- Added precise return type annotations for
getLoggerfunction using overloads - Modernized test suite to use pytest with parametrized testing
- Added comprehensive type annotations throughout the logging module
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| beets/logging.py | Added type annotations, overloads for getLogger, and improved function signatures |
| test/test_logging.py | Converted from unittest to pytest with parametrized tests for better coverage |
| docs/changelog.rst | Added changelog entry documenting the typing improvements |
| .github/CODEOWNERS | Added specific ownership for metadata_plugins.py (unrelated to logging changes) |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `beets/logging.py:98-107` </location>
<code_context>
class _LogMessage:
- def __init__(self, msg, args, kwargs):
+ def __init__(
+ self,
+ msg: str,
+ args: logging._ArgsType,
+ kwargs: dict[str, Any],
+ ):
self.msg = msg
</code_context>
<issue_to_address>
**suggestion:** Using logging._ArgsType and dict[str, Any] may reduce compatibility with older Python versions.
Consider replacing logging._ArgsType with a public type like Sequence[Any], and dict[str, Any] with Dict[str, Any] for better compatibility with older Python versions.
```suggestion
from typing import Any, Sequence, Dict
class _LogMessage:
def __init__(
self,
msg: str,
args: Sequence[Any],
kwargs: Dict[str, Any],
):
self.msg = msg
self.args = args
self.kwargs = kwargs
```
</issue_to_address>
### Comment 2
<location> `beets/logging.py:127` </location>
<code_context>
- stacklevel = kwargs.pop("stacklevel", 1)
- stacklevel = {"stacklevel": stacklevel}
+ if isinstance(msg, str):
+ msg = self._LogMessage(msg, args, kwargs)
</code_context>
<issue_to_address>
**suggestion:** The conditional wrapping of msg in _LogMessage may lead to inconsistent message handling.
Consider enforcing or documenting the expected type of msg to prevent inconsistent formatting when msg is not a str.
Suggested implementation:
```python
"""
Log msg.format(*args, **kwargs)
Args:
msg (str): The log message format string. Must be a string.
Raises:
TypeError: If msg is not a string.
"""
```
```python
if not isinstance(msg, str):
raise TypeError(f"msg must be a str, got {type(msg).__name__}")
msg = self._LogMessage(msg, args, kwargs)
```
</issue_to_address>
### Comment 3
<location> `beets/logging.py:177-180` </location>
<code_context>
-# Override the `getLogger` to use our machinery.
-def getLogger(name=None): # noqa
+@overload
+def getLogger(name: str) -> BeetsLogger: ...
+@overload
+def getLogger(name: None = ...) -> RootLogger: ...
+def getLogger(name=None) -> BeetsLogger | RootLogger: # noqa: N802
if name:
</code_context>
<issue_to_address>
**suggestion:** Overload signatures for getLogger may not match runtime behavior exactly.
The implementation returns Logger.root when None is passed, which may not be typed as RootLogger. Please align the runtime return type with the overloads or update the overloads for consistency.
</issue_to_address>
### Comment 4
<location> `test/test_logging.py:65` </location>
<code_context>
+ with caplog.at_level(level, logger="test_logger"):
+ logger.log(level, msg, *args, **kwargs)
+
+ assert str(caplog.records[0].msg) == expected
</code_context>
<issue_to_address>
**suggestion (testing):** Assert that all log records are as expected, not just the first.
Only the first log record is asserted. If multiple logs are expected, iterate through all records or assert the total count to ensure accuracy.
```suggestion
# Assert that all log records are as expected
assert len(caplog.records) == 1, f"Expected 1 log record, got {len(caplog.records)}"
for record in caplog.records:
assert str(record.msg) == expected
```
</issue_to_address>
### Comment 5
<location> `beets/logging.py:182-185` </location>
<code_context>
def getLogger(name=None) -> BeetsLogger | RootLogger: # noqa: N802
if name:
return my_manager.getLogger(name) # type: ignore[return-value]
else:
return Logger.root
</code_context>
<issue_to_address>
**suggestion (code-quality):** Replace if statement with if expression ([`assign-if-exp`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/assign-if-exp/))
```suggestion
return my_manager.getLogger(name) if name else Logger.root
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6032 +/- ##
==========================================
+ Coverage 66.71% 66.92% +0.20%
==========================================
Files 117 117
Lines 18128 18133 +5
Branches 3073 3076 +3
==========================================
+ Hits 12095 12135 +40
+ Misses 5378 5338 -40
- Partials 655 660 +5
🚀 New features to boost your workflow:
|
and added myself to codeowners file.
issues with the ci. Also python 3.9 requires unions here...
This PR enhances
beets/logging.pywith improved typing and tests:getLoggernow returns the precise logger type (BeetsLoggerorRootLogger).pytestandparametrizefor more concise and readable coverage.