def insert(self, input):
     if type(input) is OrderedDict:
         self._insert(input)
     elif type(input) is list:
         all_ids = set()
         for i in input:
             if '_id' in i:
                 if not self.options.object_field_order_matters and type(i['_id']) is HashableOrderedDict:
                     i['_id'] = HashableOrderedDict(sorted(i['_id'].items(), key=lambda (key, value): key))
                 if i['_id'] in all_ids:
                     # print i['_id']
                     raise MongoModelException("Duplicated value not allowed by unique index", code=11000)
                 all_ids.add(i['_id'])
         # All '_id's are good
         buffer = []
         # keep in mind when inserting many docs at once, the operation needs to be atomic, i.e. all or nothing.
         for doc in input:
             if '_id' not in doc:
                 doc['_id'] = gen.random_object_id()
             buffer.append(doc)
             tmp = self.data.values() + buffer
             for index in self.indexes:
                 index.validate_and_build_entry(tmp)
         # Ready to insert them all.
         for doc in buffer:
             self.data[doc['_id']] = deepcopy(doc)
     else:
         raise MongoModelException("Tried to insert an unordered document.")
 def _insert(self, doc):
     if '_id' not in doc:
         doc['_id'] = gen.random_object_id()
     tmp = self.data.values() + [doc]
     for index in self.indexes:
         index.validate_and_build_entry(tmp)
     self.data[doc['_id']] = deepcopy(doc)
 def _insert(self, doc):
     if '_id' not in doc:
         doc['_id'] = gen.random_object_id()
     self.data[doc['_id']] = deepcopy(doc)
    def update(self, query, update, upsert, multi):
        if self.has_operator_expressions(
                update) and not self.check_fields(update):
            raise MongoModelException(
                'Cannot apply different update operation to the same field.')
        if len(query) == 0:
            return
        key = query.keys()[0]
        any = False
        old_data = deepcopy(self.data)
        n = 0
        try:
            for k, item in self.data.iteritems():
                if evaluate(key, query[key], item, self.options):
                    any = True
                    n += 1
                    # print "Result: ", item
                    if len(update) > 0:
                        self.process_update_operator(k, update)
                        if not multi:
                            return
                    else:
                        self.replace(k, update)
                        if not multi:
                            return
        except MongoModelException as e:
            self.data = old_data
            raise

        # need to create a new doc
        if upsert and not any:
            n += 1
            if self.has_operator_expressions(update):
                new_id = None
                try:
                    # this case break determinism when tested against non-model things
                    if "_id" not in query:
                        new_id = gen.random_object_id()
                    else:
                        new_id = query["_id"]
                    if has_operator(query):
                        #                        self.data[new_id] = deepcopy(self.transformOperatorQueryToUpsert(query))
                        self.data[new_id] = deepcopy(
                            self.
                            transform_operator_query_to_updatable_document(
                                query))
                    else:
                        self.data[new_id] = OrderedDict(query)

                    if self.data[new_id] is not None:
                        self.data[new_id]['_id'] = new_id
                        self.process_update_operator(new_id,
                                                     update,
                                                     new_doc=True)
                    else:
                        del self.data[new_id]
                except MongoModelException as e:
                    # print "delete new_id", new_id, "because of the exception"
                    if new_id in self.data:
                        del self.data[new_id]
                    raise e
            else:
                if "_id" in query:
                    update["_id"] = query["_id"]
                self.insert(update)
        else:
            # mongoDB raise an exception for the '$setOnInsert' update operator even if the upsert is False
            if '$setOnInsert' in update.keys() and len(
                    update['$setOnInsert']) == 0:
                raise MongoModelException(
                    "'$setOnInsert' is empty. You must specify a field like so: {$mod: {<field>: ...}}"
                )
        return {'n': n}