From 3ba02df115a52625cd429ffa05dd35331727fc21 Mon Sep 17 00:00:00 2001 From: jowilf Date: Sat, 15 Oct 2022 16:39:09 +0100 Subject: [PATCH 1/3] Add py.typed(PEP 561) and update dependencies --- examples/fastapi/app.py | 57 +++++++++++++++++++++---------------- examples/flask/app.py | 2 +- pyproject.toml | 10 +++---- sqlalchemy_file/__init__.py | 2 +- sqlalchemy_file/py.typed | 0 sqlalchemy_file/types.py | 2 ++ 6 files changed, 41 insertions(+), 32 deletions(-) create mode 100644 sqlalchemy_file/py.typed diff --git a/examples/fastapi/app.py b/examples/fastapi/app.py index b216601..f353a43 100644 --- a/examples/fastapi/app.py +++ b/examples/fastapi/app.py @@ -1,5 +1,5 @@ import os -from typing import List, Optional, Union +from typing import Generator, List, Optional, Union import uvicorn from fastapi import Depends, FastAPI @@ -26,8 +26,7 @@ StreamingResponse, ) -engine = create_engine("sqlite:////tmp/example.db?check_same_thread=False", echo=True) - +engine = create_engine("sqlite:///example.db?check_same_thread=False", echo=True) os.makedirs("/tmp/storage", 0o777, exist_ok=True) driver = get_driver(Provider.LOCAL)("/tmp/storage") @@ -80,7 +79,7 @@ class CategoryOut(CategoryBase): def category_form( - name: str = Form(...), + name: str = Form(..., min_length=3), image: Optional[UploadFile] = FormFile(None), ): return Category(name=name, image=image) @@ -89,37 +88,45 @@ def category_form( app = FastAPI(title="SQLAlchemy-file Example", debug=True) +def get_session() -> Generator[Session, None, None]: + session: Session = Session(engine, expire_on_commit=False) + try: + yield session + except Exception as e: + session.rollback() + raise e + finally: + session.close() + + @app.get("/categories", response_model=List[CategoryOut]) -def get_all(): - with Session(engine) as session: - return session.execute(select(Category)).all() +async def get_all(session: Session = Depends(get_session)): + return session.execute(select(Category)).scalars().all() @app.get("/categories/{id}", response_model=CategoryOut) -def get_one(id: int = Path(...)): - with Session(engine) as session: - category = session.get(Category, id) - if category is not None: - return category - return JSONResponse({"detail": "Not found"}, status_code=404) +async def get_one(id: int = Path(...), session: Session = Depends(get_session)): + category = session.get(Category, id) + if category is not None: + return category + return JSONResponse({"detail": "Not found"}, status_code=404) @app.post("/categories", response_model=CategoryOut) -def create_new(category: Category = Depends(category_form)): - with Session(engine) as session: - try: - session.add(category) - session.commit() - session.refresh(category) - return category - except ValidationError as e: - return JSONResponse( - dict(error={"key": e.key, "msg": e.msg}), status_code=422 - ) +async def create_new( + category: Category = Depends(category_form), session: Session = Depends(get_session) +): + try: + session.add(category) + session.commit() + session.refresh(category) + return category + except ValidationError as e: + return JSONResponse(dict(error={"key": e.key, "msg": e.msg}), status_code=422) @app.get("/medias/{storage}/{file_id}", response_class=FileResponse) -def serve_files(storage: str = Path(...), file_id: str = Path(...)): +async def serve_files(storage: str = Path(...), file_id: str = Path(...)): try: file = StorageManager.get_file(f"{storage}/{file_id}") if isinstance(file.object.driver, LocalStorageDriver): diff --git a/examples/flask/app.py b/examples/flask/app.py index 287171c..c14d387 100644 --- a/examples/flask/app.py +++ b/examples/flask/app.py @@ -30,7 +30,7 @@ class Book(db.Model): ImageField( upload_storage="images", thumbnail_size=(50, 50), - validators=[SizeValidator("16M")], + validators=[SizeValidator("1M")], ) ) document = db.Column( diff --git a/pyproject.toml b/pyproject.toml index 88cca8b..792d547 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "sqlalchemy-file" -version = "0.1.4" +version = "0.1.5" description = "SQLAlchemy-file is a SQLAlchemy extension for attaching files to SQLAlchemy model and uploading them to various storage." authors = ["Jocelin Hounon "] license = "MIT" @@ -29,23 +29,23 @@ classifiers = [ [tool.poetry.dependencies] python = "^3.7" SQLAlchemy = ">=1.4,<1.5.0" -apache-libcloud = "^3.6.0" +apache-libcloud = ">=3.6.0,<3.7" [tool.poetry.dev-dependencies] pytest = "^7.1.2" sqlmodel = "^0.0.8" Pillow = "^9.2.0" -fasteners = "^0.17.3" +fasteners = "^0.18" black = "^22.6.0" coverage = { extras = ["toml"], version = "^6.4.2" } flake8 = "^3.9.2" -mypy = "^0.971" +mypy = "^0.982" isort = "^5.10.1" mkdocs-material = "^8.4.3" PyMySQL = { extras = ["rsa"], version = "^1.0.2" } psycopg2-binary = "^2.9.3" mkdocstrings = { extras = ["python"], version = "^0.19.0" } -fastapi = "^0.82.0" +fastapi = "^0.85.1" uvicorn = "^0.18.2" python-multipart = "^0.0.5" Flask = "^2.2.2" diff --git a/sqlalchemy_file/__init__.py b/sqlalchemy_file/__init__.py index 7af5a1a..e8b3de7 100644 --- a/sqlalchemy_file/__init__.py +++ b/sqlalchemy_file/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.1.4" +__version__ = "0.1.5" from .file import File as File from .types import FileField as FileField diff --git a/sqlalchemy_file/py.typed b/sqlalchemy_file/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/sqlalchemy_file/types.py b/sqlalchemy_file/types.py index ecde4a4..1fa8c4c 100644 --- a/sqlalchemy_file/types.py +++ b/sqlalchemy_file/types.py @@ -103,6 +103,8 @@ class ImageField(FileField): but also validates that the uploaded object is a valid image. """ + cache_ok = True + def __init__( self, *args: Tuple[Any], From c78714e964a03bf9759339a62c2ee7f7460b6633 Mon Sep 17 00:00:00 2001 From: jowilf Date: Sat, 15 Oct 2022 17:09:04 +0100 Subject: [PATCH 2/3] Update importlib-metadata for python<=3.7 --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 792d547..de8d681 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ uvicorn = "^0.18.2" python-multipart = "^0.0.5" Flask = "^2.2.2" Flask-SQLAlchemy = "^2.5.1" +importlib-metadata = { version = "<5.0", python = "<=3.7" } [tool.coverage.report] fail_under = 95 From cd21a49bbe95d2171cef73c7da47bd804123def1 Mon Sep 17 00:00:00 2001 From: jowilf Date: Sat, 15 Oct 2022 17:26:27 +0100 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 8 ++++++++ docs/changelog.md | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69125a4..d4ba8a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.5] - 2022-10-15 + +--- + +### Added + +- Add py.typed(PEP 561) by @jowilf https://github.com/jowilf/sqlalchemy-file/pull/14 + ## [0.1.4] - 2022-08-30 --- diff --git a/docs/changelog.md b/docs/changelog.md index 4b64235..196ae68 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.5] - 2022-10-15 + +--- + +### Added + +- Add py.typed(PEP 561) in [#14](https://github.com/jowilf/sqlalchemy-file/pull/14) + ## [0.1.4] - 2022-08-30 ---