[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: providing sphinx3-* binaries



On 2017-09-28 01:03:27, Dmitry Shachnev wrote:
> Hi Antoine, and thanks for the detailed mail!
>
> On Tue, Sep 26, 2017 at 06:29:05PM -0400, Antoine Beaupré wrote:
>> We just had a short conversation on the #debian-devel IRC channel
>> regarding the upcoming Python 2 EOL, in the context of the Sphinx
>> packages.
>>
>> [...]
>>
>> So that's the first problem I have. The other problem we identified is
>> that the /usr/bin/sphinx-build symlink is not owned by any package.
>>
>> $ LANG=C dpkg -S /usr/bin/sphinx-build
>> dpkg-query: no path found matching pattern /usr/bin/sphinx-build
>>
>> That's a rather bad practice... We shouldn't install those symlinks in
>> postinst. They should be alternatives or conflicts or *something*. In
>> 2013, the sphinx maintainer [explained][1] the following:
>>
>> > True for docutils; however, sphinx doesn't use alternatives, and it
>> > doesn't do so for good reasons.
>> >
>> > The alternatives mechanisms is only suitable if both commands are
>> > compatible, i.e. their behavior doesn't vary with Python version. This
>> > is the case for rst2html and friends, but no so much for
>> > sphinx-build. The problem is that sphinx-build can import 3rd-party
>> > Python code, which is not necessarily compatible with both Python 2
>> > and 3.
>>
>> I understand that reasoning, but I don't think I agree with it. Or at
>> least, I don't think that, in the long term, it should be something that
>> blocks us.
>
> I think the reason why we should not use alternatives still applies. The
> current approach is conservative and it guarantees that when a package has
> python-sphinx in build-dependencies, /usr/bin/sphinx-build will always use
> Python 2. With alternatives there is no such guarantee.

Understood, fair point.

> And moving Python 3 packages to /usr/bin/sphinx3-build or something like
> that will mean diverging from upstream (see below).

Note that we already diverge from upstream in numerous places in Python,
first and foremost in the naming of the Python binary itself.

>> I am not sure what the solution is, but I would offer the following:
>>
>>  1. there should be a more easy way to override SPHINXBUILD in
>>     quickstart-generated Makefiles. IMHO, that means SPHINXBUILD?=
>>     instead of SPHINXBUILD=
>
> Good suggestion, I have submitted a pull request upstream:
> https://github.com/sphinx-doc/sphinx/pull/4092

Excellent - I meant to do that but ran out of time writing the email in
the first place. :)

I see, however, it's not getting too much traction.. But they have a
fair point - I didn't realize there was a difference between variables
from the environment and from the commandline in Make. Maybe it's good
enough as it is then.

>>  2. similarly, --with=sphinx should do the right thing depending on the
>>     detected pybuild Python version, that is, call
>>     /usr/share/sphinx/scripts/python{,3}/sphinx-build directly depending
>>     on which version we are building for.
>
> I do not understand this. You mentioned pybuild, so you are talking about
> setup.py based build systems, not Makefile based ones, right?

True. Well, technically, I refer to dh_sphinxdoc, but from what I could
tell, that doesn't seem to actually *build* the documentation, but just
clean it up, something I didn't expect.

> If setup.py calls build_sphinx automatically, then there is nothing else
> to do. If it does not, then you should call ‘setup.py build_sphinx’ with
> explicit interpreter, i.e. python or python3.
>
> The only thing where pybuild may help is when you want to run Sphinx for
> all supported Python versions, then you can use its COMMAND syntax.
>
> And there is no such thing as --with=sphinx. There is --with=sphinxdoc,
> but it operates on already built and installed documentation, so it cannot
> help with building.

I guess this is what I mean should be automated better. Every time I
used --with=sphinxdoc, I expected it to build the docs and then
remembered, when the produced package lacked any docs whatsoever, that I
needed to build things myself.

A simple --with=sphinxdoc should be sufficient to build sphinx docs. We
shouldn't expect upstream to do that step in setup.py, as it is rarely
hooked into the main build. Yes, there's the `build_sphinx` command, but
it's not hooked into `setup.py build` except in some rare project.

This is why I mention pybuild: maybe *that* is where docs should be
built? I am not sure. In any case, I feel there's a shim missing here,
and there's a good occasion to leverage the automation we have to
generate proper build deps and build-time commands.

>>  3. sphinx packages should follow the "python vs python3"
>>     convention. right now, when you run the "python" binary, you get
>>     Python 2. if you want Python 3, you run "python3". I don't know if
>>     there are plans to change this, but that's irrelevant at this stage:
>>     sphinx should follow convention and call python2 sphinx when you run
>>     "sphinx-build" and python3 sphinx when you run "sphinx3-build", and
>>     both should be available in $PATH.
>
> What is the problem with using /usr/share/sphinx/scripts/python3/sphinx-build
> explicitly if you want to force Python 3?

It's hard to find. It's unusal for a user-facing command to be absent
from the path yet to expect users to find it, especially when one
version *is* available in the path.

> If you like shorter command names, then you can also use ‘python3 -m sphinx’.
> Using the -m syntax instead of scripts is even endorsed by Sphinx upstream
> these days (see your link [2]).

Sure. I just found out about this while writing the email, after almost
a decade of maintaining python packages. That's a clear symptom of bad
discovery, although the upstream Makefile changes may help with that
eventually.

> Also there is no such thing as sphinx3-build upstream (unlike other packages
> that follow this convention). So all upstream projects will try to use
> sphinx-build, not sphinx3-build, even if they are Python 3 only. And if you
> override this command anyway, you can use two existing ways, I don’t see a
> need for the third one.

The reasoning here is that is is more discoverable, namely through
commandline completion, and is consistent with the /usr/bin/python*
binary naming conventions.

>>  4. the sphinx package is not following the usual convention of
>>     providing only libraries in python*. or to be more precise, it's
>>     rather odd that "sphinx-common" is what installs the python2 or
>>     python3 binary in $PATH. i would suggest providing new binary
>>     packages called "sphinx" and "sphinx3" that would provide those
>>     binaries.
>
> I won’t say that this convention is usual. There are many packages named
> python-* or python3-* which provide executable scripts.

I would argue that is a strange practice: I tend to ignore packages that
start with python* unless I am programming something. As a user, they
are basically useless because I am supposed to code something to use
those libraries. Now, granted, sphinx is a little special because it
*is* a programmer-oriented library, but keep in mind it can be used for
non-programs as well (see the Debian policy for example).

> Let me summarize what you, in my opinion, should do as a maintainer of
> packages using Sphinx:
>
> 1) If your project is not using autodoc: just build-depend on python3-sphinx
> and use /usr/bin/sphinx-build. There is no need to care about
> versions.
> 2) If your project uses autodoc, and is compatible with both Python 2 and 3:
> same as in 1), just use /usr/bin/sphinx-build.
> 3) If your project uses autodoc, and is only compatible with Python 3:
> use ‘python3 -m sphinx’ or ‘python3 setup.py build_sphinx’, depending on the
> upstream build system.
> 4) If your project uses autodoc, and is only compatible with Python 2:
> Port it to python 3. Or use ‘python2 -m sphinx’ or ‘python2 setup.py
> build_sphinx’.
>
> If you think this classification is incomplete, then please let me know
> where I am wrong.

That is a fair description, of course. It would be great to have build
step automated. At the very least, the above should be clearly
documented somewhere, maybe in dh_sphinxdoc's README or
manpage. Documenting that dh_sphinxdoc doesn't build in its manpage
would also go a long way, as that rather implicit right now. (ie. it
doesn't say it builds sphinx docs, but it doesn't say it doesn't either:
we need to assume that the list of things it does is exhaustive and
complete, something I never assume about documentation :)

>>  5. optionally, the sphinx and sphinx3 packages *may* conflict with each
>>     other to fight over the sphinx-build symlink. then people needing to
>>     build against *both* packages can use the "python -m sphinx"
>>     mechanism in their makefiles, since it's what upstream seems to be
>>     [doing][2]
>
> Let me quote Policy section 5.4:
>
> “adding Conflicts is normally not the best solution when two packages provide
> the same files. Depending on the reason for that conflict, using alternatives
> or renaming the files is often a better approach.”

Okay then the policy seems to point towards shipping sphinx3-build
binary, no?

>>  6. there are currently packages depending on *both* python-sphinx and
>>     python3-sphinx. for me, that makes no sense at all: there is a
>>     single set of documentation files built in a package, and it must be
>>     on either one of those packages, but not both. if the software
>>     supports building with python3, then it should depend on
>>     python3-sphinx, if not, it should depend on python-sphinx. by
>>     switching to sphinx{,3} binary packages, this would make that
>>     distinction clearer as well.
>
> This may happen when setup.py depends on Sphinx and automatically calls it
> during build. Such packages have to build-depend on both Python 2 and 3
> versions of Sphinx, even if only one version of documentation actually gets
> shipped.

I don't follow. Why do they need to depend on both? We don't need *nor*
want to build the documentation twice - if upstream's setup.py
automatically calls build_sphinx, then this is something we should be
working around (again, pybuild?) if only to save time on the buildds.

>> My pain points would mostly be fixed with th e simple #1 and #3
>> fixes. Without breaking anything, we could already provide a
>> sphinx3-build binary, and we could file a PR upstream to make
>> SPHINXBUILD more easily overridable. The rest is just a brainstorm of
>> possible medium-term fixes to try and fix that dangling symlink issue.
>>
>> I understand this is a complex situation and I would love to have better
>> answers, but I'm not sure there are any simple answers here. We
>> shouldn't hesitate to make radical changes, however: we have transition
>> tools to help us with that stuff, and if we can upgrade libc and gcc
>> across all of Debian fairly painlessly these days, i don't see why we
>> couldn't articulate such a transition for ~1000 python packages. :)
>
> In my opinion there should be a very strong reason to make changes that
> break packages. I have to deal with Sphinx upstream breaking compatibility
> which results in lots of FTBFS bugs for each major version. And I don’t
> want to introduce even more incompatibility myself.

meh. I saw the current FTBFS transition as a perfect moment to switch
over to python3 myself, but maybe i'm being a little too
enthusiastic. ;)

So maybe there's just nothing else to do here in the short term. I'll
start using "make SPHINXBUILD='python3 -m sphinx'" even though I find
that real clunky. In fact, the more I think about it, the less I see the
point of using the Makefiles at all from debian/rules: i'll probably
just call "python3 -m sphinx" or "setup.py build_sphinx" myself from
there, as needed.

The problem, then, of course, is that I lose that precious
automation. Most Python Debian packages really don't need that much
stuff in debian/rules - this is enough for 90% of the cases:

%:
        dh $@ --with=python2,python3 --buildsystem=pybuild

Yet, when I want to build docs in there, i need to override the build
targets immediately:

override_dh_auto_build:
        dh_auto_build
        # builder=html,man only supported in Sphinx 1.6, not yet released:
        # http://www.sphinx-doc.org/en/master/setuptools.html
        make -C doc html man SPHINXBUILD="python3 -m sphinx"
        # ^untested

I'd like to be able to just assume sphinxdoc will do the right thing and
build me a set of HTML docs (at least). Ideally, I'd be able to choose
the builders (html, man, epub, etc) through the environment, but then
that'd need to change the build-deps as well, something I understand is
basically impossible. ;)

Anyways, I learned a lot through this. Thanks for all the information,
and I hope we can update docs somewhere to reflect the current situation
and move ahead with some better build process for this as well.

A.

-- 
Having failed to discover weapons of mass destruction, Washington
shifted its propaganda to "establishing democracy." That flatly refutes
their earlier claim that the "only question" was whether Saddam would
disarm. But with a sufficiently obedient intellectual class, and loyal
media, the farce can proceed untroubled.
                        - Noam Chomsky, in an interview about Irak


Reply to: