Bug#995490: lintian: false positive python3-script-but-no-python3-dep with Depends: python3, seems to want python3:any instead
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: Bug#995490: lintian: false positive python3-script-but-no-python3-dep with Depends: python3, seems to want python3:any instead
- From: Simon McVittie <smcv@debian.org>
- Date: Sat, 2 Oct 2021 01:44:34 +0100
- Message-id: <YVerchnRKva/zgyi@momentum.pseudorandom.co.uk>
- Reply-to: Simon McVittie <smcv@debian.org>, 995490@bugs.debian.org
Package: lintian
Version: 2.107.0
Severity: normal
xdg-desktop-portal-tests has a python3 script. It also has
"Depends: python3".
This is now diagnosed as "python3-script-but-no-python3-dep"; looking at
recent commits, Lintian seems to want it to depend on python3:any instead.
I think that's incorrect: a dependency on either python3 or python3:any
guarantees that some sort of /usr/bin/python3 will be available, so
either one should be considered to be acceptable, and the tag should
only be emitted if neither of those dependencies is present.
For *many* use-cases, a dependency on python3:any is *preferred*: it'ss
a less specific dependency than python3, as I'll explain further below,
so it constrains the dependency solution less (and in particular it's
helpful to people who want to cross-compile or install packages from a
secondary architecture). However, for *some* use-cases, a dependency on
python3:any would be incorrect, and only a dependency on python3 would be
sufficient - so we cannot recommend python3:any over python3 in all cases!
If we could, then the :any qualifier would be pointless.
I think most (maybe all) of the tags of the form "you have a script whose
interpreter is foo, so you need a dependency on package-containing-foo",
where package-containing-foo is Multi-Arch: allowed, should accept either
package-containing-foo or package-containing-foo:any as being sufficient
to provide the required functionality.
I think (but I'm not 100% sure yet) that this is to do with a bug in the
recent changes to Lintian::Relation::Predicate, in which the "implies"
relationship seems to be reversed in some cases. Have those changes been
checked by someone with in-depth knowledge of multiarch?
---
Further explanation:
Looking at the recent commit
https://salsa.debian.org/lintian/lintian/-/commit/9bc560a6 I think there's
maybe some confusion about what the :any qualifier on dependencies means,
which might be contributing to this.
Suppose we have these packages, which represent the four possible Multi-Arch
policies:
- dbus: Multi-Arch: foreign
- python3: Multi-Arch: allowed
- libglib2.0-0: Multi-Arch: same
- libopusfile0: no Multi-Arch field (sometimes said to be "Multi-Arch: no")
If I have a dependent package like this:
Package: dependent
Architecture: amd64
Depends: dbus, python3, libglib2.0-0, libopusfile0
then what that effectively means is that it depends on:
- dbus of any architecture (because dbus has M-A: foreign)
- python3:amd64
- libglib2.0-0:amd64
- libopusfile0:amd64
If I changed my dependent package so that, instead, it was like this:
Package: dependent
Architecture: amd64
Depends: dbus, python3:any, libglib2.0-0, libopusfile0
^^^^
then the result is that it depends on:
- dbus of any architecture
- python3 of any architecture (this is what has changed)
- libglib2.0-0:amd64
- libopusfile0:amd64
The reason why packages like python3 can be depended on in two different
ways is that they can be used in two different ways.
If I just write a pure-Python script with #!/usr/bin/python3, then I can
run it with any python3 interpreter that I can execute. On my amd64 system,
I would usually want to run it with python3:amd64, but if I wanted to,
I could install python3:i386 and run it with that (or I could even install
python3:riscv64 and qemu-user, if I was feeling ambitious). In this
situation, I can safely use "Depends: python3:any". This is the "weaker"
dependency that provides fewer guarantees, and I think it is the common
case in practice.
However, suppose instead that my script contains "import dependentlib",
where "dependentlib" is a Python 3 module written in C or C++ and included
in the dependent package. Now the situation has changed. If the package
that I have installed is dependent:amd64, then I cannot run my script
using python3:i386, because I do not have an i386 version of dependentlib:
I must specifically have python3:amd64. So I need to depend on
"Depends: python3" and get a python3 of the same architecture.
The version without :any is the conservative choice, which might be
harder to install but is always OK, so it gets the unqualified syntax. The
more liberal dependency with the opt-in :any qualifier is preferred *if*
it is sufficient, but it is not always sufficient.
Going back to the package that triggered this bug report, it would
*probably* be valid to change xdg-desktop-portal-tests to depend on
python3:any, but I have not done the analysis to prove that, and until
someone does so, the safe, conservative option is to continue to depend
on python3.
Other interpreters that have a C API, such as Perl and Ruby, are in the
same situation as Python: it is *often* better to depend on them with
the :any qualifier, but not always.
In the code changes in
https://salsa.debian.org/lintian/lintian/-/commit/9bc560a6 I'm particularly
suspicious about these two test-cases:
my $orig = 'pkgA:any, pkgB, pkgC:i386';
my $relation = Lintian::Relation->new->load($orig);
...
ok(!$relation->implies('pkgB:any'), 'pkgB does not imply pkgB:any');
...
ok($relation->implies('pkgA'), 'pkgA:any implies pkgA');
because I think they are the wrong way round. If the meaning of
"$relation->implies($x)" is something like "for every set of installed
packages that would satisfy the dependency relation $relation, we can
prove that the same set also satisfies $x" (in other words $relation is
an equal or stronger dependency than $x), then I think the correct
test would be this:
my $orig = 'pkgA:any, pkgB, pkgC:i386';
my $relation = Lintian::Relation->new->load($orig);
...
ok($relation->implies('pkgB:any'), 'pkgB implies pkgB:any');
...
ok(!$relation->implies('pkgA'), 'pkgA:any does not imply pkgA');
However, it's late at night so don't 100% trust me on that...
Multiarch is complicated and sometimes confusing even for experienced
Debian developers, and less-experienced developers often follow Lintian's
advice without applying much critical thinking to it, so I would recommend
getting feedback from a domain expert before making changes that emit
additional multiarch-related hints - it would be counterproductive for
Lintian to be giving wrong advice.
smcv
Reply to: