MutableDict does not detect pop call

Issue #3605 resolved
Radek Miček created an issue

Running the following code

import sys
import sqlalchemy
from sqlalchemy import Table, Column, Integer, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.mutable import MutableDict
from sqlalchemy.types import TypeDecorator, VARCHAR
import json

class JSONEncodedDict(TypeDecorator):
    impl = VARCHAR

    def process_bind_param(self, value, dialect):
        if value is not None:
            value = json.dumps(value)
        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            value = json.loads(value)
        return value

Base = declarative_base()

class MyDataClass(Base):
    __tablename__ = 'my_data'
    id = Column(Integer, primary_key=True)
    data = Column(MutableDict.as_mutable(JSONEncodedDict))

engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=engine)
sess = Session()

Base.metadata.create_all(engine)

m1 = MyDataClass(data={'value1':'foo'})
sess.add(m1)
sess.commit()

print('sys', sys.version)
print('SQLAlchemy', sqlalchemy.__version__)

m1.data['value1'] = 'bar'
assert m1 in sess.dirty, 'dirty after assignment'
sess.commit()

m1.data.pop('value1')
assert m1 in sess.dirty, 'dirty after pop'

results in AssertionError raised on its last line

('sys', '2.7.3 (default, Mar 13 2014, 11:03:55) \n[GCC 4.7.2]')
('SQLAlchemy', '1.0.9')
Traceback (most recent call last):
  File "mut.py", line 48, in <module>
    assert m1 in sess.dirty, 'dirty after pop'
AssertionError: dirty after pop

Comments (9)

  1. Valentin Kaplov

    The method MutableDict.pop() doesn't accept 'default' parameter, that has builtin dict.pop method. The next code will raise an error:

    from sqlalchemy.ext.mutable import MutableDict
    d = MutableDict()
    d.pop('1', None) # Should return None, because of default=None has been passed 
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: pop() takes exactly 2 arguments (3 given)
    
  2. Log in to comment