Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
max-parallel: 3
matrix:
python-version: [3.6, 3.7, 3.8]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v1
Expand Down Expand Up @@ -42,7 +42,7 @@ jobs:
key: pytest-${{ matrix.python-version }}
- name: Check docs build
# only run this for the python version used by netlify:
if: matrix.python-version == 3.7
if: matrix.python-version == '3.8'
run: |
make docs-build-ci
- name: Check that formatting, linting, and tests pass
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
max-parallel: 1
matrix:
python-version: [3.7]
python-version: ['3.8']

steps:
- uses: actions/checkout@v1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
max-parallel: 3
matrix:
python-version: [3.6, 3.7, 3.8]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v1
Expand Down Expand Up @@ -40,7 +40,7 @@ jobs:
key: pytest-${{ matrix.python-version }}
- name: Check docs build
# only run this for the python version used by netlify:
if: matrix.python-version == 3.7
if: matrix.python-version == '3.8'
run: |
make docs-build-ci
- name: Check that formatting, linting, and tests pass
Expand Down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
*.hdf5
.idea/

env/
venv/
.venv/
env3*/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down Expand Up @@ -86,4 +91,4 @@ venv.bak/

site

.bento/
.tool-versions
27 changes: 9 additions & 18 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ tests_src = tests
docs_src = docs/src
all_src = $(pkg_src) $(tests_src)

isort = isort -rc $(all_src)
autoflake = autoflake -r --remove-all-unused-imports --ignore-init-module-imports $(all_src)
black = black $(all_src)
flake8 = flake8 $(all_src)
mypy_base = mypy --show-error-codes
mypy = $(mypy_base) $(all_src)
test = pytest --cov=fastapi_utils
Expand All @@ -26,13 +22,15 @@ test:

.PHONY: format ## Auto-format the source code (isort, autoflake, black)
format:
$(isort)
$(autoflake) -i
$(black)
black $(all_src)
black -l 82 $(docs_src)
ruff --fix $(all_src)

.PHONY: lint ## Run flake8 over the application source and tests
.PHONY: lint
lint:
$(flake8)
ruff $(all_src)
black --check --diff $(all_src)
black -l 82 $(docs_src) --check --diff

.PHONY: mypy ## Run mypy over the application source and tests
mypy:
Expand All @@ -49,15 +47,7 @@ testcov:
fi

.PHONY: ci ## Run all CI validation steps without making any changes to code
ci: check-format lint mypy test

.PHONY: check-format ## Check the source code format without changes
check-format:
$(isort) $(docs_src) --check-only
@echo $(autoflake) $(docs_src) --check
@( set -o pipefail; $(autoflake) $(docs_src) --check | (grep -v "No issues detected!" || true) )
$(black) --check
black -l 82 $(docs_src) --check
ci: lint mypy test

.PHONY: clean ## Remove temporary and cache files/directories
clean:
Expand All @@ -72,6 +62,7 @@ clean:
rm -rf `find . -type d -name .pytest_cache`
rm -rf `find . -type d -name .cache`
rm -rf `find . -type d -name .mypy_cache`
rm -rf `find . -type d -name .ruff_cache`
rm -rf `find . -type d -name htmlcov`
rm -rf `find . -type d -name "*.egg-info"`
rm -rf `find . -type d -name build`
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

---

<a href="https://fastapi.tiangolo.com">FastAPI</a> is a modern, fast web framework for building APIs with Python 3.6+.
<a href="https://fastapi.tiangolo.com">FastAPI</a> is a modern, fast web framework for building APIs with Python 3.7+.

But if you're here, you probably already knew that!

Expand Down Expand Up @@ -59,7 +59,7 @@ See the [docs](https://fastapi-utils.davidmontague.xyz/) for more details and ex

## Requirements

This package is intended for use with any recent version of FastAPI (depending on `pydantic>=1.0`), and Python 3.6+.
This package is intended for use with any recent version of FastAPI (depending on `pydantic>=1.0`), and Python 3.7+.

## Installation

Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

---

<a href="https://fastapi.tiangolo.com">FastAPI</a> is a modern, fast web framework for building APIs with Python 3.6+.
<a href="https://fastapi.tiangolo.com">FastAPI</a> is a modern, fast web framework for building APIs with Python 3.7+.

But if you're here, you probably already knew that!

Expand Down Expand Up @@ -59,7 +59,7 @@ See the [docs](https://fastapi-utils.davidmontague.xyz/) for more details and ex

## Requirements

This package is intended for use with any recent version of FastAPI (depending on `pydantic>=1.0`), and Python 3.6+.
This package is intended for use with any recent version of FastAPI (depending on `pydantic>=1.0`), and Python 3.7+.

## Installation

Expand Down
8 changes: 8 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## Latest changes

## 0.3.0

* Move to ruff for linting, etc.
* Update various dependencies
* Stop supporting Python 3.6
* Deprecate InferringRouter (as its functionality is now built into `fastapi.APIRouter`)
* Resolve various deprecationwarnings introduced by sqlalchemy 1.4.

## 0.2.1

* Fix bug with multiple decorators on same method
Expand Down
2 changes: 1 addition & 1 deletion docs/src/camelcase2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy.orm import declarative_base, declared_attr

from fastapi_utils.camelcase import camel2snake

Expand Down
8 changes: 4 additions & 4 deletions docs/src/class_based_views1.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import sqlalchemy as sa
from fastapi import Depends, FastAPI, Header, HTTPException
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import Session
from starlette.status import HTTP_403_FORBIDDEN, HTTP_404_NOT_FOUND

Expand Down Expand Up @@ -35,15 +35,15 @@ class ItemInDB(ItemCreate):


def get_jwt_user(authorization: str = Header(...)) -> UserID:
""" Pretend this function gets a UserID from a JWT in the auth header """
"""Pretend this function gets a UserID from a JWT in the auth header"""


def get_db() -> Session:
""" Pretend this function returns a SQLAlchemy ORM session"""
"""Pretend this function returns a SQLAlchemy ORM session"""


def get_owned_item(session: Session, owner: UserID, item_id: ItemID) -> ItemORM:
item: Optional[ItemORM] = session.query(ItemORM).get(item_id)
item: Optional[ItemORM] = session.get(ItemORM, item_id)
if item is not None and item.owner != owner:
raise HTTPException(status_code=HTTP_403_FORBIDDEN)
if item is None:
Expand Down
9 changes: 4 additions & 5 deletions docs/src/class_based_views2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

import sqlalchemy as sa
from fastapi import Depends, FastAPI, Header, HTTPException
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm import Session, declarative_base
from starlette.status import HTTP_403_FORBIDDEN, HTTP_404_NOT_FOUND

from fastapi_utils.api_model import APIMessage, APIModel
Expand Down Expand Up @@ -37,15 +36,15 @@ class ItemInDB(ItemCreate):


def get_jwt_user(authorization: str = Header(...)) -> UserID:
""" Pretend this function gets a UserID from a JWT in the auth header """
"""Pretend this function gets a UserID from a JWT in the auth header"""


def get_db() -> Session:
""" Pretend this function returns a SQLAlchemy ORM session"""
"""Pretend this function returns a SQLAlchemy ORM session"""


def get_owned_item(session: Session, owner: UserID, item_id: ItemID) -> ItemORM:
item: Optional[ItemORM] = session.query(ItemORM).get(item_id)
item: Optional[ItemORM] = session.get(ItemORM, item_id)
if item is not None and item.owner != owner:
raise HTTPException(status_code=HTTP_403_FORBIDDEN)
if item is None:
Expand Down
2 changes: 1 addition & 1 deletion docs/src/guid1.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import declarative_base

from fastapi_utils.guid_type import GUID

Expand Down
2 changes: 1 addition & 1 deletion docs/src/repeated_tasks1.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


def remove_expired_tokens(db: Session) -> None:
""" Pretend this function deletes expired tokens from the database """
"""Pretend this function deletes expired tokens from the database"""


@app.on_event("startup")
Expand Down
11 changes: 5 additions & 6 deletions docs/src/session1.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import sqlalchemy as sa
from fastapi import Depends, FastAPI
from pydantic import BaseSettings
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm import Session, declarative_base

from fastapi_utils.guid_type import GUID, GUID_DEFAULT_SQLITE
from fastapi_utils.session import FastAPISessionMaker
Expand All @@ -21,19 +20,19 @@ class User(Base):


class DBSettings(BaseSettings):
""" Parses variables from environment on instantiation """
"""Parses variables from environment on instantiation"""

database_uri: str # could break up into scheme, username, password, host, db


def get_db() -> Iterator[Session]:
""" FastAPI dependency that provides a sqlalchemy session """
"""FastAPI dependency that provides a sqlalchemy session"""
yield from _get_fastapi_sessionmaker().get_db()


@lru_cache()
def _get_fastapi_sessionmaker() -> FastAPISessionMaker:
""" This function could be replaced with a global variable if preferred """
"""This function could be replaced with a global variable if preferred"""
database_uri = DBSettings().database_uri
return FastAPISessionMaker(database_uri)

Expand All @@ -43,6 +42,6 @@ def _get_fastapi_sessionmaker() -> FastAPISessionMaker:

@app.get("/{user_id}")
def get_user_name(db: Session = Depends(get_db), *, user_id: UUID) -> str:
user = db.query(User).get(user_id)
user = db.get(User, user_id)
username = user.name
return username
4 changes: 2 additions & 2 deletions docs/user-guide/basics/guid-type.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ you can use `fastapi_utils.guid_type.GUID_SERVER_DEFAULT_POSTGRESQL`:

```python
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import declarative_base

from fastapi_utils.guid_type import GUID, GUID_SERVER_DEFAULT_POSTGRESQL

Expand Down Expand Up @@ -89,7 +89,7 @@ create new records):

```python
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import declarative_base

from fastapi_utils.guid_type import GUID, GUID_DEFAULT_SQLITE

Expand Down
2 changes: 1 addition & 1 deletion fastapi_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.1"
__version__ = "0.3.0"
2 changes: 2 additions & 0 deletions fastapi_utils/api_model.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from functools import partial

from pydantic import BaseConfig, BaseModel
Expand Down
8 changes: 5 additions & 3 deletions fastapi_utils/api_settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from functools import lru_cache
from typing import Any, Dict
from typing import Any

from pydantic import BaseSettings

Expand Down Expand Up @@ -31,14 +33,14 @@ class APISettings(BaseSettings):
disable_docs: bool = False

@property
def fastapi_kwargs(self) -> Dict[str, Any]:
def fastapi_kwargs(self) -> dict[str, Any]:
"""
This returns a dictionary of the most commonly used keyword arguments when initializing a FastAPI instance

If `self.disable_docs` is True, the various docs-related arguments are disabled, preventing your spec from being
published.
"""
fastapi_kwargs: Dict[str, Any] = {
fastapi_kwargs: dict[str, Any] = {
"debug": self.debug,
"docs_url": self.docs_url,
"openapi_prefix": self.openapi_prefix,
Expand Down
2 changes: 2 additions & 0 deletions fastapi_utils/camelcase.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import re


Expand Down
Loading