Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added base usage example for aiohttp server #231

Merged
merged 2 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.DS_Store
.idea/
.vscode
.venv/
.env

# Byte-compiled / optimized / DLL files
__pycache__/
Expand All @@ -10,6 +13,7 @@ __pycache__/

# Distribution / packaging
.Python
.installed.cfg
env/
venv/
build/
Expand All @@ -23,7 +27,6 @@ parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg*
*.ini

Expand Down
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Overview
The complete documentation:
http://peewee-async-lib.readthedocs.io


Install
-------

Expand All @@ -37,14 +38,14 @@ or for MySQL:
pip install peewee-async[mysql]
```


Quickstart
----------

Create 'test' PostgreSQL database for running this snippet:

createdb -E utf-8 test


```python
import asyncio
import peewee
Expand Down Expand Up @@ -99,35 +100,54 @@ with objects.allow_sync():
# Not bad. Watch this, I'm async!
```


More examples
-------------

Build and run with Docker Compose:

```bash
docker compose -f examples/docker-compose.yaml build
rudyryk marked this conversation as resolved.
Show resolved Hide resolved
docker compose -f examples/docker-compose.yaml up
```


Documentation
-------------

http://peewee-async-lib.readthedocs.io

http://peewee-async.readthedocs.io - **DEPRECATED**


Developing
----------

Install dependencies using pip:

```bash
pip install -e .[develop]
```

Or using [poetry](https://python-poetry.org/docs/):

```bash
poetry install -E develop
```

Run databases:

```bash
docker-compose up -d
```

Run tests:

```bash
pytest tests -v -s
```


Discuss
-------

Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: '3.3'

services:
postgres:
image: postgres
image: postgres:16.2-alpine3.19
ports:
- '5432:5432'
command: postgres -c log_statement=all
Expand Down
18 changes: 18 additions & 0 deletions examples/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM python:3.10.14-slim

WORKDIR /app

RUN python -m venv /opt/venv

ENV VIRTUAL_ENV=/opt/venv
ENV PATH=${VIRTUAL_ENV}/bin:${PATH}

RUN pip install --upgrade pip

ADD examples/requirements.txt .

RUN pip install -r requirements.txt

ADD *.py pyproject.toml README.md ./

RUN pip install -e .
104 changes: 104 additions & 0 deletions examples/aiohttp_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import json
import logging
import os
# from asyncio import sleep as async_sleep
rudyryk marked this conversation as resolved.
Show resolved Hide resolved
from secrets import token_hex
from datetime import datetime
from aiohttp import web
from peewee import Model, CharField, TextField, DateTimeField
from peewee_async import PooledPostgresqlDatabase, Manager

logger = logging.getLogger(__name__)

database = PooledPostgresqlDatabase(
'examples', user='postgres', password='postgres',
host='db-postgres', port=5432,
min_connections=10, max_connections=100,
)

objects = Manager(database)
rudyryk marked this conversation as resolved.
Show resolved Hide resolved

app = web.Application()

routes = web.RouteTableDef()


class Post(Model):
title = CharField(unique=True)
key = CharField(unique=True, default=lambda: token_hex(8))
text = TextField()
created_at = DateTimeField(index=True, default=datetime.utcnow)

class Meta:
database = database

def __str__(self):
return self.title


def create_tables():
with database:
database.create_tables([Post], safe=True)


def add_post(title, text):
with database.atomic():
Post.create(title=title, text=text)


@routes.get('/')
async def get_post_endpoint(request):
query = dict(request.query)
post_id = query.pop('p', 1)
post = await objects.get_or_none(Post, id=post_id)
if post:
return web.Response(text=post.text)
else:
return web.Response(text="Not found", status=404)


@routes.post('/')
async def update_post_endpoint(request):
query = dict(request.query)
post_id = query.pop('p', 1)
try:
data = await request.content.read()
data = json.loads(data)
text = data.get('text')
if not text:
raise ValueError("Missing 'text' in data")
except Exception as exc:
return web.Response(text=str(exc), status=400)

post = await objects.get_or_none(Post, id=post_id)
if post:
post.text = text
await objects.update(post)
return web.Response(text=post.text)
else:
return web.Response(text="Not found", status=404)


# Setup application routes

app.add_routes(routes)


if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)

# Initialize database
create_tables()

# Add some random posts
try:
add_post("Hello, world", "This is a first post")
add_post("Hello, world 2", "This is a second post")
add_post("42", "What is this all about?")
add_post("Let it be!", "Let it be, let it be, let it be, let it be")
except Exception as e:
print("Error adding posts: {}".format(e))

# Run application server
port = os.environ.get('HTTP_PORT', 10080)
app.run(port=port, host='0.0.0.0')
26 changes: 26 additions & 0 deletions examples/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3'

services:
db-postgres:
image: postgres
command: postgres -c log_statement=all
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=examples

aiohttp:
build:
context: ..
dockerfile: examples/Dockerfile
depends_on:
- db-postgres
ports:
- 127.0.0.1:10080:10080
volumes:
- ../examples:/app/examples
rudyryk marked this conversation as resolved.
Show resolved Hide resolved
- ../peewee_async.py:/app/peewee_async.py:ro
- ../peewee_asyncext.py:/app/peewee_asyncext.py:ro
command: gunicorn --bind 0.0.0.0:10080 --log-level INFO --access-logfile -
--worker-class aiohttp.GunicornWebWorker --reload
examples.aiohttp_example:app
12 changes: 12 additions & 0 deletions examples/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fastapi==0.111.0
uvicorn==0.29.0
tornado==6.4
aiohttp==3.9.5
uvicorn==0.29.0
rudyryk marked this conversation as resolved.
Show resolved Hide resolved
gunicorn==22.0.0

aiopg~=1.4.0
aiomysql~=0.2.0

peewee~=3.17.3
# peewee-async~=0.10.0
2 changes: 1 addition & 1 deletion peewee_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ def execute_sql(self, *args, **kwargs):
return super().execute_sql(*args, **kwargs)

async def fetch_results(self, query, cursor):
if isinstance(query, peewee.ModelCompoundSelectQuery):
if isinstance(query, peewee.BaseModelSelect):
return await AsyncQueryWrapper.make_for_all_rows(cursor, query)
if isinstance(query, peewee.RawQuery):
return await AsyncQueryWrapper.make_for_all_rows(cursor, query)
Expand Down
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ pytest-asyncio = { version = "^0.21.1", optional = true }
sphinx = { version = "^7.1.2", optional = true }
sphinx-rtd-theme = { version = "^1.3.0rc1", optional = true }



[tool.poetry.extras]
postgresql = ["aiopg"]
mysql = ["aiomysql", "cryptography"]
Expand Down
Loading