@@ -38,13 +38,29 @@ class Transaction:
3838 verbose : bool | int | None = None
3939 constraints : list [str ] | None = None
4040
41- def __post_init__ (self ):
41+ def __post_init__ (self ) -> None :
4242 # If index_urls is None, pyodide-lock.json have to be searched first.
4343 # TODO: when PyPI starts to support hosting WASM wheels, this might be deleted.
4444 self .search_pyodide_lock_first = (
4545 self .index_urls == package_index .DEFAULT_INDEX_URLS
4646 )
4747
48+ self .constrained_reqs : dict [str , Requirement ] = {}
49+
50+ for constraint in self .constraints or []:
51+ con = Requirement (constraint )
52+ if not con .name :
53+ logger .debug ("Transaction: discarding nameless constraint: %s" , con )
54+ continue
55+ if con .extras :
56+ logger .debug ("Transaction: discarding [extras] constraint: %s" , con )
57+ continue
58+ if not con .url or len (con .specifier ):
59+ logger .debug ("Transaction: discarding versionless constraint: %s" , con )
60+ continue
61+ con .name = canonicalize_name (con .name )
62+ self .constrained_reqs [con .name ] = con
63+
4864 async def gather_requirements (
4965 self ,
5066 requirements : list [str ] | list [Requirement ],
@@ -88,6 +104,14 @@ def check_version_satisfied(self, req: Requirement) -> tuple[bool, str]:
88104 f"Requested '{ req } ', " f"but { req .name } =={ ver } is already installed"
89105 )
90106
107+ def constrain_requirement (self , req : Requirement ) -> Requirement :
108+ """Provide a constrained requirement, if available, or the original."""
109+ constrained_req = self .constrained_reqs .get (canonicalize_name (req .name ))
110+ if constrained_req :
111+ logger .debug ("Transaction: %s constrained to %s" , req , constrained_req )
112+ return constrained_req
113+ return req
114+
91115 async def add_requirement_inner (
92116 self ,
93117 req : Requirement ,
@@ -100,6 +124,8 @@ async def add_requirement_inner(
100124 for e in req .extras :
101125 self .ctx_extras .append ({"extra" : e })
102126
127+ req = self .constrain_requirement (req )
128+
103129 if self .pre :
104130 req .specifier .prereleases = True
105131
@@ -136,6 +162,7 @@ def eval_marker(e: dict[str, str]) -> bool:
136162 eval_marker (e ) for e in self .ctx_extras
137163 ):
138164 return
165+
139166 # Is some version of this package is already installed?
140167 req .name = canonicalize_name (req .name )
141168
0 commit comments