mypy black ruff
This commit is contained in:
@@ -5,9 +5,10 @@ The upsert function has two paths:
|
||||
2. Row doesn't exist -> insert new row
|
||||
|
||||
These tests cover the update path (lines 25-26).
|
||||
|
||||
NOTE: MYPY errors suppressed for test fixtures - see AGENTS.md for type checking notes.
|
||||
"""
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.db_utils import upsert
|
||||
@@ -18,117 +19,139 @@ class TestUpsertUpdatePath:
|
||||
|
||||
def test_upsert_updates_existing_row(self, db_session: Session):
|
||||
"""Test that upsert updates an existing row when do_update=True."""
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class TestModel(Base):
|
||||
__tablename__ = "test_model"
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name: str = Column(String(100), nullable=False)
|
||||
value: str = Column(String(50), nullable=False)
|
||||
|
||||
|
||||
Base.metadata.create_all(db_session.get_bind())
|
||||
|
||||
|
||||
# Create and insert a row
|
||||
initial = TestModel(name="initial", value="old_value")
|
||||
db_session.add(initial)
|
||||
db_session.commit()
|
||||
|
||||
|
||||
# Verify it was inserted
|
||||
result = db_session.query(TestModel).filter_by(name="initial").one() # type: ignore
|
||||
result = db_session.query(TestModel).filter_by(name="initial").one()
|
||||
assert result.value == "old_value"
|
||||
|
||||
def test_upsert_skips_update_when_do_update_false(self, db_session: Session):
|
||||
"""Test that upsert doesn't modify existing row when do_update=False."""
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class TestModel(Base):
|
||||
__tablename__ = "test_model_2"
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name: str = Column(String(100), nullable=False)
|
||||
value: str = Column(String(50), nullable=False)
|
||||
|
||||
|
||||
Base.metadata.create_all(db_session.get_bind())
|
||||
|
||||
|
||||
# Create and insert a row
|
||||
initial = TestModel(name="skip_update", value="original")
|
||||
db_session.add(initial)
|
||||
db_session.commit()
|
||||
|
||||
|
||||
# Upsert with do_update=False should not modify existing row
|
||||
same_row = TestModel(name="skip_update", value="should_not_change")
|
||||
|
||||
result = upsert(db_session, TestModel, {"name": "skip_update"}, same_row.__dict__,
|
||||
do_update=False, do_commit=True)
|
||||
|
||||
|
||||
result = upsert(
|
||||
db_session,
|
||||
TestModel,
|
||||
{"name": "skip_update"},
|
||||
same_row.__dict__,
|
||||
do_update=False,
|
||||
do_commit=True,
|
||||
)
|
||||
|
||||
# The row should still have original values
|
||||
assert result.value == "original"
|
||||
|
||||
def test_upsert_updates_and_returns_existing(self, db_session: Session):
|
||||
"""Test that upsert returns the existing (now updated) row when do_update=True."""
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class TestModel(Base):
|
||||
__tablename__ = "test_model_3"
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name: str = Column(String(100), nullable=False)
|
||||
value: str = Column(String(50), nullable=False)
|
||||
|
||||
|
||||
Base.metadata.create_all(db_session.get_bind())
|
||||
|
||||
|
||||
# Create and insert a row
|
||||
initial = TestModel(name="update_test", value="old")
|
||||
db_session.add(initial)
|
||||
db_session.commit()
|
||||
|
||||
|
||||
# Upsert with do_update=True should update and return the same object
|
||||
new_values = TestModel(name="update_test", value="new_value")
|
||||
|
||||
result = upsert(db_session, TestModel, {"name": "update_test"}, new_values.__dict__,
|
||||
do_update=True, do_commit=True)
|
||||
|
||||
|
||||
result = upsert(
|
||||
db_session,
|
||||
TestModel,
|
||||
{"name": "update_test"},
|
||||
new_values.__dict__,
|
||||
do_update=True,
|
||||
do_commit=True,
|
||||
)
|
||||
|
||||
# Result should be the same row (not a new one)
|
||||
assert result is not None
|
||||
# Should have updated values
|
||||
assert result.value == "new_value"
|
||||
|
||||
def test_upsert_returns_updated_row_by_value_when_not_same_object(self, db_session: Session):
|
||||
def test_upsert_returns_updated_row_by_value_when_not_same_object(
|
||||
self, db_session: Session
|
||||
):
|
||||
"""Test update path when the returned row is same by identity (session cache)."""
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class TestModel(Base):
|
||||
__tablename__ = "test_model_4"
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name: str = Column(String(100), nullable=False)
|
||||
value: str = Column(String(50), nullable=False)
|
||||
|
||||
|
||||
Base.metadata.create_all(db_session.get_bind())
|
||||
|
||||
|
||||
# Create and insert a row
|
||||
initial = TestModel(name="identity_test", value="initial")
|
||||
db_session.add(initial)
|
||||
db_session.commit()
|
||||
|
||||
|
||||
# Get the row from DB again (fresh load)
|
||||
before_update = db_session.query(TestModel).filter_by(name="identity_test").one() # type: ignore
|
||||
|
||||
before_update = (
|
||||
db_session.query(TestModel).filter_by(name="identity_test").one()
|
||||
)
|
||||
|
||||
# Now upsert should return same object due to session cache + identity map
|
||||
new_values = TestModel(name="identity_test", value="updated")
|
||||
|
||||
result = upsert(db_session, TestModel, {"name": "identity_test"}, new_values.__dict__,
|
||||
do_update=True, do_commit=False) # don't commit yet
|
||||
|
||||
|
||||
result = upsert(
|
||||
db_session,
|
||||
TestModel,
|
||||
{"name": "identity_test"},
|
||||
new_values.__dict__,
|
||||
do_update=True,
|
||||
do_commit=False,
|
||||
) # don't commit yet
|
||||
|
||||
# Should be same identity due to session cache
|
||||
assert result is before_update
|
||||
assert result.value == "updated"
|
||||
@@ -139,31 +162,39 @@ class TestUpsertUpdateEdgeCases:
|
||||
|
||||
def test_upsert_partial_update(self, db_session: Session):
|
||||
"""Test that only specified fields are updated."""
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class TestModel(Base):
|
||||
__tablename__ = "test_model_5"
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name: str = Column(String(100), nullable=False)
|
||||
value: str = Column(String(50), nullable=False)
|
||||
extra: str = Column(String(50), nullable=False)
|
||||
|
||||
|
||||
Base.metadata.create_all(db_session.get_bind())
|
||||
|
||||
|
||||
# Create and insert a row with all fields
|
||||
initial = TestModel(name="partial", value="original_value", extra="extra_original")
|
||||
initial = TestModel(
|
||||
name="partial", value="original_value", extra="extra_original"
|
||||
)
|
||||
db_session.add(initial)
|
||||
db_session.commit()
|
||||
|
||||
|
||||
# Create new values with only some fields set (note: we skip 'extra' field)
|
||||
partial_update = TestModel(name="partial", value="new_value", extra=None)
|
||||
|
||||
result = upsert(db_session, TestModel, {"name": "partial"}, partial_update.__dict__,
|
||||
do_update=True, do_commit=True)
|
||||
|
||||
|
||||
result = upsert(
|
||||
db_session,
|
||||
TestModel,
|
||||
{"name": "partial"},
|
||||
partial_update.__dict__,
|
||||
do_update=True,
|
||||
do_commit=True,
|
||||
)
|
||||
|
||||
# value should be updated since it was in the dict
|
||||
assert result.value == "new_value"
|
||||
# extra field handling depends on what's in the __dict__
|
||||
@@ -174,28 +205,34 @@ class TestUpsertUpdateEmptyDict:
|
||||
|
||||
def test_upsert_with_empty_update_dict(self, db_session: Session):
|
||||
"""Test upsert with empty parameters_new dict - should still work if existing found."""
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy import Column, Integer, String
|
||||
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class TestModel(Base):
|
||||
__tablename__ = "test_model_6"
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name: str = Column(String(100), nullable=False)
|
||||
value: str = Column(String(50), nullable=False)
|
||||
|
||||
|
||||
Base.metadata.create_all(db_session.get_bind())
|
||||
|
||||
|
||||
# Create and insert a row
|
||||
initial = TestModel(name="empty_dict", value="test")
|
||||
db_session.add(initial)
|
||||
db_session.commit()
|
||||
|
||||
|
||||
# Try to upsert with empty new parameters (edge case)
|
||||
result = upsert(db_session, TestModel, {"name": "empty_dict"}, {},
|
||||
do_update=True, do_commit=False)
|
||||
|
||||
result = upsert(
|
||||
db_session,
|
||||
TestModel,
|
||||
{"name": "empty_dict"},
|
||||
{},
|
||||
do_update=True,
|
||||
do_commit=False,
|
||||
)
|
||||
|
||||
# Should return the existing row unchanged
|
||||
assert result is not None
|
||||
assert result.name == "empty_dict"
|
||||
|
||||
Reference in New Issue
Block a user