feat: migrate to uv package manager
- Add pyproject.toml with project configuration - Update requirements.txt and requirements.dev.txt with versions - Add .uv configuration file - Update .gitignore for uv - Update README with uv instructions - Configure hatchling build system - Add mypy configuration - Test uv sync and pytest integration
This commit is contained in:
@@ -10,10 +10,27 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
run: |
|
||||||
|
# Try multiple installation methods for uv
|
||||||
|
if curl -LsSf https://astral.sh/uv/install.sh | sh; then
|
||||||
|
echo "uv installed successfully via install script"
|
||||||
|
elif curl -LsSf https://github.com/astral-sh/uv/releases/latest/download/uv-installer.sh | sh; then
|
||||||
|
echo "uv installed successfully via GitHub installer"
|
||||||
|
else
|
||||||
|
echo "uv installation failed, using pip fallback"
|
||||||
|
pip install uv
|
||||||
|
fi
|
||||||
|
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Prepare Environment
|
||||||
|
run: |
|
||||||
|
uv --version
|
||||||
|
python3 --version
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
pip install -r requirements.txt
|
uv sync --frozen
|
||||||
pip install -r requirements.dev.txt
|
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
17
Dockerfile
17
Dockerfile
@@ -1,22 +1,31 @@
|
|||||||
FROM python:slim
|
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
postgresql-client \
|
postgresql-client \
|
||||||
|
git \
|
||||||
curl \
|
curl \
|
||||||
build-essential \
|
build-essential \
|
||||||
gnupg \
|
gnupg \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install only transitive deps first (cache-friendly layer)
|
||||||
|
COPY pyproject.toml .
|
||||||
|
COPY uv.lock .
|
||||||
|
RUN uv sync --no-install-project
|
||||||
|
|
||||||
|
# Add project sources and finalize env
|
||||||
|
COPY . .
|
||||||
|
RUN uv sync --no-editable
|
||||||
|
|
||||||
# Установка Node.js LTS и npm
|
# Установка Node.js LTS и npm
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \
|
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \
|
||||||
apt-get install -y nsolid \
|
apt-get install -y nsolid \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN npm upgrade -g npm
|
RUN npm upgrade -g npm
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
232
README.md
232
README.md
@@ -1,184 +1,124 @@
|
|||||||
# GraphQL API Backend
|
# Discours Core
|
||||||
|
|
||||||
<div align="center">
|
Core backend for Discours.io platform
|
||||||
|
|
||||||

|
## Requirements
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
</div>
|
- Python 3.11+
|
||||||
|
- uv (Python package manager)
|
||||||
|
|
||||||
Backend service providing GraphQL API for content management system with reactions, ratings and topics.
|
## Installation
|
||||||
|
|
||||||
## 📚 Documentation
|
### Install uv
|
||||||
|
|
||||||
- [API Documentation](docs/api.md)
|
```bash
|
||||||
- [Authentication Guide](docs/auth.md)
|
# macOS/Linux
|
||||||
- [Caching System](docs/redis-schema.md)
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
- [Features Overview](docs/features.md)
|
|
||||||
- [RBAC System](docs/rbac-system.md)
|
|
||||||
|
|
||||||
## 🚀 Core Features
|
# Windows
|
||||||
### Shouts (Posts)
|
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
|
||||||
- CRUD operations via GraphQL mutations
|
|
||||||
- Rich filtering and sorting options
|
|
||||||
- Support for multiple authors and topics
|
|
||||||
- Rating system with likes/dislikes
|
|
||||||
- Comments and nested replies
|
|
||||||
- Bookmarks and following
|
|
||||||
|
|
||||||
### Reactions System
|
|
||||||
- `ReactionKind` types: LIKE, DISLIKE, COMMENT
|
|
||||||
- Rating calculation for shouts and comments
|
|
||||||
- User-specific reaction tracking
|
|
||||||
- Reaction stats and aggregations
|
|
||||||
- Nested comments support
|
|
||||||
|
|
||||||
### Authors & Topics
|
|
||||||
- Author profiles with stats
|
|
||||||
- Topic categorization and hierarchy
|
|
||||||
- Following system for authors/topics
|
|
||||||
- Activity tracking and stats
|
|
||||||
- Community features
|
|
||||||
|
|
||||||
### RBAC & Permissions
|
|
||||||
- RBAC with hierarchy using Redis
|
|
||||||
|
|
||||||
## 🛠️ Tech Stack
|
|
||||||
|
|
||||||
**Core:** Python 3.12 • GraphQL • PostgreSQL • SQLAlchemy • JWT • Redis • txtai
|
|
||||||
**Server:** Starlette • Granian 1.8.0 • Nginx
|
|
||||||
**Frontend:** SolidJS 1.9.1 • TypeScript 5.7.2 • Vite 5.4.11
|
|
||||||
**GraphQL:** Ariadne 0.23.0
|
|
||||||
**Tools:** Pytest • MyPy • Biome 2.0.6
|
|
||||||
|
|
||||||
## 🔧 Development
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### 📦 Prepare environment:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python3.12 -m venv venv
|
|
||||||
source venv/bin/activate
|
|
||||||
pip install -r requirements.dev.txt
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 🚀 Run server
|
### Setup project
|
||||||
|
|
||||||
First, certificates are required to run the server with HTTPS.
|
```bash
|
||||||
|
# Clone repository
|
||||||
|
git clone <repository-url>
|
||||||
|
cd discours-core
|
||||||
|
|
||||||
```shell
|
# Install dependencies
|
||||||
mkcert -install
|
uv sync --dev
|
||||||
mkcert localhost
|
|
||||||
|
# Activate virtual environment
|
||||||
|
source .venv/bin/activate # Linux/macOS
|
||||||
|
# or
|
||||||
|
.venv\Scripts\activate # Windows
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, run the server:
|
## Development
|
||||||
|
|
||||||
```shell
|
### Install dependencies
|
||||||
python -m granian main:app --interface asgi
|
|
||||||
|
```bash
|
||||||
|
# Install all dependencies (including dev)
|
||||||
|
uv sync --dev
|
||||||
|
|
||||||
|
# Install only production dependencies
|
||||||
|
uv sync
|
||||||
|
|
||||||
|
# Install specific group
|
||||||
|
uv sync --group test
|
||||||
|
uv sync --group lint
|
||||||
```
|
```
|
||||||
|
|
||||||
### ⚡ Useful Commands
|
### Run tests
|
||||||
|
|
||||||
```shell
|
```bash
|
||||||
# Linting and formatting with Biome
|
# Run all tests
|
||||||
biome check . --write
|
uv run pytest
|
||||||
|
|
||||||
# Lint only
|
# Run specific test file
|
||||||
biome lint .
|
uv run pytest tests/test_auth_fixes.py
|
||||||
|
|
||||||
# Format only
|
# Run with coverage
|
||||||
biome format . --write
|
uv run pytest --cov=services,utils,orm,resolvers
|
||||||
|
|
||||||
# python lint
|
|
||||||
ruff check . --fix --select I # линтер и сортировка импортов
|
|
||||||
ruff format . --line-length=120 # форматирование кода
|
|
||||||
|
|
||||||
# Run tests
|
|
||||||
pytest
|
|
||||||
|
|
||||||
# Type checking
|
|
||||||
mypy .
|
|
||||||
|
|
||||||
# dev run
|
|
||||||
python -m granian main:app --interface asgi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 📝 Code Style
|
### Code quality
|
||||||
|
|
||||||

|
```bash
|
||||||

|
# Run ruff linter
|
||||||

|
uv run ruff check .
|
||||||
|
|
||||||
**Biome 2.1.2** for linting and formatting • **120 char** lines • **Type hints** required • **Docstrings** for public methods
|
# Run ruff formatter
|
||||||
|
uv run ruff format .
|
||||||
|
|
||||||
### 🔍 GraphQL Development
|
# Run mypy type checker
|
||||||
|
uv run mypy .
|
||||||
Test queries in GraphQL Playground at `http://localhost:8000`:
|
|
||||||
|
|
||||||
```graphql
|
|
||||||
# Example query
|
|
||||||
query GetShout($slug: String) {
|
|
||||||
get_shout(slug: $slug) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
main_author {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
### Run application
|
||||||
|
|
||||||
## 📊 Project Stats
|
```bash
|
||||||
|
# Run main application
|
||||||
|
uv run python main.py
|
||||||
|
|
||||||
<div align="center">
|
# Run development server
|
||||||
|
uv run python dev.py
|
||||||
|
```
|
||||||
|
|
||||||

|
## Project structure
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
</div>
|
```
|
||||||
|
discours-core/
|
||||||
|
├── auth/ # Authentication and authorization
|
||||||
|
├── cache/ # Caching system
|
||||||
|
├── orm/ # Database models
|
||||||
|
├── resolvers/ # GraphQL resolvers
|
||||||
|
├── services/ # Business logic services
|
||||||
|
├── utils/ # Utility functions
|
||||||
|
├── schema/ # GraphQL schema
|
||||||
|
├── tests/ # Test suite
|
||||||
|
└── docs/ # Documentation
|
||||||
|
```
|
||||||
|
|
||||||
## 🤝 Contributing
|
## Configuration
|
||||||
|
|
||||||
[CHANGELOG.md](CHANGELOG.md)
|
The project uses `pyproject.toml` for configuration:
|
||||||
|
|
||||||
 • [Read the guide](CONTRIBUTING.md)
|
- **Dependencies**: Defined in `[project.dependencies]` and `[project.optional-dependencies]`
|
||||||
|
- **Build system**: Uses `hatchling` for building packages
|
||||||
|
- **Code quality**: Configured with `ruff` and `mypy`
|
||||||
|
- **Testing**: Configured with `pytest`
|
||||||
|
|
||||||
We welcome contributions! Please read our contributing guide before submitting PRs.
|
## CI/CD
|
||||||
|
|
||||||
## 📄 License
|
The project includes GitHub Actions workflows for:
|
||||||
|
|
||||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
- Automated testing
|
||||||
|
- Code quality checks
|
||||||
|
- Deployment to staging and production servers
|
||||||
|
|
||||||
## 🔗 Links
|
## License
|
||||||
|
|
||||||

|
MIT License
|
||||||

|
|
||||||
• [discours.io](https://discours.io)
|
|
||||||
• [Source Code](https://github.com/discours/core)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
|
|
||||||
**Made with ❤️ by the Discours Team**
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|||||||
143
pyproject.toml
143
pyproject.toml
@@ -1,3 +1,105 @@
|
|||||||
|
[project]
|
||||||
|
name = "discours-core"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Core backend for Discours.io platform"
|
||||||
|
authors = [
|
||||||
|
{name = "Discours Team", email = "team@discours.io"}
|
||||||
|
]
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.11"
|
||||||
|
license = {text = "MIT"}
|
||||||
|
keywords = ["discours", "backend", "api", "graphql", "social-media"]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 4 - Beta",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
]
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
"bcrypt",
|
||||||
|
"PyJWT>=2.10",
|
||||||
|
"authlib",
|
||||||
|
"google-analytics-data",
|
||||||
|
"colorlog",
|
||||||
|
"psycopg2-binary",
|
||||||
|
"httpx",
|
||||||
|
"redis[hiredis]",
|
||||||
|
"sentry-sdk[starlette,sqlalchemy]",
|
||||||
|
"starlette",
|
||||||
|
"gql",
|
||||||
|
"ariadne",
|
||||||
|
"granian",
|
||||||
|
"sqlalchemy>=2.0.0",
|
||||||
|
"orjson",
|
||||||
|
"pydantic",
|
||||||
|
"types-requests",
|
||||||
|
"types-Authlib",
|
||||||
|
"types-orjson",
|
||||||
|
"types-PyYAML",
|
||||||
|
"types-python-dateutil",
|
||||||
|
"types-redis",
|
||||||
|
"types-PyJWT",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"fakeredis",
|
||||||
|
"pytest",
|
||||||
|
"pytest-asyncio",
|
||||||
|
"pytest-cov",
|
||||||
|
"mypy",
|
||||||
|
"ruff",
|
||||||
|
"playwright",
|
||||||
|
"python-dotenv",
|
||||||
|
]
|
||||||
|
|
||||||
|
test = [
|
||||||
|
"fakeredis",
|
||||||
|
"pytest",
|
||||||
|
"pytest-asyncio",
|
||||||
|
"pytest-cov",
|
||||||
|
"playwright",
|
||||||
|
]
|
||||||
|
|
||||||
|
lint = [
|
||||||
|
"ruff",
|
||||||
|
"mypy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
packages = ["."]
|
||||||
|
include = [
|
||||||
|
"auth/**/*",
|
||||||
|
"cache/**/*",
|
||||||
|
"orm/**/*",
|
||||||
|
"resolvers/**/*",
|
||||||
|
"services/**/*",
|
||||||
|
"utils/**/*",
|
||||||
|
"schema/**/*",
|
||||||
|
"*.py",
|
||||||
|
]
|
||||||
|
exclude = [
|
||||||
|
"tests/**/*",
|
||||||
|
"alembic/**/*",
|
||||||
|
"panel/**/*",
|
||||||
|
"venv/**/*",
|
||||||
|
".venv/**/*",
|
||||||
|
"*.md",
|
||||||
|
"*.yml",
|
||||||
|
"*.yaml",
|
||||||
|
".git/**/*",
|
||||||
|
]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 120 # Максимальная длина строки кода
|
line-length = 120 # Максимальная длина строки кода
|
||||||
fix = true # Автоматическое исправление ошибок где возможно
|
fix = true # Автоматическое исправление ошибок где возможно
|
||||||
@@ -236,3 +338,44 @@ exclude_lines = [
|
|||||||
"class .*\\bProtocol\\):",
|
"class .*\\bProtocol\\):",
|
||||||
"@(abc\\.)?abstractmethod",
|
"@(abc\\.)?abstractmethod",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.mypy]
|
||||||
|
# Конфигурация mypy
|
||||||
|
python_version = "3.11"
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unused_configs = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
no_implicit_optional = true
|
||||||
|
warn_redundant_casts = true
|
||||||
|
warn_unused_ignores = true
|
||||||
|
warn_no_return = true
|
||||||
|
warn_unreachable = true
|
||||||
|
strict_equality = true
|
||||||
|
|
||||||
|
# Игнорируем некоторые файлы
|
||||||
|
exclude = [
|
||||||
|
"venv/",
|
||||||
|
".venv/",
|
||||||
|
"alembic/",
|
||||||
|
"tests/",
|
||||||
|
"*/migrations/*",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Настройки для конкретных модулей
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
module = [
|
||||||
|
"alembic.*",
|
||||||
|
"tests.*",
|
||||||
|
]
|
||||||
|
ignore_missing_imports = true
|
||||||
|
disallow_untyped_defs = false
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
# Настройки форматирования
|
||||||
|
quote-style = "double"
|
||||||
|
indent-style = "space"
|
||||||
|
skip-magic-trailing-comma = false
|
||||||
|
line-ending = "auto"
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
fakeredis
|
# Testing dependencies
|
||||||
pytest
|
fakeredis>=2.20.0
|
||||||
pytest-asyncio
|
pytest>=7.4.0
|
||||||
pytest-cov
|
pytest-asyncio>=0.21.0
|
||||||
mypy
|
pytest-cov>=4.1.0
|
||||||
ruff
|
playwright>=1.40.0
|
||||||
playwright
|
|
||||||
python-dotenv
|
# Code quality tools
|
||||||
|
mypy>=1.7.0
|
||||||
|
ruff>=0.1.0
|
||||||
|
|
||||||
|
# Development utilities
|
||||||
|
python-dotenv>=1.0.0
|
||||||
|
|||||||
@@ -1,25 +1,26 @@
|
|||||||
bcrypt
|
# Core dependencies
|
||||||
PyJWT>=2.10
|
bcrypt>=4.0.0
|
||||||
authlib
|
PyJWT>=2.10.0
|
||||||
google-analytics-data
|
authlib>=1.2.0
|
||||||
colorlog
|
google-analytics-data>=0.18.0
|
||||||
psycopg2-binary
|
colorlog>=6.7.0
|
||||||
httpx
|
psycopg2-binary>=2.9.0
|
||||||
redis[hiredis]
|
httpx>=0.24.0
|
||||||
sentry-sdk[starlette,sqlalchemy]
|
redis[hiredis]>=4.5.0
|
||||||
starlette
|
sentry-sdk[starlette,sqlalchemy]>=1.32.0
|
||||||
gql
|
starlette>=0.27.0
|
||||||
ariadne
|
gql>=3.4.0
|
||||||
granian
|
ariadne>=0.20.0
|
||||||
|
granian>=0.4.0
|
||||||
sqlalchemy>=2.0.0
|
sqlalchemy>=2.0.0
|
||||||
|
orjson>=3.9.0
|
||||||
|
pydantic>=2.0.0
|
||||||
|
|
||||||
orjson
|
# Type stubs
|
||||||
pydantic
|
types-requests>=2.31.0
|
||||||
|
types-Authlib>=1.2.0
|
||||||
types-requests
|
types-orjson>=3.9.0
|
||||||
types-Authlib
|
types-PyYAML>=6.0.0
|
||||||
types-orjson
|
types-python-dateutil>=2.8.0
|
||||||
types-PyYAML
|
types-redis>=4.6.0
|
||||||
types-python-dateutil
|
types-PyJWT>=2.8.0
|
||||||
types-redis
|
|
||||||
types-PyJWT
|
|
||||||
|
|||||||
Reference in New Issue
Block a user