Re: [Distutils] PEP 517 again

2017-08-26 Thread Paul Moore
On 26 August 2017 at 02:17, xoviat  wrote:
> The fact that Nick, who I think is
> the only core developer here, immediately jumped on this issue confirms my
> suspicions here.

*ahem* Donald and myself are both core devs too. And possibly others,
I honestly don't know. (Not that I think it makes much difference -
arguments should be taken on their merit, not on who made them).

Paul
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread Paul Moore
On 26 August 2017 at 03:17, Guido van Rossum  wrote:
> In pretty much any other context, if you have an operation that returns an
> regular value or an error value, the error value should be None. (Exceptions
> include e.g. returning a non-negative int or -1 for errors, or True for
> success and False for errors.)

So, given that build_sdist returns the path of the newly built sdist,
the correct way to signal "I didn't manage to build a sdist" would be
to return None.

Now that it's put this way, it seems glaringly obvious to me that this
is the correct thing to do.
Paul
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] Conditionless setup.py

2017-08-26 Thread David Mertz
Me too. YAML is *so much* more widely used, and the complicated edge cases
can simply be ignored for this requirement.

Maybe it's just because I've never heard of whatever improper behavior the
author engaged in, but I don't think a data format needs to answer to the
actions of its creator(s). If G. Klyne or C. Newman were to do something
dreadful I wouldn't want dates to stop following ISO-8601.[*]

[*] I don't even know the 8601 authors' first names, and assume they are
good and honorable people. Just making an analogy.

On Aug 25, 2017 5:46 PM, "xoviat"  wrote:

> I personally do not understand the aversion to YAML. I mean yes, the
> specification is more complicated, but it's also more popular and the YAML
> files will not be complex enough for a C library to help that much. And
> since it's more popular, people might even prefer specifying package
> metadata in a pyproject.yaml. pip could even cache a wheel of the pyyaml
> package between builds that could be imported at build time with a
> zipimporter rather than vendoring the package. And as a plus it's not named
> after an alleged sexist.
>
> Honestly this is not an issue that interests me very much but this rant is
> because I was surprised that toml was chosen when I first found out about
> it.
>
> 2017-08-25 18:16 GMT-05:00 Nathaniel Smith :
>
>> On Fri, Aug 25, 2017 at 1:00 PM, Jeremy Stanley 
>> wrote:
>> > (The
>> > community around it is sensitive to gender diversity issues and
>> > wants to avoid acquiring more of a "brogrammer" image, so some of us
>> > worry that any conspicuous TOML files checked into revision control
>> > repositories could be seen as a tacit endorsement of the author's
>> > alleged behavior at GH a few years ago.)
>>
>> I was one of the folks championing TOML during the original
>> discussions, and this is an issue that also worried me a lot. In case
>> it's a useful data point: I actually contacted several of the main
>> rust/cargo developers, since they were the major users of TOML and are
>> also well known to be sensitive to these issues, to ask if they've had
>> any issues with this, and they said that they haven't heard any
>> complaints.
>>
>> Obviously there's a difference between "no-one complained" and "no-one
>> was bothered", and I suspect the community's existing reputation may
>> affect how this is interpreted as well, but... maybe useful as a data
>> point.
>>
>> Between this and the way the TOML spec appears to have been abandoned
>> at v0.4 (with the admonition "you should assume that is is unstable
>> and act accordingly") I've wondered if we should fork it, rename it
>> "the obvious minimal language", and release our own 1.0.
>>
>> -n
>>
>> --
>> Nathaniel J. Smith -- https://vorpus.org
>> ___
>> Distutils-SIG maillist  -  Distutils-SIG@python.org
>> https://mail.python.org/mailman/listinfo/distutils-sig
>>
>
>
> ___
> Distutils-SIG maillist  -  Distutils-SIG@python.org
> https://mail.python.org/mailman/listinfo/distutils-sig
>
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
Is everyone on board with that?

On Aug 26, 2017 4:29 AM, "Paul Moore"  wrote:

> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
> > In pretty much any other context, if you have an operation that returns
> an
> > regular value or an error value, the error value should be None.
> (Exceptions
> > include e.g. returning a non-negative int or -1 for errors, or True for
> > success and False for errors.)
>
> So, given that build_sdist returns the path of the newly built sdist,
> the correct way to signal "I didn't manage to build a sdist" would be
> to return None.
>
> Now that it's put this way, it seems glaringly obvious to me that this
> is the correct thing to do.
> Paul
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread Daniel Holth
I'm bored with that

On Sat, Aug 26, 2017, 11:59 xoviat  wrote:

> Is everyone on board with that?
>
> On Aug 26, 2017 4:29 AM, "Paul Moore"  wrote:
>
>> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
>> > In pretty much any other context, if you have an operation that returns
>> an
>> > regular value or an error value, the error value should be None.
>> (Exceptions
>> > include e.g. returning a non-negative int or -1 for errors, or True for
>> > success and False for errors.)
>>
>> So, given that build_sdist returns the path of the newly built sdist,
>> the correct way to signal "I didn't manage to build a sdist" would be
>> to return None.
>>
>> Now that it's put this way, it seems glaringly obvious to me that this
>> is the correct thing to do.
>> Paul
>>
> ___
> Distutils-SIG maillist  -  Distutils-SIG@python.org
> https://mail.python.org/mailman/listinfo/distutils-sig
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
Should probably take Guido out of this email chain now. And does everyone
agree with what Nathaniel said on sys.path?

On Aug 26, 2017 11:00 AM, "Daniel Holth"  wrote:

I'm bored with that

On Sat, Aug 26, 2017, 11:59 xoviat  wrote:

> Is everyone on board with that?
>
> On Aug 26, 2017 4:29 AM, "Paul Moore"  wrote:
>
>> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
>> > In pretty much any other context, if you have an operation that returns
>> an
>> > regular value or an error value, the error value should be None.
>> (Exceptions
>> > include e.g. returning a non-negative int or -1 for errors, or True for
>> > success and False for errors.)
>>
>> So, given that build_sdist returns the path of the newly built sdist,
>> the correct way to signal "I didn't manage to build a sdist" would be
>> to return None.
>>
>> Now that it's put this way, it seems glaringly obvious to me that this
>> is the correct thing to do.
>> Paul
>>
> ___
>
> Distutils-SIG maillist  -  Distutils-SIG@python.org
> https://mail.python.org/mailman/listinfo/distutils-sig
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread Nathaniel Smith
[removed Guido from CC]

On Aug 26, 2017 02:29, "Paul Moore"  wrote:

On 26 August 2017 at 03:17, Guido van Rossum  wrote:
> In pretty much any other context, if you have an operation that returns an
> regular value or an error value, the error value should be None.
(Exceptions
> include e.g. returning a non-negative int or -1 for errors, or True for
> success and False for errors.)

So, given that build_sdist returns the path of the newly built sdist,
the correct way to signal "I didn't manage to build a sdist" would be
to return None.

Now that it's put this way, it seems glaringly obvious to me that this
is the correct thing to do.


Eh... I would really prefer something that's (a) more explicit about what
specifically went wrong, and (b) harder to return by accident. It's not at
all obvious that if the list of requirements is 'None' that means 'this
build supports making sdists in general but cannot make them from this
source tree but might still be able to make a wheel'. And if you forget to
put in a return statement, then python returns None for you, which seems
like it could lead to some super confusing error modes.

-n
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
The current PEP requires that build_sdist return the basename of the sdist.
So forgetting a return statement is not an option unless people really
don't read the PEP.

On Aug 26, 2017 2:18 PM, "Nathaniel Smith"  wrote:

> [removed Guido from CC]
>
> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
>
> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
> > In pretty much any other context, if you have an operation that returns
> an
> > regular value or an error value, the error value should be None.
> (Exceptions
> > include e.g. returning a non-negative int or -1 for errors, or True for
> > success and False for errors.)
>
> So, given that build_sdist returns the path of the newly built sdist,
> the correct way to signal "I didn't manage to build a sdist" would be
> to return None.
>
> Now that it's put this way, it seems glaringly obvious to me that this
> is the correct thing to do.
>
>
> Eh... I would really prefer something that's (a) more explicit about what
> specifically went wrong, and (b) harder to return by accident. It's not at
> all obvious that if the list of requirements is 'None' that means 'this
> build supports making sdists in general but cannot make them from this
> source tree but might still be able to make a wheel'. And if you forget to
> put in a return statement, then python returns None for you, which seems
> like it could lead to some super confusing error modes.
>
> -n
>
> ___
> Distutils-SIG maillist  -  Distutils-SIG@python.org
> https://mail.python.org/mailman/listinfo/distutils-sig
>
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread Paul Moore
On 26 August 2017 at 20:17, Nathaniel Smith  wrote:
> Eh... I would really prefer something that's (a) more explicit about what
> specifically went wrong, and (b) harder to return by accident. It's not at
> all obvious that if the list of requirements is 'None' that means 'this
> build supports making sdists in general but cannot make them from this
> source tree but might still be able to make a wheel'. And if you forget to
> put in a return statement, then python returns None for you, which seems
> like it could lead to some super confusing error modes.

Well, we've had an extensive discussion about how frontends need to
trust backends to get things right. I don't really see it as
reasonable to now argue that backends might "forget" to return the
right value - they might just as well "forget" to properly isolate
builds...

As regards an explicit description of what went wrong, why can't we
just use the same reporting methods that we will for any other build
issue (backends simply report the problem on stdout/stderr)? I don't
see why the backend has to package up its error information and send
it to the frontend to report, when we already have a perfectly
effective way for backends to report errors and/or warnings to the
user. If you're worried that the frontend might suppress the
information (maybe because it's planning on falling back to a direct
wheel build) then isn't that just the converse - backends need to
trust frontends to do the right thing?

It's hard to come up with convincing counterarguments to hypothetical
concerns. Do you have a specific scenario that worries you? I see
"return the path, or None indicating you couldn't build the sdist" as
a nice, simple solution. If there's a case we know of right now where
it's *too* simple, then let's understand the specifics - otherwise,
why not defer worrying about it for now? We can revise the PEP later
if experience shows we missed something.

Paul
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread Nathaniel Smith
On Sat, Aug 26, 2017 at 12:54 PM, Paul Moore  wrote:
> On 26 August 2017 at 20:17, Nathaniel Smith  wrote:
>> Eh... I would really prefer something that's (a) more explicit about what
>> specifically went wrong, and (b) harder to return by accident. It's not at
>> all obvious that if the list of requirements is 'None' that means 'this
>> build supports making sdists in general but cannot make them from this
>> source tree but might still be able to make a wheel'. And if you forget to
>> put in a return statement, then python returns None for you, which seems
>> like it could lead to some super confusing error modes.
>
> Well, we've had an extensive discussion about how frontends need to
> trust backends to get things right. I don't really see it as
> reasonable to now argue that backends might "forget" to return the
> right value - they might just as well "forget" to properly isolate
> builds...

It's not about division of responsibilities, it's about handling
errors gracefully when they happen. There are three bins:

- creating an sdist succeeded
- creating an sdist failed for expected reasons, and a clever frontend
might be able to handle the problem automatically if it understands
what the problem is (sdist creation isn't supported in this case) and
understands its goals (just trying to build a wheel really, so the
sdist isn't crucial)
- creating an sdist failed for unexpected reasons, that need a human
to sort out (due to a broken system, or bugs – hey, they happen – or
...)

The whole discussion has been about how we can most reliably
distinguish between the second and third categories, and give good
error messages for the third category. The argument for NotImplemented
is that it avoids cases where some internal call raises
NotImplementedError and it "leaks out" accidentally, causing a
unexpected error to be incorrectly treated as expected error -- we
don't want pip to be hiding real bugs in backend code. The argument
for NotImplementedError is that it produces better error messages on
buggy frontends. 'return None' is kind of the worst of both worlds, in
that it's an easy thing to return accidentally, and it gives confusing
error messages if the frontend fails to handle it properly. (Even more
confusing, actually, because 'NoneType object has no attribute ...' is
even harder to track down than 'NotImplementedType object has no
attribute ...'.)

> As regards an explicit description of what went wrong, why can't we
> just use the same reporting methods that we will for any other build
> issue (backends simply report the problem on stdout/stderr)? I don't
> see why the backend has to package up its error information and send
> it to the frontend to report, when we already have a perfectly
> effective way for backends to report errors and/or warnings to the
> user. If you're worried that the frontend might suppress the
> information (maybe because it's planning on falling back to a direct
> wheel build) then isn't that just the converse - backends need to
> trust frontends to do the right thing?

What I mean is more, if you're some random user and you see this in a
build backend, what do you guess it means?

  def get_requires_for_build_sdist(config_settings=None):
  return None

Now how about these?

  def get_requires_for_build_sdist(config_settings=None):
  return NotImplemented

  def get_requires_for_build_sdist(config_settings=None):
  raise NotImplementedError

  def get_requires_for_build_sdist(config_settings=None):
  raise SdistBuildNotSupported

I mean, obviously return None will work. Basically anything that's
different from "return a list or string" will work :-). That's what
makes this a bikeshed topic, and I still think we're mostly just
spinning our wheels here until Nick and Donald have a chance to hash
something out that they both can agree on. But I really don't see any
advantages to 'return None' compared to the other options that have
been discussed

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread C Anthony Risinger
On Aug 26, 2017 2:17 PM, "Nathaniel Smith"  wrote:

> [removed Guido from CC]
>
> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
>
> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
> > In pretty much any other context, if you have an operation that returns
> an
> > regular value or an error value, the error value should be None.
> (Exceptions
> > include e.g. returning a non-negative int or -1 for errors, or True for
> > success and False for errors.)
>
> So, given that build_sdist returns the path of the newly built sdist,
> the correct way to signal "I didn't manage to build a sdist" would be
> to return None.
>
> Now that it's put this way, it seems glaringly obvious to me that this
> is the correct thing to do.
>
>
> Eh... I would really prefer something that's (a) more explicit about what
> specifically went wrong, and (b) harder to return by accident. It's not at
> all obvious that if the list of requirements is 'None' that means 'this
> build supports making sdists in general but cannot make them from this
> source tree but might still be able to make a wheel'. And if you forget to
> put in a return statement, then python returns None for you, which seems
> like it could lead to some super confusing error modes.
>

Why does the frontend need to know why an sdist was not created?

Frontend is asking the backend, given the current state of the world, to
either produce an sdist, or not. Sans ahead-of-time knowledge (see below),
I would expect build_sdist to make some sanity checks about the world, then
make a binary choice about whether sdist creation is a valid goal. If not
possible, return None or NotImplemented or False or dict-of-reasons or
whatever. Only if creation was *attempted*, and in the exceptional event it
then failed, would I expect an Exception. We don't have structured
exceptions sadly so they can't really carry much useful information from a
protocol perspective above and beyond a simple None or the like anyway.

I'd personally like to see some parity between build_sdist and build_wheel
in this regard. Maybe the disconnect here is we have a way to specify hard
reqs for building a wheel, statically or dynamically, and build_wheel is
expected to never fail, but no way to specify hard reqs needed for
build_sdist, necessitating this optional signaling path?

If we had some definitive way for the frontend to know ahead of time if
build_sdist is even expected to work, it could be called with more
confidence.

This could be a new sdist-related key in [build-system], a new table like
[sdist-system].requires, or making the get_requires_for_* less optional,
and defaulting to None instead of [ ].

Frontend is responsible for prepping the world, so if it can't get a list
of reqs, somehow, for build_sdist, it knows it can't work. Same for
build_wheel, because you have to specify the backend itself, so there is at
least one requirement!

Thus if you are a backend that can produce an sdist without additional
requirements beyond build reqs, you should explicitly return empty list
from get_requires_for_build_sdist.

-- 

C Anthony
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
Why does the frontend need to know why an sdist was not created?

I was of the opinion that such a distinction is not necessary because
building a source distribution doesn't take that much time. However Donald
thought that there needed to be a distinction because of the wasted time in
attempting to build a wheel that was going to fail anyway. One of the
things to consider is that site cythonizing takes time and maybe called for
building source distribution. However since I think we're of the agreement
that a source distribution should be as close to a checkout as possible,
that may not be an issue because cythonizing may not be required to build
the sdist.

On Aug 26, 2017 3:47 PM, "C Anthony Risinger"  wrote:

> On Aug 26, 2017 2:17 PM, "Nathaniel Smith"  wrote:
>
>> [removed Guido from CC]
>>
>> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
>>
>> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
>> > In pretty much any other context, if you have an operation that returns
>> an
>> > regular value or an error value, the error value should be None.
>> (Exceptions
>> > include e.g. returning a non-negative int or -1 for errors, or True for
>> > success and False for errors.)
>>
>> So, given that build_sdist returns the path of the newly built sdist,
>> the correct way to signal "I didn't manage to build a sdist" would be
>> to return None.
>>
>> Now that it's put this way, it seems glaringly obvious to me that this
>> is the correct thing to do.
>>
>>
>> Eh... I would really prefer something that's (a) more explicit about what
>> specifically went wrong, and (b) harder to return by accident. It's not at
>> all obvious that if the list of requirements is 'None' that means 'this
>> build supports making sdists in general but cannot make them from this
>> source tree but might still be able to make a wheel'. And if you forget to
>> put in a return statement, then python returns None for you, which seems
>> like it could lead to some super confusing error modes.
>>
>
> Why does the frontend need to know why an sdist was not created?
>
> Frontend is asking the backend, given the current state of the world, to
> either produce an sdist, or not. Sans ahead-of-time knowledge (see below),
> I would expect build_sdist to make some sanity checks about the world, then
> make a binary choice about whether sdist creation is a valid goal. If not
> possible, return None or NotImplemented or False or dict-of-reasons or
> whatever. Only if creation was *attempted*, and in the exceptional event it
> then failed, would I expect an Exception. We don't have structured
> exceptions sadly so they can't really carry much useful information from a
> protocol perspective above and beyond a simple None or the like anyway.
>
> I'd personally like to see some parity between build_sdist and build_wheel
> in this regard. Maybe the disconnect here is we have a way to specify hard
> reqs for building a wheel, statically or dynamically, and build_wheel is
> expected to never fail, but no way to specify hard reqs needed for
> build_sdist, necessitating this optional signaling path?
>
> If we had some definitive way for the frontend to know ahead of time if
> build_sdist is even expected to work, it could be called with more
> confidence.
>
> This could be a new sdist-related key in [build-system], a new table like
> [sdist-system].requires, or making the get_requires_for_* less optional,
> and defaulting to None instead of [ ].
>
> Frontend is responsible for prepping the world, so if it can't get a list
> of reqs, somehow, for build_sdist, it knows it can't work. Same for
> build_wheel, because you have to specify the backend itself, so there is at
> least one requirement!
>
> Thus if you are a backend that can produce an sdist without additional
> requirements beyond build reqs, you should explicitly return empty list
> from get_requires_for_build_sdist.
>
> --
>
> C Anthony
>
> ___
> Distutils-SIG maillist  -  Distutils-SIG@python.org
> https://mail.python.org/mailman/listinfo/distutils-sig
>
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
I also think that Guido pretty much ruled out Notimplemented.

On Aug 26, 2017 4:04 PM, "xoviat"  wrote:

> Why does the frontend need to know why an sdist was not created?
>
> I was of the opinion that such a distinction is not necessary because
> building a source distribution doesn't take that much time. However Donald
> thought that there needed to be a distinction because of the wasted time in
> attempting to build a wheel that was going to fail anyway. One of the
> things to consider is that site cythonizing takes time and maybe called for
> building source distribution. However since I think we're of the agreement
> that a source distribution should be as close to a checkout as possible,
> that may not be an issue because cythonizing may not be required to build
> the sdist.
>
> On Aug 26, 2017 3:47 PM, "C Anthony Risinger" 
> wrote:
>
>> On Aug 26, 2017 2:17 PM, "Nathaniel Smith"  wrote:
>>
>>> [removed Guido from CC]
>>>
>>> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
>>>
>>> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
>>> > In pretty much any other context, if you have an operation that
>>> returns an
>>> > regular value or an error value, the error value should be None.
>>> (Exceptions
>>> > include e.g. returning a non-negative int or -1 for errors, or True for
>>> > success and False for errors.)
>>>
>>> So, given that build_sdist returns the path of the newly built sdist,
>>> the correct way to signal "I didn't manage to build a sdist" would be
>>> to return None.
>>>
>>> Now that it's put this way, it seems glaringly obvious to me that this
>>> is the correct thing to do.
>>>
>>>
>>> Eh... I would really prefer something that's (a) more explicit about
>>> what specifically went wrong, and (b) harder to return by accident. It's
>>> not at all obvious that if the list of requirements is 'None' that means
>>> 'this build supports making sdists in general but cannot make them from
>>> this source tree but might still be able to make a wheel'. And if you
>>> forget to put in a return statement, then python returns None for you,
>>> which seems like it could lead to some super confusing error modes.
>>>
>>
>> Why does the frontend need to know why an sdist was not created?
>>
>> Frontend is asking the backend, given the current state of the world, to
>> either produce an sdist, or not. Sans ahead-of-time knowledge (see below),
>> I would expect build_sdist to make some sanity checks about the world, then
>> make a binary choice about whether sdist creation is a valid goal. If not
>> possible, return None or NotImplemented or False or dict-of-reasons or
>> whatever. Only if creation was *attempted*, and in the exceptional event it
>> then failed, would I expect an Exception. We don't have structured
>> exceptions sadly so they can't really carry much useful information from a
>> protocol perspective above and beyond a simple None or the like anyway.
>>
>> I'd personally like to see some parity between build_sdist and
>> build_wheel in this regard. Maybe the disconnect here is we have a way to
>> specify hard reqs for building a wheel, statically or dynamically, and
>> build_wheel is expected to never fail, but no way to specify hard reqs
>> needed for build_sdist, necessitating this optional signaling path?
>>
>> If we had some definitive way for the frontend to know ahead of time if
>> build_sdist is even expected to work, it could be called with more
>> confidence.
>>
>> This could be a new sdist-related key in [build-system], a new table like
>> [sdist-system].requires, or making the get_requires_for_* less optional,
>> and defaulting to None instead of [ ].
>>
>> Frontend is responsible for prepping the world, so if it can't get a list
>> of reqs, somehow, for build_sdist, it knows it can't work. Same for
>> build_wheel, because you have to specify the backend itself, so there is at
>> least one requirement!
>>
>> Thus if you are a backend that can produce an sdist without additional
>> requirements beyond build reqs, you should explicitly return empty list
>> from get_requires_for_build_sdist.
>>
>> --
>>
>> C Anthony
>>
>> ___
>> Distutils-SIG maillist  -  Distutils-SIG@python.org
>> https://mail.python.org/mailman/listinfo/distutils-sig
>>
>>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
Nathaniel:

We're not talking about signaling failure in get_requires* we're talking
about signaling failure in build*.

On Aug 26, 2017 3:42 PM, "Nathaniel Smith"  wrote:

> On Sat, Aug 26, 2017 at 12:54 PM, Paul Moore  wrote:
> > On 26 August 2017 at 20:17, Nathaniel Smith  wrote:
> >> Eh... I would really prefer something that's (a) more explicit about
> what
> >> specifically went wrong, and (b) harder to return by accident. It's not
> at
> >> all obvious that if the list of requirements is 'None' that means 'this
> >> build supports making sdists in general but cannot make them from this
> >> source tree but might still be able to make a wheel'. And if you forget
> to
> >> put in a return statement, then python returns None for you, which seems
> >> like it could lead to some super confusing error modes.
> >
> > Well, we've had an extensive discussion about how frontends need to
> > trust backends to get things right. I don't really see it as
> > reasonable to now argue that backends might "forget" to return the
> > right value - they might just as well "forget" to properly isolate
> > builds...
>
> It's not about division of responsibilities, it's about handling
> errors gracefully when they happen. There are three bins:
>
> - creating an sdist succeeded
> - creating an sdist failed for expected reasons, and a clever frontend
> might be able to handle the problem automatically if it understands
> what the problem is (sdist creation isn't supported in this case) and
> understands its goals (just trying to build a wheel really, so the
> sdist isn't crucial)
> - creating an sdist failed for unexpected reasons, that need a human
> to sort out (due to a broken system, or bugs – hey, they happen – or
> ...)
>
> The whole discussion has been about how we can most reliably
> distinguish between the second and third categories, and give good
> error messages for the third category. The argument for NotImplemented
> is that it avoids cases where some internal call raises
> NotImplementedError and it "leaks out" accidentally, causing a
> unexpected error to be incorrectly treated as expected error -- we
> don't want pip to be hiding real bugs in backend code. The argument
> for NotImplementedError is that it produces better error messages on
> buggy frontends. 'return None' is kind of the worst of both worlds, in
> that it's an easy thing to return accidentally, and it gives confusing
> error messages if the frontend fails to handle it properly. (Even more
> confusing, actually, because 'NoneType object has no attribute ...' is
> even harder to track down than 'NotImplementedType object has no
> attribute ...'.)
>
> > As regards an explicit description of what went wrong, why can't we
> > just use the same reporting methods that we will for any other build
> > issue (backends simply report the problem on stdout/stderr)? I don't
> > see why the backend has to package up its error information and send
> > it to the frontend to report, when we already have a perfectly
> > effective way for backends to report errors and/or warnings to the
> > user. If you're worried that the frontend might suppress the
> > information (maybe because it's planning on falling back to a direct
> > wheel build) then isn't that just the converse - backends need to
> > trust frontends to do the right thing?
>
> What I mean is more, if you're some random user and you see this in a
> build backend, what do you guess it means?
>
>   def get_requires_for_build_sdist(config_settings=None):
>   return None
>
> Now how about these?
>
>   def get_requires_for_build_sdist(config_settings=None):
>   return NotImplemented
>
>   def get_requires_for_build_sdist(config_settings=None):
>   raise NotImplementedError
>
>   def get_requires_for_build_sdist(config_settings=None):
>   raise SdistBuildNotSupported
>
> I mean, obviously return None will work. Basically anything that's
> different from "return a list or string" will work :-). That's what
> makes this a bikeshed topic, and I still think we're mostly just
> spinning our wheels here until Nick and Donald have a chance to hash
> something out that they both can agree on. But I really don't see any
> advantages to 'return None' compared to the other options that have
> been discussed
>
> -n
>
> --
> Nathaniel J. Smith -- https://vorpus.org
> ___
> Distutils-SIG maillist  -  Distutils-SIG@python.org
> https://mail.python.org/mailman/listinfo/distutils-sig
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread Nathaniel Smith
On Sat, Aug 26, 2017 at 2:06 PM, xoviat  wrote:
> I also think that Guido pretty much ruled out Notimplemented.

As I've said, I don't think it matters a huge deal whether we use
NotImplemented or not. But please don't treat Guido as some kind of
pronouncement generating machine where you hurl out-of-context
questions at him and then use his response as a club to beat down
discussion. It's rude to Guido, it's rude to Nick and Donald (to whom
Guido has explicitly delegated his BDFL authority in packaging-related
matters), and it's rude to everyone trying to discuss proposals on
their merits.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
As I said, I don't care what the particular solution is on this issue.
However I'm simply trying to anticipate and resolve potential disagreements
that could drag this out for a significant period of time. It is clear that
Nick and Donald have a disagreement on this issue which is actually not in
and of itself packaging related. The clear way to resolve this was to get a
pronouncement.

On Aug 26, 2017 4:56 PM, "Nathaniel Smith"  wrote:

> On Sat, Aug 26, 2017 at 2:06 PM, xoviat  wrote:
> > I also think that Guido pretty much ruled out Notimplemented.
>
> As I've said, I don't think it matters a huge deal whether we use
> NotImplemented or not. But please don't treat Guido as some kind of
> pronouncement generating machine where you hurl out-of-context
> questions at him and then use his response as a club to beat down
> discussion. It's rude to Guido, it's rude to Nick and Donald (to whom
> Guido has explicitly delegated his BDFL authority in packaging-related
> matters), and it's rude to everyone trying to discuss proposals on
> their merits.
>
> -n
>
> --
> Nathaniel J. Smith -- https://vorpus.org
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
With respect to this issue, if everyone told me that I was wrong then I
would say I'm obviously wrong. But some people are saying one thing and
other people are saying something else.

On Aug 26, 2017 5:03 PM, "xoviat"  wrote:

> As I said, I don't care what the particular solution is on this issue.
> However I'm simply trying to anticipate and resolve potential disagreements
> that could drag this out for a significant period of time. It is clear that
> Nick and Donald have a disagreement on this issue which is actually not in
> and of itself packaging related. The clear way to resolve this was to get a
> pronouncement.
>
> On Aug 26, 2017 4:56 PM, "Nathaniel Smith"  wrote:
>
>> On Sat, Aug 26, 2017 at 2:06 PM, xoviat  wrote:
>> > I also think that Guido pretty much ruled out Notimplemented.
>>
>> As I've said, I don't think it matters a huge deal whether we use
>> NotImplemented or not. But please don't treat Guido as some kind of
>> pronouncement generating machine where you hurl out-of-context
>> questions at him and then use his response as a club to beat down
>> discussion. It's rude to Guido, it's rude to Nick and Donald (to whom
>> Guido has explicitly delegated his BDFL authority in packaging-related
>> matters), and it's rude to everyone trying to discuss proposals on
>> their merits.
>>
>> -n
>>
>> --
>> Nathaniel J. Smith -- https://vorpus.org
>>
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread Nathaniel Smith
On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
 wrote:
> On Aug 26, 2017 2:17 PM, "Nathaniel Smith"  wrote:
>>
>> [removed Guido from CC]
>>
>> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
>>
>> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
>> > In pretty much any other context, if you have an operation that returns
>> > an
>> > regular value or an error value, the error value should be None.
>> > (Exceptions
>> > include e.g. returning a non-negative int or -1 for errors, or True for
>> > success and False for errors.)
>>
>> So, given that build_sdist returns the path of the newly built sdist,
>> the correct way to signal "I didn't manage to build a sdist" would be
>> to return None.
>>
>> Now that it's put this way, it seems glaringly obvious to me that this
>> is the correct thing to do.
>>
>>
>> Eh... I would really prefer something that's (a) more explicit about what
>> specifically went wrong, and (b) harder to return by accident. It's not at
>> all obvious that if the list of requirements is 'None' that means 'this
>> build supports making sdists in general but cannot make them from this
>> source tree but might still be able to make a wheel'. And if you forget to
>> put in a return statement, then python returns None for you, which seems
>> like it could lead to some super confusing error modes.
>
>
> Why does the frontend need to know why an sdist was not created?

This whole discussion is about handling a specific case: suppose you
have a frontend like pip that when given a source directory and asked
to build a wheel, wants to implement that as:
  - build sdist
  - unpack sdist
  - build wheel from unpacked sdist

And suppose you have a backend like flit, that can build sdists from
some source directories (e.g. VCS checkouts) but not others (e.g.
unpacked sdists). We need some way for pip and flit to negotiate that
even though pip *normally* would implement its build-a-wheel operation
by first building an sdist, in this case it's ok to silently fall back
to some other strategy (like building the wheel directly in the source
tree, or manually copying the source tree somewhere else and then
building a wheel in it).

But, we don't want this fallback behavior to hide real bugs. So if the
backend says "look, I just can't do sdists here, and that's an
expected thing, it's not something where the user needs to take any
particular action like filing a bug report or fixing their system or
anything like that, so if you have an alternative way to accomplish
what you're trying to do then you should just silently discard this
error and try that", ...cool. But if it doesn't explicitly say that,
then we don't want to silently discard the error and do something
else.

It's taken a *lot* of back and forth to reach consensus that all we
need here is some special error signal from the *_sdist operations.
Let's focus on resolving that :-)

> Frontend is asking the backend, given the current state of the world, to
> either produce an sdist, or not. Sans ahead-of-time knowledge (see below), I
> would expect build_sdist to make some sanity checks about the world, then
> make a binary choice about whether sdist creation is a valid goal. If not
> possible, return None or NotImplemented or False or dict-of-reasons or
> whatever. Only if creation was *attempted*, and in the exceptional event it
> then failed, would I expect an Exception. We don't have structured
> exceptions sadly so they can't really carry much useful information from a
> protocol perspective above and beyond a simple None or the like anyway.
>
> I'd personally like to see some parity between build_sdist and build_wheel
> in this regard. Maybe the disconnect here is we have a way to specify hard
> reqs for building a wheel, statically or dynamically, and build_wheel is
> expected to never fail, but no way to specify hard reqs needed for
> build_sdist, necessitating this optional signaling path?

Not sure what you mean about hard reqs. The reason for the lack of
parity is that we don't currently have any use cases where build_wheel
is expected to fail, but this is expected in some sense (not sure what
that would even mean), and there's some fallback that the frontend may
want to invoke instead.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
Nathaniel:

Just to clarify, we're talking about returning none for the build function
not the get requirements function. The get requirements function is always
expected to succeed and is optional. If while the backend is discovering
requirements it finds that it cannot build, then it can return an empty
list. It cannot however signal in the get requirements function that it
cannot build. At least with what is being proposed.

The reason that the proposal works is that the build function can never
return none on success.

On Aug 26, 2017 5:13 PM, "Nathaniel Smith"  wrote:

> On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
>  wrote:
> > On Aug 26, 2017 2:17 PM, "Nathaniel Smith"  wrote:
> >>
> >> [removed Guido from CC]
> >>
> >> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
> >>
> >> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
> >> > In pretty much any other context, if you have an operation that
> returns
> >> > an
> >> > regular value or an error value, the error value should be None.
> >> > (Exceptions
> >> > include e.g. returning a non-negative int or -1 for errors, or True
> for
> >> > success and False for errors.)
> >>
> >> So, given that build_sdist returns the path of the newly built sdist,
> >> the correct way to signal "I didn't manage to build a sdist" would be
> >> to return None.
> >>
> >> Now that it's put this way, it seems glaringly obvious to me that this
> >> is the correct thing to do.
> >>
> >>
> >> Eh... I would really prefer something that's (a) more explicit about
> what
> >> specifically went wrong, and (b) harder to return by accident. It's not
> at
> >> all obvious that if the list of requirements is 'None' that means 'this
> >> build supports making sdists in general but cannot make them from this
> >> source tree but might still be able to make a wheel'. And if you forget
> to
> >> put in a return statement, then python returns None for you, which seems
> >> like it could lead to some super confusing error modes.
> >
> >
> > Why does the frontend need to know why an sdist was not created?
>
> This whole discussion is about handling a specific case: suppose you
> have a frontend like pip that when given a source directory and asked
> to build a wheel, wants to implement that as:
>   - build sdist
>   - unpack sdist
>   - build wheel from unpacked sdist
>
> And suppose you have a backend like flit, that can build sdists from
> some source directories (e.g. VCS checkouts) but not others (e.g.
> unpacked sdists). We need some way for pip and flit to negotiate that
> even though pip *normally* would implement its build-a-wheel operation
> by first building an sdist, in this case it's ok to silently fall back
> to some other strategy (like building the wheel directly in the source
> tree, or manually copying the source tree somewhere else and then
> building a wheel in it).
>
> But, we don't want this fallback behavior to hide real bugs. So if the
> backend says "look, I just can't do sdists here, and that's an
> expected thing, it's not something where the user needs to take any
> particular action like filing a bug report or fixing their system or
> anything like that, so if you have an alternative way to accomplish
> what you're trying to do then you should just silently discard this
> error and try that", ...cool. But if it doesn't explicitly say that,
> then we don't want to silently discard the error and do something
> else.
>
> It's taken a *lot* of back and forth to reach consensus that all we
> need here is some special error signal from the *_sdist operations.
> Let's focus on resolving that :-)
>
> > Frontend is asking the backend, given the current state of the world, to
> > either produce an sdist, or not. Sans ahead-of-time knowledge (see
> below), I
> > would expect build_sdist to make some sanity checks about the world, then
> > make a binary choice about whether sdist creation is a valid goal. If not
> > possible, return None or NotImplemented or False or dict-of-reasons or
> > whatever. Only if creation was *attempted*, and in the exceptional event
> it
> > then failed, would I expect an Exception. We don't have structured
> > exceptions sadly so they can't really carry much useful information from
> a
> > protocol perspective above and beyond a simple None or the like anyway.
> >
> > I'd personally like to see some parity between build_sdist and
> build_wheel
> > in this regard. Maybe the disconnect here is we have a way to specify
> hard
> > reqs for building a wheel, statically or dynamically, and build_wheel is
> > expected to never fail, but no way to specify hard reqs needed for
> > build_sdist, necessitating this optional signaling path?
>
> Not sure what you mean about hard reqs. The reason for the lack of
> parity is that we don't currently have any use cases where build_wheel
> is expected to fail, but this is expected in some sense (not sure what
> that would even mean), and there's some fallback that the frontend may
> want to invoke instead

Re: [Distutils] PEP 517 again

2017-08-26 Thread C Anthony Risinger
On Aug 26, 2017 5:13 PM, "Nathaniel Smith"  wrote:

On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
 wrote:
> On Aug 26, 2017 2:17 PM, "Nathaniel Smith"  wrote:
>>
>> [removed Guido from CC]
>>
>> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
>>
>> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
>> > In pretty much any other context, if you have an operation that returns
>> > an
>> > regular value or an error value, the error value should be None.
>> > (Exceptions
>> > include e.g. returning a non-negative int or -1 for errors, or True for
>> > success and False for errors.)
>>
>> So, given that build_sdist returns the path of the newly built sdist,
>> the correct way to signal "I didn't manage to build a sdist" would be
>> to return None.
>>
>> Now that it's put this way, it seems glaringly obvious to me that this
>> is the correct thing to do.
>>
>>
>> Eh... I would really prefer something that's (a) more explicit about what
>> specifically went wrong, and (b) harder to return by accident. It's not
at
>> all obvious that if the list of requirements is 'None' that means 'this
>> build supports making sdists in general but cannot make them from this
>> source tree but might still be able to make a wheel'. And if you forget
to
>> put in a return statement, then python returns None for you, which seems
>> like it could lead to some super confusing error modes.
>
>
> Why does the frontend need to know why an sdist was not created?

This whole discussion is about handling a specific case: suppose you
have a frontend like pip that when given a source directory and asked
to build a wheel, wants to implement that as:
  - build sdist
  - unpack sdist
  - build wheel from unpacked sdist

And suppose you have a backend like flit, that can build sdists from
some source directories (e.g. VCS checkouts) but not others (e.g.
unpacked sdists). We need some way for pip and flit to negotiate that
even though pip *normally* would implement its build-a-wheel operation
by first building an sdist, in this case it's ok to silently fall back
to some other strategy (like building the wheel directly in the source
tree, or manually copying the source tree somewhere else and then
building a wheel in it).

But, we don't want this fallback behavior to hide real bugs. So if the
backend says "look, I just can't do sdists here, and that's an
expected thing, it's not something where the user needs to take any
particular action like filing a bug report or fixing their system or
anything like that, so if you have an alternative way to accomplish
what you're trying to do then you should just silently discard this
error and try that", ...cool. But if it doesn't explicitly say that,
then we don't want to silently discard the error and do something
else.

It's taken a *lot* of back and forth to reach consensus that all we
need here is some special error signal from the *_sdist operations.
Let's focus on resolving that :-)


Sure sure, I understand all that, and why we think we need some special
error signal from `build_sdist`, as currently written.

What I'm suggesting, is maybe calling `build_sdist` without knowing if it
can succeed is already a mistake.

Consider instead, if we make the following small changes:

1. `get_requires_for_build_*` is passed the sdist and wheel directories,
just like `build_*`, giving them the chance to actually look at tree before
deciding what other reqs might be necessary.

2. `get_requires_for_build_*` returns None to signal `build_*` is
unsupported (superceded by static reqs defined in TOML) and [...] to signal
support (can be empty).

3. `get_requires_for_build_*` assumed to return None if missing (so
optional and implies no support).

4. sdist reqs = `get_requires_for_build_sdist` (dynamic) + ??? (static)

5. wheel reqs = `get_requires_for_build_wheel` (dynamic) +
`build-system.requires` (static)

6. If no reqs are found for sdist (no declared reqs in TOML and
`get_requires_for_build_sdist` is missing or returns None), then
`build_sdist` is unsupported.

7. If no reqs are found for wheel (no declared reqs in TOML and
`get_requires_for_build_wheel` is missing or returns None), then
`build_wheel` is unsupported. This one is a spec violation because at least
one req is expected here (the backed itself).

This arrangement allows pip to know ahead-of-time if `build_sdist` is
appropriate. If no sdist reqs are explicitly acknowledged, then no sdist
can be created. Full stop.

Example usages:

* Backeds that only support wheel creation do not implement
`get_requires_for_build_sdist` at all.

* Backeds that conditionally support sdist creation implement
`get_requires_for_build_sdist` and return None if unsupported. This is
where flit signals "impossible" from an unpacked sdist and [...] from VCS.

* Backeds that always support sdist creation (setuptools) implement
`get_requires_for_build_sdist` and return [...] unconditionally.

So for pip's sdist -> unpack -> wheel path, it knows right away if it
should build 

Re: [Distutils] PEP 517 again

2017-08-26 Thread C Anthony Risinger
On Aug 26, 2017 5:13 PM, "Nathaniel Smith"  wrote:

On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
 wrote:
> On Aug 26, 2017 2:17 PM, "Nathaniel Smith"  wrote:
>>
>> [removed Guido from CC]
>>
>> On Aug 26, 2017 02:29, "Paul Moore"  wrote:
>>
>> On 26 August 2017 at 03:17, Guido van Rossum  wrote:
>> > In pretty much any other context, if you have an operation that returns
>> > an
>> > regular value or an error value, the error value should be None.
>> > (Exceptions
>> > include e.g. returning a non-negative int or -1 for errors, or True for
>> > success and False for errors.)
>>
>> So, given that build_sdist returns the path of the newly built sdist,
>> the correct way to signal "I didn't manage to build a sdist" would be
>> to return None.
>>
>> Now that it's put this way, it seems glaringly obvious to me that this
>> is the correct thing to do.
>>
>>
>> Eh... I would really prefer something that's (a) more explicit about what
>> specifically went wrong, and (b) harder to return by accident. It's not
at
>> all obvious that if the list of requirements is 'None' that means 'this
>> build supports making sdists in general but cannot make them from this
>> source tree but might still be able to make a wheel'. And if you forget
to
>> put in a return statement, then python returns None for you, which seems
>> like it could lead to some super confusing error modes.
>
>
> Why does the frontend need to know why an sdist was not created?

This whole discussion is about handling a specific case: suppose you
have a frontend like pip that when given a source directory and asked
to build a wheel, wants to implement that as:
  - build sdist
  - unpack sdist
  - build wheel from unpacked sdist

And suppose you have a backend like flit, that can build sdists from
some source directories (e.g. VCS checkouts) but not others (e.g.
unpacked sdists). We need some way for pip and flit to negotiate that
even though pip *normally* would implement its build-a-wheel operation
by first building an sdist, in this case it's ok to silently fall back
to some other strategy (like building the wheel directly in the source
tree, or manually copying the source tree somewhere else and then
building a wheel in it).

But, we don't want this fallback behavior to hide real bugs. So if the
backend says "look, I just can't do sdists here, and that's an
expected thing, it's not something where the user needs to take any
particular action like filing a bug report or fixing their system or
anything like that, so if you have an alternative way to accomplish
what you're trying to do then you should just silently discard this
error and try that", ...cool. But if it doesn't explicitly say that,
then we don't want to silently discard the error and do something
else.

It's taken a *lot* of back and forth to reach consensus that all we
need here is some special error signal from the *_sdist operations.
Let's focus on resolving that :-)

Sure sure, I understand all that, and why we think we need some special
error signal from `build_sdist`, as currently written.

What I'm suggesting, is maybe calling `build_sdist` without knowing if it
can succeed is already a mistake.

Consider instead, if we make the following small changes:

1. `get_requires_for_build_*` is passed the sdist and wheel directories,
just like `build_*`, giving them the chance to actually look at tree before
deciding what other reqs might be necessary.

2. `get_requires_for_build_*` returns None to signal `build_*` is
unsupported (superceded by static reqs defined in TOML) and [...] to signal
support (can be empty).

3. `get_requires_for_build_*` assumed to return None if missing (so
optional and implies no support).

4. sdist reqs = `get_requires_for_build_sdist` (dynamic) + ??? (static)

5. wheel reqs = `get_requires_for_build_wheel` (dynamic) +
`build-system.requires` (static)

6. If no reqs are found for sdist (no declared reqs in TOML and
`get_requires_for_build_sdist` is missing or returns None), then
`build_sdist` is unsupported.

7. If no reqs are found for wheel (no declared reqs in TOML and
`get_requires_for_build_wheel` is missing or returns None), then
`build_wheel` is unsupported. This one is a spec violation because at least
one req is expected here (the backed itself).

This arrangement allows pip to know ahead-of-time if `build_sdist` is
appropriate. If no sdist reqs are explicitly acknowledged, then no sdist
can be created. Full stop.

Example usages:

* Backeds that only support wheel creation do not implement
`get_requires_for_build_sdist` at all.

* Backeds that conditionally support sdist creation implement
`get_requires_for_build_sdist` and return None if unsupported. This is
where flit signals "impossible" from an unpacked sdist and [...] from VCS.

* Backeds that always support sdist creation (setuptools) implement
`get_requires_for_build_sdist` and return [...] unconditionally.

So for pip's sdist -> unpack -> wheel path, it knows right away if it
should build a

Re: [Distutils] PEP 517 again

2017-08-26 Thread Nathaniel Smith
On Sat, Aug 26, 2017 at 6:30 PM, C Anthony Risinger
 wrote:
> On Aug 26, 2017 5:13 PM, "Nathaniel Smith"  wrote:
>
> On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
>  wrote:
>
> Sure sure, I understand all that, and why we think we need some special
> error signal from `build_sdist`, as currently written.
>
> What I'm suggesting, is maybe calling `build_sdist` without knowing if it
> can succeed is already a mistake.
>
> Consider instead, if we make the following small changes:
>
> 1. `get_requires_for_build_*` is passed the sdist and wheel directories,
> just like `build_*`, giving them the chance to actually look at tree before
> deciding what other reqs might be necessary.

That's not a change, that's how it works :-).

> 2. `get_requires_for_build_*` returns None to signal `build_*` is
> unsupported (superceded by static reqs defined in TOML) and [...] to signal
> support (can be empty).
>
> 3. `get_requires_for_build_*` assumed to return None if missing (so optional
> and implies no support).

This is what I originally proposed, except you use None where I use
NotImplemented, which has the disadvantages I noted earlier. Also,
people didn't like the missing get_requires_for_build_* being treated
as no-support, which makes sense, since we expect that
get_requires_for_build_* won't be used very often. But one can switch
the default here without affecting much else. The reason we want to
let build_sdist report failure is just for convenience of backends who
don't have any other reason to implement get_requires_for_build_sdist.

> 4. sdist reqs = `get_requires_for_build_sdist` (dynamic) + ??? (static)
>
> 5. wheel reqs = `get_requires_for_build_wheel` (dynamic) +
> `build-system.requires` (static)

build-system.requires contains the requirements that are always
installed before we even try importing the backend, so they're
available to all backend hooks equally.

> 6. If no reqs are found for sdist (no declared reqs in TOML and
> `get_requires_for_build_sdist` is missing or returns None), then
> `build_sdist` is unsupported.
>
> 7. If no reqs are found for wheel (no declared reqs in TOML and
> `get_requires_for_build_wheel` is missing or returns None), then
> `build_wheel` is unsupported. This one is a spec violation because at least
> one req is expected here (the backed itself).

The TOML requires aren't really useful as a signal about whether sdist
specifically is supported. Plus I think we probably want to leave
no-requires-in-TOML as a valid option for saying "I don't need
anything installed" (maybe because the backend is shipped inside the
source tree) rather than overloading it to have extra meanings.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread C Anthony Risinger
On Sat, Aug 26, 2017 at 9:00 PM, Nathaniel Smith  wrote:

> On Sat, Aug 26, 2017 at 6:30 PM, C Anthony Risinger
>  wrote:
> > On Aug 26, 2017 5:13 PM, "Nathaniel Smith"  wrote:
> >
> > On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
> >  wrote:
> >
> > Sure sure, I understand all that, and why we think we need some special
> > error signal from `build_sdist`, as currently written.
> >
> > What I'm suggesting, is maybe calling `build_sdist` without knowing if it
> > can succeed is already a mistake.
> >
> > Consider instead, if we make the following small changes:
> >
> > 1. `get_requires_for_build_*` is passed the sdist and wheel directories,
> > just like `build_*`, giving them the chance to actually look at tree
> before
> > deciding what other reqs might be necessary.
>
> That's not a change, that's how it works :-).
>

Is that a change I missed from this thread? I'm reading here:

https://github.com/python/peps/blob/597ffba/pep-0517.txt#L301
https://github.com/python/peps/blob/597ffba/pep-0517.txt#L254
https://www.python.org/dev/peps/pep-0517/#get-requires-for-build-sdist
https://www.python.org/dev/peps/pep-0517/#get-requires-for-build-wheel

and they do not appear to receive the source or wheel directories.


> > 2. `get_requires_for_build_*` returns None to signal `build_*` is
> > unsupported (superceded by static reqs defined in TOML) and [...] to
> signal
> > support (can be empty).
> >
> > 3. `get_requires_for_build_*` assumed to return None if missing (so
> optional
> > and implies no support).
>
> This is what I originally proposed, except you use None where I use
> NotImplemented, which has the disadvantages I noted earlier. Also,
> people didn't like the missing get_requires_for_build_* being treated
> as no-support, which makes sense, since we expect that
> get_requires_for_build_* won't be used very often. But one can switch
> the default here without affecting much else. The reason we want to
> let build_sdist report failure is just for convenience of backends who
> don't have any other reason to implement get_requires_for_build_sdist.
>

Oh OK, good good. Well in that case I agree with you and missed the
suggestion. I personally prefer NotImplemented as well here but None seemed
mostly just as good and did not elicit as much pushback. It's not too big
of deal either way.

However, a missing `get_requires_for_build_wheel` technically signaling
"unsupported" makes good sense to me because it's always supplemented by
the static *and mandatory* `build-system.requires` list. There is no proper
way (without breaking the spec) to signal "unsupported" for `build_wheel`
since the backend itself (setuptools, wheel, flit) is specified here.
"Unsupported" is only signaled when *both* the static and dynamic requires
are None (or NotImplemented as mentioned). The kicker here in my offering,
is that the presence of `build-system.requires` *does not in any way imply*
`build_sdist` support. As written, there is no way to statically set the
requirements for sdist support (though this could be changed of course with
a new TOML key/table), so you must explicitly signal it with something like:

def get_requires_for_build_sdist(*args, **kwds): return []

This means, by default, `build_wheel` is "supported" and `build_sdist` is
"unsupported", and both are no fail operations. If called, any exception is
fatal to the entire process. If a backend goes through the work of
supporting sdist creation, is it really a problem to relay this support
with a 3 line function definition?

Wheel (could also define nothing at all):

def get_requires_for_build_sdist(source_dir, ...):
# I have no interest in sdists and I never will.
# GO AWAY.
return None

Flit:

def get_requires_for_build_sdist(source_dir, ...):
# I can output an sdist if the source directory is a VCS checkout I
understand.
requires =
get_requires_for_vcs_checkout_or_signal_unsupported(source_dir)
return requires

Setuptools:

def get_requires_for_build_sdist(source_dir, ...):
# I'm going to successfully create an sdist or die trying!
# There is literally no directory I can't handle so I don't even look.
return []

This seems pretty straightforward to me and avoids overloading
`build_sdist`, keeping it no fail like `build_wheel`.

Semantically, it's really the job of the requirements discovery mechanism
to decide one of:

a) Zero or more requirements are needed to transform target source_dir into
an sdist.
b) No requirement enables my backend to transform target source_dir into an
sdist.

This lets `build_*` focus purely on building things straight away. There is
a difference between "no more reqs are needed to do X" and "no possible req
will achieve X" even though both add zero requirements. Why not let this
hook relay it's decision more completely?


> > 4. sdist reqs = `get_requires_for_build_sdist` (dynamic) + ??? (static)
> >
> > 5. wheel reqs = `get_requires_for_build_wheel` (dynamic) +
> > `build-system.requires` (st

Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
> and they do not appear to receive the source or wheel directories.

The source directory is the current directory, if I am not mistaken.

> This lets `build_*` focus purely on building things straight away. There
is a difference between "no more reqs are needed to do X" and "no possible
req will achieve X" even though both add zero requirements. Why not let
this hook relay it's decision more completely?

Not trying to speak on behalf of flit here, but if I understand correctly,
flit requires git to build a source distribution. Flit knows its build
requirements, so it can just return them when get_requires is called.
However, it needs to attempt to invoke git to find out whether it can build
a source distribution, which if I understand correctly, is a lengthy
operation (whether that's actually true is not actually relevant because we
are discussion potentially any backend/operation). It's more efficient if
git is only invoked once, and if a failure occurs, then under the proposal
"None" would be returned from build_sdist rather than the name of the built
source distribution.

 def get_requires_for_build_sdist(source_dir, ...):
# I have no interest in sdists and I never will.
# GO AWAY.
return None

I have to say that the above example is not a good idea. Perhaps I was a
bit muddled on that point earlier: the reason that "return None" is a good
idea for build sdist is, well:

def build_sdist(...):  # Indicates success
return "x.tar.gz"

def build_sdist(...):  # Indicates failure
return None


Those are not truthily equivalent, which is important because it means that
someone is unlikely to make a mistake on that matter.

2017-08-26 23:05 GMT-05:00 C Anthony Risinger :

> On Sat, Aug 26, 2017 at 9:00 PM, Nathaniel Smith  wrote:
>
>> On Sat, Aug 26, 2017 at 6:30 PM, C Anthony Risinger
>>  wrote:
>> > On Aug 26, 2017 5:13 PM, "Nathaniel Smith"  wrote:
>> >
>> > On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
>> >  wrote:
>> >
>> > Sure sure, I understand all that, and why we think we need some special
>> > error signal from `build_sdist`, as currently written.
>> >
>> > What I'm suggesting, is maybe calling `build_sdist` without knowing if
>> it
>> > can succeed is already a mistake.
>> >
>> > Consider instead, if we make the following small changes:
>> >
>> > 1. `get_requires_for_build_*` is passed the sdist and wheel directories,
>> > just like `build_*`, giving them the chance to actually look at tree
>> before
>> > deciding what other reqs might be necessary.
>>
>> That's not a change, that's how it works :-).
>>
>
> Is that a change I missed from this thread? I'm reading here:
>
> https://github.com/python/peps/blob/597ffba/pep-0517.txt#L301
> https://github.com/python/peps/blob/597ffba/pep-0517.txt#L254
> https://www.python.org/dev/peps/pep-0517/#get-requires-for-build-sdist
> https://www.python.org/dev/peps/pep-0517/#get-requires-for-build-wheel
>
> and they do not appear to receive the source or wheel directories.
>
>
>> > 2. `get_requires_for_build_*` returns None to signal `build_*` is
>> > unsupported (superceded by static reqs defined in TOML) and [...] to
>> signal
>> > support (can be empty).
>> >
>> > 3. `get_requires_for_build_*` assumed to return None if missing (so
>> optional
>> > and implies no support).
>>
>> This is what I originally proposed, except you use None where I use
>> NotImplemented, which has the disadvantages I noted earlier. Also,
>> people didn't like the missing get_requires_for_build_* being treated
>> as no-support, which makes sense, since we expect that
>> get_requires_for_build_* won't be used very often. But one can switch
>> the default here without affecting much else. The reason we want to
>> let build_sdist report failure is just for convenience of backends who
>> don't have any other reason to implement get_requires_for_build_sdist.
>>
>
> Oh OK, good good. Well in that case I agree with you and missed the
> suggestion. I personally prefer NotImplemented as well here but None seemed
> mostly just as good and did not elicit as much pushback. It's not too big
> of deal either way.
>
> However, a missing `get_requires_for_build_wheel` technically signaling
> "unsupported" makes good sense to me because it's always supplemented by
> the static *and mandatory* `build-system.requires` list. There is no proper
> way (without breaking the spec) to signal "unsupported" for `build_wheel`
> since the backend itself (setuptools, wheel, flit) is specified here.
> "Unsupported" is only signaled when *both* the static and dynamic requires
> are None (or NotImplemented as mentioned). The kicker here in my offering,
> is that the presence of `build-system.requires` *does not in any way imply*
> `build_sdist` support. As written, there is no way to statically set the
> requirements for sdist support (though this could be changed of course with
> a new TOML key/table), so you must explicitly signal it with something like:
>
> def get_requires_for_build_sdis

Re: [Distutils] PEP 517 again

2017-08-26 Thread C Anthony Risinger
On Sat, Aug 26, 2017 at 11:05 PM, C Anthony Risinger 
wrote:

> On Sat, Aug 26, 2017 at 9:00 PM, Nathaniel Smith  wrote:
>
>> On Sat, Aug 26, 2017 at 6:30 PM, C Anthony Risinger
>>  wrote:
>> > On Aug 26, 2017 5:13 PM, "Nathaniel Smith"  wrote:
>> >
>> > On Sat, Aug 26, 2017 at 1:47 PM, C Anthony Risinger
>> >  wrote:
>> >
>> > Sure sure, I understand all that, and why we think we need some special
>> > error signal from `build_sdist`, as currently written.
>> >
>> > What I'm suggesting, is maybe calling `build_sdist` without knowing if
>> it
>> > can succeed is already a mistake.
>> >
>> > Consider instead, if we make the following small changes:
>> >
>> > 1. `get_requires_for_build_*` is passed the sdist and wheel directories,
>> > just like `build_*`, giving them the chance to actually look at tree
>> before
>> > deciding what other reqs might be necessary.
>>
>> That's not a change, that's how it works :-).
>>
>
> Is that a change I missed from this thread? I'm reading here:
>
> https://github.com/python/peps/blob/597ffba/pep-0517.txt#L301
> https://github.com/python/peps/blob/597ffba/pep-0517.txt#L254
> https://www.python.org/dev/peps/pep-0517/#get-requires-for-build-sdist
> https://www.python.org/dev/peps/pep-0517/#get-requires-for-build-wheel
>
> and they do not appear to receive the source or wheel directories.
>
>
>> > 2. `get_requires_for_build_*` returns None to signal `build_*` is
>> > unsupported (superceded by static reqs defined in TOML) and [...] to
>> signal
>> > support (can be empty).
>> >
>> > 3. `get_requires_for_build_*` assumed to return None if missing (so
>> optional
>> > and implies no support).
>>
>> This is what I originally proposed, except you use None where I use
>> NotImplemented, which has the disadvantages I noted earlier. Also,
>> people didn't like the missing get_requires_for_build_* being treated
>> as no-support, which makes sense, since we expect that
>> get_requires_for_build_* won't be used very often. But one can switch
>> the default here without affecting much else. The reason we want to
>> let build_sdist report failure is just for convenience of backends who
>> don't have any other reason to implement get_requires_for_build_sdist.
>>
>
> Oh OK, good good. Well in that case I agree with you and missed the
> suggestion. I personally prefer NotImplemented as well here but None seemed
> mostly just as good and did not elicit as much pushback. It's not too big
> of deal either way.
>
> However, a missing `get_requires_for_build_wheel` technically signaling
> "unsupported" makes good sense to me because it's always supplemented by
> the static *and mandatory* `build-system.requires` list. There is no proper
> way (without breaking the spec) to signal "unsupported" for `build_wheel`
> since the backend itself (setuptools, wheel, flit) is specified here.
> "Unsupported" is only signaled when *both* the static and dynamic requires
> are None (or NotImplemented as mentioned). The kicker here in my offering,
> is that the presence of `build-system.requires` *does not in any way imply*
> `build_sdist` support. As written, there is no way to statically set the
> requirements for sdist support (though this could be changed of course with
> a new TOML key/table), so you must explicitly signal it with something like:
>
> def get_requires_for_build_sdist(*args, **kwds): return []
>
> This means, by default, `build_wheel` is "supported" and `build_sdist` is
> "unsupported", and both are no fail operations. If called, any exception is
> fatal to the entire process. If a backend goes through the work of
> supporting sdist creation, is it really a problem to relay this support
> with a 3 line function definition?
>
> Wheel (could also define nothing at all):
>
> def get_requires_for_build_sdist(source_dir, ...):
> # I have no interest in sdists and I never will.
> # GO AWAY.
> return None
>
> Flit:
>
> def get_requires_for_build_sdist(source_dir, ...):
> # I can output an sdist if the source directory is a VCS checkout I
> understand.
> requires = get_requires_for_vcs_checkout_or_signal_unsupported(source_
> dir)
> return requires
>
> Setuptools:
>
> def get_requires_for_build_sdist(source_dir, ...):
> # I'm going to successfully create an sdist or die trying!
> # There is literally no directory I can't handle so I don't even look.
> return []
>
> This seems pretty straightforward to me and avoids overloading
> `build_sdist`, keeping it no fail like `build_wheel`.
>
> Semantically, it's really the job of the requirements discovery mechanism
> to decide one of:
>
> a) Zero or more requirements are needed to transform target source_dir
> into an sdist.
> b) No requirement enables my backend to transform target source_dir into
> an sdist.
>
> This lets `build_*` focus purely on building things straight away. There
> is a difference between "no more reqs are needed to do X" and "no possible
> req will achieve X" even though both add zero requirement

Re: [Distutils] PEP 517 again

2017-08-26 Thread C Anthony Risinger
On Sat, Aug 26, 2017 at 11:18 PM, xoviat  wrote:

> > and they do not appear to receive the source or wheel directories.
>
> The source directory is the current directory, if I am not mistaken.
>

Oh right right, for some reason I was reading the `build_*` hooks as
receiving the input directory rather than the output directory. I don't see
it stated anywhere that the PWD will be the source directory however. Might
be a good addition.

In this case, `get_requires_for_*` hooks should also be able to depend on
PWD being the applicable source directory (which of course might be an
unpacked sdist like in pip's proposed multistage sdist -> unpack -> wheel
pipeline).


> > This lets `build_*` focus purely on building things straight away.
> There is a difference between "no more reqs are needed to do X" and "no
> possible req will achieve X" even though both add zero requirements. Why
> not let this hook relay it's decision more completely?
>
> Not trying to speak on behalf of flit here, but if I understand correctly,
> flit requires git to build a source distribution. Flit knows its build
> requirements, so it can just return them when get_requires is called.
> However, it needs to attempt to invoke git to find out whether it can build
> a source distribution, which if I understand correctly, is a lengthy
> operation (whether that's actually true is not actually relevant because we
> are discussion potentially any backend/operation). It's more efficient if
> git is only invoked once, and if a failure occurs, then under the proposal
> "None" would be returned from build_sdist rather than the name of the built
> source distribution.
>

What is the benefit in making `build_sdist` handle this assertion?
Requirements checking is only performed once, earlier than building.
Somewhere, somehow, something must look to see if git exists. Is it not
more appropriate to check early, while asserting python requirements, vs.
actually being told to build an sdist? That is already the expectation on
the wheel side of things since it would also fail if necessary system
binaries are missing. Checking for git is conflating system reqs and python
reqs as "requirements", but I don't see why the get_requires_* hooks can't
do both if they so choose.


>  def get_requires_for_build_sdist(source_dir, ...):
> # I have no interest in sdists and I never will.
> # GO AWAY.
> return None
>
> I have to say that the above example is not a good idea. Perhaps I was a
> bit muddled on that point earlier: the reason that "return None" is a good
> idea for build sdist is, well:
>
> def build_sdist(...):  # Indicates success
> return "x.tar.gz"
>
> def build_sdist(...):  # Indicates failure
> return None
>
>
> Those are not truthily equivalent, which is important because it means
> that someone is unlikely to make a mistake on that matter.
>

What is the difference? Both equally inform the frontend that building an
sdist is not going to happen.

At the end of the day, I'm not too partial to any of the solutions I've
read thus far, and do not have any desire to derail progress. I just don't
like the variation in `build_sdist` vs. `build_wheel` because it feels like
a kludge to me. I thought perhaps defaulting sdists to "unsupported" and
requiring a backend to opt-in was both more elegant and more explicit,
allowing tools like flit to better express their conditional sdist support.

-- 

C Anthony
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig


Re: [Distutils] PEP 517 again

2017-08-26 Thread xoviat
The difference is that an empty list for requires would indicate that
building is possible but none would not. Those two values are truthily
equivalent.

For building, the name returned indicates building was possible, but it's
not truthily equivalent to none.

On Aug 27, 2017 12:08 AM, "C Anthony Risinger" 
wrote:

> On Sat, Aug 26, 2017 at 11:18 PM, xoviat  wrote:
>
>> > and they do not appear to receive the source or wheel directories.
>>
>> The source directory is the current directory, if I am not mistaken.
>>
>
> Oh right right, for some reason I was reading the `build_*` hooks as
> receiving the input directory rather than the output directory. I don't
> see it stated anywhere that the PWD will be the source directory however.
> Might be a good addition.
>
> In this case, `get_requires_for_*` hooks should also be able to depend on
> PWD being the applicable source directory (which of course might be an
> unpacked sdist like in pip's proposed multistage sdist -> unpack -> wheel
> pipeline).
>
>
>> > This lets `build_*` focus purely on building things straight away.
>> There is a difference between "no more reqs are needed to do X" and "no
>> possible req will achieve X" even though both add zero requirements. Why
>> not let this hook relay it's decision more completely?
>>
>> Not trying to speak on behalf of flit here, but if I understand
>> correctly, flit requires git to build a source distribution. Flit knows its
>> build requirements, so it can just return them when get_requires is called.
>> However, it needs to attempt to invoke git to find out whether it can build
>> a source distribution, which if I understand correctly, is a lengthy
>> operation (whether that's actually true is not actually relevant because we
>> are discussion potentially any backend/operation). It's more efficient if
>> git is only invoked once, and if a failure occurs, then under the proposal
>> "None" would be returned from build_sdist rather than the name of the built
>> source distribution.
>>
>
> What is the benefit in making `build_sdist` handle this assertion?
> Requirements checking is only performed once, earlier than building.
> Somewhere, somehow, something must look to see if git exists. Is it not
> more appropriate to check early, while asserting python requirements, vs.
> actually being told to build an sdist? That is already the expectation on
> the wheel side of things since it would also fail if necessary system
> binaries are missing. Checking for git is conflating system reqs and python
> reqs as "requirements", but I don't see why the get_requires_* hooks can't
> do both if they so choose.
>
>
>>  def get_requires_for_build_sdist(source_dir, ...):
>> # I have no interest in sdists and I never will.
>> # GO AWAY.
>> return None
>>
>> I have to say that the above example is not a good idea. Perhaps I was a
>> bit muddled on that point earlier: the reason that "return None" is a good
>> idea for build sdist is, well:
>>
>> def build_sdist(...):  # Indicates success
>> return "x.tar.gz"
>>
>> def build_sdist(...):  # Indicates failure
>> return None
>>
>>
>> Those are not truthily equivalent, which is important because it means
>> that someone is unlikely to make a mistake on that matter.
>>
>
> What is the difference? Both equally inform the frontend that building an
> sdist is not going to happen.
>
> At the end of the day, I'm not too partial to any of the solutions I've
> read thus far, and do not have any desire to derail progress. I just don't
> like the variation in `build_sdist` vs. `build_wheel` because it feels like
> a kludge to me. I thought perhaps defaulting sdists to "unsupported" and
> requiring a backend to opt-in was both more elegant and more explicit,
> allowing tools like flit to better express their conditional sdist support.
>
> --
>
> C Anthony
>
___
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig