diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index 829afddd204b..5e985ee7407d 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -6655,7 +6655,11 @@ export interface components { state_ids: { [key: string]: string[]; }; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Update Time * Format: date-time @@ -6742,7 +6746,11 @@ export interface components { * @description Whether this item has been permanently removed. */ purged: boolean; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Update Time * Format: date-time @@ -7956,9 +7964,9 @@ export interface components { collection_type?: string | null; /** * Column Definitions - * @description Specify definitions for row data if collection_type if sample_sheet + * @description Specify definitions for row data if collection_type is sample_sheet */ - column_definitions?: components["schemas"]["SampleSheetColumnDefinition"][] | null; + column_definitions?: components["schemas"]["SampleSheetColumnDefinition-Input"][] | null; /** * Content * @description Depending on the `source` it can be: @@ -8187,9 +8195,9 @@ export interface components { collection_type?: string | null; /** * Column Definitions - * @description Specify definitions for row data if collection_type if sample_sheet + * @description Specify definitions for row data if collection_type is sample_sheet */ - column_definitions?: components["schemas"]["SampleSheetColumnDefinition"][] | null; + column_definitions?: components["schemas"]["SampleSheetColumnDefinition-Input"][] | null; /** * Copy Elements * @description Whether to create a copy of the source HDAs for the new collection. @@ -8552,7 +8560,13 @@ export interface components { /** Message */ message: string; }; - /** CustomArchivedHistoryView */ + /** + * CustomArchivedHistoryView + * @description Archived History Response with all optional fields. + * + * It is used for serializing only specific attributes using the "keys" + * query parameter. + */ CustomArchivedHistoryView: { /** * Annotation @@ -8604,8 +8618,9 @@ export interface components { /** * Genome Build * @description TODO + * @default ? */ - genome_build?: string | null; + genome_build: string | null; /** * History ID * @example 0123456789ABCDEF @@ -8676,7 +8691,11 @@ export interface components { state_ids?: { [key: string]: string[]; } | null; - tags?: components["schemas"]["TagCollection"] | null; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags?: string[] | null; /** * Update Time * @description The last time and date this item was updated. @@ -8782,7 +8801,14 @@ export interface components { */ installed_builds: components["schemas"]["LabelValuePair"][]; }; - /** CustomHistoryView */ + /** + * CustomHistoryView + * @description History Response with all optional fields. + * + * It is used for serializing only specific attributes using the "keys" + * query parameter. Unfortunately, we cannot know the exact fields that + * will be requested, so we have to allow all fields to be optional. + */ CustomHistoryView: { /** * Annotation @@ -8829,8 +8855,9 @@ export interface components { /** * Genome Build * @description TODO + * @default ? */ - genome_build?: string | null; + genome_build: string | null; /** * History ID * @example 0123456789ABCDEF @@ -8901,7 +8928,11 @@ export interface components { state_ids?: { [key: string]: string[]; } | null; - tags?: components["schemas"]["TagCollection"] | null; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags?: string[] | null; /** * Update Time * @description The last time and date this item was updated. @@ -9544,7 +9575,11 @@ export interface components { * @constant */ model_class: "HistoryDatasetCollectionAssociation"; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; }; /** * DatasetCollectionContentElements @@ -11060,6 +11095,8 @@ export interface components { type: | ("File" | "null" | "boolean" | "int" | "float" | "string") | ("File" | "null" | "boolean" | "int" | "float" | "string")[]; + } & { + [key: string]: unknown; }; /** FileDataElement */ FileDataElement: { @@ -11238,7 +11275,11 @@ export interface components { * @description The current state of this dataset. */ state: components["schemas"]["DatasetState"]; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * @description discriminator enum property added by openapi-typescript * @enum {string} @@ -11692,7 +11733,7 @@ export interface components { /** Collection Type */ collection_type?: string | null; /** Column Definitions */ - column_definitions?: components["schemas"]["SampleSheetColumnDefinition"][] | null; + column_definitions?: components["schemas"]["SampleSheetColumnDefinition-Input"][] | null; destination: components["schemas"]["HdcaDestination"]; /** Ftp Path */ ftp_path: string; @@ -11978,7 +12019,10 @@ export interface components { */ type: "group_tag"; }; - /** GroupUpdatePayload */ + /** + * GroupUpdatePayload + * @description Payload schema for updating a group. + */ GroupUpdatePayload: { /** name of the group */ name?: string | null; @@ -12018,7 +12062,13 @@ export interface components { /** Name */ name: string; }; - /** HDACustom */ + /** + * HDACustom + * @description Can contain any serializable property of an HDA. + * + * Allows arbitrary custom keys to be specified in the serialization + * parameters without a particular view (predefined set of keys). + */ HDACustom: { /** * Accessible @@ -12034,8 +12084,10 @@ export interface components { * API Type * @deprecated * @description TODO + * @default file + * @constant */ - api_type?: "file" | null; + api_type: "file"; /** * Copied From History Dataset Association Id * @description ID of HDA this HDA was copied from. @@ -12122,8 +12174,9 @@ export interface components { /** * Genome Build * @description TODO + * @default ? */ - genome_build?: string | null; + genome_build: string | null; /** * Hashes * @description The list of hashes associated with this dataset. @@ -12132,8 +12185,9 @@ export interface components { /** * HDA or LDDA * @description Whether this dataset belongs to a history (HDA) or a library (LDDA). + * @default hda */ - hda_ldda?: components["schemas"]["DatasetSourceType"] | null; + hda_ldda: components["schemas"]["DatasetSourceType"]; /** * HID * @description The index position of this item in the History. @@ -12225,12 +12279,18 @@ export interface components { * @description The current state of this dataset. */ state?: components["schemas"]["DatasetState"] | null; - tags?: components["schemas"]["TagCollection"] | null; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags?: string[] | null; /** * Type * @description This is always `file` for datasets. + * @default file + * @constant */ - type?: "file" | null; + type: "file"; /** * Type - ID * @description The type and the encoded ID of this item. Used for caching. @@ -12488,7 +12548,11 @@ export interface components { * @description The current state of this dataset. */ state: components["schemas"]["DatasetState"]; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Type * @description This is always `file` for datasets. @@ -12588,7 +12652,11 @@ export interface components { * @description The current state of this dataset. */ state: components["schemas"]["DatasetState"]; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Type * @description The type of this item. @@ -12735,7 +12803,11 @@ export interface components { * @description The current state of this dataset. */ state: components["schemas"]["DatasetState"]; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Type * @description The type of this item. @@ -12763,7 +12835,13 @@ export interface components { */ visible: boolean; }; - /** HDCACustom */ + /** + * HDCACustom + * @description Can contain any serializable property of an HDCA. + * + * Allows arbitrary custom keys to be specified in the serialization + * parameters without a particular view (predefined set of keys). + */ HDCACustom: { /** * Dataset Collection ID @@ -12779,7 +12857,7 @@ export interface components { * Column Definitions * @description Column data associated with each element of this collection. */ - column_definitions?: components["schemas"]["SampleSheetColumnDefinition"][] | null; + column_definitions?: components["schemas"]["SampleSheetColumnDefinition-Output"][] | null; /** * Contents URL * @description The relative URL to access the contents of this History. @@ -12803,8 +12881,9 @@ export interface components { /** * Elements * @description The summary information of each of the elements inside the dataset collection. + * @default [] */ - elements?: components["schemas"]["DCESummary"][] | null; + elements: components["schemas"]["DCESummary"][]; /** * Elements Datatypes * @description A set containing all the different element datatypes in the collection. @@ -12872,7 +12951,7 @@ export interface components { * Populated * @description Whether the dataset collection elements (and any subcollections elements) were successfully populated. */ - populated?: boolean | null; + populated?: boolean; /** * Populated State * @description Indicates the general state of the elements in the dataset collection:- 'new': new dataset collection, unpopulated elements.- 'ok': collection elements populated (HDAs may or may not have errors).- 'failed': some problem populating, won't be populated. @@ -12888,12 +12967,18 @@ export interface components { * @description A list of objects containing the object store ID and the oldest creation time of the datasets stored in that object store for this collection.This is used to determine the age of the datasets in the collection when the object store is short-lived. */ store_times_summary?: components["schemas"]["OldestCreateTimeByObjectStoreId"][] | null; - tags?: components["schemas"]["TagCollection"] | null; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags?: string[] | null; /** * Type * @description This is always `collection` for dataset collections. + * @default collection + * @constant */ - type?: "collection" | null; + type: "collection"; /** * Type - ID * @description The type and the encoded ID of this item. Used for caching. @@ -12935,7 +13020,7 @@ export interface components { * Column Definitions * @description Column data associated with each element of this collection. */ - column_definitions?: components["schemas"]["SampleSheetColumnDefinition"][] | null; + column_definitions?: components["schemas"]["SampleSheetColumnDefinition-Output"][] | null; /** * Contents URL * @description The relative URL to access the contents of this History. @@ -13047,7 +13132,11 @@ export interface components { * @description A list of objects containing the object store ID and the oldest creation time of the datasets stored in that object store for this collection.This is used to determine the age of the datasets in the collection when the object store is short-lived. */ store_times_summary?: components["schemas"]["OldestCreateTimeByObjectStoreId"][] | null; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Type * @description This is always `collection` for dataset collections. @@ -13187,7 +13276,11 @@ export interface components { * @description A list of objects containing the object store ID and the oldest creation time of the datasets stored in that object store for this collection.This is used to determine the age of the datasets in the collection when the object store is short-lived. */ store_times_summary?: components["schemas"]["OldestCreateTimeByObjectStoreId"][] | null; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Type * @description This is always `collection` for dataset collections. @@ -13335,7 +13428,7 @@ export interface components { /** Collection Type */ collection_type?: string | null; /** Column Definitions */ - column_definitions?: components["schemas"]["SampleSheetColumnDefinition"][] | null; + column_definitions?: components["schemas"]["SampleSheetColumnDefinition-Input"][] | null; destination: components["schemas"]["HdcaDestination"]; /** Ftp Path */ ftp_path?: string | null; @@ -13366,7 +13459,7 @@ export interface components { /** Collection Type */ collection_type?: string | null; /** Column Definitions */ - column_definitions?: components["schemas"]["SampleSheetColumnDefinition"][] | null; + column_definitions?: components["schemas"]["SampleSheetColumnDefinition-Input"][] | null; destination: components["schemas"]["HdcaDestination"]; /** Elements */ elements: ( @@ -13951,7 +14044,11 @@ export interface components { state_ids: { [key: string]: string[]; }; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Update Time * Format: date-time @@ -14036,7 +14133,11 @@ export interface components { * @description Whether this item has been permanently removed. */ purged: boolean; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Update Time * Format: date-time @@ -15454,7 +15555,7 @@ export interface components { * Item tags * @description The list of tags that will replace the current tags associated with the item. */ - item_tags?: components["schemas"]["TagCollection"] | null; + item_tags?: string[] | null; }; /** * ItemTagsResponse @@ -16510,7 +16611,11 @@ export interface components { peek: string | null; /** State */ state: string; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** Update Time */ update_time: string; /** Uploaded By */ @@ -17803,7 +17908,11 @@ export interface components { * @description The identifying slug for the page URL, must be unique. */ slug: string; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Title * @description The name of the page. @@ -17884,7 +17993,11 @@ export interface components { * @description The identifying slug for the page URL, must be unique. */ slug: string; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Title * @description The name of the page. @@ -19387,7 +19500,35 @@ export interface components { type: "rules"; }; /** SampleSheetColumnDefinition */ - SampleSheetColumnDefinition: { + "SampleSheetColumnDefinition-Input": { + /** Default Value */ + default_value?: number | boolean | string | null; + /** Description */ + description?: string | null; + /** Name */ + name: string; + /** Optional */ + optional: boolean; + /** Restrictions */ + restrictions?: (number | boolean | string | null)[] | null; + /** Suggestions */ + suggestions?: (number | boolean | string | null)[] | null; + /** + * Type + * @enum {string} + */ + type: "string" | "int" | "float" | "boolean" | "element_identifier"; + /** Validators */ + validators?: + | { + [key: string]: unknown; + }[] + | null; + } & { + [key: string]: unknown; + }; + /** SampleSheetColumnDefinition */ + "SampleSheetColumnDefinition-Output": { /** Default Value */ default_value?: number | boolean | string | null; /** Description */ @@ -20556,7 +20697,11 @@ export interface components { | components["schemas"]["ToolStep"] | components["schemas"]["SubworkflowStep"]; }; - tags: components["schemas"]["TagCollection"]; + /** + * Tags + * @description The collection of tags associated with an item. + */ + tags: string[]; /** * Update Time * Format: date-time @@ -20661,11 +20806,6 @@ export interface components { * @enum {string} */ SupportedType: "None" | "BasicAuth" | "BearerAuth" | "PassportAuth"; - /** - * TagCollection - * @description Represents the collection of tags associated with an item. - */ - TagCollection: string[]; /** TagOperationParams */ TagOperationParams: { /** Tags */ @@ -21482,7 +21622,7 @@ export interface components { * Tags * @description A list of tags to add to this item. */ - tags?: components["schemas"]["TagCollection"] | null; + tags?: string[] | null; /** * Visible * @description Whether this item is visible in the history. @@ -21509,7 +21649,8 @@ export interface components { published?: boolean | null; /** Purged */ purged?: boolean | null; - tags?: components["schemas"]["TagCollection"] | null; + /** Tags */ + tags?: string[] | null; }; /** UpdateInstancePayload */ UpdateInstancePayload: { @@ -22647,7 +22788,7 @@ export interface components { * Tags * @description A list of tags to add to this item. */ - tags?: components["schemas"]["TagCollection"] | null; + tags?: string[] | null; /** * Title * @description The name of the visualization. @@ -22717,7 +22858,7 @@ export interface components { * Tags * @description A list of tags to add to this item. */ - tags: components["schemas"]["TagCollection"] | null; + tags: string[] | null; /** * Title * @description The name of the visualization. diff --git a/client/src/components/Collections/sheet/SampleSheetGrid.vue b/client/src/components/Collections/sheet/SampleSheetGrid.vue index 4c04462cd138..ed408e8256db 100644 --- a/client/src/components/Collections/sheet/SampleSheetGrid.vue +++ b/client/src/components/Collections/sheet/SampleSheetGrid.vue @@ -372,7 +372,7 @@ if ("name" in props.initialElements) { initialize(); -type ColumnDefinition = components["schemas"]["SampleSheetColumnDefinition"]; +type ColumnDefinition = components["schemas"]["SampleSheetColumnDefinition-Input"]; function uriFromRow(row: AgRowData): string { return row["url"] as string as string; diff --git a/client/src/components/Workflow/WorkflowAnnotation.test.ts b/client/src/components/Workflow/WorkflowAnnotation.test.ts index 4bf8499c5acf..cb629e9fa915 100644 --- a/client/src/components/Workflow/WorkflowAnnotation.test.ts +++ b/client/src/components/Workflow/WorkflowAnnotation.test.ts @@ -27,6 +27,7 @@ const SAMPLE_RUN_COUNT = 100; const TEST_HISTORY_ID = "test-history-id"; const TEST_HISTORY = { id: TEST_HISTORY_ID, + genome_build: "?", name: "fake-history-name", }; diff --git a/lib/galaxy/celery/base_task.py b/lib/galaxy/celery/base_task.py index af5d5accdc94..31d35a7e8e19 100644 --- a/lib/galaxy/celery/base_task.py +++ b/lib/galaxy/celery/base_task.py @@ -1,5 +1,6 @@ import datetime from abc import abstractmethod +from typing import cast from celery import Task from sqlalchemy import ( @@ -10,6 +11,7 @@ update, ) from sqlalchemy.dialects.postgresql import insert as ps_insert +from sqlalchemy.engine import CursorResult from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import scoped_session @@ -143,7 +145,9 @@ def calculate_task_start_time( except IntegrityError: # Row was inserted by another thread since we tried the update above. sched_time = now + datetime.timedelta(seconds=task_interval_secs) - result = sa_session.execute(self._update_stmt, {"userid": user_id, "sched_time": sched_time}) + result = cast( + CursorResult, sa_session.execute(self._update_stmt, {"userid": user_id, "sched_time": sched_time}) + ) if result.rowcount == 0: raise Exception(f"Failed to update a celery_user_rate_limit row for user id {user_id}") sa_session.commit() diff --git a/lib/galaxy/dependencies/dev-requirements.txt b/lib/galaxy/dependencies/dev-requirements.txt index 342f6db0ecfe..0421f5faaa85 100644 --- a/lib/galaxy/dependencies/dev-requirements.txt +++ b/lib/galaxy/dependencies/dev-requirements.txt @@ -1,26 +1,26 @@ # This file was autogenerated by uv via the following command: # uv export --frozen --no-annotate --no-hashes --only-group=dev aiohappyeyeballs==2.6.1 -aiohttp==3.12.15 +aiohttp==3.13.0 aiosignal==1.4.0 alabaster==0.7.16 ; python_full_version < '3.10' alabaster==1.0.0 ; python_full_version >= '3.10' anyio==4.11.0 ase==3.26.0 async-timeout==5.0.1 ; python_full_version < '3.11' -attrs==25.3.0 +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.9.0 -boto3==1.40.18 -botocore==1.40.18 +boto3==1.40.49 +botocore==1.40.49 build==1.3.0 cachecontrol==0.14.3 cachetools==6.2.0 -cattrs==25.2.0 -certifi==2025.8.3 +cattrs==25.3.0 +certifi==2025.10.5 cffi==2.0.0 ; (implementation_name != 'pypy' and os_name == 'nt') or platform_python_implementation != 'PyPy' charset-normalizer==3.4.3 click==8.1.8 ; python_full_version < '3.10' @@ -43,10 +43,11 @@ docutils==0.21.2 dogpile-cache==1.4.1 enum-tools==0.12.0 ; python_full_version >= '3.10' exceptiongroup==1.3.0 ; python_full_version < '3.11' -filelock==3.19.1 +filelock==3.19.1 ; python_full_version < '3.10' +filelock==3.20.0 ; python_full_version >= '3.10' fluent-logger==0.11.1 fonttools==4.60.1 -frozenlist==1.7.0 +frozenlist==1.8.0 galaxy-release-util==0.3.1 greenlet==3.2.4 h11==0.16.0 @@ -82,20 +83,20 @@ markdown-it-py==3.0.0 markdown-it-reporter==0.0.2 markupsafe==3.0.3 matplotlib==3.9.4 ; python_full_version < '3.10' -matplotlib==3.10.6 ; python_full_version >= '3.10' +matplotlib==3.10.7 ; 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' mdurl==0.1.2 mirakuru==2.6.1 mistune==3.0.2 more-itertools==10.8.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' -msgpack==1.1.1 -multidict==6.6.4 +msgpack==1.1.2 +multidict==6.7.0 mypy==1.18.2 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' -nh3==0.3.0 +nh3==0.3.1 numpy==2.0.2 ; python_full_version < '3.10' numpy==2.2.6 ; python_full_version == '3.10.*' numpy==2.3.3 ; python_full_version >= '3.11' @@ -109,14 +110,15 @@ pathspec==0.12.1 pfzy==0.3.4 pillow==11.3.0 pkce==1.0.3 -platformdirs==4.4.0 +platformdirs==4.4.0 ; python_full_version < '3.10' +platformdirs==4.5.0 ; python_full_version >= '3.10' playwright==1.55.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 prompt-toolkit==3.0.52 -propcache==0.3.2 +propcache==0.4.1 psutil==7.1.0 ; sys_platform != 'cygwin' psycopg==3.2.10 pycparser==2.23 ; (implementation_name != 'PyPy' and implementation_name != 'pypy' and os_name == 'nt') or (implementation_name != 'PyPy' and platform_python_implementation != 'PyPy') @@ -157,7 +159,7 @@ requests-toolbelt==1.0.0 responses==0.25.8 rfc3986==2.0.0 rich==13.9.4 -rich-click==1.9.1 +rich-click==1.9.3 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.7.3 ; python_full_version >= '3.10' @@ -166,7 +168,7 @@ rpds-py==0.27.1 ruamel-yaml==0.18.15 ruamel-yaml-clib==0.2.14 ; python_full_version < '3.14' and platform_python_implementation == 'CPython' rucio-clients==38.3.0 -s3transfer==0.13.1 +s3transfer==0.14.0 schema-salad==8.9.20250723145140 scipy==1.13.1 ; python_full_version < '3.10' scipy==1.15.3 ; python_full_version == '3.10.*' @@ -199,7 +201,7 @@ testfixtures==9.1.0 ; python_full_version >= '3.11' text-unidecode==1.3 tinydb==4.8.2 toml==0.10.2 -tomli==2.2.1 ; python_full_version <= '3.11' +tomli==2.3.0 ; python_full_version <= '3.11' total-perspective-vortex==3.1.1 trio==0.31.0 trio-websocket==0.12.2 @@ -218,8 +220,8 @@ urllib3==2.5.0 ; python_full_version >= '3.10' watchdog==6.0.0 wcwidth==0.2.14 webencodings==0.5.1 ; python_full_version < '3.10' -websocket-client==1.8.0 +websocket-client==1.9.0 werkzeug==3.1.3 wsproto==1.2.0 -yarl==1.20.1 +yarl==1.22.0 zipp==3.23.0 ; python_full_version < '3.12' diff --git a/lib/galaxy/dependencies/pinned-lint-requirements.txt b/lib/galaxy/dependencies/pinned-lint-requirements.txt index 15632ea85bce..e2380cf033b7 100644 --- a/lib/galaxy/dependencies/pinned-lint-requirements.txt +++ b/lib/galaxy/dependencies/pinned-lint-requirements.txt @@ -1,7 +1,7 @@ -attrs==25.3.0 +attrs==25.4.0 flake8==7.3.0 flake8-bugbear==24.12.12 mccabe==0.7.0 pycodestyle==2.14.0 pyflakes==3.4.0 -ruff==0.13.3 +ruff==0.14.0 diff --git a/lib/galaxy/dependencies/pinned-requirements.txt b/lib/galaxy/dependencies/pinned-requirements.txt index bdf89e4b9307..42f57c6740f2 100644 --- a/lib/galaxy/dependencies/pinned-requirements.txt +++ b/lib/galaxy/dependencies/pinned-requirements.txt @@ -2,10 +2,10 @@ # uv export --frozen --no-annotate --no-hashes --no-dev a2wsgi==1.10.10 adal==1.2.7 -aiobotocore==2.24.2 -aiofiles==24.1.0 +aiobotocore==2.25.0 +aiofiles==25.1.0 aiohappyeyeballs==2.6.1 -aiohttp==3.12.15 +aiohttp==3.13.0 aioitertools==0.12.0 aiosignal==1.4.0 alembic==1.16.5 @@ -18,7 +18,7 @@ arcp==0.2.1 argcomplete==3.6.2 async-timeout==5.0.1 ; python_full_version < '3.11' attmap==0.13.2 -attrs==25.3.0 +attrs==25.4.0 babel==2.17.0 bagit==1.9.0 bagit-profile==1.3.1 @@ -30,12 +30,12 @@ bioblend==1.6.0 bleach==6.2.0 boltons==25.0.0 boto==2.49.0 -botocore==1.40.18 +botocore==1.40.49 bx-python==0.14.0 cachecontrol==0.14.3 cachetools==6.2.0 celery==5.5.3 -certifi==2025.8.3 +certifi==2025.10.5 cffi==2.0.0 ; implementation_name == 'pypy' or platform_python_implementation != 'PyPy' charset-normalizer==3.4.3 circus==0.19.0 @@ -67,19 +67,20 @@ edam-ontology==1.25.2 email-validator==2.3.0 et-xmlfile==2.0.0 exceptiongroup==1.3.0 ; python_full_version < '3.11' -fastapi-slim==0.118.0 -filelock==3.19.1 +fastapi-slim==0.118.3 +filelock==3.19.1 ; python_full_version < '3.10' +filelock==3.20.0 ; python_full_version >= '3.10' fissix==24.4.24 -frozenlist==1.7.0 +frozenlist==1.8.0 fs==2.4.16 fsspec==2025.9.0 future==1.0.0 -google-api-core==2.25.2 +google-api-core==2.26.0 google-auth==2.41.1 google-cloud-batch==0.17.37 googleapis-common-protos==1.70.0 gravity==1.1.1 -greenlet==3.2.4 ; (python_full_version < '3.14' and platform_machine == 'AMD64') or (python_full_version < '3.14' and platform_machine == 'WIN32') or (python_full_version < '3.14' and platform_machine == 'aarch64') or (python_full_version < '3.14' and platform_machine == 'amd64') or (python_full_version < '3.14' and platform_machine == 'ppc64le') or (python_full_version < '3.14' and platform_machine == 'win32') or (python_full_version < '3.14' and platform_machine == 'x86_64') +greenlet==3.2.4 ; 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' grpcio==1.75.1 grpcio-status==1.75.1 gunicorn==23.0.0 @@ -91,10 +92,10 @@ httpcore==1.0.9 httpx==0.28.1 humanfriendly==10.0 idna==3.10 -ijson==3.4.0 +ijson==3.4.0.post0 importlib-metadata==8.7.0 ; python_full_version < '3.10' importlib-resources==6.5.2 ; python_full_version < '3.12' -invoke==2.2.0 +invoke==2.2.1 isa-rwval==0.10.11 isal==1.8.0 isodate==0.7.2 ; python_full_version < '3.11' @@ -118,8 +119,8 @@ mercurial==7.1.1 mistune==3.0.2 mrcfile==1.5.4 msal==1.34.0 -msgpack==1.1.1 -multidict==6.6.4 +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.*' @@ -142,7 +143,7 @@ pastedeploy==3.1.0 pebble==5.1.3 pillow==11.3.0 prompt-toolkit==3.0.52 -propcache==0.3.2 +propcache==0.4.1 proto-plus==1.26.1 protobuf==6.32.1 prov==1.5.1 @@ -152,8 +153,8 @@ pyasn1==0.6.1 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.11.9 -pydantic-core==2.33.2 +pydantic==2.12.2 +pydantic-core==2.41.4 pydantic-tes==0.2.0 pydot==4.0.1 pyeventsystem==0.1.0 @@ -198,10 +199,11 @@ setuptools==80.9.0 six==1.17.0 slowapi==0.1.9 sniffio==1.3.1 -social-auth-core==4.7.0 +social-auth-core==4.7.0 ; python_full_version < '3.10' +social-auth-core==4.8.1 ; python_full_version >= '3.10' sortedcontainers==2.4.0 spython==0.3.14 -sqlalchemy==2.0.43 +sqlalchemy==2.0.44 sqlparse==0.5.3 starlette==0.48.0 starlette-context==0.4.0 @@ -211,9 +213,9 @@ 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.9.30 ; python_full_version >= '3.11' +tifffile==2025.10.4 ; python_full_version >= '3.11' tinydb==4.8.2 -tomli==2.2.1 ; python_full_version < '3.11' +tomli==2.3.0 ; python_full_version < '3.11' tornado==6.5.2 tqdm==4.67.1 tuspy==1.1.0 @@ -234,7 +236,7 @@ webob==1.8.9 whoosh==2.7.4 wrapt==1.17.3 yacman==0.9.3 -yarl==1.20.1 +yarl==1.22.0 zipp==3.23.0 ; python_full_version < '3.10' zipstream-new==1.1.8 zstandard==0.25.0 diff --git a/lib/galaxy/dependencies/pinned-test-requirements.txt b/lib/galaxy/dependencies/pinned-test-requirements.txt index 56430c591aa2..0f81fc7efd44 100644 --- a/lib/galaxy/dependencies/pinned-test-requirements.txt +++ b/lib/galaxy/dependencies/pinned-test-requirements.txt @@ -1,20 +1,20 @@ # This file was autogenerated by uv via the following command: # uv export --frozen --no-annotate --no-hashes --only-group=test aiohappyeyeballs==2.6.1 -aiohttp==3.12.15 +aiohttp==3.13.0 aiosignal==1.4.0 anyio==4.11.0 ase==3.26.0 async-timeout==5.0.1 ; python_full_version < '3.11' -attrs==25.3.0 +attrs==25.4.0 axe-selenium-python==2.1.6 backports-asyncio-runner==1.2.0 ; python_full_version < '3.11' -boto3==1.40.18 -botocore==1.40.18 +boto3==1.40.49 +botocore==1.40.49 cachecontrol==0.14.3 cachetools==6.2.0 -cattrs==25.2.0 -certifi==2025.8.3 +cattrs==25.3.0 +certifi==2025.10.5 cffi==2.0.0 ; implementation_name != 'pypy' and os_name == 'nt' charset-normalizer==3.4.3 click==8.1.8 ; python_full_version < '3.10' @@ -32,10 +32,11 @@ defusedxml==0.7.1 dogpile-cache==1.4.1 enum-tools==0.12.0 ; python_full_version >= '3.10' exceptiongroup==1.3.0 ; python_full_version < '3.11' -filelock==3.19.1 +filelock==3.19.1 ; python_full_version < '3.10' +filelock==3.20.0 ; python_full_version >= '3.10' fluent-logger==0.11.1 fonttools==4.60.1 -frozenlist==1.7.0 +frozenlist==1.8.0 greenlet==3.2.4 h11==0.16.0 html5lib==1.1 ; python_full_version < '3.10' @@ -61,12 +62,12 @@ lxml==6.0.2 markdown-it-py==3.0.0 markupsafe==3.0.3 matplotlib==3.9.4 ; python_full_version < '3.10' -matplotlib==3.10.6 ; python_full_version >= '3.10' +matplotlib==3.10.7 ; python_full_version >= '3.10' mdurl==0.1.2 mirakuru==2.6.1 mistune==3.0.2 -msgpack==1.1.1 -multidict==6.6.4 +msgpack==1.1.2 +multidict==6.7.0 mypy==1.18.2 mypy-extensions==1.1.0 numpy==2.0.2 ; python_full_version < '3.10' @@ -82,14 +83,15 @@ pathspec==0.12.1 pfzy==0.3.4 pillow==11.3.0 pkce==1.0.3 -platformdirs==4.4.0 +platformdirs==4.4.0 ; python_full_version < '3.10' +platformdirs==4.5.0 ; python_full_version >= '3.10' playwright==1.55.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 prompt-toolkit==3.0.52 -propcache==0.3.2 +propcache==0.4.1 psutil==7.1.0 ; sys_platform != 'cygwin' psycopg==3.2.10 pycparser==2.23 ; implementation_name != 'PyPy' and implementation_name != 'pypy' and os_name == 'nt' @@ -121,7 +123,7 @@ requests==2.32.5 requests-cache==1.2.1 responses==0.25.8 rich==13.9.4 -rich-click==1.9.1 +rich-click==1.9.3 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.7.3 ; python_full_version >= '3.10' @@ -129,7 +131,7 @@ rpds-py==0.27.1 ruamel-yaml==0.18.15 ruamel-yaml-clib==0.2.14 ; python_full_version < '3.14' and platform_python_implementation == 'CPython' rucio-clients==38.3.0 -s3transfer==0.13.1 +s3transfer==0.14.0 schema-salad==8.9.20250723145140 scipy==1.13.1 ; python_full_version < '3.10' scipy==1.15.3 ; python_full_version == '3.10.*' @@ -148,7 +150,7 @@ testfixtures==9.1.0 ; python_full_version >= '3.11' text-unidecode==1.3 tinydb==4.8.2 toml==0.10.2 -tomli==2.2.1 ; python_full_version <= '3.11' +tomli==2.3.0 ; python_full_version <= '3.11' total-perspective-vortex==3.1.1 trio==0.31.0 trio-websocket==0.12.2 @@ -166,8 +168,8 @@ urllib3==2.5.0 ; python_full_version >= '3.10' watchdog==6.0.0 wcwidth==0.2.14 webencodings==0.5.1 ; python_full_version < '3.10' -websocket-client==1.8.0 +websocket-client==1.9.0 werkzeug==3.1.3 wsproto==1.2.0 -yarl==1.20.1 +yarl==1.22.0 zipp==3.23.0 ; python_full_version < '3.12' diff --git a/lib/galaxy/dependencies/pinned-typecheck-requirements.txt b/lib/galaxy/dependencies/pinned-typecheck-requirements.txt index 4497f64bfbc3..53c9dc791166 100644 --- a/lib/galaxy/dependencies/pinned-typecheck-requirements.txt +++ b/lib/galaxy/dependencies/pinned-typecheck-requirements.txt @@ -1,7 +1,7 @@ # This file was autogenerated by uv via the following command: # uv export --frozen --no-annotate --no-hashes --only-group=typecheck annotated-types==0.7.0 -boto3-stubs==1.40.45 +boto3-stubs==1.40.50 botocore-stubs==1.40.33 cffi==2.0.0 ; platform_python_implementation != 'PyPy' cryptography==46.0.2 @@ -11,26 +11,26 @@ mypy-boto3-s3==1.40.26 mypy-extensions==1.1.0 pathspec==0.12.1 pycparser==2.23 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' -pydantic==2.11.9 -pydantic-core==2.33.2 -tomli==2.2.1 ; python_full_version < '3.11' +pydantic==2.12.2 +pydantic-core==2.41.4 +tomli==2.3.0 ; python_full_version < '3.11' types-awscrt==0.27.6 types-bleach==6.2.0.20250809 types-boto==2.49.18.20241019 types-contextvars==2.4.7.3 types-dataclasses==0.6.6 -types-docutils==0.22.2.20250924 +types-docutils==0.22.2.20251006 types-html5lib==1.1.11.20250917 types-markdown==3.9.0.20250906 types-paramiko==4.0.0.20250822 -types-python-dateutil==2.9.0.20250822 +types-python-dateutil==2.9.0.20251008 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.20250913 ; python_full_version >= '3.10' types-s3transfer==0.13.1 types-setuptools==80.9.0.20250822 -types-six==1.17.0.20250515 +types-six==1.17.0.20251009 types-urllib3==1.26.25.14 ; python_full_version < '3.10' typing-extensions==4.15.0 typing-inspection==0.4.2 diff --git a/lib/galaxy/files/models.py b/lib/galaxy/files/models.py index fd11633e2eb5..61642fccd531 100644 --- a/lib/galaxy/files/models.py +++ b/lib/galaxy/files/models.py @@ -251,7 +251,6 @@ class FilesSourceProperties(StrictModel): supports: Annotated[ FileSourceSupports, Field( - default_factory=FileSourceSupports, description="Features supported by this file source.", ), ] = FileSourceSupports() diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py index b3b39174afb6..8b76e8fe5a6c 100644 --- a/lib/galaxy/jobs/__init__.py +++ b/lib/galaxy/jobs/__init__.py @@ -24,6 +24,7 @@ from typing import ( Any, Callable, + cast, Optional, TYPE_CHECKING, Union, @@ -38,6 +39,7 @@ select, update, ) +from sqlalchemy.engine import CursorResult from galaxy import ( model, @@ -1777,7 +1779,7 @@ def queue_with_limit(self, job: Job, job_destination: JobDestination): ) ) - result = self.sa_session.execute(update_stmt) + result = cast(CursorResult, self.sa_session.execute(update_stmt)) self.sa_session.commit() state_updated = result.rowcount > 0 if state_updated: diff --git a/lib/galaxy/managers/notification.py b/lib/galaxy/managers/notification.py index c6f220583d35..35584274b4fb 100644 --- a/lib/galaxy/managers/notification.py +++ b/lib/galaxy/managers/notification.py @@ -22,6 +22,7 @@ union, update, ) +from sqlalchemy.engine import CursorResult from sqlalchemy.orm import InstrumentedAttribute from sqlalchemy.sql import Select from typing_extensions import Protocol @@ -371,7 +372,7 @@ def update_user_notifications( stmt = stmt.values(seen_time=seen_time) if request.deleted is not None: stmt = stmt.values(deleted=request.deleted) - result = self.sa_session.execute(stmt) + result = cast(CursorResult, self.sa_session.execute(stmt)) updated_row_count = result.rowcount self.sa_session.commit() return updated_row_count @@ -395,7 +396,7 @@ def update_broadcasted_notification(self, notification_id: int, request: Notific stmt = stmt.values(expiration_time=request.expiration_time) if request.content is not None: stmt = stmt.values(content=request.content.json()) - result = self.sa_session.execute(stmt) + result = cast(CursorResult, self.sa_session.execute(stmt)) updated_row_count = result.rowcount self.sa_session.commit() return updated_row_count @@ -449,11 +450,13 @@ def cleanup_expired_notifications(self) -> CleanupResultSummary: delete_stmt = delete(UserNotificationAssociation).where( UserNotificationAssociation.notification_id.in_(expired_notifications_stmt) ) - result = self.sa_session.execute(delete_stmt, execution_options={"synchronize_session": False}) + result = cast( + CursorResult, self.sa_session.execute(delete_stmt, execution_options={"synchronize_session": False}) + ) deleted_associations_count = result.rowcount delete_stmt = delete(Notification).where(notification_has_expired) - result = self.sa_session.execute(delete_stmt) + result = cast(CursorResult, self.sa_session.execute(delete_stmt)) deleted_notifications_count = result.rowcount self.sa_session.commit() diff --git a/lib/galaxy/managers/tags.py b/lib/galaxy/managers/tags.py index eaf19cf1e5b9..7f55b9e40730 100644 --- a/lib/galaxy/managers/tags.py +++ b/lib/galaxy/managers/tags.py @@ -47,8 +47,8 @@ def update(self, trans: ProvidesUserContext, payload: ItemTagsPayload) -> None: """Apply a new set of tags to an item; previous tags are deleted.""" user = trans.user new_tags: Optional[str] = None - if payload.item_tags and len(payload.item_tags.root) > 0: - new_tags = ",".join(payload.item_tags.root) + if payload.item_tags: + new_tags = ",".join(payload.item_tags) item = self._get_item(trans.tag_handler, payload) trans.tag_handler.delete_item_tags(user, item) trans.tag_handler.apply_item_tags(user, item, new_tags) diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index f76c79225da1..417afba292cb 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -99,6 +99,7 @@ VARCHAR, ) from sqlalchemy.dialects.postgresql import JSONB +from sqlalchemy.engine import CursorResult from sqlalchemy.exc import ( CompileError, OperationalError, @@ -2013,8 +2014,13 @@ def set_state(self, state: JobState) -> bool: session = object_session(self) if session and self.id and state not in Job.finished_states: # Do not update if job is in a terminal state - rval = session.execute( - update(Job).where(Job.id == self.id, ~Job.state.in_((state, *Job.finished_states))).values(state=state) + rval = cast( # https://docs.sqlalchemy.org/en/20/changelog/changelog_20.html#change-0651b868cdc88d28c57469affceaf05f + CursorResult, + session.execute( + update(Job) + .where(Job.id == self.id, ~Job.state.in_((state, *Job.finished_states))) + .values(state=state) + ), ) if rval.rowcount == 1: # Need to expire state since we just updated it, but ORM doesn't know about it. @@ -10796,10 +10802,14 @@ class UserAuthnzToken(Base, UserMixin, RepresentById): user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("galaxy_user.id"), index=True) uid: Mapped[Optional[str]] = mapped_column(VARCHAR(255)) # type:ignore[assignment] provider: Mapped[Optional[str]] = mapped_column(VARCHAR(32)) # type:ignore[assignment] - extra_data: Mapped[Optional[dict[str, Any]]] = mapped_column(MutableJSONType) # type:ignore[assignment] + extra_data: Mapped[Optional[dict[str, Any]]] = mapped_column( # type:ignore[assignment, unused-ignore] + MutableJSONType + ) lifetime: Mapped[Optional[int]] assoc_type: Mapped[Optional[str]] = mapped_column(VARCHAR(64)) - user: Mapped[Optional["User"]] = relationship(back_populates="social_auth") + user: Mapped[Optional["User"]] = relationship( # type:ignore[assignment, unused-ignore] + back_populates="social_auth" + ) # This static property is set at: galaxy.authnz.psa_authnz.PSAAuthnz sa_session = None diff --git a/lib/galaxy/schema/schema.py b/lib/galaxy/schema/schema.py index f12aff953400..4556d0e13abc 100644 --- a/lib/galaxy/schema/schema.py +++ b/lib/galaxy/schema/schema.py @@ -31,6 +31,7 @@ from typing_extensions import ( Literal, NotRequired, + TypeAlias, TypedDict, ) @@ -595,18 +596,15 @@ class HistoryContentSource(str, Enum): DatasetCollectionInstanceType = Literal["history", "library"] -TagItem = Annotated[str, Field(..., pattern=TAG_ITEM_PATTERN)] - - -class TagCollection(RootModel): - """Represents the collection of tags associated with an item.""" - - root: list[TagItem] = Field( - default=..., +TagItem: TypeAlias = Annotated[str, Field(pattern=TAG_ITEM_PATTERN)] +TagCollection: TypeAlias = Annotated[ + list[TagItem], + Field( title="Tags", description="The collection of tags associated with an item.", examples=["COVID-19", "#myFancyTag", "covid19.galaxyproject.org"], - ) + ), +] class MetadataFile(Model): @@ -1795,7 +1793,7 @@ class CreateNewCollectionPayload(Model): column_definitions: Optional[SampleSheetColumnDefinitions] = Field( default=None, title="Column Definitions", - description="Specify definitions for row data if collection_type if sample_sheet", + description="Specify definitions for row data if collection_type is sample_sheet", ) rows: Optional[SampleSheetRows] = Field( default=None, diff --git a/lib/galaxy/util/config_templates.py b/lib/galaxy/util/config_templates.py index 12695d50cda9..ccdd798c6051 100644 --- a/lib/galaxy/util/config_templates.py +++ b/lib/galaxy/util/config_templates.py @@ -6,7 +6,6 @@ import logging import os from collections.abc import Iterable -from copy import deepcopy from typing import ( Any, Callable, @@ -33,6 +32,7 @@ ) from pydantic.fields import FieldInfo from typing_extensions import ( + Annotated, Literal, NotRequired, Protocol, @@ -618,6 +618,31 @@ class ImplicitConfigurationParameters(TypedDict): M = TypeVar("M", bound="BaseModel") +# Implementation copied from https://github.com/pydantic/pydantic/issues/12329#issuecomment-3382159312 +def _make_field_optional(field_info: FieldInfo): + """Returns the field's definition to be used in a `create_model()` call to make the field optional.""" + annotation = field_info.annotation + assert annotation is not None + if isinstance(annotation, type) and issubclass(annotation, BaseModel): + annotation = make_model_with_all_fields_optional(annotation) + if field_info.is_required(): + return Annotated[Union[annotation, None], field_info], None + else: + return Annotated[annotation, field_info] + + +def make_model_with_all_fields_optional(model: Type[M], fields=None) -> Type[M]: + """Returns a new Pydantic model based on `model`, but with all fields optional.""" + if fields is None: + fields = model.model_fields.items() + return create_model( + model.__name__, + __doc__=model.__doc__, + __base__=model, + **{field_name: _make_field_optional(field_info) for field_name, field_info in fields}, + ) + + # TODO: This is a workaround to make all fields optional. # It should be removed when Python/pydantic supports this feature natively. # https://github.com/pydantic/pydantic/issues/1673 @@ -630,26 +655,14 @@ def partial_model( exclude = [] def decorator(model: Type[M]) -> Type[M]: - def make_optional(field: FieldInfo, default: Any = None) -> tuple[Any, FieldInfo]: - new = deepcopy(field) - new.default = default - new.annotation = Optional[field.annotation or Any] # type:ignore[assignment] - return new.annotation, new - if include is None: fields: Iterable[tuple[str, FieldInfo]] = model.model_fields.items() else: fields = ((k, v) for k, v in model.model_fields.items() if k in include) - return create_model( - model.__name__, - __base__=model, - __module__=model.__module__, - **{ - field_name: make_optional(field_info) - for field_name, field_info in fields - if exclude is None or field_name not in exclude - }, - ) # type:ignore[call-overload] + if exclude is not None: + fields = ((k, v) for k, v in fields if k not in exclude) + + return make_model_with_all_fields_optional(model, fields) return decorator diff --git a/lib/galaxy/webapps/openapi/utils.py b/lib/galaxy/webapps/openapi/utils.py index c362b40c49a6..aef58fb97b5e 100644 --- a/lib/galaxy/webapps/openapi/utils.py +++ b/lib/galaxy/webapps/openapi/utils.py @@ -11,7 +11,6 @@ from fastapi import routing from fastapi._compat import ( - GenerateJsonSchema, get_compat_model_name_map, get_definitions, ) @@ -22,6 +21,7 @@ get_fields_from_routes, get_openapi_path, ) +from pydantic.json_schema import GenerateJsonSchema from starlette.routing import BaseRoute