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:
2025-08-12 13:12:39 +03:00
parent 333dc19020
commit 663942c41e
7 changed files with 2168 additions and 183 deletions

View File

@@ -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: |

View File

@@ -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
View File

@@ -1,184 +1,124 @@
# GraphQL API Backend # Discours Core
<div align="center"> Core backend for Discours.io platform
![Version](https://img.shields.io/badge/v0.7.8-lightgrey) ## Requirements
![Tests](https://img.shields.io/badge/tests%2090%25-lightcyan?logo=pytest&logoColor=black)
![Python](https://img.shields.io/badge/python%203.12+-lightblue?logo=python&logoColor=black)
![PostgreSQL](https://img.shields.io/badge/postgresql%2016.1-lightblue?logo=postgresql&logoColor=black)
![Redis](https://img.shields.io/badge/redis%206.2.0-salmon?logo=redis&logoColor=black)
![txtai](https://img.shields.io/badge/txtai%208.6.0-lavender?logo=elasticsearch&logoColor=black)
![GraphQL](https://img.shields.io/badge/ariadne%200.23.0-pink?logo=graphql&logoColor=black)
![TypeScript](https://img.shields.io/badge/typescript%205.8.3-blue?logo=typescript&logoColor=black)
![SolidJS](https://img.shields.io/badge/solidjs%201.9.1-blue?logo=solid&logoColor=black)
![Vite](https://img.shields.io/badge/vite%207.0.0-blue?logo=vite&logoColor=black)
![Biome](https://img.shields.io/badge/biome%202.0.6-blue?logo=biome&logoColor=black)
</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
![PRs Welcome](https://img.shields.io/badge/PRs-welcome-lightcyan?logo=git&logoColor=black)
![Biome](https://img.shields.io/badge/biome%202.0.6-yellow?logo=code&logoColor=black)
![Mypy](https://img.shields.io/badge/mypy-lavender?logo=python&logoColor=black)
### 📦 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
![Line 120](https://img.shields.io/badge/line%20120-lightblue?logo=prettier&logoColor=black) ```bash
![Types](https://img.shields.io/badge/typed-pink?logo=python&logoColor=black) # Run ruff linter
![Docs](https://img.shields.io/badge/documented-lightcyan?logo=markdown&logoColor=black) 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
```
![Lines](https://img.shields.io/badge/15k%2B-lines-lightcyan?logo=code&logoColor=black) ## Project structure
![Files](https://img.shields.io/badge/100%2B-files-lavender?logo=folder&logoColor=black)
![Coverage](https://img.shields.io/badge/90%25-coverage-gold?logo=test-tube&logoColor=black)
![MIT](https://img.shields.io/badge/MIT-license-silver?logo=balance-scale&logoColor=black)
</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:
![Contributing](https://img.shields.io/badge/contributing-guide-salmon?logo=handshake&logoColor=black) • [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
![Website](https://img.shields.io/badge/discours.io-website-lightblue?logo=globe&logoColor=black) MIT License
![GitHub](https://img.shields.io/badge/discours/core-github-silver?logo=github&logoColor=black)
• [discours.io](https://discours.io)
• [Source Code](https://github.com/discours/core)
---
<div align="center">
**Made with ❤️ by the Discours Team**
![Made with Love](https://img.shields.io/badge/made%20with%20❤-pink?logo=heart&logoColor=black)
![Open Source](https://img.shields.io/badge/open%20source-lightcyan?logo=open-source-initiative&logoColor=black)
</div>

View File

@@ -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"

View File

@@ -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

View File

@@ -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

1870
uv.lock generated Normal file

File diff suppressed because it is too large Load Diff