def __init__(self, modelXbrl): self.modelXbrl = modelXbrl if modelXbrl.modelManager.validateDisclosureSystem: if modelXbrl.modelManager.disclosureSystem.HMRC: self.instValidator = ValidateHmrc.ValidateHmrc(modelXbrl) else: self.instValidator = ValidateFiling.ValidateFiling(modelXbrl) self.formulaValidator = ValidateXbrl.ValidateXbrl(modelXbrl) else: self.instValidator = ValidateXbrl.ValidateXbrl(modelXbrl) self.formulaValidator = self.instValidator
def __init__(self, modelXbrl): self.modelXbrl = modelXbrl if modelXbrl.modelManager.validateDisclosureSystem: self.instValidator = ValidateXbrl.ValidateXbrl(modelXbrl) self.formulaValidator = ValidateXbrl.ValidateXbrl(modelXbrl) else: self.instValidator = ValidateXbrl.ValidateXbrl(modelXbrl) self.formulaValidator = self.instValidator if hasattr(modelXbrl,"fileSource"): self.useFileSource = modelXbrl.fileSource else: self.useFileSource = None
def __init__(self, modelXbrl): self.modelXbrl = modelXbrl if modelXbrl.modelManager.validateDisclosureSystem: if modelXbrl.modelManager.disclosureSystem.HMRC: # deprecated non-plugin validator self.instValidator = ValidateHmrc.ValidateHmrc(modelXbrl) elif modelXbrl.modelManager.disclosureSystem.EFMorGFM or modelXbrl.modelManager.disclosureSystem.SBRNL: # deprecated non-plugin validator self.instValidator = ValidateFiling.ValidateFiling(modelXbrl) else: # custom validator, probably a plug-in self.instValidator = ValidateXbrl.ValidateXbrl(modelXbrl) self.formulaValidator = ValidateXbrl.ValidateXbrl(modelXbrl) else: self.instValidator = ValidateXbrl.ValidateXbrl(modelXbrl) self.formulaValidator = self.instValidator if hasattr(modelXbrl,"fileSource"): self.useFileSource = modelXbrl.fileSource else: self.useFileSource = None
def __init__(self, cntlr, isCmdLine=False): self.cntlr = cntlr # setup tester xml = "<rootElement/>" self.modelXbrl = ModelXbrl.create(cntlr.modelManager, ModelDocument.Type.UnknownNonXML, initialXml=xml, isEntry=True) self.validator = ValidateXbrl.ValidateXbrl(self.modelXbrl) self.validator.validate(self.modelXbrl) # required to set up cntlr.showStatus(_("Initializing Formula Grammar")) XPathParser.initializeParser(cntlr.modelManager) cntlr.showStatus(None) self.trRegs = sorted(ixtNamespaces.keys()) self.trPrefixNSs = dict((qn.prefix, qn.namespaceURI) for qn in self.modelXbrl.modelManager.customTransforms.keys()) self.trRegs.extend(sorted(self.trPrefixNSs.keys())) self.trPrefixNSs.update(ixtNamespaces)
def watchCycle(self): while not self.stopRequested: rssWatchOptions = self.rssModelXbrl.modelManager.rssWatchOptions # check rss expiration rssHeaders = self.cntlr.webCache.getheaders(self.rssModelXbrl.modelManager.rssWatchOptions.get("feedSourceUri")) expires = parseRfcDatetime(rssHeaders.get("expires")) reloadNow = True # texpires and expires > datetime.datetime.now() # reload rss feed self.rssModelXbrl.reload('checking RSS items', reloadCache=reloadNow) if self.stopRequested: break # setup validator postLoadActions = [] if rssWatchOptions.get("validateDisclosureSystemRules"): self.instValidator = ValidateFiling.ValidateFiling(self.rssModelXbrl) postLoadActions.append(_("validating")) elif rssWatchOptions.get("validateXbrlRules") or rssWatchOptions.get("validateFormulaAssertions"): self.instValidator = ValidateXbrl.ValidateXbrl(self.rssModelXbrl) postLoadActions.append(_("validating")) if (rssWatchOptions.get("validateFormulaAssertions")): postLoadActions.append(_("running formulas")) else: self.instValidator = None matchTextExpr = rssWatchOptions.get("matchTextExpr") if matchTextExpr: matchPattern = re.compile(matchTextExpr) postLoadActions.append(_("matching text")) else: matchPattern= None postLoadAction = ', '.join(postLoadActions) # anything to check new filings for if (rssWatchOptions.get("validateDisclosureSystemRules") or rssWatchOptions.get("validateXbrlRules") or rssWatchOptions.get("validateCalcLinkbase") or rssWatchOptions.get("validateFormulaAssertions") or rssWatchOptions.get("alertMatchedFactText") or any(pluginXbrlMethod(rssWatchOptions) for pluginXbrlMethod in pluginClassMethods("RssWatch.HasWatchAction")) ): # form keys in ascending order of pubdate pubDateRssItems = [] for rssItem in self.rssModelXbrl.modelDocument.rssItems: pubDateRssItems.append((rssItem.pubDate,rssItem.objectId())) for pubDate, rssItemObjectId in sorted(pubDateRssItems): rssItem = self.rssModelXbrl.modelObject(rssItemObjectId) # update ui thread via modelManager (running in background here) self.rssModelXbrl.modelManager.viewModelObject(self.rssModelXbrl, rssItem.objectId()) if self.stopRequested: break latestPubDate = XmlUtil.datetimeValue(rssWatchOptions.get("latestPubDate")) if (latestPubDate and rssItem.pubDate < latestPubDate): continue try: # try zipped URL if possible, else expanded instance document modelXbrl = ModelXbrl.load(self.rssModelXbrl.modelManager, openFileSource(rssItem.zippedUrl, self.cntlr), postLoadAction) if self.stopRequested: modelXbrl.close() break emailAlert = False if modelXbrl.modelDocument is None: modelXbrl.error("arelle.rssWatch", _("RSS item %(company)s %(form)s document not loaded: %(date)s"), modelXbrl=modelXbrl, company=rssItem.companyName, form=rssItem.formType, date=rssItem.filingDate) rssItem.status = "not loadable" else: # validate schema, linkbase, or instance if self.stopRequested: modelXbrl.close() break if self.instValidator: self.instValidator.validate(modelXbrl) if modelXbrl.errors and rssWatchOptions.get("alertValiditionError"): emailAlert = True for pluginXbrlMethod in pluginClassMethods("RssWatch.DoWatchAction"): pluginXbrlMethod(modelXbrl, rssWatchOptions, rssItem) # check match expression if matchPattern: for fact in modelXbrl.factsInInstance: v = fact.value if v is not None: m = matchPattern.search(v) if m: fr, to = m.span() msg = _("Fact Variable {0}\n context {1}\n matched text: {2}").format( fact.qname, fact.contextID, v[max(0,fr-20):to+20]) modelXbrl.info("arelle.rssInfo", msg, modelXbrl=modelXbrl) # msg as code passes it through to the status if rssWatchOptions.get("alertMatchedFactText"): emailAlert = True if (rssWatchOptions.get("formulaFileUri") and rssWatchOptions.get("validateFormulaAssertions") and self.instValidator): # attach formulas ModelDocument.load(modelXbrl, rssWatchOptions["formulaFileUri"]) ValidateFormula.validate(self.instValidator) rssItem.setResults(modelXbrl) modelXbrl.close() del modelXbrl # completely dereference self.rssModelXbrl.modelManager.viewModelObject(self.rssModelXbrl, rssItem.objectId()) if rssItem.assertionUnsuccessful and rssWatchOptions.get("alertAssertionUnsuccessful"): emailAlert = True msg = _("Filing CIK {0}\n " "company {1}\n " "published {2}\n " "form type {3}\n " "filing date {4}\n " "period {5}\n " "year end {6}\n " "results: {7}").format( rssItem.cikNumber, rssItem.companyName, rssItem.pubDate, rssItem.formType, rssItem.filingDate, rssItem.period, rssItem.fiscalYearEnd, rssItem.status) self.rssModelXbrl.info("arelle:rssWatch", msg, modelXbrl=self.rssModelXbrl) emailAddress = rssWatchOptions.get("emailAddress") if emailAlert and emailAddress: self.rssModelXbrl.modelManager.showStatus(_("sending e-mail alert")) import smtplib from email.mime.text import MIMEText emailMsg = MIMEText(msg) emailMsg["Subject"] = _("Arelle RSS Watch alert on {0}").format(rssItem.companyName) emailMsg["From"] = emailAddress emailMsg["To"] = emailAddress smtp = smtplib.SMTP() smtp.sendmail(emailAddress, [emailAddress], emailMsg.as_string()) smtp.quit() self.rssModelXbrl.modelManager.showStatus(_("RSS item {0}, {1} completed, status {2}").format(rssItem.companyName, rssItem.formType, rssItem.status), 3500) self.rssModelXbrl.modelManager.cntlr.rssWatchUpdateOption(rssItem.pubDate.strftime('%Y-%m-%dT%H:%M:%S')) except Exception as err: self.rssModelXbrl.error("arelle.rssError", _("RSS item %(company)s, %(form)s, %(date)s, exception: %(error)s"), modelXbrl=self.rssModelXbrl, company=rssItem.companyName, form=rssItem.formType, date=rssItem.filingDate, error=err, exc_info=True) if self.stopRequested: break if self.stopRequested: self.cntlr.showStatus(_("RSS watch, stop requested"), 10000) else: import time time.sleep(600) self.thread = None # close thread self.stopRequested = False
def validate(self, modelVersReport): self.modelVersReport = modelVersReport versReport = modelVersReport.modelDocument if not hasattr(versReport, "xmlDocument"): # not parsed return for DTSname in ("fromDTS", "toDTS"): DTSmodelXbrl = getattr(versReport, DTSname) if DTSmodelXbrl is None or DTSmodelXbrl.modelDocument is None: self.modelVersReport.error("vere:invalidDTSIdentifier", _("%(dts)s is missing or not loaded"), modelObject=self, dts=DTSname) else: # validate DTS ValidateXbrl.ValidateXbrl(DTSmodelXbrl).validate(DTSmodelXbrl) if len(DTSmodelXbrl.errors) > 0: self.modelVersReport.error("vere:invalidDTSIdentifier", _("%(dts) has errors: %(error)s"), modelObject=DTSmodelXbrl.modelDocument, dts=DTSname, error=DTSmodelXbrl.errors) # validate linkbases ValidateXbrl.ValidateXbrl(self.modelVersReport).validate(modelVersReport) versReportElt = versReport.xmlRootElement # check actions for assignmentRef in versReportElt.iterdescendants(tag="{http://xbrl.org/2010/versioning-base}assignmentRef"): ref = assignmentRef.get("ref") if ref not in versReport.idObjects or \ not isinstance(versReport.idObjects[ref], ModelVersObject.ModelAssignment): self.modelVersReport.error("vere:invalidAssignmentRef", _("AssignmentRef %(assignmentRef)s does not reference an assignment"), modelObject=assignmentRef, assignmentRef=ref) # check namespace renames for NSrename in versReport.namespaceRenameFrom.values(): if NSrename.fromURI not in versReport.fromDTS.namespaceDocs: self.modelVersReport.error("vere:invalidNamespaceMapping", _("NamespaceRename fromURI %(uri)s does not reference a schema in fromDTS"), modelObject=self, uri=NSrename.fromURI) if NSrename.toURI not in versReport.toDTS.namespaceDocs: self.modelVersReport.error("vere:invalidNamespaceMapping", _("NamespaceRename toURI %(uri)s does not reference a schema in toDTS"), modelObject=self, uri=NSrename.toURI) # check role changes for roleChange in versReport.roleChanges.values(): if roleChange.fromURI not in versReport.fromDTS.roleTypes: self.modelVersReport.error("vere:invalidRoleChange", _("RoleChange fromURI %(uri)s does not reference a roleType in fromDTS"), modelObject=self, uri=roleChange.fromURI) if roleChange.toURI not in versReport.toDTS.roleTypes: self.modelVersReport.error("vere:invalidRoleChange", _("RoleChange toURI %(uri)s does not reference a roleType in toDTS"), modelObject=self, uri=roleChange.toURI) # check reportRefs # check actions for reportRef in versReportElt.iterdescendants(tag="{http://xbrl.org/2010/versioning-base}reportRef"): xlinkType = reportRef.get("{http://www.w3.org/1999/xlink}type") if xlinkType != "simple": self.modelVersReport.error("vere:invalidXlinkType", _("ReportRef xlink:type %(xlinkType)s must be \"simple\""), modelObject=reportRef, xlinkType=xlinkType) # if existing it must be valid href = reportRef.get("{http://www.w3.org/1999/xlink}href") # TBD arcrole = reportRef.get("{http://www.w3.org/1999/xlink}arcrole") if arcrole is None: self.modelVersReport.error("vere:missingXlinkArcrole", _("ReportRef xlink:arcrole is missing"), modelObject=reportRef) else: if arcrole != "http://xbrl.org/arcrole/2010/versioning/related-report": self.modelVersReport.error("vere:invalidXlinkArcrole", _("ReportRef xlink:arcrole %(arcrole)s is invalid"), modelObject=reportRef, arcrole=arcrole) if versReport.fromDTS and versReport.toDTS: # check concept changes of concept basic for conceptChange in versReport.conceptBasicChanges: if conceptChange.name != "conceptAdd" and \ (conceptChange.fromConcept is None or \ conceptChange.fromConcept.qname not in versReport.fromDTS.qnameConcepts): self.modelVersReport.error("vercbe:invalidConceptReference", _("%(event)s fromConcept %(concept)s does not reference a concept in fromDTS"), modelObject=conceptChange, event=conceptChange.name, concept=conceptChange.fromConceptQname) if conceptChange.name != "conceptDelete" and \ (conceptChange.toConcept is None or \ conceptChange.toConcept.qname not in versReport.toDTS.qnameConcepts): self.modelVersReport.error("vercbe:invalidConceptReference", _("%(event)s toConcept %(concept)s does not reference a concept in toDTS"), modelObject=conceptChange, event=conceptChange.name, concept=conceptChange.toConceptQname) # check concept changes of concept extended for conceptChange in versReport.conceptExtendedChanges: fromConcept = conceptChange.fromConcept toConcept = conceptChange.toConcept fromResource = conceptChange.fromResource toResource = conceptChange.toResource # fromConcept checks if not conceptChange.name.endswith("Add"): if not fromConcept is not None: self.modelVersReport.error("vercbe:invalidConceptReference", _("%(action)s %(event)s fromConcept %(concept)s does not reference a concept in fromDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, concept=conceptChange.fromConceptQname) # tuple check elif _("Child") in conceptChange.name and \ not versReport.fromDTS.qnameConcepts[fromConcept.qname] \ .isTuple: self.modelVersReport.error("vercbe:invalidConceptReference", _("%(action)s %(event)s fromConcept %(concept)s must be defined as a tuple"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, concept=conceptChange.fromConceptQname) # resource check elif "Label" in conceptChange.name: if fromResource is None: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s fromResource %(resource)s does not reference a resource in fromDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue) else: relationship = fromConcept.relationshipToResource(fromResource, XbrlConst.conceptLabel) if relationship is not None: if relationship.qname != XbrlConst.qnLinkLabelArc or \ relationship.parentQname != XbrlConst.qnLinkLabelLink or \ fromResource.qname != XbrlConst.qnLinkLabel: self.modelVersReport.error("vercee:invalidConceptLabelIdentifier", _("%(action)s %(event)s fromResource %(resource)s for %(concept)s in fromDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue, concept=conceptChange.fromConceptQname) else: relationship = fromConcept.relationshipToResource(fromResource, XbrlConst.elementLabel) if relationship is not None: if relationship.qname != XbrlConst.qnGenArc or \ fromResource.qname != XbrlConst.qnGenLabel: self.modelVersReport.error("vercee:invalidConceptLabelIdentifier", _("%(action)s %(event)s fromResource %(resource)s for %(concept)s in fromDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue, concept=conceptChange.fromConceptQname) else: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s fromResource %(resource)s does not have a label relationship to {3} in fromDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue) elif "Reference" in conceptChange.name: if fromResource is None: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s fromResource %(resource)s does not reference a resource in fromDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue) else: relationship = fromConcept.relationshipToResource(fromResource, XbrlConst.conceptReference) if relationship is not None: if relationship.qname != XbrlConst.qnLinkReferenceArc or \ relationship.parentQname != XbrlConst.qnLinkReferenceLink or \ fromResource.qname != XbrlConst.qnLinkReference: self.modelVersReport.error("vercee:invalidConceptReferenceIdentifier", _("%(action)s %(event)s fromResource %(resource)s for %(concept)s in fromDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue, concept=conceptChange.fromConceptQname) else: relationship = fromConcept.relationshipToResource(fromResource, XbrlConst.elementReference) if relationship is not None: if relationship.qname != XbrlConst.qnGenArc or \ fromResource.qname != XbrlConst.qnGenReference: self.modelVersReport.error("vercee:invalidConceptReferenceIdentifier", _("%(action)s %(event)s fromResource %(resource)s for %(concept)s in fromDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue, concept=conceptChange.fromConceptQname) else: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s fromResource %(resource)s does not have a reference relationship to %(concept)s in fromDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.fromResourceValue, concept=conceptChange.fromConceptQname) # toConcept checks if not conceptChange.name.endswith("Delete"): if not toConcept is not None: self.modelVersReport.error("vercbe:invalidConceptReference", _("%(action)s %(event)s toConcept %(concept)s does not reference a concept in toDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, concept=conceptChange.toConceptQname) # tuple check elif "Child" in conceptChange.name and \ not versReport.toDTS.qnameConcepts[toConcept.qname] \ .isTuple: self.modelVersReport.error("vercbe:invalidConceptReference", _("%(action)s %(event)s toConcept %(concept)s must be defined as a tuple"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, concept=conceptChange.toConceptQname) # resource check elif "Label" in conceptChange.name: if toResource is None: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s toResource %(resource)s for %(concept)s does not reference a resource in toDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue, concept=conceptChange.toConceptQname) else: relationship = toConcept.relationshipToResource(toResource, XbrlConst.conceptLabel) if relationship is not None: if relationship.qname != XbrlConst.qnLinkLabelArc or \ relationship.parentQname != XbrlConst.qnLinkLabelLink or \ toResource.qname != XbrlConst.qnLinkLabel: self.modelVersReport.error("vercee:invalidConceptLabelIdentifier", _("%(action)s %(event)s toResource %(resource)s for %(concept)s in toDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue, concept=conceptChange.toConceptQname) else: relationship = toConcept.relationshipToResource(toResource, XbrlConst.elementLabel) if relationship is not None: if relationship.qname != XbrlConst.qnGenArc or \ toResource.qname != XbrlConst.qnGenLabel: self.modelVersReport.error("vercee:invalidConceptLabelIdentifier", _("%(action)s %(event)s toResource %(resource)s for %(concept)s in toDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue, concept=conceptChange.toConceptQname) else: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s toResource %(resource)s does not have a label relationship to %(concept)s in toDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue, concept=conceptChange.toConceptQname) elif "Reference" in conceptChange.name: if toResource is None: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s toResource %(resource)s does not reference a resource in toDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue) else: relationship = toConcept.relationshipToResource(toResource, XbrlConst.conceptReference) if relationship is not None: if relationship.qname != XbrlConst.qnLinkReferenceArc or \ relationship.parentQname != XbrlConst.qnLinkReferenceLink or \ toResource.qname != XbrlConst.qnLinkReference: self.modelVersReport.error("vercee:invalidConceptReferenceIdentifier", _("%(action)s %(event)s toResource %(resource)s for %(concept)s in toDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue, concept=conceptChange.toConceptQname) else: relationship = toConcept.relationshipToResource(toResource, XbrlConst.elementReference) if relationship is not None: if relationship.qname != XbrlConst.qnGenArc or \ toResource.qname != XbrlConst.qnGenReference: self.modelVersReport.error("vercee:invalidConceptReferenceIdentifier", _("%(action)s %(event)s toResource %(resource)s for %(concept)s in toDTS does not have expected link, arc, or label elements"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue, concept=conceptChange.toConceptQname) else: self.modelVersReport.error("vercee:invalidContentResourceIdentifier", _("%(action)s %(event)s toResource %(resource)s does not have a reference relationship to %(concept)s in toDTS"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, resource=conceptChange.toResourceValue, concept=conceptChange.toConceptQname) # check concept correspondence if fromConcept is not None and toConcept is not None: if versReport.toDTSqname(fromConcept.qname) != toConcept.qname and \ versReport.equivalentConcepts.get(fromConcept.qname) != toConcept.qname and \ toConcept.qname not in versReport.relatedConcepts.get(fromConcept.qname,[]): self.modelVersReport.error("vercee:invalidConceptCorrespondence", _("%(action)s %(event)s fromConcept %(conceptFrom)s and toConcept %(conceptTo)s must be equivalent or related"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, conceptFrom=conceptChange.fromConceptQname, conceptTo=conceptChange.toConceptQname) # custom attribute events if conceptChange.name.startswith("conceptAttribute"): try: for attr in conceptAttributeEventAttributes[conceptChange.name]: customAttributeQname = conceptChange.customAttributeQname(attr) if not customAttributeQname or customAttributeQname.namespaceURI is None: self.modelVersReport.error("vercee:invalidAttributeChange", _("%(action)s %(event)s %(attr)s $(attrName)s does not have a namespace"), modelObject=conceptChange, action=conceptChange.actionId, attr=attr, attrName=customAttributeQname) elif customAttributeQname.namespaceURI in (XbrlConst.xbrli, XbrlConst.xsd): self.modelVersReport.error("vercee:illegalCustomAttributeEvent", _("%(action)s %(event)s %(attr)s $(attrName)s has an invalid namespace"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name, attr=attr, attrName=customAttributeQname) except KeyError: self.modelVersReport.info("arelle:eventNotRecognized", _("%(action)s %(event)s event is not recognized"), modelObject=conceptChange, action=conceptChange.actionId, event=conceptChange.name) # check relationship set changes for relSetChange in versReport.relationshipSetChanges: for relationshipSet, name in ((relSetChange.fromRelationshipSet, "fromRelationshipSet"), (relSetChange.toRelationshipSet, "toRelationshipSet")): if relationshipSet is not None: relationshipSetValid = True if relationshipSet.link and relationshipSet.link not in relationshipSet.dts.qnameConcepts: self.modelVersReport.error("verrelse:invalidLinkElementReference", _("%(event)s %(relSet)s link %(link)s does not reference an element in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, link=relationshipSet.link) relationshipSetValid = False if relationshipSet.arc and relationshipSet.arc not in relationshipSet.dts.qnameConcepts: self.modelVersReport.error("verrelse:invalidArcElementReference", _("%(event)s %(relSet)s arc %(arc) does not reference an element in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, arc=relationshipSet.arc) relationshipSetValid = False if relationshipSet.linkrole and not (XbrlConst.isStandardRole(relationshipSet.linkrole) or relationshipSet.linkrole in relationshipSet.dts.roleTypes): self.modelVersReport.error("verrelse:invalidLinkrole", _("%(event)s %(relSet)s linkrole %(linkrole)s does not reference an linkrole in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, linkrole=relationshipSet.linkrole) relationshipSetValid = False if relationshipSet.arcrole and not (XbrlConst.isStandardArcrole(relationshipSet.arcrole) or relationshipSet.arcrole in relationshipSet.dts.arcroleTypes): self.modelVersReport.error("verrelse:invalidArcrole", _("%(event)s %(relSet)s arcrole %(arcrole)s does not reference an arcrole in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, arcrole=relationshipSet.arcrole) relationshipSetValid = False for relationship in relationshipSet.relationships: # fromConcept checks if relationship.fromConcept is None: self.modelVersReport.error("verrelse:invalidConceptReference", _("%(event)s %(relSet)s relationship fromConcept %(conceptFrom)s does not reference a concept in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, conceptFrom=relationship.fromName) relationshipSetValid = False if relationship.toName and relationship.toConcept is None: self.modelVersReport.error("verrelse:invalidConceptReference", _("%(event)s %(relSet)s relationship toConcept %(conceptTo)s does not reference a concept in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, conceptTo=relationship.toName) relationshipSetValid = False if relationshipSetValid: # test that relations exist if relationship.fromRelationship is None: if relationship.toName: self.modelVersReport.error("verrelse:invalidRelationshipReference", _("%(event)s %(relSet)s no relationship found from fromConcept %(conceptFrom)s to toConcept %(conceptTo)s in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, conceptFrom=relationship.fromName, conceptTo=relationship.toName) else: self.modelVersReport.error("verrelse:invalidRelationshipReference", _("%(event)s %(relSet)s no relationship found fromConcept %(conceptFrom)s in its DTS"), modelObject=relSetChange, event=relSetChange.name, relSet=name, conceptFrom=relationship.fromName) ''' # check instance aspect changes for iaChange in versReport.instanceAspectChanges: # validate related concepts for aspectName in ("{http://xbrl.org/2010/versioning-instance-aspects}concept", "{http://xbrl.org/2010/versioning-instance-aspects}member"): for aspectElt in iaChange.iterdescendants(aspectName): # check link attribute link = aspectElement.get("link") if link is not None: iaChange.hrefToModelObject(link, dts) ''' self.close()
def __init__(self, mainWin): parent = mainWin.parent super(DialogTransformTester, self).__init__(parent) self.mainWin = mainWin self.parent = parent parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.selectedGroup = None self.transient(self.parent) self.title(_("Transformation Tester")) frame = Frame(self) # setup tester xml = "<rootElement/>" self.modelXbrl = ModelXbrl.create(mainWin.modelManager, ModelDocument.Type.UnknownNonXML, initialXml=xml, isEntry=True) self.validator = ValidateXbrl.ValidateXbrl(self.modelXbrl) self.validator.validate(self.modelXbrl) # required to set up mainWin.showStatus(_("Initializing Formula Grammar")) XPathParser.initializeParser(mainWin.modelManager) mainWin.showStatus(None) self.trRegs = sorted(ixtNamespaces.keys()) self.trReg = self.trRegs[-1] # default is latest self.trPrefixNSs = dict( (qn.prefix, qn.namespaceURI) for qn in self.modelXbrl.modelManager.customTransforms.keys()) self.trRegs.extend(sorted(self.trPrefixNSs.keys())) self.trPrefixNSs.update(ixtNamespaces) self.trNames = self.getTrNames() # load grid trRegLabel = label(frame, 0, 0, _("Registry:")) self.trRegName = gridCombobox( frame, 1, 0, value=self.trReg, values=self.trRegs, comboboxselected=self.trRegComboBoxSelected) trRegToolTipMessage = _("Select Transformation Registry") ToolTip(self.trRegName, text=trRegToolTipMessage, wraplength=360) ToolTip(trRegLabel, text=trRegToolTipMessage, wraplength=360) trNameLabel = label(frame, 0, 1, _("Transform:")) self.trNameName = gridCombobox( frame, 1, 1, value="", values=self.trNames, comboboxselected=self.trNameComboBoxSelected) trRegToolTipMessage = _("Select or enter transform") ToolTip(self.trRegName, text=trRegToolTipMessage, wraplength=360) ToolTip(trRegLabel, text=trRegToolTipMessage, wraplength=360) sourceLabel = label(frame, 0, 2, _("Source text:")) ToolTip(sourceLabel, text=_("Enter the source text which is to be transformed. "), wraplength=240) self.sourceVar = StringVar() self.sourceVar.set("") sourceEntry = Entry(frame, textvariable=self.sourceVar, width=50) sourceLabel.grid(row=2, column=0, sticky=W) sourceEntry.grid(row=2, column=1, sticky=EW, pady=3, padx=3) resultLabel = label(frame, 1, 3, _("Result:")) ToolTip(sourceLabel, text=_("Transformation result. "), wraplength=240) self.resultVar = StringVar() self.resultVar.set("") resultEntry = Entry(frame, textvariable=self.resultVar, width=50) resultLabel.grid(row=3, column=0, sticky=W) resultEntry.grid(row=3, column=1, sticky=EW, pady=3, padx=3) mainWin.showStatus(None) btnPad = 2 if mainWin.isMSW else 0 # buttons too narrow on windows okButton = Button(frame, text=_("Transform"), width=8 + btnPad, command=self.ok) cancelButton = Button(frame, text=_("Done"), width=4 + btnPad, command=self.close) cancelButton.grid(row=4, column=0, sticky=E, columnspan=2, pady=3, padx=3) okButton.grid(row=4, column=0, sticky=E, columnspan=2, pady=3, padx=64) ToolTip(okButton, text=_("Transform the source entered. "), wraplength=240) ToolTip(cancelButton, text=_("Close this dialog. "), wraplength=240) frame.grid(row=0, column=0, sticky=(N, S, E, W)) frame.columnconfigure(1, weight=3) frame.columnconfigure(2, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) self.geometry("+{0}+{1}".format(dialogX + 150, dialogY + 100)) #self.bind("<Return>", self.ok) #self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self)
def validate(self, modelVersReport): self.modelVersReport = modelVersReport versReport = modelVersReport.modelDocument if not hasattr(versReport, "xmlDocument"): # not parsed return for DTSname in ("fromDTS", "toDTS"): DTSmodelXbrl = getattr(versReport, DTSname) if DTSmodelXbrl is None or DTSmodelXbrl.modelDocument is None: self.modelVersReport.error( _("{0} is missing or not loaded").format(DTSname), "err", "vere:invalidDTSIdentifier") else: # validate DTS ValidateXbrl.ValidateXbrl(DTSmodelXbrl).validate(DTSmodelXbrl) if len(DTSmodelXbrl.errors) > 0: self.modelVersReport.error( _("{0} {1} has errors: {2}").format( DTSname, DTSmodelXbrl.modelDocument.basename, DTSmodelXbrl.errors), "err", "vere:invalidDTSIdentifier") # validate linkbases ValidateXbrl.ValidateXbrl( self.modelVersReport).validate(modelVersReport) versReportElt = versReport.xmlRootElement # check actions for assignmentRef in versReportElt.getElementsByTagNameNS( XbrlConst.ver, "assignmentRef"): ref = assignmentRef.getAttribute("ref") if ref not in versReport.idObjects or \ not isinstance(versReport.idObjects[ref], ModelVersObject.ModelAssignment): self.modelVersReport.error( _("AssignmentRef {0} does not reference an assignment"). format(ref), "err", "vere:invalidAssignmentRef") # check namespace renames for NSrename in versReport.namespaceRenameFrom.values(): if NSrename.fromURI not in versReport.fromDTS.namespaceDocs: self.modelVersReport.error( _("NamespaceRename fromURI {0} does not reference a schema in fromDTS" ).format(NSrename.fromURI), "err", "vere:invalidNamespaceMapping") if NSrename.toURI not in versReport.toDTS.namespaceDocs: self.modelVersReport.error( _("NamespaceRename toURI {0} does not reference a schema in toDTS" ).format(NSrename.toURI), "err", "vere:invalidNamespaceMapping") # check role changes for roleChange in versReport.roleChanges.values(): if roleChange.fromURI not in versReport.fromDTS.roleTypes: self.modelVersReport.error( _("RoleChange fromURI {0} does not reference a roleType in fromDTS" ).format(roleChange.fromURI), "err", "vere:invalidRoleChange") if roleChange.toURI not in versReport.toDTS.roleTypes: self.modelVersReport.error( _("RoleChange toURI {0} does not reference a roleType in toDTS" ).format(roleChange.toURI), "err", "vere:invalidRoleChange") # check reportRefs # check actions for reportRef in versReportElt.getElementsByTagNameNS( XbrlConst.ver, "reportRef"): xlinkType = reportRef.getAttributeNS(XbrlConst.xlink, "type") if xlinkType != "simple": self.modelVersReport.error( _("ReportRef xlink:type {0} must be \"simple\"").format( xlinkType), "err", "vere:invalidXlinkType") # if existing it must be valid href = reportRef.getAttributeNS(XbrlConst.xlink, "href") # TBD if not reportRef.hasAttributeNS(XbrlConst.xlink, "arcrole"): self.modelVersReport.error( _("ReportRef xlink:arcrole is missing"), "err", "vere:missingXlinkArcrole") else: arcrole = reportRef.getAttributeNS(XbrlConst.xlink, "arcrole") if arcrole != "http://xbrl.org/arcrole/2010/versioning/related-report": self.modelVersReport.error( _("ReportRef xlink:arcrole {0} is invalid").format( arcrole), "err", "vere:invalidXlinkArcrole") if versReport.fromDTS and versReport.toDTS: # check concept changes of concept basic for conceptChange in versReport.conceptBasicChanges: if conceptChange.name != "conceptAdd" and \ (conceptChange.fromConcept is None or \ conceptChange.fromConcept.qname not in versReport.fromDTS.qnameConcepts): self.modelVersReport.error( _("{0} fromConcept {1} does not reference a concept in fromDTS" ).format(conceptChange.name, conceptChange.fromConceptQname), "err", "vercbe:invalidConceptReference") if conceptChange.name != "conceptDelete" and \ (conceptChange.toConcept is None or \ conceptChange.toConcept.qname not in versReport.toDTS.qnameConcepts): self.modelVersReport.error( _("{0} toConcept {1} does not reference a concept in toDTS" ).format(conceptChange.name, conceptChange.toConceptQname), "err", "vercbe:invalidConceptReference") # check concept changes of concept extended for conceptChange in versReport.conceptExtendedChanges: fromConcept = conceptChange.fromConcept toConcept = conceptChange.toConcept fromResource = conceptChange.fromResource toResource = conceptChange.toResource # fromConcept checks if not conceptChange.name.endswith("Add"): if not fromConcept: self.modelVersReport.error( _("{0} {1} fromConcept {2} does not reference a concept in fromDTS" ).format(conceptChange.actionId, conceptChange.name, conceptChange.fromConceptQname), "err", "vercbe:invalidConceptReference") # tuple check elif "Child" in conceptChange.name and \ not versReport.fromDTS.qnameConcepts[fromConcept.qname] \ .isTuple: self.modelVersReport.error( _("{0} {1} fromConcept {2} must be defined as a tuple" ).format(conceptChange.actionId, conceptChange.name, conceptChange.fromConceptQname), "err", "vercbe:invalidConceptReference") # resource check elif "Label" in conceptChange.name: if not fromResource: self.modelVersReport.error( _("{0} {1} fromResource {2} does not reference a resource in fromDTS" ).format(conceptChange.actionId, conceptChange.name, conceptChange.fromResourceValue), "err", "vercee:invalidContentResourceIdentifier") else: relationship = fromConcept.relationshipToResource( fromResource, XbrlConst.conceptLabel) if relationship: if relationship.qname != XbrlConst.qnLinkLabelArc or \ relationship.parentQname != XbrlConst.qnLinkLabelLink or \ fromResource.qname != XbrlConst.qnLinkLabel: self.modelVersReport.error( _("{0} {1} fromResource {2} for {3} in fromDTS does not have expected link, arc, or label elements" ).format( conceptChange.actionId, conceptChange.name, conceptChange.fromResourceValue, conceptChange.fromConceptQname), "err", "vercee:invalidConceptLabelIdentifier") else: relationship = fromConcept.relationshipToResource( fromResource, XbrlConst.elementLabel) if relationship: if relationship.qname != XbrlConst.qnGenArc or \ fromResource.qname != XbrlConst.qnGenLabel: self.modelVersReport.error( _("{0} {1} fromResource {2} for {3} in fromDTS does not have expected link, arc, or label elements" ).format( conceptChange.actionId, conceptChange.name, conceptChange. fromResourceValue, conceptChange. fromConceptQname), "err", "vercee:invalidConceptLabelIdentifier" ) else: self.modelVersReport.error( _("{0} {1} fromResource {2} does not have a label relationship to {3} in fromDTS" ).format( conceptChange.actionId, conceptChange.name, conceptChange.fromResourceValue, conceptChange.fromConceptQname), "err", "vercee:invalidContentResourceIdentifier" ) elif "Reference" in conceptChange.name: if not fromResource: self.modelVersReport.error( _("{0} {1} fromResource {2} does not reference a resource in fromDTS" ).format(conceptChange.actionId, conceptChange.name, conceptChange.fromResourceValue), "err", "vercee:invalidContentResourceIdentifier") else: relationship = fromConcept.relationshipToResource( fromResource, XbrlConst.conceptReference) if relationship: if relationship.qname != XbrlConst.qnLinkReferenceArc or \ relationship.parentQname != XbrlConst.qnLinkReferenceLink or \ fromResource.qname != XbrlConst.qnLinkReference: self.modelVersReport.error( _("{0} {1} fromResource {2} for {3} in fromDTS does not have expected link, arc, or label elements" ).format( conceptChange.actionId, conceptChange.name, conceptChange.fromResourceValue, conceptChange.fromConceptQname), "err", "vercee:invalidConceptReferenceIdentifier" ) else: relationship = fromConcept.relationshipToResource( fromResource, XbrlConst.elementReference) if relationship: if relationship.qname != XbrlConst.qnGenArc or \ fromResource.qname != XbrlConst.qnGenReference: self.modelVersReport.error( _("{0} {1} fromResource {2} for {3} in fromDTS does not have expected link, arc, or label elements" ).format( conceptChange.actionId, conceptChange.name, conceptChange. fromResourceValue, conceptChange. fromConceptQname), "err", "vercee:invalidConceptReferenceIdentifier" ) else: self.modelVersReport.error( _("{0} {1} fromResource {2} does not have a reference relationship to {3} in fromDTS" ).format( conceptChange.actionId, conceptChange.name, conceptChange.fromResourceValue, conceptChange.fromConceptQname), "err", "vercee:invalidContentResourceIdentifier" ) # toConcept checks if not conceptChange.name.endswith("Delete"): if not toConcept: self.modelVersReport.error( _("{0} {1} toConcept {2} does not reference a concept in toDTS" ).format(conceptChange.actionId, conceptChange.name, conceptChange.toConceptQname), "err", "vercbe:invalidConceptReference") # tuple check elif "Child" in conceptChange.name and \ not versReport.toDTS.qnameConcepts[toConcept.qname] \ .isTuple: self.modelVersReport.error( _("{0} {1} toConcept {2} must be defined as a tuple" ).format(conceptChange.actionId, conceptChange.name, conceptChange.toConceptQname), "err", "vercbe:invalidConceptReference") # resource check elif "Label" in conceptChange.name: if not toResource: self.modelVersReport.error( _("{0} {1} toResource {2} does not reference a resource in toDTS" ).format(conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue), "err", "vercee:invalidContentResourceIdentifier") else: relationship = toConcept.relationshipToResource( toResource, XbrlConst.conceptLabel) if relationship: if relationship.qname != XbrlConst.qnLinkLabelArc or \ relationship.parentQname != XbrlConst.qnLinkLabelLink or \ toResource.qname != XbrlConst.qnLinkLabel: self.modelVersReport.error( _("{0} {1} toResource {2} for {3} in toDTS does not have expected link, arc, or label elements" ).format( conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue, conceptChange.toConceptQname), "err", "vercee:invalidConceptLabelIdentifier") else: relationship = toConcept.relationshipToResource( toResource, XbrlConst.elementLabel) if relationship: if relationship.qname != XbrlConst.qnGenArc or \ toResource.qname != XbrlConst.qnGenLabel: self.modelVersReport.error( _("{0} {1} toResource {2} for {3} in toDTS does not have expected link, arc, or label elements" ). format( conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue, conceptChange.toConceptQname), "err", "vercee:invalidConceptLabelIdentifier" ) else: self.modelVersReport.error( _("{0} {1} toResource {2} does not have a label relationship to {3} in toDTS" ).format( conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue, conceptChange.toConceptQname), "err", "vercee:invalidContentResourceIdentifier" ) elif "Reference" in conceptChange.name: if not toResource: self.modelVersReport.error( _("{0} {1} toResource {2} does not reference a resource in toDTS" ).format(conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue), "err", "vercee:invalidContentResourceIdentifier") else: relationship = toConcept.relationshipToResource( toResource, XbrlConst.conceptReference) if relationship: if relationship.qname != XbrlConst.qnLinkReferenceArc or \ relationship.parentQname != XbrlConst.qnLinkReferenceLink or \ toResource.qname != XbrlConst.qnLinkReference: self.modelVersReport.error( _("{0} {1} toResource {2} for {3} in toDTS does not have expected link, arc, or label elements" ).format( conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue, conceptChange.toConceptQname), "err", "vercee:invalidConceptReferenceIdentifier" ) else: relationship = toConcept.relationshipToResource( toResource, XbrlConst.elementReference) if relationship: if relationship.qname != XbrlConst.qnGenArc or \ toResource.qname != XbrlConst.qnGenReference: self.modelVersReport.error( _("{0} {1} toResource {2} for {3} in toDTS does not have expected link, arc, or label elements" ). format( conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue, conceptChange.toConceptQname), "err", "vercee:invalidConceptReferenceIdentifier" ) else: self.modelVersReport.error( _("{0} {1} toResource {2} does not have a reference relationship to {3} in toDTS" ).format( conceptChange.actionId, conceptChange.name, conceptChange.toResourceValue, conceptChange.toConceptQname), "err", "vercee:invalidContentResourceIdentifier" ) # check concept correspondence if fromConcept and toConcept: if versReport.toDTSqname(fromConcept.qname) != toConcept.qname and \ versReport.equivalentConcepts.get(fromConcept.qname) != toConcept.qname and \ toConcept.qname not in versReport.relatedConcepts.get(fromConcept.qname,[]): self.modelVersReport.error( _("{0} {1} fromConcept {2} and toConcept {3} must be equivalent or related" ).format(conceptChange.actionId, conceptChange.name, conceptChange.fromConceptQname, conceptChange.toConceptQname), "err", "vercee:invalidConceptCorrespondence") # custom attribute events if conceptChange.name.startswith("conceptAttribute"): try: for attr in conceptAttributeEventAttributes[ conceptChange.name]: customAttributeQname = conceptChange.customAttributeQname( attr) if not customAttributeQname or customAttributeQname.namespaceURI is None: self.modelVersReport.error( _("{0} {1} {2} {3} does not have a namespace" ).format(conceptChange.actionId, conceptChange.name, attr, customAttributeQname), "err", "vercee:invalidAttributeChange") elif customAttributeQname.namespaceURI in ( XbrlConst.xbrli, XbrlConst.xsd): self.modelVersReport.error( _("{0} {1} {2} {3} has an invalid namespace" ).format(conceptChange.actionId, conceptChange.name, attr, customAttributeQname), "err", "vercee:illegalCustomAttributeEvent") except KeyError: self.modelVersReport.error( _("{0} {1} event is not recognized").format( conceptChange.actionId, conceptChange.name), "info", "arelle:eventNotRecognized") # check relationship set changes for relSetChange in versReport.relationshipSetChanges: for relationshipSet, name in ( (relSetChange.fromRelationshipSet, "fromRelationshipSet"), (relSetChange.toRelationshipSet, "toRelationshipSet")): if relationshipSet: relationshipSetValid = True if relationshipSet.link and relationshipSet.link not in relationshipSet.dts.qnameConcepts: self.modelVersReport.error( _("{0} link {1} does not reference an element in its DTS" ).format(relSetChange.name, name, relationshipSet.link), "err", "verrelse:invalidLinkElementReference") relationshipSetValid = False if relationshipSet.arc and relationshipSet.arc not in relationshipSet.dts.qnameConcepts: self.modelVersReport.error( _("{0} arc {1} does not reference an element in its DTS" ).format(relSetChange.name, name, relationshipSet.link), "err", "verrelse:invalidArcElementReference") relationshipSetValid = False if relationshipSet.linkrole and not ( XbrlConst.isStandardRole( relationshipSet.linkrole) or relationshipSet.linkrole in relationshipSet.dts.roleTypes): self.modelVersReport.error( _("{0} linkrole {1} does not reference an linkrole in its DTS" ).format(relSetChange.name, name, relationshipSet.linkrole), "err", "verrelse:invalidLinkrole") relationshipSetValid = False if relationshipSet.arcrole and not ( XbrlConst.isStandardArcrole( relationshipSet.arcrole) or relationshipSet.arcrole in relationshipSet.dts.arcroleTypes): self.modelVersReport.error( _("{0} arcrole {1} does not reference an arcrole in its DTS" ).format(relSetChange.name, name, relationshipSet.linkrole), "err", "verrelse:invalidArcrole") relationshipSetValid = False for relationship in relationshipSet.relationships: # fromConcept checks if not relationship.fromConcept: self.modelVersReport.error( _("{0} {1} relationship fromConcept {2} does not reference a concept in its DTS" ).format(relSetChange.name, name, relationship.fromName), "err", "verrelse:invalidConceptReference") relationshipSetValid = False if relationship.toName and not relationship.toConcept: self.modelVersReport.error( _("{0} {1} relationship toConcept {2} does not reference a concept in its DTS" ).format(relSetChange.name, name, relationship.toName), "err", "verrelse:invalidConceptReference") relationshipSetValid = False if relationshipSetValid: # test that relations exist if relationship.fromRelationship is None: if relationship.toName: self.modelVersReport.error( _("{0} {1} no relationship found from toConcept {2} to {3} in its DTS" ).format(relSetChange.name, name, relationship.fromName, relationship.toName), "err", "verrelse:invalidRelationshipReference" ) else: self.modelVersReport.error( _("{0} {1} no relationship found from toConcept {2} in its DTS" ).format(relSetChange.name, name, relationship.fromName), "err", "verrelse:invalidRelationshipReference" ) '''