def __setitem__(self, attr, val): if attr == "funmongo_subtype": self.actual_setitem(attr, val) return if not isinstance(attr, str): raise Exception(error_field_str(attr)) # checking if the field is expected or additional_fields is set if not attr in self.structure: if not hasattr_n_val(self, "additional_fields", True): raise Exception( error_unknown_field(self, attr, "Cannot set field ")) else: # checking that the value has the right type defined in structure if type(self.structure[attr]) is list: ok = False for typ in self.structure[attr]: if isinstance(val, typ): ok = True break if not ok: raise Exception(error_wrong_val_type(self, attr, val)) else: if not isinstance(val, self.structure[attr]): raise Exception(error_wrong_val_type(self, attr, val)) # checking that the field is not already set or that this field is mutable if attr in self.doc_items: if not hasattr_n_val(self, "all_mutable", True): if not hasattr(self, "mutable") or attr not in self.mutable: raise Exception(error_not_mutable(self, attr)) self.actual_setitem(attr, val)
def update_structure_if_needed(self): if not hasattr_n_val(type(self), "funmongo_already_done", True): if not hasattr(type(self), "structure"): type(self).structure = {} if not hasattr(type(self), "autoset"): type(self).autoset = {} if not hasattr(type(self), "indexes"): type(self).indexes = [] if not hasattr(type(self), "mutable"): type(self).mutable = [] type(self).funmongo_raw_structure = copy(type(self).structure) type(self).funmongo_already_done = False parents = find_valid_parent_docs(type(self)) self.check_child_same_module_as_parents(parents) if len(parents) > 0: type(self).funmongo_is_child = True if len(parents) > 1: type(self).funmongo_parents = parents type(self).indexes.append("funmongo_subtype") self.update_structure_with_parents(parents) for ind in type(self).indexes: if type(ind) is str: options["db"][self.collec].create_index(ind) else: options["db"][self.collec].create_index([ind]) type(self).funmongo_already_done = True
def validate(self): err = self.invalid_document() if err: raise Exception(err) self.update_structure_if_needed() is_child = hasattr_n_val(type(self), "funmongo_is_child", True) err = self.invalid_document() if err: raise Exception(err) # checking that autoset fields are not set, and setting them for key, func in type(self).autoset: if not key in self.doc_items: self[key] = func(self) for key, typ in self.structure.items(): if not key in self.doc_items: if hasattr_n_val(type(self), "can_be_incomplete", True): self.unsafe_set(key, None) continue else: raise Exception("Missing field : " + key + self.error_info()) if hasattr_n_val(type(self), "can_be_incomplete", True) and self.doc_items[key] is None: continue if type(typ) is list: ok = False for t in typ: if isinstance(self.doc_items[key], t): ok = True if not ok: raise Exception("Bad type for field " + key + self.error_info()) else: if not isinstance(self.doc_items[key], typ): raise Exception("Bad type for field " + key + self.error_info()) expected_nb_fields = len(self.structure.keys()) if is_child: expected_nb_fields += 1 if not hasattr_n_val(self, "additional_fields", True) and len( self.doc_items.keys()) != expected_nb_fields: for key in self.doc_items.keys(): if not key in self.structure and (not is_child or key != "funmongo_subtype"): raise Exception( error_unknown_field(self, key, "Invalid field "))
def find_valid_parent_docs(current_doc): parents = current_doc.__bases__ ret = [] for par in parents: if par is not Document: if hasattr_n_val(par, "is_funmongo_doc", True): ret.extend(find_valid_parent_docs(par)) ret.append(par) return list(set(ret))
def funmongo_init(self, args=None, unsafe=False): if args is None: args = {} self.update_structure_if_needed() self.doc_items = {} if hasattr_n_val(type(self), "funmongo_is_child", True): if hasattr(type(self), "funmongo_parents"): types = [type(self).__name__] for par in type(self).funmongo_parents: types.append(par.__name__) self["funmongo_subtype"] = types else: self["funmongo_subtype"] = type(self).__name__ for key, val in args.items(): if unsafe: self.unsafe_set(key, val) elif hasattr_n_val(type(self), "can_be_incomplete", True) and val is None: continue else: self[key] = val if hasattr(self, "init_func") and self.init_func: self.init_func()
def restrict_to_subtype(model, sel): if hasattr_n_val(model, "funmongo_is_child", True): sel["funmongo_subtype"] = model.__name__ return sel