[PATCH v7 00/31] python: create installable package

John Snow posted 31 patches 2 years, 11 months ago
Failed in applying to current master (apply log)
There is a newer version of this series
python/PACKAGE.rst                          |  43 ++++
python/README.rst                           |  58 +++++
python/qemu/README.rst                      |   8 +
python/qemu/machine/README.rst              |   9 +
python/qemu/qmp/README.rst                  |   9 +
python/qemu/utils/README.rst                |   7 +
.gitlab-ci.d/containers.yml                 |   5 +
.gitlab-ci.yml                              |  26 +++
python/.gitignore                           |  16 ++
python/MANIFEST.in                          |   3 +
python/Makefile                             |  48 ++++
python/Pipfile                              |  13 ++
python/Pipfile.lock                         | 231 ++++++++++++++++++++
python/VERSION                              |   1 +
python/avocado.cfg                          |  10 +
python/mypy.ini                             |   4 -
python/qemu/.flake8                         |   2 -
python/qemu/.isort.cfg                      |   7 -
python/qemu/__init__.py                     |  11 -
python/qemu/machine/__init__.py             |  36 +++
python/qemu/{ => machine}/console_socket.py |  11 +-
python/qemu/{ => machine}/machine.py        |  46 ++--
python/qemu/{ => machine}/qtest.py          |   3 +-
python/qemu/pylintrc                        |  58 -----
python/qemu/{qmp.py => qmp/__init__.py}     |  12 +-
python/qemu/{utils.py => utils/__init__.py} |  18 +-
python/qemu/{ => utils}/accel.py            |   0
python/setup.cfg                            | 102 +++++++++
python/setup.py                             |  23 ++
python/tests/flake8.sh                      |   2 +
python/tests/isort.sh                       |   2 +
python/tests/mypy.sh                        |   2 +
python/tests/pylint.sh                      |   2 +
tests/acceptance/avocado_qemu/__init__.py   |   9 +-
tests/acceptance/virtio-gpu.py              |   2 +-
tests/docker/dockerfiles/python.docker      |  18 ++
tests/qemu-iotests/297                      |   1 +
tests/qemu-iotests/300                      |   4 +-
tests/qemu-iotests/iotests.py               |   2 +-
tests/vm/aarch64vm.py                       |   2 +-
tests/vm/basevm.py                          |   3 +-
41 files changed, 750 insertions(+), 119 deletions(-)
create mode 100644 python/PACKAGE.rst
create mode 100644 python/README.rst
create mode 100644 python/qemu/README.rst
create mode 100644 python/qemu/machine/README.rst
create mode 100644 python/qemu/qmp/README.rst
create mode 100644 python/qemu/utils/README.rst
create mode 100644 python/.gitignore
create mode 100644 python/MANIFEST.in
create mode 100644 python/Makefile
create mode 100644 python/Pipfile
create mode 100644 python/Pipfile.lock
create mode 100644 python/VERSION
create mode 100644 python/avocado.cfg
delete mode 100644 python/mypy.ini
delete mode 100644 python/qemu/.flake8
delete mode 100644 python/qemu/.isort.cfg
delete mode 100644 python/qemu/__init__.py
create mode 100644 python/qemu/machine/__init__.py
rename python/qemu/{ => machine}/console_socket.py (94%)
rename python/qemu/{ => machine}/machine.py (96%)
rename python/qemu/{ => machine}/qtest.py (98%)
delete mode 100644 python/qemu/pylintrc
rename python/qemu/{qmp.py => qmp/__init__.py} (96%)
rename python/qemu/{utils.py => utils/__init__.py} (66%)
rename python/qemu/{ => utils}/accel.py (100%)
create mode 100644 python/setup.cfg
create mode 100755 python/setup.py
create mode 100755 python/tests/flake8.sh
create mode 100755 python/tests/isort.sh
create mode 100755 python/tests/mypy.sh
create mode 100755 python/tests/pylint.sh
create mode 100644 tests/docker/dockerfiles/python.docker
[PATCH v7 00/31] python: create installable package
Posted by John Snow 2 years, 11 months ago
Based-on: https://gitlab.com/cleber.gnu/qemu/-/commits/python-next
CI: https://gitlab.com/jsnow/qemu/-/pipelines/309506648
GitLab: https://gitlab.com/jsnow/qemu/-/tree/python-package-mk4
MR: https://gitlab.com/jsnow/qemu/-/merge_requests/7

ABOUT
=====

This series factors the python/qemu directory as an installable
package. It does not yet actually change the mechanics of how any other
python source in the tree actually consumes it (yet), beyond the import
path -- some import statements change in a few places.

RATIONALE
=========

The primary motivation of this series is primarily to formalize our
dependencies on mypy, flake8, isort, and pylint alongside versions that
are known to work. It does this using the setup.cfg and setup.py
files. It also adds explicitly pinned versions (using Pipfile.lock) of
these dependencies that should behave in a repeatable and known way for
developers and CI environments both. Lastly, it enables those CI checks
such that we can enforce Python coding quality checks via the CI tests.

An auxiliary motivation is that 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 that button
remains *unpushed* and this series *will not* cause any such
releases. We have time to debate finer points like API guarantees and
versioning even after this series is merged.

Other bits of interest
----------------------

With the python tooling as a proper package, you can install this
package in editable or production mode to a virtual environment, your
local user environment, or your system packages. The primary benefit of
this is to gain access to QMP tooling regardless of CWD, without needing
to battle sys.path (and confounding other python analysis tools).

For example: when developing, you may go to qemu/python/ and run `make
venv` followed by `pipenv shell` to activate a virtual environment that
contains the qemu python packages. These packages will always reflect
the current version of the source files in the tree. When you are
finished, you can simply exit the shell (^d) to remove these packages
from your python environment.

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 by using pip: "pip install
[--user] ."

TESTING THIS SERIES
===================

First of all, nothing should change. Without any intervention,
everything should behave exactly as it did before. The only new
information here comes from how to interact with and run the linters
that will be enforcing code quality standards in this subdirectory.

There are various invocations available that will test subtly different
combinations using subtly different environments. I am assuming some
light knowledge of Python environments and installing Python packages
here. If you have questions, I would be delighted to answer them.

To test the new tests, CD to ./python/ first, and then:

0. Try "make" or "make help" to get a sense of this series.

1. Try "make venv && pipenv shell" to get a venv with the package
   installed to it in editable mode. Ctrl+d exits this venv shell. While
   in this shell, any python script that uses "from qemu.[qmp|machine]
   import ..." should work correctly regardless of where the script is,
   or what your CWD is.

   This will pull some packages from PyPI and install them into the
   virtual environment, leaving your normal environment untouched.

   You will need Python 3.6 and pipenv installed on your system to do
   this step. For Fedora: "dnf install python36 pipenv" will do the
   trick. If you don't have this, skip down to \#4 and onwards.

2. Try "make check" while still in the shell to run the Python linters
using the venv built in the previous step. This will run avocado, which
will in turn execute mypy, flake8, isort and pylint with the correct
arguments.

3. Having exited the shell from above, try "make venv-check". This will
create and update the venv if needed, then run 'make check' within the
context of that shell. It should pass as long as the above did. You
should be able to run "make distclean" prior to running "make
venv-check" and have the entire process work start to finish.

4. Still outside of the venv, you may try running "make check". This
will not install anything, but unless you have the right Python
dependencies installed, these tests may fail for you. You might try
using "pip install --user .[devel]" to install the development packages
needed to run the tests successfully to your local user's python
environment. Once done, you will probably want to "pip uninstall qemu"
to remove the qemu packages to avoid them interfering with other things.

5. "make distclean" will delete the venv and any temporary files that
may have been created by packaging, installing, testing, etc.

6. You may also (if you wish) create your own environment using a Python
   other than 3.6, bypassing pipenv. This may be useful for environments
   in which you simply do not have Python 3.6 readily available, or
   explicitly wish to test against a different version.

   Using the Python of your choice:

   - `> make distclean` (Remove the .venv, if you created one.)
   - `> /usr/bin/python3.9 -m venv .venv`
   - `> source .venv/bin/activate` (or activate.[fish|csh])
   - `> make develop`  (Installs linter deps to this venv)
   - `> make check`    (Runs tests using current env)
   - `> deactivate`    (Leaves the venv)

   This *should* pass, and if it doesn't, it's a bug. Due to
   dependencies changing like shifting sands, it's impossible to promise
   support for every last combination of dependency and python
   version. This is why the "make venv-check" target uses Python 3 and a
   very explicit set of packages instead. Still, this form *should*
   pass.

7. If you are running Fedora or a distro that packages multiple Python
versions, you can try running "make check-tox" to run the linters under
all Python versions from Python 3.6 to 3.9. This will create a series of
virtual environments under the .tox folder, leaving your existing
environment unscathed. This should pass, provided you have the requisite
Python versions on hand. When you are done, "make distclean" should
remove any testing files.

CHANGELOG
=========

V7
--

```
001/31:[----] [--] 'python/console_socket: avoid one-letter variable'
002/31:[----] [--] 'python/machine: use subprocess.DEVNULL instead of open(os.path.devnull)'
003/31:[0002] [FC] 'python/machine: use subprocess.run instead of subprocess.Popen'
004/31:[----] [--] 'python/console_socket: Add a pylint ignore'
005/31:[----] [-C] 'python/machine: Disable pylint warning for open() in _pre_launch'
006/31:[----] [--] 'python/machine: disable warning for Popen in _launch()'
007/31:[down] 'python/machine: Trim line length to below 80 chars'
008/31:[----] [--] 'iotests/297: add --namespace-packages to mypy arguments'
009/31:[0040] [FC] 'python: create qemu packages'
010/31:[0005] [FC] 'python: add qemu package installer'
011/31:[----] [--] 'python: add VERSION file'
012/31:[0008] [FC] 'python: add directory structure README.rst files'
013/31:[0001] [FC] 'python: add MANIFEST.in'
014/31:[----] [--] 'python: Add pipenv support'
015/31:[----] [--] 'python: add pylint import exceptions'
016/31:[----] [-C] 'python: move pylintrc into setup.cfg'
017/31:[0084] [FC] 'python: add pylint to pipenv'
018/31:[----] [-C] 'python: move flake8 config to setup.cfg'
019/31:[----] [-C] 'python: add excluded dirs to flake8 config'
020/31:[0028] [FC] 'python: Add flake8 to pipenv'
021/31:[----] [--] 'python: move mypy.ini into setup.cfg'
022/31:[0004] [FC] 'python: add mypy to pipenv'
023/31:[----] [--] 'python: move .isort.cfg into setup.cfg'
024/31:[0004] [FC] 'python/qemu: add isort to pipenv'
025/31:[0004] [FC] 'python/qemu: add qemu package itself to pipenv'
026/31:[0016] [FC] 'python: add devel package requirements to setuptools'
027/31:[0106] [FC] 'python: add avocado-framework and tests'
028/31:[0020] [FC] 'python: add Makefile for some common tasks'
029/31:[0004] [FC] 'python: add .gitignore'
030/31:[0026] [FC] 'python: add tox support'
031/31:[0043] [FC] 'gitlab: add python linters to CI'
```

Most of these changes are minor or were discussed on-list.
(RBs were kept in most, but not all cases.)

 - 00: Rebased on cleber/python-next
     - Inlined python linting fixes again for my own sake of ease.
 - 03: Changed check=True to check=False
 - 07: New, minor delinting on top of cleber/python-next.
 - 09: Squashed 'utils' package creation into this patch. Update commit msg.
     - Removed list of exported functions from package docstring
     - utils/__init__.py now based on Cleber's utils.py
 - 10: List subpackages explicitly; avoids some warnings for bdist/sdist
 - 12: Phrasing suggestions from Cleber.
 - 13: Exclude 'README.rst' (Didn't realize it was being included!)
     - Update commit msg.
 - 17: Upgraded to pylint 2.8.x ...
 - 20: Only Pipenv.lock hash changes.
 - 22: Only Pipenv.lock hash changes.
 - 24: Update commit msg.
     - Pipenv.lock hash changes.
 - 25: Only Pipenv.lock hash changes.
 - 26: Add README/PACKAGE blurbs explaining "qemu[devel]" usage.
 - 27: Pipenv.lock hash changes.
     - Update 'pipenv lock' comment to suggest '--dev'
     - Re-sort dependency list to be alphabetical.
 - 28: Use python3 setup.py clean --all for make target;
     - shift dist/ cleaning to 'make distclean'
     - Update README/PACKAGE blurbs to suggest the 'make develop' target
 - 29: Remove .gitignore entries duplicated from the tree root.
 - 30: Add Python 3.10 to the test matrix.
     - Add PyPI classifiers for Python 3.6 - 3.10 support
     - Move tox.ini into setup.cfg
 - 31: Add a new python container just for running these tests.
     - Rename 'check-python' to 'check-python-pipenv'
     - Add 'check-python-tox' test that is allowed to fail w/ warning to CI.

STATUS
=======

```
[01] python-console_socket-avoid     # [RB] CR,PM [SOB] JS
[02] python-machine-use-subprocess   # [RB] CR,PM [SOB] JS
[03] python-machine-use-subprocess-0 # [RB] CR [TB] CR [SOB] JS
[04] python-console_socket-add-a     # [RB] CR [SOB] JS
[05] python-machine-disable-pylint   # [RB] CR,WdSM [SOB] JS
[06] python-machine-disable-warning  # [RB] CR [SOB] JS
[07] python-machine-trim-line        # [SOB] JS
[08] iotests-297-add-namespace       # [RB] CR [SOB] JS
[09] python-create-qemu-packages     # [SOB] JS
[10] python-add-qemu-package         # [SOB] JS
[11] python-add-version-file         # [RB] CR [SOB] JS
[12] python-add-directory-structure  # [RB] CR [SOB] JS
[13] python-add-manifest-in          # [SOB] JS
[14] python-add-pipenv-support       # [RB] CR [SOB] JS
[15] python-add-pylint-import        # [RB] CR [SOB] JS
[16] python-move-pylintrc-into       # [RB] CR [TB] CR [SOB] JS
[17] python-add-pylint-to-pipenv     # [SOB] JS
[18] python-move-flake8-config-to    # [RB] CR [SOB] JS
[19] python-add-excluded-dirs-to     # [RB] CR [SOB] JS
[20] python-add-flake8-to-pipenv     # [RB] CR [TB] CR [SOB] JS
[21] python-move-mypy-ini-into       # [RB] CR [SOB] JS
[22] python-add-mypy-to-pipenv       # [RB] CR [TB] CR [SOB] JS
[23] python-move-isort-cfg-into      # [RB] CR [SOB] JS
[24] python-qemu-add-isort-to        # [RB] CR [SOB] JS
[25] python-qemu-add-qemu-package    # [RB] CR [TB] CR [SOB] JS
[26] python-add-devel-package        # [RB] CR [SOB] JS
[27] python-add-avocado-framework    # [RB] CR [TB] CR [SOB] JS
[28] python-add-makefile-for-some    # [RB] CR [TB] CR [SOB] JS
[29] python-add-gitignore            # [SOB] JS
[30] python-add-tox-support          # [RB] CR [TB] CR [SOB] JS
[31] gitlab-add-python-linters-to    # [SOB] JS
```

In need of review:

```
[07] python-machine-trim-line        (New)
[09] python-create-qemu-packages     (Modified enough due to rebase)
[10] python-add-qemu-package         (Modified w/o discussion on list)
[13] python-add-manifest-in          (Modified w/o discussion on list)
[17] python-add-pylint-to-pipenv     (Upgraded pylint minimum version)
[29] python-add-gitignore
[31] gitlab-add-python-linters-to
```

John Snow (31):
  python/console_socket: avoid one-letter variable
  python/machine: use subprocess.DEVNULL instead of
    open(os.path.devnull)
  python/machine: use subprocess.run instead of subprocess.Popen
  python/console_socket: Add a pylint ignore
  python/machine: Disable pylint warning for open() in _pre_launch
  python/machine: disable warning for Popen in _launch()
  python/machine: Trim line length to below 80 chars
  iotests/297: add --namespace-packages to mypy arguments
  python: create qemu packages
  python: add qemu package installer
  python: add VERSION file
  python: add directory structure README.rst files
  python: add MANIFEST.in
  python: Add pipenv support
  python: add pylint import exceptions
  python: move pylintrc into setup.cfg
  python: add pylint to pipenv
  python: move flake8 config to setup.cfg
  python: add excluded dirs to flake8 config
  python: Add flake8 to pipenv
  python: move mypy.ini into setup.cfg
  python: add mypy to pipenv
  python: move .isort.cfg into setup.cfg
  python/qemu: add isort to pipenv
  python/qemu: add qemu package itself to pipenv
  python: add devel package requirements to setuptools
  python: add avocado-framework and tests
  python: add Makefile for some common tasks
  python: add .gitignore
  python: add tox support
  gitlab: add python linters to CI

 python/PACKAGE.rst                          |  43 ++++
 python/README.rst                           |  58 +++++
 python/qemu/README.rst                      |   8 +
 python/qemu/machine/README.rst              |   9 +
 python/qemu/qmp/README.rst                  |   9 +
 python/qemu/utils/README.rst                |   7 +
 .gitlab-ci.d/containers.yml                 |   5 +
 .gitlab-ci.yml                              |  26 +++
 python/.gitignore                           |  16 ++
 python/MANIFEST.in                          |   3 +
 python/Makefile                             |  48 ++++
 python/Pipfile                              |  13 ++
 python/Pipfile.lock                         | 231 ++++++++++++++++++++
 python/VERSION                              |   1 +
 python/avocado.cfg                          |  10 +
 python/mypy.ini                             |   4 -
 python/qemu/.flake8                         |   2 -
 python/qemu/.isort.cfg                      |   7 -
 python/qemu/__init__.py                     |  11 -
 python/qemu/machine/__init__.py             |  36 +++
 python/qemu/{ => machine}/console_socket.py |  11 +-
 python/qemu/{ => machine}/machine.py        |  46 ++--
 python/qemu/{ => machine}/qtest.py          |   3 +-
 python/qemu/pylintrc                        |  58 -----
 python/qemu/{qmp.py => qmp/__init__.py}     |  12 +-
 python/qemu/{utils.py => utils/__init__.py} |  18 +-
 python/qemu/{ => utils}/accel.py            |   0
 python/setup.cfg                            | 102 +++++++++
 python/setup.py                             |  23 ++
 python/tests/flake8.sh                      |   2 +
 python/tests/isort.sh                       |   2 +
 python/tests/mypy.sh                        |   2 +
 python/tests/pylint.sh                      |   2 +
 tests/acceptance/avocado_qemu/__init__.py   |   9 +-
 tests/acceptance/virtio-gpu.py              |   2 +-
 tests/docker/dockerfiles/python.docker      |  18 ++
 tests/qemu-iotests/297                      |   1 +
 tests/qemu-iotests/300                      |   4 +-
 tests/qemu-iotests/iotests.py               |   2 +-
 tests/vm/aarch64vm.py                       |   2 +-
 tests/vm/basevm.py                          |   3 +-
 41 files changed, 750 insertions(+), 119 deletions(-)
 create mode 100644 python/PACKAGE.rst
 create mode 100644 python/README.rst
 create mode 100644 python/qemu/README.rst
 create mode 100644 python/qemu/machine/README.rst
 create mode 100644 python/qemu/qmp/README.rst
 create mode 100644 python/qemu/utils/README.rst
 create mode 100644 python/.gitignore
 create mode 100644 python/MANIFEST.in
 create mode 100644 python/Makefile
 create mode 100644 python/Pipfile
 create mode 100644 python/Pipfile.lock
 create mode 100644 python/VERSION
 create mode 100644 python/avocado.cfg
 delete mode 100644 python/mypy.ini
 delete mode 100644 python/qemu/.flake8
 delete mode 100644 python/qemu/.isort.cfg
 delete mode 100644 python/qemu/__init__.py
 create mode 100644 python/qemu/machine/__init__.py
 rename python/qemu/{ => machine}/console_socket.py (94%)
 rename python/qemu/{ => machine}/machine.py (96%)
 rename python/qemu/{ => machine}/qtest.py (98%)
 delete mode 100644 python/qemu/pylintrc
 rename python/qemu/{qmp.py => qmp/__init__.py} (96%)
 rename python/qemu/{utils.py => utils/__init__.py} (66%)
 rename python/qemu/{ => utils}/accel.py (100%)
 create mode 100644 python/setup.cfg
 create mode 100755 python/setup.py
 create mode 100755 python/tests/flake8.sh
 create mode 100755 python/tests/isort.sh
 create mode 100755 python/tests/mypy.sh
 create mode 100755 python/tests/pylint.sh
 create mode 100644 tests/docker/dockerfiles/python.docker

-- 
2.31.1