From 1c97a06fcc597d53f797919eb84bb564f65a7ac6 Mon Sep 17 00:00:00 2001 From: matusdrobuliak66 Date: Sat, 22 Apr 2023 18:02:50 +0200 Subject: [PATCH 1/4] mypy webserver - product plugin --- .../simcore_service_webserver/application.py | 2 +- .../products/__init__.py | 0 .../{products_db.py => products/_db.py} | 19 +++++------ .../_events.py} | 10 +++--- .../_middlewares.py} | 6 ++-- .../{products_model.py => products/_model.py} | 28 ++++++++-------- .../{products.py => products/plugin.py} | 32 +++++++++++-------- .../integration/01/test_project_workflow.py | 2 +- .../tests/integration/02/test_computation.py | 23 ++++++------- .../isolated/test_products_middlewares.py | 8 ++--- .../unit/isolated/test_products_model.py | 2 +- .../test_resource_manager.py | 2 +- .../unit/with_dbs/03/login/test_login_2fa.py | 2 +- .../03/{ => products}/test_products_db.py | 8 +++-- .../tests/unit/with_dbs/03/tags/conftest.py | 2 +- 15 files changed, 75 insertions(+), 71 deletions(-) create mode 100644 services/web/server/src/simcore_service_webserver/products/__init__.py rename services/web/server/src/simcore_service_webserver/{products_db.py => products/_db.py} (82%) rename services/web/server/src/simcore_service_webserver/{products_events.py => products/_events.py} (91%) rename services/web/server/src/simcore_service_webserver/{products_middlewares.py => products/_middlewares.py} (94%) rename services/web/server/src/simcore_service_webserver/{products_model.py => products/_model.py} (91%) rename services/web/server/src/simcore_service_webserver/{products.py => products/plugin.py} (81%) rename services/web/server/tests/unit/with_dbs/03/{ => products}/test_products_db.py (95%) diff --git a/services/web/server/src/simcore_service_webserver/application.py b/services/web/server/src/simcore_service_webserver/application.py index 69e8bbb739c..54b611d4b78 100644 --- a/services/web/server/src/simcore_service_webserver/application.py +++ b/services/web/server/src/simcore_service_webserver/application.py @@ -26,7 +26,7 @@ from .login.plugin import setup_login from .long_running_tasks import setup_long_running_tasks from .meta_modeling.plugin import setup_meta_modeling -from .products import setup_products +from .products.plugin import setup_products from .projects.plugin import setup_projects from .publications import setup_publications from .rabbitmq import setup_rabbitmq diff --git a/services/web/server/src/simcore_service_webserver/products/__init__.py b/services/web/server/src/simcore_service_webserver/products/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/services/web/server/src/simcore_service_webserver/products_db.py b/services/web/server/src/simcore_service_webserver/products/_db.py similarity index 82% rename from services/web/server/src/simcore_service_webserver/products_db.py rename to services/web/server/src/simcore_service_webserver/products/_db.py index 7794cf7853b..e8cdfb3a83c 100644 --- a/services/web/server/src/simcore_service_webserver/products_db.py +++ b/services/web/server/src/simcore_service_webserver/products/_db.py @@ -1,14 +1,14 @@ import logging -from typing import AsyncIterator, Optional +from typing import AsyncIterator import sqlalchemy as sa from aiopg.sa.connection import SAConnection from aiopg.sa.result import ResultProxy, RowProxy from simcore_postgres_database.models.products import jinja2_templates -from .db_base_repository import BaseRepository -from .db_models import products -from .products_model import Product +from ..db_base_repository import BaseRepository +from ..db_models import products +from ._model import Product log = logging.getLogger(__name__) @@ -31,30 +31,31 @@ async def iter_products(conn: SAConnection) -> AsyncIterator[ResultProxy]: class ProductRepository(BaseRepository): - async def get_product(self, product_name: str) -> Optional[Product]: + async def get_product(self, product_name: str) -> Product | None: async with self.engine.acquire() as conn: result: ResultProxy = await conn.execute( sa.select(_COLUMNS_IN_MODEL).where(products.c.name == product_name) ) - row: Optional[RowProxy] = await result.first() + row: RowProxy | None = await result.first() return Product.from_orm(row) if row else None async def get_template_content( self, template_name: str, - ) -> Optional[str]: + ) -> str | None: async with self.engine.acquire() as conn: - return await conn.scalar( + template_content: str | None = await conn.scalar( sa.select([jinja2_templates.c.content]).where( jinja2_templates.c.name == template_name ) ) + return template_content async def get_product_template_content( self, product_name: str, product_template: sa.Column = products.c.registration_email_template, - ) -> Optional[str]: + ) -> str | None: async with self.engine.acquire() as conn: oj = sa.join( products, diff --git a/services/web/server/src/simcore_service_webserver/products_events.py b/services/web/server/src/simcore_service_webserver/products/_events.py similarity index 91% rename from services/web/server/src/simcore_service_webserver/products_events.py rename to services/web/server/src/simcore_service_webserver/products/_events.py index 3dba2daab3c..dba76de3bb6 100644 --- a/services/web/server/src/simcore_service_webserver/products_events.py +++ b/services/web/server/src/simcore_service_webserver/products/_events.py @@ -11,10 +11,10 @@ get_or_create_product_group, ) -from ._constants import APP_DB_ENGINE_KEY, APP_PRODUCTS_KEY -from .products_db import iter_products -from .products_model import Product -from .statics_constants import FRONTEND_APP_DEFAULT, FRONTEND_APPS_AVAILABLE +from .._constants import APP_DB_ENGINE_KEY, APP_PRODUCTS_KEY +from ..products_db import iter_products +from ..products_model import Product +from ..statics_constants import FRONTEND_APP_DEFAULT, FRONTEND_APPS_AVAILABLE log = logging.getLogger(__name__) @@ -76,7 +76,7 @@ async def load_products_on_startup(app: web.Application): async with engine.acquire() as conn: async for row in iter_products(conn): try: - name = row.name # type:ignore + name = row.name app_products[name] = Product.from_orm(row) assert name in FRONTEND_APPS_AVAILABLE # nosec diff --git a/services/web/server/src/simcore_service_webserver/products_middlewares.py b/services/web/server/src/simcore_service_webserver/products/_middlewares.py similarity index 94% rename from services/web/server/src/simcore_service_webserver/products_middlewares.py rename to services/web/server/src/simcore_service_webserver/products/_middlewares.py index ba04ad63a71..27d0f10809b 100644 --- a/services/web/server/src/simcore_service_webserver/products_middlewares.py +++ b/services/web/server/src/simcore_service_webserver/products/_middlewares.py @@ -3,9 +3,9 @@ from aiohttp import web from servicelib.aiohttp.typing_extension import Handler -from ._constants import APP_PRODUCTS_KEY, RQ_PRODUCT_KEY, X_PRODUCT_NAME_HEADER -from ._meta import API_VTAG -from .products_model import Product +from .._constants import APP_PRODUCTS_KEY, RQ_PRODUCT_KEY, X_PRODUCT_NAME_HEADER +from .._meta import API_VTAG +from ._model import Product log = logging.getLogger(__name__) diff --git a/services/web/server/src/simcore_service_webserver/products_model.py b/services/web/server/src/simcore_service_webserver/products/_model.py similarity index 91% rename from services/web/server/src/simcore_service_webserver/products_model.py rename to services/web/server/src/simcore_service_webserver/products/_model.py index 673e3ca00da..ef7c4c21f9a 100644 --- a/services/web/server/src/simcore_service_webserver/products_model.py +++ b/services/web/server/src/simcore_service_webserver/products/_model.py @@ -1,6 +1,6 @@ import logging import string -from typing import Any, Optional, Pattern, Union +from typing import Any, Pattern from models_library.basic_regex import ( PUBLIC_VARIABLE_NAME_RE, @@ -20,8 +20,8 @@ WebFeedback, ) -from .db_models import products -from .statics_constants import FRONTEND_APPS_AVAILABLE +from ..db_models import products +from ..statics_constants import FRONTEND_APPS_AVAILABLE log = logging.getLogger(__name__) @@ -42,7 +42,7 @@ class Product(BaseModel): name: ProductName = Field(regex=PUBLIC_VARIABLE_NAME_RE) display_name: str = Field(..., description="Long display name") - short_name: Optional[str] = Field( + short_name: str | None = Field( None, regex=TWILIO_ALPHANUMERIC_SENDER_ID_RE, min_length=2, @@ -58,20 +58,20 @@ class Product(BaseModel): " Other support emails can be defined under 'support' field", ) - twilio_messaging_sid: Optional[str] = Field( + twilio_messaging_sid: str | None = Field( default=None, min_length=34, max_length=34, description="Identifier for SMS" ) - vendor: Optional[Vendor] = Field( + vendor: Vendor | None = Field( None, description="Vendor information such as company name, address, copyright, ...", ) - issues: Optional[list[IssueTracker]] = None + issues: list[IssueTracker] | None = None - manuals: Optional[list[Manual]] = None + manuals: list[Manual] | None = None - support: Optional[list[Union[Forum, EmailFeedback, WebFeedback]]] = Field(None) + support: list[Forum | EmailFeedback | WebFeedback] | None = Field(None) login_settings: ProductLoginSettingsDict = Field( ..., @@ -79,16 +79,16 @@ class Product(BaseModel): "Note that these are NOT the final plugin settings but those are obtained from login.settings.get_plugin_settings", ) - registration_email_template: Optional[str] = Field( + registration_email_template: str | None = Field( None, x_template_name="registration_email" ) - max_open_studies_per_user: Optional[PositiveInt] = Field( + max_open_studies_per_user: PositiveInt | None = Field( default=None, description="Limits the number of studies a user may have open concurently (disabled if NULL)", ) - group_id: Optional[int] = Field( + group_id: int | None = Field( default=None, description="Groups associated to this product" ) @@ -232,10 +232,10 @@ def to_statics(self) -> dict[str, Any]: by_alias=True, ) - def get_template_name_for(self, filename: str) -> Optional[str]: + def get_template_name_for(self, filename: str) -> str | None: """Checks for field marked with 'x_template_name' that fits the argument""" template_name = filename.removesuffix(".jinja2") for field in self.__fields__.values(): if field.field_info.extra.get("x_template_name") == template_name: - return getattr(self, field.name) + return f"{getattr(self, field.name)}" return None diff --git a/services/web/server/src/simcore_service_webserver/products.py b/services/web/server/src/simcore_service_webserver/products/plugin.py similarity index 81% rename from services/web/server/src/simcore_service_webserver/products.py rename to services/web/server/src/simcore_service_webserver/products/plugin.py index f1ba58c7821..6326647cad7 100644 --- a/services/web/server/src/simcore_service_webserver/products.py +++ b/services/web/server/src/simcore_service_webserver/products/plugin.py @@ -12,23 +12,23 @@ import logging import os.path from pathlib import Path -from typing import Optional import aiofiles from aiohttp import web +from models_library.products import ProductName from servicelib.aiohttp.application_setup import ModuleCategory, app_module_setup -from ._constants import APP_PRODUCTS_KEY, APP_SETTINGS_KEY, RQ_PRODUCT_KEY -from ._resources import resources -from .products_db import ProductRepository -from .products_events import ( +from .._constants import APP_PRODUCTS_KEY, APP_SETTINGS_KEY, RQ_PRODUCT_KEY +from .._resources import resources +from ._db import ProductRepository +from ._events import ( APP_PRODUCTS_TEMPLATES_DIR_KEY, auto_create_products_groups, load_products_on_startup, setup_product_templates, ) -from .products_middlewares import discover_product_middleware -from .products_model import Product, ProductName +from ._middlewares import discover_product_middleware +from ._model import Product log = logging.getLogger(__name__) @@ -62,22 +62,26 @@ def setup_products(app: web.Application): def get_product_name(request: web.Request) -> str: - return request[RQ_PRODUCT_KEY] + product_name: str = request[RQ_PRODUCT_KEY] + return product_name def get_current_product(request: web.Request) -> Product: """Returns product associated to current request""" product_name: ProductName = get_product_name(request) - return request.app[APP_PRODUCTS_KEY][product_name] + current_product: Product = request.app[APP_PRODUCTS_KEY][product_name] + return current_product def list_products(app: web.Application) -> list[Product]: - return app[APP_PRODUCTS_KEY].values() + products: list[Product] = app[APP_PRODUCTS_KEY].values() + return products async def get_product_template_path(request: web.Request, filename: str) -> Path: def _themed(dirname, template) -> Path: - return resources.get_path(os.path.join(dirname, template)) + path: Path = resources.get_path(os.path.join(dirname, template)) + return path async def _get_content(template_name: str): repo = ProductRepository(request) @@ -86,7 +90,7 @@ async def _get_content(template_name: str): raise ValueError(f"Missing template {template_name} for product") return content - def _safe_get_current_product(request: web.Request) -> Optional[Product]: + def _safe_get_current_product(request: web.Request) -> Product | None: try: product: Product = get_current_product(request) return product @@ -95,8 +99,8 @@ def _safe_get_current_product(request: web.Request) -> Optional[Product]: # --- if product := _safe_get_current_product(request): - if template_name := product.get_template_name_for(filename): # type: ignore - template_dir = request.app[APP_PRODUCTS_TEMPLATES_DIR_KEY] + if template_name := product.get_template_name_for(filename): + template_dir: Path = request.app[APP_PRODUCTS_TEMPLATES_DIR_KEY] template_path = template_dir / template_name if not template_path.exists(): # cache diff --git a/services/web/server/tests/integration/01/test_project_workflow.py b/services/web/server/tests/integration/01/test_project_workflow.py index 77291c4db38..d1e505daaef 100644 --- a/services/web/server/tests/integration/01/test_project_workflow.py +++ b/services/web/server/tests/integration/01/test_project_workflow.py @@ -35,7 +35,7 @@ from simcore_service_webserver.director_v2 import setup_director_v2 from simcore_service_webserver.garbage_collector import setup_garbage_collector from simcore_service_webserver.login.plugin import setup_login -from simcore_service_webserver.products import setup_products +from simcore_service_webserver.products.plugin import setup_products from simcore_service_webserver.projects.plugin import setup_projects from simcore_service_webserver.projects.project_models import ProjectDict from simcore_service_webserver.resource_manager.plugin import setup_resource_manager diff --git a/services/web/server/tests/integration/02/test_computation.py b/services/web/server/tests/integration/02/test_computation.py index ceb09b482ec..d2a22b384d3 100644 --- a/services/web/server/tests/integration/02/test_computation.py +++ b/services/web/server/tests/integration/02/test_computation.py @@ -9,7 +9,7 @@ import time from copy import deepcopy from pathlib import Path -from typing import Any, Callable, NamedTuple, Union +from typing import Any, Callable, NamedTuple import pytest import sqlalchemy as sa @@ -37,7 +37,7 @@ from simcore_service_webserver.diagnostics import setup_diagnostics from simcore_service_webserver.director_v2 import setup_director_v2 from simcore_service_webserver.login.plugin import setup_login -from simcore_service_webserver.products import setup_products +from simcore_service_webserver.products.plugin import setup_products from simcore_service_webserver.projects.plugin import setup_projects from simcore_service_webserver.resource_manager.plugin import setup_resource_manager from simcore_service_webserver.rest import setup_rest @@ -81,17 +81,14 @@ class ExpectedResponse(NamedTuple): will have no access, therefore ExpectedResponse.ok = HTTPUnauthorized """ - ok: Union[type[web.HTTPUnauthorized], type[web.HTTPForbidden], type[web.HTTPOk]] - created: Union[ - type[web.HTTPUnauthorized], type[web.HTTPForbidden], type[web.HTTPCreated] - ] - no_content: Union[ - type[web.HTTPUnauthorized], type[web.HTTPForbidden], type[web.HTTPNoContent] - ] - forbidden: Union[ - type[web.HTTPUnauthorized], - type[web.HTTPForbidden], - ] + ok: type[web.HTTPUnauthorized] | type[web.HTTPForbidden] | type[web.HTTPOk] + created: ( + type[web.HTTPUnauthorized] | type[web.HTTPForbidden] | type[web.HTTPCreated] + ) + no_content: ( + type[web.HTTPUnauthorized] | type[web.HTTPForbidden] | type[web.HTTPNoContent] + ) + forbidden: (type[web.HTTPUnauthorized] | type[web.HTTPForbidden]) # pylint: disable=no-member def __str__(self) -> str: items = ", ".join(f"{k}={v.__name__}" for k, v in self._asdict().items()) diff --git a/services/web/server/tests/unit/isolated/test_products_middlewares.py b/services/web/server/tests/unit/isolated/test_products_middlewares.py index 9b55f43ef36..bb71ba2e559 100644 --- a/services/web/server/tests/unit/isolated/test_products_middlewares.py +++ b/services/web/server/tests/unit/isolated/test_products_middlewares.py @@ -9,10 +9,10 @@ from simcore_postgres_database.models.products import LOGIN_SETTINGS_DEFAULT from simcore_postgres_database.webserver_models import products from simcore_service_webserver._constants import X_PRODUCT_NAME_HEADER -from simcore_service_webserver.products import get_product_name -from simcore_service_webserver.products_events import _set_app_state -from simcore_service_webserver.products_middlewares import discover_product_middleware -from simcore_service_webserver.products_model import Product +from simcore_service_webserver.products._events import _set_app_state +from simcore_service_webserver.products._middlewares import discover_product_middleware +from simcore_service_webserver.products._model import Product +from simcore_service_webserver.products.plugin import get_product_name from simcore_service_webserver.statics_constants import FRONTEND_APP_DEFAULT from yarl import URL diff --git a/services/web/server/tests/unit/isolated/test_products_model.py b/services/web/server/tests/unit/isolated/test_products_model.py index a8e8219f7e9..6e79e2943ea 100644 --- a/services/web/server/tests/unit/isolated/test_products_model.py +++ b/services/web/server/tests/unit/isolated/test_products_model.py @@ -8,7 +8,7 @@ import pytest from pydantic import BaseModel from servicelib.json_serialization import json_dumps -from simcore_service_webserver.products_db import Product +from simcore_service_webserver.products._db import Product @pytest.mark.parametrize( diff --git a/services/web/server/tests/unit/with_dbs/03/garbage_collector/test_resource_manager.py b/services/web/server/tests/unit/with_dbs/03/garbage_collector/test_resource_manager.py index 2d8825cabd5..15fb6bf0b19 100644 --- a/services/web/server/tests/unit/with_dbs/03/garbage_collector/test_resource_manager.py +++ b/services/web/server/tests/unit/with_dbs/03/garbage_collector/test_resource_manager.py @@ -35,7 +35,7 @@ from simcore_service_webserver.db import setup_db from simcore_service_webserver.director_v2 import setup_director_v2 from simcore_service_webserver.login.plugin import setup_login -from simcore_service_webserver.products import setup_products +from simcore_service_webserver.products.plugin import setup_products from simcore_service_webserver.projects.plugin import setup_projects from simcore_service_webserver.projects.projects_api import ( remove_project_dynamic_services, diff --git a/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py b/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py index 49a75e44152..565b889ee80 100644 --- a/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py +++ b/services/web/server/tests/unit/with_dbs/03/login/test_login_2fa.py @@ -28,7 +28,7 @@ send_email_code, ) from simcore_service_webserver.login.storage import AsyncpgStorage -from simcore_service_webserver.products import get_current_product +from simcore_service_webserver.products.plugin import get_current_product @pytest.fixture diff --git a/services/web/server/tests/unit/with_dbs/03/test_products_db.py b/services/web/server/tests/unit/with_dbs/03/products/test_products_db.py similarity index 95% rename from services/web/server/tests/unit/with_dbs/03/test_products_db.py rename to services/web/server/tests/unit/with_dbs/03/products/test_products_db.py index 7f29eddd2f2..0332ff904e7 100644 --- a/services/web/server/tests/unit/with_dbs/03/test_products_db.py +++ b/services/web/server/tests/unit/with_dbs/03/products/test_products_db.py @@ -23,9 +23,11 @@ products, ) from simcore_service_webserver.db import APP_DB_ENGINE_KEY -from simcore_service_webserver.products_db import ProductRepository -from simcore_service_webserver.products_middlewares import _get_app_default_product_name -from simcore_service_webserver.products_model import Product +from simcore_service_webserver.products._db import ProductRepository +from simcore_service_webserver.products._middlewares import ( + _get_app_default_product_name, +) +from simcore_service_webserver.products._model import Product @pytest.fixture diff --git a/services/web/server/tests/unit/with_dbs/03/tags/conftest.py b/services/web/server/tests/unit/with_dbs/03/tags/conftest.py index cf4189b5b2b..156dab7af3e 100644 --- a/services/web/server/tests/unit/with_dbs/03/tags/conftest.py +++ b/services/web/server/tests/unit/with_dbs/03/tags/conftest.py @@ -15,7 +15,7 @@ from simcore_service_webserver.director.plugin import setup_director from simcore_service_webserver.director_v2 import setup_director_v2 from simcore_service_webserver.login.plugin import setup_login -from simcore_service_webserver.products import setup_products +from simcore_service_webserver.products.plugin import setup_products from simcore_service_webserver.projects.plugin import setup_projects from simcore_service_webserver.resource_manager.plugin import setup_resource_manager from simcore_service_webserver.rest import setup_rest From 2e97cb1dec82951e1d1a8f73f863266852f24aba Mon Sep 17 00:00:00 2001 From: matusdrobuliak66 Date: Sat, 22 Apr 2023 18:11:06 +0200 Subject: [PATCH 2/4] mypy webserver - product plugin 2 part --- .../simcore_service_webserver/email_handlers.py | 6 +++--- .../server/src/simcore_service_webserver/groups.py | 2 +- .../simcore_service_webserver/groups_handlers.py | 7 +++---- .../login/handlers_2fa.py | 2 +- .../login/handlers_auth.py | 10 +++++----- .../login/handlers_change.py | 2 +- .../login/handlers_confirmation.py | 2 +- .../login/handlers_registration.py | 14 +++++++------- .../src/simcore_service_webserver/login/plugin.py | 5 ++--- .../simcore_service_webserver/login/utils_email.py | 2 +- .../simcore_service_webserver/products/_events.py | 4 ++-- .../projects/projects_api.py | 2 +- .../projects/projects_handlers.py | 2 +- .../publication_handlers.py | 2 +- .../src/simcore_service_webserver/publications.py | 2 +- .../src/simcore_service_webserver/rest_handlers.py | 2 +- .../src/simcore_service_webserver/statics.py | 2 +- .../simcore_service_webserver/statics_events.py | 2 +- .../simcore_service_webserver/statics_handlers.py | 2 +- .../studies_dispatcher/_studies_access.py | 2 +- .../studies_dispatcher/handlers_redirects.py | 10 +++++----- .../studies_dispatcher/handlers_rest.py | 2 +- .../studies_dispatcher/plugin.py | 2 +- 23 files changed, 43 insertions(+), 45 deletions(-) diff --git a/services/web/server/src/simcore_service_webserver/email_handlers.py b/services/web/server/src/simcore_service_webserver/email_handlers.py index fdbb62aef3d..f8d3713b4f9 100644 --- a/services/web/server/src/simcore_service_webserver/email_handlers.py +++ b/services/web/server/src/simcore_service_webserver/email_handlers.py @@ -1,5 +1,5 @@ import logging -from typing import Any, Literal, Optional +from typing import Any, Literal from aiohttp import web from models_library.emails import LowerCaseEmailStr @@ -13,7 +13,7 @@ send_email_from_template, ) from .login.decorators import login_required -from .products import Product, get_current_product, get_product_template_path +from .products.plugin import Product, get_current_product, get_product_template_path from .security_decorators import permission_required from .utils import get_traceback_string from .utils_aiohttp import envelope_json_response @@ -27,7 +27,7 @@ class TestEmail(BaseModel): - from_: Optional[LowerCaseEmailStr] = Field(None, description="Email sender") + from_: LowerCaseEmailStr | None = Field(None, description="Email sender") to: LowerCaseEmailStr = Field(..., description="Email receiver") template_name: Literal[ "change_email_email.jinja2", diff --git a/services/web/server/src/simcore_service_webserver/groups.py b/services/web/server/src/simcore_service_webserver/groups.py index c0341be4ed3..e29dcc6d074 100644 --- a/services/web/server/src/simcore_service_webserver/groups.py +++ b/services/web/server/src/simcore_service_webserver/groups.py @@ -13,7 +13,7 @@ from . import groups_handlers from ._constants import APP_OPENAPI_SPECS_KEY, APP_SETTINGS_KEY -from .products import setup_products +from .products.plugin import setup_products logger = logging.getLogger(__name__) 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 94c65d7f96f..9ebbabf318c 100644 --- a/services/web/server/src/simcore_service_webserver/groups_handlers.py +++ b/services/web/server/src/simcore_service_webserver/groups_handlers.py @@ -2,7 +2,6 @@ import json import logging from contextlib import suppress -from typing import Optional from aiohttp import web from models_library.emails import LowerCaseEmailStr @@ -62,7 +61,7 @@ async def list_groups(request: web.Request): List of the groups I belonged to """ - from .products import Product, get_current_product + from .products.plugin import Product, get_current_product product: Product = get_current_product(request) user_id = request[RQT_USERID_KEY] @@ -285,7 +284,7 @@ async def get_scicrunch_resource(request: web.Request): # check if in database first repo = ResearchResourceRepository(request.app) - resource: Optional[ResearchResource] = await repo.get_resource(rrid) + resource: ResearchResource | None = await repo.get_resource(rrid) if not resource: # otherwise, request to scicrunch service scicrunch = SciCrunch.get_instance(request.app) @@ -306,7 +305,7 @@ async def add_scicrunch_resource(request: web.Request): # check if exists repo = ResearchResourceRepository(request.app) - resource: Optional[ResearchResource] = await repo.get_resource(rrid) + resource: ResearchResource | None = await repo.get_resource(rrid) if not resource: # then request scicrunch service scicrunch = SciCrunch.get_instance(request.app) diff --git a/services/web/server/src/simcore_service_webserver/login/handlers_2fa.py b/services/web/server/src/simcore_service_webserver/login/handlers_2fa.py index 3ca79f7332c..5bdd63fa98d 100644 --- a/services/web/server/src/simcore_service_webserver/login/handlers_2fa.py +++ b/services/web/server/src/simcore_service_webserver/login/handlers_2fa.py @@ -10,7 +10,7 @@ from servicelib.error_codes import create_error_code from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON -from ..products import Product, get_current_product +from ..products.plugin import Product, get_current_product from ..session_access import session_access_required from ._2fa import ( create_2fa_code, diff --git a/services/web/server/src/simcore_service_webserver/login/handlers_auth.py b/services/web/server/src/simcore_service_webserver/login/handlers_auth.py index 00ed749b568..d58ef29f21b 100644 --- a/services/web/server/src/simcore_service_webserver/login/handlers_auth.py +++ b/services/web/server/src/simcore_service_webserver/login/handlers_auth.py @@ -1,5 +1,5 @@ import logging -from typing import Final, Optional +from typing import Final from aiohttp import web from aiohttp.web import RouteTableDef @@ -12,7 +12,7 @@ from simcore_postgres_database.models.users import UserRole from .._meta import API_VTAG -from ..products import Product, get_current_product +from ..products.plugin import Product, get_current_product from ..security_api import check_password, forget from ..session_access import on_success_grant_session_access_to, session_access_required from ..utils_aiohttp import NextPage @@ -62,8 +62,8 @@ class LoginBody(InputSchema): class CodePageParams(BaseModel): message: str - retry_2fa_after: Optional[PositiveInt] = None - next_url: Optional[str] = None + retry_2fa_after: PositiveInt | None = None + next_url: str | None = None class LoginNextPage(NextPage[CodePageParams]): @@ -240,7 +240,7 @@ async def login_2fa(request: web.Request): class LogoutBody(InputSchema): - client_session_id: Optional[str] = Field( + client_session_id: str | None = Field( None, example="5ac57685-c40f-448f-8711-70be1936fd63" ) diff --git a/services/web/server/src/simcore_service_webserver/login/handlers_change.py b/services/web/server/src/simcore_service_webserver/login/handlers_change.py index eb5f522fb85..b03aa325dbc 100644 --- a/services/web/server/src/simcore_service_webserver/login/handlers_change.py +++ b/services/web/server/src/simcore_service_webserver/login/handlers_change.py @@ -8,7 +8,7 @@ from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from .._meta import API_VTAG -from ..products import Product, get_current_product +from ..products.plugin import Product, get_current_product from ..security_api import check_password, encrypt_password from ..utils import HOUR from ..utils_rate_limiting import global_rate_limit_route diff --git a/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py b/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py index 833176eadcf..911b64b8cb4 100644 --- a/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py +++ b/services/web/server/src/simcore_service_webserver/login/handlers_confirmation.py @@ -13,7 +13,7 @@ from simcore_postgres_database.errors import UniqueViolation from yarl import URL -from ..products import Product, get_current_product +from ..products.plugin import Product, get_current_product from ..security_api import encrypt_password from ..session_access import session_access_required from ..utils import MINUTE diff --git a/services/web/server/src/simcore_service_webserver/login/handlers_registration.py b/services/web/server/src/simcore_service_webserver/login/handlers_registration.py index 391f1c5246e..75423411a99 100644 --- a/services/web/server/src/simcore_service_webserver/login/handlers_registration.py +++ b/services/web/server/src/simcore_service_webserver/login/handlers_registration.py @@ -1,6 +1,6 @@ import logging from datetime import datetime, timedelta -from typing import Literal, Optional +from typing import Literal from aiohttp import web from aiohttp.web import RouteTableDef @@ -13,7 +13,7 @@ from .._meta import API_VTAG from ..groups_api import auto_add_user_to_groups, auto_add_user_to_product_group from ..invitations import is_service_invitation_code -from ..products import Product, get_current_product +from ..products.plugin import Product, get_current_product from ..security_api import encrypt_password from ..session_access import on_success_grant_session_access_to, session_access_required from ..utils import MINUTE @@ -70,7 +70,7 @@ class InvitationCheck(InputSchema): class InvitationInfo(InputSchema): - email: Optional[LowerCaseEmailStr] = Field( + email: LowerCaseEmailStr | None = Field( None, description="Email associated to invitation or None" ) @@ -112,8 +112,8 @@ async def check_registration_invitation(request: web.Request): class RegisterBody(InputSchema): email: LowerCaseEmailStr password: SecretStr - confirm: Optional[SecretStr] = Field(None, description="Password confirmation") - invitation: Optional[str] = Field(None, description="Invitation code") + confirm: SecretStr | None = Field(None, description="Password confirmation") + invitation: str | None = Field(None, description="Invitation code") _password_confirm_match = validator("confirm", allow_reuse=True)( check_confirm_password_match @@ -151,7 +151,7 @@ async def register(request: web.Request): await check_other_registrations(email=registration.email, db=db, cfg=cfg) - expires_at: Optional[datetime] = None # = does not expire + expires_at: datetime | None = None # = does not expire if settings.LOGIN_REGISTRATION_INVITATION_REQUIRED: # Only requests with INVITATION can register user # to either a permanent or to a trial account @@ -257,7 +257,7 @@ class RegisterPhoneBody(InputSchema): class _PageParams(BaseModel): - retry_2fa_after: Optional[PositiveInt] = None + retry_2fa_after: PositiveInt | None = None class RegisterPhoneNextPage(NextPage[_PageParams]): diff --git a/services/web/server/src/simcore_service_webserver/login/plugin.py b/services/web/server/src/simcore_service_webserver/login/plugin.py index dcab164482a..f4aaeff6ff1 100644 --- a/services/web/server/src/simcore_service_webserver/login/plugin.py +++ b/services/web/server/src/simcore_service_webserver/login/plugin.py @@ -1,7 +1,6 @@ import asyncio import json import logging -from typing import Optional import asyncpg from aiohttp import web @@ -21,7 +20,7 @@ from ..email_settings import SMTPSettings from ..email_settings import get_plugin_settings as get_email_plugin_settings from ..invitations import setup_invitations -from ..products import ProductName, list_products, setup_products +from ..products.plugin import ProductName, list_products, setup_products from ..redis import setup_redis from ..rest import setup_rest from ._constants import APP_LOGIN_SETTINGS_PER_PRODUCT_KEY @@ -83,7 +82,7 @@ async def _resolve_login_settings_per_product(app: web.Application): for the login plugin. Note that product settings override app settings. """ # app plugin settings - app_login_settings: Optional[LoginSettings] + app_login_settings: LoginSettings | None login_settings_per_product: dict[ProductName, LoginSettingsForProduct] = {} if app_login_settings := app[APP_SETTINGS_KEY].WEBSERVER_LOGIN: diff --git a/services/web/server/src/simcore_service_webserver/login/utils_email.py b/services/web/server/src/simcore_service_webserver/login/utils_email.py index 0a326e8eb79..69348122d3f 100644 --- a/services/web/server/src/simcore_service_webserver/login/utils_email.py +++ b/services/web/server/src/simcore_service_webserver/login/utils_email.py @@ -6,7 +6,7 @@ from .._resources import resources from ..email_core import AttachmentTuple, send_email_from_template -from ..products import get_product_template_path +from ..products.plugin import get_product_template_path log = logging.getLogger(__name__) 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 dba76de3bb6..9a7ef784547 100644 --- a/services/web/server/src/simcore_service_webserver/products/_events.py +++ b/services/web/server/src/simcore_service_webserver/products/_events.py @@ -12,8 +12,8 @@ ) from .._constants import APP_DB_ENGINE_KEY, APP_PRODUCTS_KEY -from ..products_db import iter_products -from ..products_model import Product +from ..products._db import iter_products +from ..products._model import Product from ..statics_constants import FRONTEND_APP_DEFAULT, FRONTEND_APPS_AVAILABLE log = logging.getLogger(__name__) 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 7514af280a4..039cd487050 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 @@ -51,7 +51,7 @@ from simcore_postgres_database.webserver_models import ProjectType from .. import catalog_client, director_v2_api, storage_api -from ..products import get_product_name +from ..products.plugin import get_product_name from ..redis import get_redis_lock_manager_client_sdk from ..resource_manager.websocket_manager import ( PROJECT_ID_KEY, diff --git a/services/web/server/src/simcore_service_webserver/projects/projects_handlers.py b/services/web/server/src/simcore_service_webserver/projects/projects_handlers.py index aeb3409e6cf..97fd8f0856d 100644 --- a/services/web/server/src/simcore_service_webserver/projects/projects_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/projects_handlers.py @@ -29,7 +29,7 @@ from .._meta import api_version_prefix as VTAG from ..director_v2_exceptions import DirectorServiceError from ..login.decorators import login_required -from ..products import Product, get_current_product +from ..products.plugin import Product, get_current_product from ..security_decorators import permission_required from . import projects_api from .projects_exceptions import ( diff --git a/services/web/server/src/simcore_service_webserver/publication_handlers.py b/services/web/server/src/simcore_service_webserver/publication_handlers.py index b346c76812a..e8936a86425 100644 --- a/services/web/server/src/simcore_service_webserver/publication_handlers.py +++ b/services/web/server/src/simcore_service_webserver/publication_handlers.py @@ -9,7 +9,7 @@ from .login.decorators import login_required from .login.storage import AsyncpgStorage, get_plugin_storage from .login.utils_email import themed -from .products import get_current_product +from .products.plugin import get_current_product log = logging.getLogger(__name__) diff --git a/services/web/server/src/simcore_service_webserver/publications.py b/services/web/server/src/simcore_service_webserver/publications.py index 6e79f539db0..30f443e384f 100644 --- a/services/web/server/src/simcore_service_webserver/publications.py +++ b/services/web/server/src/simcore_service_webserver/publications.py @@ -9,7 +9,7 @@ from . import publication_handlers from .email import setup_email -from .products import setup_products +from .products.plugin import setup_products logger = logging.getLogger(__name__) diff --git a/services/web/server/src/simcore_service_webserver/rest_handlers.py b/services/web/server/src/simcore_service_webserver/rest_handlers.py index 9a9b2334dae..5320bc1dc1f 100644 --- a/services/web/server/src/simcore_service_webserver/rest_handlers.py +++ b/services/web/server/src/simcore_service_webserver/rest_handlers.py @@ -11,7 +11,7 @@ from ._meta import API_VTAG from .application_settings import APP_SETTINGS_KEY from .login.decorators import login_required -from .products import get_product_name +from .products.plugin import get_product_name from .redis import get_redis_scheduled_maintenance_client from .rest_healthcheck import HealthCheck, HealthCheckFailed from .utils_aiohttp import envelope_json_response diff --git a/services/web/server/src/simcore_service_webserver/statics.py b/services/web/server/src/simcore_service_webserver/statics.py index cbe92cdf571..d8e23e6516e 100644 --- a/services/web/server/src/simcore_service_webserver/statics.py +++ b/services/web/server/src/simcore_service_webserver/statics.py @@ -12,7 +12,7 @@ from servicelib.aiohttp.application_setup import ModuleCategory, app_module_setup from ._constants import INDEX_RESOURCE_NAME -from .products import setup_products +from .products.plugin import setup_products from .statics_events import create_cached_indexes, create_statics_json from .statics_handlers import get_cached_frontend_index, get_statics_json from .statics_settings import StaticWebserverModuleSettings, get_plugin_settings diff --git a/services/web/server/src/simcore_service_webserver/statics_events.py b/services/web/server/src/simcore_service_webserver/statics_events.py index 11a3c837ed9..1b273fb480d 100644 --- a/services/web/server/src/simcore_service_webserver/statics_events.py +++ b/services/web/server/src/simcore_service_webserver/statics_events.py @@ -14,7 +14,7 @@ from yarl import URL from ._constants import APP_SETTINGS_KEY -from .products import APP_PRODUCTS_KEY, Product +from .products.plugin import APP_PRODUCTS_KEY, Product from .statics_constants import ( APP_FRONTEND_CACHED_INDEXES_KEY, APP_FRONTEND_CACHED_STATICS_JSON_KEY, diff --git a/services/web/server/src/simcore_service_webserver/statics_handlers.py b/services/web/server/src/simcore_service_webserver/statics_handlers.py index 5fd28a1db8d..8d4fa1e3428 100644 --- a/services/web/server/src/simcore_service_webserver/statics_handlers.py +++ b/services/web/server/src/simcore_service_webserver/statics_handlers.py @@ -2,7 +2,7 @@ from aiohttp import web -from .products import get_product_name +from .products.plugin import get_product_name from .statics_constants import ( APP_FRONTEND_CACHED_INDEXES_KEY, APP_FRONTEND_CACHED_STATICS_JSON_KEY, diff --git a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_studies_access.py b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_studies_access.py index 2ffb79b17e3..ff39bd72c8c 100644 --- a/services/web/server/src/simcore_service_webserver/studies_dispatcher/_studies_access.py +++ b/services/web/server/src/simcore_service_webserver/studies_dispatcher/_studies_access.py @@ -28,7 +28,7 @@ from .._constants import INDEX_RESOURCE_NAME from ..garbage_collector_settings import GUEST_USER_RC_LOCK_FORMAT -from ..products import get_product_name +from ..products.plugin import get_product_name from ..projects.project_models import ProjectDict from ..projects.projects_db import ANY_USER, ProjectDBAPI from ..projects.projects_exceptions import ( diff --git a/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_redirects.py b/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_redirects.py index 9e6817baa84..92b764f1d1a 100644 --- a/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_redirects.py +++ b/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_redirects.py @@ -4,7 +4,7 @@ import functools import logging import urllib.parse -from typing import Optional, cast +from typing import cast from aiohttp import web from models_library.services import ServiceKey, ServiceVersion @@ -14,7 +14,7 @@ from servicelib.aiohttp.typing_extension import Handler from servicelib.error_codes import create_error_code -from ..products import get_product_name +from ..products.plugin import get_product_name from ..utils import compose_support_error_msg from ..utils_aiohttp import create_redirect_response from ._catalog import validate_requested_service @@ -29,7 +29,7 @@ class ViewerQueryParams(BaseModel): - file_type: Optional[str] = None + file_type: str | None = None viewer_key: ServiceKey viewer_version: ServiceVersion @@ -54,8 +54,8 @@ def ensure_extension_upper_and_dotless(cls, v): class RedirectionQueryParams(ViewerQueryParams): file_name: str = "unknown" - file_size: Optional[PositiveInt] = None - download_link: Optional[HttpUrl] = None + file_size: PositiveInt | None = None + download_link: HttpUrl | None = None @validator("download_link", pre=True) @classmethod diff --git a/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_rest.py b/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_rest.py index 2f97b3e4576..b19dafb77c3 100644 --- a/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_rest.py +++ b/services/web/server/src/simcore_service_webserver/studies_dispatcher/handlers_rest.py @@ -13,7 +13,7 @@ from pydantic.networks import HttpUrl from .._meta import API_VTAG -from ..products import get_product_name +from ..products.plugin import get_product_name from ..utils_aiohttp import envelope_json_response from ._catalog import ServiceMetaData, iter_latest_product_services from ._core import list_viewers_info diff --git a/services/web/server/src/simcore_service_webserver/studies_dispatcher/plugin.py b/services/web/server/src/simcore_service_webserver/studies_dispatcher/plugin.py index 537b843ac2c..7b34dc1e1e2 100644 --- a/services/web/server/src/simcore_service_webserver/studies_dispatcher/plugin.py +++ b/services/web/server/src/simcore_service_webserver/studies_dispatcher/plugin.py @@ -4,7 +4,7 @@ from servicelib.aiohttp.application_setup import ModuleCategory, app_module_setup from ..login.decorators import login_required -from ..products import setup_products +from ..products.plugin import setup_products from . import handlers_rest from ._studies_access import get_redirection_to_study_page from .handlers_redirects import get_redirection_to_viewer From 0fc02c7254a4b01ecdaf81ced0bf3af3db0e8ad9 Mon Sep 17 00:00:00 2001 From: matusdrobuliak66 Date: Sat, 22 Apr 2023 20:31:04 +0200 Subject: [PATCH 3/4] minor mypy fix --- .../server/src/simcore_service_webserver/products/_events.py | 4 ++-- .../server/src/simcore_service_webserver/products/_model.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) 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 9a7ef784547..dde7f95473c 100644 --- a/services/web/server/src/simcore_service_webserver/products/_events.py +++ b/services/web/server/src/simcore_service_webserver/products/_events.py @@ -12,9 +12,9 @@ ) from .._constants import APP_DB_ENGINE_KEY, APP_PRODUCTS_KEY -from ..products._db import iter_products -from ..products._model import Product from ..statics_constants import FRONTEND_APP_DEFAULT, FRONTEND_APPS_AVAILABLE +from ._db import iter_products +from ._model import Product log = logging.getLogger(__name__) diff --git a/services/web/server/src/simcore_service_webserver/products/_model.py b/services/web/server/src/simcore_service_webserver/products/_model.py index ef7c4c21f9a..8b3a220f959 100644 --- a/services/web/server/src/simcore_service_webserver/products/_model.py +++ b/services/web/server/src/simcore_service_webserver/products/_model.py @@ -237,5 +237,6 @@ def get_template_name_for(self, filename: str) -> str | None: template_name = filename.removesuffix(".jinja2") for field in self.__fields__.values(): if field.field_info.extra.get("x_template_name") == template_name: - return f"{getattr(self, field.name)}" + template_name_attribute: str = getattr(self, field.name) + return template_name_attribute return None From 8d2049f0ac40917dbf109aac563a7ab5e86c2007 Mon Sep 17 00:00:00 2001 From: matusdrobuliak66 Date: Mon, 24 Apr 2023 17:00:31 +0200 Subject: [PATCH 4/4] artificial change to rerun CI --- services/web/server/src/simcore_service_webserver/groups.py | 1 + 1 file changed, 1 insertion(+) diff --git a/services/web/server/src/simcore_service_webserver/groups.py b/services/web/server/src/simcore_service_webserver/groups.py index e29dcc6d074..4c2568f88b1 100644 --- a/services/web/server/src/simcore_service_webserver/groups.py +++ b/services/web/server/src/simcore_service_webserver/groups.py @@ -15,6 +15,7 @@ from ._constants import APP_OPENAPI_SPECS_KEY, APP_SETTINGS_KEY from .products.plugin import setup_products + logger = logging.getLogger(__name__)