diff --git a/main.py b/main.py index 2283d84..7274f47 100644 --- a/main.py +++ b/main.py @@ -1,18 +1,18 @@ -import os import asyncio +import os from os.path import exists from sentry_sdk.integrations.aiohttp import AioHttpIntegration from sentry_sdk.integrations.redis import RedisIntegration from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration from sentry_sdk.integrations.strawberry import StrawberryIntegration -from strawberry.asgi import GraphQL from starlette.applications import Starlette +from strawberry.asgi import GraphQL -from services.rediscache import redis from resolvers.listener import reactions_worker from resolvers.schema import schema -from settings import DEV_SERVER_PID_FILE_NAME, SENTRY_DSN, MODE +from services.rediscache import redis +from settings import DEV_SERVER_PID_FILE_NAME, MODE, SENTRY_DSN async def start_up(): diff --git a/orm/notification.py b/orm/notification.py index 3b829e8..2a5c799 100644 --- a/orm/notification.py +++ b/orm/notification.py @@ -1,6 +1,8 @@ -from enum import Enum as Enumeration import time -from sqlalchemy import Column, Enum, Integer, ForeignKey, JSON as JSONType +from enum import Enum as Enumeration + +from sqlalchemy import JSON as JSONType +from sqlalchemy import Column, Enum, ForeignKey, Integer from sqlalchemy.orm import relationship from orm.author import Author diff --git a/pyproject.toml b/pyproject.toml index 9db6f3f..dceab60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,18 +13,20 @@ python = "^3.12" SQLAlchemy = "^2.0.22" psycopg2-binary = "^2.9.9" redis = {extras = ["hiredis"], version = "^5.0.1"} -uvicorn = "^0.24.0.post1" -strawberry-graphql = {extras = ["asgi", "debug-server"], version = "^0.215.1" } +uvicorn = "^0.24.0" +strawberry-graphql = {extras = ["asgi", "debug-server"], version = "^0.216.1" } +strawberry-sqlalchemy-mapper = "^0.4.0" sentry-sdk = "^1.37.1" -strawberry-sqlalchemy-mapper = "^0.3.1" aiohttp = "^3.9.1" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] +setuptools = "^69.0.2" pytest = "^7.4.2" black = { version = "^23.12.0", python = ">=3.12" } ruff = { version = "^0.1.8", python = ">=3.12" } mypy = { version = "^1.7", python = ">=3.12" } -setuptools = "^69.0.2" +isort = "^5.13.2" +pyright = "^1.1.341" [tool.black] line-length = 120 @@ -58,18 +60,33 @@ use_parentheses = true ensure_newline_before_comments = true line_length = 120 + [tool.pyright] venvPath = "." venv = ".venv" include = ["."] -exclude = ["**/__pycache__"] -ignore = [] -defineConstant = { DEBUG = true } -reportMissingImports = true -reportMissingTypeStubs = false -pythonVersion = "312" -pythonPlatform = "Linux" -executionEnvironments = [] +useLibraryCodeForTypes = true +disableLanguageServices = false +disableOrganizeImports = false +reportMissingImports = false +reportMissingModuleSource = "warning" +reportImportCycles = "warning" +maxMemoryForLargeFile = 4096 +pythonVersion = "3.12" +autoImportCompletions = true +useVirtualEnv = true +typeCheckingMode = "basic" +disableJediCompletion = false +disableCompletion = false +disableSnippetCompletion = false +disableGoToDefinition = false +disableRenaming = false +disableSignatureHelp = false +diagnostics = true +logLevel = "Information" +pluginSearchPaths = [] +typings = {} +mergeTypeStubPackages = false [tool.mypy] python_version = "3.12" diff --git a/resolvers/schema.py b/resolvers/schema.py index ec1779a..8e79bf5 100644 --- a/resolvers/schema.py +++ b/resolvers/schema.py @@ -1,15 +1,18 @@ +import logging from typing import List -from sqlalchemy import and_, select -from sqlalchemy.orm import aliased -from sqlalchemy.exc import SQLAlchemyError -from orm.notification import Notification as NotificationMessage, NotificationSeen +import strawberry +from sqlalchemy import and_, select +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import aliased +from strawberry.schema.config import StrawberryConfig +from strawberry_sqlalchemy_mapper import StrawberrySQLAlchemyMapper + +from orm.author import Author +from orm.notification import Notification as NotificationMessage +from orm.notification import NotificationSeen from services.auth import LoginRequiredMiddleware from services.db import local_session -import strawberry -from strawberry_sqlalchemy_mapper import StrawberrySQLAlchemyMapper -from strawberry.schema.config import StrawberryConfig -import logging strawberry_sqlalchemy_mapper = StrawberrySQLAlchemyMapper() @@ -39,7 +42,7 @@ class NotificationsResult: total: int -def get_notifications(author_id: int, session, limit: int, offset: int) -> List[Notification]: +def get_notifications(author_id: int, session, after: int, limit: int = 9999, offset: int = 0) -> List[Notification]: NotificationSeenAlias = aliased(NotificationSeen) query = ( select(NotificationMessage, NotificationSeenAlias.viewer.label("seen")) @@ -47,6 +50,7 @@ def get_notifications(author_id: int, session, limit: int, offset: int) -> List[ NotificationSeen, and_(NotificationSeen.viewer == author_id, NotificationSeen.notification == NotificationMessage.id), ) + .filter(NotificationMessage.created_at > after) .group_by(NotificationSeen.notification) ) if limit: @@ -77,7 +81,9 @@ class Query: with local_session() as session: try: if author_id: - notifications = get_notifications(author_id, session, limit, offset) + author = session.query(Author).filter(Author.id == author_id).first() + after = author.last_seen + notifications = get_notifications(author_id, session, after, limit, offset) if notifications and len(notifications) > 0: nr = NotificationsResult( notifications=notifications, @@ -110,27 +116,27 @@ class Mutation: f"[mark_notification_as_read] Ошибка при обновлении статуса прочтения уведомления: {str(e)}" ) return NotificationSeenResult(error="cant mark as read") - return NotificationSeenResult() + return NotificationSeenResult(error=None) @strawberry.mutation async def mark_all_notifications_as_read(self, info) -> NotificationSeenResult: author_id = info.context.get("author_id") if author_id: - try: - with local_session() as session: - nslist = get_notifications(author_id, session, None, None) + with local_session() as session: + try: + nslist = get_notifications(author_id, session) for n in nslist: if author_id not in n.seen: ns = NotificationSeen(viewer=author_id, notification=n.id) session.add(ns) session.commit() - except SQLAlchemyError as e: - session.rollback() - logger.error( - f"[mark_all_notifications_as_read] Ошибка при обновлении статуса прочтения всех уведомлений: {str(e)}" - ) - return NotificationSeenResult(error="cant mark as read") - return NotificationSeenResult() + except SQLAlchemyError as e: + session.rollback() + logger.error( + f"[mark_all_notifications_as_read] Ошибка обновления статуса прочтения всех уведомлений: {e}" + ) + return NotificationSeenResult(error="cant mark as read") + return NotificationSeenResult(error=None) schema = strawberry.Schema( diff --git a/services/auth.py b/services/auth.py index 515b0fa..e001e6d 100644 --- a/services/auth.py +++ b/services/auth.py @@ -7,7 +7,7 @@ from services.db import local_session from settings import AUTH_URL -async def check_auth(req) -> (bool, int | None): +async def check_auth(req): token = req.headers.get("Authorization") if token: # Logging the authentication token @@ -62,7 +62,7 @@ async def check_auth(req) -> (bool, int | None): except Exception as e: # Handling and logging exceptions during authentication check print(f"[services.auth] {e}") - raise HTTPUnauthorized(message="Please, login first") + raise HTTPUnauthorized(text="Please, login first") return False, None diff --git a/services/core.py b/services/core.py index 3972efe..f3eff20 100644 --- a/services/core.py +++ b/services/core.py @@ -1,5 +1,7 @@ -from typing import List, Any +from typing import Any, List + import aiohttp + from settings import API_BASE headers = {"Content-Type": "application/json"} @@ -23,7 +25,7 @@ async def _request_endpoint(query_name, body): traceback.print_exc() -async def get_followed_shouts(author_id: int) -> List[Any]: +async def get_followed_shouts(author_id: int): query_name = "load_shouts_followed" query_type = "query" operation = "GetFollowedShouts" diff --git a/services/rediscache.py b/services/rediscache.py index dbe0519..96f0b93 100644 --- a/services/rediscache.py +++ b/services/rediscache.py @@ -2,6 +2,7 @@ import asyncio import json import redis.asyncio as aredis + from settings import REDIS_URL