From 1dfa4dce6dc6558b5c0d515bb0b1789c20ec3d5a Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Mon, 22 Dec 2025 13:51:45 +0100 Subject: [PATCH 01/14] Add function test for filtering outputs in repeats --- test/functional/tools/output_filter.xml | 71 ++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) 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 + + + + + + + + + @@ -147,5 +200,21 @@ echo 'p2.reverse' > p2.reverse + + + + + + + + + + + + + + + + From a4cd192617848fa4a4c8688337968f167a3fea81 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Fri, 18 Apr 2025 10:30:46 -0400 Subject: [PATCH 02/14] Add form directory input on blur as well as enter; ensure valid though. --- client/src/components/Form/Elements/FormDirectory.vue | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/src/components/Form/Elements/FormDirectory.vue b/client/src/components/Form/Elements/FormDirectory.vue index 4040d5d5241..29f12722a3f 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" /> @@ -158,6 +159,14 @@ export default { } this.$emit("input", url); }, + handleBlur() { + if (this.currentDirectoryName && this.isValidName) { + const newFolder = this.currentDirectoryName; + this.pathChunks.push({ pathChunk: newFolder, editable: true }); + this.currentDirectoryName = ""; + } + this.updateURL(); + }, }, }; From 09e85bdfdbca4f71eb30808d87c7e6f4f41fa138 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Fri, 18 Apr 2025 10:36:41 -0400 Subject: [PATCH 03/14] Minor refactoring to form directory element --- .../Form/Elements/FormDirectory.vue | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/client/src/components/Form/Elements/FormDirectory.vue b/client/src/components/Form/Elements/FormDirectory.vue index 29f12722a3f..a57ab446ddc 100644 --- a/client/src/components/Form/Elements/FormDirectory.vue +++ b/client/src/components/Form/Elements/FormDirectory.vue @@ -140,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) { @@ -159,14 +170,6 @@ export default { } this.$emit("input", url); }, - handleBlur() { - if (this.currentDirectoryName && this.isValidName) { - const newFolder = this.currentDirectoryName; - this.pathChunks.push({ pathChunk: newFolder, editable: true }); - this.currentDirectoryName = ""; - } - this.updateURL(); - }, }, }; From 93aa658198fbbb98e85deb09eaf6f5f137717153 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Wed, 14 Jan 2026 11:12:36 -0500 Subject: [PATCH 04/14] verify path is added on blur and fix test data mutation --- .../Form/Elements/FormDirectory.test.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) 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}`); + }); }); From 02e2b7901597ccd717188d017a4b0c6021a616fc Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Thu, 15 Jan 2026 23:13:59 +0000 Subject: [PATCH 05/14] Use ``fail-on-cache-miss`` when restoring the client cache built by the `build_client.yaml` GitHub workflow. Galaxy would fail anyway at startup when trying to build the cache due to missing `node`, but the reason for the error would be less clear. --- .github/workflows/first_startup.yaml | 1 + .github/workflows/integration_selenium.yaml | 1 + .github/workflows/osx_startup.yaml | 1 + .github/workflows/playwright.yaml | 1 + .github/workflows/selenium.yaml | 1 + 5 files changed, 5 insertions(+) diff --git a/.github/workflows/first_startup.yaml b/.github/workflows/first_startup.yaml index 2fb478fa8bb..f77b42c9926 100644 --- a/.github/workflows/first_startup.yaml +++ b/.github/workflows/first_startup.yaml @@ -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/integration_selenium.yaml b/.github/workflows/integration_selenium.yaml index 468a1792ae5..0a157255b4c 100644 --- a/.github/workflows/integration_selenium.yaml +++ b/.github/workflows/integration_selenium.yaml @@ -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/osx_startup.yaml b/.github/workflows/osx_startup.yaml index 259f91e972d..c21b004ad10 100644 --- a/.github/workflows/osx_startup.yaml +++ b/.github/workflows/osx_startup.yaml @@ -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/playwright.yaml b/.github/workflows/playwright.yaml index 2d1f246b131..76aca43d266 100644 --- a/.github/workflows/playwright.yaml +++ b/.github/workflows/playwright.yaml @@ -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/selenium.yaml b/.github/workflows/selenium.yaml index 7820aad9110..ce697e2e35f 100644 --- a/.github/workflows/selenium.yaml +++ b/.github/workflows/selenium.yaml @@ -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 From 0e90fac766c2503530885d0f63b531f847c2f257 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Sat, 17 Jan 2026 18:02:56 +0000 Subject: [PATCH 06/14] Update to gravity 1.2.0 --- lib/galaxy/config/config_manage.py | 2 +- lib/galaxy/dependencies/pinned-requirements.txt | 2 +- packages/config/setup.cfg | 2 +- pyproject.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/galaxy/config/config_manage.py b/lib/galaxy/config/config_manage.py index 144cb38a199..10bfd0ba105 100644 --- a/lib/galaxy/config/config_manage.py +++ b/lib/galaxy/config/config_manage.py @@ -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/dependencies/pinned-requirements.txt b/lib/galaxy/dependencies/pinned-requirements.txt index a2f63503124..2f9a0dc0321 100644 --- a/lib/galaxy/dependencies/pinned-requirements.txt +++ b/lib/galaxy/dependencies/pinned-requirements.txt @@ -111,7 +111,7 @@ 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' googleapis-common-protos==1.72.0 -gravity @ git+https://github.com/nsoranzo/gravity.git@7c5f457424658ee904694f5566e61b562bce7ed6 +gravity==1.2.0 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' diff --git a/packages/config/setup.cfg b/packages/config/setup.cfg index b14aa426151..420b54a80ba 100644 --- a/packages/config/setup.cfg +++ b/packages/config/setup.cfg @@ -44,7 +44,7 @@ python_requires = >=3.9 [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/pyproject.toml b/pyproject.toml index 22254a0f480..ba6c1842475 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", From ace6cdbbc17ee78950ef3abbf31c0f82a315aad5 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Sun, 18 Jan 2026 13:43:17 +0000 Subject: [PATCH 07/14] Rebuild config samples and docs with `make config-rebuild` --- doc/source/admin/galaxy_options.rst | 8 +-- lib/galaxy/config/sample/galaxy.yml.sample | 55 +++++++++++++++---- lib/galaxy/config/sample/tool_shed.yml.sample | 6 ++ 3 files changed, 54 insertions(+), 15 deletions(-) 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/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 From 7f640f69ab05ca7e16ac370dfc68687af24e2821 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Mon, 19 Jan 2026 10:51:54 +0100 Subject: [PATCH 08/14] Fix race condition in workflow collection populated state check The `expire_populated_state()` method was only expiring the SQLAlchemy `populated_state` attribute but not clearing the cached `_populated_optimized` value. This caused a race condition during workflow scheduling: 1. `populated_optimized` was called and cached False (nested collection NEW) 2. Job thread marked the nested collection as OK 3. `waiting_for_elements` saw the new state (OK) and returned False 4. `expire_populated_state()` was called but didn't clear the cache 5. Second `populated` check returned the stale cached False 6. Workflow incorrectly failed with collection_failed The fix ensures the cached value is cleared so the second populated check gets fresh database state, preventing spurious collection_failed errors for collections that are actively being populated. Fixes flaky test: test_workflow_list_list_multi_data_map_over --- lib/galaxy/model/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 9172543e7e5..4f64900339a 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -6892,6 +6892,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): From eb9fde1dcd273ee775361f61d3296d146ae609ef Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Mon, 5 Jan 2026 23:37:30 +0000 Subject: [PATCH 09/14] Drop support for Python 3.9 --- .circleci/config.yml | 4 ++-- .github/workflows/api.yaml | 2 +- .github/workflows/bioblend.yaml | 2 +- .github/workflows/check_test_class_names.yaml | 2 +- .github/workflows/converter_tests.yaml | 2 +- .github/workflows/cwl_conformance.yaml | 2 +- .github/workflows/db_indexes.yaml | 4 ++-- .github/workflows/dependencies.yaml | 2 +- .github/workflows/deployment.yaml | 2 +- .github/workflows/docs.yaml | 2 +- .github/workflows/first_startup.yaml | 2 +- .github/workflows/framework_tools.yaml | 2 +- .github/workflows/framework_workflows.yaml | 2 +- .github/workflows/integration.yaml | 2 +- .github/workflows/integration_selenium.yaml | 2 +- .github/workflows/lint.yaml | 2 +- .github/workflows/lint_openapi_schema.yml | 2 +- .github/workflows/main_tools.yaml | 2 +- .github/workflows/mulled.yaml | 2 +- .github/workflows/osx_startup.yaml | 2 +- .github/workflows/performance.yaml | 2 +- .github/workflows/playwright.yaml | 2 +- .github/workflows/publish_artifacts.yaml | 2 +- .github/workflows/selenium.yaml | 2 +- .github/workflows/test_galaxy_packages.yaml | 2 +- .github/workflows/toolshed.yaml | 2 +- .github/workflows/unit-postgres.yaml | 2 +- .github/workflows/unit.yaml | 2 +- Makefile | 4 ++-- README.rst | 4 ++-- doc/source/admin/python.md | 2 +- lib/galaxy/agents/base.py | 2 +- lib/galaxy/app.py | 2 +- lib/galaxy/authnz/psa_authnz.py | 10 +------- lib/galaxy/celery/__init__.py | 2 +- lib/galaxy/celery/tasks.py | 2 +- lib/galaxy/config/__init__.py | 2 +- lib/galaxy/config/config_manage.py | 2 +- lib/galaxy/datatypes/blast.py | 2 +- lib/galaxy/datatypes/data.py | 4 ++-- .../display_applications/parameters.py | 2 +- lib/galaxy/datatypes/images.py | 2 +- lib/galaxy/datatypes/molecules.py | 2 +- lib/galaxy/datatypes/msa.py | 2 +- lib/galaxy/datatypes/sequence.py | 6 +++-- lib/galaxy/datatypes/sniff.py | 6 +++-- lib/galaxy/datatypes/spaln.py | 2 +- lib/galaxy/files/__init__.py | 2 +- lib/galaxy/files/sources/azure.py | 2 +- lib/galaxy/files/sources/invenio.py | 2 +- lib/galaxy/files/templates/models.py | 2 +- lib/galaxy/job_execution/container_monitor.py | 2 +- lib/galaxy/job_execution/output_collect.py | 2 +- lib/galaxy/jobs/__init__.py | 6 +++-- lib/galaxy/jobs/job_destination.py | 5 +--- lib/galaxy/jobs/mapper.py | 2 +- lib/galaxy/jobs/runners/drmaa.py | 3 +-- .../jobs/runners/util/cli/job/__init__.py | 3 +-- lib/galaxy/managers/base.py | 2 +- lib/galaxy/managers/collections.py | 2 +- lib/galaxy/managers/context.py | 2 +- lib/galaxy/managers/histories.py | 2 +- lib/galaxy/managers/pages.py | 2 +- lib/galaxy/managers/workflows.py | 4 +--- lib/galaxy/model/__init__.py | 4 ++-- .../types/sample_sheet_workbook.py | 2 +- lib/galaxy/model/migrations/alembic/env.py | 2 +- lib/galaxy/model/store/__init__.py | 2 +- lib/galaxy/model/store/discover.py | 6 +++-- .../model/tool_shed_install/__init__.py | 2 +- .../unittest_utils/model_testing_utils.py | 6 +++-- lib/galaxy/queue_worker.py | 2 +- lib/galaxy/quota/_schema.py | 2 +- lib/galaxy/schema/fetch_data.py | 2 +- lib/galaxy/schema/fields.py | 6 ++--- lib/galaxy/schema/groups.py | 6 +++-- lib/galaxy/schema/history.py | 2 +- lib/galaxy/schema/invocation.py | 2 +- lib/galaxy/schema/jobs.py | 2 +- lib/galaxy/schema/library_contents.py | 4 +--- lib/galaxy/schema/notifications.py | 4 +--- lib/galaxy/schema/schema.py | 4 ++-- lib/galaxy/schema/storage_cleaner.py | 2 +- lib/galaxy/schema/types.py | 4 +--- lib/galaxy/schema/visualization.py | 2 +- lib/galaxy/schema/workflow/comments.py | 2 +- lib/galaxy/security/__init__.py | 3 +-- lib/galaxy/selenium/axe_results.py | 2 +- lib/galaxy/selenium/has_driver_protocol.py | 2 +- lib/galaxy/tools/_types.py | 3 +-- lib/galaxy/tools/evaluation.py | 2 +- lib/galaxy/tools/execute.py | 4 ++-- lib/galaxy/tools/fetch/workbooks.py | 2 +- .../tools/parameters/cancelable_request.py | 2 +- .../tools/parameters/dynamic_options.py | 3 +-- lib/galaxy/tools/parameters/grouping.py | 6 +++-- lib/galaxy/tools/remote_tool_eval.py | 2 +- lib/galaxy/tools/wrappers.py | 2 +- .../visualization/data_providers/registry.py | 3 +-- .../visualization/plugins/resource_parser.py | 2 +- .../web/framework/middleware/remoteuser.py | 2 +- lib/galaxy/web_stack/__init__.py | 2 +- lib/galaxy/web_stack/handlers.py | 8 +++---- lib/galaxy/webapps/base/controller.py | 2 +- lib/galaxy/webapps/base/webapp.py | 2 +- lib/galaxy/webapps/galaxy/api/__init__.py | 8 ++++--- .../webapps/galaxy/services/credentials.py | 2 +- .../galaxy/services/dataset_collections.py | 2 +- .../galaxy/services/history_contents.py | 2 +- lib/galaxy/webapps/openapi/_compat/v2.py | 2 +- lib/galaxy/work/context.py | 3 +-- lib/galaxy/workflow/refactor/schema.py | 4 +--- lib/galaxy_test/api/test_drs.py | 4 +--- lib/galaxy_test/base/decorators.py | 6 +++-- lib/galaxy_test/base/populators.py | 8 ++++--- lib/galaxy_test/base/uses_shed_api.py | 2 +- lib/galaxy_test/selenium/test_workflow_run.py | 2 +- lib/tool_shed/managers/categories.py | 2 +- lib/tool_shed/managers/repositories.py | 2 +- lib/tool_shed/test/base/api_util.py | 4 ++-- lib/tool_shed/test/functional/conftest.py | 4 ++-- lib/tool_shed/webapp/api/groups.py | 4 +--- lib/tool_shed/webapp/api/repositories.py | 4 +--- .../webapp/api/repository_revisions.py | 4 +--- .../webapp/framework/middleware/remoteuser.py | 2 +- .../webapp/model/migrations/alembic/env.py | 2 +- lib/tool_shed_client/schema/__init__.py | 2 +- packages/app/setup.cfg | 4 +--- packages/auth/setup.cfg | 4 +--- packages/config/setup.cfg | 3 +-- packages/data/setup.cfg | 4 +--- packages/files/setup.cfg | 3 +-- packages/job_execution/setup.cfg | 3 +-- packages/meta/setup.cfg | 3 +-- packages/navigation/setup.cfg | 3 +-- packages/pyproject.toml | 2 +- packages/schema/setup.cfg | 3 +-- packages/selenium/setup.cfg | 3 +-- packages/test_api/setup.cfg | 3 +-- packages/test_base/setup.cfg | 3 +-- packages/test_driver/setup.cfg | 3 +-- packages/test_selenium/setup.cfg | 3 +-- packages/tool_shed/setup.cfg | 3 +-- packages/tool_shed_schema/setup.cfg | 4 +--- packages/tours/setup.cfg | 3 +-- packages/web_apps/setup.cfg | 3 +-- packages/web_client/setup.cfg | 3 +-- packages/web_framework/setup.cfg | 3 +-- packages/web_stack/setup.cfg | 3 +-- pyproject.toml | 7 +++--- scripts/check_python.py | 2 +- scripts/common_startup.sh | 4 ++-- test/integration/test_container_resolvers.py | 2 +- test/integration/test_kubernetes_runner.py | 2 +- test/integration/test_purge_datasets.py | 2 +- .../app/managers/test_user_file_sources.py | 2 +- test/unit/data/model/test_model_store.py | 23 +++++-------------- test/unit/files/_base.py | 2 +- test/unit/selenium/util.py | 2 +- 159 files changed, 212 insertions(+), 269 deletions(-) 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 f77b42c9926..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} 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 0a157255b4c..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 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 c21b004ad10..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} 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 76aca43d266..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: 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 ce697e2e35f..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: 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/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 10bfd0ba105..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, ) 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 8fd9a56c502..7b0e102bc1b 100644 --- a/lib/galaxy/datatypes/images.py +++ b/lib/galaxy/datatypes/images.py @@ -10,6 +10,7 @@ import struct from collections.abc import Iterator from typing import ( Any, + Literal, Optional, Union, ) @@ -18,7 +19,6 @@ import mrcfile import numpy as np import png 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/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 5512092aabb..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, ) 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/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/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/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 420b54a80ba..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,7 +38,7 @@ install_requires = pykwalify PyYAML packages = find: -python_requires = >=3.9 +python_requires = >=3.10 [options.extras_require] test = diff --git a/packages/data/setup.cfg b/packages/data/setup.cfg index eb15f2a311b..d31edbd7805 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 @@ -66,8 +65,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 688156fd7d3..2fb14ee95ad 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", @@ -189,7 +189,6 @@ typecheck = [ [tool.black] line-length = 120 -target-version = ['py39'] include = '\.pyi?$' extend-exclude = ''' ^/( @@ -202,7 +201,6 @@ extend-exclude = ''' isort = true [tool.ruff] -target-version = "py39" exclude = [ "lib/tool_shed/test/test_data/repos" ] @@ -218,7 +216,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/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, ) From 57cc11250879cb7630c6277d4b070fe91c6ac87a Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Fri, 9 Jan 2026 14:18:54 +0000 Subject: [PATCH 10/14] Update dependencies after dropping Python 3.9 support --- lib/galaxy/dependencies/dev-requirements.txt | 185 ++++++-------- .../dependencies/pinned-requirements.txt | 227 +++++++----------- .../dependencies/pinned-test-requirements.txt | 162 ++++++------- .../pinned-typecheck-requirements.txt | 6 +- 4 files changed, 243 insertions(+), 337 deletions(-) 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 2f9a0dc0321..c90ddd41590 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==1.2.0 -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' +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,35 +122,32 @@ 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 mistralai==1.9.11 @@ -179,73 +158,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 pydot==4.0.1 pyeventsystem==0.1.0 pyfaidx==0.9.0.3 @@ -261,20 +229,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 @@ -285,45 +251,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' @@ -331,20 +290,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 From d3bad8ed1ff8d404fb5a1ee03ff55bbdd962c3ee Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Mon, 19 Jan 2026 19:03:38 +0100 Subject: [PATCH 11/14] Require Mercurial 7.2rc0 for Python 3.14 support Mercurial 7.2rc0 is the first release with Python 3.14 support. Running 7.1.2 on Python 3.14 causes significant performance issues that lead to test timeouts. Use version markers to specify 7.2rc0 for Python 3.14+ while keeping 7.1.2 for earlier Python versions. --- lib/galaxy/dependencies/pinned-requirements.txt | 3 ++- pyproject.toml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/galaxy/dependencies/pinned-requirements.txt b/lib/galaxy/dependencies/pinned-requirements.txt index 2f9a0dc0321..83fe9855306 100644 --- a/lib/galaxy/dependencies/pinned-requirements.txt +++ b/lib/galaxy/dependencies/pinned-requirements.txt @@ -170,7 +170,8 @@ markdown-it-py==4.0.0 ; python_full_version >= '3.11' markupsafe==3.0.3 mcp==1.25.0 ; python_full_version >= '3.10' 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 diff --git a/pyproject.toml b/pyproject.toml index 688156fd7d3..4b32d1a3485 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", From c147814793243a936e6b4ea82a7b74f256926392 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Mon, 19 Jan 2026 19:03:49 +0100 Subject: [PATCH 12/14] Fix Mercurial 7.2 API compatibility for cmdutil.findpossible The cmdutil.findpossible function was removed in Mercurial 7.2. Instead of introspecting the command table to get diff defaults, use mdiff.diffopts.defaults directly which is more stable. --- .../webapp/controllers/repository.py | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/tool_shed/webapp/controllers/repository.py b/lib/tool_shed/webapp/controllers/repository.py index 4d8f2a4c612..1ff9d9d9718 100644 --- a/lib/tool_shed/webapp/controllers/repository.py +++ b/lib/tool_shed/webapp/controllers/repository.py @@ -6,8 +6,6 @@ import tempfile from datetime import date from mercurial import ( - cmdutil, - commands, mdiff, patch, ) @@ -75,14 +73,14 @@ malicious_error_can_push = " Correct this changeset as soon as possible, it pot 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]} + """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 == b"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 +2364,8 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): else: ctx_child = None diffs = [] + # Get default diff options with string keys and properly typed values 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()} options_dict["maxfile"] = basic_util.MAXDIFFSIZE options_dict["maxtotal"] = basic_util.MAXDIFFSIZE diffopts = mdiff.diffopts(**options_dict) From 4364049db52d4e55240d38a9d31ecb7f26502d82 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Mon, 19 Jan 2026 19:03:57 +0100 Subject: [PATCH 13/14] Optimize metadata reset to clone repository once Previously, reset_all_metadata_on_repository_in_tool_shed() cloned the repository separately for each changeset revision over HTTP. With 6 changesets at ~6-7 seconds per clone, this took ~40 seconds total, exceeding Playwright's 30-second timeout. Now clone the repository once and use hg update to switch between revisions. This reduces 6 network round-trips to 1, making the operation complete well within the timeout. --- .../tool_shed/metadata/metadata_generator.py | 4 ++- .../metadata/repository_metadata_manager.py | 31 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) 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/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. From 8e048715f6230915cd9cd9bac7e76014fad35424 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Tue, 20 Jan 2026 09:10:03 +0100 Subject: [PATCH 14/14] Add type annotation to get_mercurial_default_options_dict --- lib/tool_shed/webapp/controllers/repository.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/tool_shed/webapp/controllers/repository.py b/lib/tool_shed/webapp/controllers/repository.py index 1ff9d9d9718..c4bbb712266 100644 --- a/lib/tool_shed/webapp/controllers/repository.py +++ b/lib/tool_shed/webapp/controllers/repository.py @@ -4,6 +4,7 @@ import os import string import tempfile from datetime import date +from typing import Any from mercurial import ( mdiff, @@ -72,11 +73,11 @@ 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): +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 == b"diff": + 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()} @@ -2365,7 +2366,7 @@ class RepositoryController(BaseUIController, ratings_util.ItemRatings): ctx_child = None diffs = [] # Get default diff options with string keys and properly typed values - options_dict = get_mercurial_default_options_dict(b"diff") + 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)