Skip to content

Commit

Permalink
Merge pull request #19 from samudradev/refactor-api
Browse files Browse the repository at this point in the history
♻️ REFACTOR: API Cleanup
  • Loading branch information
Thaza-Kun authored Sep 27, 2022
2 parents 76b8d5c + 2eee481 commit 1a52562
Show file tree
Hide file tree
Showing 17 changed files with 396 additions and 212 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ jobs:
poetry install
- name: Test with pytest
run: |
poetry run pytest --verbose
poetry run pytest
30 changes: 16 additions & 14 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ repos:
rev: v2.5.0
hooks:
- id: check-added-large-files
- repo: local
hooks:
# - id: pylint
# name: pylint
# entry: poetry run pylint samudra/
# language: system
# always_run: true
# pass_filenames: false
- id: create requirements
name: create requirements
entry: poetry export -o requirements.txt --extras mysql --without-hashes
language: system
always_run: true
pass_filenames: false
# - repo: local
# hooks:
# - id: pylint
# name: pylint
# entry: poetry run pylint samudra/
# language: system
# always_run: true
# pass_filenames: false
# - repo: https://github.com/python-poetry/poetry
# rev: 1.2.0
# hooks:
# - id: poetry-check
# - id: poetry-lock
# - id: poetry-export
# name: create requirements with mysql
# args: [ "-o", "requirements.txt", "--extras", "mysql", "--without-hashes" ]
260 changes: 150 additions & 110 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "samudra"
version = "0.6.0"
version = "0.7.0"
description = ""
authors = ["Thaza_Kun <[email protected]>"]

Expand Down
37 changes: 37 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
anyio==3.6.1 ; python_version >= "3.8" and python_version < "4.0"
bcrypt==3.2.2 ; python_version >= "3.8" and python_version < "4.0"
certifi==2022.9.24 ; python_version >= "3.8" and python_version < "4"
cffi==1.15.1 ; python_version >= "3.8" and python_version < "4.0"
charset-normalizer==2.1.1 ; python_version >= "3.8" and python_version < "4"
click==8.1.3 ; python_version >= "3.8" and python_version < "4.0"
colorama==0.4.5 ; python_version >= "3.8" and python_version < "4.0" and platform_system == "Windows"
cryptography==37.0.4 ; python_version >= "3.8" and python_version < "4.0"
ecdsa==0.18.0 ; python_version >= "3.8" and python_version < "4.0"
et-xmlfile==1.1.0 ; python_version >= "3.8" and python_version < "4.0"
fastapi==0.79.1 ; python_version >= "3.8" and python_version < "4.0"
h11==0.14.0 ; python_version >= "3.8" and python_version < "4.0"
idna==3.4 ; python_version >= "3.8" and python_version < "4"
numpy==1.23.3 ; python_version >= "3.8" and python_version < "4.0"
openpyxl==3.0.10 ; python_version >= "3.8" and python_version < "4.0"
pandas==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
passlib==1.7.4 ; python_version >= "3.8" and python_version < "4.0"
peewee==3.15.3 ; python_version >= "3.8" and python_version < "4.0"
pyasn1==0.4.8 ; python_version >= "3.8" and python_version < "4.0"
pycparser==2.21 ; python_version >= "3.8" and python_version < "4.0"
pycryptodome==3.15.0 ; python_version >= "3.8" and python_version < "4.0"
pydantic==1.10.2 ; python_version >= "3.8" and python_version < "4.0"
pymysql==1.0.2 ; python_version >= "3.8" and python_version < "4.0"
python-dateutil==2.8.2 ; python_version >= "3.8" and python_version < "4.0"
python-dotenv==0.20.0 ; python_version >= "3.8" and python_version < "4.0"
python-jose==3.3.0 ; python_version >= "3.8" and python_version < "4.0"
python-multipart==0.0.5 ; python_version >= "3.8" and python_version < "4.0"
pytomlpp==1.0.11 ; python_version >= "3.8" and python_version < "4.0"
pytz==2022.2.1 ; python_version >= "3.8" and python_version < "4.0"
requests==2.28.1 ; python_version >= "3.8" and python_version < "4"
rsa==4.9 ; python_version >= "3.8" and python_version < "4"
six==1.16.0 ; python_version >= "3.8" and python_version < "4.0"
sniffio==1.3.0 ; python_version >= "3.8" and python_version < "4.0"
starlette==0.19.1 ; python_version >= "3.8" and python_version < "4.0"
typing-extensions==4.3.0 ; python_version >= "3.8" and python_version < "4.0"
urllib3==1.26.12 ; python_version >= "3.8" and python_version < "4"
uvicorn==0.18.3 ; python_version >= "3.8" and python_version < "4.0"
35 changes: 25 additions & 10 deletions samudra/core/crud/lemma.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from peewee import prefetch

from samudra import models
from schemas.input.query_filter import QueryFilter


def create_lemma(lemma: str, safe: bool = True) -> models.Lemma:
Expand All @@ -12,30 +13,44 @@ def create_lemma(lemma: str, safe: bool = True) -> models.Lemma:


def get_lemma_minimum_info(
where: Any, limit: Optional[int] = None
query: Optional[QueryFilter] = None, where: Any = None
) -> List[models.Lemma]:
stmt = models.Lemma.select(models.Lemma).where(where).limit(limit)
query: QueryFilter = QueryFilter(**query.dict())
stmt = models.Lemma.select().where(where)

to_return = prefetch(
stmt,
models.Konsep,
models.CakupanXKonsep,
models.Cakupan,
models.Cakupan.select().where(
(
models.Cakupan.nama.in_(query.cakupan)
if query.cakupan is not None
else None
)
),
models.KataAsingXKonsep,
models.KataAsing,
models.KataAsing.select().where(
(
models.KataAsing.nama.in_(query.kata_asing)
if query.kata_asing is not None
else None
)
),
)
return to_return


def get_lemma(limit: int = 10) -> List[models.Lemma]:
return get_lemma_minimum_info(where=None, limit=limit)
def get_lemma(query: QueryFilter) -> List[models.Lemma]:
return get_lemma_minimum_info(query=query)


def get_lemma_by_name(nama: str, limit: int = 1) -> List[models.Lemma]:
return get_lemma_minimum_info(where=models.Lemma.nama == nama, limit=limit)
def get_lemma_by_name(nama: str, query: QueryFilter) -> List[models.Lemma]:
return get_lemma_minimum_info(where=models.Lemma.nama == nama, query=query)


def get_lemma_by_id(lemma_id: int, limit: Optional[int] = None) -> List[models.Lemma]:
return get_lemma_minimum_info(where=(models.Lemma.id == lemma_id), limit=limit)
def get_lemma_by_id(lemma_id: int, query: QueryFilter) -> List[models.Lemma]:
return get_lemma_minimum_info(where=(models.Lemma.id == lemma_id), query=query)


def delete_lemma(lemma: models.Lemma) -> int:
Expand Down
9 changes: 9 additions & 0 deletions samudra/schemas/input/query_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from typing import List, Optional

import pydantic as pyd


class QueryFilter(pyd.BaseModel):
limit: Optional[int]
cakupan: Optional[List[str]]
kata_asing: Optional[List[str]]
5 changes: 3 additions & 2 deletions samudra/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@

from samudra.conf.server.cors_policy import ALLOWED_ORIGINS
from samudra.server.setup import check_tables
from samudra.server import lemmas, authentication
from samudra.server import lemmas, auth, golongan_kata

SLEEP_TIME: int = 10

app = FastAPI()

# TODO: Add more server endpoints!
app.include_router(lemmas.router)
app.include_router(authentication.router)
app.include_router(auth.router)
app.include_router(golongan_kata.router)

app.add_middleware(
CORSMiddleware,
Expand Down
2 changes: 1 addition & 1 deletion samudra/server/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .routes import lemmas, authentication
from .routes import lemmas, auth, golongan_kata
Original file line number Diff line number Diff line change
@@ -1,38 +1,19 @@
from typing import Optional
import os
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from jose import jwt

from samudra import models, schemas
from samudra.core import auth
from samudra.server.dependencies import get_db
from datetime import datetime, timedelta
from datetime import timedelta

from pydantic import BaseModel
from server.tokens import (
ACCESS_TOKEN_EXPIRE_MINUTES,
PenggunaCreateDTO,
create_access_token,
)

SECRET_KEY = os.getenv("SECRET_KEY")
ALGORITHM = os.getenv("ALGORITHM")
ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES"))


class PenggunaCreateDTO(BaseModel):
nama: str
katalaluan: str


def create_access_token(data: dict, expires_delta: Optional[timedelta]):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY)
return encoded_jwt


router = APIRouter(prefix="/authentication", dependencies=[Depends(get_db)])
# TODO Set peranan
router = APIRouter(prefix="/auth", dependencies=[Depends(get_db)])


@router.post("/daftar", response_model=schemas.DaftarResponse)
Expand Down
8 changes: 5 additions & 3 deletions samudra/server/routes/golongan_kata.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
from core import crud
from server.dependencies import get_db, oauth2_scheme

router = APIRouter(prefix="/golongan_kata", dependencies=[Depends(get_db)])
router = APIRouter(prefix="/golongan", dependencies=[Depends(get_db)])


@router.post('/new')
def create_golongan_kata(post: schemas.CreateGolonganKata, token: str = Depends(oauth2_scheme)):
@router.post("/new")
def create_golongan_kata(
post: schemas.CreateGolonganKata, token: str = Depends(oauth2_scheme)
):
try:
return crud.create_golongan_kata(data=post)
except ValueError as e:
Expand Down
29 changes: 22 additions & 7 deletions samudra/server/routes/lemmas.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,47 @@
from typing import List, Union, Dict
from typing import List, Union, Dict, Optional

import pydantic
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException, Query

from samudra import models, schemas
from samudra.core import crud
from samudra.server.dependencies import get_db
from schemas.input.query_filter import QueryFilter
from server.dependencies import oauth2_scheme

router = APIRouter(prefix="/lemma", dependencies=[Depends(get_db)])


@router.get("/", response_model=List[schemas.LemmaResponse])
def get_all_lemma(limit: int = None) -> List[models.Lemma]:
return crud.get_lemma(limit=limit)
def get_all_lemma(
limit: Optional[int] = Query(default=None),
cakupan: Optional[List[str]] = Query(default=None),
kata_asing: Optional[List[str]] = Query(default=None),
) -> List[models.Lemma]:
return crud.get_lemma(
QueryFilter(limit=limit, cakupan=cakupan, kata_asing=kata_asing)
)


@router.get("/{nama}", response_model=List[schemas.LemmaResponse])
def read_lemma(nama: str) -> List[models.Lemma]:
db_lemma = crud.get_lemma_by_name(nama=nama)
def read_lemma(
nama: str,
limit: Optional[int] = Query(default=None),
cakupan: Optional[List[str]] = Query(default=None),
kata_asing: Optional[List[str]] = Query(default=None),
) -> List[models.Lemma]:
db_lemma = crud.get_lemma_by_name(
nama=nama,
query=QueryFilter(limit=limit, cakupan=cakupan, kata_asing=kata_asing),
)
if db_lemma is None:
raise HTTPException(status_code=404, detail="Lemma not in record")
return db_lemma


@router.post("/{nama}", response_model=schemas.KonsepResponseFromAnnotatedBody)
def create_lemma(
nama: str, post: schemas.AnnotatedText, token: str = Depends(oauth2_scheme)
nama: str, post: schemas.AnnotatedText, token: str = Depends(oauth2_scheme)
) -> Union[models.Konsep, schemas.AnnotatedText]:
try:
to_return = crud.create_konsep(post, lemma_name=nama)
Expand Down
3 changes: 3 additions & 0 deletions samudra/server/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from samudra.conf import Database


# TODO Refactor Database.connection to decouple dependency on conf


def check_tables(create_tables: bool = False) -> None:
for TABLE in models.TABLES:
if Database.connection.table_exists(TABLE):
Expand Down
26 changes: 26 additions & 0 deletions samudra/server/tokens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os
from datetime import timedelta, datetime
from typing import Optional

from jose import jwt
from pydantic import BaseModel

SECRET_KEY = os.getenv("SECRET_KEY")
ALGORITHM = os.getenv("ALGORITHM")
ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES"))


class PenggunaCreateDTO(BaseModel):
nama: str
katalaluan: str


def create_access_token(data: dict, expires_delta: Optional[timedelta]):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY)
return encoded_jwt
4 changes: 3 additions & 1 deletion tests/mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import peewee as pw

from conf import Database
from samudra import schemas
from samudra.models import TABLES, JOIN_TABLES

mock_db = pw.SqliteDatabase(':memory:')
Database.engine = pw.SqliteDatabase(":memory:")

models = [*TABLES]
relational_models = [*JOIN_TABLES]
mock_db = Database.engine


def bind_test_database(function: callable, *args, **kwargs) -> callable:
Expand Down
Loading

0 comments on commit 1a52562

Please sign in to comment.