Migrated issue, originally created by Daniel Kolsoi (@TheDan64)
Python sets support common set operations as bitwise operators such as &=, |=, ^=, -=. The MutableSet class seems to fully support these operations as full methods (.intersection, .union, ...) but not bitwise operators.
This is unexpected since the bitwise operators do in fact modify the underlying set(due to inheriting from set), but since the .changed() method is not called by MutableSet, sqlalchemy is never notified that the data has been modified. This leads to the possibility of having a mutable set column which is modified locally but does not get updated on commit or flush.
For example,
from sqlalchemy.ext.mutable import MutableSet
from sqlalchemy.types import TypeDecorator, UnicodeText
class _JSONEncodedSet(TypeDecorator):
impl = UnicodeText
def process_bind_param(self, value, dialect):
if value is not None:
value = json.dumps(list(value))
return value
def process_result_value(self, value, dialect):
if value is not None:
value = set(json.loads(value))
return value
JSONEncodedSet = MutableSet.as_mutable(_JSONEncodedSet)
from sqlalchemy.ext.declarative import declarative_base
BaseModel = declarative_base()
class MyModel(BaseModel):
json_set = Column(JSONEncodedSet)
from sqlalchemy.orm import scoped_session, sessionmaker
from zope.sqlalchemy import ZopeTransactionExtension
session = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
session.add(MyModel(json_set={1, 2, 3}))
session.flush()
model = session.query(MyModel).first()
model.json_set &= {1, 3}
session.flush()
del model
model = session.query(MyModel).first()
assert model.json_set == {1, 3} # AssertionError
Similarly, MutableList doesn't seem to support += [1]
Tested in SqlAlchemy 1.1.3, Sqlite but doesn't seem to be DB specific.
Migrated issue, originally created by Daniel Kolsoi (@TheDan64)
Python sets support common set operations as bitwise operators such as &=, |=, ^=, -=. The MutableSet class seems to fully support these operations as full methods (.intersection, .union, ...) but not bitwise operators.
This is unexpected since the bitwise operators do in fact modify the underlying set(due to inheriting from set), but since the .changed() method is not called by MutableSet, sqlalchemy is never notified that the data has been modified. This leads to the possibility of having a mutable set column which is modified locally but does not get updated on commit or flush.
For example,
Similarly, MutableList doesn't seem to support += [1]
Tested in SqlAlchemy 1.1.3, Sqlite but doesn't seem to be DB specific.