mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-07-24 18:04:32 +02:00
ForeignKey is now a frozen dataclass, restoring hashability
The namedtuple-to-dataclass change made ForeignKey unhashable, breaking set(table.foreign_keys) and dict-key usage that worked in 3.x. frozen=True restores immutability and hashability. Equality and hashing cover all compared fields including on_delete/on_update - two foreign keys differing only in their actions are different constraints. Refs https://github.com/simonw/sqlite-utils/issues/769#issuecomment-4900034150 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8e015d024c
commit
404e935b63
4 changed files with 51 additions and 8 deletions
|
|
@ -193,7 +193,7 @@ Summary information about a column, see :ref:`python_api_analyze_column`.
|
|||
"""
|
||||
|
||||
|
||||
@dataclass(order=True)
|
||||
@dataclass(order=True, frozen=True)
|
||||
class ForeignKey:
|
||||
"""
|
||||
A foreign key defined on a table.
|
||||
|
|
@ -208,6 +208,11 @@ class ForeignKey:
|
|||
``on_delete`` and ``on_update`` hold the foreign key actions, e.g.
|
||||
``"CASCADE"`` - ``"NO ACTION"`` if not set.
|
||||
|
||||
Instances are immutable and hashable, so they can be collected into
|
||||
sets and used as dictionary keys. Equality covers every compared field,
|
||||
including ``on_delete`` and ``on_update`` - two foreign keys differing
|
||||
only in their actions are different constraints.
|
||||
|
||||
Prior to sqlite-utils 4.0 this was a ``namedtuple`` and could be unpacked
|
||||
or indexed as ``(table, column, other_table, other_column)``. It is now a
|
||||
dataclass - access its fields by name instead.
|
||||
|
|
@ -227,16 +232,21 @@ class ForeignKey:
|
|||
|
||||
def __post_init__(self):
|
||||
# Populate columns/other_columns for single-column foreign keys,
|
||||
# normalizing any lists to tuples
|
||||
# normalizing any lists to tuples. object.__setattr__ because the
|
||||
# dataclass is frozen
|
||||
if self.columns:
|
||||
self.columns = tuple(self.columns)
|
||||
object.__setattr__(self, "columns", tuple(self.columns))
|
||||
else:
|
||||
self.columns = (self.column,) if self.column is not None else ()
|
||||
object.__setattr__(
|
||||
self, "columns", (self.column,) if self.column is not None else ()
|
||||
)
|
||||
if self.other_columns:
|
||||
self.other_columns = tuple(self.other_columns)
|
||||
object.__setattr__(self, "other_columns", tuple(self.other_columns))
|
||||
else:
|
||||
self.other_columns = (
|
||||
(self.other_column,) if self.other_column is not None else ()
|
||||
object.__setattr__(
|
||||
self,
|
||||
"other_columns",
|
||||
(self.other_column,) if self.other_column is not None else (),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue