mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-10-29 17:42:12 +08:00
Vendorise `packaging.versions.LegacyVersion`
Fix https://github.com/galaxyproject/galaxy/issues/15898 .
This commit is contained in:
@@ -66,7 +66,7 @@ myst-parser==1.0.0 ; python_version >= "3.7" and python_version < "3.12"
|
||||
numpy==1.21.6 ; python_version >= "3.7" and python_version < "3.8"
|
||||
numpy==1.24.2 ; python_version >= "3.8" and python_version < "3.12"
|
||||
outcome==1.2.0 ; python_version >= "3.7" and python_version < "3.12"
|
||||
packaging==21.3 ; python_version >= "3.7" and python_version < "3.12"
|
||||
packaging==23.1 ; python_version >= "3.7" and python_version < "3.12"
|
||||
pathspec==0.11.1 ; python_version >= "3.7" and python_version < "3.12"
|
||||
pillow==9.5.0 ; python_version >= "3.7" and python_version < "3.12"
|
||||
pkce==1.0.3 ; python_version >= "3.7" and python_version < "3.12"
|
||||
|
||||
@@ -110,7 +110,7 @@ numpy==1.21.6 ; python_version >= "3.7" and python_version < "3.8"
|
||||
numpy==1.24.2 ; python_version >= "3.8" and python_version < "3.12"
|
||||
oauthlib==3.2.2 ; python_version >= "3.7" and python_version < "3.12"
|
||||
oyaml==1.0 ; python_version >= "3.7" and python_version < "3.12"
|
||||
packaging==21.3 ; python_version >= "3.7" and python_version < "3.12"
|
||||
packaging==23.1 ; python_version >= "3.7" and python_version < "3.12"
|
||||
paramiko==3.1.0 ; python_version >= "3.7" and python_version < "3.12"
|
||||
parse==1.19.0 ; python_version >= "3.7" and python_version < "3.12"
|
||||
parsley==1.3 ; python_version >= "3.7" and python_version < "3.12"
|
||||
|
||||
@@ -22,8 +22,8 @@ from typing import (
|
||||
TYPE_CHECKING,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
import yaml
|
||||
from packaging.version import Version
|
||||
from pulsar.client.staging import COMMAND_VERSION_FILENAME
|
||||
|
||||
from galaxy import (
|
||||
@@ -1089,7 +1089,7 @@ class MinimalJobWrapper(HasResourceParameters):
|
||||
@property
|
||||
def outputs_directory(self):
|
||||
"""Default location of ``outputs_to_working_directory``."""
|
||||
return None if self.created_with_galaxy_version < packaging.version.parse("20.01") else "outputs"
|
||||
return None if self.created_with_galaxy_version < Version("20.01") else "outputs"
|
||||
|
||||
@property
|
||||
def outputs_to_working_directory(self):
|
||||
@@ -1098,7 +1098,7 @@ class MinimalJobWrapper(HasResourceParameters):
|
||||
@property
|
||||
def created_with_galaxy_version(self):
|
||||
galaxy_version = self.get_job().galaxy_version or "19.05"
|
||||
return packaging.version.parse(galaxy_version)
|
||||
return Version(galaxy_version)
|
||||
|
||||
@property
|
||||
def dependency_shell_commands(self):
|
||||
|
||||
@@ -14,9 +14,9 @@ from typing import (
|
||||
Dict,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
import pulsar.core
|
||||
import yaml
|
||||
from packaging.version import Version
|
||||
from pulsar.client import (
|
||||
build_client_manager,
|
||||
CLIENT_INPUT_PATH_TYPES,
|
||||
@@ -64,9 +64,9 @@ __all__ = (
|
||||
)
|
||||
|
||||
MINIMUM_PULSAR_VERSIONS = {
|
||||
"_default_": packaging.version.parse("0.7.0.dev3"),
|
||||
"remote_metadata": packaging.version.parse("0.8.0"),
|
||||
"remote_container_handling": packaging.version.parse("0.9.1.dev0"), # probably 0.10 ultimately?
|
||||
"_default_": Version("0.7.0.dev3"),
|
||||
"remote_metadata": Version("0.8.0"),
|
||||
"remote_container_handling": Version("0.9.1.dev0"), # probably 0.10 ultimately?
|
||||
}
|
||||
|
||||
NO_REMOTE_GALAXY_FOR_METADATA_MESSAGE = "Pulsar misconfiguration - Pulsar client configured to set metadata remotely, but remote Pulsar isn't properly configured with a galaxy_home directory."
|
||||
@@ -498,7 +498,7 @@ class PulsarJobRunner(AsynchronousJobRunner):
|
||||
pulsar_version=pulsar_version,
|
||||
)
|
||||
rewrite_paths = not PulsarJobRunner.__rewrite_parameters(client)
|
||||
if pulsar_version < packaging.version.parse("0.14.999") and rewrite_paths:
|
||||
if pulsar_version < Version("0.14.999") and rewrite_paths:
|
||||
job_wrapper.disable_commands_in_new_shell()
|
||||
container = None
|
||||
if remote_container is None:
|
||||
@@ -810,7 +810,7 @@ class PulsarJobRunner(AsynchronousJobRunner):
|
||||
|
||||
@staticmethod
|
||||
def pulsar_version(remote_job_config):
|
||||
pulsar_version = packaging.version.parse(remote_job_config.get("pulsar_version", "0.6.0"))
|
||||
pulsar_version = Version(remote_job_config.get("pulsar_version", "0.6.0"))
|
||||
return pulsar_version
|
||||
|
||||
@staticmethod
|
||||
@@ -818,7 +818,7 @@ class PulsarJobRunner(AsynchronousJobRunner):
|
||||
check_features = check_features or {}
|
||||
# 0.6.0 was newest Pulsar version that did not report it's version.
|
||||
pulsar_version = PulsarJobRunner.pulsar_version(remote_job_config)
|
||||
needed_version = packaging.version.parse("0.0.0")
|
||||
needed_version = Version("0.0.0")
|
||||
log.info(f"pulsar_version is {pulsar_version}")
|
||||
for feature, needed in list(check_features.items()) + [("_default_", True)]:
|
||||
if not needed:
|
||||
|
||||
@@ -20,8 +20,9 @@ from typing import (
|
||||
Union,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
from packaging.version import Version
|
||||
|
||||
from galaxy.tool_util.version import parse_version
|
||||
from galaxy.util import (
|
||||
commands,
|
||||
download_to_file,
|
||||
@@ -87,7 +88,7 @@ def find_conda_prefix() -> str:
|
||||
class CondaContext(installable.InstallableContext):
|
||||
installable_description = "Conda"
|
||||
_conda_build_available: Optional[bool]
|
||||
_conda_version: Optional[Union[packaging.version.Version, packaging.version.LegacyVersion]]
|
||||
_conda_version: Optional[Version]
|
||||
_experimental_solver_available: Optional[bool]
|
||||
|
||||
def __init__(
|
||||
@@ -132,10 +133,10 @@ class CondaContext(installable.InstallableContext):
|
||||
self._experimental_solver_available = None
|
||||
|
||||
@property
|
||||
def conda_version(self) -> Union[packaging.version.Version, packaging.version.LegacyVersion]:
|
||||
def conda_version(self) -> Version:
|
||||
if self._conda_version is None:
|
||||
self._guess_conda_properties()
|
||||
assert isinstance(self._conda_version, (packaging.version.Version, packaging.version.LegacyVersion))
|
||||
assert isinstance(self._conda_version, Version)
|
||||
return self._conda_version
|
||||
|
||||
@property
|
||||
@@ -147,12 +148,12 @@ class CondaContext(installable.InstallableContext):
|
||||
|
||||
def _guess_conda_properties(self) -> None:
|
||||
info = self.conda_info()
|
||||
self._conda_version = packaging.version.parse(info["conda_version"])
|
||||
self._conda_version = Version(info["conda_version"])
|
||||
self._conda_build_available = False
|
||||
conda_build_version = info.get("conda_build_version")
|
||||
if conda_build_version and conda_build_version != "not installed":
|
||||
try:
|
||||
packaging.version.parse(conda_build_version)
|
||||
Version(conda_build_version)
|
||||
self._conda_build_available = True
|
||||
except Exception:
|
||||
pass
|
||||
@@ -169,9 +170,9 @@ class CondaContext(installable.InstallableContext):
|
||||
@property
|
||||
def _experimental_solver_args(self) -> List[str]:
|
||||
if self._experimental_solver_available is None:
|
||||
self._experimental_solver_available = self.conda_version >= packaging.version.parse(
|
||||
"4.12.0"
|
||||
) and self.is_package_installed("conda-libmamba-solver")
|
||||
self._experimental_solver_available = self.conda_version >= Version("4.12.0") and self.is_package_installed(
|
||||
"conda-libmamba-solver"
|
||||
)
|
||||
if self._experimental_solver_available:
|
||||
return ["--experimental-solver", "libmamba"]
|
||||
else:
|
||||
@@ -282,7 +283,7 @@ class CondaContext(installable.InstallableContext):
|
||||
for try_strict in [True, False]:
|
||||
create_args = ["-y", "--quiet"]
|
||||
if try_strict:
|
||||
if self.conda_version >= packaging.version.parse("4.7.5"):
|
||||
if self.conda_version >= Version("4.7.5"):
|
||||
create_args.append("--strict-channel-priority")
|
||||
else:
|
||||
continue
|
||||
@@ -313,7 +314,7 @@ class CondaContext(installable.InstallableContext):
|
||||
for try_strict in [True, False]:
|
||||
install_args = ["-y"]
|
||||
if try_strict:
|
||||
if self.conda_version >= packaging.version.parse("4.7.5"):
|
||||
if self.conda_version >= Version("4.7.5"):
|
||||
install_args.append("--strict-channel-priority")
|
||||
else:
|
||||
continue
|
||||
@@ -567,7 +568,7 @@ def best_search_result(
|
||||
# the latest update time.
|
||||
hits = json.loads(res).get(conda_target.package, [])[::-1]
|
||||
hits = sorted(hits, key=lambda hit: hit["build_number"], reverse=True)
|
||||
hits = sorted(hits, key=lambda hit: packaging.version.parse(hit["version"]), reverse=True)
|
||||
hits = sorted(hits, key=lambda hit: parse_version(hit["version"]), reverse=True)
|
||||
except commands.CommandLineException as e:
|
||||
log.error(f"Could not execute: '{e.command}'\n{e}")
|
||||
hits = []
|
||||
@@ -632,8 +633,8 @@ def build_isolated_environment(
|
||||
# Adjust fix if they fix Conda - xref
|
||||
# - https://github.com/galaxyproject/galaxy/issues/3635
|
||||
# - https://github.com/conda/conda/issues/2035
|
||||
offline_works = (conda_context.conda_version < packaging.version.parse("4.3")) or (
|
||||
conda_context.conda_version >= packaging.version.parse("4.4")
|
||||
offline_works = (conda_context.conda_version < Version("4.3")) or (
|
||||
conda_context.conda_version >= Version("4.4")
|
||||
)
|
||||
if offline_works:
|
||||
create_args.append("--offline")
|
||||
|
||||
@@ -17,11 +17,12 @@ from typing import (
|
||||
Union,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
import requests
|
||||
from conda_package_streaming.package_streaming import stream_conda_info
|
||||
from conda_package_streaming.url import stream_conda_info as stream_conda_info_from_url
|
||||
|
||||
from galaxy.tool_util.version import parse_version
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from galaxy.tool_util.deps.container_resolvers import ResolutionCache
|
||||
|
||||
@@ -189,8 +190,8 @@ def parse_tag(tag):
|
||||
build_number = -1
|
||||
return PARSED_TAG(
|
||||
tag=tag,
|
||||
version=packaging.version.parse(version),
|
||||
build_string=packaging.version.parse(build_string),
|
||||
version=parse_version(version),
|
||||
build_string=parse_version(build_string),
|
||||
build_number=build_number,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
"""This module contains linting functions for general aspects of the tool."""
|
||||
import re
|
||||
|
||||
import packaging.version
|
||||
from galaxy.tool_util.version import (
|
||||
LegacyVersion,
|
||||
parse_version,
|
||||
)
|
||||
|
||||
ERROR_VERSION_MSG = "Tool version is missing or empty."
|
||||
WARN_VERSION_MSG = "Tool version [%s] is not compliant with PEP 440."
|
||||
@@ -34,10 +37,10 @@ def lint_general(tool_source, lint_ctx):
|
||||
else:
|
||||
tool_node = None
|
||||
version = tool_source.parse_version() or ""
|
||||
parsed_version = packaging.version.parse(version)
|
||||
parsed_version = parse_version(version)
|
||||
if not version:
|
||||
lint_ctx.error(ERROR_VERSION_MSG, node=tool_node)
|
||||
elif isinstance(parsed_version, packaging.version.LegacyVersion):
|
||||
elif isinstance(parsed_version, LegacyVersion):
|
||||
lint_ctx.warn(WARN_VERSION_MSG % version, node=tool_node)
|
||||
elif version != version.strip():
|
||||
lint_ctx.warn(WARN_WHITESPACE_PRESUFFIX % ("Tool version", version), node=tool_node)
|
||||
|
||||
@@ -9,7 +9,7 @@ from typing import (
|
||||
Optional,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
from packaging.version import Version
|
||||
|
||||
from galaxy.tool_util.deps import requirements
|
||||
from galaxy.tool_util.parser.util import (
|
||||
@@ -525,7 +525,7 @@ class XmlToolSource(ToolSource):
|
||||
|
||||
def parse_strict_shell(self):
|
||||
command_el = self._command_el
|
||||
if packaging.version.parse(self.parse_profile()) < packaging.version.parse("20.09"):
|
||||
if Version(self.parse_profile()) < Version("20.09"):
|
||||
default = "False"
|
||||
else:
|
||||
default = "True"
|
||||
@@ -558,7 +558,7 @@ class XmlToolSource(ToolSource):
|
||||
|
||||
return rval
|
||||
|
||||
def parse_profile(self):
|
||||
def parse_profile(self) -> str:
|
||||
# Pre-16.04 or default XML defaults
|
||||
# - Use standard error for error detection.
|
||||
# - Don't run shells with -e
|
||||
@@ -573,7 +573,7 @@ class XmlToolSource(ToolSource):
|
||||
def parse_python_template_version(self):
|
||||
python_template_version = self.root.get("python_template_version")
|
||||
if python_template_version is not None:
|
||||
python_template_version = packaging.version.Version(python_template_version)
|
||||
python_template_version = Version(python_template_version)
|
||||
return python_template_version
|
||||
|
||||
def parse_creator(self):
|
||||
|
||||
@@ -5,9 +5,9 @@ from typing import (
|
||||
List,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
from sortedcontainers import SortedSet
|
||||
|
||||
from galaxy.tool_util.version import parse_version
|
||||
from galaxy.util.tool_version import remove_version_from_guid
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class ToolLineage:
|
||||
|
||||
def __init__(self, tool_id, **kwds):
|
||||
self.tool_id = tool_id
|
||||
self.tool_versions = SortedSet(key=packaging.version.parse)
|
||||
self.tool_versions = SortedSet(key=parse_version)
|
||||
|
||||
@property
|
||||
def tool_ids(self) -> List[str]:
|
||||
|
||||
@@ -25,10 +25,7 @@ from typing import (
|
||||
)
|
||||
|
||||
import requests
|
||||
from packaging.version import (
|
||||
parse as parse_version,
|
||||
Version,
|
||||
)
|
||||
from packaging.version import Version
|
||||
from requests import Response
|
||||
from requests.cookies import RequestsCookieJar
|
||||
from typing_extensions import (
|
||||
@@ -200,7 +197,7 @@ class GalaxyInteractorApi:
|
||||
@property
|
||||
def target_galaxy_version(self):
|
||||
if self._target_galaxy_version is None:
|
||||
self._target_galaxy_version = parse_version(self._get("version").json()["version_major"])
|
||||
self._target_galaxy_version = Version(self._get("version").json()["version_major"])
|
||||
return self._target_galaxy_version
|
||||
|
||||
@property
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
# Copyright (c) Donald Stufft and individual contributors.
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# The following code derives from packaging 21.3 before the LegacyVersion class
|
||||
# was removed: https://github.com/pypa/packaging/blob/21.3/packaging/version.py
|
||||
|
||||
import re
|
||||
from typing import (
|
||||
Iterator,
|
||||
List,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
|
||||
from packaging.version import (
|
||||
_BaseVersion,
|
||||
InvalidVersion,
|
||||
Version,
|
||||
)
|
||||
|
||||
__all__ = ["parse_version", "LegacyVersion"]
|
||||
|
||||
LegacyCmpKey = Tuple[int, Tuple[str, ...]]
|
||||
|
||||
|
||||
def parse_version(version: str) -> Union["LegacyVersion", "Version"]:
|
||||
"""
|
||||
Parse the given version string and return either a :class:`Version` object
|
||||
or a :class:`LegacyVersion` object depending on if the given version is
|
||||
a valid PEP 440 version or a legacy version.
|
||||
"""
|
||||
try:
|
||||
return Version(version)
|
||||
except InvalidVersion:
|
||||
return LegacyVersion(version)
|
||||
|
||||
|
||||
class LegacyVersion(_BaseVersion):
|
||||
def __init__(self, version: str) -> None:
|
||||
self._version = str(version)
|
||||
self._key = _legacy_cmpkey(self._version)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self._version
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<LegacyVersion('{self}')>"
|
||||
|
||||
@property
|
||||
def public(self) -> str:
|
||||
return self._version
|
||||
|
||||
@property
|
||||
def base_version(self) -> str:
|
||||
return self._version
|
||||
|
||||
@property
|
||||
def epoch(self) -> int:
|
||||
return -1
|
||||
|
||||
@property
|
||||
def release(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def pre(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def post(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def dev(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def local(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_prerelease(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_postrelease(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_devrelease(self) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
|
||||
|
||||
_legacy_version_replacement_map = {
|
||||
"pre": "c",
|
||||
"preview": "c",
|
||||
"-": "final-",
|
||||
"rc": "c",
|
||||
"dev": "@",
|
||||
}
|
||||
|
||||
|
||||
def _parse_version_parts(s: str) -> Iterator[str]:
|
||||
for part in _legacy_version_component_re.split(s):
|
||||
part = _legacy_version_replacement_map.get(part, part)
|
||||
|
||||
if not part or part == ".":
|
||||
continue
|
||||
|
||||
if part[:1] in "0123456789":
|
||||
# pad for numeric comparison
|
||||
yield part.zfill(8)
|
||||
else:
|
||||
yield "*" + part
|
||||
|
||||
# ensure that alpha/beta/candidate are before final
|
||||
yield "*final"
|
||||
|
||||
|
||||
def _legacy_cmpkey(version: str) -> LegacyCmpKey:
|
||||
# We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
|
||||
# greater than or equal to 0. This will effectively put the LegacyVersion,
|
||||
# which uses the defacto standard originally implemented by setuptools,
|
||||
# as before all PEP 440 versions.
|
||||
epoch = -1
|
||||
|
||||
# This scheme is taken from pkg_resources.parse_version setuptools prior to
|
||||
# it's adoption of the packaging library.
|
||||
parts: List[str] = []
|
||||
for part in _parse_version_parts(version.lower()):
|
||||
if part.startswith("*"):
|
||||
# remove "-" before a prerelease tag
|
||||
if part < "*final":
|
||||
while parts and parts[-1] == "*final-":
|
||||
parts.pop()
|
||||
|
||||
# remove trailing zeros from each series of numeric parts
|
||||
while parts and parts[-1] == "00000000":
|
||||
parts.pop()
|
||||
|
||||
parts.append(part)
|
||||
|
||||
return epoch, tuple(parts)
|
||||
@@ -25,10 +25,10 @@ from typing import (
|
||||
)
|
||||
from urllib.parse import unquote_plus
|
||||
|
||||
import packaging.version
|
||||
import webob.exc
|
||||
from lxml import etree
|
||||
from mako.template import Template
|
||||
from packaging.version import Version
|
||||
|
||||
from galaxy import (
|
||||
exceptions,
|
||||
@@ -79,6 +79,10 @@ from galaxy.tool_util.toolbox import (
|
||||
)
|
||||
from galaxy.tool_util.toolbox.views.sources import StaticToolBoxViewSources
|
||||
from galaxy.tool_util.verify.test_data import TestDataNotFoundError
|
||||
from galaxy.tool_util.version import (
|
||||
LegacyVersion,
|
||||
parse_version,
|
||||
)
|
||||
from galaxy.tools import expressions
|
||||
from galaxy.tools.actions import (
|
||||
DefaultToolAction,
|
||||
@@ -223,28 +227,28 @@ GALAXY_LIB_TOOLS_UNVERSIONED = [
|
||||
# Tools that needed galaxy on the PATH in the past but no longer do along
|
||||
# with the version at which they were fixed.
|
||||
GALAXY_LIB_TOOLS_VERSIONED = {
|
||||
"meme_fimo": packaging.version.parse("5.0.5"),
|
||||
"Extract genomic DNA 1": packaging.version.parse("3.0.0"),
|
||||
"fetchflank": packaging.version.parse("1.0.1"),
|
||||
"gops_intersect_1": packaging.version.parse("1.0.0"),
|
||||
"lastz_wrapper_2": packaging.version.parse("1.3"),
|
||||
"PEsortedSAM2readprofile": packaging.version.parse("1.1.1"),
|
||||
"sam_to_bam": packaging.version.parse("1.1.3"),
|
||||
"sam_pileup": packaging.version.parse("1.1.3"),
|
||||
"vcf_to_maf_customtrack1": packaging.version.parse("1.0.1"),
|
||||
"secure_hash_message_digest": packaging.version.parse("0.0.2"),
|
||||
"join1": packaging.version.parse("2.1.3"),
|
||||
"wiggle2simple1": packaging.version.parse("1.0.1"),
|
||||
"CONVERTER_wiggle_to_interval_0": packaging.version.parse("1.0.1"),
|
||||
"aggregate_scores_in_intervals2": packaging.version.parse("1.1.4"),
|
||||
"CONVERTER_fastq_to_fqtoc0": packaging.version.parse("1.0.1"),
|
||||
"CONVERTER_tar_to_directory": packaging.version.parse("1.0.1"),
|
||||
"tabular_to_dbnsfp": packaging.version.parse("1.0.1"),
|
||||
"cufflinks": packaging.version.parse("2.2.1.3"),
|
||||
"Convert characters1": packaging.version.parse("1.0.1"),
|
||||
"substitutions1": packaging.version.parse("1.0.1"),
|
||||
"winSplitter": packaging.version.parse("1.0.1"),
|
||||
"Interval2Maf1": packaging.version.parse("1.0.1+galaxy0"),
|
||||
"meme_fimo": parse_version("5.0.5"),
|
||||
"Extract genomic DNA 1": parse_version("3.0.0"),
|
||||
"fetchflank": parse_version("1.0.1"),
|
||||
"gops_intersect_1": parse_version("1.0.0"),
|
||||
"lastz_wrapper_2": parse_version("1.3"),
|
||||
"PEsortedSAM2readprofile": parse_version("1.1.1"),
|
||||
"sam_to_bam": parse_version("1.1.3"),
|
||||
"sam_pileup": parse_version("1.1.3"),
|
||||
"vcf_to_maf_customtrack1": parse_version("1.0.1"),
|
||||
"secure_hash_message_digest": parse_version("0.0.2"),
|
||||
"join1": parse_version("2.1.3"),
|
||||
"wiggle2simple1": parse_version("1.0.1"),
|
||||
"CONVERTER_wiggle_to_interval_0": parse_version("1.0.1"),
|
||||
"aggregate_scores_in_intervals2": parse_version("1.1.4"),
|
||||
"CONVERTER_fastq_to_fqtoc0": parse_version("1.0.1"),
|
||||
"CONVERTER_tar_to_directory": parse_version("1.0.1"),
|
||||
"tabular_to_dbnsfp": parse_version("1.0.1"),
|
||||
"cufflinks": parse_version("2.2.1.3"),
|
||||
"Convert characters1": parse_version("1.0.1"),
|
||||
"substitutions1": parse_version("1.0.1"),
|
||||
"winSplitter": parse_version("1.0.1"),
|
||||
"Interval2Maf1": parse_version("1.0.1+galaxy0"),
|
||||
}
|
||||
|
||||
REQUIRE_FULL_DIRECTORY = {
|
||||
@@ -252,7 +256,7 @@ REQUIRE_FULL_DIRECTORY = {
|
||||
}
|
||||
IMPLICITLY_REQUIRED_TOOL_FILES: Dict[str, Dict] = {
|
||||
"deseq2": {
|
||||
"version": packaging.version.parse("2.11.40.6"),
|
||||
"version": parse_version("2.11.40.6"),
|
||||
"required": {"includes": [{"path": "*.R", "path_type": "glob"}]},
|
||||
},
|
||||
# minimum example:
|
||||
@@ -277,21 +281,21 @@ IMPLICITLY_REQUIRED_TOOL_FILES: Dict[str, Dict] = {
|
||||
|
||||
|
||||
class safe_update(NamedTuple):
|
||||
min_version: Union[packaging.version.LegacyVersion, packaging.version.Version]
|
||||
current_version: Union[packaging.version.LegacyVersion, packaging.version.Version]
|
||||
min_version: Union[LegacyVersion, Version]
|
||||
current_version: Union[LegacyVersion, Version]
|
||||
|
||||
|
||||
# Tool updates that did not change parameters in a way that requires rebuilding workflows
|
||||
WORKFLOW_SAFE_TOOL_VERSION_UPDATES = {
|
||||
"Filter1": safe_update(packaging.version.parse("1.1.0"), packaging.version.parse("1.1.1")),
|
||||
"__BUILD_LIST__": safe_update(packaging.version.parse("1.0.0"), packaging.version.parse("1.1.0")),
|
||||
"__APPLY_RULES__": safe_update(packaging.version.parse("1.0.0"), packaging.version.parse("1.1.0")),
|
||||
"__EXTRACT_DATASET__": safe_update(packaging.version.parse("1.0.0"), packaging.version.parse("1.0.1")),
|
||||
"Grep1": safe_update(packaging.version.parse("1.0.1"), packaging.version.parse("1.0.4")),
|
||||
"Show beginning1": safe_update(packaging.version.parse("1.0.0"), packaging.version.parse("1.0.2")),
|
||||
"Show tail1": safe_update(packaging.version.parse("1.0.0"), packaging.version.parse("1.0.1")),
|
||||
"sort1": safe_update(packaging.version.parse("1.1.0"), packaging.version.parse("1.2.0")),
|
||||
"CONVERTER_interval_to_bgzip_0": safe_update(packaging.version.parse("1.0.1"), packaging.version.parse("1.0.2")),
|
||||
"Filter1": safe_update(parse_version("1.1.0"), parse_version("1.1.1")),
|
||||
"__BUILD_LIST__": safe_update(parse_version("1.0.0"), parse_version("1.1.0")),
|
||||
"__APPLY_RULES__": safe_update(parse_version("1.0.0"), parse_version("1.1.0")),
|
||||
"__EXTRACT_DATASET__": safe_update(parse_version("1.0.0"), parse_version("1.0.1")),
|
||||
"Grep1": safe_update(parse_version("1.0.1"), parse_version("1.0.4")),
|
||||
"Show beginning1": safe_update(parse_version("1.0.0"), parse_version("1.0.2")),
|
||||
"Show tail1": safe_update(parse_version("1.0.0"), parse_version("1.0.1")),
|
||||
"sort1": safe_update(parse_version("1.1.0"), parse_version("1.2.0")),
|
||||
"CONVERTER_interval_to_bgzip_0": safe_update(parse_version("1.0.1"), parse_version("1.0.2")),
|
||||
}
|
||||
|
||||
|
||||
@@ -757,7 +761,7 @@ class Tool(Dictifiable):
|
||||
# guid attribute since it is useful to have.
|
||||
self.guid = guid
|
||||
self.old_id: Optional[str] = None
|
||||
self.python_template_version: Optional[packaging.version.Version] = None
|
||||
self.python_template_version: Optional[Version] = None
|
||||
self._lineage = None
|
||||
self.dependencies: List = []
|
||||
# populate toolshed repository info, if available
|
||||
@@ -835,7 +839,7 @@ class Tool(Dictifiable):
|
||||
|
||||
@property
|
||||
def version_object(self):
|
||||
return packaging.version.parse(self.version)
|
||||
return parse_version(self.version)
|
||||
|
||||
@property
|
||||
def sa_session(self):
|
||||
@@ -1005,12 +1009,8 @@ class Tool(Dictifiable):
|
||||
if not dynamic and not self.id:
|
||||
raise Exception(f"Missing tool 'id' for tool at '{tool_source}'")
|
||||
|
||||
profile = packaging.version.parse(str(self.profile))
|
||||
if (
|
||||
self.app.name == "galaxy"
|
||||
and profile >= packaging.version.parse("16.04")
|
||||
and packaging.version.parse(VERSION_MAJOR) < profile
|
||||
):
|
||||
profile = Version(str(self.profile))
|
||||
if self.app.name == "galaxy" and profile >= Version("16.04") and Version(VERSION_MAJOR) < profile:
|
||||
message = f"The tool [{self.id}] targets version {self.profile} of Galaxy, you should upgrade Galaxy to ensure proper functioning of this tool."
|
||||
raise Exception(message)
|
||||
|
||||
@@ -1018,9 +1018,9 @@ class Tool(Dictifiable):
|
||||
if self.python_template_version is None:
|
||||
# If python_template_version not specified we assume tools with profile versions >= 19.05 are python 3 ready
|
||||
if self.profile >= 19.05:
|
||||
self.python_template_version = packaging.version.Version("3.5")
|
||||
self.python_template_version = Version("3.5")
|
||||
else:
|
||||
self.python_template_version = packaging.version.Version("2.7")
|
||||
self.python_template_version = Version("2.7")
|
||||
|
||||
# Get the (user visible) name of the tool
|
||||
self.name = tool_source.parse_name()
|
||||
|
||||
@@ -7,7 +7,7 @@ from typing import (
|
||||
Sequence,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
from packaging.version import Version
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -147,7 +147,7 @@ def _json_wrap_input(input, value_wrapper, profile, handle_files="skip"):
|
||||
else:
|
||||
json_value = _cast_if_not_none(value_wrapper, bool, empty_to_none=input.optional)
|
||||
elif input_type == "select":
|
||||
if packaging.version.parse(str(profile)) < packaging.version.parse("20.05"):
|
||||
if Version(str(profile)) < Version("20.05"):
|
||||
json_value = _cast_if_not_none(value_wrapper, str)
|
||||
else:
|
||||
if input.multiple:
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
import traceback
|
||||
from lib2to3.refactor import RefactoringTool
|
||||
|
||||
import packaging.version
|
||||
from Cheetah.Compiler import Compiler
|
||||
from Cheetah.NameMapper import NotFound
|
||||
from Cheetah.Parser import ParseError
|
||||
from Cheetah.Template import Template
|
||||
from packaging.version import Version
|
||||
from past.translation import myfixes
|
||||
|
||||
from . import unicodify
|
||||
@@ -55,7 +55,7 @@ def fill_template(
|
||||
if not context:
|
||||
context = kwargs
|
||||
if isinstance(python_template_version, str):
|
||||
python_template_version = packaging.version.parse(python_template_version)
|
||||
python_template_version = Version(python_template_version)
|
||||
try:
|
||||
klass = Template.compile(source=template_text, compilerClass=compiler_class)
|
||||
except ParseError as e:
|
||||
|
||||
@@ -17,7 +17,6 @@ from typing import (
|
||||
Union,
|
||||
)
|
||||
|
||||
import packaging.version
|
||||
from cwl_utils.expression import do_eval
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
@@ -48,6 +47,7 @@ from galaxy.schema.invocation import (
|
||||
)
|
||||
from galaxy.tool_util.cwl.util import set_basename_and_derived_properties
|
||||
from galaxy.tool_util.parser.output_objects import ToolExpressionOutput
|
||||
from galaxy.tool_util.version import parse_version
|
||||
from galaxy.tools import (
|
||||
DatabaseOperationTool,
|
||||
DefaultToolState,
|
||||
@@ -1679,11 +1679,7 @@ class ToolModule(WorkflowModule):
|
||||
if safe_version and self.tool.lineage:
|
||||
# tool versions are sorted from old to new, so check newest version first
|
||||
for lineage_version in reversed(self.tool.lineage.tool_versions):
|
||||
if (
|
||||
safe_version.current_version
|
||||
>= packaging.version.parse(lineage_version)
|
||||
>= safe_version.min_version
|
||||
):
|
||||
if safe_version.current_version >= parse_version(lineage_version) >= safe_version.min_version:
|
||||
self.tool = trans.app.toolbox.get_tool(
|
||||
tool_id, tool_version=lineage_version, exact=True, tool_uuid=tool_uuid
|
||||
)
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ Mercurial = "*"
|
||||
mrcfile = "*"
|
||||
nodeenv = "*"
|
||||
numpy = "*"
|
||||
packaging = "<22" # packaging 22.0 dropped LegacyVersion
|
||||
packaging = "*"
|
||||
paramiko = "!=2.9.0, !=2.9.1" # https://github.com/paramiko/paramiko/issues/1961
|
||||
Parsley = "*"
|
||||
Paste = "*"
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
import pytest
|
||||
from packaging.version import Version
|
||||
|
||||
from galaxy.tool_util.version import (
|
||||
LegacyVersion,
|
||||
parse_version,
|
||||
)
|
||||
|
||||
# This list must be in the correct sorting order
|
||||
VERSIONS = [
|
||||
# Implicit epoch of 0
|
||||
"1.0.dev456",
|
||||
"1.0a1",
|
||||
"1.0a2.dev456",
|
||||
"1.0a12.dev456",
|
||||
"1.0a12",
|
||||
"1.0b1.dev456",
|
||||
"1.0b2",
|
||||
"1.0b2.post345.dev456",
|
||||
"1.0b2.post345",
|
||||
"1.0b2-346",
|
||||
"1.0c1.dev456",
|
||||
"1.0c1",
|
||||
"1.0rc2",
|
||||
"1.0c3",
|
||||
"1.0",
|
||||
"1.0.post456.dev34",
|
||||
"1.0.post456",
|
||||
"1.1.dev1",
|
||||
"1.2+123abc",
|
||||
"1.2+123abc456",
|
||||
"1.2+abc",
|
||||
"1.2+abc123",
|
||||
"1.2+abc123def",
|
||||
"1.2+1234.abc",
|
||||
"1.2+123456",
|
||||
"1.2.r32+123456",
|
||||
"1.2.rev33+123456",
|
||||
# Explicit epoch of 1
|
||||
"1!1.0.dev456",
|
||||
"1!1.0a1",
|
||||
"1!1.0a2.dev456",
|
||||
"1!1.0a12.dev456",
|
||||
"1!1.0a12",
|
||||
"1!1.0b1.dev456",
|
||||
"1!1.0b2",
|
||||
"1!1.0b2.post345.dev456",
|
||||
"1!1.0b2.post345",
|
||||
"1!1.0b2-346",
|
||||
"1!1.0c1.dev456",
|
||||
"1!1.0c1",
|
||||
"1!1.0rc2",
|
||||
"1!1.0c3",
|
||||
"1!1.0",
|
||||
"1!1.0.post456.dev34",
|
||||
"1!1.0.post456",
|
||||
"1!1.1.dev1",
|
||||
"1!1.2+123abc",
|
||||
"1!1.2+123abc456",
|
||||
"1!1.2+abc",
|
||||
"1!1.2+abc123",
|
||||
"1!1.2+abc123def",
|
||||
"1!1.2+1234.abc",
|
||||
"1!1.2+123456",
|
||||
"1!1.2.r32+123456",
|
||||
"1!1.2.rev33+123456",
|
||||
]
|
||||
|
||||
LEGACY_VERSIONS = ["foobar", "a cat is fine too", "lolwut", "1.8.1+2+galaxy0"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version", VERSIONS)
|
||||
def test_parse_pep440_versions(version: str) -> None:
|
||||
assert isinstance(parse_version(version), Version)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version", LEGACY_VERSIONS)
|
||||
def test_legacy_version_fields(version: str) -> None:
|
||||
parsed_version = parse_version(version)
|
||||
assert isinstance(parsed_version, LegacyVersion)
|
||||
assert parsed_version.public == version
|
||||
assert parsed_version.base_version == version
|
||||
assert parsed_version.epoch == -1
|
||||
assert parsed_version.release is None
|
||||
assert parsed_version.pre is None
|
||||
assert parsed_version.post is None
|
||||
assert parsed_version.dev is None
|
||||
assert parsed_version.local is None
|
||||
assert parsed_version.is_prerelease is False
|
||||
assert parsed_version.is_postrelease is False
|
||||
assert parsed_version.is_devrelease is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"lower_ver,greater_ver",
|
||||
[(VERSIONS[i], VERSIONS[i + 1]) for i in range(len(VERSIONS) - 1)]
|
||||
+ [(lv, v) for v in VERSIONS for lv in LEGACY_VERSIONS],
|
||||
)
|
||||
def test_version_cmp(lower_ver: str, greater_ver: str) -> None:
|
||||
assert parse_version(lower_ver) < parse_version(greater_ver)
|
||||
Reference in New Issue
Block a user