Skip to content

Commit 58db12d

Browse files
committed
sqlalchemy integration
1 parent 734c246 commit 58db12d

File tree

23 files changed

+620
-21
lines changed

23 files changed

+620
-21
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
__pycache__
22
.vscode
3-
src-gen/
3+
src-gen/
4+
.coverage
5+
.env
6+
htmlcov/

docker-compose.dev.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
version: "3.8"
2+
services:
3+
db:
4+
image: postgres:12.3
5+
environment:
6+
POSTGRES_PASSWORD: password
7+
volumes:
8+
- ./tmp/db/data:/var/lib/postgresql/data
9+
ports:
10+
- "5432:5432"
11+
networks:
12+
- internal-network
13+
- external-network
14+
test_db:
15+
image: postgres:12.3
16+
environment:
17+
POSTGRES_PASSWORD: password
18+
volumes:
19+
- ./tmp/test_db/data:/var/lib/postgresql/data
20+
ports:
21+
- "5433:5432"
22+
networks:
23+
- internal-network
24+
- external-network
25+
26+
networks:
27+
internal-network:
28+
internal: true
29+
external-network:
30+

poetry.lock

Lines changed: 230 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,20 @@ black = "^21.5b1"
1212
fastapi = "^0.67.0"
1313
uvicorn = "^0.14.0"
1414
starlette-context = "^0.3.3"
15+
SQLAlchemy = "^1.4.22"
16+
psycopg2 = "^2.9.1"
1517

1618
[tool.poetry.dev-dependencies]
1719
poethepoet = "^0.10.0"
20+
pytest-cov = "^2.12.1"
1821

1922
[build-system]
2023
requires = ["poetry-core>=1.0.0"]
2124
build-backend = "poetry.core.masonry.api"
2225

2326

2427
[tool.poe.tasks]
25-
test = "pytest src"
28+
test = { shell = "DATABASE_URL=postgresql://postgres:password@localhost:5433/postgres pytest src" }
29+
test_coverage = "pytest --cov=src --cov-report=html"
2630
start = "uvicorn src.api.main:app --reload"
31+
compose_up = "docker-compose -f docker-compose.dev.yml up"

src/api/config.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1+
from typing import cast
2+
import os
13
from starlette.config import Config
24
from starlette.datastructures import CommaSeparatedStrings, Secret
35

4-
config = Config(".env")
6+
7+
env_filename = os.getenv("ENV_FILENAME", ".env")
8+
9+
config = Config(env_filename)
510

611
DEBUG = config("DEBUG", cast=bool, default=False)
12+
APP_NAME = "Online Auctions API"
13+
DATABASE_URL = config(
14+
"DATABASE_URL", default="postgresql://postgres:password@localhost:5432/postgres"
15+
)
16+
717
# SECRET_KEY = config("SECRET_KEY", cast=Secret, default="secret")
818
# ALLOWED_HOSTS = config("ALLOWED_HOSTS", cast=CommaSeparatedStrings, default="*")

src/api/dependencies.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
from fastapi import Header, HTTPException
22
from pydantic import BaseModel
3-
from seedwork.domain.value_objects import UUID
4-
53
from dataclasses import dataclass
4+
from seedwork.domain.value_objects import UUID
65

76

87
class CurrentUser(BaseModel):

src/api/infrastructure/database.py

Whitespace-only changes.

src/api/main.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from fastapi import FastAPI
22
from starlette.middleware import Middleware
3-
from starlette_context import plugins
3+
from starlette_context import context, plugins
44
from starlette_context.middleware import ContextMiddleware
5+
from sqlalchemy import create_engine
56

67
from seedwork.domain.value_objects import UUID
78
from seedwork.infrastructure.repository import InMemoryRepository
@@ -12,20 +13,63 @@
1213
import api.config as config
1314
from api.routers import catalog, users
1415

16+
# database engine
17+
engine = create_engine(config.DATABASE_URL, echo=config.DEBUG)
18+
19+
1520
middleware = [
1621
Middleware(
1722
ContextMiddleware,
1823
plugins=(plugins.RequestIdPlugin(), plugins.CorrelationIdPlugin()),
1924
)
2025
]
2126

22-
app = FastAPI(debug=config.DEBUG)
27+
app = FastAPI(debug=config.DEBUG, middleware=middleware)
2328

2429
app.include_router(catalog.router)
2530
app.include_router(users.router)
31+
app.engine = engine
2632

2733

2834
@app.get("/")
2935
async def root():
30-
# print(request)
3136
return {"info": "Online auctions API. See /docs for documentation"}
37+
38+
39+
@app.get("/test")
40+
async def test():
41+
print((context.get("X-Request-ID")))
42+
return {"test": "test"}
43+
44+
45+
# ####
46+
# from fastapi import Depends
47+
48+
49+
# def common_parameters(x: str, y: int):
50+
# print(args, kwargs)
51+
# return None
52+
53+
54+
# def common_parameters2(z: int = 10):
55+
# print(args, kwargs)
56+
# return None
57+
58+
59+
# def get_context():
60+
# context = object()
61+
# context.correlation_id = "1234"
62+
# return context
63+
64+
65+
# @app.get("/dependency")
66+
# async def root(
67+
# # foo=Depends(common_parameters),
68+
# # bar=Depends(common_parameters2),
69+
# context=Depends(get_context),
70+
# ):
71+
# # print(request)
72+
# return {
73+
# "info": "Online auctions API. See /docs for documentation "
74+
# + context.correlation_id
75+
# }

src/api/modules.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from modules.catalog.module import CatalogModule
2+
3+
4+
catalog_module = CatalogModule()

src/api/routers/catalog.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1-
from fastapi import APIRouter
1+
from fastapi import APIRouter, Depends
22
from seedwork.domain.value_objects import UUID
33

4+
from modules.catalog.module import CatalogModule
5+
from modules.catalog.application.commands import CreateListingDraftCommand
6+
from modules.catalog.application.queries import GetAllListingsQuery
7+
8+
from ..dependencies import request_context, RequestContext
9+
from ..modules import catalog_module as module
10+
11+
412
router = APIRouter()
513

614

715
@router.get("/catalog", tags=["catalog"])
816
async def get_all_listings():
17+
result = module.execute_query(GetAllListingsQuery())
918
"""
1019
Shows all published listings in the catalog
1120
"""
12-
return {"message": "catalog here"}
21+
return {"data": result}
1322

1423

1524
@router.get("/catalog/{listing_id}", tags=["catalog"])
@@ -20,8 +29,19 @@ async def get_listing_details(listing_id: UUID):
2029
return {"message": "catalog here"}
2130

2231

23-
@router.post("/catalog", tags=["catalog"])
24-
async def create_listing():
32+
@router.post("/catalog", tags=["catalog"], status_code=201)
33+
async def create_listing(request_context: RequestContext = Depends(request_context)):
2534
"""
2635
Creates a new listing.
2736
"""
37+
result = module.execute_command(
38+
CreateListingDraftCommand(
39+
title="title",
40+
description="",
41+
price=1,
42+
seller_id=request_context.current_user.id,
43+
)
44+
)
45+
# TODO: for now we return just the id, but in the future we should return
46+
# a representation of a newly created listing resource
47+
return {"id": result.id}

0 commit comments

Comments
 (0)