On closer inspection of stuff I probably should have noticed in the first place, I've concluded that some of the stuff I want to do with pip is probably easier than I thought.
Here's the deal. find_candidates constructs a set of Candidates and a list of InstallRequirements. I'm trying to figure out if I can rely on those always having some value when I want them to. The kinds of requirements that need to be processed are:
- ExplicitRequirement. I'll come back to this. (provides candidate)
- SpecifierRequirement. I think this is the kind of requirement I'll most want to have working. (provides ireq)
- RequiresPythonRequirement. I don't... think this should ever be relevant? (never provides ireq)
- UnsatisfiableRequirement. I can hardly improve on this situation.
Okay, so, the Factory makes ExplicitRequirements that contain candidates with a link, but either the link matches, in which case there's no work to do, or the link doesn't match, in which case it's unsatisfiable and I don't need to do anything. The other source of ExplicitRequirements is ExtrasCandidates.
I've got a hypothesis about how this works, but I'm not confident: ExtrasCandidates wrap specific existing Candidates (because otherwise how could you determine the extras requirements), so ExtrasCandidates shouldn't come into play when generating candidates in the first place. Let's keep that in mind as something that might go wrong.
So, for the normal case of taking a SpecifierRequirement and creating a candidate from a Link, we have the following flow:
- If there isn't an ireq, skip the rest of these steps and continue with _iter_found_candidates, which may need to be changed some.
- If there aren't URL constraints, skip the rest of these steps, as above.
- If the first URL constraint points to an incompatible wheel, skip as above.
- Use the first of each (in the case of ireqs, for consistency, in the case of links, because multiple links break it anyway) with _make_candidate_from_link, doing the full due diligence to populate all of the arguments correctly.
- Add the candidate to explicit_candidates.
I'll need to re-evaluate whether _iter_found_candidates needs to change any. Also, I'm not sure whether to pass extras to _make_candidate_from_link. On the one hand, "project with extras" is a different node from "project", so their candidates are not interchangeable. On the other hand, if not there, then where?
I think I'm misunderstanding something, but I'm not sure what. I think I need to review the documentation for how pip's resolver works.
Wait, if the loop lives in the vendored resolvelib, that would mean that the extras could be built up across multiple invocations. I'll have to see if that works out, and if that actually helps.
Thinking about this more, I'm slightly more confident.
I'm also tired. I'm going to wrap up now, because there's no point in drawing this out.