PickleType is broken in SQLAlchemy 0.6 python 3.1

Issue #1581 resolved
Former user created an issue

The following code doesn't work (last line throws).

from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, String, Boolean
from sqlalchemy import MetaData, ForeignKey, PickleType, UniqueConstraint
from sqlalchemy.orm import relation, backref
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class SomeEntity(Base):
    __tablename__ = 'some_entity'
    id = Column(Integer, primary_key=True)
    attributes = Column(PickleType)


url='sqlite:///:memory:'
engine = create_engine(url)
metadata = Base.metadata
metadata.create_all(engine)
Sessioner = sessionmaker(bind=engine)
session = Sessioner()

# Just set the attribute to save it
s = SomeEntity(attributes={'baked': 'beans', 'spam': 'ham'})
session.add(s)
session.commit()

print(s.id)

# a query throws an exception!
items = list(session.query(SomeEntity))

The following exception occurs:

Traceback (most recent call last):
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\attributes.py", line 366, i
n get
    return dict_[self.key](self.key)
KeyError: 'id'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "F:\Documents and Settings\Yuv\My Documents\Graphine\mainline\graph\tempy
.py", line 36, in <module>
    print(s.id)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\attributes.py", line 158, i
n __get__
    return self.impl.get(instance_state(instance), instance_dict(instance))
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\attributes.py", line 377, i
n get
    value = callable_(passive=passive)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\state.py", line 195, in __c
all__
    attr.impl.key for attr in class_manager.attributes if
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\mapper.py", line 1870, in _
load_scalar_attributes
    result = session.query(mapper)._get(identity_key, refresh_state=state, only_
load_props=attribute_names)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\query.py", line 1449, in _g
et
    return q.all()[0](0)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\query.py", line 1218, in al
l
    return list(self)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\query.py", line 1369, in in
stances
    rows = [process[0](process[0)(context, row) for row in fetch]
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\query.py", line 1369, in <l
istcomp>
    rows = [process[0](process[0)(context, row) for row in fetch]
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\query.py", line 2002, in ma
in
    return _instance(row, None)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\mapper.py", line 1721, in _
instance
    populate_state(state, dict_, row, isnew, only_load_props)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\mapper.py", line 1610, in p
opulate_state
    populator(state, dict_, row, isnew=isnew, **flags)
  File "F:\Python31\lib\site-packages\sqlalchemy\orm\strategies.py", line 118, i
n new_execute
    dict_[key](key) = row[col](col)
  File "F:\Python31\lib\site-packages\sqlalchemy\engine\base.py", line 1544, in
__getitem__
    return self.__parent._get_col(self.__row, key)
  File "F:\Python31\lib\site-packages\sqlalchemy\engine\base.py", line 1918, in
_get_col
    return processor(row[index](index))
  File "F:\Python31\lib\site-packages\sqlalchemy\types.py", line 303, in process

    return self.process_result_value(impl_processor(value), dialect)
  File "F:\Python31\lib\site-packages\sqlalchemy\types.py", line 849, in process
_result_value
    return loads(value)
  File "F:\Python31\lib\pickle.py", line 1369, in loads
    raise TypeError("Can't load pickle from unicode string")
TypeError: Can't load pickle from unicode string

inspecting the exception, the binary pickle is encapsulated in a unicode string.

Adding an 'eval' in "process_result_value" in PickleType in types.py solves the problem but I'm assuming this whole fiasco needs to be treated elsewhere.

    def process_result_value(self, value, dialect):

        loads = self.pickler.loads
        if value is None:
            return None
# start Py3K
        return loads(value)
        #return loads(eval(value)) # bad solution that works

--yuv (ubershmekel at gmail)

Comments (4)

  1. Log in to comment