fix(models): use plain dict for JSON columns
LNbits's db.dict_to_model walks each field and unconditionally
calls `issubclass(field.type_, bool)` (lnbits/db.py:730). When
field.type_ is a parameterized generic alias like
`list[dict[str, str]]` (the value type of OpenHours.schedule's
`dict[str, list[dict[str, str]]]`), Python raises:
TypeError: issubclass() arg 1 must be a class
— which surfaced as a 500 on GET /restaurants and any other
endpoint that deserialized a Restaurant row. POSTs succeeded
(serialization writes JSON), but every read crashed. So newly
created restaurants disappeared from the list and the settings
page 500'd.
Same risk on RestaurantExtra.fields, MenuItemExtra.fields, and
OrderExtra.fields (all `dict[str, str]`) — those didn't crash
but silently failed to round-trip (the JSON string stayed a
string instead of being parsed back to a dict).
Loosen all four fields to plain `dict`. With type_=dict,
LNbits's deserializer hits its 'type_ is dict' branch
(lnbits/db.py:744) and json.loads the value correctly. The
runtime shape is unchanged; we just lose static type
parameterization on these JSON columns. Documented inline so
future contributors don't tighten them back.
This commit is contained in:
parent
37a2f64be6
commit
f157785d22
1 changed files with 18 additions and 5 deletions
23
models.py
23
models.py
|
|
@ -53,10 +53,18 @@ class OpenHours(BaseModel):
|
|||
"""Weekly opening schedule. Weekday key 0=Mon .. 6=Sun.
|
||||
|
||||
Each day is a list of {start, end} ranges so a venue can be open
|
||||
e.g. 11:00-15:00 and 18:00-23:00 in the same day.
|
||||
e.g. 11:00-15:00 and 18:00-23:00 in the same day. Persisted as
|
||||
JSON in the DB.
|
||||
|
||||
Typed as plain `dict` (not `dict[str, list[dict[str, str]]]`) so
|
||||
LNbits's `db.dict_to_model` walks the field cleanly: its
|
||||
introspection calls `issubclass(field.type_, bool)` while
|
||||
iterating, and a parameterized generic alias trips it with
|
||||
"issubclass() arg 1 must be a class". The runtime shape is
|
||||
still the dict-of-lists-of-dicts described above.
|
||||
"""
|
||||
|
||||
schedule: dict[str, list[dict[str, str]]] = Field(default_factory=dict)
|
||||
schedule: dict = Field(default_factory=dict)
|
||||
|
||||
|
||||
class SocialLinks(BaseModel):
|
||||
|
|
@ -69,7 +77,10 @@ class SocialLinks(BaseModel):
|
|||
|
||||
class RestaurantExtra(BaseModel):
|
||||
notes: Optional[str] = None
|
||||
fields: dict[str, str] = Field(default_factory=dict)
|
||||
# Typed as plain `dict` (not `dict[str, str]`) so LNbits's
|
||||
# `db.dict_to_model` round-trips it cleanly — see OpenHours for
|
||||
# the same workaround and rationale.
|
||||
fields: dict = Field(default_factory=dict)
|
||||
|
||||
|
||||
class CreateRestaurant(BaseModel):
|
||||
|
|
@ -211,7 +222,8 @@ class MenuItemExtra(BaseModel):
|
|||
"""Free-form metadata that doesn't deserve a column yet."""
|
||||
|
||||
notes: Optional[str] = None
|
||||
fields: dict[str, str] = Field(default_factory=dict)
|
||||
# Plain `dict` — see OpenHours for the LNbits round-trip workaround.
|
||||
fields: dict = Field(default_factory=dict)
|
||||
|
||||
|
||||
class CreateMenuItem(BaseModel):
|
||||
|
|
@ -404,7 +416,8 @@ class OrderExtra(BaseModel):
|
|||
fiat_currency: Optional[str] = None
|
||||
fiat_rate: Optional[float] = None
|
||||
refund_address: Optional[str] = None
|
||||
fields: dict[str, str] = Field(default_factory=dict)
|
||||
# Plain `dict` — see OpenHours for the LNbits round-trip workaround.
|
||||
fields: dict = Field(default_factory=dict)
|
||||
|
||||
|
||||
class CreateOrder(BaseModel):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue