MongoEngine / MongoEngine/mongoengine

copy.deepcopy fails on mongoengine object

Open
#993 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4.3k
Forks
1.2k
Avg merge
4h 41m
Merged PRs (30d)
11

Description

self.shift = Shift.objects.get(id=shift_id)
self.presave = copy.deepcopy(self.shift)

throws the error:
#1091 self.error('Only accept a document object') in to_mongo() method of CachedReferenceField class defined in mongonengine/fields.py

this is my debugger:
http://snag.gy/svEOT.jpg


*my model:*

``` python
class Shift(Document):  
    parent      = ReferenceField('Shift')  # shift parent ID, if we have type=reschedule or reassigned
    type        = StringField(max_length=50, required=True, choices=['regular', 'holiday', 'newshift', 'reschedule', 'reassignment'])
    date        = DateTimeField() #only if exception is created
    school      = ReferenceField(School, required=True)
    location    = ReferenceField(Location, required=True)
    guard       = ReferenceField(Guard, required=True) #only if exception is created
    name        = StringField(max_length=255)
    weekday     = IntField(required=True, min_value=1, max_value=7)  # isoweekday, Monday = 1
    start       = TimeField(required=True)
    finish      = TimeField(required=True)
    start_sec   = IntField(required=True)
    finish_sec  = IntField(required=True)
    weight      = IntField(required=True) # used for sorting - this is hh_mm_ss for local of this school timezone
    holidays    = ListField(DateTimeField()) # only for regular shift, let's not create a custom exception for each holiday date
    comment     = StringField(max_length=2000)
    created_at  = DateTimeField()
    updated_at  = DateTimeField()
    deactivated_at = DateTimeField()

    # speed up fields
    guard_name  = StringField(max_length=515)
    guard_phone = StringField(max_length=255)
    school_name = StringField(max_length=255)
    location_name = StringField(max_length=255)
    parent_cache = CachedReferenceField('Shift', fields=['type', 'start', 'finish', 'start_sec', 'finish_sec', 'guard', 'weight'])

    @property
    def assigned_guard(self):
        return self.guard

    @property
    def holiday(self):
        if self.date in self.holidays:
            return True
        return False

    def confirmations(self, date=None):
        if date:
            return Confirmation.objects(date=date, shift=self)
        else:
            return Confirmation.objects(shift=self)

    def exceptions(self, date=None):
        """

        :param date: should be of datetime.date type
        :return:
        """
        if self.parent:
            return list()

        if isinstance(date, datetime.date):
            date = todatetime(date)

        if date:
            return Shift.objects(parent=self, date=date)
        else:
            return Shift.objects(parent=self)


    def notify(self, message=None, guard=None, type=None):
        """
        Used to notify guard about new shift assigned to him
        """
        from bll.mobile_notifications import ShiftPushNotification
        ShiftPushNotification(self, message=message, guard=guard, type=type).send()    

    def delete(self, *args, **kwargs):
        """
        Override delete method, so that we mark that physical record in DB as deactivated_at
        instead of physically removing it
        also send DELETE signal for other collections to handle CASCADE/NULLIFY properly
        """
        self.deactivated_at = datetime.datetime.now()
        signals.pre_delete.send(self.__class__, document=self)
        return super(Shift, self).save(*args, **kwargs)

    def to_json(self):
        return {
            'id': self.id,
            'guard': self.guard,
            'name': self.name,
            'start': self.start,
            'finish': self.finish,
            'weekday': self.weekday,
            'type': self.type
        }


    def __str__(self):
        return str(self.id)

    meta = {
        'indexes': [
            {'fields': ['+name']},
            {'fields': ['+date', 'location']},
            {'fields': ['+date','+school', '+location']},
            {'fields': ['+location']},
            {'fields': ['+guard']},
            {'fields': ['+parent']},
            {'fields': ['+parent_cache.guard']},
        ]
    }

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the deepcopy reproduction in the issue and inspect CachedReferenceField.to_mongo() in mongoengine/fields.py, especially the path reported at error #1091. Determine the expected deepcopy behavior for the Shift document and verify that the reproduction no longer raises the reported error.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, python
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.