pyproject-build

This commit is contained in:
Untone 2023-10-14 14:52:04 +03:00
parent bc2fc7c9a0
commit 499893e10b
13 changed files with 100 additions and 75 deletions

View File

@ -1,6 +0,0 @@
[flake8]
ignore = E203,W504,W191,W503
exclude = .git
max-complexity = 10
max-line-length = 108
indent-string = ' '

View File

@ -1,3 +1,9 @@
[0.2.13]
- migrated to pyproject and poetry
- validators added
- fixed graphql requests for core api
- uses official redis[hiredis] async
[0.2.12] [0.2.12]
- sigil is back for test - sigil is back for test

View File

@ -1,8 +1,20 @@
# Use an official Python runtime as a parent image
FROM python:slim FROM python:slim
# Set the working directory in the container to /app
WORKDIR /app WORKDIR /app
# Add metadata to the image to describe that the container is listening on port 80
EXPOSE 80 EXPOSE 80
COPY requirements.txt .
RUN apt-get update && apt-get install -y gcc && pip install -r requirements.txt # Copy the current directory contents into the container at /app
COPY . . COPY . /app
# Install any needed packages specified in pyproject.toml
RUN apt-get update && apt-get install -y gcc curl && \
curl -sSL https://install.python-poetry.org | python - && \
poetry config virtualenvs.create false && \
poetry install --no-dev
# Run server.py when the container launches
CMD ["python", "server.py"] CMD ["python", "server.py"]

54
pyproject.toml Normal file
View File

@ -0,0 +1,54 @@
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "discoursio-inbox"
version = "0.2.13"
description = "Inbox server for discours.io"
authors = ["Tony Rewin <anton.rewin@gmail.com>"]
[tool.poetry.dependencies]
python = "^3.8"
sentry-sdk = "^1.4.3"
redis = {extras = ["hiredis"], version = "^3.5.3"}
ariadne = "^0.13.0"
starlette = "^0.14.2"
uvicorn = "^0.15.0"
httpx = "^0.18.2"
itsdangerous = "^2.0.1"
[tool.poetry.dev-dependencies]
pytest = "^6.2.5"
[tool.black]
line-length = 120
target-version = ['py312']
include = '\.pyi?$'
exclude = '''
(
/(
\.eggs # exclude a few common directories in the
| \.git # root of the project
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
| foo.py # also separately exclude a file named foo.py in
# the root of the project
)
'''
[tool.isort]
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
line_length = 120

View File

@ -1,13 +0,0 @@
sentry-sdk
redis[hiredis]
ariadne
starlette
uvicorn
httpx
itsdangerous
######## development deps
isort
brunette
flake8
mypy
its

View File

@ -1,7 +1,7 @@
import json import json
import uuid import uuid
from datetime import datetime, timezone from datetime import datetime, timezone
from validators.chat import Chat from validators.inbox import Chat
from services.auth import login_required from services.auth import login_required
from services.redis import redis from services.redis import redis
from services.schema import mutation from services.schema import mutation
@ -85,6 +85,9 @@ async def create_chat(_, info, title="", members=None):
for member_id in members: for member_id in members:
await redis.execute("SADD", f"chats_by_author/{member_id}", chat_id) await redis.execute("SADD", f"chats_by_author/{member_id}", chat_id)
print(f"[resolvers.chatss] creating: {chat}")
await redis.execute("SET", f"chats/{chat_id}", json.dumps(chat)) await redis.execute("SET", f"chats/{chat_id}", json.dumps(chat))
await redis.execute("SET", f"chats/{chat_id}/next_message_id", str(0)) await redis.execute("SET", f"chats/{chat_id}/next_message_id", str(0))

View File

@ -4,7 +4,7 @@ from services.core import get_author, get_network
from services.redis import redis from services.redis import redis
from services.auth import login_required from services.auth import login_required
from services.schema import query from services.schema import query
from validators.chat import Message, Chat, ChatMember from validators.inbox import Message, Chat, ChatMember
from .chats import create_chat from .chats import create_chat
from .unread import get_unread_counter from .unread import get_unread_counter
import asyncio import asyncio
@ -60,7 +60,7 @@ async def load_chats(
if len(cids) == 0: if len(cids) == 0:
print(f"[resolvers.load] no chats for user with id={author_id}") print(f"[resolvers.load] no chats for user with id={author_id}")
r = await create_chat(None, info, members=[2]) # member with id = 2 is discours r = await create_chat(None, info, members=[2]) # member with id = 2 is discours
print(f"[resolvers.load] created chat: {r}") print(f"[resolvers.load] created chat: {r['chat']}")
cids.append(r["chat"]["id"]) cids.append(r["chat"]["id"])
for cid in cids: for cid in cids:
async with lock: async with lock:
@ -74,7 +74,6 @@ async def load_chats(
c["members"] = [] c["members"] = []
for member_id in member_ids: for member_id in member_ids:
a = await get_author(member_id) a = await get_author(member_id)
print(f"[resolvers.load] author with id={member_id}: {a}")
if a: if a:
a["online"] = a.get("id") in members_online a["online"] = a.get("id") in members_online
c["members"].append(a) c["members"].append(a)

View File

@ -1,7 +1,7 @@
import json import json
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import List from typing import List
from validators.chat import Message from validators.inbox import Message
from services.auth import login_required from services.auth import login_required
from services.presence import notify_message from services.presence import notify_message
from services.redis import redis from services.redis import redis

View File

@ -47,7 +47,7 @@ async def check_auth(req):
is_authenticated = user_id is not None is_authenticated = user_id is not None
return is_authenticated, user_id return is_authenticated, user_id
except Exception as e: except Exception as e:
print(f"response contains no proper data: {r}") print(f"{e}: {r}")
return False, None return False, None

View File

@ -9,7 +9,9 @@ headers = {"Content-Type": "application/json"}
async def get_author(author_id): async def get_author(author_id):
gql = { gql = {
"query": "query GetAuthorById($author_id: Int!) { getAuthorById(author_id: $author_id) { id slug userpic name lastSeen } }", "query": '''query GetAuthorById($author_id: Int!) {
getAuthorById(author_id: $author_id) { id slug userpic name lastSeen }
}''',
"operation": "GetAuthorById", "operation": "GetAuthorById",
"variables": {"author_id": author_id}, "variables": {"author_id": author_id},
} }
@ -18,9 +20,7 @@ async def get_author(author_id):
response = await client.post( response = await client.post(
API_BASE, headers=headers, data=json.dumps(gql) API_BASE, headers=headers, data=json.dumps(gql)
) )
print( print(f"[services.core] get_author: {response.status_code} {response.text}")
f"[services.core] get_author response: {response.status_code} {response.text}"
)
if response.status_code != 200: if response.status_code != 200:
return None return None
r = response.json() r = response.json()
@ -33,7 +33,11 @@ async def get_author(author_id):
async def get_network(author_id: int, limit: int = 50, offset: int = 0) -> list: async def get_network(author_id: int, limit: int = 50, offset: int = 0) -> list:
gql = { gql = {
"query": "query LoadAuthors($author_id: Int!, $limit: Int, $offset: Int) { authorFollowings(author_id: $author_id, limit: $limit, offset: $offset) { id slug userpic name } }", "query": '''query LoadAuthors($author_id: Int!, $limit: Int, $offset: Int) {
authorFollowings(author_id: $author_id, limit: $limit, offset: $offset) {
id slug userpic name
}
}''',
"operation": "LoadAuthors", "operation": "LoadAuthors",
"variables": {"author_id": author_id, "limit": limit, "offset": offset}, "variables": {"author_id": author_id, "limit": limit, "offset": offset},
} }
@ -60,7 +64,11 @@ async def get_network(author_id: int, limit: int = 50, offset: int = 0) -> list:
async def get_followers(author_id, amount): async def get_followers(author_id, amount):
gql = { gql = {
"query": "query LoadAuthors($author_id: Int!, $limit: Int, $offset: Int) { authorFollowers(author_id: $author_id, limit: $limit) { id slug userpic name } }", "query": '''query LoadAuthors($author_id: Int!, $limit: Int, $offset: Int) {
authorFollowers(author_id: $author_id, limit: $limit) {
id slug userpic name
}
}''',
"operation": "LoadAuthors", "operation": "LoadAuthors",
"variables": {"author_id": author_id, "limit": amount}, "variables": {"author_id": author_id, "limit": amount},
} }
@ -75,5 +83,6 @@ async def get_followers(author_id, amount):
r = response.json() r = response.json()
followers = r.get("data", {}).get("authorFollowers", []) followers = r.get("data", {}).get("authorFollowers", [])
except Exception as e: except Exception as e:
print(e)
followers = [] followers = []
return followers return followers

View File

@ -1,6 +1,6 @@
import json import json
from services.redis import redis from services.redis import redis
from validators.chat import Message from validators.inbox import Message
async def notify_message(message: Message, chat_id: str): async def notify_message(message: Message, chat_id: str):

View File

@ -1,39 +0,0 @@
[isort]
# https://github.com/PyCQA/isort
line_length = 120
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
force_alphabetical_sort = false
[tool:brunette]
# https://github.com/odwyersoftware/brunette
line-length = 120
single-quotes = false
[flake8]
# https://github.com/PyCQA/flake8
exclude = .git,__pycache__,.mypy_cache,.vercel
max-line-length = 120
max-complexity = 15
select = B,C,E,F,W,T4,B9
# E203: Whitespace before ':'
# E266: Too many leading '#' for block comment
# E501: Line too long (82 > 79 characters)
# E722: Do not use bare except, specify exception instead
# W503: Line break occurred before a binary operator
# F403: 'from module import *' used; unable to detect undefined names
# C901: Function is too complex
ignore = E203,E266,E501,E722,W503,F403,C901
[mypy]
# https://github.com/python/mypy
ignore_missing_imports = true
warn_return_any = false
warn_unused_configs = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
[mypy-api.*]
ignore_errors = true