def _pre_save(self): if getattr(self, "_id", None) is None: # Don't bother saving a connection that already exists, or that has a more precise link already samelink = Link().load({"refs": self.refs}) if samelink and not self.auto and self.type and not samelink.type: samelink.type = self.type samelink.save() raise DuplicateRecordError( u"Updated existing link with new type: {}".format( self.type)) elif samelink: #logger.debug("save_link: Same link exists: " + samelink["refs"][1]) raise DuplicateRecordError( "This connection already exists. Try editing instead.") else: preciselink = Link().load({ '$and': [{ 'refs': self.refs[0] }, { 'refs': { '$regex': text.Ref(self.refs[1]).regex() } }] }) if preciselink: # logger.debug("save_link: More specific link exists: " + link["refs"][1] + " and " + preciselink["refs"][1]) raise DuplicateRecordError( u"A more precise link already exists: {}".format( preciselink.refs[1]))
def _pre_save(self): if getattr(self, "_id", None) is None: # Don't bother saving a connection that already exists, or that has a more precise link already # will also find the same link with the two refs reversed samelink = Link().load({ "$or": [{ "refs": self.refs }, { "refs": [self.refs[1], self.refs[0]] }] }) if samelink: if not self.auto and self.type and not samelink.type: samelink.type = self.type samelink.save() raise DuplicateRecordError( "Updated existing link with new type: {}".format( self.type)) elif self.auto and not samelink.auto: samelink.auto = self.auto samelink.generated_by = self.generated_by samelink.source_text_oid = self.source_text_oid samelink.type = self.type samelink.refs = self.refs #in case the refs are reversed. switch them around samelink.save() raise DuplicateRecordError( "Updated existing link with auto generation data {} - {}" .format(self.refs[0], self.refs[1])) else: raise DuplicateRecordError( "Link already exists {} - {}. Try editing instead.". format(self.refs[0], self.refs[1])) else: #find a potential link that already has a more precise ref of either of this link's refs. preciselink = Link().load({ '$and': [ text.Ref(self.refs[0]).ref_regex_query(), text.Ref(self.refs[1]).ref_regex_query() ] }) if preciselink: # logger.debug("save_link: More specific link exists: " + link["refs"][1] + " and " + preciselink["refs"][1]) raise DuplicateRecordError( "A more precise link already exists: {} - {}".format( preciselink.refs[0], preciselink.refs[1])) # else: # this is a good new link if not getattr(self, "_skip_lang_check", False): self._set_available_langs() if not getattr(self, "_skip_expanded_refs_set", False): self._set_expanded_refs()
def _pre_save(self): if getattr(self, "_id", None) is None: # Don't bother saving a connection that already exists, or that has a more precise link already # will also find the same link with the two refs reversed samelink = Link().load({ "$or": [{ "refs": self.refs }, { "refs": [self.refs[1], self.refs[0]] }] }) if samelink: if not self.auto and self.type and not samelink.type: samelink.type = self.type samelink.save() raise DuplicateRecordError( u"Updated existing link with new type: {}".format( self.type)) elif self.auto and not samelink.auto: samelink.auto = self.auto samelink.generated_by = self.generated_by samelink.source_text_oid = self.source_text_oid samelink.refs = self.refs #in case the refs are reversed. switch them around samelink.save() raise DuplicateRecordError( u"Updated existing link with auto generation data {} - {}" .format(self.refs[0], self.refs[1])) else: raise DuplicateRecordError( u"Link already exists {} - {}. Try editing instead.". format(self.refs[0], self.refs[1])) else: preciselink = Link().load({ '$and': [{ 'refs': self.refs[0] }, { 'refs': { '$regex': text.Ref(self.refs[1]).regex() } }] }) if preciselink: # logger.debug("save_link: More specific link exists: " + link["refs"][1] + " and " + preciselink["refs"][1]) raise DuplicateRecordError( u"A more precise link already exists: {}".format( preciselink.refs[1]))
def _pre_save(self): if getattr(self, "_id", None) is None: # check for duplicates query = { "linkType": self.linkType, "ref": self.ref, "toTopic": self.toTopic, "dataSource": getattr(self, 'dataSource', {"$exists": False}), "class": getattr(self, 'class') } if getattr(self, "charLevelData", None): query["charLevelData.startChar"] = self.charLevelData[ 'startChar'] query["charLevelData.endChar"] = self.charLevelData['endChar'] query["charLevelData.versionTitle"] = self.charLevelData[ 'versionTitle'] query["charLevelData.language"] = self.charLevelData[ 'language'] duplicate = RefTopicLink().load(query) if duplicate is not None: raise DuplicateRecordError( "Duplicate ref topic link for linkType '{}', ref '{}', toTopic '{}', dataSource '{}'" .format(self.linkType, self.ref, self.toTopic, getattr(self, 'dataSource', 'N/A')))
def _pre_save(self): if getattr(self, "_id", None) is None: # check for duplicates duplicate = RefTopicLink().load( {"linkType": self.linkType, "ref": self.ref, "toTopic": self.toTopic, "dataSource": getattr(self, 'dataSource', {"$exists": False}), "class": getattr(self, 'class')}) if duplicate is not None: raise DuplicateRecordError("Duplicate ref topic link for linkType '{}', ref '{}', toTopic '{}', dataSource '{}'".format( self.linkType, self.ref, self.toTopic, getattr(self, 'dataSource', 'N/A')))
def _validate(self): super(IntraTopicLink, self)._validate() # check everything exists link_type = TopicLinkType().load({"slug": self.linkType}) assert link_type is not None, "Link type '{}' does not exist".format(self.linkType) from_topic = Topic.init(self.fromTopic) assert from_topic is not None, "fromTopic '{}' does not exist".format(self.fromTopic) to_topic = Topic.init(self.toTopic) assert to_topic is not None, "toTopic '{}' does not exist".format(self.toTopic) data_source = TopicDataSource().load({"slug": self.dataSource}) assert data_source is not None, "dataSource '{}' does not exist".format(self.dataSource) # check for duplicates duplicate = IntraTopicLink().load({"linkType": self.linkType, "fromTopic": self.fromTopic, "toTopic": self.toTopic, "class": getattr(self, 'class'), "_id": {"$ne": getattr(self, "_id", None)}}) if duplicate is not None: raise DuplicateRecordError( "Duplicate intra topic link for linkType '{}', fromTopic '{}', toTopic '{}'".format( self.linkType, self.fromTopic, self.toTopic)) if link_type.slug == link_type.inverseSlug: duplicate_inverse = IntraTopicLink().load({"linkType": self.linkType, "toTopic": self.fromTopic, "fromTopic": self.toTopic, "class": getattr(self, 'class'), "_id": {"$ne": getattr(self, "_id", None)}}) if duplicate_inverse is not None: raise DuplicateRecordError( "Duplicate intra topic link in the inverse direction of the symmetric linkType '{}', fromTopic '{}', toTopic '{}' exists".format( duplicate_inverse.linkType, duplicate_inverse.fromTopic, duplicate_inverse.toTopic)) # check types of topics are valid according to validFrom/To if getattr(link_type, 'validFrom', False): assert from_topic.has_types(set(link_type.validFrom)), "from topic '{}' does not have valid types '{}' for link type '{}'. Instead, types are '{}'".format(self.fromTopic, ', '.join(link_type.validFrom), self.linkType, ', '.join(from_topic.get_types())) if getattr(link_type, 'validTo', False): assert to_topic.has_types(set(link_type.validTo)), "to topic '{}' does not have valid types '{}' for link type '{}'. Instead, types are '{}'".format(self.toTopic, ', '.join(link_type.validTo), self.linkType, ', '.join(to_topic.get_types())) # assert this link doesn't create circular paths (in is_a link type) # should consider this test also for other non-symmetric link types such as child-of if self.linkType == TopicLinkType.isa_type: to_topic = Topic.init(self.toTopic) ancestors = to_topic.get_types() assert self.fromTopic not in ancestors, "{} is an is-a ancestor of {} creating an illogical circle in the topics graph, here are {} ancestors: {}".format(self.fromTopic, self.toTopic, self.toTopic, ancestors)
def _pre_save(self): self.expanded_refs = list(set(self.expanded_refs)) # clear out duplicates # make sure we're not adding duplicates manuscript_id, page_id = getattr(self, 'manuscript_slug', None), getattr(self, 'page_id', None) if manuscript_id is None or page_id is None: # important to check for None explicitly, page_id=0 is valid raise ManuscriptError('No manuscript_id or page_id') if self.is_new(): duplicate = ManuscriptPage().load({ 'manuscript_id': manuscript_id, 'page_id': page_id }) if duplicate: raise DuplicateRecordError("Record already exists. Please update existing instead of adding new.")
def normalize_slug_field(self, slug_field: str) -> str: """ Duplicates are forbidden for Manuscript slugs. Character normalization only, duplicates raise a DuplicateRecordError :param slug_field: not an attribute, this should just be a string that will be normalized. :return: normalized string """ slug = self.normalize_slug(slug_field) mongo_id = getattr(self, '_id', None) duplicate = getattr(db, self.collection).find_one({'slug': slug, "_id": {"$ne": mongo_id}}) if duplicate: raise DuplicateRecordError(f"Record with the title {slug_field} already exists") return slug
def _pre_save(self): if getattr(self, "_id", None) is None: # Don't bother saving a connection that already exists, or that has a more precise link already if self.refs != sorted(self.refs) and hasattr( self, 'charLevelData'): self.charLevelData.reverse() orig_refs = self.refs self.refs = sorted( self.refs) #make sure ref order is deterministic if orig_refs != self.refs and getattr( self, "versions", False) and getattr( self, "displayedText", False): #if reversed self.refs, make sure to reverse self.versions and self.displayedText self.versions = self.versions[::-1] self.displayedText = self.displayedText[::-1] samelink = Link().load({"refs": self.refs}) if samelink: if hasattr(self, 'score') and hasattr(self, 'charLevelData'): samelink.score = self.score samelink.charLevelData = self.charLevelData raise DuplicateRecordError( "Updated existing link with the new score and charLevelData data" ) elif not self.auto and self.type and not samelink.type: samelink.type = self.type samelink.save() raise DuplicateRecordError( "Updated existing link with new type: {}".format( self.type)) elif self.auto and not samelink.auto: samelink.auto = self.auto samelink.generated_by = self.generated_by samelink.source_text_oid = self.source_text_oid samelink.type = self.type samelink.refs = self.refs #in case the refs are reversed. switch them around samelink.save() raise DuplicateRecordError( "Updated existing link with auto generation data {} - {}" .format(self.refs[0], self.refs[1])) else: raise DuplicateRecordError( "Link already exists {} - {}. Try editing instead.". format(self.refs[0], self.refs[1])) else: #find a potential link that already has a more precise ref of either of this link's refs. preciselink = Link().load({ '$and': [ text.Ref(self.refs[0]).ref_regex_query(), text.Ref(self.refs[1]).ref_regex_query() ] }) if preciselink: # logger.debug("save_link: More specific link exists: " + link["refs"][1] + " and " + preciselink["refs"][1]) raise DuplicateRecordError( "A more precise link already exists: {} - {}".format( preciselink.refs[0], preciselink.refs[1])) # else: # this is a good new link if not getattr(self, "_skip_lang_check", False): self._set_available_langs() if not getattr(self, "_skip_expanded_refs_set", False): self._set_expanded_refs()
def _pre_save(self): if getattr(self, "_id", None) is None: # Don't bother saving a connection that already exists, or that has a more precise link already if self.refs != sorted(self.refs): if hasattr(self, 'charLevelData'): self.charLevelData.reverse() if getattr(self, "versions", False) and getattr( self, "displayedText", False): # if reversed self.refs, make sure to reverse self.versions and self.displayedText self.versions = self.versions[::-1] self.displayedText = self.displayedText[::-1] self.refs = sorted( self.refs) # make sure ref order is deterministic samelink = Link().load({"refs": self.refs}) if not samelink: #check for samelink section level vs ranged ref oref0 = text.Ref(self.refs[0]) oref1 = text.Ref(self.refs[1]) section0 = oref0.section_ref() section1 = oref1.section_ref() if oref0.is_range() and oref0.all_segment_refs( ) == section0.all_segment_refs(): samelink = Link().load({ "$and": [{ "refs": section0.normal() }, { "refs": self.refs[1] }] }) elif oref0.is_section_level(): ranged0 = text.Ref( f"{oref0.all_segment_refs()[0]}-{oref0.all_segment_refs()[-1]}" ) samelink = Link().load({ "$and": [{ "refs": ranged0.normal() }, { "refs": self.refs[1] }] }) elif oref1.is_range() and oref1.all_segment_refs( ) == section1.all_segment_refs(): samelink = Link().load({ "$and": [{ "refs": section1.normal() }, { "refs": self.refs[0] }] }) elif oref1.is_section_level(): ranged1 = text.Ref( f"{oref1.all_segment_refs()[0]}-{oref1.all_segment_refs()[-1]}" ) samelink = Link().load({ "$and": [{ "refs": ranged1.normal() }, { "refs": self.refs[0] }] }) if samelink: if hasattr(self, 'score') and hasattr(self, 'charLevelData'): samelink.score = self.score samelink.charLevelData = self.charLevelData samelink.save() raise DuplicateRecordError( "Updated existing link with the new score and charLevelData data" ) elif not self.auto and self.type and not samelink.type: samelink.type = self.type samelink.save() raise DuplicateRecordError( "Updated existing link with new type: {}".format( self.type)) elif self.auto and not samelink.auto: samelink.auto = self.auto samelink.generated_by = self.generated_by samelink.source_text_oid = self.source_text_oid samelink.type = self.type samelink.refs = self.refs #in case the refs are reversed. switch them around samelink.save() raise DuplicateRecordError( "Updated existing link with auto generation data {} - {}" .format(self.refs[0], self.refs[1])) else: raise DuplicateRecordError( "Link already exists {} - {}. Try editing instead.". format(self.refs[0], self.refs[1])) else: #find a potential link that already has a more precise ref of either of this link's refs. preciselink = Link().load({ '$and': [ text.Ref(self.refs[0]).ref_regex_query(), text.Ref(self.refs[1]).ref_regex_query() ] }) if preciselink: # logger.debug("save_link: More specific link exists: " + link["refs"][1] + " and " + preciselink["refs"][1]) if getattr(self, "_override_preciselink", False): preciselink.delete() self.generated_by = self.generated_by + '_preciselink_override' #and the new link will be posted (supposedly) else: raise DuplicateRecordError( "A more precise link already exists: {} - {}". format(preciselink.refs[0], preciselink.refs[1])) # else: # this is a good new link if not getattr(self, "_skip_lang_check", False): self._set_available_langs() if not getattr(self, "_skip_expanded_refs_set", False): self._set_expanded_refs()