qemu-devel
[Top][All Lists]
Advanced

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

Re: [PATCH v3 07/16] iotests/297: Don't rely on distro-specific linter b


From: John Snow
Subject: Re: [PATCH v3 07/16] iotests/297: Don't rely on distro-specific linter binaries
Date: Wed, 22 Sep 2021 15:53:22 -0400

(This email just explains python packaging stuff. No action items in here. Skim away.)

On Fri, Sep 17, 2021 at 5:43 AM Hanna Reitz <hreitz@redhat.com> wrote:
On 16.09.21 06:09, John Snow wrote:
> 'pylint-3' is another Fedora-ism. Use "python3 -m pylint" or "python3 -m
> mypy" to access these scripts instead. This style of invocation will
> prefer the "correct" tool when run in a virtual environment.
>
> Note that we still check for "pylint-3" before the test begins -- this
> check is now "overly strict", but shouldn't cause anything that was
> already running correctly to start failing.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
>   tests/qemu-iotests/297 | 45 ++++++++++++++++++++++++------------------
>   1 file changed, 26 insertions(+), 19 deletions(-)

I know it sounds silly, but to be honest I have no idea if replacing
`mypy` by `python3 -m mypy` is correct, because no mypy documentation
seems to suggest it.


Right, I don't think it's necessarily documented that you can do this. It just happens to be a very convenient way to invoke the same script without needing to know *where* mypy is. You let python figure out where it's going to import mypy from, and it handles the rest.

(This also makes it easier to use things like mypy, pylint etc with an explicitly specified PYTHON interpreter. I don't happen to do that in this patch, but ... we could.)
 
 From what I understand, that’s generally how Python “binaries” work,
though (i.e., installed as a module invokable with `python -m`, and then
providing some stub binary that, well, effectively does this, but kind
of in a weird way, I just don’t understand it), and none of the
parameters seem to be hurt in this conversion, so:


Right. Technically, any python package can ask for any number of executables to be installed, but the setuptools packaging ecosystem provides a way to "generate" these based on package configuration. I use a few in our own Python packages. If you look in python/setup.cfg, you'll see stuff like this:

[options.entry_points]
console_scripts =
    qom = qemu.qmp.qom:main
    qom-set = qemu.qmp.qom:QOMSet.entry_point
    qom-get = qemu.qmp.qom:QOMGet.entry_point
    qom-list = qemu.qmp.qom:QOMList.entry_point
    qom-tree = qemu.qmp.qom:QOMTree.entry_point
    qom-fuse = qemu.qmp.qom_fuse:QOMFuse.entry_point [fuse]
    qemu-ga-client = qemu.qmp.qemu_ga_client:main
    qmp-shell = qemu.qmp.qmp_shell:main

These entries cause those weird little binary wrapper scripts to be generated for you when the package is *installed*. So our packages will put 'qmp-shell' and 'qom-tree' into your $PATH*.The stuff to the right of the equals sign is just a pointer to a function that can be executed that implements the CLI command. qemu.qmp.qmp_shell points to the module to import, and ':main' points to the function to run.

The last bit of this is that many, though not all (and there's zero requirement this has to be true), python packages that implement CLI commands will often have a stanza in their __init__.py module that says something like this:

if __name__ == '__main__':
    do_the_command_line_stuff()

Alternatively, a package can include a literal __main__.py file that python knows to check for, and this module is the one that gets executed for `python3 -m mypackage` invocations. This is what mypy does.

Those are the magical blurbs that allow you to execute a module as if it were a script by running "python3 -m mymodule" -- that hooks directly into that little execution stanza. For python code distributed as packages, that's the real reason to have that little magic stanza -- it provides a convenient way to run stuff without needing to write the incredibly more tedious:

python3 -c "from mypy.__main__ import console_entry; console_entry();"

... which is quite a bit more porcelain too, depending on how they re/factor the code inside of the package.

Seeing as how mypy explicitly includes a __main__.py file: https://github.com/python/mypy/blob/master/mypy/__main__.py, I am taking it as a given that they are fully aware of invoking mypy in this fashion, and believe it safe to rely on.
 
There will be a quiz later.
(There will not be a quiz.)

Reviewed-by: Hanna Reitz <hreitz@redhat.com>

Thanks!

--js

*If your $PATH is configured to include, say, ~/.local/bin/, that is. On Fedora, this is where executable shims for python get deposited when you do "pip3 install --user somepackage". Python virtual environments will configure your $PATH to include packages installed in that venv, etc etc etc. Not every distro is configured such that pip packages are on the PATH, so you can't rely on them being there when writing other scripts, usually. Invoking the python interpreter directly seems far more flexible.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]