Update python dependencies and ruff/black versions
This commit is contained in:
@@ -60,7 +60,6 @@ select = [
|
|||||||
"ALL",
|
"ALL",
|
||||||
]
|
]
|
||||||
ignore = [
|
ignore = [
|
||||||
"ANN101",
|
|
||||||
"A003",
|
"A003",
|
||||||
"D101",
|
"D101",
|
||||||
"D104",
|
"D104",
|
||||||
@@ -85,6 +84,7 @@ ignore = [
|
|||||||
[tool.ruff.lint.per-file-ignores]
|
[tool.ruff.lint.per-file-ignores]
|
||||||
"tests*/*" = [
|
"tests*/*" = [
|
||||||
"ANN201",
|
"ANN201",
|
||||||
|
"ASYNC210",
|
||||||
"S101",
|
"S101",
|
||||||
"PLR2004",
|
"PLR2004",
|
||||||
"D103",
|
"D103",
|
||||||
|
|||||||
@@ -121,14 +121,13 @@ class FilamentParameters(BaseModel):
|
|||||||
|
|
||||||
@field_validator("color_hex")
|
@field_validator("color_hex")
|
||||||
@classmethod
|
@classmethod
|
||||||
def color_hex_validator(cls, v: Optional[str]) -> Optional[str]: # noqa: ANN102
|
def color_hex_validator(cls, v: Optional[str]) -> Optional[str]:
|
||||||
"""Validate the color_hex field."""
|
"""Validate the color_hex field."""
|
||||||
if not v:
|
if not v:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
clr = v.upper()
|
clr = v.upper()
|
||||||
if clr.startswith("#"):
|
clr = clr.removeprefix("#")
|
||||||
clr = clr[1:]
|
|
||||||
|
|
||||||
for c in clr:
|
for c in clr:
|
||||||
if c not in "0123456789ABCDEF":
|
if c not in "0123456789ABCDEF":
|
||||||
@@ -141,14 +140,13 @@ class FilamentParameters(BaseModel):
|
|||||||
|
|
||||||
@field_validator("multi_color_hexes")
|
@field_validator("multi_color_hexes")
|
||||||
@classmethod
|
@classmethod
|
||||||
def multi_color_hexes_validator(cls, v: Optional[str]) -> Optional[str]: # noqa: ANN102
|
def multi_color_hexes_validator(cls, v: Optional[str]) -> Optional[str]:
|
||||||
"""Validate the multi_color_hexes field."""
|
"""Validate the multi_color_hexes field."""
|
||||||
if not v:
|
if not v:
|
||||||
return None
|
return None
|
||||||
for clr_raw in v.split(","):
|
for clr_raw in v.split(","):
|
||||||
clr = clr_raw.upper()
|
clr = clr_raw.upper()
|
||||||
if clr.startswith("#"):
|
clr = clr.removeprefix("#")
|
||||||
clr = clr[1:]
|
|
||||||
|
|
||||||
for c in clr:
|
for c in clr:
|
||||||
if c not in "0123456789ABCDEF":
|
if c not in "0123456789ABCDEF":
|
||||||
@@ -204,24 +202,24 @@ class FilamentUpdateParameters(FilamentParameters):
|
|||||||
async def find(
|
async def find(
|
||||||
*,
|
*,
|
||||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||||
vendor_name_old: Optional[str] = Query(
|
vendor_name_old: Annotated[
|
||||||
alias="vendor_name",
|
Optional[str],
|
||||||
default=None,
|
Query(alias="vendor_name", title="Vendor Name", description="See vendor.name.", deprecated=True),
|
||||||
title="Vendor Name",
|
] = None,
|
||||||
description="See vendor.name.",
|
vendor_id_old: Annotated[
|
||||||
deprecated=True,
|
Optional[str],
|
||||||
),
|
Query(
|
||||||
vendor_id_old: Optional[str] = Query(
|
|
||||||
alias="vendor_id",
|
alias="vendor_id",
|
||||||
default=None,
|
|
||||||
title="Vendor ID",
|
title="Vendor ID",
|
||||||
description="See vendor.id.",
|
description="See vendor.id.",
|
||||||
deprecated=True,
|
deprecated=True,
|
||||||
pattern=r"^-?\d+(,-?\d+)*$",
|
pattern=r"^-?\d+(,-?\d+)*$",
|
||||||
),
|
),
|
||||||
vendor_name: Optional[str] = Query(
|
] = None,
|
||||||
|
vendor_name: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="vendor.name",
|
alias="vendor.name",
|
||||||
default=None,
|
|
||||||
title="Vendor Name",
|
title="Vendor Name",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the filament vendor name. "
|
"Partial case-insensitive search term for the filament vendor name. "
|
||||||
@@ -229,9 +227,11 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
vendor_id: Optional[str] = Query(
|
] = None,
|
||||||
|
vendor_id: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="vendor.id",
|
alias="vendor.id",
|
||||||
default=None,
|
|
||||||
title="Vendor ID",
|
title="Vendor ID",
|
||||||
description=(
|
description=(
|
||||||
"Match an exact vendor ID. Separate multiple IDs with a comma. "
|
"Match an exact vendor ID. Separate multiple IDs with a comma. "
|
||||||
@@ -240,8 +240,10 @@ async def find(
|
|||||||
pattern=r"^-?\d+(,-?\d+)*$",
|
pattern=r"^-?\d+(,-?\d+)*$",
|
||||||
examples=["1", "1,2"],
|
examples=["1", "1,2"],
|
||||||
),
|
),
|
||||||
name: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
name: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Filament Name",
|
title="Filament Name",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the filament name. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the filament name. Separate multiple terms with a comma. "
|
||||||
@@ -249,8 +251,10 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
material: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
material: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Filament Material",
|
title="Filament Material",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. "
|
||||||
@@ -258,8 +262,10 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
article_number: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
article_number: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Filament Article Number",
|
title="Filament Article Number",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the filament article number. "
|
"Partial case-insensitive search term for the filament article number. "
|
||||||
@@ -268,21 +274,27 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
color_hex: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
color_hex: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Filament Color",
|
title="Filament Color",
|
||||||
description="Match filament by similar color. Slow operation!",
|
description="Match filament by similar color. Slow operation!",
|
||||||
),
|
),
|
||||||
color_similarity_threshold: float = Query(
|
] = None,
|
||||||
default=20.0,
|
color_similarity_threshold: Annotated[
|
||||||
|
float,
|
||||||
|
Query(
|
||||||
description=(
|
description=(
|
||||||
"The similarity threshold for color matching. "
|
"The similarity threshold for color matching. "
|
||||||
"A value between 0.0-100.0, where 0 means match only exactly the same color."
|
"A value between 0.0-100.0, where 0 means match only exactly the same color."
|
||||||
),
|
),
|
||||||
example=20.0,
|
example=20.0,
|
||||||
),
|
),
|
||||||
external_id: Optional[str] = Query(
|
] = 20.0,
|
||||||
default=None,
|
external_id: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
description=(
|
description=(
|
||||||
"Find filaments imported by the given external ID. "
|
"Find filaments imported by the given external ID. "
|
||||||
"Separate multiple IDs with a comma. "
|
"Separate multiple IDs with a comma. "
|
||||||
@@ -291,24 +303,22 @@ async def find(
|
|||||||
),
|
),
|
||||||
example="polymaker_pla_polysonicblack_1000_175",
|
example="polymaker_pla_polysonicblack_1000_175",
|
||||||
),
|
),
|
||||||
sort: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
sort: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Sort",
|
title="Sort",
|
||||||
description=(
|
description=(
|
||||||
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
||||||
),
|
),
|
||||||
example="vendor.name:asc,spool_weight:desc",
|
example="vendor.name:asc,spool_weight:desc",
|
||||||
),
|
),
|
||||||
limit: Optional[int] = Query(
|
] = None,
|
||||||
default=None,
|
limit: Annotated[
|
||||||
title="Limit",
|
Optional[int],
|
||||||
description="Maximum number of items in the response.",
|
Query(title="Limit", description="Maximum number of items in the response."),
|
||||||
),
|
] = None,
|
||||||
offset: int = Query(
|
offset: Annotated[int, Query(title="Offset", description="Offset in the full result set if a limit is set.")] = 0,
|
||||||
default=0,
|
|
||||||
title="Offset",
|
|
||||||
description="Offset in the full result set if a limit is set.",
|
|
||||||
),
|
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
sort_by: dict[str, SortOrder] = {}
|
sort_by: dict[str, SortOrder] = {}
|
||||||
if sort is not None:
|
if sort is not None:
|
||||||
|
|||||||
@@ -128,46 +128,47 @@ class SpoolMeasureParameters(BaseModel):
|
|||||||
async def find(
|
async def find(
|
||||||
*,
|
*,
|
||||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||||
filament_name_old: Optional[str] = Query(
|
filament_name_old: Annotated[
|
||||||
alias="filament_name",
|
Optional[str],
|
||||||
default=None,
|
Query(alias="filament_name", title="Filament Name", description="See filament.name.", deprecated=True),
|
||||||
title="Filament Name",
|
] = None,
|
||||||
description="See filament.name.",
|
filament_id_old: Annotated[
|
||||||
deprecated=True,
|
Optional[str],
|
||||||
),
|
Query(
|
||||||
filament_id_old: Optional[str] = Query(
|
|
||||||
alias="filament_id",
|
alias="filament_id",
|
||||||
default=None,
|
|
||||||
title="Filament ID",
|
title="Filament ID",
|
||||||
description="See filament.id.",
|
description="See filament.id.",
|
||||||
deprecated=True,
|
deprecated=True,
|
||||||
pattern=r"^-?\d+(,-?\d+)*$",
|
pattern=r"^-?\d+(,-?\d+)*$",
|
||||||
),
|
),
|
||||||
filament_material_old: Optional[str] = Query(
|
] = None,
|
||||||
|
filament_material_old: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="filament_material",
|
alias="filament_material",
|
||||||
default=None,
|
|
||||||
title="Filament Material",
|
title="Filament Material",
|
||||||
description="See filament.material.",
|
description="See filament.material.",
|
||||||
deprecated=True,
|
deprecated=True,
|
||||||
),
|
),
|
||||||
vendor_name_old: Optional[str] = Query(
|
] = None,
|
||||||
alias="vendor_name",
|
vendor_name_old: Annotated[
|
||||||
default=None,
|
Optional[str],
|
||||||
title="Vendor Name",
|
Query(alias="vendor_name", title="Vendor Name", description="See filament.vendor.name.", deprecated=True),
|
||||||
description="See filament.vendor.name.",
|
] = None,
|
||||||
deprecated=True,
|
vendor_id_old: Annotated[
|
||||||
),
|
Optional[str],
|
||||||
vendor_id_old: Optional[str] = Query(
|
Query(
|
||||||
alias="vendor_id",
|
alias="vendor_id",
|
||||||
default=None,
|
|
||||||
title="Vendor ID",
|
title="Vendor ID",
|
||||||
description="See filament.vendor.id.",
|
description="See filament.vendor.id.",
|
||||||
deprecated=True,
|
deprecated=True,
|
||||||
pattern=r"^-?\d+(,-?\d+)*$",
|
pattern=r"^-?\d+(,-?\d+)*$",
|
||||||
),
|
),
|
||||||
filament_name: Optional[str] = Query(
|
] = None,
|
||||||
|
filament_name: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="filament.name",
|
alias="filament.name",
|
||||||
default=None,
|
|
||||||
title="Filament Name",
|
title="Filament Name",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the filament name. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the filament name. Separate multiple terms with a comma. "
|
||||||
@@ -175,17 +176,21 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
filament_id: Optional[str] = Query(
|
] = None,
|
||||||
|
filament_id: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="filament.id",
|
alias="filament.id",
|
||||||
default=None,
|
|
||||||
title="Filament ID",
|
title="Filament ID",
|
||||||
description="Match an exact filament ID. Separate multiple IDs with a comma.",
|
description="Match an exact filament ID. Separate multiple IDs with a comma.",
|
||||||
examples=["1", "1,2"],
|
examples=["1", "1,2"],
|
||||||
pattern=r"^-?\d+(,-?\d+)*$",
|
pattern=r"^-?\d+(,-?\d+)*$",
|
||||||
),
|
),
|
||||||
filament_material: Optional[str] = Query(
|
] = None,
|
||||||
|
filament_material: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="filament.material",
|
alias="filament.material",
|
||||||
default=None,
|
|
||||||
title="Filament Material",
|
title="Filament Material",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. "
|
||||||
@@ -193,19 +198,24 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
filament_vendor_name: Optional[str] = Query(
|
] = None,
|
||||||
|
filament_vendor_name: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="filament.vendor.name",
|
alias="filament.vendor.name",
|
||||||
default=None,
|
|
||||||
title="Vendor Name",
|
title="Vendor Name",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the filament vendor name. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the filament vendor name. "
|
||||||
|
"Separate multiple terms with a comma. "
|
||||||
"Specify an empty string to match spools with no vendor name. "
|
"Specify an empty string to match spools with no vendor name. "
|
||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
filament_vendor_id: Optional[str] = Query(
|
] = None,
|
||||||
|
filament_vendor_id: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
alias="filament.vendor.id",
|
alias="filament.vendor.id",
|
||||||
default=None,
|
|
||||||
title="Vendor ID",
|
title="Vendor ID",
|
||||||
description=(
|
description=(
|
||||||
"Match an exact vendor ID. Separate multiple IDs with a comma. "
|
"Match an exact vendor ID. Separate multiple IDs with a comma. "
|
||||||
@@ -214,8 +224,10 @@ async def find(
|
|||||||
examples=["1", "1,2"],
|
examples=["1", "1,2"],
|
||||||
pattern=r"^-?\d+(,-?\d+)*$",
|
pattern=r"^-?\d+(,-?\d+)*$",
|
||||||
),
|
),
|
||||||
location: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
location: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Location",
|
title="Location",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the spool location. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the spool location. Separate multiple terms with a comma. "
|
||||||
@@ -223,8 +235,10 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
lot_nr: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
lot_nr: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Lot/Batch Number",
|
title="Lot/Batch Number",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the spool lot number. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the spool lot number. Separate multiple terms with a comma. "
|
||||||
@@ -232,29 +246,26 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
allow_archived: bool = Query(
|
] = None,
|
||||||
default=False,
|
allow_archived: Annotated[
|
||||||
title="Allow Archived",
|
bool,
|
||||||
description="Whether to include archived spools in the search results.",
|
Query(title="Allow Archived", description="Whether to include archived spools in the search results."),
|
||||||
),
|
] = False,
|
||||||
sort: Optional[str] = Query(
|
sort: Annotated[
|
||||||
default=None,
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Sort",
|
title="Sort",
|
||||||
description=(
|
description=(
|
||||||
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
||||||
),
|
),
|
||||||
example="filament.name:asc,filament.vendor.id:asc,location:desc",
|
example="filament.name:asc,filament.vendor.id:asc,location:desc",
|
||||||
),
|
),
|
||||||
limit: Optional[int] = Query(
|
] = None,
|
||||||
default=None,
|
limit: Annotated[
|
||||||
title="Limit",
|
Optional[int],
|
||||||
description="Maximum number of items in the response.",
|
Query(title="Limit", description="Maximum number of items in the response."),
|
||||||
),
|
] = None,
|
||||||
offset: int = Query(
|
offset: Annotated[int, Query(title="Offset", description="Offset in the full result set if a limit is set.")] = 0,
|
||||||
default=0,
|
|
||||||
title="Offset",
|
|
||||||
description="Offset in the full result set if a limit is set.",
|
|
||||||
),
|
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
sort_by: dict[str, SortOrder] = {}
|
sort_by: dict[str, SortOrder] = {}
|
||||||
if sort is not None:
|
if sort is not None:
|
||||||
|
|||||||
@@ -80,16 +80,19 @@ class VendorUpdateParameters(VendorParameters):
|
|||||||
)
|
)
|
||||||
async def find(
|
async def find(
|
||||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||||
name: Optional[str] = Query(
|
name: Annotated[
|
||||||
default=None,
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Vendor Name",
|
title="Vendor Name",
|
||||||
description=(
|
description=(
|
||||||
"Partial case-insensitive search term for the vendor name. Separate multiple terms with a comma. "
|
"Partial case-insensitive search term for the vendor name. Separate multiple terms with a comma. "
|
||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
external_id: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
external_id: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Vendor External ID",
|
title="Vendor External ID",
|
||||||
description=(
|
description=(
|
||||||
"Exact match for the vendor external ID. "
|
"Exact match for the vendor external ID. "
|
||||||
@@ -98,24 +101,22 @@ async def find(
|
|||||||
"Surround a term with quotes to search for the exact term."
|
"Surround a term with quotes to search for the exact term."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
sort: Optional[str] = Query(
|
] = None,
|
||||||
default=None,
|
sort: Annotated[
|
||||||
|
Optional[str],
|
||||||
|
Query(
|
||||||
title="Sort",
|
title="Sort",
|
||||||
description=(
|
description=(
|
||||||
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
'Sort the results by the given field. Should be a comma-separate string with "field:direction" items.'
|
||||||
),
|
),
|
||||||
example="name:asc,id:desc",
|
example="name:asc,id:desc",
|
||||||
),
|
),
|
||||||
limit: Optional[int] = Query(
|
] = None,
|
||||||
default=None,
|
limit: Annotated[
|
||||||
title="Limit",
|
Optional[int],
|
||||||
description="Maximum number of items in the response.",
|
Query(title="Limit", description="Maximum number of items in the response."),
|
||||||
),
|
] = None,
|
||||||
offset: int = Query(
|
offset: Annotated[int, Query(title="Offset", description="Offset in the full result set if a limit is set.")] = 0,
|
||||||
default=0,
|
|
||||||
title="Offset",
|
|
||||||
description="Offset in the full result set if a limit is set.",
|
|
||||||
),
|
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
sort_by: dict[str, SortOrder] = {}
|
sort_by: dict[str, SortOrder] = {}
|
||||||
if sort is not None:
|
if sort is not None:
|
||||||
|
|||||||
@@ -59,11 +59,11 @@ class Database:
|
|||||||
engine: Optional[AsyncEngine]
|
engine: Optional[AsyncEngine]
|
||||||
session_maker: Optional[async_sessionmaker[AsyncSession]]
|
session_maker: Optional[async_sessionmaker[AsyncSession]]
|
||||||
|
|
||||||
def __init__(self: "Database", connection_url: URL) -> None:
|
def __init__(self, connection_url: URL) -> None:
|
||||||
"""Construct the Database wrapper and set config parameters."""
|
"""Construct the Database wrapper and set config parameters."""
|
||||||
self.connection_url = connection_url
|
self.connection_url = connection_url
|
||||||
|
|
||||||
def is_file_based_sqlite(self: "Database") -> bool:
|
def is_file_based_sqlite(self) -> bool:
|
||||||
"""Return True if the database is file based."""
|
"""Return True if the database is file based."""
|
||||||
return (
|
return (
|
||||||
self.connection_url.drivername[:6] == "sqlite"
|
self.connection_url.drivername[:6] == "sqlite"
|
||||||
@@ -71,7 +71,7 @@ class Database:
|
|||||||
and self.connection_url.database != ":memory:"
|
and self.connection_url.database != ":memory:"
|
||||||
)
|
)
|
||||||
|
|
||||||
def connect(self: "Database") -> None:
|
def connect(self) -> None:
|
||||||
"""Connect to the database."""
|
"""Connect to the database."""
|
||||||
if env.get_logging_level() == logging.DEBUG:
|
if env.get_logging_level() == logging.DEBUG:
|
||||||
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
|
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
|
||||||
@@ -87,7 +87,7 @@ class Database:
|
|||||||
)
|
)
|
||||||
self.session_maker = async_sessionmaker(self.engine, autocommit=False, autoflush=True, expire_on_commit=False)
|
self.session_maker = async_sessionmaker(self.engine, autocommit=False, autoflush=True, expire_on_commit=False)
|
||||||
|
|
||||||
def backup(self: "Database", target_path: Union[str, PathLike[str]]) -> None:
|
def backup(self, target_path: Union[str, PathLike[str]]) -> None:
|
||||||
"""Backup the database."""
|
"""Backup the database."""
|
||||||
if not self.is_file_based_sqlite() or self.connection_url.database is None:
|
if not self.is_file_based_sqlite() or self.connection_url.database is None:
|
||||||
return
|
return
|
||||||
@@ -108,7 +108,7 @@ class Database:
|
|||||||
logger.info("Backup complete.")
|
logger.info("Backup complete.")
|
||||||
|
|
||||||
def backup_and_rotate(
|
def backup_and_rotate(
|
||||||
self: "Database",
|
self,
|
||||||
backup_folder: Union[str, PathLike[str]],
|
backup_folder: Union[str, PathLike[str]],
|
||||||
num_backups: int = 5,
|
num_backups: int = 5,
|
||||||
) -> Optional[Path]:
|
) -> Optional[Path]:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class DatabaseType(Enum):
|
|||||||
SQLITE = "sqlite"
|
SQLITE = "sqlite"
|
||||||
COCKROACHDB = "cockroachdb"
|
COCKROACHDB = "cockroachdb"
|
||||||
|
|
||||||
def to_drivername(self: "DatabaseType") -> str:
|
def to_drivername(self) -> str:
|
||||||
"""Get the drivername for the database type.
|
"""Get the drivername for the database type.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ async def startup() -> None:
|
|||||||
# There is some issue with the uvicorn worker that causes the process to hang when running alembic directly.
|
# There is some issue with the uvicorn worker that causes the process to hang when running alembic directly.
|
||||||
# See: https://github.com/sqlalchemy/alembic/discussions/1155
|
# See: https://github.com/sqlalchemy/alembic/discussions/1155
|
||||||
project_root = Path(__file__).parent.parent
|
project_root = Path(__file__).parent.parent
|
||||||
subprocess.run(["alembic", "upgrade", "head"], check=True, cwd=project_root) # noqa: S603, S607, ASYNC101
|
subprocess.run(["alembic", "upgrade", "head"], check=True, cwd=project_root) # noqa: S603, S607, ASYNC221
|
||||||
|
|
||||||
# Setup scheduler
|
# Setup scheduler
|
||||||
schedule = Scheduler()
|
schedule = Scheduler()
|
||||||
|
|||||||
@@ -162,35 +162,35 @@ def random_empty_filament_empty_vendor_impl():
|
|||||||
httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status()
|
httpx.delete(f"{URL}/api/v1/filament/{filament['id']}").raise_for_status()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture
|
||||||
def random_vendor():
|
def random_vendor():
|
||||||
"""Return a random vendor."""
|
"""Return a random vendor."""
|
||||||
with random_vendor_impl() as random_vendor:
|
with random_vendor_impl() as random_vendor:
|
||||||
yield random_vendor
|
yield random_vendor
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture
|
||||||
def random_empty_vendor():
|
def random_empty_vendor():
|
||||||
"""Return a random vendor with only required fields specified."""
|
"""Return a random vendor with only required fields specified."""
|
||||||
with random_empty_vendor_impl() as random_empty_vendor:
|
with random_empty_vendor_impl() as random_empty_vendor:
|
||||||
yield random_empty_vendor
|
yield random_empty_vendor
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture
|
||||||
def random_filament():
|
def random_filament():
|
||||||
"""Return a random filament."""
|
"""Return a random filament."""
|
||||||
with random_filament_impl() as random_filament:
|
with random_filament_impl() as random_filament:
|
||||||
yield random_filament
|
yield random_filament
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture
|
||||||
def random_empty_filament():
|
def random_empty_filament():
|
||||||
"""Return a random filament with only required fields specified."""
|
"""Return a random filament with only required fields specified."""
|
||||||
with random_empty_filament_impl() as random_empty_filament:
|
with random_empty_filament_impl() as random_empty_filament:
|
||||||
yield random_empty_filament
|
yield random_empty_filament
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture
|
||||||
def random_empty_filament_empty_vendor():
|
def random_empty_filament_empty_vendor():
|
||||||
"""Return a random filament with only required fields specified and a vendor with only required fields specified."""
|
"""Return a random filament with only required fields specified and a vendor with only required fields specified."""
|
||||||
with random_empty_filament_empty_vendor_impl() as random_empty_filament_empty_vendor:
|
with random_empty_filament_empty_vendor_impl() as random_empty_filament_empty_vendor:
|
||||||
|
|||||||
@@ -138,12 +138,12 @@ def test_use_spool_not_found():
|
|||||||
assert "123456789" in message
|
assert "123456789" in message
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio()
|
@pytest.mark.asyncio
|
||||||
async def test_use_spool_concurrent(random_filament: dict[str, Any]):
|
async def test_use_spool_concurrent(random_filament: dict[str, Any]):
|
||||||
"""Test using a spool with many concurrent requests."""
|
"""Test using a spool with many concurrent requests."""
|
||||||
# Setup
|
# Setup
|
||||||
start_weight = 1000
|
start_weight = 1000
|
||||||
result = httpx.post( # noqa: ASYNC100
|
result = httpx.post(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
json={
|
json={
|
||||||
"filament_id": random_filament["id"],
|
"filament_id": random_filament["id"],
|
||||||
@@ -171,10 +171,10 @@ async def test_use_spool_concurrent(random_filament: dict[str, Any]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}") # noqa: ASYNC100
|
result = httpx.get(f"{URL}/api/v1/spool/{spool['id']}")
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
spool = result.json()
|
spool = result.json()
|
||||||
assert spool["remaining_weight"] == pytest.approx(start_weight - (used_weight * requests))
|
assert spool["remaining_weight"] == pytest.approx(start_weight - (used_weight * requests))
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status() # noqa: ASYNC100
|
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status()
|
||||||
|
|||||||
Reference in New Issue
Block a user