New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
On Debian and derivatives, python and python3 modules are wrong about installation paths
#8739
Comments
|
Shouldn't meson's behavior here be exactly identical to debian users using other mechanisms such as unpatched setuptools/pip via get-pip.py, or using pep 517/518 build systems that handle installation themselves? I knew debian is a hot mess here, but I didn't realize it was this bad! What do debian packagers packaging software built with meson, do to fix their distro packaging recipes? |
Sorry to pick the language, but "unpatched pip" is a misconception: pip, setuptools etc. internally use distutils stdlib package, so it's both unpatched and patched at the same time. You can't really get "unpatched pip" on system's python if by "unpatched" you mean the totality of behaviour. This is getting less true as we speak:
Now debian circumvented it, their own truth is still not reflected in sysconfig's functions, so if something doesn't change I'm afraid they will still patch that vendored distutils in setuptools, at the same time ignoring sysconfig.
I honestly don't know, I haven't seen any official packages doing that, and I've seen other approaches like libvirt: the main library is built using meson and libvirt-python (another git repo) is built with usual I'd totally understand if you WONTFIX this and instead say this is debian's fault for partially patching some functions (distutils) and not patching other, more documented (sysconfig), but I'd be grateful if meson could at least consider aligning with what pip (patched or unpatched) does. The partial solution I posted might be a start, and if you need, I can post Signed-off-by for this or similar piece of code. |
|
For posterity, here's a script I used while designing a solution: #!/usr/bin/env python3
import distutils.command.install
import distutils.sysconfig
import pprint
import sys
import sysconfig
for expr in (
"sys.path",
"sysconfig.get_paths()",
"sysconfig.get_paths(vars={'base': '/usr/local', 'platbase': '/usr/local'})",
"distutils.sysconfig.get_python_lib()",
"distutils.sysconfig.get_python_lib(prefix='/usr/local')",
"distutils.sysconfig.get_python_lib(plat_specific=True, prefix='/usr/local')",
"distutils.command.install.INSTALL_SCHEMES",
):
print(f'{expr}={pprint.pformat(eval(expr))}') |
|
^^ Cinnamon has gone the route of get_install_dir() but having a meson_options.txt option used only in the debian packaging, to override the installation directory. The install dir is then used for |
|
On Fri, Jun 25, 2021 at 11:25:52AM -0700, Eli Schwartz wrote:
Cinnamon has gone the route of get_install_dir() but having
a meson_options.txt option used only in the debian packaging, to override
the installation directory. The install dir is then used for
`install_data()`.
Nice. That is perfect in distro setting, when everything is immediately
packaged, and fits "what happens in Debian, stays in Debian".
In our project most people build from sources, so I wouldn't want to impose
this problem on them. Given the choice, I still prefer my solution:
https://github.com/oscarlab/graphene/blob/6ba10c60b94a066d516bb9121c31280c0ba69468/Scripts/get-python-platlib.py
Would you review a PR which would fix this bug by documenting the problem in
Python-module.md and suggesting those two workarounds?
|
|
Yeah, a proper method is of course best... Documentation updates are cheap, I'd be open to mentioning the Debian corner case. We could also continue to discuss special casing this in meson just for Debian's sake so workarounds are not needed (we even do this for --libdir defaults although there we don't have an official API like sysconfig to return what the OS is supposed to use), but so far I'm the only core maintainer who responded to the ticket so I dunno what everyone thinks here. I'd really like to know what the general view of the team is on handling Debian here... |
|
The desired end user experience is fairly obvious: when doing the default thing with default settings, the end result should work on all distros. If every Python project needs to add workaround code then that is bad. The question is if and how we can make that happen. I've read through this entire thread and still don't fully understand the issue... |
|
Also note that the |
|
Yes. The ticket's title specifically mentions they're both wrong. Repeating the original report:
This calls out both modules. The problem is they both rely on the python stdlib |
|
The deprecated function won't disappear till Oct 2023 (Python 3.12.0), so probably using that now while silencing the deprecation warning is the pragmatic thing to do. And then revisit in 6 or 12 months to see if And put it behind a version check: if sys.version_info >= (3, 12):
# use sysconfig - Debian is weird here, see gh-8739.
else:
# This does the right thing:
from distutils.command.install import INSTALL_SCHEMES |
|
I'm not arguing "don't use a deprecated thing"... I'm pointing out it's technically the wrong approach, which only matters in the context of "that's why using it constitutes a Debian hack". Using distutils as "the Debian hack" is a perfectly valid argument to make, at least IMO. |
|
(No, we are not adding a runtime dependency on setuptools, meson has a stdlib-only policy.) |
|
There is a degree of uncertainty what Debian packaging will do in the future, so I'd respectfully suggest that if you'd like to include some solution in Meson, that should be at least coordinated with Debian and apart from Linux Mint people I haven't seen anyone from Debian packaging community weighting on this issue yet. @jpakkane >I've read through this entire thread and still don't fully understand the issue... That's OK, I don't think anyone does. For me it took about two days reading through patches and testing a solution and I don't think I understand this either, but I'll try explain this as I know it. Sorry in advance if you know any part already. So let's start by stating that Python has an interpreter-wide variable Python has two different types of modules, written in python or written in C. Modules can be from stdlib or installed otherwise. So python has mechanisms to have all that cartesian product (they're called To this end, python's standard library provides a way to query for those directories at runtime. Here comes first hard part: there are two different mechanisms for that, older Note that mainline Python has no LSB/FHS-style concept of separation of Now back to Debian. Because distros are free to adjust But the technical way they substitute So the script above, which compares
|
|
Is it possible to add a new method, say |
|
Is it possible to add a new method, say
`python_mod.detect_the_thing_where_i_should_install_my_stuff_into()` that
does all the required detection magic, does the expected thing 99% of the
time and which people can then use and not have to care about any of this?
I was under impression that python_installation.get_install_dir() and
.install_sources() are documented to do exactly that.
It's definitely possible, right now this method is called get_option() (if you
ask Cinnamon) and run_program(find_program('get-python-platlib.py'),
get_option('prefix')).stdout() (if you ask me), so if you'd like to merge
those into python_mod, it looks doable.
But then there's a problem that other functions like
python_installation.get_path() are documented to expose sysconfig methods, and
sysconfig on Debian is broken. Do you wan't to also fix those methods?
|
Debian now (since Python 3.10.2-6) adds the deb_system scheme to sysconfig. Newer distutils (such as bundled with setuptools >= 60) adds fetch schemes from sysconfig, rather than duplicating the sysconfig schemes statically in distutils.command.install. This change broke meson's deb_system check. This patch replaces that mechanism (for newer Debian releases) with explicit scheme selection, which is far simpler. But it also retains the old mechanism, for older Debian releases that require it (Debian <= 11). Fixes: mesonbuild#8739 (for python module) Fixes: https://bugs.debian.org/1026312
…n Debian Fixes: mesonbuild#8739 (on Debian >= bookworm)
…n Debian Fixes: mesonbuild#8739 (for python3 module, on Debian >= 12)
Describe the bug
On Debian and derivatives, Python paths returned by
import('python3').sysconfig_path()andimport('python').find_installation().get_path()are not insys.path(for--prefix=/usr/localand--prefix=/usr), because they have slight differences (dist-packagesvssite-packages,pythonXvspythonX.Y).To Reproduce
Expected behavior
I expect that if using
--prefix=/usror--prefix=/usr/localthe package will be installed so that it can be imported without explicitly setting$PYTHONPATH.system parameters
meson --versionninja --versionif it's a Ninja buildfurther information
There is a post https://discuss.python.org/t/pep-632-deprecate-distutils-module/5134/122 (the discussion is revolving around PEP 632, which deprecates
distutilspackage) which describes the status quo, but the explanation is incomplete. What really happens is that Debian patches onlydistutilsmodule and notsysconfig, and furthermore those changes only really work for--prefix=/usr, because with--prefix=/usr/localthe paths are invalid because of thepythonXvspythonX.Ydifference.There are 4 approaches to this problem using only standard library:
sysconfig(doesn't work, because on debian and derivatives it returns wrong things)distutils.sysconfig(only works for--prefix=/usr)site(AFAIK there is no clear way to infer the correct data from any function there)distutils.command.install.INSTALL_SCHEMESIMHO is what really works with proper detection of the corner caseThe patches are here: https://salsa.debian.org/cpython-team/python3-stdlib/-/tree/master/debian/patches, the relevant one is called
distutils-install-layout.diff.Without blaming anyone, the situation is both python meson modules are unfit for their stated purpose.
workaround
Currently we use a workaround for this: gramineproject/graphene#2353.
This is obviously not sufficient, because there is also
purelib, but we don't use it, so in original code I didn't bother.The text was updated successfully, but these errors were encountered: