diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index 6c57ccad733..95a410245a3 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false env: diff --git a/.github/workflows/ci-staging.yml b/.github/workflows/ci-staging.yml index c0c41c69e66..1fd08e48593 100644 --- a/.github/workflows/ci-staging.yml +++ b/.github/workflows/ci-staging.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false env: diff --git a/.github/workflows/ci-testing-deploy.yml b/.github/workflows/ci-testing-deploy.yml index 5be14fb3619..dda2f271391 100644 --- a/.github/workflows/ci-testing-deploy.yml +++ b/.github/workflows/ci-testing-deploy.yml @@ -271,7 +271,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false name: "[build] docker images" @@ -305,7 +305,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -350,7 +350,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -389,7 +389,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -428,7 +428,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -470,7 +470,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -514,7 +514,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -550,7 +550,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -595,7 +595,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -637,7 +637,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -685,7 +685,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -738,7 +738,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -821,7 +821,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -869,7 +869,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -911,7 +911,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -953,7 +953,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -995,7 +995,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1047,7 +1047,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1089,7 +1089,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1131,7 +1131,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1183,7 +1183,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1225,7 +1225,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1314,7 +1314,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10", "3.11"] + python: ["3.11"] + #python: ["3.11", "3.12"] TODO: re-enable it (GCR) os: [ubuntu-22.04] fail-fast: false steps: @@ -1350,7 +1351,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1392,7 +1393,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1434,7 +1435,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1476,7 +1477,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1518,7 +1519,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1560,7 +1561,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1601,7 +1602,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] docker_buildx: [v0.10.4] fail-fast: false @@ -1647,7 +1648,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1740,7 +1741,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1800,7 +1801,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1862,7 +1863,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1924,7 +1925,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -1990,7 +1991,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -2054,7 +2055,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -2131,7 +2132,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -2217,7 +2218,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -2278,7 +2279,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -2344,7 +2345,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] node: [14] os: [ubuntu-22.04] fail-fast: false @@ -2428,7 +2429,7 @@ jobs: # image: mcr.microsoft.com/playwright/python:v1.39.0-jammy strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -2492,7 +2493,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false steps: @@ -2552,7 +2553,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.10"] + python: ["3.11"] os: [ubuntu-22.04] fail-fast: false env: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a8bb2f6113d..5708407ca45 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ exclude: "^.venv$|^.cache$|^.pytest_cache$" fail_fast: false default_language_version: - python: python3.10 + python: python3.11 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.2.0 @@ -26,7 +26,7 @@ repos: hooks: - id: pyupgrade args: - - "--py310-plus" + - "--py311-plus" name: upgrade code - repo: https://github.com/hadialqattan/pycln rev: v2.1.4 diff --git a/.pylintrc b/.pylintrc index b680ebc6541..9454261215a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -89,7 +89,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.10 +py-version=3.11 # Discover python modules and packages in the file system subtree. recursive=true diff --git a/.ruff.toml b/.ruff.toml index 319a925d2fa..cba34d54b13 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -47,7 +47,7 @@ ignore = [ "TRY300", # Checks for return statements in try blocks. SEE https://beta.ruff.rs/docs/rules/try-consider-else/ ] -target-version = "py310" +target-version = "py311" [per-file-ignores] diff --git a/mypy.ini b/mypy.ini index 6d2dbbae389..9df50ed1d52 100644 --- a/mypy.ini +++ b/mypy.ini @@ -11,7 +11,7 @@ namespace_packages = True no_implicit_reexport = True # NOTE: this crashes mypy when declared here, therefore it is declared in the setup.cfg files # plugins = pydantic.mypy -python_version = 3.10 +python_version = 3.11 show_column_numbers = True show_error_context = False strict_optional = True diff --git a/packages/models-library/src/models_library/basic_types.py b/packages/models-library/src/models_library/basic_types.py index 2f186b31fe2..18788e188a8 100644 --- a/packages/models-library/src/models_library/basic_types.py +++ b/packages/models-library/src/models_library/basic_types.py @@ -1,7 +1,8 @@ import re -from enum import Enum +from enum import StrEnum from typing import Final, TypeAlias + from pydantic import ( ConstrainedDecimal, ConstrainedInt, @@ -142,14 +143,14 @@ class HttpUrlWithCustomMinLength(HttpUrl): min_length = 0 -class LogLevel(str, Enum): +class LogLevel(StrEnum): DEBUG = "DEBUG" INFO = "INFO" WARNING = "WARNING" ERROR = "ERROR" -class BootModeEnum(str, Enum): +class BootModeEnum(StrEnum): """ Values taken by SC_BOOT_MODE environment variable set in Dockerfile and used during docker/boot.sh @@ -166,7 +167,7 @@ def is_devel_mode(self) -> bool: return self in (self.DEBUG, self.DEVELOPMENT, self.LOCAL) -class BuildTargetEnum(str, Enum): +class BuildTargetEnum(StrEnum): """ Values taken by SC_BUILD_TARGET environment variable set in Dockerfile that defines the stage targeted in the diff --git a/packages/models-library/src/models_library/utils/enums.py b/packages/models-library/src/models_library/utils/enums.py index 2e0be0e4865..7f0ff7eaf48 100644 --- a/packages/models-library/src/models_library/utils/enums.py +++ b/packages/models-library/src/models_library/utils/enums.py @@ -1,10 +1,10 @@ import inspect -from enum import Enum, unique +from enum import Enum, StrEnum, unique from typing import Any @unique -class StrAutoEnum(str, Enum): +class StrAutoEnum(StrEnum): @staticmethod def _generate_next_value_(name, start, count, last_values): return name.upper() diff --git a/packages/models-library/tests/test__pydantic_models_and_enums.py b/packages/models-library/tests/test__pydantic_models_and_enums.py index 832ec221c2e..51b4151fecb 100644 --- a/packages/models-library/tests/test__pydantic_models_and_enums.py +++ b/packages/models-library/tests/test__pydantic_models_and_enums.py @@ -1,4 +1,4 @@ -from enum import Enum, unique +from enum import Enum, StrEnum, unique import pytest from models_library.utils.enums import are_equivalent_enums, enum_to_dict @@ -36,12 +36,12 @@ def test_equivalent_enums_are_not_strictly_equal(): @unique -class ColorStrAndEnum1(str, Enum): +class ColorStrAndEnum1(StrEnum): RED = "RED" @unique -class ColorStrAndEnum2(str, Enum): +class ColorStrAndEnum2(StrEnum): RED = "RED" diff --git a/packages/postgres-database/scripts/erd/Dockerfile b/packages/postgres-database/scripts/erd/Dockerfile index 855ba38136b..fae33a3af00 100644 --- a/packages/postgres-database/scripts/erd/Dockerfile +++ b/packages/postgres-database/scripts/erd/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base RUN apt-get update \ diff --git a/packages/postgres-database/scripts/erd/Makefile b/packages/postgres-database/scripts/erd/Makefile index c4adb54d2cb..b9e66dcc44d 100644 --- a/packages/postgres-database/scripts/erd/Makefile +++ b/packages/postgres-database/scripts/erd/Makefile @@ -3,7 +3,7 @@ # .DEFAULT_GOAL := help -PYTHON_VERSION=3.10.14 +PYTHON_VERSION=3.11.9 # locations REPODIR := $(shell git rev-parse --show-toplevel) diff --git a/packages/postgres-database/src/simcore_postgres_database/models/payments_transactions.py b/packages/postgres-database/src/simcore_postgres_database/models/payments_transactions.py index c3ea71bfcf2..21916b0615b 100644 --- a/packages/postgres-database/src/simcore_postgres_database/models/payments_transactions.py +++ b/packages/postgres-database/src/simcore_postgres_database/models/payments_transactions.py @@ -1,4 +1,4 @@ -import enum +from enum import StrEnum, unique import sqlalchemy as sa @@ -11,8 +11,8 @@ from .base import metadata -@enum.unique -class PaymentTransactionState(str, enum.Enum): +@unique +class PaymentTransactionState(StrEnum): PENDING = "PENDING" # payment initiated SUCCESS = "SUCCESS" # payment completed with success FAILED = "FAILED" # payment failed diff --git a/packages/service-integration/Dockerfile b/packages/service-integration/Dockerfile index 7812c48b66c..25069fdebbe 100644 --- a/packages/service-integration/Dockerfile +++ b/packages/service-integration/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base LABEL maintainer=pcrespov diff --git a/packages/service-library/tests/deferred_tasks/test__base_deferred_handler.py b/packages/service-library/tests/deferred_tasks/test__base_deferred_handler.py index 80a6090a63e..9f3451058bf 100644 --- a/packages/service-library/tests/deferred_tasks/test__base_deferred_handler.py +++ b/packages/service-library/tests/deferred_tasks/test__base_deferred_handler.py @@ -445,7 +445,7 @@ async def _run_that_times_out(_: DeferredContext) -> None: await _assert_mock_call(mocks, key=MockKeys.ON_FINISHED_WITH_ERROR, count=1) for entry in mocks[MockKeys.ON_FINISHED_WITH_ERROR].call_args_list: - assert "asyncio.exceptions.TimeoutError" in entry.args[0].error + assert "builtins.TimeoutError" in entry.args[0].error await _assert_mock_call(mocks, key=MockKeys.RUN_DEFERRED, count=0) await _assert_mock_call(mocks, key=MockKeys.ON_DEFERRED_RESULT, count=0) diff --git a/packages/settings-library/src/settings_library/r_clone.py b/packages/settings-library/src/settings_library/r_clone.py index 4bab5f4a327..ff04d509bef 100644 --- a/packages/settings-library/src/settings_library/r_clone.py +++ b/packages/settings-library/src/settings_library/r_clone.py @@ -1,4 +1,4 @@ -from enum import Enum +from enum import StrEnum from pydantic import Field, NonNegativeInt @@ -6,7 +6,7 @@ from .s3 import S3Settings -class S3Provider(str, Enum): +class S3Provider(StrEnum): AWS = "AWS" CEPH = "CEPH" MINIO = "MINIO" diff --git a/packages/settings-library/tests/test_application.py b/packages/settings-library/tests/test_application.py index 8f847e5dd24..ac88b2c538a 100644 --- a/packages/settings-library/tests/test_application.py +++ b/packages/settings-library/tests/test_application.py @@ -17,7 +17,7 @@ def envs_from_docker_inspect() -> EnvVarsDict: "PATH=/home/scu/.venv/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "LANG=C.UTF-8", "GPG_KEY=A035C8C19219BA821ECEA86B64E628F8D684696D", - "PYTHON_VERSION=3.10.14", + "PYTHON_VERSION=3.11.9", "PYTHON_PIP_VERSION=22.3.1", "PYTHON_SETUPTOOLS_VERSION=65.5.1", "PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/d5cb0afaf23b8520f1bbcfed521017b4a95f5c01/public/get-pip.py", diff --git a/packages/settings-library/tests/test_base.py b/packages/settings-library/tests/test_base.py index aa1ffa95a23..7cbd9fa8773 100644 --- a/packages/settings-library/tests/test_base.py +++ b/packages/settings-library/tests/test_base.py @@ -4,7 +4,6 @@ # pylint: disable=too-many-arguments # pylint: disable=protected-access -import inspect import json from collections.abc import Callable from typing import Any @@ -310,7 +309,6 @@ def test_issubclass_type_error_with_pydantic_models(): # TypeError: issubclass() arg 1 must be a class # - assert inspect.isclass(dict[str, str]) assert not issubclass(dict, BaseSettings) # NOTE: this should be fixed by pydantic at some point. When this happens, this test will fail diff --git a/packages/simcore-sdk/src/simcore_sdk/node_ports_common/aws_s3_cli.py b/packages/simcore-sdk/src/simcore_sdk/node_ports_common/aws_s3_cli.py index 72ed5b97279..35d1d7c71f8 100644 --- a/packages/simcore-sdk/src/simcore_sdk/node_ports_common/aws_s3_cli.py +++ b/packages/simcore-sdk/src/simcore_sdk/node_ports_common/aws_s3_cli.py @@ -126,7 +126,9 @@ async def _async_aws_cli_command( ) assert proc.stdout # nosec - await asyncio.wait([_read_stream(proc.stdout, [*aws_cli_s3_log_parsers])]) + await asyncio.wait( + [asyncio.create_task(_read_stream(proc.stdout, [*aws_cli_s3_log_parsers]))] + ) _stdout, _stderr = await proc.communicate() diff --git a/packages/simcore-sdk/src/simcore_sdk/node_ports_common/r_clone.py b/packages/simcore-sdk/src/simcore_sdk/node_ports_common/r_clone.py index b9bc3d8437a..18e15139493 100644 --- a/packages/simcore-sdk/src/simcore_sdk/node_ports_common/r_clone.py +++ b/packages/simcore-sdk/src/simcore_sdk/node_ports_common/r_clone.py @@ -90,7 +90,9 @@ async def _async_r_clone_command( ) assert proc.stdout # nosec - await asyncio.wait([_read_stream(proc.stdout, [*r_clone_log_parsers])]) + await asyncio.wait( + [asyncio.create_task(_read_stream(proc.stdout, [*r_clone_log_parsers]))] + ) # NOTE: ANE not sure why you do this call here. The above one already reads out the stream. _stdout, _stderr = await proc.communicate() diff --git a/requirements/PYTHON_VERSION b/requirements/PYTHON_VERSION index c8cfe395918..2c0733315e4 100644 --- a/requirements/PYTHON_VERSION +++ b/requirements/PYTHON_VERSION @@ -1 +1 @@ -3.10 +3.11 diff --git a/requirements/how-to-upgrade-python.md b/requirements/how-to-upgrade-python.md index 90aaa6e1ef7..51217f5f53b 100644 --- a/requirements/how-to-upgrade-python.md +++ b/requirements/how-to-upgrade-python.md @@ -47,7 +47,7 @@ Both python and pip version are specified: runs-on: ${{ matrix.os }} strategy: matrix: - python: ["3.9", "3.10"] + python: ["3.9", "3.11"] ``` - [pyupgrade](https://github.com/asottile/pyupgrade) tool which has been containarized (``scripts/pyupgrade.bash``) and added as a Makefile recipe (``make pyupgrade``) diff --git a/requirements/tools/Dockerfile b/requirements/tools/Dockerfile index 8d01e09395c..65d6faa3cad 100644 --- a/requirements/tools/Dockerfile +++ b/requirements/tools/Dockerfile @@ -8,7 +8,7 @@ # - Can be installed with pyenv (SEE pyenv install --list ) # # -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base ENV VIRTUAL_ENV=/home/scu/.venv diff --git a/requirements/tools/Makefile b/requirements/tools/Makefile index 8a39071579d..395bb9e6bc4 100644 --- a/requirements/tools/Makefile +++ b/requirements/tools/Makefile @@ -14,7 +14,7 @@ # .DEFAULT_GOAL := help -PYTHON_VERSION=3.10.14 +PYTHON_VERSION=3.11.9 # locations REPODIR := $(shell git rev-parse --show-toplevel) diff --git a/scripts/apt-packages-versions/Dockerfile b/scripts/apt-packages-versions/Dockerfile index c7c1724982e..5992008917c 100644 --- a/scripts/apt-packages-versions/Dockerfile +++ b/scripts/apt-packages-versions/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base RUN \ diff --git a/scripts/erd/Dockerfile b/scripts/erd/Dockerfile index 887ab055368..ce98f367944 100644 --- a/scripts/erd/Dockerfile +++ b/scripts/erd/Dockerfile @@ -7,7 +7,7 @@ # - https://erdantic.drivendata.org/stable/ # -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base RUN apt-get update \ diff --git a/scripts/maintenance/migrate_project/Dockerfile b/scripts/maintenance/migrate_project/Dockerfile index 72afc85d823..d4a17f9ba40 100644 --- a/scripts/maintenance/migrate_project/Dockerfile +++ b/scripts/maintenance/migrate_project/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM python:3.10.14-buster +FROM python:3.11.9-buster RUN curl https://rclone.org/install.sh | bash && \ rclone --version diff --git a/scripts/openapi-pydantic-models-generator.bash b/scripts/openapi-pydantic-models-generator.bash index 9264a06b48c..82cf503f1d6 100755 --- a/scripts/openapi-pydantic-models-generator.bash +++ b/scripts/openapi-pydantic-models-generator.bash @@ -6,7 +6,7 @@ set -o nounset set -o pipefail IFS=$'\n\t' -PYTHON_VERSION=3.10.14 +PYTHON_VERSION=3.11.9 IMAGE_NAME="local/datamodel-code-generator:${PYTHON_VERSION}" WORKDIR="$(pwd)" diff --git a/scripts/pydeps-docker/Dockerfile b/scripts/pydeps-docker/Dockerfile index 80c5777957a..ed647427913 100644 --- a/scripts/pydeps-docker/Dockerfile +++ b/scripts/pydeps-docker/Dockerfile @@ -8,7 +8,7 @@ # - Can be installed with pyenv (SEE pyenv install --list ) # # -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base diff --git a/scripts/pydeps.bash b/scripts/pydeps.bash index affd21597d7..18e6803369b 100755 --- a/scripts/pydeps.bash +++ b/scripts/pydeps.bash @@ -8,7 +8,7 @@ set -o pipefail IFS=$'\n\t' SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) -PYTHON_VERSION=3.10.14 +PYTHON_VERSION=3.11.9 IMAGE_NAME="local/pydeps-devkit:${PYTHON_VERSION}" WORKDIR="$(pwd)" diff --git a/scripts/pyupgrade.bash b/scripts/pyupgrade.bash index 9a775686db3..4423a8583ee 100755 --- a/scripts/pyupgrade.bash +++ b/scripts/pyupgrade.bash @@ -8,7 +8,7 @@ IFS=$'\n\t' # # # NOTE: check --py* flag in CLI when PYTHON_VERSION is modified -PYTHON_VERSION=3.10.14 +PYTHON_VERSION=3.11.9 IMAGE_NAME="local/pyupgrade-devkit:${PYTHON_VERSION}" WORKDIR="$(pwd)" @@ -28,7 +28,7 @@ RUN pip install \ pyupgrade ENTRYPOINT ["pyupgrade", \ - "--py310-plus" ] + "--py311-plus" ] EOF } diff --git a/services/agent/Dockerfile b/services/agent/Dockerfile index 17a597cbdb9..fdff90cc5f3 100644 --- a/services/agent/Dockerfile +++ b/services/agent/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/api-server/Dockerfile b/services/api-server/Dockerfile index ccc7b6f89c7..597f421ab4d 100644 --- a/services/api-server/Dockerfile +++ b/services/api-server/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # # USAGE: diff --git a/services/autoscaling/Dockerfile b/services/autoscaling/Dockerfile index 719a7a697aa..a4d50b497c9 100644 --- a/services/autoscaling/Dockerfile +++ b/services/autoscaling/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/catalog/Dockerfile b/services/catalog/Dockerfile index 63c537aece1..b87d90b1224 100644 --- a/services/catalog/Dockerfile +++ b/services/catalog/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # # diff --git a/services/clusters-keeper/Dockerfile b/services/clusters-keeper/Dockerfile index 13283e38aca..cd29d763adf 100644 --- a/services/clusters-keeper/Dockerfile +++ b/services/clusters-keeper/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/dask-sidecar/Dockerfile b/services/dask-sidecar/Dockerfile index 335819505be..b91cefa9e88 100644 --- a/services/dask-sidecar/Dockerfile +++ b/services/dask-sidecar/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM --platform=${TARGETPLATFORM} python:${PYTHON_VERSION}-slim-bookworm as base ARG TARGETPLATFORM ARG BUILDPLATFORM diff --git a/services/datcore-adapter/Dockerfile b/services/datcore-adapter/Dockerfile index 40394e44d21..fc4c2fcd403 100644 --- a/services/datcore-adapter/Dockerfile +++ b/services/datcore-adapter/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/director-v2/Dockerfile b/services/director-v2/Dockerfile index f87fc623868..4e29e4a3d2f 100644 --- a/services/director-v2/Dockerfile +++ b/services/director-v2/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/director-v2/tests/unit/test_core_settings.py b/services/director-v2/tests/unit/test_core_settings.py index 237febac3d4..84d99057f3a 100644 --- a/services/director-v2/tests/unit/test_core_settings.py +++ b/services/director-v2/tests/unit/test_core_settings.py @@ -21,7 +21,7 @@ def _get_backend_type_options() -> set[str]: - return {x for x in dir(S3Provider) if not x.startswith("_")} + return {x for x in S3Provider if not x.startswith("_")} def test_supported_backends_did_not_change() -> None: diff --git a/services/dynamic-scheduler/Dockerfile b/services/dynamic-scheduler/Dockerfile index b0bc9e9846b..fb2db946f75 100644 --- a/services/dynamic-scheduler/Dockerfile +++ b/services/dynamic-scheduler/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/dynamic-sidecar/Dockerfile b/services/dynamic-sidecar/Dockerfile index 07a1701b657..c02ba67c9de 100644 --- a/services/dynamic-sidecar/Dockerfile +++ b/services/dynamic-sidecar/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # # USAGE: diff --git a/services/efs-guardian/Dockerfile b/services/efs-guardian/Dockerfile index a6e187aace4..8d75f1ac056 100644 --- a/services/efs-guardian/Dockerfile +++ b/services/efs-guardian/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/invitations/Dockerfile b/services/invitations/Dockerfile index d9673f0c1ae..b7635329edc 100644 --- a/services/invitations/Dockerfile +++ b/services/invitations/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/migration/Dockerfile b/services/migration/Dockerfile index 05f0bb3ce19..9cd1988399b 100644 --- a/services/migration/Dockerfile +++ b/services/migration/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base LABEL maintainer=sanderegg diff --git a/services/osparc-gateway-server/.env-devel b/services/osparc-gateway-server/.env-devel index 62b5b6c2795..944c6914d43 100644 --- a/services/osparc-gateway-server/.env-devel +++ b/services/osparc-gateway-server/.env-devel @@ -1,2 +1,2 @@ -COMPUTATIONAL_SIDECAR_IMAGE=itisfoundation/dask-sidecar:master-github-latest +COMPUTATIONAL_SIDECAR_IMAGE=local/dask-sidecar:production COMPUTATIONAL_SIDECAR_LOG_LEVEL=INFO diff --git a/services/osparc-gateway-server/Dockerfile b/services/osparc-gateway-server/Dockerfile index c80ccd9a5bf..150063ce0fc 100644 --- a/services/osparc-gateway-server/Dockerfile +++ b/services/osparc-gateway-server/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bullseye as base ARG TARGETPLATFORM ARG BUILDPLATFORM diff --git a/services/payments/Dockerfile b/services/payments/Dockerfile index c29f0ca9fe6..692541c29d0 100644 --- a/services/payments/Dockerfile +++ b/services/payments/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/resource-usage-tracker/Dockerfile b/services/resource-usage-tracker/Dockerfile index 34d81cf8801..31001e4f735 100644 --- a/services/resource-usage-tracker/Dockerfile +++ b/services/resource-usage-tracker/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # diff --git a/services/storage/Dockerfile b/services/storage/Dockerfile index 02974a9485b..688f5dfa9f9 100644 --- a/services/storage/Dockerfile +++ b/services/storage/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # # USAGE: diff --git a/services/web/Dockerfile b/services/web/Dockerfile index ecb19b9afde..1e134f8c106 100644 --- a/services/web/Dockerfile +++ b/services/web/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION="3.10.14" +ARG PYTHON_VERSION="3.11.9" FROM python:${PYTHON_VERSION}-slim-bookworm as base # # USAGE: @@ -78,7 +78,8 @@ RUN --mount=type=cache,target=/var/cache/apt,mode=0755,sharing=private \ set -eux \ && apt-get update \ && apt-get install -y --no-install-recommends \ - build-essential + build-essential \ + libffi-dev # NOTE: install https://github.com/astral-sh/uv ultra-fast rust-based pip replacement RUN --mount=type=cache,mode=0755,target=/root/.cache/pip \ diff --git a/services/web/server/requirements/_base.txt b/services/web/server/requirements/_base.txt index f80a025a702..ab574d6c39f 100644 --- a/services/web/server/requirements/_base.txt +++ b/services/web/server/requirements/_base.txt @@ -152,8 +152,6 @@ email-validator==1.2.1 # via pydantic et-xmlfile==1.1.0 # via openpyxl -exceptiongroup==1.2.1 - # via anyio faker==19.6.1 # via -r requirements/_base.in fast-depends==2.4.2 @@ -162,8 +160,9 @@ faststream==0.5.10 # via # -r requirements/../../../../packages/service-library/requirements/_base.in # -r requirements/../../../../packages/simcore-sdk/requirements/../../../packages/service-library/requirements/_base.in -frozenlist==1.3.0 +frozenlist==1.4.1 # via + # -c requirements/./constraints.txt # aiohttp # aiosignal greenlet==2.0.2 @@ -297,7 +296,7 @@ pycountry==23.12.11 # via -r requirements/_base.in pycparser==2.21 # via cffi -pydantic==1.9.0 +pydantic==1.10.17 # via # -c requirements/../../../../packages/models-library/requirements/../../../requirements/constraints.txt # -c requirements/../../../../packages/postgres-database/requirements/../../../requirements/constraints.txt @@ -314,6 +313,7 @@ pydantic==1.9.0 # -c requirements/../../../../packages/simcore-sdk/requirements/../../../packages/settings-library/requirements/../../../requirements/constraints.txt # -c requirements/../../../../packages/simcore-sdk/requirements/../../../requirements/constraints.txt # -c requirements/../../../../requirements/constraints.txt + # -c requirements/./constraints.txt # -r requirements/../../../../packages/models-library/requirements/_base.in # -r requirements/../../../../packages/postgres-database/requirements/_base.in # -r requirements/../../../../packages/service-library/requirements/../../../packages/models-library/requirements/_base.in @@ -466,7 +466,6 @@ typing-extensions==4.12.0 # via # aiodebug # aiodocker - # anyio # faststream # pydantic # typer @@ -506,7 +505,7 @@ urllib3==1.26.11 # requests werkzeug==2.1.2 # via -r requirements/../../../../packages/service-library/requirements/_aiohttp.in -yarl==1.5.1 +yarl==1.9.4 # via # -c requirements/./constraints.txt # -r requirements/../../../../packages/postgres-database/requirements/_base.in diff --git a/services/web/server/requirements/_test.txt b/services/web/server/requirements/_test.txt index 121d65f42a3..28185fac32f 100644 --- a/services/web/server/requirements/_test.txt +++ b/services/web/server/requirements/_test.txt @@ -53,11 +53,6 @@ coverage==7.6.1 # pytest-cov docker==7.1.0 # via -r requirements/_test.in -exceptiongroup==1.2.1 - # via - # -c requirements/_base.txt - # hypothesis - # pytest execnet==2.1.1 # via pytest-xdist faker==19.6.1 @@ -66,7 +61,7 @@ faker==19.6.1 # -r requirements/_test.in flaky==3.8.1 # via -r requirements/_test.in -frozenlist==1.3.0 +frozenlist==1.4.1 # via # -c requirements/_base.txt # aiohttp @@ -223,10 +218,7 @@ tenacity==8.5.0 termcolor==2.4.0 # via pytest-sugar tomli==2.0.1 - # via - # coverage - # mypy - # pytest + # via coverage types-aiofiles==24.1.0.20240626 # via -r requirements/_test.in types-jsonschema==4.23.0.20240813 @@ -251,7 +243,7 @@ urllib3==1.26.11 # requests websockets==13.0 # via -r requirements/_test.in -yarl==1.5.1 +yarl==1.9.4 # via # -c requirements/_base.txt # aiohttp diff --git a/services/web/server/requirements/_tools.txt b/services/web/server/requirements/_tools.txt index c5d598f293f..4d6682cf5c2 100644 --- a/services/web/server/requirements/_tools.txt +++ b/services/web/server/requirements/_tools.txt @@ -97,8 +97,6 @@ typing-extensions==4.12.0 # via # -c requirements/_base.txt # -c requirements/_test.txt - # astroid - # black # mypy virtualenv==20.26.3 # via pre-commit diff --git a/services/web/server/requirements/constraints.txt b/services/web/server/requirements/constraints.txt index b7bd91a0af0..71c712593cb 100644 --- a/services/web/server/requirements/constraints.txt +++ b/services/web/server/requirements/constraints.txt @@ -3,5 +3,10 @@ # Include this file with --contraints # -# SEE services/web/server/tests/unit/isolated/test_utils.py::test_yarl_url_compose_changed_with_latest_release -yarl<1.6 +# yarl version 1.8.2 is the first one shipping wheels for Python 3.11 +# SEE services/web/server/tests/unit/isolated/test_utils.py::test_yarl_new_url_generation for properly usage +yarl>=1.8.2 +frozenlist>=1.3.1 + +# See: https://github.com/pydantic/pydantic/issues/4011 +pydantic>=1.10 diff --git a/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py b/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py index 70d8cb4aa97..ce7a7be0943 100644 --- a/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py @@ -23,8 +23,8 @@ class _RequestContext(RequestParams): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] @routes.get(f"/{API_VTAG}/auth/api-keys", name="list_api_keys") diff --git a/services/web/server/src/simcore_service_webserver/catalog/client.py b/services/web/server/src/simcore_service_webserver/catalog/client.py index bc958a1df8e..8a8f6083252 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/client.py +++ b/services/web/server/src/simcore_service_webserver/catalog/client.py @@ -114,9 +114,9 @@ async def get_service( product_name: str, ) -> dict[str, Any]: settings: CatalogSettings = get_plugin_settings(app) - url = ( - URL(settings.api_base_url) - / f"services/{urllib.parse.quote_plus(service_key)}/{service_version}" + url = URL( + f"{settings.api_base_url}/services/{urllib.parse.quote_plus(service_key)}/{service_version}", + encoded=True, ).with_query({"user_id": user_id}) with _handle_client_exceptions(app) as session: @@ -136,8 +136,10 @@ async def get_service_resources( ) -> ServiceResourcesDict: settings: CatalogSettings = get_plugin_settings(app) url = ( - URL(settings.api_base_url) - / f"services/{urllib.parse.quote_plus(service_key)}/{service_version}/resources" + URL( + f"{settings.api_base_url}/services/{urllib.parse.quote_plus(service_key)}/{service_version}/resources", + encoded=True, + ) ).with_query({"user_id": user_id}) with _handle_client_exceptions(app) as session: @@ -155,9 +157,9 @@ async def get_service_access_rights( product_name: str, ) -> ServiceAccessRightsGet: settings: CatalogSettings = get_plugin_settings(app) - url = ( - URL(settings.api_base_url) - / f"services/{urllib.parse.quote_plus(service_key)}/{service_version}/accessRights" + url = URL( + f"{settings.api_base_url}/services/{urllib.parse.quote_plus(service_key)}/{service_version}/accessRights", + encoded=True, ).with_query({"user_id": user_id}) with _handle_client_exceptions(app) as session: @@ -179,9 +181,9 @@ async def update_service( ) -> dict[str, Any]: settings: CatalogSettings = get_plugin_settings(app) - url = ( - URL(settings.api_base_url) - / f"services/{urllib.parse.quote_plus(service_key)}/{service_version}" + url = URL( + f"{settings.api_base_url}/services/{urllib.parse.quote_plus(service_key)}/{service_version}", + encoded=True, ).with_query({"user_id": user_id}) with _handle_client_exceptions(app) as session: diff --git a/services/web/server/src/simcore_service_webserver/cli.py b/services/web/server/src/simcore_service_webserver/cli.py index 0b20a9827ab..bbd9b327a9b 100644 --- a/services/web/server/src/simcore_service_webserver/cli.py +++ b/services/web/server/src/simcore_service_webserver/cli.py @@ -15,10 +15,12 @@ import logging import os +from typing import Final import typer from aiohttp import web from settings_library.utils_cli import create_settings_command +from typing_extensions import Annotated from .application_settings import ApplicationSettings from .login import cli as login_cli @@ -81,7 +83,26 @@ async def app_factory() -> web.Application: create_settings_command(settings_cls=ApplicationSettings, logger=_logger) ) -main.command()(login_cli.invitations) +_NO_TRIAL_DAYS: Final[int] = -1 + + +@main.command() +def invitations( + base_url: str, + issuer_email: str, + trial_days: Annotated[int, typer.Argument()] = _NO_TRIAL_DAYS, + user_id: int = 1, + num_codes: int = 15, + code_length: int = 30, +): + login_cli.invitations( + base_url=base_url, + issuer_email=issuer_email, + trial_days=trial_days if trial_days != _NO_TRIAL_DAYS else None, + user_id=user_id, + num_codes=num_codes, + code_length=code_length, + ) @main.command() diff --git a/services/web/server/src/simcore_service_webserver/clusters/_handlers.py b/services/web/server/src/simcore_service_webserver/clusters/_handlers.py index 64993021665..70752da883b 100644 --- a/services/web/server/src/simcore_service_webserver/clusters/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/clusters/_handlers.py @@ -63,7 +63,7 @@ async def wrapper(request: web.Request) -> web.StreamResponse: class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] # diff --git a/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py b/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py index 4b0a5a4b024..fb80f3aa3fa 100644 --- a/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py @@ -47,8 +47,8 @@ class RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] class _ComputationStarted(BaseModel): diff --git a/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py b/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py index 1e67d43c6d8..313b83d8c08 100644 --- a/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py +++ b/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py @@ -66,8 +66,8 @@ async def wrapper(request: web.Request) -> web.StreamResponse: class FoldersRequestContext(RequestParams): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] class FoldersPathParams(StrictRequestParams): @@ -76,7 +76,7 @@ class FoldersPathParams(StrictRequestParams): class FolderListWithJsonStrQueryParams(PageQueryParameters): # pylint: disable=unsubscriptable-object - order_by: Json[OrderBy] = Field( # type: ignore[type-arg] + order_by: Json[OrderBy] = Field( default=OrderBy(field=IDStr("modified"), direction=OrderDirection.DESC), description="Order by field (modified_at|name|description) and direction (asc|desc). The default sorting order is ascending.", example='{"field": "name", "direction": "desc"}', diff --git a/services/web/server/src/simcore_service_webserver/folders/_groups_handlers.py b/services/web/server/src/simcore_service_webserver/folders/_groups_handlers.py index 5de2bc035b0..0c2696f0722 100644 --- a/services/web/server/src/simcore_service_webserver/folders/_groups_handlers.py +++ b/services/web/server/src/simcore_service_webserver/folders/_groups_handlers.py @@ -31,8 +31,8 @@ class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] def _handle_folders_groups_exceptions(handler: Handler): diff --git a/services/web/server/src/simcore_service_webserver/groups/_handlers.py b/services/web/server/src/simcore_service_webserver/groups/_handlers.py index a04df023405..2f0b0411601 100644 --- a/services/web/server/src/simcore_service_webserver/groups/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/groups/_handlers.py @@ -43,8 +43,8 @@ class _GroupsRequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] def _handle_groups_exceptions(handler: Handler): diff --git a/services/web/server/src/simcore_service_webserver/login/_registration.py b/services/web/server/src/simcore_service_webserver/login/_registration.py index 7da8a7b1085..322dbb026c4 100644 --- a/services/web/server/src/simcore_service_webserver/login/_registration.py +++ b/services/web/server/src/simcore_service_webserver/login/_registration.py @@ -74,9 +74,7 @@ class InvitationData(BaseModel): class _InvitationValidator(BaseModel): action: ConfirmationAction - data: Json[ # type: ignore[type-arg] # pydantic upgrade to 1.10 needed # pylint: disable=unsubscriptable-object - InvitationData - ] + data: Json[InvitationData] # pylint: disable=unsubscriptable-object @validator("action", pre=True) @classmethod @@ -278,7 +276,7 @@ async def check_and_consume_invitation( # database-type invitations if confirmation_token := await validate_confirmation_code(invitation_code, db, cfg): try: - invitation_data: InvitationData = _InvitationValidator.parse_obj( # type: ignore[assignment] # need to update pydantic + invitation_data: InvitationData = _InvitationValidator.parse_obj( confirmation_token ).data return invitation_data diff --git a/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py b/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py index 318dcfb34f4..2ad608e3c12 100644 --- a/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py +++ b/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py @@ -89,8 +89,8 @@ async def request_product_account(request: web.Request): class _AuthenticatedContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] @routes.post(f"/{API_VTAG}/auth/unregister", name="unregister_account") diff --git a/services/web/server/src/simcore_service_webserver/login/cli.py b/services/web/server/src/simcore_service_webserver/login/cli.py index cc682852d2a..561ec8c1e9f 100644 --- a/services/web/server/src/simcore_service_webserver/login/cli.py +++ b/services/web/server/src/simcore_service_webserver/login/cli.py @@ -19,7 +19,7 @@ def invitations( ): """Generates a list of invitation links for registration""" - invitation = InvitationData(issuer=issuer_email, trial_account_days=trial_days) + invitation = InvitationData(issuer=issuer_email, trial_account_days=trial_days) # type: ignore[call-arg] # guest field is deprecated codes = [generate_password(code_length) for _ in range(num_codes)] diff --git a/services/web/server/src/simcore_service_webserver/long_running_tasks.py b/services/web/server/src/simcore_service_webserver/long_running_tasks.py index 7f689c28f33..a7e4e8c725b 100644 --- a/services/web/server/src/simcore_service_webserver/long_running_tasks.py +++ b/services/web/server/src/simcore_service_webserver/long_running_tasks.py @@ -18,8 +18,8 @@ class _RequestContext(RequestParams): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] def _webserver_request_context_decorator(handler: Handler): diff --git a/services/web/server/src/simcore_service_webserver/meta_modeling/_function_nodes.py b/services/web/server/src/simcore_service_webserver/meta_modeling/_function_nodes.py index e7b5637d77a..c51f3374510 100644 --- a/services/web/server/src/simcore_service_webserver/meta_modeling/_function_nodes.py +++ b/services/web/server/src/simcore_service_webserver/meta_modeling/_function_nodes.py @@ -15,6 +15,7 @@ from models_library.function_services_catalog import catalog, is_iterator_service from models_library.projects_nodes import Node +from models_library.services_types import ServiceKey, ServiceVersion # META-FUNCTIONS --------------------------------------------------- assert catalog # nosec @@ -31,12 +32,12 @@ def create_param_node_from_iterator_with_outputs(iterator_node: Node) -> Node: assert iterator_node.version == "1.0.0" # nosec return Node( - key="simcore/services/frontend/parameter/integer", - version="1.0.0", + key=ServiceKey("simcore/services/frontend/parameter/integer"), + version=ServiceVersion("1.0.0"), label=iterator_node.label, inputs={}, inputNodes=[], - thumbnail="", # NOTE: hack due to issue in projects json-schema + thumbnail="", # type: ignore[arg-type] # NOTE: hack due to issue in projects json-schema outputs=deepcopy(iterator_node.outputs), ) diff --git a/services/web/server/src/simcore_service_webserver/meta_modeling/_results.py b/services/web/server/src/simcore_service_webserver/meta_modeling/_results.py index 2929ff6a7eb..68829e3489a 100644 --- a/services/web/server/src/simcore_service_webserver/meta_modeling/_results.py +++ b/services/web/server/src/simcore_service_webserver/meta_modeling/_results.py @@ -112,5 +112,5 @@ def extract_project_results(workbench: dict[str, Any]) -> ExtractedResults: values = node["outputs"] results[noid], labels[noid] = values, label - res = ExtractedResults(progress=progress, labels=labels, values=results) + res = ExtractedResults(progress=progress, labels=labels, values=results) # type: ignore[arg-type] return res diff --git a/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py b/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py index 1e2a8a60625..f1c9f9df733 100644 --- a/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py +++ b/services/web/server/src/simcore_service_webserver/payments/_onetime_api.py @@ -11,6 +11,7 @@ PaymentTransaction, WalletPaymentInitiated, ) +from models_library.basic_types import IDStr from models_library.products import ProductName from models_library.users import UserID from models_library.wallets import WalletID @@ -99,7 +100,7 @@ async def _fake_init_payment( initiated_at=arrow.utcnow().datetime, ) return WalletPaymentInitiated( - payment_id=payment_id, payment_form_url=f"{external_form_link}" + payment_id=IDStr(payment_id), payment_form_url=f"{external_form_link}" # type: ignore[arg-type] ) diff --git a/services/web/server/src/simcore_service_webserver/products/_db.py b/services/web/server/src/simcore_service_webserver/products/_db.py index d0317fdc61b..37a960bf9a4 100644 --- a/services/web/server/src/simcore_service_webserver/products/_db.py +++ b/services/web/server/src/simcore_service_webserver/products/_db.py @@ -100,7 +100,7 @@ async def get_product(self, product_name: str) -> Product | None: return Product( **dict(row.items()), is_payment_enabled=payments.enabled, - credits_per_usd=payments.credits_per_usd, + credits_per_usd=payments.credits_per_usd, # type: ignore[arg-type] ) return None diff --git a/services/web/server/src/simcore_service_webserver/products/_events.py b/services/web/server/src/simcore_service_webserver/products/_events.py index 22f7ced4f33..64726ce55c3 100644 --- a/services/web/server/src/simcore_service_webserver/products/_events.py +++ b/services/web/server/src/simcore_service_webserver/products/_events.py @@ -90,7 +90,7 @@ async def load_products_on_startup(app: web.Application): app_products[name] = Product( **dict(row.items()), is_payment_enabled=payments.enabled, - credits_per_usd=payments.credits_per_usd, + credits_per_usd=payments.credits_per_usd, # type: ignore[arg-type] ) assert name in FRONTEND_APPS_AVAILABLE # nosec diff --git a/services/web/server/src/simcore_service_webserver/products/_handlers.py b/services/web/server/src/simcore_service_webserver/products/_handlers.py index 4803475b0af..bfdabef6d6f 100644 --- a/services/web/server/src/simcore_service_webserver/products/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/products/_handlers.py @@ -28,8 +28,8 @@ class _ProductsRequestContext(RequestParams): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] @routes.get(f"/{VTAG}/credits-price", name="get_current_product_price") @@ -41,8 +41,8 @@ async def _get_current_product_price(request: web.Request): credit_price = GetCreditPrice( product_name=req_ctx.product_name, - usd_per_credit=price_info.usd_per_credit if price_info else None, - min_payment_amount_usd=price_info.min_payment_amount_usd + usd_per_credit=price_info.usd_per_credit if price_info else None, # type: ignore[arg-type] + min_payment_amount_usd=price_info.min_payment_amount_usd # type: ignore[arg-type] if price_info else None, ) diff --git a/services/web/server/src/simcore_service_webserver/products/_invitations_handlers.py b/services/web/server/src/simcore_service_webserver/products/_invitations_handlers.py index b05dfcdf090..093e925db3d 100644 --- a/services/web/server/src/simcore_service_webserver/products/_invitations_handlers.py +++ b/services/web/server/src/simcore_service_webserver/products/_invitations_handlers.py @@ -27,8 +27,8 @@ class _ProductsRequestContext(RequestParams): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] @routes.post(f"/{VTAG}/invitation:generate", name="generate_invitation") @@ -60,11 +60,11 @@ async def generate_invitation(request: web.Request): invitation = InvitationGenerated( product_name=generated.product, - issuer=generated.issuer, - guest=generated.guest, + issuer=generated.issuer, # type: ignore[arg-type] + guest=generated.guest, # type: ignore[arg-type] trial_account_days=generated.trial_account_days, extra_credits_in_usd=generated.extra_credits_in_usd, created=generated.created, - invitation_link=f"{invitation_link}", + invitation_link=f"{invitation_link}", # type: ignore[arg-type] ) return envelope_json_response(invitation.dict(exclude_none=True)) diff --git a/services/web/server/src/simcore_service_webserver/projects/_common_models.py b/services/web/server/src/simcore_service_webserver/projects/_common_models.py index 091df0ef49a..d25a0f6c24b 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_common_models.py +++ b/services/web/server/src/simcore_service_webserver/projects/_common_models.py @@ -13,8 +13,8 @@ class RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] class ProjectPathParams(BaseModel): diff --git a/services/web/server/src/simcore_service_webserver/projects/_crud_handlers_models.py b/services/web/server/src/simcore_service_webserver/projects/_crud_handlers_models.py index 369b240a004..0fc3489c8a6 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_crud_handlers_models.py +++ b/services/web/server/src/simcore_service_webserver/projects/_crud_handlers_models.py @@ -26,18 +26,18 @@ class ProjectCreateHeaders(BaseModel): - simcore_user_agent: str = Field( + simcore_user_agent: str = Field( # type: ignore[literal-required] default=UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE, description="Optional simcore user agent", alias=X_SIMCORE_USER_AGENT, ) - parent_project_uuid: ProjectID | None = Field( + parent_project_uuid: ProjectID | None = Field( # type: ignore[literal-required] default=None, description="Optional parent project UUID", alias=X_SIMCORE_PARENT_PROJECT_UUID, ) - parent_node_id: NodeID | None = Field( + parent_node_id: NodeID | None = Field( # type: ignore[literal-required] default=None, description="Optional parent node ID", alias=X_SIMCORE_PARENT_NODE_ID, @@ -112,7 +112,7 @@ def search_check_empty_string(cls, v): class ProjectListWithJsonStrParams(ProjectListParams): - order_by: Json[OrderBy] = Field( # type: ignore[type-arg] # need update to pydantic 1.10 # pylint: disable=unsubscriptable-object + order_by: Json[OrderBy] = Field( # pylint: disable=unsubscriptable-object default=OrderBy(field=IDStr("last_change_date"), direction=OrderDirection.DESC), description="Order by field (type|uuid|name|description|prj_owner|creation_date|last_change_date) and direction (asc|desc). The default sorting order is ascending.", example='{"field": "prj_owner", "direction": "desc"}', diff --git a/services/web/server/src/simcore_service_webserver/projects/_nodes_api.py b/services/web/server/src/simcore_service_webserver/projects/_nodes_api.py index 22866cf6b2a..ab6ba4b7d93 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_nodes_api.py +++ b/services/web/server/src/simcore_service_webserver/projects/_nodes_api.py @@ -233,7 +233,7 @@ async def get_node_screenshots( file_url = await get_download_link(app, user_id, filelink) screenshots.append( NodeScreenshot( - thumbnail_url=f"https://placehold.co/170x120?text={text}", + thumbnail_url=f"https://placehold.co/170x120?text={text}", # type: ignore[arg-type] file_url=file_url, ) ) diff --git a/services/web/server/src/simcore_service_webserver/projects/_ports_api.py b/services/web/server/src/simcore_service_webserver/projects/_ports_api.py index 30b7bd2ca12..95a42f32046 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_ports_api.py +++ b/services/web/server/src/simcore_service_webserver/projects/_ports_api.py @@ -212,7 +212,7 @@ def _get_outputs_in_workbench(workbench: dict[NodeID, Node]) -> dict[NodeID, Any async def _get_computation_tasks_outputs( app: web.Application, *, project_id: ProjectID, nodes_ids: set[NodeID] ) -> dict[NodeID, dict[OutputName, Any]]: - selection = TasksSelection(nodes_ids=nodes_ids) + selection = TasksSelection(nodes_ids=list(nodes_ids)) batch: TasksOutputs = await get_batch_tasks_outputs( app, project_id=project_id, selection=selection ) diff --git a/services/web/server/src/simcore_service_webserver/projects/_projects_nodes_pricing_unit_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_projects_nodes_pricing_unit_handlers.py index 2c4f7f940bb..552869a0404 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_projects_nodes_pricing_unit_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_projects_nodes_pricing_unit_handlers.py @@ -87,7 +87,7 @@ async def get_project_node_pricing_unit(request: web.Request): webserver_pricing_unit_get = PricingUnitGet( pricing_unit_id=pricing_unit_get.pricing_unit_id, unit_name=pricing_unit_get.unit_name, - unit_extra_info=pricing_unit_get.unit_extra_info, + unit_extra_info=pricing_unit_get.unit_extra_info, # type: ignore[arg-type] current_cost_per_unit=pricing_unit_get.current_cost_per_unit, default=pricing_unit_get.default, ) diff --git a/services/web/server/src/simcore_service_webserver/projects/db.py b/services/web/server/src/simcore_service_webserver/projects/db.py index 0431d4a5a21..ab49bb67036 100644 --- a/services/web/server/src/simcore_service_webserver/projects/db.py +++ b/services/web/server/src/simcore_service_webserver/projects/db.py @@ -15,6 +15,7 @@ from aiopg.sa import Engine from aiopg.sa.connection import SAConnection from aiopg.sa.result import ResultProxy, RowProxy +from models_library.basic_types import IDStr from models_library.folders import FolderID from models_library.projects import ProjectID, ProjectIDStr from models_library.projects_comments import CommentID, ProjectsCommentsDB @@ -332,7 +333,7 @@ async def list_projects( # pylint: disable=too-many-arguments limit: int | None = None, search: str | None = None, order_by: OrderBy = OrderBy( - field="last_change_date", direction=OrderDirection.DESC + field=IDStr("last_change_date"), direction=OrderDirection.DESC ), folder_id: FolderID | None = None, ) -> tuple[list[dict[str, Any]], list[ProjectType], int]: diff --git a/services/web/server/src/simcore_service_webserver/projects/lock.py b/services/web/server/src/simcore_service_webserver/projects/lock.py index 8a7ff51576d..eccab79c45a 100644 --- a/services/web/server/src/simcore_service_webserver/projects/lock.py +++ b/services/web/server/src/simcore_service_webserver/projects/lock.py @@ -53,7 +53,7 @@ async def lock_project( blocking=False, token=ProjectLocked( value=True, - owner=Owner(user_id=user_id, **user_fullname), + owner=Owner(user_id=user_id, **user_fullname), # type: ignore[arg-type] status=status, ).json(), ): diff --git a/services/web/server/src/simcore_service_webserver/projects/projects_api.py b/services/web/server/src/simcore_service_webserver/projects/projects_api.py index a8829e7f084..8d3c0783111 100644 --- a/services/web/server/src/simcore_service_webserver/projects/projects_api.py +++ b/services/web/server/src/simcore_service_webserver/projects/projects_api.py @@ -1337,7 +1337,7 @@ async def _get_project_lock_state( ) return ProjectLocked( value=False, - owner=Owner(user_id=list(set_user_ids)[0], **usernames[0]), + owner=Owner(user_id=list(set_user_ids)[0], **usernames[0]), # type: ignore[arg-type] status=ProjectStatus.OPENED, ) # the project is opened in another tab or browser, or by another user, both case resolves to the project being locked, and opened @@ -1348,7 +1348,7 @@ async def _get_project_lock_state( ) return ProjectLocked( value=True, - owner=Owner(user_id=list(set_user_ids)[0], **usernames[0]), + owner=Owner(user_id=list(set_user_ids)[0], **usernames[0]), # type: ignore[arg-type] status=ProjectStatus.OPENED, ) diff --git a/services/web/server/src/simcore_service_webserver/resource_usage/_client.py b/services/web/server/src/simcore_service_webserver/resource_usage/_client.py index fa26d50caa9..63763aa145b 100644 --- a/services/web/server/src/simcore_service_webserver/resource_usage/_client.py +++ b/services/web/server/src/simcore_service_webserver/resource_usage/_client.py @@ -87,7 +87,8 @@ async def get_default_service_pricing_plan( ) -> PricingPlanGet: settings: ResourceUsageTrackerSettings = get_plugin_settings(app) url = URL( - f"{settings.api_base_url}/services/{urllib.parse.quote_plus(service_key)}/{service_version}/pricing-plan" + f"{settings.api_base_url}/services/{urllib.parse.quote_plus(service_key)}/{service_version}/pricing-plan", + encoded=True, ).with_query( { "product_name": product_name, diff --git a/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_admin_handlers.py b/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_admin_handlers.py index c79058fe791..b71317b1aab 100644 --- a/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_admin_handlers.py +++ b/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_admin_handlers.py @@ -56,8 +56,8 @@ async def wrapper(request: web.Request) -> web.StreamResponse: class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] # @@ -138,7 +138,7 @@ async def get_pricing_plan(request: web.Request): PricingUnitAdminGet( pricing_unit_id=pricing_unit.pricing_unit_id, unit_name=pricing_unit.unit_name, - unit_extra_info=pricing_unit.unit_extra_info, + unit_extra_info=pricing_unit.unit_extra_info, # type: ignore[arg-type] specific_info=pricing_unit.specific_info, current_cost_per_unit=pricing_unit.current_cost_per_unit, default=pricing_unit.default, @@ -187,7 +187,7 @@ async def create_pricing_plan(request: web.Request): PricingUnitAdminGet( pricing_unit_id=pricing_unit.pricing_unit_id, unit_name=pricing_unit.unit_name, - unit_extra_info=pricing_unit.unit_extra_info, + unit_extra_info=pricing_unit.unit_extra_info, # type: ignore[arg-type] specific_info=pricing_unit.specific_info, current_cost_per_unit=pricing_unit.current_cost_per_unit, default=pricing_unit.default, @@ -237,7 +237,7 @@ async def update_pricing_plan(request: web.Request): PricingUnitAdminGet( pricing_unit_id=pricing_unit.pricing_unit_id, unit_name=pricing_unit.unit_name, - unit_extra_info=pricing_unit.unit_extra_info, + unit_extra_info=pricing_unit.unit_extra_info, # type: ignore[arg-type] specific_info=pricing_unit.specific_info, current_cost_per_unit=pricing_unit.current_cost_per_unit, default=pricing_unit.default, @@ -282,7 +282,7 @@ async def get_pricing_unit(request: web.Request): webserver_pricing_unit_get = PricingUnitAdminGet( pricing_unit_id=pricing_unit_get.pricing_unit_id, unit_name=pricing_unit_get.unit_name, - unit_extra_info=pricing_unit_get.unit_extra_info, + unit_extra_info=pricing_unit_get.unit_extra_info, # type: ignore[arg-type] specific_info=pricing_unit_get.specific_info, current_cost_per_unit=pricing_unit_get.current_cost_per_unit, default=pricing_unit_get.default, @@ -321,7 +321,7 @@ async def create_pricing_unit(request: web.Request): webserver_pricing_unit_get = PricingUnitAdminGet( pricing_unit_id=pricing_unit_get.pricing_unit_id, unit_name=pricing_unit_get.unit_name, - unit_extra_info=pricing_unit_get.unit_extra_info, + unit_extra_info=pricing_unit_get.unit_extra_info, # type: ignore[arg-type] specific_info=pricing_unit_get.specific_info, current_cost_per_unit=pricing_unit_get.current_cost_per_unit, default=pricing_unit_get.default, @@ -360,7 +360,7 @@ async def update_pricing_unit(request: web.Request): webserver_pricing_unit_get = PricingUnitAdminGet( pricing_unit_id=pricing_unit_get.pricing_unit_id, unit_name=pricing_unit_get.unit_name, - unit_extra_info=pricing_unit_get.unit_extra_info, + unit_extra_info=pricing_unit_get.unit_extra_info, # type: ignore[arg-type] specific_info=pricing_unit_get.specific_info, current_cost_per_unit=pricing_unit_get.current_cost_per_unit, default=pricing_unit_get.default, diff --git a/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_handlers.py b/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_handlers.py index 191abec399a..86072f00e5e 100644 --- a/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_handlers.py +++ b/services/web/server/src/simcore_service_webserver/resource_usage/_pricing_plans_handlers.py @@ -35,8 +35,8 @@ async def wrapper(request: web.Request) -> web.StreamResponse: class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] # @@ -77,7 +77,7 @@ async def get_pricing_plan_unit(request: web.Request): webserver_pricing_unit_get = PricingUnitGet( pricing_unit_id=pricing_unit_get.pricing_unit_id, unit_name=pricing_unit_get.unit_name, - unit_extra_info=pricing_unit_get.unit_extra_info, + unit_extra_info=pricing_unit_get.unit_extra_info, # type: ignore[arg-type] current_cost_per_unit=pricing_unit_get.current_cost_per_unit, default=pricing_unit_get.default, ) diff --git a/services/web/server/src/simcore_service_webserver/resource_usage/_service_runs_handlers.py b/services/web/server/src/simcore_service_webserver/resource_usage/_service_runs_handlers.py index 1539168e03d..f265e45faf1 100644 --- a/services/web/server/src/simcore_service_webserver/resource_usage/_service_runs_handlers.py +++ b/services/web/server/src/simcore_service_webserver/resource_usage/_service_runs_handlers.py @@ -62,8 +62,8 @@ async def wrapper(request: web.Request) -> web.StreamResponse: class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] ORDER_BY_DESCRIPTION = "Order by field (wallet_id|wallet_name|user_id|project_id|project_name|node_id|node_name|service_key|service_version|service_type|started_at|stopped_at|service_run_status|credit_cost|transaction_status) and direction (asc|desc). The default sorting order is ascending." @@ -71,12 +71,12 @@ class _RequestContext(BaseModel): class _ListServicesResourceUsagesQueryParams(BaseModel): wallet_id: WalletID | None = Field(default=None) - order_by: Json[OrderBy] = Field( # type: ignore[type-arg] # need to update pydantic # pylint: disable=unsubscriptable-object + order_by: Json[OrderBy] = Field( # pylint: disable=unsubscriptable-object default=OrderBy(field=IDStr("started_at"), direction=OrderDirection.DESC), description=ORDER_BY_DESCRIPTION, example='{"field": "started_at", "direction": "desc"}', ) - filters: ( # type: ignore[type-arg] # need to update pydantic + filters: ( Json[ServiceResourceUsagesFilters] # pylint: disable=unsubscriptable-object | None ) = Field( diff --git a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_projects.py b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_projects.py index 4c1f0de2d06..e4b71213ee6 100644 --- a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_projects.py +++ b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_projects.py @@ -12,7 +12,7 @@ from typing import NamedTuple from aiohttp import web -from models_library.projects import Project, ProjectID +from models_library.projects import DateTimeStr, Project, ProjectID from models_library.projects_access import AccessRights from models_library.projects_nodes import Node from models_library.projects_nodes_io import DownloadLink, NodeID, PortLink @@ -69,7 +69,7 @@ def _create_file_picker(download_link: str, output_label: str | None): label="File Picker", inputs={}, inputNodes=[], - outputs={output_id: output}, + outputs={output_id: output}, # type: ignore[dict-item] progress=0, ) return node, output_id @@ -94,13 +94,13 @@ def _create_project( uuid=project_id, name=name, description=description, - thumbnail=thumbnail, + thumbnail=thumbnail, # type: ignore[arg-type] prjOwner=owner.email, - accessRights={owner.primary_gid: access_rights}, - creationDate=now_str(), - lastChangeDate=now_str(), - workbench=workbench, - ui=StudyUI(workbench=workbench_ui), + accessRights={owner.primary_gid: access_rights}, # type: ignore[dict-item] + creationDate=DateTimeStr(now_str()), + lastChangeDate=DateTimeStr(now_str()), + workbench=workbench, # type: ignore[arg-type] + ui=StudyUI(workbench=workbench_ui), # type: ignore[arg-type] ) return project @@ -153,7 +153,7 @@ def _create_project_with_filepicker_and_service( version=viewer_info.version, label=viewer_info.label, inputs={ - viewer_info.input_port_key: PortLink( + viewer_info.input_port_key: PortLink( # type: ignore[dict-item] nodeUuid=file_picker_id, output=file_picker_output_id, ) diff --git a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_rest_handlers.py b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_rest_handlers.py index a96a87d8cc4..9f66cd460b0 100644 --- a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_rest_handlers.py +++ b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_rest_handlers.py @@ -8,6 +8,7 @@ from aiohttp import web from aiohttp.web import Request from models_library.services import ServiceKey +from models_library.services_types import ServiceVersion from pydantic import BaseModel, Field, ValidationError, parse_obj_as, validator from pydantic.networks import HttpUrl @@ -43,7 +44,8 @@ def _compose_service_only_dispatcher_prefix_url( request: web.Request, service_key: str, service_version: str ) -> HttpUrl: params = ViewerQueryParams( - viewer_key=service_key, viewer_version=service_version + viewer_key=ServiceKey(service_key), + viewer_version=ServiceVersion(service_version), ).dict(exclude_none=True, exclude_unset=True) absolute_url = request.url.join( request.app.router["get_redirection_to_viewer"].url_for().with_query(**params) diff --git a/services/web/server/src/simcore_service_webserver/tags/_handlers.py b/services/web/server/src/simcore_service_webserver/tags/_handlers.py index 8603cce3d28..df95777ae80 100644 --- a/services/web/server/src/simcore_service_webserver/tags/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/tags/_handlers.py @@ -47,7 +47,7 @@ async def wrapper(request: web.Request) -> web.StreamResponse: class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] class _InputSchema(BaseModel): @@ -108,7 +108,7 @@ def from_db(cls, tag: TagDict) -> "TagGet": name=tag["name"], description=tag["description"], color=tag["color"], - access_rights=TagAccessRights( + access_rights=TagAccessRights( # type: ignore[call-arg] read=tag["read"], write=tag["write"], delete=tag["delete"], diff --git a/services/web/server/src/simcore_service_webserver/users/_handlers.py b/services/web/server/src/simcore_service_webserver/users/_handlers.py index 3b9f40ea84d..ede00340d4e 100644 --- a/services/web/server/src/simcore_service_webserver/users/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/users/_handlers.py @@ -30,8 +30,8 @@ class UsersRequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] def _handle_users_exceptions(handler: Handler): diff --git a/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py b/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py index cae7c4c5485..9f5513b904f 100644 --- a/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py +++ b/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py @@ -29,8 +29,8 @@ class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: ProductName = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: ProductName = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] def _handle_users_exceptions(handler: Handler): diff --git a/services/web/server/src/simcore_service_webserver/users/api.py b/services/web/server/src/simcore_service_webserver/users/api.py index afd406bf774..7b913f937cf 100644 --- a/services/web/server/src/simcore_service_webserver/users/api.py +++ b/services/web/server/src/simcore_service_webserver/users/api.py @@ -123,7 +123,7 @@ async def get_user_profile( last_name=user_profile["last_name"], login=user_profile["login"], role=user_profile["role"], - groups={ + groups={ # type: ignore[arg-type] "me": user_primary_group, "organizations": user_standard_groups, "all": all_group, diff --git a/services/web/server/src/simcore_service_webserver/version_control/models.py b/services/web/server/src/simcore_service_webserver/version_control/models.py index ce1178341b9..a562459547e 100644 --- a/services/web/server/src/simcore_service_webserver/version_control/models.py +++ b/services/web/server/src/simcore_service_webserver/version_control/models.py @@ -44,7 +44,7 @@ def from_commit_log(cls, commit: RowProxy, tags: list[RowProxy]) -> "Checkpoint" checksum=commit.snapshot_checksum, tags=tuple(tag.name for tag in tags), message=commit.message, - parents_ids=(commit.parent_commit_id,) if commit.parent_commit_id else None, + parents_ids=(commit.parent_commit_id,) if commit.parent_commit_id else None, # type: ignore[arg-type] created_at=commit.created, ) diff --git a/services/web/server/src/simcore_service_webserver/wallets/_api.py b/services/web/server/src/simcore_service_webserver/wallets/_api.py index b2638b56d80..2f4752277da 100644 --- a/services/web/server/src/simcore_service_webserver/wallets/_api.py +++ b/services/web/server/src/simcore_service_webserver/wallets/_api.py @@ -9,6 +9,7 @@ WalletGetPermissions, WalletGetWithAvailableCredits, ) +from models_library.basic_types import IDStr from models_library.products import ProductName from models_library.users import UserID from models_library.wallets import UserWalletDB, WalletDB, WalletID, WalletStatus @@ -65,7 +66,7 @@ async def list_wallets_with_available_credits_for_user( wallets_api.append( WalletGetWithAvailableCredits( wallet_id=wallet.wallet_id, - name=wallet.name, + name=IDStr(wallet.name), description=wallet.description, owner=wallet.owner, thumbnail=wallet.thumbnail, @@ -96,7 +97,7 @@ async def get_wallet_with_available_credits_by_user_and_wallet( return WalletGetWithAvailableCredits( wallet_id=user_wallet_db.wallet_id, - name=user_wallet_db.name, + name=IDStr(user_wallet_db.name), description=user_wallet_db.description, owner=user_wallet_db.owner, thumbnail=user_wallet_db.thumbnail, @@ -223,7 +224,7 @@ async def get_wallet_by_user( wallet_api: WalletGet = WalletGet( wallet_id=wallet.wallet_id, - name=wallet.name, + name=IDStr(wallet.name), description=wallet.description, owner=wallet.owner, thumbnail=wallet.thumbnail, diff --git a/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py b/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py index 723ea2655c6..6690d6d41e4 100644 --- a/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py +++ b/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py @@ -31,8 +31,8 @@ class _RequestContext(BaseModel): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] def _handle_wallets_groups_exceptions(handler: Handler): diff --git a/services/web/server/src/simcore_service_webserver/wallets/_handlers.py b/services/web/server/src/simcore_service_webserver/wallets/_handlers.py index 0168b71eff9..0b43bbea59a 100644 --- a/services/web/server/src/simcore_service_webserver/wallets/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/wallets/_handlers.py @@ -91,8 +91,8 @@ async def wrapper(request: web.Request) -> web.StreamResponse: class WalletsRequestContext(RequestParams): - user_id: UserID = Field(..., alias=RQT_USERID_KEY) - product_name: str = Field(..., alias=RQ_PRODUCT_KEY) + user_id: UserID = Field(..., alias=RQT_USERID_KEY) # type: ignore[literal-required] + product_name: str = Field(..., alias=RQ_PRODUCT_KEY) # type: ignore[literal-required] class WalletsPathParams(StrictRequestParams): diff --git a/services/web/server/tests/unit/isolated/test_application_settings.py b/services/web/server/tests/unit/isolated/test_application_settings.py index 8300fc3a73c..9b03e109202 100644 --- a/services/web/server/tests/unit/isolated/test_application_settings.py +++ b/services/web/server/tests/unit/isolated/test_application_settings.py @@ -81,7 +81,7 @@ def mock_env_dockerfile_build(monkeypatch: pytest.MonkeyPatch) -> EnvVarsDict: PYTHON_GET_PIP_SHA256=6123659241292b2147b58922b9ffe11dda66b39d52d8a6f3aa310bc1d60ea6f7 PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/a1675ab6c2bd898ed82b1f58c486097f763c74a9/public/get-pip.py PYTHON_PIP_VERSION=21.1.3 - PYTHON_VERSION=3.10.14 + PYTHON_VERSION=3.11.9 PYTHONDONTWRITEBYTECODE=1 PYTHONOPTIMIZE=TRUE SC_BOOT_MODE=production diff --git a/services/web/server/tests/unit/isolated/test_utils.py b/services/web/server/tests/unit/isolated/test_utils.py index 4b609ceaf3a..a0a89e36458 100644 --- a/services/web/server/tests/unit/isolated/test_utils.py +++ b/services/web/server/tests/unit/isolated/test_utils.py @@ -5,10 +5,8 @@ import urllib.parse from contextlib import contextmanager from datetime import datetime -from urllib.parse import unquote_plus import pytest -import yarl from simcore_service_webserver.utils import ( DATETIME_FORMAT, compose_support_error_msg, @@ -19,6 +17,30 @@ from yarl import URL +def test_yarl_new_url_generation(): + api_endpoint = URL("http://director:8001/v0") + service_key = "simcore/services/dynamic/smash" + service_version = "1.0.3" + + quoted_service_key = urllib.parse.quote(service_key, safe="") + + # Since 1.6.x composition using '/' creates URLs with auto-encoding enabled by default + assert ( + (str(api_endpoint / "services" / quoted_service_key / service_version)) + == "http://director:8001/v0/services/simcore%252Fservices%252Fdynamic%252Fsmash/1.0.3" + ) + + # Passing encoded=True parameter prevents URL auto-encoding, user is responsible about URL correctness + url = URL( + f"http://director:8001/v0/services/{quoted_service_key}/1.0.3", encoded=True + ) + + assert ( + (str(url)) + == "http://director:8001/v0/services/simcore%2Fservices%2Fdynamic%2Fsmash/1.0.3" + ) + + def test_time_utils(): snapshot0 = now_str() @@ -35,45 +57,6 @@ def test_time_utils(): assert now_time == datetime.strptime(snapshot, DATETIME_FORMAT) -def test_yarl_url_compose_changed_with_latest_release(): - # TODO: add tests and do this upgrade carefuly. Part of https://github.com/ITISFoundation/osparc-simcore/issues/2008 - # - # With yarl=1.6.* failed tests/unit/isolated/test_director_api.py::test_director_workflow - # - # Actually is more consistent since - # services/simcore%2Fservices%2Fdynamic%2Fsmash/1.0.3 is decoposed as [services, simcore%2Fservices%2Fdynamic%2Fsmash, 1.0.3] - # - api_endpoint = URL("http://director:8001/v0") - service_key = "simcore/services/dynamic/smash" - service_version = "1.0.3" - - url = ( - api_endpoint - / "services" - / urllib.parse.quote(service_key, safe="") - / service_version - ) - - assert ( - "/", - "v0", - "services", - service_key, - service_version, - ) == url.parts, f"In yarl==1.5.1, this fails in {yarl.__version__}" - - assert "simcore/services/dynamic/smash/1.0.3" == unquote_plus( - "simcore%2Fservices%2Fdynamic%2Fsmash/1.0.3" - ) - assert ( - urllib.parse.quote(service_key, safe="") - == "simcore%2Fservices%2Fdynamic%2Fsmash" - ) - assert ( - urllib.parse.quote_plus(service_key) == "simcore%2Fservices%2Fdynamic%2Fsmash" - ) - - @pytest.mark.skip(reason="DEV-demo") async def test_compute_sha1_on_small_dataset(fake_project: dict): # Based on GitHK review https://github.com/ITISFoundation/osparc-simcore/pull/2556: diff --git a/services/web/server/tests/unit/with_dbs/01/test_resource_manager_user_sessions.py b/services/web/server/tests/unit/with_dbs/01/test_resource_manager_user_sessions.py index 403dfbc6a2e..9e46f5a27f7 100644 --- a/services/web/server/tests/unit/with_dbs/01/test_resource_manager_user_sessions.py +++ b/services/web/server/tests/unit/with_dbs/01/test_resource_manager_user_sessions.py @@ -28,6 +28,7 @@ UserSessionID, managed_resource, ) +from tenacity import AsyncRetrying, stop_after_delay, wait_fixed @pytest.fixture @@ -188,10 +189,18 @@ def get_random_int(): await redis_registry.set_key_alive(first_key, 0) await redis_registry.set_key_alive(second_key, -3000) - time.sleep(1) # minimum amount of sleep - - assert await redis_registry.is_key_alive(second_key) is False - assert await redis_registry.is_key_alive(first_key) is False + async for attempt in AsyncRetrying( + wait=wait_fixed(0.1), + stop=stop_after_delay(5), + reraise=True, + ): + + with attempt: + print( + f"checking redis registry for keys alive, [attempt {attempt.retry_state.attempt_number}]..." + ) + assert await redis_registry.is_key_alive(second_key) is False + assert await redis_registry.is_key_alive(first_key) is False alive_keys, dead_keys = await redis_registry.get_all_resource_keys() assert len(alive_keys) == 0