Updated most python dependencies

Primarily FastAPI and Pydantic to v2. Also ruff to latest.

Updated some code to support Pydantic v2
This commit is contained in:
Donkie
2024-05-23 19:42:27 +02:00
parent 306dbe40af
commit 535fa40ad2
29 changed files with 839 additions and 531 deletions

View File

@@ -6,10 +6,8 @@ from typing import Annotated, Optional
from fastapi import APIRouter, Depends, Query, WebSocket, WebSocketDisconnect
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field, validator
from pydantic.error_wrappers import ErrorWrapper
from pydantic import BaseModel, Field, field_validator
from sqlalchemy.ext.asyncio import AsyncSession
from spoolman.api.v1.models import Filament, FilamentEvent, Message
@@ -32,69 +30,80 @@ router = APIRouter(
class FilamentParameters(BaseModel):
name: Optional[str] = Field(
None,
max_length=64,
description=(
"Filament name, to distinguish this filament type among others from the same vendor."
"Should contain its color for example."
),
example="PolyTerra™ Charcoal Black",
examples=["PolyTerra™ Charcoal Black"],
)
vendor_id: Optional[int] = Field(description="The ID of the vendor of this filament type.")
vendor_id: Optional[int] = Field(None, description="The ID of the vendor of this filament type.")
material: Optional[str] = Field(
None,
max_length=64,
description="The material of this filament, e.g. PLA.",
example="PLA",
examples=["PLA"],
)
price: Optional[float] = Field(
None,
ge=0,
description="The price of this filament in the system configured currency.",
example=20.0,
examples=[20.0],
)
density: float = Field(gt=0, description="The density of this filament in g/cm3.", example=1.24)
diameter: float = Field(gt=0, description="The diameter of this filament in mm.", example=1.75)
density: float = Field(gt=0, description="The density of this filament in g/cm3.", examples=[1.24])
diameter: float = Field(gt=0, description="The diameter of this filament in mm.", examples=[1.75])
weight: Optional[float] = Field(
None,
gt=0,
description="The weight of the filament in a full spool, in grams. (net weight)",
example=1000,
examples=[1000],
)
spool_weight: Optional[float] = Field(gt=0, description="The empty spool weight, in grams.", example=140)
spool_weight: Optional[float] = Field(None, gt=0, description="The empty spool weight, in grams.", examples=[140])
article_number: Optional[str] = Field(
None,
max_length=64,
description="Vendor article number, e.g. EAN, QR code, etc.",
example="PM70820",
examples=["PM70820"],
)
comment: Optional[str] = Field(
None,
max_length=1024,
description="Free text comment about this filament type.",
example="",
examples=[""],
)
settings_extruder_temp: Optional[int] = Field(
None,
ge=0,
description="Overridden extruder temperature, in °C.",
example=210,
examples=[210],
)
settings_bed_temp: Optional[int] = Field(
None,
ge=0,
description="Overridden bed temperature, in °C.",
example=60,
examples=[60],
)
color_hex: Optional[str] = Field(
None,
description="Hexadecimal color code of the filament, e.g. FF0000 for red. Supports alpha channel at the end.",
example="FF0000",
examples=["FF0000"],
)
external_id: Optional[str] = Field(
None,
max_length=256,
description=(
"Set if this filament comes from an external database. This contains the ID in the external database."
),
example="polymaker_pla_polysonicblack_1000_175",
examples=["polymaker_pla_polysonicblack_1000_175"],
)
extra: Optional[dict[str, str]] = Field(
None,
description="Extra fields for this filament.",
)
@validator("color_hex")
@field_validator("color_hex")
@classmethod
@classmethod
def color_hex_validator(cls, v: Optional[str]) -> Optional[str]: # noqa: ANN102
"""Validate the color_hex field."""
@@ -115,8 +124,16 @@ class FilamentParameters(BaseModel):
class FilamentUpdateParameters(FilamentParameters):
density: Optional[float] = Field(gt=0, description="The density of this filament in g/cm3.", example=1.24)
diameter: Optional[float] = Field(gt=0, description="The diameter of this filament in mm.", example=1.75)
density: Optional[float] = Field(None, gt=0, description="The density of this filament in g/cm3.", examples=[1.24])
diameter: Optional[float] = Field(None, gt=0, description="The diameter of this filament in mm.", examples=[1.75])
@field_validator("density", "diameter")
@classmethod
def prevent_none(cls: type["FilamentUpdateParameters"], v: Optional[float]) -> Optional[float]:
"""Prevent density and diameter from being None."""
if v is None:
raise ValueError("Value must not be None.")
return v
@router.get(
@@ -149,6 +166,7 @@ async def find(
title="Vendor ID",
description="See vendor.id.",
deprecated=True,
pattern=r"^-?\d+(,-?\d+)*$",
),
vendor_name: Optional[str] = Query(
alias="vendor.name",
@@ -167,6 +185,7 @@ async def find(
"Match an exact vendor ID. Separate multiple IDs with a comma. "
"Specify -1 to match filaments with no vendor."
),
pattern=r"^-?\d+(,-?\d+)*$",
examples=["1", "1,2"],
),
name: Optional[str] = Query(
@@ -243,10 +262,7 @@ async def find(
vendor_id = vendor_id if vendor_id is not None else vendor_id_old
if vendor_id is not None:
try:
vendor_ids = [int(vendor_id_item) for vendor_id_item in vendor_id.split(",")]
except ValueError as e:
raise RequestValidationError([ErrorWrapper(ValueError("Invalid vendor_id"), ("query", "vendor_id"))]) from e
vendor_ids = [int(vendor_id_item) for vendor_id_item in vendor_id.split(",")]
else:
vendor_ids = None
@@ -399,12 +415,7 @@ async def update( # noqa: ANN201
filament_id: int,
body: FilamentUpdateParameters,
):
patch_data = body.dict(exclude_unset=True)
if "density" in patch_data and body.density is None:
raise RequestValidationError([ErrorWrapper(ValueError("density cannot be unset"), ("query", "density"))])
if "diameter" in patch_data and body.diameter is None:
raise RequestValidationError([ErrorWrapper(ValueError("diameter cannot be unset"), ("query", "diameter"))])
patch_data = body.model_dump(exclude_unset=True)
if body.extra:
all_fields = await get_extra_fields(db, EntityType.filament)