Skip to content
This repository was archived by the owner on Jan 21, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 27 additions & 0 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Python CI

on:
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.13"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
- name: Run tests and check coverage
run: |
poetry run pytest ./tests --cov=python_chat --cov=./tests --cov-report term-missing --cov-fail-under=85
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ mypy:
lint: ruff-lint mypy

test:
$(VENV)/bin/pytest src/tests
$(VENV)/bin/pytest ./tests

test-cov:
$(VENV)/bin/pytest src/tests --cov=src --cov=src/tests
$(VENV)/bin/pytest ./tests --cov=python_chat --cov=./tests --cov-report term-missing --cov-fail-under=85
6 changes: 3 additions & 3 deletions db_init.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from src.app import create_app
from src.database import db
from src.database.db_init import initialize_db
from python_chat.app import create_app
from python_chat.database import db
from python_chat.database.db_init import initialize_db

if __name__ == "__main__":
app = create_app()
Expand Down
963 changes: 481 additions & 482 deletions poetry.lock

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ dependencies = [
]

[tool.poetry]
package-mode = false

package-mode = true
packages = [{ include = "python_chat" }]

[tool.poetry.group.dev.dependencies]
pytest-cov = "^6.1.1"
Expand Down Expand Up @@ -137,9 +137,9 @@ skip-magic-trailing-comma = false
line-ending = "auto"

[tool.pytest.ini_options]
pythonpath = "src"
pythonpath = "."
addopts = ["--import-mode=importlib", "-v"]
testpaths = ["src/tests"]
testpaths = ["/tests"]
norecursedirs = [
"postgres-data",
".git",
Expand All @@ -151,7 +151,7 @@ norecursedirs = [
]

[tool.coverage.run]
source = ["src"]
source = ["python_chat"]
omit = [
"*/db_init.py",
"*/postgres-data/*",
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions src/app.py → python_chat/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from flask_login import LoginManager
from flask_socketio import SocketIO

from src.database import db
from src.database.models.user import User
from src.utils.logger import setup_logger
from python_chat.database import db
from python_chat.database.models.user import User
from python_chat.utils.logger import setup_logger

socketio = SocketIO()

Expand Down Expand Up @@ -48,7 +48,7 @@ def load_user(user_id):
app.logger.error(f"Error loading user {user_id}: {e}")
return None

from src.routes import admin, auth, chats, index, profile
from python_chat.routes import admin, auth, chats, index, profile

app.register_blueprint(auth.bp)
app.register_blueprint(index.bp)
Expand All @@ -58,7 +58,7 @@ def load_user(user_id):

# Initialize Socket.IO event handlers
with app.app_context():
from src.routes.events import init_socketio
from python_chat.routes.events import init_socketio

init_socketio(socketio)

Expand Down
10 changes: 5 additions & 5 deletions src/database/db_init.py → python_chat/database/db_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import os
import sys

from src.database import db
from src.database.models.chat import Chat, ChatMember
from src.database.models.chat_message import ChatMessage
from src.database.models.user import User
from python_chat.database import db
from python_chat.database.models.chat import Chat, ChatMember
from python_chat.database.models.chat_message import ChatMessage
from python_chat.database.models.user import User

# Add the project root to Python path to fix import issues
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
Expand Down Expand Up @@ -74,7 +74,7 @@ def initialize_db(app, db):

if __name__ == "__main__":
# Execute as standalone script
from src.app import create_app
from python_chat.app import create_app

app = create_app()
success = initialize_db(app, db)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from sqlalchemy import Boolean, DateTime, String
from sqlalchemy.orm import Mapped, mapped_column, relationship

from src.database import Base, db
from src.database.models.chat_member import ChatMember
from src.database.models.chat_message import ChatMessage
from src.database.models.user import User
from python_chat.database import Base, db
from python_chat.database.models.chat_member import ChatMember
from python_chat.database.models.chat_message import ChatMessage
from python_chat.database.models.user import User


class Chat(Base):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, Text
from sqlalchemy.orm import Mapped, mapped_column

from src.database import Base, db
from python_chat.database import Base, db


class ChatMember(Base):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from sqlalchemy import DateTime, ForeignKey, Integer, Text
from sqlalchemy.orm import Mapped, mapped_column

from src.database import Base, db
from python_chat.database import Base, db


class ChatMessage(Base):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from sqlalchemy.orm import Mapped, mapped_column
from werkzeug.security import check_password_hash, generate_password_hash

from src.database import Base, db
from python_chat.database import Base, db


class User(UserMixin, Base):
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions src/forms/auth.py → python_chat/forms/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from wtforms import BooleanField, PasswordField, StringField, SubmitField
from wtforms.validators import DataRequired, EqualTo, Length, ValidationError

from src.database import db
from src.database.models.user import User
from python_chat.database import db
from python_chat.database.models.user import User


class LoginForm(FlaskForm):
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions src/routes/admin.py → python_chat/routes/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from flask_login import current_user, login_required
from sqlalchemy import func, text

from src.database import db
from src.database.models.chat import Chat
from src.database.models.chat_message import ChatMessage
from src.database.models.user import User
from python_chat.database import db
from python_chat.database.models.chat import Chat
from python_chat.database.models.chat_message import ChatMessage
from python_chat.database.models.user import User

bp = Blueprint("admin", __name__)

Expand Down
6 changes: 3 additions & 3 deletions src/routes/auth.py → python_chat/routes/auth.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from flask import Blueprint, current_app, flash, redirect, render_template, request, url_for
from flask_login import current_user, login_user, logout_user

from src.database import db
from src.database.models.user import User
from src.forms.auth import LoginForm, RegistrationForm
from python_chat.database import db
from python_chat.database.models.user import User
from python_chat.forms.auth import LoginForm, RegistrationForm

bp = Blueprint("auth", __name__)

Expand Down
18 changes: 9 additions & 9 deletions src/routes/chats.py → python_chat/routes/chats.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
from sqlalchemy import select
from werkzeug.exceptions import HTTPException, NotFound

from src.database import db
from src.database.models.chat import Chat
from src.database.models.chat_member import ChatMember
from src.database.models.chat_message import ChatMessage
from src.database.models.user import User
from python_chat.database import db
from python_chat.database.models.chat import Chat
from python_chat.database.models.chat_member import ChatMember
from python_chat.database.models.chat_message import ChatMessage
from python_chat.database.models.user import User

bp = Blueprint("chats", __name__)

Expand Down Expand Up @@ -217,8 +217,8 @@ def ban_chat_user(chat_id):
chat.ban_member(target_user, reason)

# Получаем socket ID пользователя, чтобы принудительно удалить его из комнаты
from src.app import socketio
from src.routes.events import users
from python_chat.app import socketio
from python_chat.routes.events import users

# Найдем все активные соединения этого пользователя
user_socket_ids = [sid for sid, user_data in users.items() if user_data.get("user_id") == int(user_id)]
Expand Down Expand Up @@ -281,7 +281,7 @@ def unban_chat_user(chat_id):
chat.unban_member(target_user)

# Отправляем уведомление всем в чате о разбане пользователя
from src.app import socketio
from python_chat.app import socketio

room_name = str(chat_id)
socketio.emit("user_unbanned", {"username": target_user.username, "unbanned_by": current_user.username}, room=room_name)
Expand Down Expand Up @@ -346,7 +346,7 @@ def delete_message(message_id):
db.session.commit()

# Notify other users about the message deletion
from src.app import socketio
from python_chat.app import socketio

# Prepare additional info about who deleted the message and why
deletion_info = {
Expand Down
8 changes: 4 additions & 4 deletions src/routes/events.py → python_chat/routes/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from flask_login import current_user
from flask_socketio import emit, join_room, leave_room

from src.database import db
from src.database.models.chat_message import ChatMessage
from python_chat.database import db
from python_chat.database.models.chat_message import ChatMessage

# Global dictionary to store connected users and their information
users: dict[str, dict[str, Any]] = {}
Expand Down Expand Up @@ -67,7 +67,7 @@ def handle_message(data):
try:
from sqlalchemy import select

from src.database.models.chat_member import ChatMember
from python_chat.database.models.chat_member import ChatMember

# Проверяем, забанен ли пользователь
banned_check = db.session.execute(select(ChatMember).filter(ChatMember.chat_id == chat_id, ChatMember.user_id == user["user_id"], ChatMember.is_banned)).scalar_one_or_none()
Expand Down Expand Up @@ -129,7 +129,7 @@ def handle_join(data):
try:
from sqlalchemy import select

from src.database.models.chat_member import ChatMember
from python_chat.database.models.chat_member import ChatMember

# Check if the user exists in the chat member list and is banned
banned_check = db.session.execute(select(ChatMember).filter(ChatMember.chat_id == chat_id, ChatMember.user_id == user["user_id"], ChatMember.is_banned)).scalar_one_or_none()
Expand Down
6 changes: 3 additions & 3 deletions src/routes/index.py → python_chat/routes/index.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from flask import Blueprint, current_app, redirect, render_template, url_for
from flask_login import current_user

from src.database import db
from src.database.models.chat import Chat
from src.database.models.chat_member import ChatMember
from python_chat.database import db
from python_chat.database.models.chat import Chat
from python_chat.database.models.chat_member import ChatMember

bp = Blueprint("index", __name__)

Expand Down
6 changes: 3 additions & 3 deletions src/routes/profile.py → python_chat/routes/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from flask_login import current_user, login_required
from sqlalchemy import func, select

from src.database import db
from src.database.models.chat_member import ChatMember
from src.database.models.chat_message import ChatMessage
from python_chat.database import db
from python_chat.database.models.chat_member import ChatMember
from python_chat.database.models.chat_message import ChatMessage

bp = Blueprint("profile", __name__)

Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion run.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.app import create_app, socketio # pragma: no cover
from python_chat.app import create_app, socketio # pragma: no cover

if __name__ == "__main__":
app = create_app()
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from sqlalchemy.orm import scoped_session, sessionmaker
from testcontainers.postgres import PostgresContainer

from src.app import create_app
from src.database import db
from python_chat.app import create_app
from python_chat.database import db


@pytest.fixture(scope="session")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.database.models import Chat, ChatMember, ChatMessage, User
from python_chat.database.models import Chat, ChatMember, ChatMessage, User


class TestChat:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from sqlalchemy.orm.collections import InstrumentedList

from src.database.models import Chat, ChatMember, User
from python_chat.database.models import Chat, ChatMember, User


class TestChatMember:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.database.models import Chat, ChatMessage, User
from python_chat.database.models import Chat, ChatMessage, User


class TestChatMessage:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.database.models import Chat, ChatMember, ChatMessage, User
from python_chat.database.models import Chat, ChatMember, ChatMessage, User


class TestUser:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from flask_socketio import SocketIO, SocketIOTestClient
from sqlalchemy.orm import Session

from src.database.models.chat import Chat
from src.database.models.chat_member import ChatMember
from src.database.models.chat_message import ChatMessage
from src.database.models.user import User
from python_chat.database.models.chat import Chat
from python_chat.database.models.chat_member import ChatMember
from python_chat.database.models.chat_message import ChatMessage
from python_chat.database.models.user import User

# TODO To be honest, routes tests are not integration tests. (Even when they use db session)
# They are more like unit tests, because they test only one route at a time.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
from flask.testing import FlaskClient
from sqlalchemy.orm import Session

from src.database.models.chat import Chat
from src.database.models.chat_message import ChatMessage
from src.database.models.user import User
from python_chat.database.models.chat import Chat
from python_chat.database.models.chat_message import ChatMessage
from python_chat.database.models.user import User


class TestAdminRoutes:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from src.database.models.user import User
from python_chat.database.models.user import User


class TestAuthRoutes:
Expand Down
Loading