diff -Nru spades-3.13.1+dfsg/debian/changelog spades-3.13.1+dfsg/debian/changelog --- spades-3.13.1+dfsg/debian/changelog 2020-11-19 17:38:35.000000000 +0000 +++ spades-3.13.1+dfsg/debian/changelog 2022-02-21 10:37:56.000000000 +0000 @@ -1,3 +1,10 @@ +spades (3.13.1+dfsg-2ubuntu1) jammy; urgency=medium + + * d/patches: + + Add python 3.10 support by getting rid of distutils. + + -- Alexandre Ghiti Mon, 21 Feb 2022 10:37:56 +0000 + spades (3.13.1+dfsg-2build3) hirsute; urgency=medium * No-change rebuild to build with python3.9 as default. diff -Nru spades-3.13.1+dfsg/debian/control spades-3.13.1+dfsg/debian/control --- spades-3.13.1+dfsg/debian/control 2019-11-22 09:48:44.000000000 +0000 +++ spades-3.13.1+dfsg/debian/control 2022-02-21 10:37:42.000000000 +0000 @@ -1,5 +1,6 @@ Source: spades -Maintainer: Debian Med Packaging Team +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Med Packaging Team Uploaders: Andreas Tille , Sascha Steinbiss , Michael R. Crusoe , diff -Nru spades-3.13.1+dfsg/debian/patches/python3.10_support.patch spades-3.13.1+dfsg/debian/patches/python3.10_support.patch --- spades-3.13.1+dfsg/debian/patches/python3.10_support.patch 1970-01-01 00:00:00.000000000 +0000 +++ spades-3.13.1+dfsg/debian/patches/python3.10_support.patch 2022-02-10 15:02:26.000000000 +0000 @@ -0,0 +1,229 @@ +Description: Add python 3.10 support + distutils is deprecated and its use triggers DeprecationWarning which + make some Ubuntu autopkgtests fail: fix this by replacing distutils by + equivalent functions. + distutils.version is simply replaced with packaging.version. + distutils.copy_tree is a bit more complicated as preserve_mode/times + does not exist directly in shutil.copytree function. + This is an adapted version of the forwarded one. +Author: Alexandre Ghiti +Origin: vendor +Forwarded: https://github.com/ablab/spades/pull/914 +Last-Update: 2022-02-10 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/assembler/spades.py ++++ b/assembler/spades.py +@@ -10,7 +10,6 @@ + import os + import shutil + from site import addsitedir +-from distutils import dir_util + from os.path import abspath, expanduser + import sys + import getopt +@@ -650,6 +649,24 @@ + sys.exit(code) + + ++# shutil.copyfile does not copy any metadata (time and permission), so one ++# cannot expect preserve_mode = False and preserve_times = True to work. ++def copy_tree(src, dst, preserve_times = True, preserve_mode = True): ++ if preserve_mode == False: ++ copy_fn = shutil.copyfile ++ else: ++ copy_fn = shutil.copy2 ++ ++ # shutil.copytree preserves the timestamp, so we must update it afterwards. ++ shutil.copytree(src, dst, copy_function = copy_fn, dirs_exist_ok = True) ++ ++ if preserve_times == False: ++ for dirpath, _, filenames in os.walk(dst): ++ os.utime(dirpath, None) ++ for file in filenames: ++ os.utime(os.path.join(dirpath, file), None) ++ ++ + def main(args): + os.environ["LC_ALL"] = "C" + +@@ -778,9 +795,9 @@ + shutil.rmtree(tmp_configs_dir) + if not os.path.isdir(tmp_configs_dir): + if options_storage.configs_dir: +- dir_util.copy_tree(options_storage.configs_dir, tmp_configs_dir, preserve_times=False, preserve_mode=False) ++ copy_tree(options_storage.configs_dir, tmp_configs_dir, preserve_times=False, preserve_mode=False) + else: +- dir_util.copy_tree(os.path.join(spades_home, "configs"), tmp_configs_dir, preserve_times=False, preserve_mode=False) ++ copy_tree(os.path.join(spades_home, "configs"), tmp_configs_dir, preserve_times=False, preserve_mode=False) + + corrected_dataset_yaml_filename = '' + if "error_correction" in cfg: +--- a/assembler/src/spades_pipeline/corrector_logic.py ++++ b/assembler/src/spades_pipeline/corrector_logic.py +@@ -14,7 +14,6 @@ + import support + import process_cfg + from site import addsitedir +-from distutils import dir_util + + + +@@ -37,6 +36,23 @@ + file_c.close() + + ++# shutil.copyfile does not copy any metadata (time and permission), so one ++# cannot expect preserve_mode = False and preserve_times = True to work. ++def copy_tree(src, dst, preserve_times = True, preserve_mode = True): ++ if preserve_mode == False: ++ copy_fn = shutil.copyfile ++ else: ++ copy_fn = shutil.copy2 ++ ++ # shutil.copytree preserves the timestamp, so we must update it afterwards. ++ shutil.copytree(src, dst, copy_function = copy_fn, dirs_exist_ok = True) ++ ++ if preserve_times == False: ++ for dirpath, _, filenames in os.walk(dst): ++ os.utime(dirpath, None) ++ for file in filenames: ++ os.utime(os.path.join(dirpath, file), None) ++ + + def run_corrector(configs_dir, execution_home, cfg, + ext_python_modules_home, log, to_correct, result): +@@ -49,7 +65,7 @@ + dst_configs = os.path.join(cfg.output_dir, "configs") + if os.path.exists(dst_configs): + shutil.rmtree(dst_configs) +- dir_util.copy_tree(os.path.join(configs_dir, "corrector"), dst_configs, preserve_times=False) ++ copy_tree(os.path.join(configs_dir, "corrector"), dst_configs, preserve_times=False) + cfg_file_name = os.path.join(dst_configs, "corrector.info") + + cfg.tmp_dir = support.get_tmp_dir(prefix="corrector_") +--- a/assembler/src/spades_pipeline/hammer_logic.py ++++ b/assembler/src/spades_pipeline/hammer_logic.py +@@ -16,7 +16,6 @@ + import options_storage + import process_cfg + from site import addsitedir +-from distutils import dir_util + from os.path import isfile + + +@@ -104,6 +103,24 @@ + default_flow_style=False, default_style='"', width=float("inf")) + + ++# shutil.copyfile does not copy any metadata (time and permission), so one ++# cannot expect preserve_mode = False and preserve_times = True to work. ++def copy_tree(src, dst, preserve_times = True, preserve_mode = True): ++ if preserve_mode == False: ++ copy_fn = shutil.copyfile ++ else: ++ copy_fn = shutil.copy2 ++ ++ # shutil.copytree preserves the timestamp, so we must update it afterwards. ++ shutil.copytree(src, dst, copy_function = copy_fn, dirs_exist_ok = True) ++ ++ if preserve_times == False: ++ for dirpath, _, filenames in os.walk(dst): ++ os.utime(dirpath, None) ++ for file in filenames: ++ os.utime(os.path.join(dirpath, file), None) ++ ++ + def run_hammer(corrected_dataset_yaml_filename, configs_dir, execution_home, cfg, + dataset_data, ext_python_modules_home, only_compressing_is_needed, log): + addsitedir(ext_python_modules_home) +@@ -128,10 +145,10 @@ + if os.path.exists(dst_configs): + shutil.rmtree(dst_configs) + if cfg.iontorrent: +- dir_util.copy_tree(os.path.join(configs_dir, "ionhammer"), dst_configs, preserve_times=False) ++ copy_tree(os.path.join(configs_dir, "ionhammer"), dst_configs, preserve_times=False) + cfg_file_name = os.path.join(dst_configs, "ionhammer.cfg") + else: +- dir_util.copy_tree(os.path.join(configs_dir, "hammer"), dst_configs, preserve_times=False) ++ copy_tree(os.path.join(configs_dir, "hammer"), dst_configs, preserve_times=False) + cfg_file_name = os.path.join(dst_configs, "config.info") + + cfg.tmp_dir = support.get_tmp_dir(prefix="hammer_") +--- a/assembler/src/spades_pipeline/spades_logic.py ++++ b/assembler/src/spades_pipeline/spades_logic.py +@@ -14,7 +14,6 @@ + import process_cfg + from process_cfg import bool_to_str + from site import addsitedir +-from distutils import dir_util + import options_storage + + BASE_STAGE = "construction" +@@ -156,6 +155,24 @@ + command.append(os.path.join(configs_dir, "careful_mode.info")) + + ++# shutil.copyfile does not copy any metadata (time and permission), so one ++# cannot expect preserve_mode = False and preserve_times = True to work. ++def copy_tree(src, dst, preserve_times = True, preserve_mode = True): ++ if preserve_mode == False: ++ copy_fn = shutil.copyfile ++ else: ++ copy_fn = shutil.copy2 ++ ++ # shutil.copytree preserves the timestamp, so we must update it afterwards. ++ shutil.copytree(src, dst, copy_function = copy_fn, dirs_exist_ok = True) ++ ++ if preserve_times == False: ++ for dirpath, _, filenames in os.walk(dst): ++ os.utime(dirpath, None) ++ for file in filenames: ++ os.utime(os.path.join(dirpath, file), None) ++ ++ + def run_iteration(configs_dir, execution_home, cfg, log, K, prev_K, last_one): + data_dir = os.path.join(cfg.output_dir, "K%d" % K) + stage = BASE_STAGE +@@ -180,8 +197,7 @@ + shutil.rmtree(data_dir) + os.makedirs(data_dir) + +- dir_util._path_created = {} # see http://stackoverflow.com/questions/9160227/dir-util-copy-tree-fails-after-shutil-rmtree +- dir_util.copy_tree(os.path.join(configs_dir, "debruijn"), dst_configs, preserve_times=False) ++ copy_tree(os.path.join(configs_dir, "debruijn"), dst_configs, preserve_times=False) + + log.info("\n== Running assembler: " + ("K%d" % K) + "\n") + if prev_K: +@@ -254,7 +270,7 @@ + shutil.rmtree(data_dir) + os.makedirs(data_dir) + +- dir_util.copy_tree(os.path.join(configs_dir, "debruijn"), dst_configs, preserve_times=False) ++ copy_tree(os.path.join(configs_dir, "debruijn"), dst_configs, preserve_times=False) + + log.info("\n== Running scaffold correction \n") + scaffolds_file = os.path.join(latest, "scaffolds.fasta") +--- a/assembler/src/spades_pipeline/support.py ++++ b/assembler/src/spades_pipeline/support.py +@@ -21,7 +21,10 @@ + from common import SeqIO + import math + from os.path import abspath, expanduser, join +-from distutils.version import LooseVersion ++try: ++ from packaging.version import Version ++except ModuleNotFoundError: ++ from distutils.version import LooseVersion as Version + + # constants to print and detect warnings and errors in logs + SPADES_PY_ERROR_MESSAGE = "== Error == " +@@ -99,7 +102,7 @@ + min_inc = max_inc = supported_versions + max_exc = __next_version(max_inc) + supported_versions_msg.append("Python%s: %s" % (major, supported_versions.replace('+', " and higher"))) +- if LooseVersion(min_inc) <= LooseVersion(current_version) < LooseVersion(max_exc): ++ if Version(min_inc) <= Version(current_version) < Version(max_exc): + return True + error("Python version " + current_version + " is not supported!\n" + + "Supported versions are " + ", ".join(supported_versions_msg)) diff -Nru spades-3.13.1+dfsg/debian/patches/series spades-3.13.1+dfsg/debian/patches/series --- spades-3.13.1+dfsg/debian/patches/series 2019-11-22 09:48:44.000000000 +0000 +++ spades-3.13.1+dfsg/debian/patches/series 2022-02-10 15:02:26.000000000 +0000 @@ -20,3 +20,4 @@ gcc7.patch python3.patch yaml_load.patch +python3.10_support.patch