Skip to content

Commit

Permalink
Feat/update 3 (#14)
Browse files Browse the repository at this point in the history
Update logic and tests
  • Loading branch information
kaziamov authored Jan 27, 2024
1 parent 231ea8d commit 3191b0b
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 117 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ name: Compatibility Check
on:
push:
branches:
- 'dev'
- 'staging'

jobs:
compatibility:
runs-on: ubuntu-20.04

strategy:
matrix:
python-version: [3.6, "3.10"]
python-version: [ 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12" ]

steps:
- name: Checkout code
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Coverage

on:
push:
branches: [ "main" ]
branches: [ "dev" ]

jobs:
build:
Expand All @@ -11,8 +11,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- run: pip install poetry
- run: make install
- run: |
pip install poetry
poetry install
- name: Test & publish code coverage
uses: paambaati/[email protected]
env:
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: lint-test

on:
push:
branches: [ "dev" ]

jobs:
build:

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- run: |
pip install poetry
poetry install
poetry run flake8
2 changes: 1 addition & 1 deletion .github/workflows/pypi-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
- uses: actions/setup-python@v2
- run: pip install poetry
- run: poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}
- run: poetry publish --build
- run: poetry publish --build
Empty file removed .github/workflows/tests.yml
Empty file.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ readme = "README.md"

[tool.poetry.dependencies]
python = "^3.9"
sqlalchemy = "^2.0.0"

[tool.poetry.group.dev.dependencies]
flake8 = "^7.0.0"

[tool.poetry.group.test.dependencies]
pytest = "^7.4.3"
sqlalchemy = "^2.0.25"
aiosqlite = "^0.19.0"

[build-system]
Expand Down
137 changes: 97 additions & 40 deletions simplecrud/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,116 +2,173 @@
from typing import Dict

# from cachetools import LFUCache
from sqlalchemy import select
from sqlalchemy import select, delete

from .settings import session
from .utils import inject_connection

logger = logging.getLogger(__name__)


async def create_obj(model, **params):
"""Create object in db"""
logger.debug(f"{__name__}.create_obj: model = {model}, params = {params}")
new_obj = model(**params)
async with session() as conn:
conn.add(new_obj)
await conn.commit()
await conn.refresh(new_obj)
return new_obj

async def get_object(model, **filters):
# READ / GET
@inject_connection
async def get_object(model, filters, conn=None):
"""Get object from db"""
key = f"{model.__name__}{filters}"
query = select(model).filter_by(**filters)
logger.debug(f"{__name__}.get_obj: query = {query}")
async with session() as conn:
async with conn:
result = await conn.execute(query)
logger.debug(f"{__name__}.get_obj: result = {result}")
obj = result.scalars().first()
logger.debug(f"{__name__}.get_obj: obj = {obj}")
return obj


async def get_all(model):
@inject_connection
async def get_all(model, conn=None):
"""Get objects from db"""
query = select(model)
async with session() as conn:
async with conn:
result = await conn.execute(query)
logger.debug(f"{__name__}.get_all: result = {result}")
objects = result.scalars().all()
logger.debug(f"{__name__}.get_all: obj = {objects}")
return objects


async def get_all_with_filter(model, filters: dict):
@inject_connection
async def get_all_with_filter(model, filters: dict, conn=None):
"""Get objects from db"""
query = select(model).filter_by(**filters)
async with session() as conn:
async with conn:
result = await conn.execute(query)
logger.debug(f"{__name__}.get_all: result = {result}")
objects = result.scalars().all()
logger.debug(f"{__name__}.get_all: obj = {objects}")
return objects


async def get_objects(model, filters: Dict, limit=10, per_page=10):
@inject_connection
async def get_objects(model, filters: Dict, limit=10, per_page=10, conn=None):
"""Get objects from db"""
query = select(model).filter_by(**filters).limit(limit).offset(per_page)
logger.debug(f"{__name__}.get_objects: query = {query}")
async with session() as conn:
async with conn:
result = await conn.execute(query)
logger.debug(f"{__name__}.get_objects: result = {result}")
objects = result.scalars().all()
logger.debug(f"{__name__}.get_objects: obj = {objects}")
return objects


async def get_or_create_object(model, **params):
async def get_or_create_object(model, params, conn=None):
"""Get object from db or create new one"""
key = f"{model.__name__}{params}"
obj = await get_object(model, **params)
obj = await get_object(model, params, conn=conn)
if not obj:
obj = await create_object(model, **params)
obj = await create_object(model, params, conn=conn)
return obj


async def create_object(model, **params):
# CREATE
@inject_connection
async def create_object(model, params, conn=None):
"""Create object in db"""
logger.debug(f"{__name__}.create_obj: model = {model}, params = {params}")
new_obj = model(**params)
async with session() as conn:
async with conn:
conn.add(new_obj)
await conn.commit()
await conn.refresh(new_obj)
return new_obj


def create_objects():
pass
@inject_connection
async def bulk_create(objects, conn=None):
for obj in objects:
await create_object(obj, conn=conn)


async def update_object(model, id: int, **params):
async with session() as conn:
obj = await get_object(model, id=id)
for key, value in params.items():
# UPDATE
@inject_connection
async def update_object(obj, params, conn=None):
"""
Soft Update object in db.
If attribute not exists in model`s fields, then skip field without error
"""
avaliable_fields = obj.__class__.__table__.columns.keys()
for key, value in params.items():
if key in avaliable_fields:
setattr(obj, key, value)
conn.add(obj)
async with conn:
await conn.commit()
await conn.refresh(obj)
conn.refresh(obj)
return obj


def update_objects():
pass
@inject_connection
async def update_or_error(obj, params, conn=None):
"""
Soft Update object in db.
If attribute not exists in model`s fields, then skip field without error
"""
avaliable_fields = obj.__class__.__table__.columns.keys()
for key, value in params.items():
if key in avaliable_fields:
setattr(obj, key, value)
else:
raise AttributeError(f"Attribute {key} not exists in {obj.__class__.__name__}")
async with conn:
await conn.commit()
conn.refresh(obj)
return obj


def update_or_create_object():
pass
@inject_connection
async def update_object_by_id(model, id: int, params, conn=None):
obj = await get_object(model, id=id)
updated_obj = await update_object(obj, params, conn=conn)
return updated_obj


async def delete_object(model, id: int):
def bulk_update():
pass


def delete_objects():
pass
@inject_connection
async def update_or_create_object(model, filters, params, conn=None):
obj = await get_or_create_object(model, filters, conn=conn)
return await update_object(obj, params, conn=conn)


# DELETE
@inject_connection
async def delete_object(obj, conn=None):
model = obj.__class__
id_ = obj.id
return await delete_object_by_id(model, id_, conn=conn)


@inject_connection
async def delete_object_by_id(model, id_: int, conn=None):
query = delete(model).where(model.id == id_)
async with conn:
await conn.execute(query)
await conn.commit()
logger.debug(f"{__name__}.delete_object_by_id: model = {model}, id = {id_}")
return True


@inject_connection
async def bulk_delete(objects, conn=None):
for obj in objects:
await delete_object(obj, conn=conn)
return True


@inject_connection
async def bulk_delete_by_id(model, ids, conn=None):
for id_ in ids:
await delete_object_by_id(model, id_, conn=conn)
return True

Loading

0 comments on commit 3191b0b

Please sign in to comment.