[Distutils] Environment marker expression types

Daniel Holth dholth at gmail.com
Fri Apr 26 03:56:58 CEST 2013


On Thu, Apr 25, 2013 at 8:12 PM, PJ Eby <pje at telecommunity.com> wrote:
> I was just fiddling with an experimental environment marker
> implementation for setuptools, and ran across a bit of a quirk in the
> spec.  It says that the value of 'extra' is 'None', but that
> comparisons can only be done on strings.
>
> This leads to two problems: first, the syntax doesn't have a way to
> spell 'None', so you can't actually compare it to something.  Second,
> if you compare it to a string using the equality operators, IIUC
> you'll get a TypeError under Python 3.
>
> Should it actually be defaulting 'extra' to an empty string?  That
> would actually make a lot more sense, and avoid the issue of
> implementing non-string comparisons, None literals, etc.
>
> (Doing extras in this way actually has another problem, btw, which is
> that it's insane to do a != comparison on an 'extra'.  And there are
> probably other insane operations on extras, because unlike everything
> else, the extra would need to be dynamically evaluated.  I think it
> would probably be an improvement to remove extras from the environment
> marker system altogether and just have a mapping of extras instead,
> ala setuptools.  But that can be treated as a separate issue from the
> 'None' problem.)

I wondered when someone was going to bring that up.

Markerlib, currently a part of distribute as _markerlib, works by
compiling each unique conditional (environment marker) to a function
using the AST module. One of the arguments to the function is "extra"
and the rest are the ordinary environment marker names like os and
python version.

(Markerlib also takes advantage of the fact that in AST/eval land
variable names can have dots in them without triggering attribute
access which I think is kindof cool.)

Once the marker is compiled it is really fast to evaluate a few times
which we do for extras (number of extras declared + 1 times). The way
they are evaluated  / defined is designed to limit mischief like
installing different requirements if two extras are requested at once
instead of installing one extra, and then later installing the other.

It wouldn't make sense to write "None" in the environment marker
itself. We ask you not to mention "extra" at all in that case. Once
it's a function I can pass None as a parameter to guarantee it won't
match anything you wrote in your marker.

Long story short IMO the concrete requirements fall out more or less
effortlessly. I liked flattening the per-environment and per-extras
conditional requirements into a single mechanism, and I had no choice
pre-JSON-metadata.


Hello Nick!

It could also be more like

requires :  [ { condition : "foo == 'gurgle'", requirements : [ "bar",
"baz" ] } , { requirements : [ "quux", "splort" ] } ]

for a conditional and unconditional requirement.

This syntax would also avoid putting data in keys which seems to be fashionable.


More information about the Distutils-SIG mailing list