0

Let's say I have the following example:

from datetime import datetime
import dill
from pymongo import MongoClient
from umongo import Instance, Document, fields, validate

db = MongoClient().test
instance = Instance(db)

@instance.register
class User(Document):
    email = fields.EmailField(required=True, unique=True)
    birthday = fields.DateTimeField(validate=validate.Range(min=datetime(1900, 1, 1)))
    friends = fields.ListField(fields.ReferenceField("User"))

    class Meta:
        collection = db.user

User.ensure_indexes()

goku = User(email='goku@sayen.com', birthday=datetime(1984, 11, 20))
goku.commit()

found_goku = User.find_one({"email": 'goku@sayen.com'})
with open("dumped.dil", "wb") as out_file:
    dill.dump(found_goku, out_file)

This results in the following error on dill.dump:

_pickle.PicklingError: Can't pickle <Implementation class 'tests.test_serialize_umongo.User'>: it's not found as tests.test_serialize_umongo.User

I understand that I can not simply pickle a User because I can not pickle the database instance. I want to pickle a user to a Dict using umongo's dump and overriding __getstate__, but I do not know how to get around this it's not found aserror.

Anton
  • 1,314
  • 1
  • 12
  • 27
  • Can you post the full stacktrace? And are you running that exact sample to generate the exact error? I'm getting a different result than you. – Chris Larson Feb 15 '19 at 20:09

1 Answers1

1

If I understand you correctly, I believe what you're looking for is the following. In essence, we're using the document's own dump() method to pass the serialized document as the user to be pickled. The only difference here is the last line: dill.dump(found_goku.dump(), out_file):

from datetime import datetime
import dill
from pymongo import MongoClient
from umongo import Instance, Document, fields, validate

db = MongoClient().test
instance = Instance(db)

@instance.register
class User(Document):
    email = fields.EmailField(required=True, unique=True)
    birthday = fields.DateTimeField(validate=validate.Range(min=datetime(1900, 1, 1)))
    friends = fields.ListField(fields.ReferenceField("User"))

    class Meta:
        collection = db.user

User.ensure_indexes()

goku = User(email='goku@sayen.com', birthday=datetime(1984, 11, 20))
goku.commit()

found_goku = User.find_one({"email": 'goku@sayen.com'})
with open("dumped.dil", "wb") as out_file:
    dill.dump(found_goku.dump(), out_file)
Chris Larson
  • 1,684
  • 1
  • 11
  • 19
  • Thanks for this simple solution! Could you maybe add that you just need to call dump before the serialization? Otherwise It might not be clear what you added when looking at the block of code. – Anton Feb 18 '19 at 08:52