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

Bug#995490: lintian: false positive python3-script-but-no-python3-dep with Depends: python3, seems to want python3:any instead



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: