Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions migrations/20250929000000_init_comments.sql
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
-- +goose Up
-- +goose StatementBegin
CREATE TYPE comment_status AS ENUM ('DELETED', 'HIDDEN', 'ON_MODERATION');

CREATE TABLE IF NOT EXISTS comments (
id BIGSERIAL PRIMARY KEY,
mod_id BIGINT NOT NULL,
author_id BIGINT NOT NULL,
text TEXT NOT NULL,
status comment_status,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
edited_at TIMESTAMPTZ
);
Expand All @@ -15,4 +18,5 @@ CREATE INDEX IF NOT EXISTS idx_comments_mod_id ON comments (mod_id);
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS comments;
DROP TYPE IF EXISTS comment_status;
-- +goose StatementEnd
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
distribution = true

[tool.black]
line-length = 79
line-length = 120
target-version = ["py313"]
skip-string-normalization = false
exclude = '''
Expand All @@ -19,7 +19,7 @@ exclude = '''

[tool.isort]
profile = "black"
line_length = 79
line_length = 120
known_first_party = ["app"]
multi_line_output = 3
include_trailing_comma = true
Expand All @@ -29,7 +29,7 @@ ensure_newline_before_comments = true
skip = [".venv", "src/commentservice/grpc"]

[tool.flake8]
max-line-length = 79
max-line-length = 120
extend-ignore = ["E203", "W503"]
per-file-ignores = [
"__init__.py:F401",
Expand All @@ -44,7 +44,7 @@ exclude = [
]

[tool.ruff]
line-length = 79
line-length = 120
target-version = "py313"
preview = true
exclude = [".venv", "build", "dist", "src/commentservice/grpc"]
Expand Down
3 changes: 3 additions & 0 deletions src/commentservice/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
STATUS_DELETED = "DELETED"
STATUS_HIDDEN = "HIDDEN"
STATUS_ON_MODERATION = "ON_MODERATION"
24 changes: 13 additions & 11 deletions src/commentservice/grpc/comment_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 18 additions & 4 deletions src/commentservice/grpc/comment_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ import datetime

from google.protobuf import timestamp_pb2 as _timestamp_pb2
from google.protobuf.internal import containers as _containers
from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from collections.abc import Iterable as _Iterable, Mapping as _Mapping
from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union

DESCRIPTOR: _descriptor.FileDescriptor

class CommentStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = ()
COMMENT_STATUS_UNSPECIFIED: _ClassVar[CommentStatus]
COMMENT_STATUS_DELETED: _ClassVar[CommentStatus]
COMMENT_STATUS_HIDDEN: _ClassVar[CommentStatus]
COMMENT_STATUS_ON_MODERATION: _ClassVar[CommentStatus]
COMMENT_STATUS_UNSPECIFIED: CommentStatus
COMMENT_STATUS_DELETED: CommentStatus
COMMENT_STATUS_HIDDEN: CommentStatus
COMMENT_STATUS_ON_MODERATION: CommentStatus

class Comment(_message.Message):
__slots__ = ("id", "author_id", "text", "created_at", "edited_at")
ID_FIELD_NUMBER: _ClassVar[int]
Expand Down Expand Up @@ -53,13 +65,15 @@ class GetCommentsResponse(_message.Message):
comments: _containers.RepeatedCompositeFieldContainer[Comment]
def __init__(self, mod_id: _Optional[int] = ..., comments: _Optional[_Iterable[_Union[Comment, _Mapping]]] = ...) -> None: ...

class DeleteCommentRequest(_message.Message):
__slots__ = ("comment_id",)
class SetStatusRequest(_message.Message):
__slots__ = ("comment_id", "status")
COMMENT_ID_FIELD_NUMBER: _ClassVar[int]
STATUS_FIELD_NUMBER: _ClassVar[int]
comment_id: int
def __init__(self, comment_id: _Optional[int] = ...) -> None: ...
status: CommentStatus
def __init__(self, comment_id: _Optional[int] = ..., status: _Optional[_Union[CommentStatus, str]] = ...) -> None: ...

class DeleteCommentResponse(_message.Message):
class SetStatusResponse(_message.Message):
__slots__ = ("success",)
SUCCESS_FIELD_NUMBER: _ClassVar[int]
success: bool
Expand Down
47 changes: 27 additions & 20 deletions src/commentservice/grpc/comment_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@


class CommentServiceStub(object):
"""Missing associated documentation comment in .proto file."""
"""Сервис для работы с комментариями: создание, получение, изменение статуса, редактирование
"""

def __init__(self, channel):
"""Constructor.
Expand All @@ -44,10 +45,10 @@ def __init__(self, channel):
request_serializer=comment__pb2.GetCommentsRequest.SerializeToString,
response_deserializer=comment__pb2.GetCommentsResponse.FromString,
_registered_method=True)
self.DeleteComment = channel.unary_unary(
'/comment.CommentService/DeleteComment',
request_serializer=comment__pb2.DeleteCommentRequest.SerializeToString,
response_deserializer=comment__pb2.DeleteCommentResponse.FromString,
self.SetStatus = channel.unary_unary(
'/comment.CommentService/SetStatus',
request_serializer=comment__pb2.SetStatusRequest.SerializeToString,
response_deserializer=comment__pb2.SetStatusResponse.FromString,
_registered_method=True)
self.EditComment = channel.unary_unary(
'/comment.CommentService/EditComment',
Expand All @@ -57,28 +58,33 @@ def __init__(self, channel):


class CommentServiceServicer(object):
"""Missing associated documentation comment in .proto file."""
"""Сервис для работы с комментариями: создание, получение, изменение статуса, редактирование
"""

def CreateComment(self, request, context):
"""Missing associated documentation comment in .proto file."""
"""Создание комментария
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')

def GetComments(self, request, context):
"""Missing associated documentation comment in .proto file."""
"""Получение комментариев
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')

def DeleteComment(self, request, context):
"""Missing associated documentation comment in .proto file."""
def SetStatus(self, request, context):
"""Изменение статуса комментария
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')

def EditComment(self, request, context):
"""Missing associated documentation comment in .proto file."""
"""Редактирование комментария
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
Expand All @@ -96,10 +102,10 @@ def add_CommentServiceServicer_to_server(servicer, server):
request_deserializer=comment__pb2.GetCommentsRequest.FromString,
response_serializer=comment__pb2.GetCommentsResponse.SerializeToString,
),
'DeleteComment': grpc.unary_unary_rpc_method_handler(
servicer.DeleteComment,
request_deserializer=comment__pb2.DeleteCommentRequest.FromString,
response_serializer=comment__pb2.DeleteCommentResponse.SerializeToString,
'SetStatus': grpc.unary_unary_rpc_method_handler(
servicer.SetStatus,
request_deserializer=comment__pb2.SetStatusRequest.FromString,
response_serializer=comment__pb2.SetStatusResponse.SerializeToString,
),
'EditComment': grpc.unary_unary_rpc_method_handler(
servicer.EditComment,
Expand All @@ -115,7 +121,8 @@ def add_CommentServiceServicer_to_server(servicer, server):

# This class is part of an EXPERIMENTAL API.
class CommentService(object):
"""Missing associated documentation comment in .proto file."""
"""Сервис для работы с комментариями: создание, получение, изменение статуса, редактирование
"""

@staticmethod
def CreateComment(request,
Expand Down Expand Up @@ -172,7 +179,7 @@ def GetComments(request,
_registered_method=True)

@staticmethod
def DeleteComment(request,
def SetStatus(request,
target,
options=(),
channel_credentials=None,
Expand All @@ -185,9 +192,9 @@ def DeleteComment(request,
return grpc.experimental.unary_unary(
request,
target,
'/comment.CommentService/DeleteComment',
comment__pb2.DeleteCommentRequest.SerializeToString,
comment__pb2.DeleteCommentResponse.FromString,
'/comment.CommentService/SetStatus',
comment__pb2.SetStatusRequest.SerializeToString,
comment__pb2.SetStatusResponse.FromString,
options,
channel_credentials,
insecure,
Expand Down
4 changes: 1 addition & 3 deletions src/commentservice/handler/create_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ async def CreateComment(
request: comment_pb2.CreateCommentRequest,
_: grpc.ServicerContext,
) -> comment_pb2.CreateCommentResponse:
id = await service.create_comment(
request.mod_id, request.author_id, request.text
)
id = await service.create_comment(request.mod_id, request.author_id, request.text)
return comment_pb2.CreateCommentResponse(
comment_id=id,
)
13 changes: 0 additions & 13 deletions src/commentservice/handler/delete_comment.py

This file was deleted.

4 changes: 1 addition & 3 deletions src/commentservice/handler/get_comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ async def GetComments(
_: grpc.ServicerContext,
) -> comment_pb2.GetCommentsResponse:
comments = await service.get_comments(mod_id=request.mod_id)
return comment_pb2.GetCommentsResponse(
mod_id=request.mod_id, comments=convertCommentsToProto(comments)
)
return comment_pb2.GetCommentsResponse(mod_id=request.mod_id, comments=convertCommentsToProto(comments))


def convertCommentToProto(comment: Comment) -> comment_pb2.Comment:
Expand Down
16 changes: 6 additions & 10 deletions src/commentservice/handler/handler.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import grpc

from commentservice.grpc import comment_pb2, comment_pb2_grpc
from commentservice.handler.create_comment import (
CreateComment as _create_comment,
)
from commentservice.handler.delete_comment import (
DeleteComment as _delete_comment,
)
from commentservice.handler.create_comment import CreateComment as _create_comment
from commentservice.handler.edit_comment import EditComment as _edit_comment
from commentservice.handler.get_comments import GetComments as _get_comments
from commentservice.handler.set_status import SetStatus as _set_status
from commentservice.service.service import CommentService


Expand All @@ -30,12 +26,12 @@ async def EditComment(
) -> comment_pb2.EditCommentResponse:
return await _edit_comment(self._service, request, context)

async def DeleteComment(
async def SetStatus(
self,
request: comment_pb2.DeleteCommentRequest,
request: comment_pb2.SetStatusRequest,
context: grpc.ServicerContext,
) -> comment_pb2.DeleteCommentResponse:
return await _delete_comment(self._service, request, context)
) -> comment_pb2.SetStatusResponse:
return await _set_status(self._service, request, context)

async def GetComments(
self,
Expand Down
40 changes: 40 additions & 0 deletions src/commentservice/handler/set_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import grpc

from commentservice.constants import (
STATUS_DELETED,
STATUS_HIDDEN,
STATUS_ON_MODERATION,
)
from commentservice.grpc import comment_pb2
from commentservice.service.service import CommentService

_ENUM_TO_DB_STATUS_BY_VALUE: dict[int, str] = {
comment_pb2.CommentStatus.COMMENT_STATUS_DELETED: STATUS_DELETED,
comment_pb2.CommentStatus.COMMENT_STATUS_HIDDEN: STATUS_HIDDEN,
comment_pb2.CommentStatus.COMMENT_STATUS_ON_MODERATION: STATUS_ON_MODERATION,
}


def _convert_enum_to_status(status_value: int) -> str:
if status_value == comment_pb2.CommentStatus.COMMENT_STATUS_UNSPECIFIED:
raise ValueError("Status must be specified")
return _ENUM_TO_DB_STATUS_BY_VALUE[status_value]


async def SetStatus(

Check warning on line 24 in src/commentservice/handler/set_status.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename function "SetStatus" to match the regular expression ^[a-z_][a-z0-9_]*$.

See more on https://sonarcloud.io/project/issues?id=esclient_comment-service&issues=AZq3mo0G_1mZfFUECfnM&open=AZq3mo0G_1mZfFUECfnM&pullRequest=35
service: CommentService,
request: comment_pb2.SetStatusRequest,
context: grpc.ServicerContext, # noqa: ARG001
) -> comment_pb2.SetStatusResponse:
try:
status_str = _convert_enum_to_status(request.status)
success = await service.set_status(request.comment_id, status_str)
return comment_pb2.SetStatusResponse(success=success)
except ValueError as e:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details(str(e))
return comment_pb2.SetStatusResponse(success=False)
except Exception as e:
context.set_code(grpc.StatusCode.INTERNAL)
context.set_details(f"Failed to set status: {e!s}")
return comment_pb2.SetStatusResponse(success=False)
4 changes: 1 addition & 3 deletions src/commentservice/repository/create_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
from asyncpg import Pool


async def create_comment(
db_pool: Pool, mod_id: int, author_id: int, text: str
) -> int:
async def create_comment(db_pool: Pool, mod_id: int, author_id: int, text: str) -> int:
async with db_pool.acquire() as conn:
comment_id = await conn.fetchval(
"""
Expand Down
15 changes: 0 additions & 15 deletions src/commentservice/repository/delete_comment.py

This file was deleted.

Loading