11from __future__ import annotations
22
33from collections import defaultdict
4+ from collections .abc import Mapping
45from logging import getLogger
56from typing import Any
67
78from pip ._vendor .resolvelib .reporters import BaseReporter
89
9- from .base import Candidate , Requirement
10+ from .base import Candidate , Constraint , Requirement
1011
1112logger = getLogger (__name__ )
1213
1314
1415class PipReporter (BaseReporter [Requirement , Candidate , str ]):
15- def __init__ (self ) -> None :
16+ def __init__ (self , constraints : Mapping [ str , Constraint ] | None = None ) -> None :
1617 self .reject_count_by_package : defaultdict [str , int ] = defaultdict (int )
18+ self ._constraints = constraints or {}
1719
1820 self ._messages_at_reject_count = {
1921 1 : (
@@ -35,25 +37,36 @@ def __init__(self) -> None:
3537 }
3638
3739 def rejecting_candidate (self , criterion : Any , candidate : Candidate ) -> None :
40+ """Report a candidate being rejected.
41+
42+ Logs both the rejection count message (if applicable) and details about
43+ the requirements and constraints that caused the rejection.
44+ """
3845 self .reject_count_by_package [candidate .name ] += 1
3946
4047 count = self .reject_count_by_package [candidate .name ]
41- if count not in self ._messages_at_reject_count :
42- return
43-
44- message = self ._messages_at_reject_count [count ]
45- logger .info ("INFO: %s" , message .format (package_name = candidate .name ))
48+ if count in self ._messages_at_reject_count :
49+ message = self ._messages_at_reject_count [count ]
50+ logger .info ("INFO: %s" , message .format (package_name = candidate .name ))
4651
4752 msg = "Will try a different candidate, due to conflict:"
4853 for req_info in criterion .information :
4954 req , parent = req_info .requirement , req_info .parent
50- # Inspired by Factory.get_installation_error
5155 msg += "\n "
5256 if parent :
5357 msg += f"{ parent .name } { parent .version } depends on "
5458 else :
5559 msg += "The user requested "
5660 msg += req .format_for_error ()
61+
62+ # Add any relevant constraints
63+ if self ._constraints :
64+ name = candidate .name
65+ constraint = self ._constraints .get (name )
66+ if constraint and constraint .specifier :
67+ constraint_text = f"{ name } { constraint .specifier } "
68+ msg += f"\n The user requested (constraint) { constraint_text } "
69+
5770 logger .debug (msg )
5871
5972
0 commit comments