Files
galaxy/scripts/fix_dm_versions.py
T
paperbenni bec3d3ad9c Drop support for Python 3.8
Drop Python 3.8 support in 5 Pulsar-compatible packages
(job_metrics, tool_util, tool_util_models, util, objectstore)
and run pyupgrade --py310-plus on their source code.

- Bump requires-python from >=3.8 to >=3.10 in all 5 packages
- Remove Python 3.8 and 3.9 classifiers
- Remove ruff per-file-ignores for UP rules on these paths
- Remove backports.zoneinfo conditional dependency
- Remove pydyf<0.11 pin from conditional-requirements.txt
- Update Makefile pyupgrade target (remove PY38_PYUPGRADE_PATHS)
- Update CI workflow to test with Python 3.10 instead of 3.8

Clean up unused deprecated typing imports after pyupgrade

Remove now-unused typing imports (Dict, List, Optional, Set, Tuple,
Type, Union) that became dead after pyupgrade --py310-plus converted
annotations to use built-in types and | syntax.

Also run ruff check --fix --select=UP007,UP045 across the entire
codebase to convert remaining Optional[X] -> X | None and
Union[X, Y] -> X | Y patterns.

Enable ruff UP007/UP045 for Python 3.10 union syntax

Remove UP007 (Union[X,Y] -> X | Y) and UP045 (Optional[X] -> X | None)
from the ruff ignore list and convert all type aliases across the
codebase. These rules were deferred while Python 3.9 was supported;
requires-python is now >=3.10.

A custom script was used because neither ruff --fix nor
pyupgrade --py310-plus converts Optional[X]/Union[X,Y] in type alias
positions (e.g. X = Union[A, B]) — they only handle annotation
positions (e.g. def f(x: Optional[int])). All 167 violations were
module-level type aliases. A few edge cases were fixed manually:
single-element Union[X,], typing.Union qualified refs, runtime
Optional[type] calls, and Annotated[Optional[...]] pydantic fields.

Fix UP007 autofix regression with string forward reference type aliases

Commit fa6bd955a0 enabled ruff UP007/UP045 and auto-fixed
module-level type aliases using Union with string forward
references, producing invalid 'str | str' expressions.

This was a known ruff bug (charliermarsh/ruff#826) that has since
been fixed in later ruff versions, but this codebase was
converted before the fix was in place.

Revert to Union syntax and restore TYPE_CHECKING imports that
ruff's TCH rule cleaned up as a side effect when it thought the
forward references were unused.
2026-06-25 15:12:05 +01:00

81 lines
2.6 KiB
Python
Executable File

#!/usr/bin/env python
import argparse
import shutil
from datetime import datetime
from lxml import etree
desc = """
Fix shed_data_manager_conf.xml
Modifies the guid and version attribute of data_manager tags:
- the version in the guid (text after the last slash) is replaced
by the data manager tool version
- the version attribute is set to the data manager tool version
By default only data managers with duplicated guid are modified
and version attributes are not added if absent.
A copy of the original file with a time stamp appended to the name
is created.
Note, if there are versions of the data manager tool that have the
same version there will still be DMs with duplicated guids. These
need to be corrected manually.
"""
parser = argparse.ArgumentParser(description=desc)
parser.add_argument(
"shed_data_manager_conf",
metavar="CONFIG_FILE",
type=str,
default="config/shed_data_manager_conf.xml",
help="an integer for the accumulator",
)
parser.add_argument(
"--all-entries", action="store_true", help="modify all entries (default only those with duplicated guid)"
)
parser.add_argument("--add-version", action="store_true", help="also add version attribute if absent")
parser.add_argument("--dry-run", action="store_true", help="do not write resulting config file")
args = parser.parse_args()
with open(args.shed_data_manager_conf) as fh:
tree = etree.parse(args.shed_data_manager_conf)
root = tree.getroot()
guid_mapping = {}
for dm in root.iter("data_manager"):
guid = dm.attrib["guid"]
if guid not in guid_mapping:
guid_mapping[guid] = [dm]
else:
guid_mapping[guid].append(dm)
for guid in guid_mapping:
if len(guid_mapping[guid]) > 1:
print(f"{guid} found {len(guid_mapping[guid])}x")
elif not args.all_entries:
continue
for dm in guid_mapping[guid]:
tool_version = dm.find("./tool/version")
tool_version = tool_version.text
new_guid = f"{guid[: guid.rfind('/')]}/{tool_version}"
dm.attrib["guid"] = new_guid
print(f"changing guid: {guid} -> {new_guid}")
if "version" in dm.attrib:
print(f"changing version: {dm.attrib['version']} -> {tool_version}")
dm.attrib["version"] = tool_version
elif args.add_version:
print(f"adding version: {tool_version}")
dm.attrib["version"] = tool_version
if not args.dry_run:
nfn = args.shed_data_manager_conf + datetime.now().isoformat()
print(f"save copy at {nfn}")
shutil.copyfile(args.shed_data_manager_conf, nfn)
print(f"saving {args.shed_data_manager_conf}")
tree.write(args.shed_data_manager_conf)