Skip to content

Commit ac61d71

Browse files
committed
Don't assume that LogRecord.args is a tuple
In the context of pip, and especially when `rich=True`, I bet it *is* true that `LogRecord.args` is always a tuple. However, in general, this is not true. Single argument dicts actually [are treated specially by Python's logging infrastructure](https://github.com/python/cpython/blob/v3.11.9/Lib/logging/__init__.py#L301-L320): >>> def build_record(*args): ... return LogRecord(name="name", level=0, pathname="pathname", lineno=42, msg="msg", args=args, exc_info=False).args ... >>> build_record({"foo": 42}, {"bar": 43}) ({'foo': 42}, {'bar': 43}) # <-- this is a tuple! >>> build_record(42) (42,) # <-- this is a tuple! >>> build_record({"foo": 42}) {'foo': 42} # <-- this is not a tuple! This fixes #12751 While I was in here, I also changed our logging story so we can actually capture the full stacktrace when logging is turned up. That would have been quite useful for me when debugging this issue, and would also be useful for folks debugging keyring backends. Hopefully this is uncontroversial. Happy to split this out into a separate PR if folks prefer.
1 parent 86b8b23 commit ac61d71

File tree

3 files changed

+6
-1
lines changed

3 files changed

+6
-1
lines changed

news/12751.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Avoid keyring logging crashes when pip is run in verbose mode.

src/pip/_internal/network/auth.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ def _get_keyring_auth(
271271
try:
272272
return self.keyring_provider.get_auth_info(url, username)
273273
except Exception as exc:
274+
# Log the full exception (with stacktrace) at debug, so it'll only
275+
# show up when running in verbose mode.
276+
logger.debug("Keyring is skipped due to an exception", exc_info=True)
277+
# Always log a shortened version of the exception.
274278
logger.warning(
275279
"Keyring is skipped due to an exception: %s",
276280
str(exc),

src/pip/_internal/utils/logging.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ def emit(self, record: logging.LogRecord) -> None:
154154
style: Optional[Style] = None
155155

156156
# If we are given a diagnostic error to present, present it with indentation.
157-
assert isinstance(record.args, tuple)
158157
if getattr(record, "rich", False):
158+
assert isinstance(record.args, tuple)
159159
(rich_renderable,) = record.args
160160
assert isinstance(
161161
rich_renderable, (ConsoleRenderable, RichCast, str)

0 commit comments

Comments
 (0)