From dc787e08e29729f53551839cd4ff6ed19dfb4f16 Mon Sep 17 00:00:00 2001 From: Yihuang Yu Date: Mon, 3 Jun 2024 17:06:40 +0800 Subject: [PATCH] rfe: Deprecate distutils module distutils will be formally marked as deprecated since python3.10, and will no longer work from python3.12. To enable python3.12 in avocado framework, this patch will replace distutils to use other modules. Signed-off-by: Yihuang Yu --- setup.py | 42 +++++++++++++++++++++++---------------- virttest/bootstrap.py | 5 ++--- virttest/utils_version.py | 10 ++++------ 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/setup.py b/setup.py index eb21f7869f..0e23de3df0 100644 --- a/setup.py +++ b/setup.py @@ -12,24 +12,26 @@ # Copyright: Red Hat Inc. 2013-2014 # Author: Lucas Meneghel Rodrigues -# pylint: disable=E0611 -import os import shutil -from distutils.command.clean import clean from pathlib import Path - -from setuptools import find_packages, setup +from setuptools import find_packages, setup, Command VERSION = open("VERSION", "r").read().strip() -class Clean(clean): - """Our custom command to get rid of scratch files after build.""" +class CleanCommand(Command): + """Custom command to clean up build and scratch files.""" + + description = "Custom clean command to tidy up the project root" + user_options = [] + + def initialize_options(self): + pass - description = "Get rid of scratch, byte files and build stuff." + def finalize_options(self): + pass def run(self): - super().run() cleaning_list = [ "MANIFEST", "BUILD", @@ -46,12 +48,12 @@ def run(self): cleaning_list += list(Path(".").rglob("__pycache__")) for e in cleaning_list: - if not os.path.exists(e): - continue - if os.path.isfile(e): - os.remove(e) - if os.path.isdir(e): - shutil.rmtree(e) + path = Path(e) + if path.exists(): + if path.is_file(): + path.unlink() + elif path.is_dir(): + shutil.rmtree(path) if __name__ == "__main__": @@ -96,6 +98,12 @@ def run(self): "avocado-vt = avocado_vt.plugins.vt_runner:VTTestRunner", ], }, - install_requires=["netifaces", "six", "aexpect", "avocado-framework>=82.1"], - cmdclass={"clean": Clean}, + install_requires=[ + "netifaces", + "packaging", + "six", + "aexpect", + "avocado-framework>=82.1", + ], + cmdclass={"clean": CleanCommand}, ) diff --git a/virttest/bootstrap.py b/virttest/bootstrap.py index 581434eca7..4b8ec9e46b 100644 --- a/virttest/bootstrap.py +++ b/virttest/bootstrap.py @@ -4,7 +4,6 @@ import re import shutil import sys -from distutils import dir_util # virtualenv problem pylint: disable=E0611 from avocado.utils import cpu, distro, genio, linux_modules from avocado.utils import path as utils_path @@ -910,7 +909,7 @@ def bootstrap(options, interactive=False): LOG.info("%d - Updating test providers repo configuration from local copy", step) tp_base_dir = data_dir.get_base_test_providers_dir() tp_local_dir = data_dir.get_test_providers_dir() - dir_util.copy_tree(tp_base_dir, tp_local_dir) + shutil.copytree(tp_base_dir, tp_local_dir) not_downloaded = asset.test_providers_not_downloaded() if not_downloaded: @@ -950,7 +949,7 @@ def bootstrap(options, interactive=False): LOG.info( "%d - Syncing backend dirs %s -> %s", step, base_backend_dir, local_backend_dir ) - dir_util.copy_tree(base_backend_dir, local_backend_dir) + shutil.copytree(base_backend_dir, local_backend_dir) sync_download_dir(interactive) diff --git a/virttest/utils_version.py b/virttest/utils_version.py index 7540f1b64a..6a17370498 100644 --- a/virttest/utils_version.py +++ b/virttest/utils_version.py @@ -1,8 +1,6 @@ import operator import re -from distutils.version import ( # pylint: disable=no-name-in-module,import-error - LooseVersion, -) +from packaging.version import parse class VersionInterval(object): @@ -31,8 +29,8 @@ def __init__(self, interval): raise ValueError("Invalid string representation of an interval") self.opening, lower, upper, self.closing = match.groups() - self.lower_bound = LooseVersion(lower) if lower else None - self.upper_bound = LooseVersion(upper) if upper else None + self.lower_bound = parse(lower) if lower else None + self.upper_bound = parse(upper) if upper else None self._check_interval() def _check_interval(self): @@ -64,7 +62,7 @@ def __contains__(self, version): "]": operator.ge, } in_interval = True - version = LooseVersion(version) + version = parse(version) if self.lower_bound: opt = op_mapping.get(self.opening) in_interval = opt(self.lower_bound, version)