Compare commits

..

6 Commits

Author SHA1 Message Date
github-actions[bot] 8e4fd7c722 📝 Update release notes
[skip ci]
2026-06-25 16:26:19 +00:00
Sebastián Ramírez 54de75638b ➕ Move prek to top level dependencies (#2353) 2026-06-25 16:26:00 +00:00
github-actions[bot] 49a94eaab4 📝 Update release notes
[skip ci]
2026-06-25 16:19:39 +00:00
Sebastián Ramírez 14728b636c ⬆️ Upgrade Python to 3.14 (#2352) 2026-06-25 16:19:18 +00:00
github-actions[bot] a727535488 📝 Update release notes
[skip ci]
2026-06-25 16:04:26 +00:00
Sebastián Ramírez 95a7a61c8b 🔧 Sort keys in pyproject.toml (#2350) 2026-06-25 16:04:06 +00:00
16 changed files with 39 additions and 1062 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ jobs:
bun-version: 1.3.12 bun-version: 1.3.12
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with: with:
python-version: '3.10' python-version-file: .python-version
- name: Setup tmate session - name: Setup tmate session
uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
+1 -1
View File
@@ -44,7 +44,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with: with:
python-version: "3.11" python-version-file: .python-version
- name: Setup uv - name: Setup uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with: with:
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
persist-credentials: false persist-credentials: false
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with: with:
python-version: "3.13" python-version-file: .python-version
- name: Setup uv - name: Setup uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with: with:
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with: with:
python-version: "3.10" python-version-file: .python-version
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with: with:
+1
View File
@@ -0,0 +1 @@
3.14
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3.10 FROM python:3.14
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
+2 -2
View File
@@ -18,7 +18,7 @@ reusable_oauth2 = OAuth2PasswordBearer(
) )
def get_db() -> Generator[Session, None, None]: def get_db() -> Generator[Session]:
with Session(engine) as session: with Session(engine) as session:
yield session yield session
@@ -33,7 +33,7 @@ def get_current_user(session: SessionDep, token: TokenDep) -> User:
token, settings.SECRET_KEY, algorithms=[security.ALGORITHM] token, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
) )
token_data = TokenPayload(**payload) token_data = TokenPayload(**payload)
except (InvalidTokenError, ValidationError): except InvalidTokenError, ValidationError:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
detail="Could not validate credentials", detail="Could not validate credentials",
+1 -2
View File
@@ -1,6 +1,6 @@
import secrets import secrets
import warnings import warnings
from typing import Annotated, Any, Literal from typing import Annotated, Any, Literal, Self
from pydantic import ( from pydantic import (
AnyUrl, AnyUrl,
@@ -12,7 +12,6 @@ from pydantic import (
model_validator, model_validator,
) )
from pydantic_settings import BaseSettings, SettingsConfigDict from pydantic_settings import BaseSettings, SettingsConfigDict
from typing_extensions import Self
def parse_cors(v: Any) -> list[str] | str: def parse_cors(v: Any) -> list[str] | str:
+2 -2
View File
@@ -1,4 +1,4 @@
from datetime import datetime, timedelta, timezone from datetime import UTC, datetime, timedelta
from typing import Any from typing import Any
import jwt import jwt
@@ -20,7 +20,7 @@ ALGORITHM = "HS256"
def create_access_token(subject: str | Any, expires_delta: timedelta) -> str: def create_access_token(subject: str | Any, expires_delta: timedelta) -> str:
expire = datetime.now(timezone.utc) + expires_delta expire = datetime.now(UTC) + expires_delta
to_encode = {"exp": expire, "sub": str(subject)} to_encode = {"exp": expire, "sub": str(subject)}
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM) encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt return encoded_jwt
+3 -3
View File
@@ -1,5 +1,5 @@
import uuid import uuid
from datetime import datetime, timezone from datetime import UTC, datetime
from pydantic import EmailStr from pydantic import EmailStr
from sqlalchemy import DateTime from sqlalchemy import DateTime
@@ -7,7 +7,7 @@ from sqlmodel import Field, Relationship, SQLModel
def get_datetime_utc() -> datetime: def get_datetime_utc() -> datetime:
return datetime.now(timezone.utc) return datetime.now(UTC)
# Shared properties # Shared properties
@@ -53,7 +53,7 @@ class User(UserBase, table=True):
default_factory=get_datetime_utc, default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore sa_type=DateTime(timezone=True), # type: ignore
) )
items: list["Item"] = Relationship(back_populates="owner", cascade_delete=True) items: list[Item] = Relationship(back_populates="owner", cascade_delete=True)
# Properties to return via API, id is always required # Properties to return via API, id is always required
+2 -2
View File
@@ -1,6 +1,6 @@
import logging import logging
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, timedelta, timezone from datetime import UTC, datetime, timedelta
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
@@ -102,7 +102,7 @@ def generate_new_account_email(
def generate_password_reset_token(email: str) -> str: def generate_password_reset_token(email: str) -> str:
delta = timedelta(hours=settings.EMAIL_RESET_TOKEN_EXPIRE_HOURS) delta = timedelta(hours=settings.EMAIL_RESET_TOKEN_EXPIRE_HOURS)
now = datetime.now(timezone.utc) now = datetime.now(UTC)
expires = now + delta expires = now + delta
exp = expires.timestamp() exp = expires.timestamp()
encoded_jwt = jwt.encode( encoded_jwt = jwt.encode(
+2 -3
View File
@@ -2,7 +2,7 @@
name = "app" name = "app"
version = "0.1.0" version = "0.1.0"
description = "" description = ""
requires-python = ">=3.10,<4.0" requires-python = ">=3.14,<4.0"
dependencies = [ dependencies = [
"fastapi[standard]<1.0.0,>=0.114.2", "fastapi[standard]<1.0.0,>=0.114.2",
"python-multipart<1.0.0,>=0.0.27", "python-multipart<1.0.0,>=0.0.27",
@@ -27,7 +27,6 @@ dev = [
"mypy<3.0.0,>=1.8.0", "mypy<3.0.0,>=1.8.0",
"ty>=0.0.25", "ty>=0.0.25",
"ruff<1.0.0,>=0.2.2", "ruff<1.0.0,>=0.2.2",
"prek>=0.2.24,<1.0.0",
"coverage<8.0.0,>=7.4.3", "coverage<8.0.0,>=7.4.3",
] ]
@@ -40,7 +39,7 @@ strict = true
exclude = ["venv", ".venv", "alembic"] exclude = ["venv", ".venv", "alembic"]
[tool.ruff] [tool.ruff]
target-version = "py310" target-version = "py314"
exclude = ["alembic"] exclude = ["alembic"]
[tool.ruff.lint] [tool.ruff.lint]
+2 -2
View File
@@ -13,7 +13,7 @@ from tests.utils.utils import get_superuser_token_headers
@pytest.fixture(scope="session", autouse=True) @pytest.fixture(scope="session", autouse=True)
def db() -> Generator[Session, None, None]: def db() -> Generator[Session]:
with Session(engine) as session: with Session(engine) as session:
init_db(session) init_db(session)
yield session yield session
@@ -25,7 +25,7 @@ def db() -> Generator[Session, None, None]:
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def client() -> Generator[TestClient, None, None]: def client() -> Generator[TestClient]:
with TestClient(app) as c: with TestClient(app) as c:
yield c yield c
+4 -3
View File
@@ -1,8 +1,6 @@
[tool.uv.workspace]
members = ["backend"]
[dependency-groups] [dependency-groups]
dev = [ dev = [
"prek>=0.2.24,<1.0.0",
"zizmor>=1.25.2", "zizmor>=1.25.2",
] ]
@@ -10,6 +8,9 @@ github-actions = [
"smokeshow >=0.5.0", "smokeshow >=0.5.0",
] ]
[tool.uv.workspace]
members = ["backend"]
[tool.typos.files] [tool.typos.files]
extend-exclude = [ extend-exclude = [
"img/", "img/",
+3
View File
@@ -9,6 +9,7 @@
### Upgrades ### Upgrades
* ⬆️ Upgrade Python to 3.14. PR [#2352](https://github.com/fastapi/full-stack-fastapi-template/pull/2352) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade Sentry and FastAPI. PR [#2181](https://github.com/fastapi/full-stack-fastapi-template/pull/2181) by [@patrick91](https://github.com/patrick91). * ⬆️ Upgrade Sentry and FastAPI. PR [#2181](https://github.com/fastapi/full-stack-fastapi-template/pull/2181) by [@patrick91](https://github.com/patrick91).
### Docs ### Docs
@@ -19,6 +20,8 @@
### Internal ### Internal
* ➕ Move prek to top level dependencies. PR [#2353](https://github.com/fastapi/full-stack-fastapi-template/pull/2353) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Sort keys in pyproject.toml. PR [#2350](https://github.com/fastapi/full-stack-fastapi-template/pull/2350) by [@tiangolo](https://github.com/tiangolo).
* 👷 Simplify pull request workflow triggers. PR [#2349](https://github.com/fastapi/full-stack-fastapi-template/pull/2349) by [@tiangolo](https://github.com/tiangolo). * 👷 Simplify pull request workflow triggers. PR [#2349](https://github.com/fastapi/full-stack-fastapi-template/pull/2349) by [@tiangolo](https://github.com/tiangolo).
* 👷 Update issue-manager to 0.7.1. PR [#2348](https://github.com/fastapi/full-stack-fastapi-template/pull/2348) by [@tiangolo](https://github.com/tiangolo). * 👷 Update issue-manager to 0.7.1. PR [#2348](https://github.com/fastapi/full-stack-fastapi-template/pull/2348) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Update issue-manager to 0.7.0. PR [#2347](https://github.com/fastapi/full-stack-fastapi-template/pull/2347) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Update issue-manager to 0.7.0. PR [#2347](https://github.com/fastapi/full-stack-fastapi-template/pull/2347) by [@tiangolo](https://github.com/tiangolo).
Generated
+12 -1038
View File
File diff suppressed because it is too large Load Diff