edelooff / sqlalchemy-json

Full-featured JSON type with mutation tracking for SQLAlchemy
http://variable-scope.com/posts/mutation-tracking-in-nested-json-structures-using-sqlalchemy
BSD 2-Clause "Simplified" License
189 stars 34 forks source link

Pickle throws TypeError #47

Closed msebas closed 1 year ago

msebas commented 1 year ago

Hello,

I have a few DB objects i want to move around, meaning I have to pickle the actual instances. I discovered that when the Classes contain a NestedMutableJson column the pickle fails with the error message TypeError: cannot pickle 'weakref' object.

I reduced it to the following test code:

import pickle
from sqlalchemy.orm import registry
from sqlalchemy import Column, BigInteger
from sqlalchemy.orm import relationship, deferred
from sqlalchemy_json import NestedMutableJson

mapper_registry_conf = registry()
ConfBase = mapper_registry_conf.generate_base()
class Test(ConfBase):
    __tablename__ = 'test'
    id = Column(BigInteger(), primary_key=True)
    data = Column(NestedMutableJson)

Now if I create an instance with data=None it works fine:

In [2]: pickle.dumps(Test(id=1,data=None))
Out[2]: b'\x80\x04\x95[\x01\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x04Test\x94\x93\x94)\x81\x94}\x94(\x8c\x12_sa_instance_state\x94\x8c\x14sqlalchemy.orm.state\x94\x8c\rInstanceState\x94\x93\x94)\x81\x94}\x94(\x8c\x08instance\x94h\x03\x8c\x0fcommitted_state\x94}\x94(\x8c\x02id\x94\x8c\x1bsqlalchemy.util.langhelpers\x94\x8c\x06symbol\x94\x93\x94\x8c\x08NO_VALUE\x94\x8c\x01x\x94\x8a\x08\xd3\xad\x9d\xec\x0c\xdceM\x87\x94R\x94\x8c\x04data\x94h\x15u\x8c\x08modified\x94\x88\x8c\x06class_\x94h\x02\x8c\x12expired_attributes\x94\x8f\x94\x8c\x07manager\x94\x8c\x1esqlalchemy.orm.instrumentation\x94\x8c\x11_SerializeManager\x94\x93\x94)\x81\x94}\x94h\x18h\x02sbubh\x0eK\x01h\x16Nub.'

But trying to pickle the instance with an (empty) dict fails:

In [3]: pickle.dumps(Test(id=1,data={}))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-e9731691560e> in <module>
----> 1 pickle.dumps(Test(id=1,data={}))

TypeError: cannot pickle 'weakref' object

The same happens when I use a list:

In [4]: pickle.dumps(Test(id=1,data=[]))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-9bfe292c9e9b> in <module>
----> 1 pickle.dumps(Test(id=1,data=[]))

TypeError: cannot pickle 'weakref' object

My version information. We are talking about a conda environment with python 3.9 on an actual openSuSE 15.4.

(test) msebas@C1168:~/workspace/test>pip list | grep -i sql
PyMySQL                       1.0.2
SQLAlchemy                    1.4.46
sqlalchemy-json               0.5.0
SQLAlchemy-Utils              0.40.0

Is there anything I am doing wrong or is this an inherent property of the lib?

msebas commented 1 year ago

Well, my fault. The git-master version 97c3ca8d5317eb49b56f4 works.