Skip to content
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

Unclear how to evaluate a marker for a set of extras #452

Open
pfmoore opened this issue Aug 17, 2021 · 8 comments
Open

Unclear how to evaluate a marker for a set of extras #452

pfmoore opened this issue Aug 17, 2021 · 8 comments

Comments

@pfmoore
Copy link
Member

pfmoore commented Aug 17, 2021

This is possibly similar to #448, but I think it's a different use case. I'm not completely clear on what "operations" #448 is meant to cover, so apologies if I missed that this is already part of that discussion.

I have two requirements:

a_req = Requirement("a[b,c]")
a_dep = Requirement("foo; extra == 'b'")

I want to check whether a_dep should apply, given that I am looking at it in the context of a_req. So, I have a set of extras, and I want to evaluate a_dep.marker to see if any apply. In the given case, I expect to get True.

The simplest way I can see is any(a_dep.marker.evaluate(environment={"extra": e}) for e in a_req.extras).

Is that the best way of doing this? Would it be useful to have an additional argument to Marker.evaluate() that specified a set of extras to check - then I could do a_dep.marker.evaluate(extras=a_req.extras) which seems more natural.

@pradyunsg
Copy link
Member

Well, that's definitely the best way to do it, as of today. Here's the relevant part in pip:

https://github.com/pypa/pip/blob/1df8934a97ac77f064e2b858b554d3fb5ce43fae/src/pip/_internal/req/req_install.py#L253

@McSinyx
Copy link

McSinyx commented Aug 27, 2021

Does PEP 508 forbid e.g. foo; extra == 'a' and extra == 'b'? I suppose no one is actually using this due to the way Marker.evaluate is implemented, but I couldn't find where it is explicitly forbidden.

@uranusjr
Copy link
Member

uranusjr commented Aug 27, 2021

It does not, but it is also very unclear what the expression means. PEP 508 is very vague about extra in markers, and both the name extra and the operator == are technically wrong (I think I said this somewhere on Discourse a while ago).

@pfmoore
Copy link
Member Author

pfmoore commented Aug 27, 2021

I agree, one of the reasons I found it hard to work out how to do this is that extras are conceptually a set, but packaging expects you to supply just one at a time, and that links back to PEP 508 using == which is only even remotely meaningful if an extra is a single value.

I doubt there's much hope of redesigning the semantics without a very extended debate, though, so we're probably stuck with what we have. I don't know if packaging could offer an API that smoothed over the weirdness at all (the idea of an extras argument to evaluate that I suggested above, for example). That's really the only reason for leaving this issue open, in case someone wants to do something with the API. Anything more fundamental would need a PEP and a wider discussion.

@uranusjr
Copy link
Member

uranusjr commented Aug 27, 2021

I’ve been planning a PEP in my head to “fix” extras once and for all. There’s no draft, but I’m thinking about doing three things:

  • Definitely define what is a valid extra name and how it’s normalised in the resolver (by standardising whatever pip is doing right now)
  • Introduce a new marker variable extras that’s a set of normalised extra names. The only valid operators are in and not in (which is actually implied since a marker_var can only be either a string literal or variable name, but it’s better to be explicit).
  • Remove extra and bump metadata version to 2.0.

BTW since this is going to bump the major version, I’m also thinking about doing two more things not strictly relavant here (but also related to extras):

  • A new metadata field Requires-Extra that specifies “default extras” to install when a package is requested with extra specification
  • Introduce a new syntax package[] to explicitly request installing a package without any extras.

Nothing concrete at this time though. Also anyone please feel free to steal any of the above idea if you have time to write a PEP 😄

@brettcannon
Copy link
Member

https://peps.python.org/pep-0685/ takes care of the normalization problem (once it's accepted).

@uranusjr
Copy link
Member

I proposed the rest of the comment above to discuss at the Packaging Summit next week.

@pradyunsg
Copy link
Member

A new metadata field Requires-Extra that specifies “default extras” to install when a package is requested with extra specification

nit: Call it Default-Extra (multiple use) please. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants