All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: Cleber Rosa <crosa@redhat.com>
Cc: "Kevin Wolf" <kwolf@redhat.com>, "Fam Zheng" <fam@euphon.net>,
	"Vladimir Sementsov-Ogievskiy" <vsementsov@virtuozzo.com>,
	"Eduardo Habkost" <ehabkost@redhat.com>,
	qemu-block@nongnu.org,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>,
	qemu-devel@nongnu.org, "Markus Armbruster" <armbru@redhat.com>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Max Reitz" <mreitz@redhat.com>,
	"Alex Bennée" <alex.bennee@linaro.org>
Subject: Re: [PATCH 0/7] python: create installable package
Date: Wed, 17 Jun 2020 16:27:35 -0400	[thread overview]
Message-ID: <32791435-4aa4-7eaa-e2c6-b53165f2e28d@redhat.com> (raw)
In-Reply-To: <20200617195241.GA434320@localhost.localdomain>



On 6/17/20 3:52 PM, Cleber Rosa wrote:
> On Tue, Jun 02, 2020 at 08:15:16PM -0400, John Snow wrote:
>> Based-on: 20200602214528.12107-1-jsnow@redhat.com
>>
>> This series factors the python/qemu directory as an installable
>> module. As a developer, you can install this to your virtual environment
>> and then always have access to the classes contained within without
>> needing to wrangle python import path problems.
>>
> 
> First of all, major kudos for picking up this task.  It's so high in
> importance to so many users (myself included) that I feel like I owe
> you many truck loads of beers now. :)
> 

Mostly I just wanted to formalize mypy, pylint, flake8 et al across the
most important python bits in our tree so that when making changes for
testing it's easier to verify that I didn't break something else.

Easiest way to get the right structure that these tools expect is to
make a real package ...

So here we are. And also Philippe asked nicely.

>> When developing, you could go to qemu/python/ and invoke `pipenv shell`
>> to activate a virtual environment within which you could type `pip
>> install -e .` to install a special development version of this package
>> to your virtual environment. This package will always reflect the most
>> recent version of the source files in the tree.
>>
>> When not developing, you could install a version of this package to your
>> environment outright to gain access to the QMP and QEMUMachine classes
>> for lightweight scripting and testing.
>>
>> This package is formatted in such a way that it COULD be uploaded to
>> https://pypi.org/project/qemu and installed independently of qemu.git
>> with `pip install qemu`, but of course that button remains unpushed.
>>
>> There are a few major questions to answer first:
>>
>> - What versioning scheme should we use? See patch 2.
>>
>> - Should we use a namespace package or not?
>>   - Namespaced: 'qemu.machine', 'qemu.monitor' etc may be separately
>>     versioned, packaged and distributed packages. Third party authors
>>     may register 'qemu.xxx' to create plugins within the namespace as
>>     they see fit.
>>
>>   - Non-namespaced: 'qemu' is one giant glob package, packaged and
>>     versioned in unison. We control this package exclusively.
>>
> 
> For simplicity sake, I'd suggest starting with non-namespaced
> approach.  It should be easier to move to a namespaced package if the
> need arises.  Also, there are many ways to extend Python code without
> necessarily requiring third party authors to register their packages
> according to a namespace.
> 
> In the Avocado project, we have been using setuptools entrypoints with
> a reasonable level of success.  Anyone can have code under any
> namespace whatsoever extending Avocado, as long as it register their
> entrypoints.
> 

It's not (from my POV) very complex to do a namespace. I have some plans
to move e.g. qapi into qemu.qapi, and some of our other tools into
qemu.tools.

Some of these packages can be published externally, some can remain in
the tree.

but -- maybe namespaces ARE complicating matters in ways I don't
understand yet. I'll be open about it. The thought was mostly about
keeping flexibility with just installing the bits and pieces that you
want/need.

>> - How do we eliminate sys.path hacks from the rest of the QEMU tree?
>>   (Background: sys.path hacks generally impede the function of static
>>   code quality analysis tools like mypy and pylint.)
>>
>>   - Simplest: parent scripts (or developer) needs to set PYTHONPATH.
>>
>>   - Harder: Python scripts should all be written to assume package form,
>>     all tests and CI that use Python should execute within a VENV.
>>
> 
> Having a venv is desirable, but it's not really necessary.  As long as
> "python setup.py develop --user" is called, that user can access this
> code without sys.path hacks.  And if the user chooses to use a venv,
> it's just an extra step.
> 

whether a venv or a user installation, it's the same thing, really: the
user needs to set up and be in that environment to use the python tools
in the tree.

Once we're there, we may as well formalize the VENV to make it easier to
set up and use.

> In the Avocado project, we have a `make develop` rule that does that
> for the main setup.py file, and for all plugins we carry on the same
> tree, which is similar in some regards to the "not at the project root
> directory" situation here with "qemu/python/setup.py".
> 

Ah, yeah. If we're going this far, I'd prefer using a VENV over
modifying the user's environment. That way you can blast it all away
with a `make distclean`.

Maybe the "make develop" target could even use the presence of a .venv
directory to know when it needs to make the environment or not ...

>>   In either case, we lose the ability (for many scripts) to "just run" a
>>   script out of the source tree if it depends on other QEMU Python
>>   files. This is annoying, but as the complexity of the Python lib
>>   grows, it is unavoidable.
>>
> 
> Like I said before, we may introduce a "make develop"-like
> requirement, but after that, I don't think we'll loose anything.
> Also, I think this is just a sign of maturity.  We should be using
> Python as it's inteded to be used, and sys.path hacks is not among
> those.
> 

Joking nitpick: There is no intended way to use Python! :)

Still, the sys.path hacks -- worse than being "unpythonic", actively
seem to get in the way of pylint, flake8, mypy et al which do provide us
with legitimate and serious value.

So, sad to say, but we might lose the ability to run these python
scripts ad-hoc out of the tree (with no setup) in order to gain a more
robust python CI regime.

I think it's a fair trade-off, but we'll see if that's born out in review.

>>   In the VENV case, we at least establish a simple paradigm: the scripts
>>   should work in their "installed" forms; and the rest of the build and
>>   test infrastructure should use this VENV to automatically handle
>>   dependencies and path requirements. This should allow us to move many
>>   of our existing python scripts with "hidden" dependencies into a
>>   proper python module hierarchy and test for regressions with mypy,
>>   flake8, pylint, etc.
>>
>>   (We could even establish e.g. Sphinx versions as a dependency for our
>>   build kit here and make sure it's installed to the VENV.)
>>
>>   Pros: Almost all scripts can be moved under python/qemu/* and checked
>>   with CQA tools. imports are written the same no matter where you are
>>   (Use the fully qualified names, e.g. qemu.core.qmp.QMPMessage).
>>   Regressions in scripts are caught *much* faster.
>>
>>   Downsides: Kind of annoying; most scripts now require you to install a
>>   devkit forwarder (pip3 install --user .) or be inside of an activated
>>   venv. Not too bad if you know python at all, but it's certainly less
>>   plug-n-play.
>>
>> - What's our backwards compatibility policy if we start shipping this?
>>
>>   Proposed: Attempt to maintain API compatibility (after stabilizing the
>>   library). Incompatible changes should probably cause a semver bump.
>>
>>   Each published release makes no attempt to support any version of QEMU
>>   other than the one it was released against. We publish this on the tin
>>   in big red letters.
> 
> It may be too early to tell, but it's not clear to me how we'll keep
> both the QEMU version supported by a given release, and its API
> "level".
> 
> Are you proposing that we have, say, "python-qemu" version 10, being
> the 10th API version, without any regard to the QEMU version
> supported?  Or version 10.5.3 would mean 10th API version, intended
> to support QEMU 5.3?
> 

I am proposing only that we use semver to track the API version of the
SDK itself.

So that could be:

A) 1.x, 2.x, 3.x (etc) with absolutely no connection to the intended
QEMU support version. It either works or it doesn't. It might not work
very spectacularly. Major semver bumps indicate a breaking change to the
library API.

B) 1.5.0.0, 1.5.1.0, 1.5.2.0 (etc) where the major version still
describes the API, but the remainder of the version describes the
intended target QEMU.

Or, we could do:

C) 5.0.0, 5.1.0, 5.2.0, etc. where it tracks the QEMU version verbatim,
end of story.


I don't like (C) very much, because it violates some prevailing idioms
about python package versioning. A or B seem better, but do run us into
potential trouble with people having mismatched versions.

I'd take A or B. (B) is a little chatty but gives some good information
and allows you to pin versions effectively, so I think I'm leaning
towards that one right now.

Well, whatever we do right now, I think I do really want to make sure we
are publishing under 0.x to really give the illustration that we are NOT
promising even the illusion of stability right now.

>>
>> TESTING THIS PACKAGE OUT:
>>
>> 1. You can install to your local user's environment normally by
>> navigating to qemu/python/ and typing "pip3 install --user ."
>>
> 
> s/install/develop/ should be a better option here.  I mean, I'm
> not aware of any reason to user install while developing.
> 

I tried to make note to the develop case in several places; for the
purposes of this email I wanted to demonstrate what installing and using
it as a user would look like.

For those unaware of the distinction:

- install does a real bona-fide installation.
- develop installs a forwarder package that references the living
development files, so the package contents (but NOT its metadata!) are
always up to date with your development files.

For QEMU developers, installing with develop is going to be the smart
way to go. When your git tree is updated, your package will be updated
along with it. You can do it once and then probably forget about it.

> - Cleber.
> 




  reply	other threads:[~2020-06-17 20:28 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-03  0:15 [PATCH 0/7] python: create installable package John Snow
2020-06-03  0:15 ` [PATCH 1/7] python/qemu: create qemu.lib module John Snow
2020-06-05 12:33   ` Vladimir Sementsov-Ogievskiy
2020-06-03  0:15 ` [PATCH 2/7] python/qemu: formalize as package John Snow
2020-06-05 14:40   ` Vladimir Sementsov-Ogievskiy
2020-06-05 15:42     ` John Snow
2020-06-05 19:23     ` John Snow
2020-06-03  0:15 ` [PATCH 3/7] python/qemu: add README.rst John Snow
2020-06-05 14:56   ` Vladimir Sementsov-Ogievskiy
2020-06-05 16:18     ` John Snow
2020-06-03  0:15 ` [PATCH 4/7] python/qemu: Add pipenv support John Snow
2020-06-05 15:37   ` Vladimir Sementsov-Ogievskiy
2020-06-05 15:54     ` John Snow
2020-06-05 16:21   ` Vladimir Sementsov-Ogievskiy
2020-06-05 17:11     ` John Snow
2020-06-06  5:31       ` Vladimir Sementsov-Ogievskiy
2020-06-03  0:15 ` [PATCH 5/7] python/qemu: add pylint to pipenv John Snow
2020-06-03  0:15 ` [PATCH 6/7] python/qemu: Add flake8 " John Snow
2020-06-03  0:15 ` [PATCH 7/7] python/qemu: add mypy " John Snow
2020-06-06  5:53 ` [PATCH 0/7] python: create installable package Vladimir Sementsov-Ogievskiy
2020-06-08 14:14   ` John Snow
2020-06-17 19:52 ` Cleber Rosa
2020-06-17 20:27   ` John Snow [this message]
2020-06-18  9:23     ` Kevin Wolf
2020-06-19 15:04       ` John Snow
2020-06-19 16:44         ` Kevin Wolf
2020-06-19 17:14           ` John Snow
2020-06-19 15:09       ` Philippe Mathieu-Daudé
2020-06-19 15:15     ` Philippe Mathieu-Daudé
2020-06-19 16:10       ` John Snow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=32791435-4aa4-7eaa-e2c6-b53165f2e28d@redhat.com \
    --to=jsnow@redhat.com \
    --cc=alex.bennee@linaro.org \
    --cc=armbru@redhat.com \
    --cc=crosa@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=fam@euphon.net \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=philmd@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=vsementsov@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.