diff --git a/.circleci/config.yml b/.circleci/config.yml
index 9c27be38c17..02cead37092 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -15,7 +15,7 @@ variables:
jobs:
get_code:
docker:
- - image: cimg/python:3.9
+ - image: cimg/python:3.10
<<: *set_workdir
steps:
# Replace standard code checkout with shallow clone to speed things up.
@@ -73,7 +73,7 @@ jobs:
- ~/repo
validate_test_tools:
docker:
- - image: cimg/python:3.9
+ - image: cimg/python:3.10
<<: *set_workdir
steps:
- *restore_repo_cache
diff --git a/.github/workflows/api.yaml b/.github/workflows/api.yaml
index 30b926eb4bc..a8085d198de 100644
--- a/.github/workflows/api.yaml
+++ b/.github/workflows/api.yaml
@@ -31,7 +31,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
chunk: [0, 1]
services:
postgres:
diff --git a/.github/workflows/bioblend.yaml b/.github/workflows/bioblend.yaml
index 4e23a6d0e6c..ea88b832ade 100644
--- a/.github/workflows/bioblend.yaml
+++ b/.github/workflows/bioblend.yaml
@@ -32,7 +32,7 @@ jobs:
fail-fast: false
matrix:
tox_env: [py314]
- galaxy_python_version: ['3.9']
+ galaxy_python_version: ['3.10']
steps:
- name: Checkout Galaxy
uses: actions/checkout@v6
diff --git a/.github/workflows/check_test_class_names.yaml b/.github/workflows/check_test_class_names.yaml
index 5c1e61ad01d..5f966e10930 100644
--- a/.github/workflows/check_test_class_names.yaml
+++ b/.github/workflows/check_test_class_names.yaml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
steps:
- uses: actions/checkout@v6
with:
diff --git a/.github/workflows/converter_tests.yaml b/.github/workflows/converter_tests.yaml
index 73eddcea628..f157ae93d9f 100644
--- a/.github/workflows/converter_tests.yaml
+++ b/.github/workflows/converter_tests.yaml
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
steps:
- if: github.event_name == 'schedule'
run: |
diff --git a/.github/workflows/cwl_conformance.yaml b/.github/workflows/cwl_conformance.yaml
index 48565879cea..21bdd3d4d8f 100644
--- a/.github/workflows/cwl_conformance.yaml
+++ b/.github/workflows/cwl_conformance.yaml
@@ -26,7 +26,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
marker: ['green', 'red and required', 'red and not required']
conformance-version: ['cwl_conformance_v1_0'] #, 'cwl_conformance_v1_1', 'cwl_conformance_v1_2']
services:
diff --git a/.github/workflows/db_indexes.yaml b/.github/workflows/db_indexes.yaml
index 1fe2c705b38..a2b1788e495 100644
--- a/.github/workflows/db_indexes.yaml
+++ b/.github/workflows/db_indexes.yaml
@@ -26,11 +26,11 @@ jobs:
matrix:
db: ['postgresql', 'sqlite']
postgresql-version: ['17']
- python-version: ['3.9']
+ python-version: ['3.10']
include:
- db: postgresql
postgresql-version: '9.6'
- python-version: '3.9'
+ python-version: '3.10'
services:
postgres:
image: postgres:${{ matrix.postgresql-version }}
diff --git a/.github/workflows/dependencies.yaml b/.github/workflows/dependencies.yaml
index e3fc0126417..1a8fe78dba5 100644
--- a/.github/workflows/dependencies.yaml
+++ b/.github/workflows/dependencies.yaml
@@ -14,7 +14,7 @@ jobs:
persist-credentials: false
- uses: actions/setup-python@v6
with:
- python-version: '3.9'
+ python-version: '3.10'
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Update dependencies
diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml
index f1b1287e6a9..28fa966e8b0 100644
--- a/.github/workflows/deployment.yaml
+++ b/.github/workflows/deployment.yaml
@@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
steps:
- uses: actions/checkout@v6
with:
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index 018f6e9082b..af666fc3163 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
steps:
- name: Get target branch name (push)
if: github.event_name == 'push'
diff --git a/.github/workflows/first_startup.yaml b/.github/workflows/first_startup.yaml
index 2fb478fa8bb..0f66fe2ae1f 100644
--- a/.github/workflows/first_startup.yaml
+++ b/.github/workflows/first_startup.yaml
@@ -25,7 +25,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9', '3.14']
+ python-version: ['3.10', '3.14']
defaults:
run:
shell: bash -l {0}
@@ -47,6 +47,7 @@ jobs:
- name: Restore client cache
uses: actions/cache@v5
with:
+ fail-on-cache-miss: true
key: galaxy-static-${{ needs.build-client.outputs.commit-id }}
path: 'galaxy root/static'
- name: Install tox
diff --git a/.github/workflows/framework_tools.yaml b/.github/workflows/framework_tools.yaml
index afc2d4e7b13..1b921215d34 100644
--- a/.github/workflows/framework_tools.yaml
+++ b/.github/workflows/framework_tools.yaml
@@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
use-legacy-api: ['if_needed', 'always']
services:
postgres:
diff --git a/.github/workflows/framework_workflows.yaml b/.github/workflows/framework_workflows.yaml
index f89793c2ed5..b8a733bd961 100644
--- a/.github/workflows/framework_workflows.yaml
+++ b/.github/workflows/framework_workflows.yaml
@@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
services:
postgres:
image: postgres:17
diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml
index a80fc12f16c..776fe4bdce9 100644
--- a/.github/workflows/integration.yaml
+++ b/.github/workflows/integration.yaml
@@ -29,7 +29,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
chunk: ['0', '1', '2', '3']
steps:
- if: github.event_name == 'schedule'
diff --git a/.github/workflows/integration_selenium.yaml b/.github/workflows/integration_selenium.yaml
index 468a1792ae5..17159e91ec3 100644
--- a/.github/workflows/integration_selenium.yaml
+++ b/.github/workflows/integration_selenium.yaml
@@ -33,7 +33,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
services:
postgres:
image: postgres:17
@@ -71,6 +71,7 @@ jobs:
- name: Restore client cache
uses: actions/cache@v5
with:
+ fail-on-cache-miss: true
key: galaxy-static-${{ needs.build-client.outputs.commit-id }}
path: 'galaxy root/static'
- name: Run tests
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index e0b32647bed..9d13c3a3016 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -22,7 +22,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9', '3.14']
+ python-version: ['3.10', '3.14']
env:
LINT_PATH: 'lib/galaxy/dependencies/pinned-lint-requirements.txt'
TYPE_PATH: 'lib/galaxy/dependencies/pinned-typecheck-requirements.txt'
diff --git a/.github/workflows/lint_openapi_schema.yml b/.github/workflows/lint_openapi_schema.yml
index 34db45a6424..d211bc42a24 100644
--- a/.github/workflows/lint_openapi_schema.yml
+++ b/.github/workflows/lint_openapi_schema.yml
@@ -22,7 +22,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9', '3.14']
+ python-version: ['3.10', '3.14']
steps:
- uses: actions/checkout@v6
with:
diff --git a/.github/workflows/main_tools.yaml b/.github/workflows/main_tools.yaml
index ce04df8e37a..dd0973843bf 100644
--- a/.github/workflows/main_tools.yaml
+++ b/.github/workflows/main_tools.yaml
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
services:
postgres:
image: postgres:17
diff --git a/.github/workflows/mulled.yaml b/.github/workflows/mulled.yaml
index 0f89d157780..625c23fb519 100644
--- a/.github/workflows/mulled.yaml
+++ b/.github/workflows/mulled.yaml
@@ -22,7 +22,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
steps:
- uses: actions/checkout@v6
with:
diff --git a/.github/workflows/osx_startup.yaml b/.github/workflows/osx_startup.yaml
index 259f91e972d..2e94dfbb65f 100644
--- a/.github/workflows/osx_startup.yaml
+++ b/.github/workflows/osx_startup.yaml
@@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9', '3.14']
+ python-version: ['3.10', '3.14']
defaults:
run:
shell: bash -l {0}
@@ -40,6 +40,7 @@ jobs:
- name: Restore client cache
uses: actions/cache@v5
with:
+ fail-on-cache-miss: true
key: galaxy-static-${{ needs.build-client.outputs.commit-id }}
path: 'galaxy root/static'
- name: Install uv
diff --git a/.github/workflows/performance.yaml b/.github/workflows/performance.yaml
index f025b4d8e19..d97f6399053 100644
--- a/.github/workflows/performance.yaml
+++ b/.github/workflows/performance.yaml
@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
services:
postgres:
image: postgres:17
diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml
index 2d1f246b131..b4f0405d871 100644
--- a/.github/workflows/playwright.yaml
+++ b/.github/workflows/playwright.yaml
@@ -33,7 +33,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
chunk: [0, 1, 2]
services:
postgres:
@@ -78,6 +78,7 @@ jobs:
- name: Restore client cache
uses: actions/cache@v5
with:
+ fail-on-cache-miss: true
key: galaxy-static-${{ needs.build-client.outputs.commit-id }}
path: 'galaxy root/static'
- name: Run tests
diff --git a/.github/workflows/publish_artifacts.yaml b/.github/workflows/publish_artifacts.yaml
index 582cc6f6a61..027042e043f 100644
--- a/.github/workflows/publish_artifacts.yaml
+++ b/.github/workflows/publish_artifacts.yaml
@@ -41,7 +41,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
steps:
- uses: actions/checkout@v6
with:
diff --git a/.github/workflows/selenium.yaml b/.github/workflows/selenium.yaml
index 7820aad9110..0d9bbed4beb 100644
--- a/.github/workflows/selenium.yaml
+++ b/.github/workflows/selenium.yaml
@@ -34,7 +34,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
chunk: [0, 1, 2]
services:
postgres:
@@ -71,6 +71,7 @@ jobs:
- name: Restore client cache
uses: actions/cache@v5
with:
+ fail-on-cache-miss: true
key: galaxy-static-${{ needs.build-client.outputs.commit-id }}
path: 'galaxy root/static'
- name: Run tests
diff --git a/.github/workflows/test_galaxy_packages.yaml b/.github/workflows/test_galaxy_packages.yaml
index fc82284bfe9..1b57dd07d11 100644
--- a/.github/workflows/test_galaxy_packages.yaml
+++ b/.github/workflows/test_galaxy_packages.yaml
@@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9', '3.14']
+ python-version: ['3.10', '3.14']
steps:
- uses: actions/checkout@v6
with:
diff --git a/.github/workflows/toolshed.yaml b/.github/workflows/toolshed.yaml
index 11af6203643..e9355b9b51c 100644
--- a/.github/workflows/toolshed.yaml
+++ b/.github/workflows/toolshed.yaml
@@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9', '3.14']
+ python-version: ['3.10', '3.14']
shed-api: ['v1', 'v2']
test-install-client: ['galaxy_api', 'standalone']
services:
diff --git a/.github/workflows/unit-postgres.yaml b/.github/workflows/unit-postgres.yaml
index bb324e61f32..6815d2d8a35 100644
--- a/.github/workflows/unit-postgres.yaml
+++ b/.github/workflows/unit-postgres.yaml
@@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9']
+ python-version: ['3.10']
services:
postgres:
image: postgres:17
diff --git a/.github/workflows/unit.yaml b/.github/workflows/unit.yaml
index 6bb9ff3ab95..825aaf74221 100644
--- a/.github/workflows/unit.yaml
+++ b/.github/workflows/unit.yaml
@@ -22,7 +22,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ['3.9', '3.14']
+ python-version: ['3.10', '3.14']
steps:
- uses: actions/checkout@v6
with:
diff --git a/Makefile b/Makefile
index e1616f388c5..4e5db97eff2 100644
--- a/Makefile
+++ b/Makefile
@@ -62,8 +62,8 @@ format: ## Format Python code base
remove-unused-imports: ## Remove unused imports in Python code base
$(IN_VENV) autoflake --in-place --remove-all-unused-imports --recursive --verbose lib/ test/
-pyupgrade: ## Convert older code patterns to Python 3.8/3.9 idiomatic ones
- ack --type=python -f | grep -v '^$(subst $(SPACE),\|^,$(NEVER_PYUPGRADE_PATHS) $(PY38_PYUPGRADE_PATHS))' | xargs pyupgrade --py39-plus
+pyupgrade: ## Convert older code patterns to Python 3.8/3.10 idiomatic ones
+ ack --type=python -f | grep -v '^$(subst $(SPACE),\|^,$(NEVER_PYUPGRADE_PATHS) $(PY38_PYUPGRADE_PATHS))' | xargs pyupgrade --py310-plus
ack --type=python -f | grep -v '^$(subst $(SPACE),\|^,$(NEVER_PYUPGRADE_PATHS) $(PY38_PYUPGRADE_PATHS))' | xargs auto-walrus
ack --type=python -f $(PY38_PYUPGRADE_PATHS) | xargs pyupgrade --py38-plus
diff --git a/README.rst b/README.rst
index a2ae0f9125d..fa9f3e7c969 100644
--- a/README.rst
+++ b/README.rst
@@ -24,12 +24,12 @@ Community support is available at `Galaxy Help
Galaxy Quickstart
=================
-Galaxy requires Python 3.9 or higher. To check your Python version, run:
+Galaxy requires Python 3.10 or higher. To check your Python version, run:
.. code:: console
$ python -V
- Python 3.9.21
+ Python 3.10.12
Start Galaxy:
diff --git a/client/src/components/Form/Elements/FormDirectory.test.js b/client/src/components/Form/Elements/FormDirectory.test.js
index cbff6c9ffe3..3aba1fb14d3 100644
--- a/client/src/components/Form/Elements/FormDirectory.test.js
+++ b/client/src/components/Form/Elements/FormDirectory.test.js
@@ -23,7 +23,7 @@ async function init(wrapper, data) {
expect(filesDialogComponent.exists()).toBe(true);
filesDialogComponent.vm.callback({ url: data.url });
// HACK: URL implementation in test environment is not the same as global node
- wrapper.vm.pathChunks = data.pathChunks;
+ wrapper.vm.pathChunks = [...data.pathChunks];
await flushPromises();
await validateLatestEmittedPath(wrapper, data.url);
}
@@ -175,4 +175,20 @@ describe("DirectoryPathEditableBreadcrumb", () => {
// retain special characters in the url
await init(wrapper, testingDataWithSpecialChars);
});
+
+ it("should save on blur", async () => {
+ await init(wrapper, testingData);
+ // enter a new path chunk
+ const input = wrapper.find("#path-input-breadcrumb");
+ await input.setValue(validPath);
+ expect(input.element.value).toBe(validPath);
+
+ await input.trigger("blur");
+ await flushPromises();
+
+ expect(spyOnAddPath).toHaveBeenCalled();
+ expect(input.element.value).toBe("");
+ expect(wrapper.findAll("li.breadcrumb-item").length).toBe(testingData.expectedNumberOfPaths + 1);
+ await validateLatestEmittedPath(wrapper, `${testingData.url}/${validPath}`);
+ });
});
diff --git a/client/src/components/Form/Elements/FormDirectory.vue b/client/src/components/Form/Elements/FormDirectory.vue
index 4040d5d5241..a57ab446ddc 100644
--- a/client/src/components/Form/Elements/FormDirectory.vue
+++ b/client/src/components/Form/Elements/FormDirectory.vue
@@ -35,7 +35,8 @@
trim
@keyup.enter="addPath"
@keydown.191.capture.prevent.stop="addPath"
- @keydown.8.capture="removeLastPath" />
+ @keydown.8.capture="removeLastPath"
+ @blur="handleBlur" />
@@ -139,12 +140,23 @@ export default {
},
addPath({ key }) {
if ((key === "Enter" || key === "/") && this.isValidName) {
- const newFolder = this.currentDirectoryName;
- this.pathChunks.push({ pathChunk: newFolder, editable: true });
- this.currentDirectoryName = "";
+ this.addDirectoryToPath();
+ }
+ },
+ handleBlur() {
+ if (this.currentDirectoryName && this.isValidName) {
+ this.addDirectoryToPath();
+ } else {
+ // If the input was touched let's propagate the change either way.
this.updateURL();
}
},
+ addDirectoryToPath() {
+ const newFolder = this.currentDirectoryName;
+ this.pathChunks.push({ pathChunk: newFolder, editable: true });
+ this.currentDirectoryName = "";
+ this.updateURL();
+ },
updateURL(isReset = false) {
let url = undefined;
if (!isReset) {
diff --git a/doc/source/admin/galaxy_options.rst b/doc/source/admin/galaxy_options.rst
index 60b91c44a99..8f922c5526c 100644
--- a/doc/source/admin/galaxy_options.rst
+++ b/doc/source/admin/galaxy_options.rst
@@ -3816,9 +3816,9 @@
:Type: bool
-~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~
``prefer_oidc_login``
-~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~
:Description:
Controls the order of the login page to prefer OIDC-based login
@@ -3834,7 +3834,7 @@
:Description:
Allow unregistered users to create new local (non-OIDC) accounts
(otherwise, they will have to be created by an admin). This option
- will be overridden to false in case disable_local_accounts is set
+ will be overridden to false in case disable_local_accounts is set
to true.
:Default: ``true``
:Type: bool
@@ -3846,7 +3846,7 @@
:Description:
Disable local accounts. If this option is set to true, at least
- one OIDC provider needs to be configured and will serve as the
+ one OIDC provider needs to be configured and will serve as the
account provider. If this option is set to true,
allow_local_account creation will be overridden with false.
:Default: ``false``
diff --git a/doc/source/admin/python.md b/doc/source/admin/python.md
index 6cdcf6ed491..98ce8f12a85 100644
--- a/doc/source/admin/python.md
+++ b/doc/source/admin/python.md
@@ -1,6 +1,6 @@
# Supported Python versions
-Galaxy's core functionality is currently supported on Python **>=3.9** .
+Galaxy's core functionality is currently supported on Python **>=3.10** .
If Galaxy complains about the version of Python you are using:
diff --git a/lib/galaxy/agents/base.py b/lib/galaxy/agents/base.py
index 6c213396847..5bbb7048380 100644
--- a/lib/galaxy/agents/base.py
+++ b/lib/galaxy/agents/base.py
@@ -8,10 +8,10 @@ from abc import (
ABC,
abstractmethod,
)
+from collections.abc import Callable
from dataclasses import dataclass
from typing import (
Any,
- Callable,
Optional,
TYPE_CHECKING,
Union,
diff --git a/lib/galaxy/app.py b/lib/galaxy/app.py
index e1552cae0c3..3a48b2ee207 100644
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -6,9 +6,9 @@ import signal
import sys
import threading
import time
+from collections.abc import Callable
from typing import (
Any,
- Callable,
Optional,
)
diff --git a/lib/galaxy/authnz/psa_authnz.py b/lib/galaxy/authnz/psa_authnz.py
index 07f90377b2d..5037ba86c2a 100644
--- a/lib/galaxy/authnz/psa_authnz.py
+++ b/lib/galaxy/authnz/psa_authnz.py
@@ -1,6 +1,5 @@
import json
import logging
-import sys
import time
from typing import TYPE_CHECKING
from urllib.parse import quote
@@ -47,14 +46,7 @@ from ..config import GalaxyAppConfiguration
if TYPE_CHECKING:
from social_core.backends.oauth import BaseOAuth2
-
- if sys.version_info >= (3, 10):
- from social_core.strategy import HttpResponseProtocol
- else:
- from typing import Protocol
-
- class HttpResponseProtocol(Protocol):
- url: str
+ from social_core.strategy import HttpResponseProtocol
log = logging.getLogger(__name__)
diff --git a/lib/galaxy/celery/__init__.py b/lib/galaxy/celery/__init__.py
index 8b04929e5eb..a15939cbd8a 100644
--- a/lib/galaxy/celery/__init__.py
+++ b/lib/galaxy/celery/__init__.py
@@ -1,5 +1,6 @@
import os
import uuid
+from collections.abc import Callable
from functools import (
lru_cache,
wraps,
@@ -8,7 +9,6 @@ from multiprocessing import get_context
from threading import local
from typing import (
Any,
- Callable,
)
import pebble
diff --git a/lib/galaxy/celery/tasks.py b/lib/galaxy/celery/tasks.py
index 88c30bcef8f..8f7ffe87f15 100644
--- a/lib/galaxy/celery/tasks.py
+++ b/lib/galaxy/celery/tasks.py
@@ -1,12 +1,12 @@
import datetime
import json
import shutil
+from collections.abc import Callable
from concurrent.futures import TimeoutError
from functools import lru_cache
from pathlib import Path
from typing import (
Any,
- Callable,
Optional,
)
diff --git a/lib/galaxy/config/__init__.py b/lib/galaxy/config/__init__.py
index 2a0d20835df..4b1d46c6df0 100644
--- a/lib/galaxy/config/__init__.py
+++ b/lib/galaxy/config/__init__.py
@@ -16,10 +16,10 @@ import string
import sys
import tempfile
import threading
+from collections.abc import Callable
from datetime import timedelta
from typing import (
Any,
- Callable,
cast,
Optional,
SupportsInt,
diff --git a/lib/galaxy/config/config_manage.py b/lib/galaxy/config/config_manage.py
index 144cb38a199..e9f93f91be0 100644
--- a/lib/galaxy/config/config_manage.py
+++ b/lib/galaxy/config/config_manage.py
@@ -6,11 +6,11 @@ from argparse import (
ArgumentParser,
Namespace,
)
+from collections.abc import Callable
from io import StringIO
from textwrap import TextWrapper
from typing import (
Any,
- Callable,
NamedTuple,
Optional,
)
@@ -19,7 +19,7 @@ import yaml
from boltons.iterutils import remap
try:
- from gravity.util import settings_to_sample
+ from gravity.settings import settings_to_sample
except ImportError:
settings_to_sample = None
diff --git a/lib/galaxy/config/sample/galaxy.yml.sample b/lib/galaxy/config/sample/galaxy.yml.sample
index 30a3eb9763b..df7c57d9a77 100644
--- a/lib/galaxy/config/sample/galaxy.yml.sample
+++ b/lib/galaxy/config/sample/galaxy.yml.sample
@@ -47,6 +47,11 @@ gravity:
# is ``supervisor``.
# memory_limit:
+ # Memory usage throttle limit (in GB), processes exceeding the limit are throttled and put under heavy reclaim pressure.
+ # If set, this is the default value for all services. Setting ``memory_high`` on an individual service overrides this
+ # value. Ignored if ``process_manager`` is ``supervisor``.
+ # memory_high:
+
# Specify Galaxy config file (galaxy.yml), if the Gravity config is separate from the Galaxy config. Assumed to be the
# same file as the Gravity config if a ``galaxy`` key exists at the root level, otherwise, this option is required.
# galaxy_config_file:
@@ -67,6 +72,11 @@ gravity:
# If not specified defaults to ``/gravity/log``.
# log_dir:
+ # Run Galaxy processes in the specified journal namespace (sets the value of ``LogNamespace=`` in the systemd service
+ # units). This allows you to keep Galaxy log messages separate in the system journal from other log messages. Ignored if
+ # ``process_manager`` is not ``systemd``. See ``systemd.exec(5)`` for details.
+ # log_namespace:
+
# Set to Galaxy's virtualenv directory.
# If not specified, Gravity assumes all processes are on PATH. This option is required in most circumstances when using
# the ``systemd`` process manager.
@@ -74,9 +84,7 @@ gravity:
# Select the application server.
# ``gunicorn`` is the default application server.
- # ``unicornherder`` is a production-oriented manager for (G)unicorn servers that automates zero-downtime Galaxy server restarts,
- # similar to uWSGI Zerg Mode used in the past.
- # Valid options are: gunicorn, unicornherder
+ # Valid options are: gunicorn
# app_server: gunicorn
# Override the default instance name.
@@ -107,8 +115,8 @@ gravity:
# extra_args:
# Use Gunicorn's --preload option to fork workers after loading the Galaxy Application.
- # Consumes less memory when multiple processes are configured. Default is ``false`` if using unicornherder, else ``true``.
- # preload:
+ # Consumes less memory when multiple processes are configured.
+ # preload: true
# umask under which service should be executed
# umask:
@@ -127,6 +135,11 @@ gravity:
# ``supervisor``.
# memory_limit:
+ # Memory usage throttle limit (in GB). If the service exceeds the limit, processes are throttled and put under heavy
+ # reclaim pressure. Default is no limit or the value of the ``memory_high`` setting at the top level of the Gravity
+ # configuration, if set. Ignored if ``process_manager`` is ``supervisor``.
+ # memory_high:
+
# Extra environment variables and their values to set when running the service. A dictionary where keys are the variable
# names.
# environment: {}
@@ -171,6 +184,11 @@ gravity:
# ``supervisor``.
# memory_limit:
+ # Memory usage throttle limit (in GB). If the service exceeds the limit, processes are throttled and put under heavy
+ # reclaim pressure. Default is no limit or the value of the ``memory_high`` setting at the top level of the Gravity
+ # configuration, if set. Ignored if ``process_manager`` is ``supervisor``.
+ # memory_high:
+
# Extra environment variables and their values to set when running the service. A dictionary where keys are the variable
# names.
# environment: {}
@@ -224,6 +242,11 @@ gravity:
# ``supervisor``.
# memory_limit:
+ # Memory usage throttle limit (in GB). If the service exceeds the limit, processes are throttled and put under heavy
+ # reclaim pressure. Default is no limit or the value of the ``memory_high`` setting at the top level of the Gravity
+ # configuration, if set. Ignored if ``process_manager`` is ``supervisor``.
+ # memory_high:
+
# Extra environment variables and their values to set when running the service. A dictionary where keys are the variable
# names.
# environment: {}
@@ -286,6 +309,11 @@ gravity:
# ``supervisor``.
# memory_limit:
+ # Memory usage throttle limit (in GB). If the service exceeds the limit, processes are throttled and put under heavy
+ # reclaim pressure. Default is no limit or the value of the ``memory_high`` setting at the top level of the Gravity
+ # configuration, if set. Ignored if ``process_manager`` is ``supervisor``.
+ # memory_high:
+
# Extra environment variables and their values to set when running the service. A dictionary where keys are the variable
# names.
# environment: {}
@@ -338,6 +366,11 @@ gravity:
# ``supervisor``.
# memory_limit:
+ # Memory usage throttle limit (in GB). If the service exceeds the limit, processes are throttled and put under heavy
+ # reclaim pressure. Default is no limit or the value of the ``memory_high`` setting at the top level of the Gravity
+ # configuration, if set. Ignored if ``process_manager`` is ``supervisor``.
+ # memory_high:
+
# Extra environment variables and their values to set when running the service. A dictionary where keys are the variable
# names.
# environment: {}
@@ -2111,19 +2144,19 @@ galaxy:
# page (even if require_login is true).
#show_welcome_with_login: false
- # Controls the order of the login page to prefer OIDC-based login
- # and registration.
+ # Controls the order of the login page to prefer OIDC-based login and
+ # registration.
#prefer_oidc_login: false
# Allow unregistered users to create new local (non-OIDC) accounts
# (otherwise, they will have to be created by an admin). This option
- # will be overridden to false in case disable_local_accounts is set
- # to true.
+ # will be overridden to false in case disable_local_accounts is set to
+ # true.
#allow_local_account_creation: true
# Disable local accounts. If this option is set to true, at least one
- # OIDC provider needs to be configured and will serve as the account
- # provider. If this option is set to true, allow_local_account
+ # OIDC provider needs to be configured and will serve as the account
+ # provider. If this option is set to true, allow_local_account
# creation will be overridden with false.
#disable_local_accounts: false
diff --git a/lib/galaxy/config/sample/tool_shed.yml.sample b/lib/galaxy/config/sample/tool_shed.yml.sample
index f7e2ac55872..9a4b9a26aab 100644
--- a/lib/galaxy/config/sample/tool_shed.yml.sample
+++ b/lib/galaxy/config/sample/tool_shed.yml.sample
@@ -23,6 +23,12 @@ tool_shed:
# without authentication.
#config_hg_for_dev: null
+ # The base URL of the Tool Shed server used for generating clone URLs
+ # and repository hostnames. If set, this value will be used instead of
+ # deriving the URL from the incoming request.
+ # Example: https://toolshed.g2.bx.psu.edu
+ #tool_shed_url: null
+
# Where Tool Shed repositories are stored.
#file_path: database/community_files
diff --git a/lib/galaxy/datatypes/blast.py b/lib/galaxy/datatypes/blast.py
index 1d8a879dd3a..fbcf447f559 100644
--- a/lib/galaxy/datatypes/blast.py
+++ b/lib/galaxy/datatypes/blast.py
@@ -32,9 +32,9 @@ Covers the ``blastxml`` format and the BLAST databases.
"""
import logging
import os
+from collections.abc import Callable
from time import sleep
from typing import (
- Callable,
Optional,
)
diff --git a/lib/galaxy/datatypes/data.py b/lib/galaxy/datatypes/data.py
index ce16a8e7422..c88607e4f45 100644
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -6,21 +6,21 @@ import shutil
import string
import tempfile
from collections.abc import (
+ Callable,
Generator,
Iterable,
)
from inspect import isclass
from typing import (
Any,
- Callable,
IO,
+ Literal,
Optional,
TYPE_CHECKING,
Union,
)
from markupsafe import escape
-from typing_extensions import Literal
from galaxy import util
from galaxy.datatypes.metadata import (
diff --git a/lib/galaxy/datatypes/display_applications/parameters.py b/lib/galaxy/datatypes/display_applications/parameters.py
index f34b4065085..c5f2a4f74ee 100644
--- a/lib/galaxy/datatypes/display_applications/parameters.py
+++ b/lib/galaxy/datatypes/display_applications/parameters.py
@@ -1,8 +1,8 @@
# Contains parameters that are used in Display Applications
import mimetypes
+from collections.abc import Callable
from dataclasses import dataclass
from typing import (
- Callable,
Optional,
TYPE_CHECKING,
Union,
diff --git a/lib/galaxy/datatypes/images.py b/lib/galaxy/datatypes/images.py
index acabffea568..cb9567ea85f 100644
--- a/lib/galaxy/datatypes/images.py
+++ b/lib/galaxy/datatypes/images.py
@@ -11,6 +11,7 @@ import struct
from collections.abc import Iterator
from typing import (
Any,
+ Literal,
Optional,
Union,
)
@@ -20,7 +21,6 @@ import numpy as np
import png
import pydicom
import tifffile
-from typing_extensions import Literal
try:
import PIL
diff --git a/lib/galaxy/datatypes/molecules.py b/lib/galaxy/datatypes/molecules.py
index 610d4421e25..d0246294d69 100644
--- a/lib/galaxy/datatypes/molecules.py
+++ b/lib/galaxy/datatypes/molecules.py
@@ -1,8 +1,8 @@
import logging
import os
import re
+from collections.abc import Callable
from typing import (
- Callable,
Optional,
)
diff --git a/lib/galaxy/datatypes/msa.py b/lib/galaxy/datatypes/msa.py
index 18c0f2655b6..43d09e47c4f 100644
--- a/lib/galaxy/datatypes/msa.py
+++ b/lib/galaxy/datatypes/msa.py
@@ -2,8 +2,8 @@ import abc
import logging
import os
import re
+from collections.abc import Callable
from typing import (
- Callable,
Optional,
)
diff --git a/lib/galaxy/datatypes/sequence.py b/lib/galaxy/datatypes/sequence.py
index 339f22b1665..8fccd58e066 100644
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -9,11 +9,13 @@ import os
import re
import string
import subprocess
-from collections.abc import Iterable
+from collections.abc import (
+ Callable,
+ Iterable,
+)
from itertools import islice
from typing import (
Any,
- Callable,
Optional,
)
diff --git a/lib/galaxy/datatypes/sniff.py b/lib/galaxy/datatypes/sniff.py
index fa990a0b00b..0b1b4cb5d23 100644
--- a/lib/galaxy/datatypes/sniff.py
+++ b/lib/galaxy/datatypes/sniff.py
@@ -12,10 +12,12 @@ import shutil
import struct
import tempfile
import zipfile
-from collections.abc import Iterable
+from collections.abc import (
+ Callable,
+ Iterable,
+)
from functools import partial
from typing import (
- Callable,
IO,
NamedTuple,
Optional,
diff --git a/lib/galaxy/datatypes/spaln.py b/lib/galaxy/datatypes/spaln.py
index e5d6aeea703..a2c477048b1 100644
--- a/lib/galaxy/datatypes/spaln.py
+++ b/lib/galaxy/datatypes/spaln.py
@@ -4,8 +4,8 @@ spaln Composite Dataset
import logging
import os.path
+from collections.abc import Callable
from typing import (
- Callable,
Optional,
)
diff --git a/lib/galaxy/dependencies/dev-requirements.txt b/lib/galaxy/dependencies/dev-requirements.txt
index a5fcd8d28a9..49b1aaf9c13 100644
--- a/lib/galaxy/dependencies/dev-requirements.txt
+++ b/lib/galaxy/dependencies/dev-requirements.txt
@@ -3,44 +3,35 @@
aiohappyeyeballs==2.6.1
aiohttp==3.13.3
aiosignal==1.4.0
-alabaster==0.7.16 ; python_full_version < '3.10'
-alabaster==1.0.0 ; python_full_version >= '3.10'
+alabaster==1.0.0
anyio==4.12.1
-ase==3.26.0 ; python_full_version < '3.10'
-ase==3.27.0 ; python_full_version >= '3.10'
+ase==3.27.0
+async-generator==1.10
async-timeout==5.0.1 ; python_full_version < '3.11'
attrs==25.4.0
axe-selenium-python==2.1.6
babel==2.17.0
backports-asyncio-runner==1.2.0 ; python_full_version < '3.11'
backports-tarfile==1.2.0 ; python_full_version < '3.12' and platform_machine != 'ppc64le' and platform_machine != 's390x'
-black==25.11.0 ; python_full_version < '3.10'
-black==25.12.0 ; python_full_version >= '3.10'
-boto3==1.41.5 ; python_full_version < '3.10'
-boto3==1.42.19 ; python_full_version >= '3.10'
-botocore==1.41.5 ; python_full_version < '3.10'
-botocore==1.42.19 ; python_full_version >= '3.10'
+black==25.12.0
+boto3==1.42.19
+botocore==1.42.19
build==1.4.0
-cachecontrol==0.14.3 ; python_full_version < '3.10'
-cachecontrol==0.14.4 ; python_full_version >= '3.10'
+cachecontrol==0.14.4
cachetools==6.2.4
cattrs==25.3.0
certifi==2026.1.4
cffi==2.0.0 ; (implementation_name != 'pypy' and os_name == 'nt') or platform_python_implementation != 'PyPy'
charset-normalizer==3.4.4
-click==8.1.8 ; python_full_version < '3.10'
-click==8.3.1 ; python_full_version >= '3.10'
+click==8.3.1
codespell==2.4.1
colorama==0.4.6 ; os_name == 'nt' or sys_platform == 'win32'
colorlog==6.10.1
-contourpy==1.3.0 ; python_full_version < '3.10'
-contourpy==1.3.2 ; python_full_version == '3.10.*'
+contourpy==1.3.2 ; python_full_version < '3.11'
contourpy==1.3.3 ; python_full_version >= '3.11'
-coverage==7.10.7 ; python_full_version < '3.10'
-coverage==7.13.1 ; python_full_version >= '3.10'
+coverage==7.13.1
cryptography==46.0.3
-cwltest==2.6.20250818005349 ; python_full_version < '3.10'
-cwltest==2.6.20251216093331 ; python_full_version >= '3.10'
+cwltest==2.6.20251216093331
cycler==0.12.1
darker==3.0.0
darkgraylib==2.4.1
@@ -48,35 +39,41 @@ decorator==5.2.1
defusedxml==0.7.1
docutils==0.21.2 ; python_full_version < '3.11'
docutils==0.22.4 ; python_full_version >= '3.11'
-dogpile-cache==1.4.1 ; python_full_version < '3.10'
-dogpile-cache==1.5.0 ; python_full_version >= '3.10'
-enum-tools==0.12.0 ; python_full_version >= '3.10'
+dogpile-cache==1.5.0
+enum-tools==0.12.0
exceptiongroup==1.3.1 ; python_full_version < '3.11'
-filelock==3.19.1 ; python_full_version < '3.10'
-filelock==3.20.3 ; python_full_version >= '3.10'
+filelock==3.20.3
fluent-logger==0.11.1
-fonttools==4.60.2 ; python_full_version < '3.10'
-fonttools==4.61.1 ; python_full_version >= '3.10'
+fonttools==4.61.1
frozenlist==1.8.0
+fsspec==2026.1.0
galaxy-release-util==0.3.1
-greenlet==3.2.4 ; python_full_version < '3.10'
-greenlet==3.3.0 ; python_full_version >= '3.10'
+gcsfs==2026.1.0
+google-api-core==2.29.0
+google-auth==2.47.0
+google-auth-oauthlib==1.2.4
+google-cloud-core==2.5.0
+google-cloud-storage==3.8.0
+google-cloud-storage-control==1.9.0
+google-crc32c==1.8.0
+google-resumable-media==2.8.0
+googleapis-common-protos==1.72.0
+greenlet==3.3.0
+grpc-google-iam-v1==0.14.3
+grpcio==1.76.0
+grpcio-status==1.76.0
h11==0.16.0
-html5lib==1.1 ; python_full_version < '3.10'
-html5rdf==1.2.1 ; python_full_version >= '3.10'
+html5rdf==1.2.1
httpcore==1.0.9
httpx==0.28.1
id==1.5.0
idna==3.11
imagesize==1.4.1
-importlib-metadata==8.7.1 ; python_full_version < '3.12'
-importlib-resources==6.5.2 ; python_full_version < '3.10'
-iniconfig==2.1.0 ; python_full_version < '3.10'
-iniconfig==2.3.0 ; python_full_version >= '3.10'
+importlib-metadata==8.7.1
+iniconfig==2.3.0
inquirerpy==0.3.4
isodate==0.7.2 ; python_full_version < '3.11'
-isort==6.1.0 ; python_full_version < '3.10'
-isort==7.0.0 ; python_full_version >= '3.10'
+isort==7.0.0
jaraco-classes==3.4.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x'
jaraco-context==6.1.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x'
jaraco-functools==4.4.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x'
@@ -85,63 +82,54 @@ jinja2==3.1.6
jmespath==1.0.1
jsonpatch==1.33
jsonpointer==3.0.0
-jsonschema==4.25.1 ; python_full_version < '3.10'
-jsonschema==4.26.0 ; python_full_version >= '3.10'
+jsonschema==4.26.0
jsonschema-specifications==2025.9.1
junit-xml==1.9
keyring==25.7.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x'
-kiwisolver==1.4.7 ; python_full_version < '3.10'
-kiwisolver==1.4.9 ; python_full_version >= '3.10'
+kiwisolver==1.4.9
librt==0.7.8 ; platform_python_implementation != 'PyPy'
lxml==6.0.2
markdown-it-py==3.0.0 ; python_full_version < '3.11'
markdown-it-py==4.0.0 ; python_full_version >= '3.11'
markdown-it-reporter==0.0.2
markupsafe==3.0.3
-matplotlib==3.9.4 ; python_full_version < '3.10'
-matplotlib==3.10.8 ; python_full_version >= '3.10'
-mdit-py-plugins==0.4.2 ; python_full_version < '3.10'
-mdit-py-plugins==0.5.0 ; python_full_version >= '3.10'
+matplotlib==3.10.8
+mdit-py-plugins==0.5.0
mdurl==0.1.2
-mirakuru==2.6.1 ; python_full_version < '3.10'
-mirakuru==3.0.1 ; python_full_version >= '3.10'
+mirakuru==3.0.1
mistune==3.1.4
more-itertools==10.8.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x'
msgpack==1.1.2
multidict==6.7.0
mypy==1.19.1
mypy-extensions==1.1.0
-myst-parser==3.0.1 ; python_full_version < '3.10'
-myst-parser==4.0.1 ; python_full_version == '3.10.*'
+myst-parser==4.0.1 ; python_full_version < '3.11'
myst-parser==5.0.0 ; python_full_version >= '3.11'
nh3==0.3.2
-numpy==2.0.2 ; python_full_version < '3.10'
-numpy==2.2.6 ; python_full_version == '3.10.*'
+numpy==2.2.6 ; python_full_version < '3.11'
numpy==2.4.1 ; python_full_version >= '3.11'
+oauthlib==3.3.1
onedatafilerestclient==21.2.5.2
outcome==1.3.0.post0
-owlrl==6.0.2 ; python_full_version < '3.10'
-owlrl==7.1.4 ; python_full_version >= '3.10'
-packaging==24.2 ; python_full_version < '3.10'
-packaging==25.0 ; python_full_version >= '3.10'
+owlrl==7.1.4
+packaging==25.0
pathspec==1.0.3
pfzy==0.3.4
-pillow==11.3.0 ; python_full_version < '3.10'
-pillow==12.1.0 ; python_full_version >= '3.10'
+pillow==12.1.0
pkce==1.0.3
-platformdirs==4.4.0 ; python_full_version < '3.10'
-platformdirs==4.5.1 ; python_full_version >= '3.10'
+platformdirs==4.5.1
playwright==1.57.0
pluggy==1.6.0
-port-for==0.7.4 ; python_full_version < '3.10'
-port-for==1.0.0 ; python_full_version >= '3.10'
-prettytable==3.16.0 ; python_full_version < '3.10'
-prettytable==3.17.0 ; python_full_version >= '3.10'
+port-for==1.0.0
+prettytable==3.17.0
prompt-toolkit==3.0.52
propcache==0.4.1
+proto-plus==1.27.0
+protobuf==6.33.4
psutil==7.2.1 ; sys_platform != 'cygwin'
-psycopg==3.2.13 ; python_full_version < '3.10'
-psycopg==3.3.2 ; python_full_version >= '3.10'
+psycopg==3.3.2
+pyasn1==0.6.2
+pyasn1-modules==0.4.2
pycparser==2.23 ; (implementation_name != 'PyPy' and implementation_name != 'pypy' and os_name == 'nt') or (implementation_name != 'PyPy' and platform_python_implementation != 'PyPy')
pyee==13.0.0
pygithub==2.8.1
@@ -150,67 +138,56 @@ pyjwt==2.10.1
pynacl==1.6.2
pyparsing==3.3.1
pyproject-hooks==1.2.0
-pyshacl==0.26.0 ; python_full_version < '3.10'
-pyshacl==0.30.1 ; python_full_version >= '3.10'
+pyshacl==0.30.1
pysocks==1.7.1
-pytest==8.4.2 ; python_full_version < '3.10'
-pytest==9.0.2 ; python_full_version >= '3.10'
-pytest-asyncio==1.2.0 ; python_full_version < '3.10'
-pytest-asyncio==1.3.0 ; python_full_version >= '3.10'
+pytest==9.0.2
+pytest-asyncio==1.3.0
pytest-base-url==2.1.0
pytest-cov==7.0.0
-pytest-html==4.1.1
+pytest-html==4.2.0
pytest-httpserver==1.1.3
pytest-json-report==1.5.0
pytest-metadata==3.1.1
pytest-mock==3.15.1
-pytest-playwright==0.7.1 ; python_full_version < '3.10'
-pytest-playwright==0.7.2 ; python_full_version >= '3.10'
+pytest-playwright==0.7.2
pytest-postgresql==7.0.2
pytest-shard==0.1.2
python-dateutil==2.9.0.post0
python-irodsclient==3.2.0
python-slugify==8.0.4
-pytokens==0.3.0
+pytokens==0.4.0
pywin32-ctypes==0.2.3 ; platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'win32'
pyyaml==6.0.3
-rdflib==7.4.0 ; python_full_version < '3.10'
-rdflib==7.5.0 ; python_full_version >= '3.10'
+rdflib==7.5.0
readme-renderer==44.0
referencing==0.36.2
requests==2.32.5
requests-cache==1.2.1
+requests-oauthlib==2.0.0
requests-toolbelt==1.0.0
responses==0.25.8
rfc3986==2.0.0
rich==13.9.4
rich-click==1.9.5
-roc-validator==0.4.2 ; python_full_version < '3.9.20'
-roc-validator==0.4.6 ; python_full_version >= '3.9.20' and python_full_version < '3.10'
-roc-validator==0.8.0 ; python_full_version >= '3.10'
+roc-validator==0.8.0
roman-numerals==4.1.0 ; python_full_version >= '3.11'
-rpds-py==0.27.1 ; python_full_version < '3.10'
-rpds-py==0.30.0 ; python_full_version >= '3.10'
+rpds-py==0.30.0
+rsa==4.9.1
ruamel-yaml==0.18.17
ruamel-yaml-clib==0.2.15 ; python_full_version < '3.15' and platform_python_implementation == 'CPython'
rucio-clients==39.0.0
-s3transfer==0.15.0 ; python_full_version < '3.10'
-s3transfer==0.16.0 ; python_full_version >= '3.10'
+s3transfer==0.16.0
schema-salad==8.9.20251102115403
-scipy==1.13.1 ; python_full_version < '3.10'
-scipy==1.15.3 ; python_full_version == '3.10.*'
+scipy==1.15.3 ; python_full_version < '3.11'
scipy==1.17.0 ; python_full_version >= '3.11'
-secretstorage==3.3.3 ; python_full_version < '3.10' and platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'linux'
-secretstorage==3.5.0 ; python_full_version >= '3.10' and platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'linux'
-selenium==4.32.0 ; python_full_version < '3.10'
-selenium==4.39.0 ; python_full_version >= '3.10'
+secretstorage==3.5.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'linux'
+selenium==4.40.0
seletools==1.5.0
six==1.17.0
sniffio==1.3.1
snowballstemmer==3.0.1
sortedcontainers==2.4.0
-sphinx==7.4.7 ; python_full_version < '3.10'
-sphinx==8.1.3 ; python_full_version == '3.10.*'
+sphinx==8.1.3 ; python_full_version < '3.11'
sphinx==9.0.4 ; python_full_version == '3.11.*'
sphinx==9.1.0 ; python_full_version >= '3.12'
sphinx-rtd-theme==3.1.0
@@ -222,8 +199,7 @@ sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
statsd==4.0.1
-stevedore==5.5.0 ; python_full_version < '3.10'
-stevedore==5.6.0 ; python_full_version >= '3.10'
+stevedore==5.6.0
tabulate==0.9.0
testfixtures==8.3.0 ; python_full_version < '3.11'
testfixtures==10.0.0 ; python_full_version >= '3.11'
@@ -232,28 +208,25 @@ tinydb==4.8.2
toml==0.10.2
tomli==2.4.0 ; python_full_version <= '3.11'
total-perspective-vortex==3.1.3
-trio==0.31.0 ; python_full_version < '3.10'
-trio==0.32.0 ; python_full_version >= '3.10'
+trio==0.32.0
+trio-typing==0.10.0
trio-websocket==0.12.2
tuspy==1.1.0
twill==3.3.1
twine==6.2.0
types-cachetools==6.2.0.20251022
-types-requests==2.31.0.6 ; python_full_version < '3.10'
-types-requests==2.32.4.20260107 ; python_full_version >= '3.10'
-types-urllib3==1.26.25.14 ; python_full_version < '3.10'
+types-certifi==2021.10.8.3
+types-requests==2.32.4.20260107
+types-urllib3==1.26.25.14
typing-extensions==4.15.0
-typos==1.42.0 ; python_full_version >= '3.10'
+typos==1.42.1
tzdata==2025.3 ; sys_platform == 'win32'
url-normalize==2.2.1
-urllib3==1.26.20 ; python_full_version < '3.10'
-urllib3==2.6.3 ; python_full_version >= '3.10'
+urllib3==2.6.3
watchdog==6.0.0
wcwidth==0.2.14
-webencodings==0.5.1 ; python_full_version < '3.10'
websocket-client==1.9.0
werkzeug==3.1.5
-wsproto==1.2.0 ; python_full_version < '3.10'
-wsproto==1.3.2 ; python_full_version >= '3.10'
+wsproto==1.3.2
yarl==1.22.0
-zipp==3.23.0 ; python_full_version < '3.12'
+zipp==3.23.0
diff --git a/lib/galaxy/dependencies/pinned-requirements.txt b/lib/galaxy/dependencies/pinned-requirements.txt
index 3a40934f059..97350202d1b 100644
--- a/lib/galaxy/dependencies/pinned-requirements.txt
+++ b/lib/galaxy/dependencies/pinned-requirements.txt
@@ -3,84 +3,73 @@
a2wsgi==1.10.10
adal==1.2.7
ag-ui-protocol==0.1.10
-aiobotocore==2.26.0 ; python_full_version < '3.10'
-aiobotocore==3.1.0 ; python_full_version >= '3.10'
+aiobotocore==3.1.0
aiofiles==25.1.0
aiohappyeyeballs==2.6.1
aiohttp==3.13.3
aioitertools==0.13.0
aiosignal==1.4.0
-alembic==1.16.5 ; python_full_version < '3.10'
-alembic==1.18.1 ; python_full_version >= '3.10'
+alembic==1.18.1
amqp==5.3.1
annotated-doc==0.0.4
annotated-types==0.7.0
anthropic==0.76.0
anyio==4.12.1
-apispec==6.8.4 ; python_full_version < '3.10'
-apispec==6.9.0 ; python_full_version >= '3.10'
+apispec==6.9.0
appdirs==1.4.4
arcp==0.2.1
argcomplete==3.6.3
async-timeout==5.0.1 ; python_full_version < '3.11.3'
attmap==0.13.2
attrs==25.4.0
-authlib==1.6.6 ; python_full_version >= '3.10'
+authlib==1.6.6
babel==2.17.0
-backports-tarfile==1.2.0 ; python_full_version >= '3.10' and python_full_version < '3.12'
+backports-tarfile==1.2.0 ; python_full_version < '3.12'
bagit==1.9.0
bagit-profile==1.3.1
bcrypt==5.0.0
bdbag==1.8.0
beaker==1.13.0
-beartype==0.22.9 ; python_full_version >= '3.10'
+beartype==0.22.9
billiard==4.2.4
bioblend==1.7.0
-bleach==6.2.0 ; python_full_version < '3.10'
-bleach==6.3.0 ; python_full_version >= '3.10'
+bleach==6.3.0
boltons==25.0.0
boto==2.49.0
-boto3==1.41.5 ; python_full_version < '3.10'
-boto3==1.42.19 ; python_full_version >= '3.10'
-botocore==1.41.5 ; python_full_version < '3.10'
-botocore==1.42.19 ; python_full_version >= '3.10'
+boto3==1.42.19
+botocore==1.42.19
bx-python==0.14.0
-cachecontrol==0.14.3 ; python_full_version < '3.10'
-cachecontrol==0.14.4 ; python_full_version >= '3.10'
-cachetools==6.2.4 ; python_full_version >= '3.10'
+cachecontrol==0.14.4
+cachetools==6.2.4
celery==5.6.2
certifi==2026.1.4
cffi==2.0.0 ; implementation_name == 'pypy' or platform_python_implementation != 'PyPy'
charset-normalizer==3.4.4
circus==0.19.0
-click==8.1.8 ; python_full_version < '3.10'
-click==8.3.1 ; python_full_version >= '3.10'
+click==8.3.1
click-didyoumean==0.3.1
click-plugins==1.1.1.2
click-repl==0.3.0
cloudauthz==0.6.0
cloudbridge==3.2.0
-cloudpickle==3.1.2 ; python_full_version >= '3.10'
+cloudpickle==3.1.2
cohere==5.20.1 ; sys_platform != 'emscripten'
colorama==0.4.6
coloredlogs==15.0.1
conda-package-streaming==0.12.0
cryptography==46.0.3
ct3==3.4.0.post5
-cwl-upgrader==1.2.12 ; python_full_version < '3.10'
-cwl-upgrader==1.2.14 ; python_full_version >= '3.10'
+cwl-upgrader==1.2.14
cwl-utils==0.40
-cwltool==3.1.20251031082601 ; python_full_version < '3.10'
-cwltool==3.1.20260108082145 ; python_full_version >= '3.10'
-cyclopts==4.5.0 ; python_full_version >= '3.10'
+cwltool==3.1.20260108082145
+cyclopts==4.5.0
defusedxml==0.7.1
deprecated==1.3.1
deprecation==2.1.0
dictobj==0.4
-diskcache==5.6.3 ; python_full_version >= '3.10'
+diskcache==5.6.3
distro==1.9.0
-dnspython==2.7.0 ; python_full_version < '3.10'
-dnspython==2.8.0 ; python_full_version >= '3.10'
+dnspython==2.8.0
docopt==0.6.2
docstring-parser==0.17.0
docutils==0.21.2 ; python_full_version < '3.11'
@@ -91,45 +80,38 @@ email-validator==2.3.0
et-xmlfile==2.0.0
eval-type-backport==0.3.1
exceptiongroup==1.3.1
-executing==2.2.1 ; python_full_version >= '3.10'
-fakeredis==2.33.0 ; python_full_version >= '3.10'
+executing==2.2.1
+fakeredis==2.33.0
fastapi==0.128.0
fastavro==1.12.1 ; sys_platform != 'emscripten'
-fastmcp==2.14.3 ; python_full_version >= '3.10'
-filelock==3.19.1 ; python_full_version < '3.10'
-filelock==3.20.3 ; python_full_version >= '3.10'
+fastmcp==2.14.3
+filelock==3.20.3
fissix==24.4.24
frozenlist==1.8.0
fs==2.4.16
-fsspec==2025.10.0 ; python_full_version < '3.10'
-fsspec==2026.1.0 ; python_full_version >= '3.10'
+fsspec==2026.1.0
future==1.0.0
genai-prices==0.0.51
google-api-core==2.29.0
google-auth==2.47.0
google-cloud-batch==0.20.0
-google-genai==1.47.0 ; python_full_version < '3.10'
-google-genai==1.59.0 ; python_full_version >= '3.10'
+google-genai==1.59.0
googleapis-common-protos==1.72.0
-gravity @ git+https://github.com/nsoranzo/gravity.git@7c5f457424658ee904694f5566e61b562bce7ed6
-greenlet==3.2.4 ; (python_full_version < '3.10' and platform_machine == 'AMD64') or (python_full_version < '3.10' and platform_machine == 'WIN32') or (python_full_version < '3.10' and platform_machine == 'aarch64') or (python_full_version < '3.10' and platform_machine == 'amd64') or (python_full_version < '3.10' and platform_machine == 'ppc64le') or (python_full_version < '3.10' and platform_machine == 'win32') or (python_full_version < '3.10' and platform_machine == 'x86_64')
-greenlet==3.3.0 ; (python_full_version >= '3.10' and platform_machine == 'AMD64') or (python_full_version >= '3.10' and platform_machine == 'WIN32') or (python_full_version >= '3.10' and platform_machine == 'aarch64') or (python_full_version >= '3.10' and platform_machine == 'amd64') or (python_full_version >= '3.10' and platform_machine == 'ppc64le') or (python_full_version >= '3.10' and platform_machine == 'win32') or (python_full_version >= '3.10' and platform_machine == 'x86_64')
-griffe==1.14.0 ; python_full_version < '3.10'
-griffe==1.15.0 ; python_full_version >= '3.10'
+gravity==1.2.0
+greenlet==3.3.0 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'
+griffe==1.15.0
groq==1.0.0
grpcio==1.76.0
-grpcio-status==1.71.2 ; python_full_version < '3.10'
-grpcio-status==1.76.0 ; python_full_version >= '3.10'
+grpcio-status==1.76.0
gunicorn==23.0.0
gxformat2==0.21.0
h11==0.16.0
h5grove==2.3.0
-h5py==3.14.0 ; python_full_version < '3.10'
-h5py==3.15.1 ; python_full_version >= '3.10'
+h5py==3.15.1
hf-xet==1.2.0 ; platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'
httpcore==1.0.9
httpx==0.28.1
-httpx-sse==0.4.3 ; python_full_version >= '3.10'
+httpx-sse==0.4.3
huggingface-hub==0.36.0
humanfriendly==10.0
idna==3.11
@@ -140,37 +122,35 @@ invoke==2.2.1
isa-rwval==0.10.11
isal==1.8.0
isodate==0.7.2 ; python_full_version < '3.11'
-jaraco-classes==3.4.0 ; python_full_version >= '3.10'
-jaraco-context==6.1.0 ; python_full_version >= '3.10'
-jaraco-functools==4.4.0 ; python_full_version >= '3.10'
-jeepney==0.9.0 ; python_full_version >= '3.10' and sys_platform == 'linux'
+jaraco-classes==3.4.0
+jaraco-context==6.1.0
+jaraco-functools==4.4.0
+jeepney==0.9.0 ; sys_platform == 'linux'
jinja2==3.1.6
jiter==0.12.0
jmespath==1.0.1
jsonref==1.1.0
-jsonschema==4.25.1 ; python_full_version < '3.10'
-jsonschema==4.26.0 ; python_full_version >= '3.10'
-jsonschema-path==0.3.4 ; python_full_version >= '3.10'
+jsonschema==4.26.0
+jsonschema-path==0.3.4
jsonschema-specifications==2025.9.1
-keyring==25.7.0 ; python_full_version >= '3.10'
+keyring==25.7.0
kombu==5.6.2
lagom==2.7.7
legacy-cgi==2.6.4 ; python_full_version >= '3.13'
-limits==4.2 ; python_full_version < '3.10'
-limits==5.6.0 ; python_full_version >= '3.10'
-logfire==4.19.0 ; python_full_version >= '3.10'
+limits==5.6.0
+logfire==4.19.0
logfire-api==4.19.0
-lupa==2.6 ; python_full_version >= '3.10'
+lupa==2.6
lxml==6.0.2
mako==1.3.10
-markdown==3.9 ; python_full_version < '3.10'
-markdown==3.10 ; python_full_version >= '3.10'
+markdown==3.10
markdown-it-py==3.0.0 ; python_full_version < '3.11'
markdown-it-py==4.0.0 ; python_full_version >= '3.11'
markupsafe==3.0.3
-mcp==1.25.0 ; python_full_version >= '3.10'
+mcp==1.25.0
mdurl==0.1.2
-mercurial==7.1.2
+mercurial==7.1.2 ; python_version < '3.14'
+mercurial==7.2rc0 ; python_version >= '3.14'
mistralai==1.9.11
mistune==3.1.4
more-itertools==10.8.0
@@ -179,73 +159,62 @@ msal==1.34.0
msgpack==1.1.2
multidict==6.7.0
mypy-extensions==1.1.0
-networkx==3.2.1 ; python_full_version < '3.10'
-networkx==3.4.2 ; python_full_version == '3.10.*'
+networkx==3.4.2 ; python_full_version < '3.11'
networkx==3.6.1 ; python_full_version >= '3.11'
-nexus-rpc==1.1.0 ; python_full_version < '3.10'
-nexus-rpc==1.2.0 ; python_full_version >= '3.10'
+nexus-rpc==1.2.0
nodejs-wheel==22.20.0
nodejs-wheel-binaries==22.20.0
-numpy==2.0.2 ; python_full_version < '3.10'
-numpy==2.2.6 ; python_full_version == '3.10.*'
+numpy==2.2.6 ; python_full_version < '3.11'
numpy==2.4.1 ; python_full_version >= '3.11'
oauthlib==3.3.1
openai==2.15.0
-openapi-pydantic==0.5.1 ; python_full_version >= '3.10'
+openapi-pydantic==0.5.1
openpyxl==3.1.5
opentelemetry-api==1.39.1
-opentelemetry-exporter-otlp-proto-common==1.39.1 ; python_full_version >= '3.10'
-opentelemetry-exporter-otlp-proto-http==1.39.1 ; python_full_version >= '3.10'
-opentelemetry-exporter-prometheus==0.60b1 ; python_full_version >= '3.10'
-opentelemetry-instrumentation==0.60b1 ; python_full_version >= '3.10'
-opentelemetry-instrumentation-httpx==0.60b1 ; python_full_version >= '3.10'
-opentelemetry-proto==1.39.1 ; python_full_version >= '3.10'
-opentelemetry-sdk==1.39.1 ; python_full_version >= '3.10'
-opentelemetry-semantic-conventions==0.60b1 ; python_full_version >= '3.10'
-opentelemetry-util-http==0.60b1 ; python_full_version >= '3.10'
+opentelemetry-exporter-otlp-proto-common==1.39.1
+opentelemetry-exporter-otlp-proto-http==1.39.1
+opentelemetry-exporter-prometheus==0.60b1
+opentelemetry-instrumentation==0.60b1
+opentelemetry-instrumentation-httpx==0.60b1
+opentelemetry-proto==1.39.1
+opentelemetry-sdk==1.39.1
+opentelemetry-semantic-conventions==0.60b1
+opentelemetry-util-http==0.60b1
orjson==3.11.5
oyaml==1.0
-packaging==24.2 ; python_full_version < '3.10'
-packaging==25.0 ; python_full_version >= '3.10'
+packaging==25.0
paramiko==4.0.0
parsley==1.3
paste==3.10.1
pastedeploy==3.1.0
-pathable==0.4.4 ; python_full_version >= '3.10'
-pathvalidate==3.3.1 ; python_full_version >= '3.10'
+pathable==0.4.4
+pathvalidate==3.3.1
pebble==5.1.3
-pillow==11.3.0 ; python_full_version < '3.10'
-pillow==12.1.0 ; python_full_version >= '3.10'
-platformdirs==4.5.1 ; python_full_version >= '3.10'
-prometheus-client==0.24.1 ; python_full_version >= '3.10'
+pillow==12.1.0
+platformdirs==4.5.1
+prometheus-client==0.24.1
prompt-toolkit==3.0.52
propcache==0.4.1
proto-plus==1.27.0
-protobuf==5.29.5 ; python_full_version < '3.10'
-protobuf==6.33.4 ; python_full_version >= '3.10'
+protobuf==6.33.4
prov==1.5.1
psutil==7.2.1
pulsar-galaxy-lib==0.15.13
-py-key-value-aio==0.3.0 ; python_full_version >= '3.10'
-py-key-value-shared==0.3.0 ; python_full_version >= '3.10'
+py-key-value-aio==0.3.0
+py-key-value-shared==0.3.0
pyasn1==0.6.2
pyasn1-modules==0.4.2
pycparser==2.23 ; (implementation_name != 'PyPy' and platform_python_implementation != 'PyPy') or (implementation_name == 'pypy' and platform_python_implementation == 'PyPy')
pycryptodome==3.23.0
pydantic==2.12.5
-pydantic-ai==0.8.1 ; python_full_version < '3.10'
-pydantic-ai==1.44.0 ; python_full_version >= '3.10'
-pydantic-ai-slim==0.8.1 ; python_full_version < '3.10'
-pydantic-ai-slim==1.44.0 ; python_full_version >= '3.10'
+pydantic-ai==1.44.0
+pydantic-ai-slim==1.44.0
pydantic-core==2.41.5
-pydantic-evals==0.8.1 ; python_full_version < '3.10'
-pydantic-evals==1.44.0 ; python_full_version >= '3.10'
-pydantic-graph==0.8.1 ; python_full_version < '3.10'
-pydantic-graph==1.44.0 ; python_full_version >= '3.10'
-pydantic-settings==2.11.0 ; python_full_version < '3.10'
-pydantic-settings==2.12.0 ; python_full_version >= '3.10'
+pydantic-evals==1.44.0
+pydantic-graph==1.44.0
+pydantic-settings==2.12.0
pydantic-tes==0.2.0
-pydocket==0.16.6 ; python_full_version >= '3.10'
+pydocket==0.16.6
pydicom==2.4.4 ; python_full_version < '3.10'
pydicom==3.0.1 ; python_full_version >= '3.10'
pydot==4.0.1
@@ -263,20 +232,18 @@ pyreadline3==3.5.4 ; sys_platform == 'win32'
pysam==0.23.3
python-dateutil==2.9.0.post0
python-dotenv==1.2.1
-python-json-logger==4.0.0 ; python_full_version >= '3.10'
+python-json-logger==4.0.0
python-magic==0.4.27
-python-multipart==0.0.20 ; python_full_version < '3.10'
-python-multipart==0.0.21 ; python_full_version >= '3.10'
+python-multipart==0.0.21
python-slugify==8.0.4
python3-openid==3.2.0
pytz==2025.2
-pywin32==311 ; python_full_version >= '3.10' and sys_platform == 'win32'
-pywin32-ctypes==0.2.3 ; python_full_version >= '3.10' and sys_platform == 'win32'
+pywin32==311 ; sys_platform == 'win32'
+pywin32-ctypes==0.2.3 ; sys_platform == 'win32'
pyyaml==6.0.3
pyzmq==27.1.0
-rdflib==7.4.0 ; python_full_version < '3.10'
-rdflib==7.5.0 ; python_full_version >= '3.10'
-redis==7.1.0 ; python_full_version >= '3.10'
+rdflib==7.5.0
+redis==7.1.0
referencing==0.36.2
refgenconf==0.12.2
regex==2026.1.15
@@ -287,45 +254,38 @@ requests-toolbelt==1.0.0
requests-unixsocket==0.4.1
rich==13.9.4
rich-argparse==1.7.2
-rich-rst==1.3.2 ; python_full_version >= '3.10'
+rich-rst==1.3.2
rocrate==0.14.2
routes==2.5.1
-rpds-py==0.27.1 ; python_full_version < '3.10'
-rpds-py==0.30.0 ; python_full_version >= '3.10'
+rpds-py==0.30.0
rsa==4.9.1
ruamel-yaml==0.18.17
ruamel-yaml-clib==0.2.15 ; python_full_version < '3.15' and platform_python_implementation == 'CPython'
-s3fs==2025.10.0 ; python_full_version < '3.10'
-s3fs==2026.1.0 ; python_full_version >= '3.10'
-s3transfer==0.15.0 ; python_full_version < '3.10'
-s3transfer==0.16.0 ; python_full_version >= '3.10'
+s3fs==2026.1.0
+s3transfer==0.16.0
schema-salad==8.9.20251102115403
-secretstorage==3.5.0 ; python_full_version >= '3.10' and sys_platform == 'linux'
+secretstorage==3.5.0 ; sys_platform == 'linux'
setuptools==80.9.0
-shellingham==1.5.4 ; python_full_version >= '3.10'
+shellingham==1.5.4
six==1.17.0
slowapi==0.1.9
sniffio==1.3.1
-social-auth-core==4.7.0 ; python_full_version < '3.10'
-social-auth-core==4.8.3 ; python_full_version >= '3.10'
+social-auth-core==4.8.3
sortedcontainers==2.4.0
spython==0.3.14
sqlalchemy==2.0.45
sqlparse==0.5.5
-sse-starlette==3.1.2 ; python_full_version >= '3.10'
-starlette==0.49.3 ; python_full_version < '3.10'
-starlette==0.50.0 ; python_full_version >= '3.10'
+sse-starlette==3.2.0
+starlette==0.50.0
starlette-context==0.4.0
supervisor==4.3.0
svgwrite==1.4.3
-temporalio==1.16.0 ; python_full_version < '3.10'
-temporalio==1.20.0 ; python_full_version >= '3.10'
+temporalio==1.20.0
tenacity==9.1.2
text-unidecode==1.3
-tifffile==2024.8.30 ; python_full_version < '3.10'
-tifffile==2025.5.10 ; python_full_version == '3.10.*'
+tifffile==2025.5.10 ; python_full_version < '3.11'
tifffile==2026.1.14 ; python_full_version >= '3.11'
-tiktoken==0.12.0 ; python_full_version >= '3.10'
+tiktoken==0.12.0
tinydb==4.8.2
tokenizers==0.22.2 ; sys_platform != 'emscripten'
tomli==2.4.0 ; python_full_version < '3.11'
@@ -333,20 +293,16 @@ tornado==6.5.4
tqdm==4.67.1
tuspy==1.1.0
tuspyserver==4.2.3
-typer==0.21.1 ; python_full_version >= '3.10'
+typer==0.21.1
types-protobuf==6.32.1.20251210
-types-requests==2.31.0.6 ; python_full_version < '3.10' and sys_platform != 'emscripten'
-types-requests==2.32.4.20260107 ; python_full_version >= '3.10' and sys_platform != 'emscripten'
-types-urllib3==1.26.25.14 ; python_full_version < '3.10' and sys_platform != 'emscripten'
+types-requests==2.32.4.20260107 ; sys_platform != 'emscripten'
typing-extensions==4.15.0
typing-inspection==0.4.2
tzdata==2025.3
tzlocal==5.3.1
ubiquerg==0.8.2
-urllib3==1.26.20 ; python_full_version < '3.10'
-urllib3==2.6.3 ; python_full_version >= '3.10'
-uvicorn==0.39.0 ; python_full_version < '3.10'
-uvicorn==0.40.0 ; python_full_version >= '3.10'
+urllib3==2.6.3
+uvicorn==0.40.0
uvloop==0.22.1
vine==5.1.0
wcwidth==0.2.14
diff --git a/lib/galaxy/dependencies/pinned-test-requirements.txt b/lib/galaxy/dependencies/pinned-test-requirements.txt
index fa5eae9337a..2d85f414e2c 100644
--- a/lib/galaxy/dependencies/pinned-test-requirements.txt
+++ b/lib/galaxy/dependencies/pinned-test-requirements.txt
@@ -4,170 +4,153 @@ aiohappyeyeballs==2.6.1
aiohttp==3.13.3
aiosignal==1.4.0
anyio==4.12.1
-ase==3.26.0 ; python_full_version < '3.10'
-ase==3.27.0 ; python_full_version >= '3.10'
+ase==3.27.0
+async-generator==1.10
async-timeout==5.0.1 ; python_full_version < '3.11'
attrs==25.4.0
axe-selenium-python==2.1.6
backports-asyncio-runner==1.2.0 ; python_full_version < '3.11'
-boto3==1.41.5 ; python_full_version < '3.10'
-boto3==1.42.19 ; python_full_version >= '3.10'
-botocore==1.41.5 ; python_full_version < '3.10'
-botocore==1.42.19 ; python_full_version >= '3.10'
-cachecontrol==0.14.3 ; python_full_version < '3.10'
-cachecontrol==0.14.4 ; python_full_version >= '3.10'
+boto3==1.42.19
+botocore==1.42.19
+cachecontrol==0.14.4
cachetools==6.2.4
cattrs==25.3.0
certifi==2026.1.4
cffi==2.0.0 ; implementation_name != 'pypy' and os_name == 'nt'
charset-normalizer==3.4.4
-click==8.1.8 ; python_full_version < '3.10'
-click==8.3.1 ; python_full_version >= '3.10'
+click==8.3.1
colorama==0.4.6 ; sys_platform == 'win32'
colorlog==6.10.1
-contourpy==1.3.0 ; python_full_version < '3.10'
-contourpy==1.3.2 ; python_full_version == '3.10.*'
+contourpy==1.3.2 ; python_full_version < '3.11'
contourpy==1.3.3 ; python_full_version >= '3.11'
-coverage==7.10.7 ; python_full_version < '3.10'
-coverage==7.13.1 ; python_full_version >= '3.10'
-cwltest==2.6.20250818005349 ; python_full_version < '3.10'
-cwltest==2.6.20251216093331 ; python_full_version >= '3.10'
+coverage==7.13.1
+cwltest==2.6.20251216093331
cycler==0.12.1
decorator==5.2.1
defusedxml==0.7.1
-dogpile-cache==1.4.1 ; python_full_version < '3.10'
-dogpile-cache==1.5.0 ; python_full_version >= '3.10'
-enum-tools==0.12.0 ; python_full_version >= '3.10'
+dogpile-cache==1.5.0
+enum-tools==0.12.0
exceptiongroup==1.3.1 ; python_full_version < '3.11'
-filelock==3.19.1 ; python_full_version < '3.10'
-filelock==3.20.3 ; python_full_version >= '3.10'
+filelock==3.20.3
fluent-logger==0.11.1
-fonttools==4.60.2 ; python_full_version < '3.10'
-fonttools==4.61.1 ; python_full_version >= '3.10'
+fonttools==4.61.1
frozenlist==1.8.0
-greenlet==3.2.4 ; python_full_version < '3.10'
-greenlet==3.3.0 ; python_full_version >= '3.10'
+fsspec==2026.1.0
+gcsfs==2026.1.0
+google-api-core==2.29.0
+google-auth==2.47.0
+google-auth-oauthlib==1.2.4
+google-cloud-core==2.5.0
+google-cloud-storage==3.8.0
+google-cloud-storage-control==1.9.0
+google-crc32c==1.8.0
+google-resumable-media==2.8.0
+googleapis-common-protos==1.72.0
+greenlet==3.3.0
+grpc-google-iam-v1==0.14.3
+grpcio==1.76.0
+grpcio-status==1.76.0
h11==0.16.0
-html5lib==1.1 ; python_full_version < '3.10'
-html5rdf==1.2.1 ; python_full_version >= '3.10'
+html5rdf==1.2.1
httpcore==1.0.9
httpx==0.28.1
idna==3.11
-importlib-metadata==8.7.1 ; python_full_version < '3.12'
-importlib-resources==6.5.2 ; python_full_version < '3.10'
-iniconfig==2.1.0 ; python_full_version < '3.10'
-iniconfig==2.3.0 ; python_full_version >= '3.10'
+importlib-metadata==8.7.1
+iniconfig==2.3.0
inquirerpy==0.3.4
isodate==0.7.2 ; python_full_version < '3.11'
jinja2==3.1.6
jmespath==1.0.1
jsonpatch==1.33
jsonpointer==3.0.0
-jsonschema==4.25.1 ; python_full_version < '3.10'
-jsonschema==4.26.0 ; python_full_version >= '3.10'
+jsonschema==4.26.0
jsonschema-specifications==2025.9.1
junit-xml==1.9
-kiwisolver==1.4.7 ; python_full_version < '3.10'
-kiwisolver==1.4.9 ; python_full_version >= '3.10'
+kiwisolver==1.4.9
librt==0.7.8 ; platform_python_implementation != 'PyPy'
lxml==6.0.2
markdown-it-py==3.0.0 ; python_full_version < '3.11'
markdown-it-py==4.0.0 ; python_full_version >= '3.11'
markupsafe==3.0.3
-matplotlib==3.9.4 ; python_full_version < '3.10'
-matplotlib==3.10.8 ; python_full_version >= '3.10'
+matplotlib==3.10.8
mdurl==0.1.2
-mirakuru==2.6.1 ; python_full_version < '3.10'
-mirakuru==3.0.1 ; python_full_version >= '3.10'
+mirakuru==3.0.1
mistune==3.1.4
msgpack==1.1.2
multidict==6.7.0
mypy==1.19.1
mypy-extensions==1.1.0
-numpy==2.0.2 ; python_full_version < '3.10'
-numpy==2.2.6 ; python_full_version == '3.10.*'
+numpy==2.2.6 ; python_full_version < '3.11'
numpy==2.4.1 ; python_full_version >= '3.11'
+oauthlib==3.3.1
onedatafilerestclient==21.2.5.2
outcome==1.3.0.post0
-owlrl==6.0.2 ; python_full_version < '3.10'
-owlrl==7.1.4 ; python_full_version >= '3.10'
-packaging==24.2 ; python_full_version < '3.10'
-packaging==25.0 ; python_full_version >= '3.10'
+owlrl==7.1.4
+packaging==25.0
pathspec==1.0.3
pfzy==0.3.4
-pillow==11.3.0 ; python_full_version < '3.10'
-pillow==12.1.0 ; python_full_version >= '3.10'
+pillow==12.1.0
pkce==1.0.3
-platformdirs==4.4.0 ; python_full_version < '3.10'
-platformdirs==4.5.1 ; python_full_version >= '3.10'
+platformdirs==4.5.1
playwright==1.57.0
pluggy==1.6.0
-port-for==0.7.4 ; python_full_version < '3.10'
-port-for==1.0.0 ; python_full_version >= '3.10'
-prettytable==3.16.0 ; python_full_version < '3.10'
-prettytable==3.17.0 ; python_full_version >= '3.10'
+port-for==1.0.0
+prettytable==3.17.0
prompt-toolkit==3.0.52
propcache==0.4.1
+proto-plus==1.27.0
+protobuf==6.33.4
psutil==7.2.1 ; sys_platform != 'cygwin'
-psycopg==3.2.13 ; python_full_version < '3.10'
-psycopg==3.3.2 ; python_full_version >= '3.10'
+psycopg==3.3.2
+pyasn1==0.6.2
+pyasn1-modules==0.4.2
pycparser==2.23 ; implementation_name != 'PyPy' and implementation_name != 'pypy' and os_name == 'nt'
pyee==13.0.0
pygments==2.19.2
pyparsing==3.3.1
-pyshacl==0.26.0 ; python_full_version < '3.10'
-pyshacl==0.30.1 ; python_full_version >= '3.10'
+pyshacl==0.30.1
pysocks==1.7.1
-pytest==8.4.2 ; python_full_version < '3.10'
-pytest==9.0.2 ; python_full_version >= '3.10'
-pytest-asyncio==1.2.0 ; python_full_version < '3.10'
-pytest-asyncio==1.3.0 ; python_full_version >= '3.10'
+pytest==9.0.2
+pytest-asyncio==1.3.0
pytest-base-url==2.1.0
pytest-cov==7.0.0
-pytest-html==4.1.1
+pytest-html==4.2.0
pytest-httpserver==1.1.3
pytest-json-report==1.5.0
pytest-metadata==3.1.1
pytest-mock==3.15.1
-pytest-playwright==0.7.1 ; python_full_version < '3.10'
-pytest-playwright==0.7.2 ; python_full_version >= '3.10'
+pytest-playwright==0.7.2
pytest-postgresql==7.0.2
pytest-shard==0.1.2
python-dateutil==2.9.0.post0
python-irodsclient==3.2.0
python-slugify==8.0.4
pyyaml==6.0.3
-rdflib==7.4.0 ; python_full_version < '3.10'
-rdflib==7.5.0 ; python_full_version >= '3.10'
+rdflib==7.5.0
referencing==0.36.2
requests==2.32.5
requests-cache==1.2.1
+requests-oauthlib==2.0.0
responses==0.25.8
rich==13.9.4
rich-click==1.9.5
-roc-validator==0.4.2 ; python_full_version < '3.9.20'
-roc-validator==0.4.6 ; python_full_version >= '3.9.20' and python_full_version < '3.10'
-roc-validator==0.8.0 ; python_full_version >= '3.10'
-rpds-py==0.27.1 ; python_full_version < '3.10'
-rpds-py==0.30.0 ; python_full_version >= '3.10'
+roc-validator==0.8.0
+rpds-py==0.30.0
+rsa==4.9.1
ruamel-yaml==0.18.17
ruamel-yaml-clib==0.2.15 ; python_full_version < '3.15' and platform_python_implementation == 'CPython'
rucio-clients==39.0.0
-s3transfer==0.15.0 ; python_full_version < '3.10'
-s3transfer==0.16.0 ; python_full_version >= '3.10'
+s3transfer==0.16.0
schema-salad==8.9.20251102115403
-scipy==1.13.1 ; python_full_version < '3.10'
-scipy==1.15.3 ; python_full_version == '3.10.*'
+scipy==1.15.3 ; python_full_version < '3.11'
scipy==1.17.0 ; python_full_version >= '3.11'
-selenium==4.32.0 ; python_full_version < '3.10'
-selenium==4.39.0 ; python_full_version >= '3.10'
+selenium==4.40.0
seletools==1.5.0
six==1.17.0
sniffio==1.3.1
sortedcontainers==2.4.0
statsd==4.0.1
-stevedore==5.5.0 ; python_full_version < '3.10'
-stevedore==5.6.0 ; python_full_version >= '3.10'
+stevedore==5.6.0
tabulate==0.9.0
testfixtures==8.3.0 ; python_full_version < '3.11'
testfixtures==10.0.0 ; python_full_version >= '3.11'
@@ -176,27 +159,24 @@ tinydb==4.8.2
toml==0.10.2
tomli==2.4.0 ; python_full_version <= '3.11'
total-perspective-vortex==3.1.3
-trio==0.31.0 ; python_full_version < '3.10'
-trio==0.32.0 ; python_full_version >= '3.10'
+trio==0.32.0
+trio-typing==0.10.0
trio-websocket==0.12.2
tuspy==1.1.0
twill==3.3.1
types-cachetools==6.2.0.20251022
-types-requests==2.31.0.6 ; python_full_version < '3.10'
-types-requests==2.32.4.20260107 ; python_full_version >= '3.10'
-types-urllib3==1.26.25.14 ; python_full_version < '3.10'
+types-certifi==2021.10.8.3
+types-requests==2.32.4.20260107
+types-urllib3==1.26.25.14
typing-extensions==4.15.0
-typos==1.42.0 ; python_full_version >= '3.10'
+typos==1.42.1
tzdata==2025.3 ; sys_platform == 'win32'
url-normalize==2.2.1
-urllib3==1.26.20 ; python_full_version < '3.10'
-urllib3==2.6.3 ; python_full_version >= '3.10'
+urllib3==2.6.3
watchdog==6.0.0
wcwidth==0.2.14
-webencodings==0.5.1 ; python_full_version < '3.10'
websocket-client==1.9.0
werkzeug==3.1.5
-wsproto==1.2.0 ; python_full_version < '3.10'
-wsproto==1.3.2 ; python_full_version >= '3.10'
+wsproto==1.3.2
yarl==1.22.0
-zipp==3.23.0 ; python_full_version < '3.12'
+zipp==3.23.0
diff --git a/lib/galaxy/dependencies/pinned-typecheck-requirements.txt b/lib/galaxy/dependencies/pinned-typecheck-requirements.txt
index f2a936e6ec3..745cd5ddb46 100644
--- a/lib/galaxy/dependencies/pinned-typecheck-requirements.txt
+++ b/lib/galaxy/dependencies/pinned-typecheck-requirements.txt
@@ -27,13 +27,11 @@ types-paramiko==4.0.0.20250822
types-python-dateutil==2.9.0.20251115
types-python-slugify==8.0.2.20240310
types-pyyaml==6.0.12.20250915
-types-requests==2.31.0.6 ; python_full_version < '3.10'
-types-requests==2.32.4.20260107 ; python_full_version >= '3.10'
+types-requests==2.32.4.20260107
types-s3transfer==0.16.0
types-setuptools==80.9.0.20251223
types-six==1.17.0.20251009
-types-urllib3==1.26.25.14 ; python_full_version < '3.10'
types-webencodings==0.5.0.20251108
typing-extensions==4.15.0
typing-inspection==0.4.2
-urllib3==2.6.3 ; python_full_version >= '3.10'
+urllib3==2.6.3
diff --git a/lib/galaxy/files/__init__.py b/lib/galaxy/files/__init__.py
index bd41e42f9ae..cf21e294c03 100644
--- a/lib/galaxy/files/__init__.py
+++ b/lib/galaxy/files/__init__.py
@@ -1,9 +1,9 @@
import logging
import os
from collections import defaultdict
+from collections.abc import Callable
from typing import (
Any,
- Callable,
NamedTuple,
Optional,
Protocol,
diff --git a/lib/galaxy/files/sources/azure.py b/lib/galaxy/files/sources/azure.py
index 25fc06fbaca..f90d794a5e0 100644
--- a/lib/galaxy/files/sources/azure.py
+++ b/lib/galaxy/files/sources/azure.py
@@ -1,4 +1,4 @@
-from typing_extensions import Literal
+from typing import Literal
try:
from fs.azblob.blob_fs import BlobFS
diff --git a/lib/galaxy/files/sources/invenio.py b/lib/galaxy/files/sources/invenio.py
index 8d1cbe846f0..e78e182e89d 100644
--- a/lib/galaxy/files/sources/invenio.py
+++ b/lib/galaxy/files/sources/invenio.py
@@ -5,13 +5,13 @@ import urllib.request
from typing import (
Any,
cast,
+ Literal,
Optional,
)
from urllib.error import HTTPError
from urllib.parse import quote
from typing_extensions import (
- Literal,
TypedDict,
)
diff --git a/lib/galaxy/files/templates/models.py b/lib/galaxy/files/templates/models.py
index 1114a9be9ad..ed9adc73f2d 100644
--- a/lib/galaxy/files/templates/models.py
+++ b/lib/galaxy/files/templates/models.py
@@ -1,6 +1,7 @@
from typing import (
Annotated,
Any,
+ Literal,
Optional,
Union,
)
@@ -9,7 +10,6 @@ from pydantic import (
Field,
RootModel,
)
-from typing_extensions import Literal
from galaxy.util.config_templates import (
ConfiguredOAuth2Sources,
diff --git a/lib/galaxy/job_execution/container_monitor.py b/lib/galaxy/job_execution/container_monitor.py
index 0590ce715db..52302ccad79 100644
--- a/lib/galaxy/job_execution/container_monitor.py
+++ b/lib/galaxy/job_execution/container_monitor.py
@@ -6,8 +6,8 @@ import sys
import tempfile
import time
import traceback
+from collections.abc import Callable
from functools import partial
-from typing import Callable
from galaxy.tool_util.deps import docker_util
from galaxy.util import (
diff --git a/lib/galaxy/job_execution/output_collect.py b/lib/galaxy/job_execution/output_collect.py
index 728e6298990..063dd1996f7 100644
--- a/lib/galaxy/job_execution/output_collect.py
+++ b/lib/galaxy/job_execution/output_collect.py
@@ -5,10 +5,10 @@ import logging
import operator
import os
import re
+from collections.abc import Callable
from tempfile import NamedTemporaryFile
from typing import (
Any,
- Callable,
Optional,
TYPE_CHECKING,
Union,
diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py
index c70a4f5bc2a..40b706cbd5c 100644
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -15,7 +15,10 @@ import shutil
import sys
import time
import traceback
-from collections.abc import Iterable
+from collections.abc import (
+ Callable,
+ Iterable,
+)
from dataclasses import (
dataclass,
field,
@@ -23,7 +26,6 @@ from dataclasses import (
from json import loads
from typing import (
Any,
- Callable,
cast,
Optional,
TYPE_CHECKING,
diff --git a/lib/galaxy/jobs/job_destination.py b/lib/galaxy/jobs/job_destination.py
index db6c615ac27..1a9fc0701df 100644
--- a/lib/galaxy/jobs/job_destination.py
+++ b/lib/galaxy/jobs/job_destination.py
@@ -1,4 +1,3 @@
-import sys
from dataclasses import (
dataclass,
field,
@@ -14,10 +13,8 @@ if TYPE_CHECKING:
from galaxy.jobs import ResubmitConfigDict
from galaxy.model import Job
-dataclass_kwargs = {"kw_only": True} if sys.version_info >= (3, 10) else {}
-
-@dataclass(**dataclass_kwargs, eq=False)
+@dataclass(kw_only=True, eq=False)
class JobDestination:
"""
Provides details about where a job runs
diff --git a/lib/galaxy/jobs/mapper.py b/lib/galaxy/jobs/mapper.py
index a4401b999c2..2684b0da492 100644
--- a/lib/galaxy/jobs/mapper.py
+++ b/lib/galaxy/jobs/mapper.py
@@ -1,9 +1,9 @@
import importlib
import logging
+from collections.abc import Callable
from inspect import getfullargspec
from types import ModuleType
from typing import (
- Callable,
TYPE_CHECKING,
Union,
)
diff --git a/lib/galaxy/jobs/runners/drmaa.py b/lib/galaxy/jobs/runners/drmaa.py
index cda9b6ea780..e6242cca853 100644
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -10,11 +10,10 @@ import string
import time
from typing import (
TYPE_CHECKING,
+ TypeAlias,
Union,
)
-from typing_extensions import TypeAlias
-
from galaxy import model
from galaxy.jobs.handler import DEFAULT_JOB_RUNNER_FAILURE_MESSAGE
from galaxy.jobs.job_destination import JobDestination
diff --git a/lib/galaxy/jobs/runners/util/cli/job/__init__.py b/lib/galaxy/jobs/runners/util/cli/job/__init__.py
index 26076407ca5..957953b78a4 100644
--- a/lib/galaxy/jobs/runners/util/cli/job/__init__.py
+++ b/lib/galaxy/jobs/runners/util/cli/job/__init__.py
@@ -7,8 +7,7 @@ from abc import (
abstractmethod,
)
from enum import Enum
-
-from typing_extensions import TypeAlias
+from typing import TypeAlias
try:
from galaxy.model import Job
diff --git a/lib/galaxy/managers/base.py b/lib/galaxy/managers/base.py
index 0e231f3ad32..9c82de31dc0 100644
--- a/lib/galaxy/managers/base.py
+++ b/lib/galaxy/managers/base.py
@@ -30,10 +30,10 @@ import builtins
import datetime
import logging
import re
+from collections.abc import Callable
from functools import partial
from typing import (
Any,
- Callable,
Generic,
NamedTuple,
Optional,
diff --git a/lib/galaxy/managers/collections.py b/lib/galaxy/managers/collections.py
index 4f0a834fd9a..26ab331775b 100644
--- a/lib/galaxy/managers/collections.py
+++ b/lib/galaxy/managers/collections.py
@@ -1,6 +1,7 @@
import logging
from typing import (
Any,
+ Literal,
Optional,
overload,
TYPE_CHECKING,
@@ -12,7 +13,6 @@ from sqlalchemy.orm import (
joinedload,
Query,
)
-from typing_extensions import Literal
from galaxy import model
from galaxy.datatypes.registry import Registry
diff --git a/lib/galaxy/managers/context.py b/lib/galaxy/managers/context.py
index c6ec8eff247..00a169d8439 100644
--- a/lib/galaxy/managers/context.py
+++ b/lib/galaxy/managers/context.py
@@ -37,10 +37,10 @@ A method that requires a user but not a history should declare its
# more checks against this issue.
import abc
import string
+from collections.abc import Callable
from json import dumps
from typing import (
Any,
- Callable,
cast,
Literal,
Optional,
diff --git a/lib/galaxy/managers/histories.py b/lib/galaxy/managers/histories.py
index e68ad5c0515..5845e1405b5 100644
--- a/lib/galaxy/managers/histories.py
+++ b/lib/galaxy/managers/histories.py
@@ -9,6 +9,7 @@ import logging
from typing import (
Any,
cast,
+ Literal,
Optional,
TYPE_CHECKING,
Union,
@@ -25,7 +26,6 @@ from sqlalchemy import (
true,
)
from sqlalchemy.orm import aliased
-from typing_extensions import Literal
from galaxy import model
from galaxy.exceptions import (
diff --git a/lib/galaxy/managers/pages.py b/lib/galaxy/managers/pages.py
index 88eb9685328..77ec6655d11 100644
--- a/lib/galaxy/managers/pages.py
+++ b/lib/galaxy/managers/pages.py
@@ -8,10 +8,10 @@ from within Galaxy.
import logging
import re
+from collections.abc import Callable
from html.entities import name2codepoint
from html.parser import HTMLParser
from typing import (
- Callable,
Optional,
TYPE_CHECKING,
Union,
diff --git a/lib/galaxy/managers/workflows.py b/lib/galaxy/managers/workflows.py
index 344128c3145..0582c2c9236 100644
--- a/lib/galaxy/managers/workflows.py
+++ b/lib/galaxy/managers/workflows.py
@@ -9,6 +9,7 @@ from typing import (
NamedTuple,
Optional,
TYPE_CHECKING,
+ TypeAlias,
Union,
)
@@ -41,9 +42,6 @@ from sqlalchemy.orm import (
joinedload,
subqueryload,
)
-from typing_extensions import (
- TypeAlias,
-)
from galaxy import (
exceptions,
diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py
index 101f8881f2a..c70972861e5 100644
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -32,10 +32,12 @@ from typing import (
cast,
ClassVar,
Generic,
+ Literal,
NamedTuple,
Optional,
overload,
TYPE_CHECKING,
+ TypeAlias,
TypeVar,
Union,
)
@@ -132,10 +134,8 @@ from sqlalchemy.orm.session import Session
from sqlalchemy.sql.expression import FromClause
from typing_extensions import (
deprecated,
- Literal,
NotRequired,
Protocol,
- TypeAlias,
TypedDict,
)
@@ -7221,6 +7221,12 @@ class DatasetCollection(Base, Dictifiable, UsesAnnotations, Serializable):
def expire_populated_state(self):
required_object_session(self).expire(self, ("populated_state",))
+ # Clear the cached populated_optimized value so it will be recomputed
+ # on the next access with fresh database state. This prevents a race
+ # condition where the cached value becomes stale while nested
+ # collections are being populated.
+ if hasattr(self, "_populated_optimized"):
+ delattr(self, "_populated_optimized")
@property
def allow_implicit_mapping(self):
diff --git a/lib/galaxy/model/dataset_collections/types/sample_sheet_workbook.py b/lib/galaxy/model/dataset_collections/types/sample_sheet_workbook.py
index 1037ea0c2de..3bbb83dc62b 100644
--- a/lib/galaxy/model/dataset_collections/types/sample_sheet_workbook.py
+++ b/lib/galaxy/model/dataset_collections/types/sample_sheet_workbook.py
@@ -1,6 +1,7 @@
from dataclasses import dataclass
from typing import (
cast,
+ Literal,
Optional,
Protocol,
TYPE_CHECKING,
@@ -15,7 +16,6 @@ from pydantic import (
BaseModel,
Field,
)
-from typing_extensions import Literal
from galaxy.exceptions import RequestParameterInvalidException
from galaxy.model.dataset_collections.rule_target_columns import (
diff --git a/lib/galaxy/model/migrations/alembic/env.py b/lib/galaxy/model/migrations/alembic/env.py
index 98091912b80..c9db41cc84d 100644
--- a/lib/galaxy/model/migrations/alembic/env.py
+++ b/lib/galaxy/model/migrations/alembic/env.py
@@ -1,7 +1,7 @@
import logging
import re
+from collections.abc import Callable
from typing import (
- Callable,
cast,
)
diff --git a/lib/galaxy/model/store/__init__.py b/lib/galaxy/model/store/__init__.py
index 00441b3ce38..08eedd509ae 100644
--- a/lib/galaxy/model/store/__init__.py
+++ b/lib/galaxy/model/store/__init__.py
@@ -8,6 +8,7 @@ import tarfile
import tempfile
from collections import defaultdict
from collections.abc import (
+ Callable,
Iterable,
Iterator,
)
@@ -22,7 +23,6 @@ from tempfile import mkdtemp
from types import TracebackType
from typing import (
Any,
- Callable,
cast,
Literal,
Optional,
diff --git a/lib/galaxy/model/store/discover.py b/lib/galaxy/model/store/discover.py
index ccd0c7960ef..50e6125a113 100644
--- a/lib/galaxy/model/store/discover.py
+++ b/lib/galaxy/model/store/discover.py
@@ -9,10 +9,12 @@ corresponding to files in other contexts.
import abc
import logging
import os
-from collections.abc import Iterable
+from collections.abc import (
+ Callable,
+ Iterable,
+)
from typing import (
Any,
- Callable,
NamedTuple,
Optional,
TYPE_CHECKING,
diff --git a/lib/galaxy/model/tool_shed_install/__init__.py b/lib/galaxy/model/tool_shed_install/__init__.py
index 4df58cf2150..4fa03b74647 100644
--- a/lib/galaxy/model/tool_shed_install/__init__.py
+++ b/lib/galaxy/model/tool_shed_install/__init__.py
@@ -1,10 +1,10 @@
import logging
import os
+from collections.abc import Callable
from datetime import datetime
from enum import Enum
from typing import (
Any,
- Callable,
Optional,
)
diff --git a/lib/galaxy/model/unittest_utils/model_testing_utils.py b/lib/galaxy/model/unittest_utils/model_testing_utils.py
index dacbde037a4..a1af8dd23ba 100644
--- a/lib/galaxy/model/unittest_utils/model_testing_utils.py
+++ b/lib/galaxy/model/unittest_utils/model_testing_utils.py
@@ -1,9 +1,11 @@
import os
import uuid
-from collections.abc import Iterator
+from collections.abc import (
+ Callable,
+ Iterator,
+)
from contextlib import contextmanager
from typing import (
- Callable,
Optional,
)
diff --git a/lib/galaxy/queue_worker.py b/lib/galaxy/queue_worker.py
index fe97e604c1b..0e3d0f719b0 100644
--- a/lib/galaxy/queue_worker.py
+++ b/lib/galaxy/queue_worker.py
@@ -135,7 +135,7 @@ class ControlTask:
while self.response is self._response:
self.connection.drain_events(timeout=timeout)
return self.response
- except socket.timeout:
+ except TimeoutError:
log.exception("Error waiting for task: '%s' sent with routing key '%s'", payload, routing_key)
except Exception:
log.exception("Error queueing async task: '%s'. for %s", payload, routing_key)
diff --git a/lib/galaxy/quota/_schema.py b/lib/galaxy/quota/_schema.py
index faf9c3cc85e..e0fee00f1d0 100644
--- a/lib/galaxy/quota/_schema.py
+++ b/lib/galaxy/quota/_schema.py
@@ -1,5 +1,6 @@
from enum import Enum
from typing import (
+ Literal,
Optional,
)
@@ -7,7 +8,6 @@ from pydantic import (
Field,
RootModel,
)
-from typing_extensions import Literal
from galaxy.schema.fields import (
EncodedDatabaseIdField,
diff --git a/lib/galaxy/schema/fetch_data.py b/lib/galaxy/schema/fetch_data.py
index e9f236603aa..91cfe8348e6 100644
--- a/lib/galaxy/schema/fetch_data.py
+++ b/lib/galaxy/schema/fetch_data.py
@@ -3,6 +3,7 @@ from enum import Enum
from typing import (
Annotated,
Any,
+ Literal,
Optional,
Union,
)
@@ -17,7 +18,6 @@ from pydantic import (
TypeAdapter,
UUID4,
)
-from typing_extensions import Literal
from galaxy.schema.fields import DecodedDatabaseIdField
from galaxy.schema.schema import Model
diff --git a/lib/galaxy/schema/fields.py b/lib/galaxy/schema/fields.py
index 180e463d877..75428e18038 100644
--- a/lib/galaxy/schema/fields.py
+++ b/lib/galaxy/schema/fields.py
@@ -1,7 +1,8 @@
import re
+from collections.abc import Callable
from typing import (
Annotated,
- Callable,
+ get_args,
get_origin,
TYPE_CHECKING,
Union,
@@ -14,9 +15,6 @@ from pydantic import (
WithJsonSchema,
)
from pydantic_core import PydanticCustomError
-from typing_extensions import (
- get_args,
-)
from galaxy.exceptions import MessageException
diff --git a/lib/galaxy/schema/groups.py b/lib/galaxy/schema/groups.py
index 867841bce92..3998096f81b 100644
--- a/lib/galaxy/schema/groups.py
+++ b/lib/galaxy/schema/groups.py
@@ -1,10 +1,12 @@
-from typing import Optional
+from typing import (
+ Literal,
+ Optional,
+)
from pydantic import (
Field,
RootModel,
)
-from typing_extensions import Literal
from galaxy.schema.fields import (
DecodedDatabaseIdField,
diff --git a/lib/galaxy/schema/history.py b/lib/galaxy/schema/history.py
index b0978dc6716..9b9a5c4985f 100644
--- a/lib/galaxy/schema/history.py
+++ b/lib/galaxy/schema/history.py
@@ -1,5 +1,6 @@
from datetime import datetime
from typing import (
+ Literal,
Optional,
)
@@ -8,7 +9,6 @@ from pydantic import (
Field,
RootModel,
)
-from typing_extensions import Literal
from galaxy.schema.fields import EncodedDatabaseIdField
from galaxy.schema.schema import (
diff --git a/lib/galaxy/schema/invocation.py b/lib/galaxy/schema/invocation.py
index 6797700f0d1..25e77fe9dfa 100644
--- a/lib/galaxy/schema/invocation.py
+++ b/lib/galaxy/schema/invocation.py
@@ -4,6 +4,7 @@ from typing import (
Annotated,
Any,
Generic,
+ Literal,
Optional,
Union,
)
@@ -17,7 +18,6 @@ from pydantic import (
UUID4,
)
from typing_extensions import (
- Literal,
TypeAliasType,
)
diff --git a/lib/galaxy/schema/jobs.py b/lib/galaxy/schema/jobs.py
index 39e3ee33cf2..a1f76797049 100644
--- a/lib/galaxy/schema/jobs.py
+++ b/lib/galaxy/schema/jobs.py
@@ -1,6 +1,7 @@
import json
from typing import (
Any,
+ Literal,
Optional,
Union,
)
@@ -11,7 +12,6 @@ from pydantic import (
field_validator,
UUID4,
)
-from typing_extensions import Literal
from galaxy.schema.fields import (
DecodedDatabaseIdField,
diff --git a/lib/galaxy/schema/library_contents.py b/lib/galaxy/schema/library_contents.py
index 1e0d1f05b65..66b3593cf98 100644
--- a/lib/galaxy/schema/library_contents.py
+++ b/lib/galaxy/schema/library_contents.py
@@ -3,6 +3,7 @@ from enum import Enum
from typing import (
Annotated,
Any,
+ Literal,
Optional,
Union,
)
@@ -13,9 +14,6 @@ from pydantic import (
RootModel,
)
from pydantic.functional_validators import field_validator
-from typing_extensions import (
- Literal,
-)
from galaxy.schema.fields import (
DecodedDatabaseIdField,
diff --git a/lib/galaxy/schema/notifications.py b/lib/galaxy/schema/notifications.py
index a7f59906924..885240d16f7 100644
--- a/lib/galaxy/schema/notifications.py
+++ b/lib/galaxy/schema/notifications.py
@@ -4,6 +4,7 @@ from typing import (
Annotated,
Any,
Generic,
+ Literal,
Optional,
Union,
)
@@ -13,9 +14,6 @@ from pydantic import (
Field,
RootModel,
)
-from typing_extensions import (
- Literal,
-)
from galaxy.schema.fields import (
DecodedDatabaseIdField,
diff --git a/lib/galaxy/schema/schema.py b/lib/galaxy/schema/schema.py
index 540b1a765fa..073c36b6836 100644
--- a/lib/galaxy/schema/schema.py
+++ b/lib/galaxy/schema/schema.py
@@ -9,7 +9,9 @@ from enum import Enum
from typing import (
Annotated,
Any,
+ Literal,
Optional,
+ TypeAlias,
Union,
)
from uuid import UUID
@@ -29,9 +31,7 @@ from pydantic import (
)
from pydantic_core import core_schema
from typing_extensions import (
- Literal,
NotRequired,
- TypeAlias,
TypedDict,
)
diff --git a/lib/galaxy/schema/storage_cleaner.py b/lib/galaxy/schema/storage_cleaner.py
index d34f2a61b0c..a7de24ca60c 100644
--- a/lib/galaxy/schema/storage_cleaner.py
+++ b/lib/galaxy/schema/storage_cleaner.py
@@ -1,11 +1,11 @@
from datetime import datetime
from enum import Enum
from typing import (
+ Literal,
Union,
)
from pydantic import Field
-from typing_extensions import Literal
from galaxy.schema.fields import (
DecodedDatabaseIdField,
diff --git a/lib/galaxy/schema/types.py b/lib/galaxy/schema/types.py
index 7a8dae0b28a..8cfce956ba1 100644
--- a/lib/galaxy/schema/types.py
+++ b/lib/galaxy/schema/types.py
@@ -1,14 +1,12 @@
from datetime import datetime
from typing import (
Annotated,
+ Literal,
Union,
)
from pydantic import ValidationInfo
from pydantic.functional_validators import AfterValidator
-from typing_extensions import (
- Literal,
-)
# Relative URLs cannot be validated with AnyUrl, they need a scheme.
# Making them an alias of `str` for now
diff --git a/lib/galaxy/schema/visualization.py b/lib/galaxy/schema/visualization.py
index d769623f408..9471301256f 100644
--- a/lib/galaxy/schema/visualization.py
+++ b/lib/galaxy/schema/visualization.py
@@ -1,5 +1,6 @@
from datetime import datetime
from typing import (
+ Literal,
Optional,
Union,
)
@@ -9,7 +10,6 @@ from pydantic import (
Field,
RootModel,
)
-from typing_extensions import Literal
from galaxy.schema.fields import (
DecodedDatabaseIdField,
diff --git a/lib/galaxy/schema/workflow/comments.py b/lib/galaxy/schema/workflow/comments.py
index 0565c60b5b8..e41763d383b 100644
--- a/lib/galaxy/schema/workflow/comments.py
+++ b/lib/galaxy/schema/workflow/comments.py
@@ -1,4 +1,5 @@
from typing import (
+ Literal,
Optional,
Union,
)
@@ -8,7 +9,6 @@ from pydantic import (
Field,
RootModel,
)
-from typing_extensions import Literal
class BaseComment(BaseModel):
diff --git a/lib/galaxy/security/__init__.py b/lib/galaxy/security/__init__.py
index 9cd98a972d1..401b3d535b7 100644
--- a/lib/galaxy/security/__init__.py
+++ b/lib/galaxy/security/__init__.py
@@ -4,11 +4,10 @@ Galaxy Security
"""
from typing import (
+ Literal,
Optional,
)
-from typing_extensions import Literal
-
from galaxy.util.bunch import Bunch
ActionModel = Literal["grant", "restrict"]
diff --git a/lib/galaxy/selenium/axe_results.py b/lib/galaxy/selenium/axe_results.py
index a0d67e5edfb..a43e1d61c6a 100644
--- a/lib/galaxy/selenium/axe_results.py
+++ b/lib/galaxy/selenium/axe_results.py
@@ -1,10 +1,10 @@
from typing import (
Any,
+ Literal,
Optional,
)
from typing_extensions import (
- Literal,
Protocol,
)
diff --git a/lib/galaxy/selenium/has_driver_protocol.py b/lib/galaxy/selenium/has_driver_protocol.py
index 62fccb1047b..ef0ef09af88 100644
--- a/lib/galaxy/selenium/has_driver_protocol.py
+++ b/lib/galaxy/selenium/has_driver_protocol.py
@@ -5,10 +5,10 @@ allowing NavigatesGalaxy to work with either backend via composition.
"""
from abc import abstractmethod
+from collections.abc import Callable
from contextlib import AbstractContextManager
from typing import (
Any,
- Callable,
Generic,
Literal,
Optional,
diff --git a/lib/galaxy/tool_shed/metadata/metadata_generator.py b/lib/galaxy/tool_shed/metadata/metadata_generator.py
index b0b7a6123a8..6422639bc3f 100644
--- a/lib/galaxy/tool_shed/metadata/metadata_generator.py
+++ b/lib/galaxy/tool_shed/metadata/metadata_generator.py
@@ -392,7 +392,9 @@ class BaseMetadataGenerator:
if invalid_tool_configs:
metadata_dict["invalid_tools"] = invalid_tool_configs
self.metadata_dict = metadata_dict
- remove_dir(work_dir)
+ # Only remove work_dir if not resetting all metadata - in that case the caller handles cleanup
+ if not self.resetting_all_metadata_on_repository:
+ remove_dir(work_dir)
def generate_package_dependency_metadata(self, elem, valid_tool_dependencies_dict, invalid_tool_dependencies_dict):
"""
diff --git a/lib/galaxy/tools/_types.py b/lib/galaxy/tools/_types.py
index dd6057a11a1..8ee3648aff7 100644
--- a/lib/galaxy/tools/_types.py
+++ b/lib/galaxy/tools/_types.py
@@ -22,11 +22,10 @@ provide strong traditional typing semantics.
from typing import (
Any,
+ Literal,
Union,
)
-from typing_extensions import Literal
-
# Input dictionary from the API, may include map/reduce instructions. Objects are referenced by "src"
# dictionaries and encoded IDS.
ToolRequestT = dict[str, Any]
diff --git a/lib/galaxy/tools/evaluation.py b/lib/galaxy/tools/evaluation.py
index 12dec5410c4..bf6d106a08e 100644
--- a/lib/galaxy/tools/evaluation.py
+++ b/lib/galaxy/tools/evaluation.py
@@ -5,10 +5,10 @@ import re
import shlex
import string
import tempfile
+from collections.abc import Callable
from datetime import datetime
from typing import (
Any,
- Callable,
Literal,
Optional,
TYPE_CHECKING,
diff --git a/lib/galaxy/tools/execute.py b/lib/galaxy/tools/execute.py
index f445e5fe0d5..8a0e9ae9796 100644
--- a/lib/galaxy/tools/execute.py
+++ b/lib/galaxy/tools/execute.py
@@ -8,17 +8,17 @@ import collections
import logging
import typing
from abc import abstractmethod
+from collections.abc import Callable
from typing import (
Any,
- Callable,
NamedTuple,
Optional,
+ TypeAlias,
Union,
)
from boltons.iterutils import remap
from packaging.version import Version
-from typing_extensions import TypeAlias
from galaxy import model
from galaxy.exceptions import ToolInputsNotOKException
diff --git a/lib/galaxy/tools/fetch/workbooks.py b/lib/galaxy/tools/fetch/workbooks.py
index 52d44c1f36f..1e509b152bf 100644
--- a/lib/galaxy/tools/fetch/workbooks.py
+++ b/lib/galaxy/tools/fetch/workbooks.py
@@ -1,5 +1,6 @@
from dataclasses import dataclass
from typing import (
+ Literal,
Optional,
Union,
)
@@ -9,7 +10,6 @@ from pydantic import (
BaseModel,
Field,
)
-from typing_extensions import Literal
from galaxy.exceptions import RequestParameterInvalidException
from galaxy.model.dataset_collections.auto_identifiers import (
diff --git a/lib/galaxy/tools/parameters/cancelable_request.py b/lib/galaxy/tools/parameters/cancelable_request.py
index 38566237964..635760e0449 100644
--- a/lib/galaxy/tools/parameters/cancelable_request.py
+++ b/lib/galaxy/tools/parameters/cancelable_request.py
@@ -2,11 +2,11 @@ import asyncio
import logging
from typing import (
Any,
+ Literal,
Optional,
)
import aiohttp
-from typing_extensions import Literal
log = logging.getLogger()
diff --git a/lib/galaxy/tools/parameters/dynamic_options.py b/lib/galaxy/tools/parameters/dynamic_options.py
index ba4e7d15e3f..69ee4431744 100644
--- a/lib/galaxy/tools/parameters/dynamic_options.py
+++ b/lib/galaxy/tools/parameters/dynamic_options.py
@@ -15,11 +15,10 @@ from typing import (
Any,
cast,
get_args,
+ Literal,
Optional,
)
-from typing_extensions import Literal
-
from galaxy.model import (
DatasetCollectionElement,
HistoryDatasetAssociation,
diff --git a/lib/galaxy/tools/parameters/grouping.py b/lib/galaxy/tools/parameters/grouping.py
index b69ae48bde4..eb525a8c848 100644
--- a/lib/galaxy/tools/parameters/grouping.py
+++ b/lib/galaxy/tools/parameters/grouping.py
@@ -6,11 +6,13 @@ import io
import logging
import os
import unicodedata
-from collections.abc import Mapping
+from collections.abc import (
+ Callable,
+ Mapping,
+)
from math import inf
from typing import (
Any,
- Callable,
Optional,
TYPE_CHECKING,
)
diff --git a/lib/galaxy/tools/remote_tool_eval.py b/lib/galaxy/tools/remote_tool_eval.py
index 2d6064c5496..6cde4936535 100644
--- a/lib/galaxy/tools/remote_tool_eval.py
+++ b/lib/galaxy/tools/remote_tool_eval.py
@@ -3,8 +3,8 @@ import os
import shutil
import tempfile
import traceback
+from collections.abc import Callable
from typing import (
- Callable,
NamedTuple,
)
diff --git a/lib/galaxy/tools/wrappers.py b/lib/galaxy/tools/wrappers.py
index c303a694ea1..9b276694b36 100644
--- a/lib/galaxy/tools/wrappers.py
+++ b/lib/galaxy/tools/wrappers.py
@@ -15,12 +15,12 @@ from typing import (
cast,
Optional,
TYPE_CHECKING,
+ TypeAlias,
Union,
)
from typing_extensions import (
Self,
- TypeAlias,
)
from galaxy.model import (
diff --git a/lib/galaxy/visualization/data_providers/registry.py b/lib/galaxy/visualization/data_providers/registry.py
index ba802629d3c..ba03f8f08b8 100644
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -1,10 +1,9 @@
from typing import (
+ Literal,
Optional,
Union,
)
-from typing_extensions import Literal
-
from galaxy.datatypes.data import (
Data,
Newick,
diff --git a/lib/galaxy/visualization/plugins/resource_parser.py b/lib/galaxy/visualization/plugins/resource_parser.py
index 173da37e281..af24e3c8e01 100644
--- a/lib/galaxy/visualization/plugins/resource_parser.py
+++ b/lib/galaxy/visualization/plugins/resource_parser.py
@@ -6,8 +6,8 @@ a dictionary of string data/ids (often from a query string).
import json
import logging
import weakref
+from collections.abc import Callable
from typing import (
- Callable,
Optional,
Union,
)
diff --git a/lib/galaxy/web/framework/middleware/remoteuser.py b/lib/galaxy/web/framework/middleware/remoteuser.py
index 8e150917e43..7139311d491 100644
--- a/lib/galaxy/web/framework/middleware/remoteuser.py
+++ b/lib/galaxy/web/framework/middleware/remoteuser.py
@@ -67,7 +67,7 @@ class RemoteUser:
if self.display_servers and "REMOTE_ADDR" in environ:
try:
host = socket.gethostbyaddr(environ["REMOTE_ADDR"])[0]
- except (OSError, socket.herror, socket.gaierror, socket.timeout):
+ except (OSError, socket.herror, socket.gaierror):
# in the event of a lookup failure, deny access
host = None
if host in self.display_servers:
diff --git a/lib/galaxy/web_stack/__init__.py b/lib/galaxy/web_stack/__init__.py
index b2c74d3c500..44accd7ba68 100644
--- a/lib/galaxy/web_stack/__init__.py
+++ b/lib/galaxy/web_stack/__init__.py
@@ -5,8 +5,8 @@ import multiprocessing
import os
import sys
import threading
+from collections.abc import Callable
from typing import (
- Callable,
Optional,
TYPE_CHECKING,
)
diff --git a/lib/galaxy/web_stack/handlers.py b/lib/galaxy/web_stack/handlers.py
index debe0e1ffde..0ee037dbf0f 100644
--- a/lib/galaxy/web_stack/handlers.py
+++ b/lib/galaxy/web_stack/handlers.py
@@ -8,13 +8,15 @@ import logging
import os
import random
from collections.abc import (
+ Callable,
Iterable,
Sequence,
)
from enum import Enum
from typing import (
Any,
- Callable,
+ Concatenate,
+ Literal,
Protocol,
TYPE_CHECKING,
TypeVar,
@@ -22,10 +24,6 @@ from typing import (
)
from sqlalchemy.orm import object_session
-from typing_extensions import (
- Concatenate,
- Literal,
-)
from galaxy.exceptions import HandlerAssignmentError
from galaxy.util import (
diff --git a/lib/galaxy/webapps/base/controller.py b/lib/galaxy/webapps/base/controller.py
index 215f63c6b5f..ac7a605b1cc 100644
--- a/lib/galaxy/webapps/base/controller.py
+++ b/lib/galaxy/webapps/base/controller.py
@@ -3,9 +3,9 @@ Contains functionality needed in every web interface
"""
import logging
+from collections.abc import Callable
from typing import (
Any,
- Callable,
)
from webob.exc import (
diff --git a/lib/galaxy/webapps/base/webapp.py b/lib/galaxy/webapps/base/webapp.py
index 9fdd44724f3..70276f05b26 100644
--- a/lib/galaxy/webapps/base/webapp.py
+++ b/lib/galaxy/webapps/base/webapp.py
@@ -721,7 +721,7 @@ class GalaxyWebTransaction(base.DefaultWebTransaction, context.ProvidesHistoryCo
if self.app.datatypes_registry.get_display_sites("ucsc") and self.request.path == display_as:
try:
host = socket.gethostbyaddr(self.environ["REMOTE_ADDR"])[0]
- except (OSError, socket.herror, socket.gaierror, socket.timeout):
+ except (OSError, socket.herror, socket.gaierror):
host = None
if host in UCSC_SERVERS:
return
diff --git a/lib/galaxy/webapps/galaxy/api/__init__.py b/lib/galaxy/webapps/galaxy/api/__init__.py
index f3a57ee407c..fcc32ac9650 100644
--- a/lib/galaxy/webapps/galaxy/api/__init__.py
+++ b/lib/galaxy/webapps/galaxy/api/__init__.py
@@ -3,13 +3,16 @@ This module *does not* contain API routes. It exclusively contains dependencies
"""
import inspect
-from collections.abc import AsyncGenerator
+from collections.abc import (
+ AsyncGenerator,
+ Callable,
+)
from enum import Enum
from string import Template
from typing import (
Any,
- Callable,
cast,
+ Literal,
NamedTuple,
Optional,
TypeVar,
@@ -56,7 +59,6 @@ from starlette.routing import (
NoMatchFound,
)
from starlette.types import Scope
-from typing_extensions import Literal
try:
from starlette_context import context as request_context
diff --git a/lib/galaxy/webapps/galaxy/services/credentials.py b/lib/galaxy/webapps/galaxy/services/credentials.py
index 619ab4cbdb1..9b7977c75db 100644
--- a/lib/galaxy/webapps/galaxy/services/credentials.py
+++ b/lib/galaxy/webapps/galaxy/services/credentials.py
@@ -1,6 +1,6 @@
+from collections.abc import Callable
from typing import (
Any,
- Callable,
cast,
Optional,
Union,
diff --git a/lib/galaxy/webapps/galaxy/services/dataset_collections.py b/lib/galaxy/webapps/galaxy/services/dataset_collections.py
index ec3d927bdb6..243ddd2c1e5 100644
--- a/lib/galaxy/webapps/galaxy/services/dataset_collections.py
+++ b/lib/galaxy/webapps/galaxy/services/dataset_collections.py
@@ -1,6 +1,7 @@
from io import BytesIO
from logging import getLogger
from typing import (
+ Literal,
Optional,
TYPE_CHECKING,
Union,
@@ -13,7 +14,6 @@ from pydantic import (
RootModel,
ValidationError,
)
-from typing_extensions import Literal
from galaxy import exceptions
from galaxy.datatypes.registry import Registry
diff --git a/lib/galaxy/webapps/galaxy/services/history_contents.py b/lib/galaxy/webapps/galaxy/services/history_contents.py
index 8b80da54e22..dec28c6a815 100644
--- a/lib/galaxy/webapps/galaxy/services/history_contents.py
+++ b/lib/galaxy/webapps/galaxy/services/history_contents.py
@@ -5,6 +5,7 @@ from collections.abc import Iterable
from typing import (
Any,
cast,
+ Literal,
Optional,
TYPE_CHECKING,
Union,
@@ -16,7 +17,6 @@ from pydantic import (
Field,
)
from typing_extensions import (
- Literal,
Protocol,
)
diff --git a/lib/galaxy/webapps/openapi/_compat/v2.py b/lib/galaxy/webapps/openapi/_compat/v2.py
index ad6c5ea57ca..7327e4ca440 100644
--- a/lib/galaxy/webapps/openapi/_compat/v2.py
+++ b/lib/galaxy/webapps/openapi/_compat/v2.py
@@ -2,6 +2,7 @@ from collections.abc import Sequence
from typing import (
Any,
cast,
+ Literal,
Union,
)
@@ -18,7 +19,6 @@ from pydantic.json_schema import (
GenerateJsonSchema as GenerateJsonSchema,
JsonSchemaValue as JsonSchemaValue,
)
-from typing_extensions import Literal
def get_definitions(
diff --git a/lib/galaxy/work/context.py b/lib/galaxy/work/context.py
index 67aae7c9f2f..5ea9805d781 100644
--- a/lib/galaxy/work/context.py
+++ b/lib/galaxy/work/context.py
@@ -1,12 +1,11 @@
import abc
from typing import (
Any,
+ Literal,
Optional,
TYPE_CHECKING,
)
-from typing_extensions import Literal
-
from galaxy.managers.context import ProvidesHistoryContext
if TYPE_CHECKING:
diff --git a/lib/galaxy/workflow/refactor/schema.py b/lib/galaxy/workflow/refactor/schema.py
index 1ed82e902ec..edef0d8b8b5 100644
--- a/lib/galaxy/workflow/refactor/schema.py
+++ b/lib/galaxy/workflow/refactor/schema.py
@@ -2,6 +2,7 @@ from enum import Enum
from typing import (
Annotated,
Any,
+ Literal,
Optional,
Union,
)
@@ -10,9 +11,6 @@ from pydantic import (
BaseModel,
Field,
)
-from typing_extensions import (
- Literal,
-)
LABEL_DESCRIPTION = "The unique label of the step being referenced."
INPUT_NAME_DESCRIPTION = "The input name as defined by the workflow module corresponding to the step being referenced. For Galaxy tool steps these inputs should be normalized using '|' (e.g. 'cond|repeat_0|input')."
diff --git a/lib/galaxy_test/api/test_drs.py b/lib/galaxy_test/api/test_drs.py
index 5859e2ecbe0..757bc5a691e 100644
--- a/lib/galaxy_test/api/test_drs.py
+++ b/lib/galaxy_test/api/test_drs.py
@@ -1,7 +1,5 @@
import tempfile
-from typing import (
- Callable,
-)
+from collections.abc import Callable
from unittest import SkipTest
from urllib.parse import (
urljoin,
diff --git a/lib/galaxy_test/base/decorators.py b/lib/galaxy_test/base/decorators.py
index 95ea1a18ab2..1bf4555014c 100644
--- a/lib/galaxy_test/base/decorators.py
+++ b/lib/galaxy_test/base/decorators.py
@@ -12,10 +12,12 @@ histories, libraries, etc... should be annotated ideally.
import os
import unittest
from functools import wraps
-from typing import Union
+from typing import (
+ Literal,
+ Union,
+)
import pytest
-from typing_extensions import Literal
KnownRequirementT = Union[
Literal["admin"],
diff --git a/lib/galaxy_test/base/populators.py b/lib/galaxy_test/base/populators.py
index 429d6bd91cb..392bc1f59bc 100644
--- a/lib/galaxy_test/base/populators.py
+++ b/lib/galaxy_test/base/populators.py
@@ -52,14 +52,17 @@ from abc import (
ABCMeta,
abstractmethod,
)
-from collections.abc import Generator
+from collections.abc import (
+ Callable,
+ Generator,
+)
from functools import wraps
from io import StringIO
from operator import itemgetter
from typing import (
Any,
- Callable,
cast,
+ Literal,
NamedTuple,
Optional,
Union,
@@ -82,7 +85,6 @@ from pydantic import (
from requests import Response
from rocrate.rocrate import ROCrate
from typing_extensions import (
- Literal,
Self,
TypedDict,
)
diff --git a/lib/galaxy_test/base/uses_shed_api.py b/lib/galaxy_test/base/uses_shed_api.py
index 597920cb5fd..e53ac075b4d 100644
--- a/lib/galaxy_test/base/uses_shed_api.py
+++ b/lib/galaxy_test/base/uses_shed_api.py
@@ -1,7 +1,7 @@
import abc
+from collections.abc import Callable
from typing import (
Any,
- Callable,
Optional,
)
from unittest import SkipTest
diff --git a/lib/galaxy_test/selenium/test_workflow_run.py b/lib/galaxy_test/selenium/test_workflow_run.py
index 793c26051b6..31334e166ad 100644
--- a/lib/galaxy_test/selenium/test_workflow_run.py
+++ b/lib/galaxy_test/selenium/test_workflow_run.py
@@ -1,10 +1,10 @@
import json
+from typing import Literal
from uuid import uuid4
import yaml
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
-from typing_extensions import Literal
from galaxy_test.base import rules_test_data
from galaxy_test.base.workflow_fixtures import (
diff --git a/lib/tool_shed/managers/categories.py b/lib/tool_shed/managers/categories.py
index 6b62c91fea9..a2b84135c4d 100644
--- a/lib/tool_shed/managers/categories.py
+++ b/lib/tool_shed/managers/categories.py
@@ -1,6 +1,6 @@
+from collections.abc import Callable
from typing import (
Any,
- Callable,
)
from sqlalchemy import select
diff --git a/lib/tool_shed/managers/repositories.py b/lib/tool_shed/managers/repositories.py
index 0cdc2d50ec1..e92f5e0d85a 100644
--- a/lib/tool_shed/managers/repositories.py
+++ b/lib/tool_shed/managers/repositories.py
@@ -5,10 +5,10 @@ Manager and Serializer for TS repositories.
import json
import logging
from collections import namedtuple
+from collections.abc import Callable
from time import strftime
from typing import (
Any,
- Callable,
cast,
Optional,
Union,
diff --git a/lib/tool_shed/metadata/repository_metadata_manager.py b/lib/tool_shed/metadata/repository_metadata_manager.py
index 13031959ff7..5c26eb70f10 100644
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -799,14 +799,24 @@ class RepositoryMetadataManager(ToolShedMetadataGenerator):
metadata_dict = None
ancestor_changeset_revision = None
ancestor_metadata_dict = None
- for changeset in self.repository.get_changesets_for_setting_metadata(self.app):
- work_dir = tempfile.mkdtemp(prefix="tmp-toolshed-ramorits")
- ctx = repo[changeset]
- log.debug("Cloning repository changeset revision: %s", str(ctx.rev()))
- assert self.repository_clone_url
- repository_clone_url = repository_clone_url or self.repository_clone_url
- cloned_ok, error_message = hg_util.clone_repository(repository_clone_url, work_dir, str(ctx.rev()))
- if cloned_ok:
+
+ # Clone repository once, then update for each changeset revision.
+ work_dir = tempfile.mkdtemp(prefix="tmp-toolshed-ramorits")
+ assert self.repository_clone_url
+ repository_clone_url = repository_clone_url or self.repository_clone_url
+ log.debug("Cloning repository for metadata reset")
+ cloned_ok, error_message = hg_util.clone_repository(repository_clone_url, work_dir)
+ if not cloned_ok:
+ log.error(f"Failed to clone repository: {error_message}")
+ basic_util.remove_dir(work_dir)
+ self._clean_repository_metadata(changeset_revisions)
+ return
+
+ try:
+ for changeset in self.repository.get_changesets_for_setting_metadata(self.app):
+ ctx = repo[changeset]
+ log.debug("Updating to changeset revision: %s", str(ctx.rev()))
+ hg_util.update_repository(work_dir, str(ctx.rev()))
log.debug("Generating metadata for changeset revision: %s", str(ctx.rev()))
self.set_changeset_revision(str(ctx))
self.set_repository_files_dir(work_dir)
@@ -823,11 +833,11 @@ class RepositoryMetadataManager(ToolShedMetadataGenerator):
# self.SUBSET - ancestor metadata is a subset of current metadata, so continue from current
# self.NOT_EQUAL_AND_NOT_SUBSET - ancestor metadata is neither equal to nor a subset of current
# metadata, so persist ancestor metadata.
- log.info(f"amd {ancestor_metadata_dict}")
+ log.debug(f"amd {ancestor_metadata_dict}")
comparison = self.compare_changeset_revisions(
ancestor_changeset_revision, ancestor_metadata_dict
)
- log.info(f"comparison {comparison}")
+ log.debug(f"comparison {comparison}")
if comparison in [self.NO_METADATA, self.EQUAL, self.SUBSET]:
ancestor_changeset_revision = self.changeset_revision
ancestor_metadata_dict = self.metadata_dict
@@ -858,6 +868,7 @@ class RepositoryMetadataManager(ToolShedMetadataGenerator):
changeset_revisions.append(metadata_changeset_revision)
ancestor_changeset_revision = None
ancestor_metadata_dict = None
+ finally:
basic_util.remove_dir(work_dir)
# Delete all repository_metadata records for this repository that do not have a changeset_revision
# value in changeset_revisions.
diff --git a/lib/tool_shed/test/base/api_util.py b/lib/tool_shed/test/base/api_util.py
index 30df5c37033..ae84e29e96c 100644
--- a/lib/tool_shed/test/base/api_util.py
+++ b/lib/tool_shed/test/base/api_util.py
@@ -1,15 +1,15 @@
import os
import re
+from collections.abc import Callable
from functools import wraps
from typing import (
Any,
- Callable,
+ Literal,
Optional,
)
from urllib.parse import urljoin
import requests
-from typing_extensions import Literal
from galaxy_test.base.api_asserts import (
assert_has_keys,
diff --git a/lib/tool_shed/test/functional/conftest.py b/lib/tool_shed/test/functional/conftest.py
index d0bcaf78508..c35efde18f3 100644
--- a/lib/tool_shed/test/functional/conftest.py
+++ b/lib/tool_shed/test/functional/conftest.py
@@ -1,7 +1,7 @@
import os
-from collections.abc import Generator
-from typing import (
+from collections.abc import (
Callable,
+ Generator,
)
import pytest
diff --git a/lib/tool_shed/webapp/api/groups.py b/lib/tool_shed/webapp/api/groups.py
index ea5b88e657d..aa89e3ba2e4 100644
--- a/lib/tool_shed/webapp/api/groups.py
+++ b/lib/tool_shed/webapp/api/groups.py
@@ -1,7 +1,5 @@
import logging
-from typing import (
- Callable,
-)
+from collections.abc import Callable
from sqlalchemy import select
diff --git a/lib/tool_shed/webapp/api/repositories.py b/lib/tool_shed/webapp/api/repositories.py
index 1534d34b6a5..1d3256c69cb 100644
--- a/lib/tool_shed/webapp/api/repositories.py
+++ b/lib/tool_shed/webapp/api/repositories.py
@@ -1,11 +1,9 @@
import json
import logging
import os
+from collections.abc import Callable
from io import StringIO
from time import strftime
-from typing import (
- Callable,
-)
from webob.compat import cgi_FieldStorage
diff --git a/lib/tool_shed/webapp/api/repository_revisions.py b/lib/tool_shed/webapp/api/repository_revisions.py
index aee7c1076d0..9aed99467bb 100644
--- a/lib/tool_shed/webapp/api/repository_revisions.py
+++ b/lib/tool_shed/webapp/api/repository_revisions.py
@@ -1,7 +1,5 @@
import logging
-from typing import (
- Callable,
-)
+from collections.abc import Callable
from sqlalchemy import select
diff --git a/lib/tool_shed/webapp/controllers/repository.py b/lib/tool_shed/webapp/controllers/repository.py
index 4d8f2a4c612..c4bbb712266 100644
--- a/lib/tool_shed/webapp/controllers/repository.py
+++ b/lib/tool_shed/webapp/controllers/repository.py
@@ -4,10 +4,9 @@ import os
import string
import tempfile
from datetime import date
+from typing import Any
from mercurial import (
- cmdutil,
- commands,
mdiff,
patch,
)
@@ -74,15 +73,15 @@ malicious_error = " This changeset cannot be downloaded because it potentially
malicious_error_can_push = " Correct this changeset as soon as possible, it potentially produces malicious behavior or contains inappropriate content."
-def get_mercurial_default_options_dict(command):
- """Borrowed from repoman - get default parameters for a mercurial command."""
- possible = cmdutil.findpossible(command, commands.table)
- # Mercurial >= 3.4 returns a tuple whose first element is the old return dict
- if type(possible) is tuple:
- possible = possible[0]
- if len(possible) != 1:
- raise Exception(f'unable to find mercurial command "{command}"')
- return {r[1].replace(b"-", b"_"): r[2] for r in next(iter(possible.values()))[1][1]}
+def get_mercurial_default_options_dict(command: str) -> dict[str, Any]:
+ """Get default parameters for a mercurial command."""
+ # Use mdiff.diffopts defaults directly instead of introspecting command table
+ # (the old cmdutil.findpossible API was removed in Mercurial 7.2)
+ if command == "diff":
+ # Convert byte keys to strings but preserve value types (int, bool)
+ # as mdiff.diffopts expects properly typed values
+ return {(k.decode("utf-8") if isinstance(k, bytes) else k): v for k, v in mdiff.diffopts.defaults.items()}
+ raise Exception(f'unable to find mercurial command "{command}"')
class RepositoryController(BaseUIController, ratings_util.ItemRatings):
@@ -2366,10 +2365,8 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings):
else:
ctx_child = None
diffs = []
- options_dict = get_mercurial_default_options_dict(b"diff")
- # Not quite sure if the following settings make any difference, but with a combination of them and the size check on each
- # diff, we don't run out of memory when viewing the changelog of the cisortho2 repository on the test tool shed.
- options_dict = {util.unicodify(k): util.unicodify(v) for k, v in options_dict.items()}
+ # Get default diff options with string keys and properly typed values
+ options_dict = get_mercurial_default_options_dict("diff")
options_dict["maxfile"] = basic_util.MAXDIFFSIZE
options_dict["maxtotal"] = basic_util.MAXDIFFSIZE
diffopts = mdiff.diffopts(**options_dict)
diff --git a/lib/tool_shed/webapp/framework/middleware/remoteuser.py b/lib/tool_shed/webapp/framework/middleware/remoteuser.py
index fff7395b228..73b4a033a44 100644
--- a/lib/tool_shed/webapp/framework/middleware/remoteuser.py
+++ b/lib/tool_shed/webapp/framework/middleware/remoteuser.py
@@ -52,7 +52,7 @@ class RemoteUser:
if self.display_servers and "REMOTE_ADDR" in environ:
try:
host = socket.gethostbyaddr(environ["REMOTE_ADDR"])[0]
- except (OSError, socket.herror, socket.gaierror, socket.timeout):
+ except (OSError, socket.herror, socket.gaierror):
# in the event of a lookup failure, deny access
host = None
if host in self.display_servers:
diff --git a/lib/tool_shed/webapp/model/migrations/alembic/env.py b/lib/tool_shed/webapp/model/migrations/alembic/env.py
index 04f4769df4c..1245260b50e 100644
--- a/lib/tool_shed/webapp/model/migrations/alembic/env.py
+++ b/lib/tool_shed/webapp/model/migrations/alembic/env.py
@@ -1,6 +1,6 @@
import logging
+from collections.abc import Callable
from typing import (
- Callable,
cast,
)
diff --git a/lib/tool_shed_client/schema/__init__.py b/lib/tool_shed_client/schema/__init__.py
index 1fe5e92890e..62cd8582b74 100644
--- a/lib/tool_shed_client/schema/__init__.py
+++ b/lib/tool_shed_client/schema/__init__.py
@@ -1,5 +1,6 @@
from typing import (
Any,
+ Literal,
Optional,
Union,
)
@@ -11,7 +12,6 @@ from pydantic import (
RootModel,
)
from typing_extensions import (
- Literal,
TypedDict,
)
diff --git a/packages/app/setup.cfg b/packages/app/setup.cfg
index a8d1aab0bc4..e5463ab0e2c 100644
--- a/packages/app/setup.cfg
+++ b/packages/app/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -83,8 +82,7 @@ install_requires =
WebOb>=1.8.9
Whoosh
packages = find:
-python_requires = >=3.9
-
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/auth/setup.cfg b/packages/auth/setup.cfg
index 8de84944002..50be0e6d7cc 100644
--- a/packages/auth/setup.cfg
+++ b/packages/auth/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -36,8 +35,7 @@ install_requires =
galaxy-data
galaxy-util
packages = find:
-python_requires = >=3.9
-
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/config/setup.cfg b/packages/config/setup.cfg
index b14aa426151..64c32e32a49 100644
--- a/packages/config/setup.cfg
+++ b/packages/config/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -39,12 +38,12 @@ install_requires =
pykwalify
PyYAML
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
pytest
- gravity @ git+https://github.com/nsoranzo/gravity.git@python3.14
+ gravity>=1.2.0
[options.entry_points]
console_scripts =
diff --git a/packages/data/setup.cfg b/packages/data/setup.cfg
index 7688f40af7d..dd66573c4e3 100644
--- a/packages/data/setup.cfg
+++ b/packages/data/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -67,8 +66,7 @@ install_requires =
tifffile
typing-extensions
packages = find:
-python_requires = >=3.9
-
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/files/setup.cfg b/packages/files/setup.cfg
index 8be26ed4ffa..00aeea918b0 100644
--- a/packages/files/setup.cfg
+++ b/packages/files/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -39,7 +38,7 @@ install_requires =
typing-extensions
fsspec
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/job_execution/setup.cfg b/packages/job_execution/setup.cfg
index a5f6b3cc879..184fefcb320 100644
--- a/packages/job_execution/setup.cfg
+++ b/packages/job_execution/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -41,7 +40,7 @@ install_requires =
MarkupSafe
SQLAlchemy>=2.0.37,<2.1,!=2.0.41
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/meta/setup.cfg b/packages/meta/setup.cfg
index 76920ecaece..cf3c7ffc0cf 100644
--- a/packages/meta/setup.cfg
+++ b/packages/meta/setup.cfg
@@ -10,7 +10,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -35,7 +34,7 @@ version = 25.1.dev0
[options]
include_package_data = True
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
install_requires = file: requirements.txt
[options.extras_require]
diff --git a/packages/navigation/setup.cfg b/packages/navigation/setup.cfg
index 34272a9810c..2f98ba69c62 100644
--- a/packages/navigation/setup.cfg
+++ b/packages/navigation/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -41,7 +40,7 @@ install_requires =
PyYAML
seletools
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.packages.find]
exclude =
diff --git a/packages/pyproject.toml b/packages/pyproject.toml
index c88224144d2..b715463b6a4 100644
--- a/packages/pyproject.toml
+++ b/packages/pyproject.toml
@@ -2,7 +2,7 @@
name = "galaxy-meta-package"
version = "0.0.0"
description = "Meta package stub (not a real package)"
-requires-python = ">=3.9"
+requires-python = ">=3.10"
dependencies = []
[tool.uv]
diff --git a/packages/schema/setup.cfg b/packages/schema/setup.cfg
index 321e3b5d8f0..a7a34374f5d 100644
--- a/packages/schema/setup.cfg
+++ b/packages/schema/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -36,7 +35,7 @@ install_requires =
galaxy-util
pydantic[email]>=2.7.4
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/selenium/setup.cfg b/packages/selenium/setup.cfg
index c827528df7a..9b43f67eaea 100644
--- a/packages/selenium/setup.cfg
+++ b/packages/selenium/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -41,7 +40,7 @@ install_requires =
selenium!=4.11.0,!=4.11.1,!=4.11.2
playwright
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/test_api/setup.cfg b/packages/test_api/setup.cfg
index e155e793e76..8344f74656e 100644
--- a/packages/test_api/setup.cfg
+++ b/packages/test_api/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -39,7 +38,7 @@ install_requires =
requests
tuspy
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
driver =
diff --git a/packages/test_base/setup.cfg b/packages/test_base/setup.cfg
index 07aa7e5fc85..b8592f53237 100644
--- a/packages/test_base/setup.cfg
+++ b/packages/test_base/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -44,7 +43,7 @@ install_requires =
requests
jsonschema
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/test_driver/setup.cfg b/packages/test_driver/setup.cfg
index b8928e3d232..3f4d57a8b90 100644
--- a/packages/test_driver/setup.cfg
+++ b/packages/test_driver/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -42,7 +41,7 @@ install_requires =
galaxy-web-apps
pytest
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/test_selenium/setup.cfg b/packages/test_selenium/setup.cfg
index 4513e653046..1a9d0c7703d 100644
--- a/packages/test_selenium/setup.cfg
+++ b/packages/test_selenium/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -44,7 +43,7 @@ install_requires =
requests
selenium!=4.11.0,!=4.11.1,!=4.11.2
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
driver =
diff --git a/packages/tool_shed/setup.cfg b/packages/tool_shed/setup.cfg
index ce03b3d453d..1b1e45dc9bb 100644
--- a/packages/tool_shed/setup.cfg
+++ b/packages/tool_shed/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -58,7 +57,7 @@ install_requires =
WebOb
Whoosh
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/tool_shed_schema/setup.cfg b/packages/tool_shed_schema/setup.cfg
index 0037fccb48d..cf223a9d157 100644
--- a/packages/tool_shed_schema/setup.cfg
+++ b/packages/tool_shed_schema/setup.cfg
@@ -9,8 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.8
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -38,7 +36,7 @@ install_requires =
pydantic>=2.7.4
typing-extensions
packages = find:
-python_requires = >=3.8
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/tours/setup.cfg b/packages/tours/setup.cfg
index 743c8c464c4..ee0552b54bb 100644
--- a/packages/tours/setup.cfg
+++ b/packages/tours/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -37,7 +36,7 @@ install_requires =
pydantic>=2.7.4
PyYAML
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.entry_points]
console_scripts =
diff --git a/packages/web_apps/setup.cfg b/packages/web_apps/setup.cfg
index 06e8f0849f6..76625ee1ea5 100644
--- a/packages/web_apps/setup.cfg
+++ b/packages/web_apps/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -68,7 +67,7 @@ install_requires =
uvloop>=0.21.0
WebOb>=1.8.9
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/web_client/setup.cfg b/packages/web_client/setup.cfg
index d96f6eeca27..b1ad9d9709c 100644
--- a/packages/web_client/setup.cfg
+++ b/packages/web_client/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -33,7 +32,7 @@ version = 25.1.dev0
[options]
include_package_data = True
packages = galaxy.web_client
-python_requires = >=3.9
+python_requires = >=3.10
[options.entry_points]
console_scripts =
diff --git a/packages/web_framework/setup.cfg b/packages/web_framework/setup.cfg
index f5c15567349..97a95a06966 100644
--- a/packages/web_framework/setup.cfg
+++ b/packages/web_framework/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -45,7 +44,7 @@ install_requires =
WebOb
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/packages/web_stack/setup.cfg b/packages/web_stack/setup.cfg
index 17bbf6008d4..7532c6d525c 100644
--- a/packages/web_stack/setup.cfg
+++ b/packages/web_stack/setup.cfg
@@ -9,7 +9,6 @@ classifiers =
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
@@ -37,7 +36,7 @@ install_requires =
galaxy-util
SQLAlchemy>=2.0.37,<2.1,!=2.0.41
packages = find:
-python_requires = >=3.9
+python_requires = >=3.10
[options.extras_require]
test =
diff --git a/pyproject.toml b/pyproject.toml
index 2fadca4969e..45107f67afa 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -10,7 +10,7 @@ maintainers = [
]
license = {file = "LICENSE.txt"}
readme = "README.rst"
-requires-python = ">=3.9"
+requires-python = ">=3.10"
dependencies = [
"a2wsgi",
"aiofiles",
@@ -41,7 +41,7 @@ dependencies = [
"fissix",
"fs",
"future>=1.0.0", # Python 3.12 support
- "gravity @ git+https://github.com/nsoranzo/gravity.git@python3.14", # Python 3.14 support
+ "gravity>=1.2.0", # Python 3.14 support
"gunicorn",
"gxformat2>=0.21.0",
"h5grove>=1.2.1",
@@ -57,7 +57,8 @@ dependencies = [
"Mako",
"Markdown",
"MarkupSafe",
- "mercurial>=6.8.2", # Python 3.13 support
+ "mercurial>=6.8.2 ; python_version<'3.14'", # Python 3.13 support
+ "mercurial>=7.2rc0 ; python_version>='3.14'", # Python 3.14 support
"mrcfile",
"more-itertools",
"msal",
@@ -190,7 +191,6 @@ typecheck = [
[tool.black]
line-length = 120
-target-version = ['py39']
include = '\.pyi?$'
extend-exclude = '''
^/(
@@ -203,7 +203,6 @@ extend-exclude = '''
isort = true
[tool.ruff]
-target-version = "py39"
exclude = [
"lib/tool_shed/test/test_data/repos"
]
@@ -219,7 +218,8 @@ select = ["E", "F", "B", "C4", "G", "ISC", "NPY", "UP"]
# E402 module level import not at top of file # TODO, we would like to improve this.
# E501 is line length (delegated to black)
# G* are TODOs
-ignore = ["B008", "B9", "E402", "E501", "G001", "G002", "G004"]
+# UP007, UP045: Python >=3.10 type annotation improvements, to be revisited later
+ignore = ["B008", "B9", "E402", "E501", "G001", "G002", "G004", "UP007", "UP045"]
[tool.ruff.lint.flake8-comprehensions]
allow-dict-calls-with-keyword-arguments = true
diff --git a/scripts/check_python.py b/scripts/check_python.py
index b3fec2eb98f..79f4d2d7241 100644
--- a/scripts/check_python.py
+++ b/scripts/check_python.py
@@ -7,7 +7,7 @@ from __future__ import print_function
import sys
-MIN_VERSION_TUPLE = (3, 9)
+MIN_VERSION_TUPLE = (3, 10)
def check_python():
diff --git a/scripts/common_startup.sh b/scripts/common_startup.sh
index 1f3359391e1..10b6b351327 100755
--- a/scripts/common_startup.sh
+++ b/scripts/common_startup.sh
@@ -12,7 +12,7 @@ SET_VENV=1
SKIP_CLIENT_BUILD=${GALAXY_SKIP_CLIENT_BUILD:-0}
INSTALL_PREBUILT_CLIENT=${GALAXY_INSTALL_PREBUILT_CLIENT:-0}
: "${PNPM_INSTALL_OPTS:=--frozen-lockfile}"
-: "${GALAXY_CONDA_PYTHON_VERSION:=3.9}"
+: "${GALAXY_CONDA_PYTHON_VERSION:=3.10}"
for arg in "$@"; do
if [ "$arg" = "--skip-venv" ]; then
@@ -37,7 +37,7 @@ RMFILES="
lib/pkg_resources.pyc
"
-MIN_PYTHON_VERSION=3.9
+MIN_PYTHON_VERSION=3.10
MIN_PIP_VERSION=20.3
# return true if $1 is in $2 else false
diff --git a/test/functional/tools/output_filter.xml b/test/functional/tools/output_filter.xml
index 584f2f43cf3..d54c3f8ae93 100644
--- a/test/functional/tools/output_filter.xml
+++ b/test/functional/tools/output_filter.xml
@@ -9,13 +9,54 @@ echo '5' > 5 &&
echo 'p1.forward' > p1.forward &&
echo 'p1.reverse' > p1.reverse &&
echo 'p2.forward' > p2.forward &&
-echo 'p2.reverse' > p2.reverse
+echo 'p2.reverse' > p2.reverse
+#for $r in $repeat
+ #if $r.cond.select == "a" and $r.cond.inner_cond.inner_select == "2"
+ && echo "$r.cond.inner_cond.text" >> repeat_cond.txt
+ #end if
+#end for
]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -34,6 +75,9 @@ echo 'p2.reverse' > p2.reverse
produce_paired_collection is True
+
+ any( [ r["cond"]["select"] == "a" and r["cond"]["inner_cond"]["inner_select"] == "2" for r in repeat ] )
+
@@ -98,6 +142,15 @@ echo 'p2.reverse' > p2.reverse
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/integration/test_container_resolvers.py b/test/integration/test_container_resolvers.py
index a92d00d64bc..4e3fdcfb4ca 100644
--- a/test/integration/test_container_resolvers.py
+++ b/test/integration/test_container_resolvers.py
@@ -4,12 +4,12 @@ import re
from typing import (
Any,
ClassVar,
+ Literal,
Optional,
TYPE_CHECKING,
)
from typing_extensions import (
- Literal,
Protocol,
)
diff --git a/test/integration/test_kubernetes_runner.py b/test/integration/test_kubernetes_runner.py
index 8e64168d7f4..43507c45545 100644
--- a/test/integration/test_kubernetes_runner.py
+++ b/test/integration/test_kubernetes_runner.py
@@ -11,12 +11,12 @@ import subprocess
import tempfile
import time
from typing import (
+ Literal,
Optional,
overload,
)
import pytest
-from typing_extensions import Literal
from galaxy.model import Job
from galaxy.tool_util.verify.wait import timeout_type
diff --git a/test/integration/test_purge_datasets.py b/test/integration/test_purge_datasets.py
index 8fb165e8954..363245397c1 100644
--- a/test/integration/test_purge_datasets.py
+++ b/test/integration/test_purge_datasets.py
@@ -1,6 +1,6 @@
import os
+from collections.abc import Callable
from typing import (
- Callable,
Optional,
)
diff --git a/test/unit/app/managers/test_user_file_sources.py b/test/unit/app/managers/test_user_file_sources.py
index cc849865360..f817ab5ec39 100644
--- a/test/unit/app/managers/test_user_file_sources.py
+++ b/test/unit/app/managers/test_user_file_sources.py
@@ -884,4 +884,4 @@ class MockExceptionResponse:
self._exception_msg = exception_msg
def raise_for_status(self):
- raise HTTPError(self._exception_msg, self._exception_msg, response=None) # type: ignore[arg-type,unused-ignore] # Fixed in types-requests 2.31.0.9 , which requires Python >=3.9 via urllib3 >=2
+ raise HTTPError(self._exception_msg, self._exception_msg, response=None)
diff --git a/test/unit/data/model/test_model_store.py b/test/unit/data/model/test_model_store.py
index f6fea192def..56ff5e6e0b9 100644
--- a/test/unit/data/model/test_model_store.py
+++ b/test/unit/data/model/test_model_store.py
@@ -660,23 +660,12 @@ def validate_invocation_collection_crate_directory(crate_directory):
def validate_with_roc_validator(crate_directory, profile):
- # roc-validator changed the ValidationSettings argument data_path to rocrate_uri in
- # v5.0.0+, but also dropped support for Python 3.9
- if sys.version_info >= (3, 10):
- settings = services.ValidationSettings(
- rocrate_uri=crate_directory,
- profile_identifier=profile,
- requirement_severity=models.Severity.REQUIRED,
- abort_on_first=False, # do not stop on first issue
- )
- else:
- settings = services.ValidationSettings(
- data_path=crate_directory,
- profile_identifier=profile,
- requirement_severity=models.Severity.REQUIRED,
- abort_on_first=False, # do not stop on first issue
- http_cache_timeout=0, # do not use cache
- )
+ settings = services.ValidationSettings(
+ rocrate_uri=crate_directory,
+ profile_identifier=profile,
+ requirement_severity=models.Severity.REQUIRED,
+ abort_on_first=False, # do not stop on first issue
+ )
result = services.validate(settings)
diff --git a/test/unit/files/_base.py b/test/unit/files/_base.py
index bd5c55e979f..13336570382 100644
--- a/test/unit/files/_base.py
+++ b/test/unit/files/_base.py
@@ -14,9 +14,9 @@ from abc import (
ABC,
abstractmethod,
)
+from collections.abc import Callable
from typing import (
Any,
- Callable,
Optional,
)
diff --git a/test/unit/selenium/util.py b/test/unit/selenium/util.py
index fa7f13dbe2f..20142ac9b2e 100644
--- a/test/unit/selenium/util.py
+++ b/test/unit/selenium/util.py
@@ -1,7 +1,7 @@
"""Pytest-specific utility functions and decorators for selenium unit tests."""
+from collections.abc import Callable
from typing import (
- Callable,
TypeVar,
Union,
)