def attributeSet(modelXbrl, modelConcept, elt, exclusions=(), equalMode=S_EQUAL, excludeIDs=False, ns2ns1Tbl=None): attrs = set() for i in range(len(elt.attributes)): attr = elt.attributes.item(i) attrNsURI = attr.namespaceURI if ns2ns1Tbl and attrNsURI in ns2ns1Tbl: attrNsURI = ns2ns1Tbl[attrNsURI] attrName = "{{{0}}}{1}".format(attrNsURI,attr.localName) if attrNsURI else attr.name if (attrName not in exclusions and (attrNsURI is None or attrNsURI not in exclusions) and attr.name not in ("xmlns") and attr.prefix != "xmlns"): if attrNsURI: qname = ModelValue.qname(attrNsURI, attr.localName) else: qname = ModelValue.qname(attr.localName) baseXsdAttrType = None if modelConcept: baseXsdAttrType = modelConcept.baseXsdAttrType(qname) if modelConcept else None if baseXsdAttrType is None: attrObject = modelXbrl.qnameAttributes.get(qname) if attrObject: baseXsdAttrType = attrObject.baseXsdType if excludeIDs and baseXsdAttrType == "ID": continue value = xTypeValue(baseXsdAttrType, elt, attr, attr.value, equalMode) attrs.add( (qname,value) ) return attrs
def sEqual(dts1, elt1, elt2, equalMode=S_EQUAL, excludeIDs=False, dts2=None, ns2ns1Tbl=None): if dts2 is None: dts2 = dts1 if elt1.localName != elt2.localName: return False if ns2ns1Tbl and elt2.namespaceURI in ns2ns1Tbl: if elt1.namespaceURI != ns2ns1Tbl[elt2.namespaceURI]: return False elif elt1.namespaceURI != elt2.namespaceURI: return False # is the element typed? modelConcept1 = dts1.qnameConcepts.get(ModelValue.qname(elt1)) modelConcept2 = dts2.qnameConcepts.get(ModelValue.qname(elt2)) if (not xEqual( modelConcept1, elt1, elt2, equalMode, modelConcept2=modelConcept2) or attributeSet(dts1, modelConcept1, elt1, (), equalMode, excludeIDs) != attributeSet( dts2, modelConcept2, elt2, (), equalMode, excludeIDs, ns2ns1Tbl)): return False children1 = childElements(elt1) children2 = childElements(elt2) if len(children1) != len(children2): return False for i in range(len(children1)): if not sEqual(dts1, children1[i], children2[i], equalMode, excludeIDs, dts2, ns2ns1Tbl): return False return True
def parameters(self): try: return self._parameters except AttributeError: self._parameters = dict([ (ModelValue.qname(paramElt, paramElt.get("name")), # prefix-less parameter names take default namespace of element (ModelValue.qname(paramElt, paramElt.get("datatype")),paramElt.get("value"))) for paramElt in XmlUtil.descendants(self, self.namespaceURI, "parameter")]) return self._parameters
def parameters(self): try: return self._parameters except AttributeError: self._parameters = dict([ (ModelValue.qname(paramElt, paramElt.get("name"),noPrefixIsNoNamespace=True), (ModelValue.qname(paramElt, paramElt.get("datatype")),paramElt.get("value"))) for paramElt in XmlUtil.descendants(self, self.namespaceURI, "parameter")]) return self._parameters
def pushVarRef( sourceStr, loc, toks ): qname = ModelValue.qname(xmlElement, toks[0][1:], noPrefixIsNoNamespace=True) if qname is None: modelXbrl.error( _("QName prefix not defined for variable reference ${0}").format(toks[0][1:]), "err","err:XPST0081") qname = ModelValue.qname(XbrlConst.xpath2err,"XPST0081") # use as qname to allow parsing to complete varRef = VariableRef(loc, qname) exprStack.append( varRef ) return varRef
def pushVarRef( sourceStr, loc, toks ): qname = ModelValue.qname(xmlElement, toks[0][1:], noPrefixIsNoNamespace=True) if qname is None: modelXbrl.error("err:XPST0081", _("QName prefix not defined for variable reference $%(variable)s"), modelObject=xmlElement, variable=toks[0][1:]) qname = ModelValue.qname(XbrlConst.xpath2err,"XPST0081") # use as qname to allow parsing to complete varRef = VariableRef(loc, qname) exprStack.append( varRef ) return varRef
def xTypeValue(baseXsdType, elt, node, value, equalMode=S_EQUAL): try: if node.xValid == XmlValidate.VALID: xvalue = node.xValue if (equalMode == XPATH_EQ or isinstance(xvalue,(float,int,bool)) or (equalMode == S_EQUAL2 and isinstance(xvalue,(ModelValue.QName)))): value = xvalue except AttributeError: if baseXsdType in ("decimal", "float", "double"): try: return float(value) except ValueError: return value elif baseXsdType in ("integer",): try: return int(value) except ValueError: return value elif baseXsdType == "boolean": return (value == "true" or value == "1") elif equalMode == S_EQUAL2 and baseXsdType == "QName": return ModelValue.qname(elt, value) elif equalMode == XPATH_EQ and baseXsdType in ("normalizedString","token","language","NMTOKEN","Name","NCName","ID","IDREF","ENTITY"): return value.strip() return value
def expected(self): for pluginXbrlMethod in pluginClassMethods( "ModelTestcaseVariation.ExpectedResult"): expected = pluginXbrlMethod(self) if expected: return expected # default behavior without plugins if self.localName == "testcase": return self.document.basename[:4] #starts with PASS or FAIL elif self.localName == "testGroup": #w3c testcase instanceTestElement = XmlUtil.descendant(self, None, "instanceTest") if instanceTestElement is not None: # take instance first return XmlUtil.descendantAttr(instanceTestElement, None, "expected", "validity") else: schemaTestElement = XmlUtil.descendant(self, None, "schemaTest") if schemaTestElement is not None: return XmlUtil.descendantAttr(schemaTestElement, None, "expected", "validity") resultElement = XmlUtil.descendant(self, None, "result") if resultElement is not None: expected = resultElement.get("expected") if expected and resultElement.get( "nonStandardErrorCodes") == "true": # if @expected and @nonStandardErrorCodes then use expected instead of error codes return expected errorElement = XmlUtil.descendant(self, None, "error") if errorElement is not None: _errorText = XmlUtil.text(errorElement) if ' ' in _errorText: # list of tokens return _errorText return ModelValue.qname(errorElement, _errorText) # turn into a QName if resultElement is not None: if expected: return expected for assertElement in XmlUtil.children(resultElement, None, "assert"): num = assertElement.get("num") if num == "99999": # inline test, use name as expected return assertElement.get("name") if len(num) == 5: return "EFM.{0}.{1}.{2}".format(num[0], num[1:3], num[3:6]) asserTests = {} for atElt in XmlUtil.children(resultElement, None, "assertionTests"): try: asserTests[atElt.get("assertionID")] = ( _INT(atElt.get("countSatisfied")), _INT(atElt.get("countNotSatisfied"))) except ValueError: pass if asserTests: return asserTests elif self.get("result"): return self.get("result") return None
def ancestorQnames(self): """(set) -- Set of QNames of ancestor elements (tuple and xbrli:xbrl)""" try: return self._ancestorQnames except AttributeError: self._ancestorQnames = set( ModelValue.qname(ancestor) for ancestor in self.iterancestors() ) return self._ancestorQnames
def expected(self): if self.localName == "testcase": return self.document.basename[:4] #starts with PASS or FAIL errorElement = XmlUtil.descendant(self, None, "error") if errorElement is not None: return ModelValue.qname(errorElement, XmlUtil.text(errorElement)) resultElement = XmlUtil.descendant(self, None, "result") if resultElement is not None: expected = resultElement.get("expected") if expected: return expected for assertElement in XmlUtil.children(resultElement, None, "assert"): num = assertElement.get("num") if len(num) == 5: return "EFM.{0}.{1}.{2}".format(num[0],num[1:3],num[3:6]) asserTests = {} for atElt in XmlUtil.children(resultElement, None, "assertionTests"): try: asserTests[atElt.get("assertionID")] = (_INT(atElt.get("countSatisfied")),_INT(atElt.get("countNotSatisfied"))) except ValueError: pass if asserTests: return asserTests elif self.get("result"): return self.get("result") return None
def readMeFirstUris(self): try: return self._readMeFirstUris except AttributeError: self._readMeFirstUris = [] # first look if any plugin method to get readme first URIs if not any( pluginXbrlMethod(self) for pluginXbrlMethod in pluginClassMethods( "ModelTestcaseVariation.ReadMeFirstUris")): if self.localName == "testGroup": #w3c testcase instanceTestElement = XmlUtil.descendant( self, None, "instanceTest") if instanceTestElement is not None: # take instance first self._readMeFirstUris.append( XmlUtil.descendantAttr( instanceTestElement, None, "instanceDocument", "{http://www.w3.org/1999/xlink}href")) else: schemaTestElement = XmlUtil.descendant( self, None, "schemaTest") if schemaTestElement is not None: self._readMeFirstUris.append( XmlUtil.descendantAttr( schemaTestElement, None, "schemaDocument", "{http://www.w3.org/1999/xlink}href")) elif self.localName == "test-case": #xpath testcase inputFileElement = XmlUtil.descendant( self, None, "input-file") if inputFileElement is not None: # take instance first self._readMeFirstUris.append("TestSources/" + inputFileElement.text + ".xml") else: # default built-in method for readme first uris for anElement in self.iterdescendants(): if isinstance(anElement, ModelObject) and anElement.get( "readMeFirst") == "true": if anElement.get( "{http://www.w3.org/1999/xlink}href"): uri = anElement.get( "{http://www.w3.org/1999/xlink}href") else: uri = XmlUtil.innerText(anElement) if anElement.get("name"): self._readMeFirstUris.append( (ModelValue.qname(anElement, anElement.get("name")), uri)) elif anElement.get("dts"): self._readMeFirstUris.append( (anElement.get("dts"), uri)) else: self._readMeFirstUris.append(uri) if not self._readMeFirstUris: # provide a dummy empty instance document self._readMeFirstUris.append( os.path.join(self.modelXbrl.modelManager.cntlr.configDir, "empty-instance.xml")) return self._readMeFirstUris
def xTypeValue(baseXsdType, elt, node, value, equalMode=S_EQUAL): try: if node.xValid == XmlValidate.VALID: xvalue = node.xValue if (equalMode == XPATH_EQ or isinstance(xvalue, (float, int, bool)) or (equalMode == S_EQUAL2 and isinstance(xvalue, (ModelValue.QName)))): value = xvalue except AttributeError: if baseXsdType in ("decimal", "float", "double"): try: return float(value) except ValueError: return value elif baseXsdType in ("integer", ): try: return int(value) except ValueError: return value elif baseXsdType == "boolean": return (value == "true" or value == "1") elif equalMode == S_EQUAL2 and baseXsdType == "QName": return ModelValue.qname(elt, value) elif equalMode == XPATH_EQ and baseXsdType in ( "normalizedString", "token", "language", "NMTOKEN", "Name", "NCName", "ID", "IDREF", "ENTITY"): return value.strip() return value
def readMeFirstUris(self): try: return self._readMeFirstUris except AttributeError: self._readMeFirstUris = [] for anElement in self.iterdescendants(): if isinstance(anElement, ModelObject) and anElement.get( "readMeFirst") == "true": if anElement.get("{http://www.w3.org/1999/xlink}href"): uri = anElement.get( "{http://www.w3.org/1999/xlink}href") else: uri = XmlUtil.innerText(anElement) if anElement.get("name"): self._readMeFirstUris.append( (ModelValue.qname(anElement, anElement.get("name")), uri)) elif anElement.get("dts"): self._readMeFirstUris.append( (anElement.get("dts"), uri)) else: self._readMeFirstUris.append(uri) if not self._readMeFirstUris: # provide a dummy empty instance document self._readMeFirstUris.append( os.path.join(self.modelXbrl.modelManager.cntlr.configDir, "empty-instance.xml")) return self._readMeFirstUris
def expected(self): if self.localName == "testcase": return self.document.basename[:4] #starts with PASS or FAIL errorElement = XmlUtil.descendant(self, None, "error") if errorElement is not None: return ModelValue.qname(errorElement, XmlUtil.text(errorElement)) resultElement = XmlUtil.descendant(self, None, "result") if resultElement is not None: expected = resultElement.get("expected") if expected: return expected for assertElement in XmlUtil.children(resultElement, None, "assert"): num = assertElement.get("num") if len(num) == 5: return "EFM.{0}.{1}.{2}".format(num[0], num[1:3], num[3:6]) asserTests = {} for atElt in XmlUtil.children(resultElement, None, "assertionTests"): try: asserTests[atElt.get("assertionID")] = ( _INT(atElt.get("countSatisfied")), _INT(atElt.get("countNotSatisfied"))) except ValueError: pass if asserTests: return asserTests elif self.get("result"): return self.get("result") return None
def QName(xc, p, source): if isinstance(p, ProgHeader): element = p.element elif xc.progHeader: element = xc.progHeader.element else: element = xc.sourceElement return ModelValue.qname(element, source, castException=FORG0001, prefixException=FONS0004)
def ancestorQnames(self): try: return self._ancestorQnames except AttributeError: self._ancestorQnames = set( ModelValue.qname(ancestor) for ancestor in self.iterancestors()) return self._ancestorQnames
def readMeFirstUris(self): try: return self._readMeFirstUris except AttributeError: self._readMeFirstUris = [] # first look if any plugin method to get readme first URIs if not any( pluginXbrlMethod(self) for pluginXbrlMethod in pluginClassMethods( "ModelTestcaseVariation.ReadMeFirstUris")): if self.localName == "testGroup": #w3c testcase instanceTestElement = XmlUtil.descendant( self, None, "instanceTest") if instanceTestElement is not None: # take instance first self._readMeFirstUris.append( XmlUtil.descendantAttr( instanceTestElement, None, "instanceDocument", "{http://www.w3.org/1999/xlink}href")) else: schemaTestElement = XmlUtil.descendant( self, None, "schemaTest") if schemaTestElement is not None: self._readMeFirstUris.append( XmlUtil.descendantAttr( schemaTestElement, None, "schemaDocument", "{http://www.w3.org/1999/xlink}href")) elif self.localName == "test-case": #xpath testcase inputFileElement = XmlUtil.descendant( self, None, "input-file") if inputFileElement is not None: # take instance first self._readMeFirstUris.append( "TestSources/" + inputFileElement.text + ".xml") else: # default built-in method for readme first uris for anElement in self.iterdescendants(): if isinstance(anElement, ModelObject) and anElement.get( "readMeFirst") == "true": if anElement.get( "{http://www.w3.org/1999/xlink}href"): uri = anElement.get( "{http://www.w3.org/1999/xlink}href") else: uri = XmlUtil.innerText(anElement) if anElement.get("name"): self._readMeFirstUris.append((ModelValue.qname( anElement, anElement.get("name")), uri)) elif anElement.get("dts"): self._readMeFirstUris.append( (anElement.get("dts"), uri)) else: self._readMeFirstUris.append(uri) if not self._readMeFirstUris: # provide a dummy empty instance document self._readMeFirstUris.append( os.path.join(self.modelXbrl.modelManager.cntlr.configDir, "empty-instance.xml")) return self._readMeFirstUris
def validateXbrlStart(val, parameters=None): val.validateEFMplugin = val.validateDisclosureSystem and getattr(val.disclosureSystem, "EFMplugin", False) if not (val.validateEFMplugin): return val.paramExhibitType = None # e.g., EX-101, EX-201 val.paramFilerIdentifier = None val.paramFilerIdentifiers = None val.paramFilerNames = None val.paramSubmissionType = None if parameters: # parameter-provided CIKs and registrant names p = parameters.get(ModelValue.qname("CIK",noPrefixIsNoNamespace=True)) if p and len(p) == 2 and p[1] not in ("null", "None"): val.paramFilerIdentifier = p[1] p = parameters.get(ModelValue.qname("cikList",noPrefixIsNoNamespace=True)) if p and len(p) == 2: val.paramFilerIdentifiers = p[1].split(",") p = parameters.get(ModelValue.qname("cikNameList",noPrefixIsNoNamespace=True)) if p and len(p) == 2: val.paramFilerNames = p[1].split("|Edgar|") if val.paramFilerIdentifiers and len(val.paramFilerIdentifiers) != len(val.paramFilerNames): val.modelXbrl.error(("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikList and cikNameList different list entry counts: %(cikList)s, %(cikNameList)s"), modelXbrl=val.modelXbrl, cikList=val.paramFilerIdentifiers, cikNameList=val.paramFilerNames) p = parameters.get(ModelValue.qname("submissionType",noPrefixIsNoNamespace=True)) if p and len(p) == 2: val.paramSubmissionType = p[1] p = parameters.get(ModelValue.qname("exhibitType",noPrefixIsNoNamespace=True)) if p and len(p) == 2: val.paramExhibitType = p[1] if val.paramExhibitType == "EX-2.01": # only applicable for edgar production and parameterized testcases val.EFM60303 = "EFM.6.23.01" else: val.EFM60303 = "EFM.6.03.03" if any((concept.qname.namespaceURI in val.disclosureSystem.standardTaxonomiesDict) for concept in val.modelXbrl.nameConcepts.get("UTR",())): val.validateUTR = True
def expected(self): for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ExpectedResult"): expected = pluginXbrlMethod(self) if expected: return expected # default behavior without plugins if self.localName == "testcase": return self.document.basename[:4] #starts with PASS or FAIL elif self.localName == "testGroup": #w3c testcase instanceTestElement = XmlUtil.descendant(self, None, "instanceTest") if instanceTestElement is not None: # take instance first return XmlUtil.descendantAttr(instanceTestElement, None, "expected", "validity") else: schemaTestElement = XmlUtil.descendant(self, None, "schemaTest") if schemaTestElement is not None: return XmlUtil.descendantAttr(schemaTestElement, None, "expected", "validity") resultElement = XmlUtil.descendant(self, None, "result") if resultElement is not None: expected = resultElement.get("expected") if expected and resultElement.get("nonStandardErrorCodes") == "true": # if @expected and @nonStandardErrorCodes then use expected instead of error codes return expected errorElement = XmlUtil.descendant(self, None, "error") resultElement = XmlUtil.descendant(self, None, "result") if errorElement is not None and not errorElement.get("nonStandardErrorCodes"): _errorText = XmlUtil.text(errorElement) if ' ' in _errorText: # list of tokens return _errorText return ModelValue.qname(errorElement, _errorText) # turn into a QName if resultElement is not None: if expected: return expected for assertElement in XmlUtil.children(resultElement, None, "assert"): num = assertElement.get("num") if num == "99999": # inline test, use name as expected return assertElement.get("name") if len(num) == 5: return "EFM.{0}.{1}.{2}".format(num[0],num[1:3],num[3:6]) asserTests = {} for atElt in XmlUtil.children(resultElement, None, "assertionTests"): try: asserTests[atElt.get("assertionID")] = (_INT(atElt.get("countSatisfied")),_INT(atElt.get("countNotSatisfied"))) except ValueError: pass if asserTests: return asserTests elif self.get("result"): return self.get("result") return None
def typeQname(self): if self.get("type"): return self.prefixedNameQname(self.get("type")) else: # check if anonymous type exists typeqname = ModelValue.qname(self.qname.clarkNotation + "@anonymousType") if typeqname in self.modelXbrl.qnameTypes: return typeqname # try substitution group for type ''' HF: I don't think attributes can have a substitution group ?? subs = self.substitutionGroup if subs: return subs.typeQname ''' return None
def sEqual(dts1, elt1, elt2, equalMode=S_EQUAL, excludeIDs=False, dts2=None, ns2ns1Tbl=None): if dts2 is None: dts2 = dts1 if elt1.localName != elt2.localName: return False if ns2ns1Tbl and elt2.namespaceURI in ns2ns1Tbl: if elt1.namespaceURI != ns2ns1Tbl[elt2.namespaceURI]: return False elif elt1.namespaceURI != elt2.namespaceURI: return False # is the element typed? modelConcept1 = dts1.qnameConcepts.get(ModelValue.qname(elt1)) modelConcept2 = dts2.qnameConcepts.get(ModelValue.qname(elt2)) if (not xEqual(modelConcept1, elt1, elt2, equalMode, modelConcept2=modelConcept2) or attributeSet(dts1, modelConcept1, elt1, (), equalMode, excludeIDs) != attributeSet(dts2, modelConcept2, elt2, (), equalMode, excludeIDs, ns2ns1Tbl)): return False children1 = childElements(elt1) children2 = childElements(elt2) if len(children1) != len(children2): return False for i in range( len(children1) ): if not sEqual(dts1, children1[i], children2[i], equalMode, excludeIDs, dts2, ns2ns1Tbl): return False return True
def attributeSet(modelXbrl, modelConcept, elt, exclusions=(), equalMode=S_EQUAL, excludeIDs=False, ns2ns1Tbl=None): attrs = set() for i in range(len(elt.attributes)): attr = elt.attributes.item(i) attrNsURI = attr.namespaceURI if ns2ns1Tbl and attrNsURI in ns2ns1Tbl: attrNsURI = ns2ns1Tbl[attrNsURI] attrName = "{{{0}}}{1}".format( attrNsURI, attr.localName) if attrNsURI else attr.name if (attrName not in exclusions and (attrNsURI is None or attrNsURI not in exclusions) and attr.name not in ("xmlns") and attr.prefix != "xmlns"): if attrNsURI: qname = ModelValue.qname(attrNsURI, attr.localName) else: qname = ModelValue.qname(attr.localName) baseXsdAttrType = None if modelConcept: baseXsdAttrType = modelConcept.baseXsdAttrType( qname) if modelConcept else None if baseXsdAttrType is None: attrObject = modelXbrl.qnameAttributes.get(qname) if attrObject: baseXsdAttrType = attrObject.baseXsdType if excludeIDs and baseXsdAttrType == "ID": continue value = xTypeValue(baseXsdAttrType, elt, attr, attr.value, equalMode) attrs.add((qname, value)) return attrs
def typeQname(self): if self.get("type"): return self.prefixedNameQname(self.get("type")) else: # check if anonymous type exists typeqname = ModelValue.qname(self.qname.clarkNotation + anonymousTypeSuffix) if typeqname in self.modelXbrl.qnameTypes: return typeqname # try substitution group for type ''' HF: I don't think attributes can have a substitution group ?? subs = self.substitutionGroup if subs: return subs.typeQname ''' return None
def validateXbrlStart(val, parameters=None): val.validateHMRCplugin = val.validateDisclosureSystem and getattr(val.disclosureSystem, "HMRCplugin", False) if not (val.validateHMRCplugin): return val.isAccounts = XmlUtil.hasAncestor(val.modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Accounts") val.isComputation = XmlUtil.hasAncestor(val.modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Computation") if parameters: p = parameters.get(ModelValue.qname("type",noPrefixIsNoNamespace=True)) if p and len(p) == 2: # override implicit type paramType = p[1].lower() val.isAccounts = paramType == "accounts" val.isComputation = paramType == "computation"
def validateXbrlStart(val, parameters=None): val.validateHMRCplugin = val.validateDisclosureSystem and getattr( val.disclosureSystem, "HMRCplugin", False) if not (val.validateHMRCplugin): return val.isAccounts = XmlUtil.hasAncestor( val.modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Accounts") val.isComputation = XmlUtil.hasAncestor( val.modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Computation") if parameters: p = parameters.get(ModelValue.qname("type", noPrefixIsNoNamespace=True)) if p and len(p) == 2: # override implicit type paramType = p[1].lower() val.isAccounts = paramType == "accounts" val.isComputation = paramType == "computation"
def readMeFirstUris(self): try: return self._readMeFirstUris except AttributeError: self._readMeFirstUris = [] for anElement in self.iterdescendants(): if isinstance(anElement,ModelObject) and anElement.get("readMeFirst") == "true": if anElement.get("{http://www.w3.org/1999/xlink}href"): uri = anElement.get("{http://www.w3.org/1999/xlink}href") else: uri = XmlUtil.innerText(anElement) if anElement.get("name"): self._readMeFirstUris.append( (ModelValue.qname(anElement, anElement.get("name")), uri) ) elif anElement.get("dts"): self._readMeFirstUris.append( (anElement.get("dts"), uri) ) else: self._readMeFirstUris.append(uri) if not self._readMeFirstUris: # provide a dummy empty instance document self._readMeFirstUris.append(os.path.join(self.modelXbrl.modelManager.cntlr.configDir, "empty-instance.xml")) return self._readMeFirstUris
def expected(self): for pluginXbrlMethod in pluginClassMethods(u"ModelTestcaseVariation.ExpectedResult"): expected = pluginXbrlMethod(self) if expected: return expected # default behavior without plugins if self.localName == u"testcase": return self.document.basename[:4] #starts with PASS or FAIL elif self.localName == u"testGroup": #w3c testcase instanceTestElement = XmlUtil.descendant(self, None, u"instanceTest") if instanceTestElement is not None: # take instance first return XmlUtil.descendantAttr(instanceTestElement, None, u"expected", u"validity") else: schemaTestElement = XmlUtil.descendant(self, None, u"schemaTest") if schemaTestElement is not None: return XmlUtil.descendantAttr(schemaTestElement, None, u"expected", u"validity") errorElement = XmlUtil.descendant(self, None, u"error") if errorElement is not None: return ModelValue.qname(errorElement, XmlUtil.text(errorElement)) resultElement = XmlUtil.descendant(self, None, u"result") if resultElement is not None: expected = resultElement.get(u"expected") if expected: return expected for assertElement in XmlUtil.children(resultElement, None, u"assert"): num = assertElement.get(u"num") if len(num) == 5: return u"EFM.{0}.{1}.{2}".format(num[0],num[1:3],num[3:6]) asserTests = {} for atElt in XmlUtil.children(resultElement, None, u"assertionTests"): try: asserTests[atElt.get(u"assertionID")] = (_INT(atElt.get(u"countSatisfied")),_INT(atElt.get(u"countNotSatisfied"))) except ValueError: pass if asserTests: return asserTests elif self.get(u"result"): return self.get(u"result") return None
def validateXbrlStart(val, parameters=None, *args, **kwargs): val.validateEFMplugin = val.validateDisclosureSystem and getattr( val.disclosureSystem, "EFMplugin", False) if not (val.validateEFMplugin): return val.paramExhibitType = None # e.g., EX-101, EX-201 val.paramFilerIdentifier = None val.paramFilerIdentifierNames = None val.paramSubmissionType = None _cik = _cikList = _cikNameList = _exhibitType = _submissionType = None if parameters: # parameter-provided CIKs and registrant names p = parameters.get(ModelValue.qname("CIK", noPrefixIsNoNamespace=True)) if p and len(p) == 2 and p[1] not in ("null", "None"): _cik = p[1] p = parameters.get( ModelValue.qname("cikList", noPrefixIsNoNamespace=True)) if p and len(p) == 2: _cikList = p[1] else: _cikList = [] p = parameters.get( ModelValue.qname("cikNameList", noPrefixIsNoNamespace=True)) if p and len(p) == 2: _cikNameList = p[1] p = parameters.get( ModelValue.qname("submissionType", noPrefixIsNoNamespace=True)) if p and len(p) == 2: _submissionType = p[1] p = parameters.get( ModelValue.qname("exhibitType", noPrefixIsNoNamespace=True)) if p and len(p) == 2: _exhibitType = p[1] # parameters may also come from report entryPoint (such as exhibitType for SDR) if hasattr(val.modelXbrl.modelManager, "efmFiling"): efmFiling = val.modelXbrl.modelManager.efmFiling if efmFiling.reports: # possible that there are no reports entryPoint = efmFiling.reports[-1].entryPoint _cik = entryPoint.get("cik", None) or _cik _cikList = entryPoint.get("cikList", None) or _cikList _cikNameList = entryPoint.get("cikNameList", None) or _cikNameList _exhibitType = entryPoint.get("exhibitType", None) or _exhibitType # exhibitType may be an attachmentType, if so remove ".INS" if _exhibitType and _exhibitType.endswith(".INS"): _exhibitType = _exhibitType[:-4] _submissionType = entryPoint.get("submissionType", None) or _submissionType if _cik and _cik not in ("null", "None"): val.paramFilerIdentifier = _cik if isinstance(_cikNameList, dict): # {cik1: name1, cik2:name2, ...} provided by json cikNameList dict parameter val.paramFilerIdentifierNames = _cikNameList else: # cik1, cik2, cik3 in cikList and name1|Edgar|name2|Edgar|name3 in cikNameList strings _filerIdentifiers = _cikList.split(",") if _cikList else [] _filerNames = _cikNameList.split("|Edgar|") if _cikNameList else [] if _filerIdentifiers: if len(_filerNames) not in (0, len(_filerIdentifiers)): val.modelXbrl.error( ("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikList and cikNameList different list entry counts: %(cikList)s, %(cikNameList)s" ), modelXbrl=val.modelXbrl, cikList=_filerIdentifiers, cikNameList=_filerNames) elif _filerNames: val.paramFilerIdentifierNames = dict( (_cik, _filerNames[i]) for i, _cik in enumerate(_filerIdentifiers)) else: val.paramFilerIdentifierNames = dict( (_cik, None) for _cik in _filerIdentifiers) elif _filerNames: val.modelXbrl.error( ("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikNameList provided but missing corresponding cikList: %(cikNameList)s" ), modelXbrl=val.modelXbrl, cikNameList=_filerNames) if _exhibitType: val.paramExhibitType = _exhibitType if _submissionType: val.paramSubmissionType = _submissionType if val.paramExhibitType == "EX-2.01": # only applicable for edgar production and parameterized testcases val.EFM60303 = "EFM.6.23.01" else: val.EFM60303 = "EFM.6.03.03" if any((concept.qname.namespaceURI in val.disclosureSystem. standardTaxonomiesDict and concept.modelDocument.inDTS) for concept in val.modelXbrl.nameConcepts.get("UTR", ())): val.validateUTR = True modelManager = val.modelXbrl.modelManager if hasattr(modelManager, "efmFiling"): efmFiling = modelManager.efmFiling efmFiling.submissionType = val.paramSubmissionType
def dereference(self): ref = self.get("ref") if ref: return self.modelXbrl.qnameConcepts.get(ModelValue.qname( self, ref)) return self
def variableQname(self): varName = self.variablename return ModelValue.qname( self.arcElement, varName, noPrefixIsNoNamespace=True) if varName else None
def validateXbrlStart(val, parameters=None, *args, **kwargs): val.validateEFMplugin = val.validateDisclosureSystem and getattr( val.disclosureSystem, "EFMplugin", False) if not (val.validateEFMplugin): return val.params = {} parameterNames = ( "CIK", "cik", "cikList", "cikNameList", "submissionType", "exhibitType", # CIK or cik both allowed "periodOfReport", "entity.fyEnd", "voluntaryFilerFlag", "wellKnownSeasonedIssuerFlag", "shellCompanyFlag", "acceleratedFilerStatus", "smallBusinessFlag", "emergingGrowthCompanyFlag", "exTransitionPeriodFlag", "invCompanyType", "rptIncludeAllSeriesFlag", "rptSeriesClassInfo.seriesIds", "newClass2.seriesIds") if parameters: # parameter-provided CIKs and registrant names for paramName in parameterNames: p = parameters.get( ModelValue.qname(paramName, noPrefixIsNoNamespace=True)) if p and len(p) == 2 and p[1] not in ("null", "None", None): val.params[paramName] = p[1] if "CIK" in val.params: # change to lower case key val.params["cik"] = val.params["CIK"] del val.params["CIK"] p = parameters.get( ModelValue.qname("ELOparams", noPrefixIsNoNamespace=True)) if p and len(p) == 2 and p[1] not in ("null", "None", None): try: for key, value in json.loads(p[1]).items(): val.params[{ "CIK": "cik" }.get(key, key)] = value # change upper case CIK to lower case except (ValueError, AttributeError, TypeError): val.modelXbrl.error( "arelle.testcaseVariationParameters", _("parameter ELOparam has malformed JSON %(json)s object"), modelXbrl=val.modelXbrl, json=p[1][:100]) # parameters may also come from report entryPoint (such as exhibitType for SDR) if hasattr(val.modelXbrl.modelManager, "efmFiling"): efmFiling = val.modelXbrl.modelManager.efmFiling if efmFiling.reports: # possible that there are no reports entryPoint = efmFiling.reports[-1].entryPoint for paramName in parameterNames: # cik is lower case here if paramName in entryPoint and entryPoint[paramName] not in ( None, ""): val.params[paramName] = entryPoint[ paramName] # if not set uses prior value # exhibitType may be an attachmentType, if so remove ".INS" if val.params.get("exhibitType", "").endswith(".INS"): val.params["exhibitType"] = val.params["exhibitType"][:-4] if isinstance(val.params.get("cikNameList", None), str): # cik1, cik2, cik3 in cikList and name1|Edgar|name2|Edgar|name3 in cikNameList strings _filerIdentifiers = val.params["cikList"].split( ",") if "cikList" in val.params else [] _filerNames = val.params["cikNameList"].split( "|Edgar|") if "cikNameList" in val.params else [] if _filerIdentifiers: if len(_filerNames) not in (0, len(_filerIdentifiers)): val.modelXbrl.error( ("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikList and cikNameList different list entry counts: %(cikList)s, %(cikNameList)s" ), modelXbrl=val.modelXbrl, cikList=_filerIdentifiers, cikNameList=_filerNames) if _filerNames: val.params["cikNameList"] = dict( (_cik, _filerNames[i] if i < len(_filerNames) else None) for i, _cik in enumerate(_filerIdentifiers)) else: val.params["cikNameList"] = dict( (_cik, None) for _cik in _filerIdentifiers) del val.params["cikList"] elif _filerNames: val.modelXbrl.error( ("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikNameList provided but missing corresponding cikList: %(cikNameList)s" ), modelXbrl=val.modelXbrl, cikNameList=_filerNames) del val.params[ "cikNameList"] # can't process without cik's as keys if val.params.get( "exhibitType", "" ) == "EX-2.01": # only applicable for edgar production and parameterized testcases val.EFM60303 = "EFM.6.23.01" else: val.EFM60303 = "EFM.6.03.03" if any((concept.qname.namespaceURI in val.disclosureSystem. standardTaxonomiesDict and concept.modelDocument.inDTS) for concept in val.modelXbrl.nameConcepts.get("UTR", ())): val.validateUTR = True modelManager = val.modelXbrl.modelManager if hasattr(modelManager, "efmFiling"): efmFiling = modelManager.efmFiling efmFiling.submissionType = val.params.get("submissionType")
def dereference(self): ref = self.get("ref") if ref: return self.modelXbrl.qnameAttributeGroups.get( ModelValue.qname(self, ref)) return self
def validate(self, modelXbrl, parameters=None): if not hasattr(modelXbrl.modelDocument, "xmlDocument"): # not parsed return busNamespacePattern = re.compile(r"^http://www\.xbrl\.org/uk/cd/business") gaapNamespacePattern = re.compile(r"^http://www\.xbrl\.org/uk/gaap/core") ifrsNamespacePattern = re.compile(r"^http://www\.iasb\.org/.*ifrs") direpNamespacePattern = re.compile(r"^http://www\.xbrl\.org/uk/reports/direp") labelHasNegativeTermPattern = re.compile(r".*[(].*\w.*[)].*") # note that some XFM tests are done by ValidateXbrl to prevent mulstiple node walks super(ValidateHmrc,self).validate(modelXbrl, parameters) xbrlInstDoc = modelXbrl.modelDocument.xmlDocument self.modelXbrl = modelXbrl modelXbrl.modelManager.showStatus(_("validating {0}").format(self.disclosureSystem.name)) isAccounts = XmlUtil.hasAncestor(modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Accounts") isComputation = XmlUtil.hasAncestor(modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Computation") if parameters: p = self.parameters.get(ModelValue.qname("type",noPrefixIsNoNamespace=True)) if p and len(p) == 2: # override implicit type paramType = p[1].lower() isAccounts = paramType == "accounts" isComputation = paramType == "computation" # instance checks if modelXbrl.modelDocument.type == ModelDocument.Type.INSTANCE or \ modelXbrl.modelDocument.type == ModelDocument.Type.INLINEXBRL: companyReferenceNumberContexts = defaultdict(list) for c1 in modelXbrl.contexts.values(): if c1 is not None: scheme, identifier = c1.entityIdentifier if scheme == "http://www.companieshouse.gov.uk/": companyReferenceNumberContexts[identifier].append(c1.id) busLocalNames = { "EntityCurrentLegalOrRegisteredName", "StartDateForPeriodCoveredByReport", "EndDateForPeriodCoveredByReport", "BalanceSheetDate", "DateApprovalAccounts", "NameDirectorSigningAccounts", "EntityDormant", "EntityTrading", "UKCompaniesHouseRegisteredNumber" } busItems = {} gaapLocalNames = { "DateApprovalAccounts", "NameDirectorSigningAccounts", "ProfitLossForPeriod" } gaapItems = {} ifrsLocalNames = { "DateAuthorisationFinancialStatementsForIssue", "ExplanationOfBodyOfAuthorisation", "ProfitLoss" } ifrsItems = {} direpLocalNames = { "DateSigningDirectorsReport", "DirectorSigningReport" } direpItems = {} uniqueFacts = {} # key = (qname, context hash, unit hash, lang) def checkFacts(facts): for f1 in facts: context = f1.context unit = f1.unit if getattr(f1,"xValid", 0) >= 4: factNamespaceURI = f1.qname.namespaceURI factLocalName = f1.qname.localName if busNamespacePattern.match(factNamespaceURI) and factLocalName in busLocalNames: busItems[factLocalName] = f1 elif gaapNamespacePattern.match(factNamespaceURI) and factLocalName in gaapLocalNames: gaapItems[factLocalName] = f1 elif ifrsNamespacePattern.match(factNamespaceURI) and factLocalName in ifrsLocalNames: ifrsItems[factLocalName] = f1 elif direpNamespacePattern.match(factNamespaceURI) and factLocalName in direpLocalNames: direpItems[factLocalName] = f1 dupKey = (f1.concept, context.contextDimAwareHash if context is not None else None, unit.hash if unit is not None else None, f1.xmlLang) if context is not None: if f1 in uniqueFacts: f2 = uniqueFacts[f1] if (f1.effectiveValue != f2.effectiveValue): modelXbrl.error("HMRC.14", _("Inconsistent duplicate facts %(fact)s context %(contextID)s and %(contextID2)s."), modelObject=(f1, f2), fact=f1.qname, contextID=f1.contextID, contextID2=f2.contextID) uniqueFacts[dupKey] = f1 if f1.isNumeric: if f1.precision: modelXbrl.error("HMRC.5.4", _("Numeric fact %(fact)s of context %(contextID)s has a precision attribute '%(precision)s'"), modelObject=f1, fact=f1.qname, contextID=f1.contextID, precision=f1.precision) try: # only process validated facts if f1.xValue < 0: label = f1.concept.label(lang="en") if not labelHasNegativeTermPattern.match(label): modelXbrl.error("HMRC.5.3", _("Numeric fact %(fact)s of context %(contextID)s has a negative value '%(value)s' but label does not have a bracketed negative term (using parentheses): %(label)s"), modelObject=f1, fact=f1.qname, contextID=f1.contextID, value=f1.value, label=label) except AttributeError: pass # if not validated it should have failed with a schema error if f1.modelTupleFacts: checkFacts(f1.modelTupleFacts) checkFacts(modelXbrl.facts) if isAccounts: if "StartDateForPeriodCoveredByReport" not in busItems: modelXbrl.error("HMRC.02", _("Period Start Date (uk-bus:StartDateForPeriodCoveredByReport) is missing."), modelObject=modelXbrl) elif busItems["StartDateForPeriodCoveredByReport"].value < "2008-04-06": modelXbrl.error("HMRC.02", _("Period Start Date (uk-bus:StartDateForPeriodCoveredByReport) must be 6 April 2008 or later."), modelObject=modelXbrl) for items, name, msg, ref in ( (busItems,"EntityCurrentLegalOrRegisteredName", _("Company Name (uk-bus:EntityCurrentLegalOrRegisteredName) is missing."), "01"), (busItems,"EndDateForPeriodCoveredByReport", _("Period End Date (uk-bus:EndDateForPeriodCoveredByReport) is missing."), "03"), (busItems,"BalanceSheetDate", _("Balance Sheet Date (uk-bus:BalanceSheetDate) is missing."), "06"), (busItems,"EntityDormant", _("Dormant/non-dormant indicator (uk-bus:EntityDormant) is missing."), "09"), (busItems,"EntityTrading", _("Trading/non-trading indicator (uk-bus:EntityTrading) is missing."), "10"), (direpItems,"DateSigningDirectorsReport", _("Date of signing Directors Report (uk-direp:DateSigningDirectorsReport) is missing."), "12"), (direpItems,"DirectorSigningReport", _("Name of Director signing Directors Report (uk-direp:DirectorSigningReport) is missing."), "13"), ): if name not in items: modelXbrl.error("HMRC.{0}".format(ref), msg, modelObject=modelXbrl, messageCodes=("HMRC.01","HMRC.03","HMRC.06","HMRC.09","HMRC.10","HMRC.12","HMRC.13")) if ("DateApprovalAccounts" not in gaapItems and "DateAuthorisationFinancialStatementsForIssue" not in ifrsItems): modelXbrl.error("HMRC.07", _("Balance Sheet Date of Approval (uk-gaap:DateApprovalAccounts) is missing OR Balance Sheet Date of Approval (uk-ifrs:DateAuthorisationFinancialStatementsForIssue) is missing."), modelObject=modelXbrl) if ("NameDirectorSigningAccounts" not in gaapItems and "ExplanationOfBodyOfAuthorisation" not in ifrsItems): modelXbrl.error("HMRC.08", _("Name of Director Approving Balance Sheet (uk-gaap:NameDirectorSigningAccounts) is missing OR Name of Director Approving Balance Sheet (ifrs:ExplanationOfBodyOfAuthorisation) is missing."), modelObject=modelXbrl) if ("ProfitLossForPeriod" not in gaapItems and "ProfitLoss" not in ifrsItems): modelXbrl.error("HMRC.11", _("Profit or Loss for the period (uk-gaap:ProfitLossForPeriod OR ifrs:ProfitLoss) is missing."), modelObject=modelXbrl) if companyReferenceNumberContexts: if "UKCompaniesHouseRegisteredNumber" not in busItems: modelXbrl.error("HMRC.16.1", _("Company Reference Number (uk-bus:UKCompaniesHouseRegisteredNumber) is missing."), modelObject=modelXbrl) else: factCompNbr = busItems["UKCompaniesHouseRegisteredNumber"].value for compRefNbr, contextIds in companyReferenceNumberContexts.items(): if compRefNbr != factCompNbr: modelXbrl.error("HMRC.16.2", _("Context entity identifier (%(entityIdentifier)s) does not match Company Reference Number (uk-bus:UKCompaniesHouseRegisteredNumber) Location: Accounts (context id %(contextID)s)."), modelObject=modelXbrl, entityIdentifier=compRefNbr, contextID=",".join(contextIds)) modelXbrl.modelManager.showStatus(_("ready"), 2000)
def ancestorQnames(self): try: return self._ancestorQnames except AttributeError: self._ancestorQnames = set( ModelValue.qname(ancestor) for ancestor in self.iterancestors() ) return self._ancestorQnames
def variableQname(self): varName = self.variablename return ModelValue.qname(self.arcElement, varName, noPrefixIsNoNamespace=True) if varName else None
def dereference(self): ref = self.get("ref") if ref: return self.modelXbrl.qnameAttributeGroups.get(ModelValue.qname(self, ref)) return self
def validate(self, modelXbrl, parameters=None): if not hasattr(modelXbrl.modelDocument, "xmlDocument"): # not parsed return busNamespacePattern = re.compile( r"^http://www\.xbrl\.org/uk/cd/business") gaapNamespacePattern = re.compile( r"^http://www\.xbrl\.org/uk/gaap/core") ifrsNamespacePattern = re.compile(r"^http://www\.iasb\.org/.*ifrs") direpNamespacePattern = re.compile( r"^http://www\.xbrl\.org/uk/reports/direp") labelHasNegativeTermPattern = re.compile(r".*[(].*\w.*[)].*") # note that some XFM tests are done by ValidateXbrl to prevent mulstiple node walks super(ValidateHmrc, self).validate(modelXbrl, parameters) xbrlInstDoc = modelXbrl.modelDocument.xmlDocument self.modelXbrl = modelXbrl modelXbrl.modelManager.showStatus( _("validating {0}").format(self.disclosureSystem.name)) isAccounts = XmlUtil.hasAncestor( modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Accounts") isComputation = XmlUtil.hasAncestor( modelXbrl.modelDocument.xmlRootElement, "http://www.govtalk.gov.uk/taxation/CT/3", "Computation") if parameters: p = self.parameters.get( ModelValue.qname("type", noPrefixIsNoNamespace=True)) if p and len(p) == 2: # override implicit type paramType = p[1].lower() isAccounts = paramType == "accounts" isComputation = paramType == "computation" # instance checks if modelXbrl.modelDocument.type == ModelDocument.Type.INSTANCE or \ modelXbrl.modelDocument.type == ModelDocument.Type.INLINEXBRL: companyReferenceNumberContexts = defaultdict(list) for c1 in modelXbrl.contexts.values(): scheme, identifier = c1.entityIdentifier if scheme == "http://www.companieshouse.gov.uk/": companyReferenceNumberContexts[identifier].append(c1.id) busLocalNames = { "EntityCurrentLegalOrRegisteredName", "StartDateForPeriodCoveredByReport", "EndDateForPeriodCoveredByReport", "BalanceSheetDate", "DateApprovalAccounts", "NameDirectorSigningAccounts", "EntityDormant", "EntityTrading", "UKCompaniesHouseRegisteredNumber" } busItems = {} gaapLocalNames = { "DateApprovalAccounts", "NameDirectorSigningAccounts", "ProfitLossForPeriod" } gaapItems = {} ifrsLocalNames = { "DateAuthorisationFinancialStatementsForIssue", "ExplanationOfBodyOfAuthorisation", "ProfitLoss" } ifrsItems = {} direpLocalNames = { "DateSigningDirectorsReport", "DirectorSigningReport" } direpItems = {} uniqueFacts = {} # key = (qname, context hash, unit hash, lang) def checkFacts(facts): for f1 in facts: context = f1.context unit = f1.unit if getattr(f1, "xValid", 0) >= 4: factNamespaceURI = f1.qname.namespaceURI factLocalName = f1.qname.localName if busNamespacePattern.match( factNamespaceURI ) and factLocalName in busLocalNames: busItems[factLocalName] = f1 elif gaapNamespacePattern.match( factNamespaceURI ) and factLocalName in gaapLocalNames: gaapItems[factLocalName] = f1 elif ifrsNamespacePattern.match( factNamespaceURI ) and factLocalName in ifrsLocalNames: ifrsItems[factLocalName] = f1 elif direpNamespacePattern.match( factNamespaceURI ) and factLocalName in direpLocalNames: direpItems[factLocalName] = f1 dupKey = (f1.concept, context.contextDimAwareHash if context is not None else None, unit.hash if unit is not None else None, f1.xmlLang) if context is not None: if f1 in uniqueFacts: f2 = uniqueFacts[f1] if (f1.effectiveValue != f2.effectiveValue): modelXbrl.error( "HMRC.14", _("Inconsistent duplicate facts %(fact)s context %(contextID)s and %(contextID2)s." ), modelObject=(f1, f2), fact=f1.qname, contextID=f1.contextID, contextID2=f2.contextID) uniqueFacts[dupKey] = f1 if f1.isNumeric: if f1.precision: modelXbrl.error( "HMRC.5.4", _("Numeric fact %(fact)s of context %(contextID)s has a precision attribute '%(precision)s'" ), modelObject=f1, fact=f1.qname, contextID=f1.contextID, precision=f1.precision) try: # only process validated facts if f1.xValue < 0: label = f1.concept.label(lang="en") if not labelHasNegativeTermPattern.match( label): modelXbrl.error( "HMRC.5.3", _("Numeric fact %(fact)s of context %(contextID)s has a negative value '%(value)s' but label does not have a bracketed negative term (using parentheses): %(label)s" ), modelObject=f1, fact=f1.qname, contextID=f1.contextID, value=f1.value, label=label) except AttributeError: pass # if not validated it should have failed with a schema error if f1.modelTupleFacts: checkFacts(f1.modelTupleFacts) checkFacts(modelXbrl.facts) if isAccounts: if "StartDateForPeriodCoveredByReport" not in busItems: modelXbrl.error( "HMRC.02", _("Period Start Date (uk-bus:StartDateForPeriodCoveredByReport) is missing." ), modelObject=modelXbrl) elif busItems[ "StartDateForPeriodCoveredByReport"].value < "2008-04-06": modelXbrl.error( "HMRC.02", _("Period Start Date (uk-bus:StartDateForPeriodCoveredByReport) must be 6 April 2008 or later." ), modelObject=modelXbrl) for items, name, msg, ref in ( (busItems, "EntityCurrentLegalOrRegisteredName", _("Company Name (uk-bus:EntityCurrentLegalOrRegisteredName) is missing." ), "01"), (busItems, "EndDateForPeriodCoveredByReport", _("Period End Date (uk-bus:EndDateForPeriodCoveredByReport) is missing." ), "03"), (busItems, "BalanceSheetDate", _("Balance Sheet Date (uk-bus:BalanceSheetDate) is missing." ), "06"), (busItems, "EntityDormant", _("Dormant/non-dormant indicator (uk-bus:EntityDormant) is missing." ), "09"), (busItems, "EntityTrading", _("Trading/non-trading indicator (uk-bus:EntityTrading) is missing." ), "10"), (direpItems, "DateSigningDirectorsReport", _("Date of signing Directors Report (uk-direp:DateSigningDirectorsReport) is missing." ), "12"), (direpItems, "DirectorSigningReport", _("Name of Director signing Directors Report (uk-direp:DirectorSigningReport) is missing." ), "13"), ): if name not in items: modelXbrl.error("HMRC.{0}".format(ref), msg, modelObject=modelXbrl, messageCodes=("HMRC.01", "HMRC.03", "HMRC.06", "HMRC.09", "HMRC.10", "HMRC.12", "HMRC.13")) if ("DateApprovalAccounts" not in gaapItems and "DateAuthorisationFinancialStatementsForIssue" not in ifrsItems): modelXbrl.error( "HMRC.07", _("Balance Sheet Date of Approval (uk-gaap:DateApprovalAccounts) is missing OR Balance Sheet Date of Approval (uk-ifrs:DateAuthorisationFinancialStatementsForIssue) is missing." ), modelObject=modelXbrl) if ("NameDirectorSigningAccounts" not in gaapItems and "ExplanationOfBodyOfAuthorisation" not in ifrsItems): modelXbrl.error( "HMRC.08", _("Name of Director Approving Balance Sheet (uk-gaap:NameDirectorSigningAccounts) is missing OR Name of Director Approving Balance Sheet (ifrs:ExplanationOfBodyOfAuthorisation) is missing." ), modelObject=modelXbrl) if ("ProfitLossForPeriod" not in gaapItems and "ProfitLoss" not in ifrsItems): modelXbrl.error( "HMRC.11", _("Profit or Loss for the period (uk-gaap:ProfitLossForPeriod OR ifrs:ProfitLoss) is missing." ), modelObject=modelXbrl) if companyReferenceNumberContexts: if "UKCompaniesHouseRegisteredNumber" not in busItems: modelXbrl.error( "HMRC.16.1", _("Company Reference Number (uk-bus:UKCompaniesHouseRegisteredNumber) is missing." ), modelObject=modelXbrl) else: factCompNbr = busItems[ "UKCompaniesHouseRegisteredNumber"].value for compRefNbr, contextIds in companyReferenceNumberContexts.items( ): if compRefNbr != factCompNbr: modelXbrl.error( "HMRC.16.2", _("Context entity identifier (%(entityIdentifier)s) does not match Company Reference Number (uk-bus:UKCompaniesHouseRegisteredNumber) Location: Accounts (context id %(contextID)s)." ), modelObject=modelXbrl, entityIdentifier=compRefNbr, contextID=",".join(contextIds)) modelXbrl.modelManager.showStatus(_("ready"), 2000)
def validateXbrlStart(val, parameters=None, *args, **kwargs): val.validateEFMplugin = val.validateDisclosureSystem and getattr(val.disclosureSystem, "EFMplugin", False) if not (val.validateEFMplugin): return val.params = {} parameterNames = ("CIK", "cik", "cikList", "cikNameList", "submissionType", "exhibitType", # CIK or cik both allowed "itemsList", "accessionNumber", "entity.repFileNum", "periodOfReport", "entityRegistration.fyEnd", "submissionHeader.fyEnd", "voluntaryFilerFlag", "wellKnownSeasonedIssuerFlag", "shellCompanyFlag", "acceleratedFilerStatus", "smallBusinessFlag", "emergingGrowthCompanyFlag", "exTransitionPeriodFlag", "invCompanyType", "rptIncludeAllSeriesFlag", "rptSeriesClassInfo.seriesIds", "newClass2.seriesIds", "eligibleFundFlag", "pursuantGeneralInstructionFlag", "filerNewRegistrantFlag", "datetimeForTesting") parameterEisFileTags = { "cik":["depositorId", "cik", "filerId"], "submissionType": "submissionType", "itemsList": "item", "periodOfReport": "periodOfReport", #"headerFyEnd": ?, #"voluntaryFilerFlag": ?, "wellKnownSeasonedIssuerFlag": "wellKnownSeasonedIssuerFlag", #"shellCompanyFlag": ?, "acceleratedFilerStatus": "acceleratedFilerStatus", "smallBusinessFlag": "smallBusinessFlag", "emergingGrowthCompanyFlag": "emergingGrowthCompanyFlag", "exTransitionPeriodFlag": "exTransitionPeriodFlag", "invCompanyType": "invCompany", #"rptIncludeAllSeriesFlag": ?, #"rptSeriesClassInfo.seriesIds": ?, #"newClass2.seriesIds": ?, "filerNewRegistrantFlag": "filerNewRegistrantFlag", "pursuantGeneralInstructionFlag": "pursuantGeneralInstructionFlag", "eligibleFundFlag": "eligibleFundFlag" } # retrieve any EIS file parameters first if val.modelXbrl.fileSource and val.modelXbrl.fileSource.isEis and hasattr(val.modelXbrl.fileSource, "eisDocument"): eisDoc = val.modelXbrl.fileSource.eisDocument for paramName, eisEltNames in parameterEisFileTags.items(): paramQName = ModelValue.qname(paramName,noPrefixIsNoNamespace=True) for eisElt in eisDoc.iter(*("{*}"+e for e in flattenSequence(eisEltNames))): if paramName in ("itemsList",): parameters.setdefault(paramQName, []).append(eisElt.text) else: parameters[paramQName] = ("", "".join(eisElt.itertext()).strip()) if parameters: # parameter-provided CIKs and registrant names for paramName in parameterNames: p = parameters.get(ModelValue.qname(paramName,noPrefixIsNoNamespace=True)) if p and len(p) == 2 and p[1] not in ("null", "None", None): v = p[1] # formula dialog and cmd line formula parameters may need type conversion if isinstance(v, str): if paramName in {"voluntaryFilerFlag", "wellKnownSeasonedIssuerFlag", "shellCompanyFlag", "acceleratedFilerStatus", "smallBusinessFlag", "emergingGrowthCompanyFlag", "exTransitionPeriodFlag", "rptIncludeAllSeriesFlag", "filerNewRegistrantFlag", "pursuantGeneralInstructionFlag", "eligibleFundFlag"}: v = {"true":True, "false":False}.get(v) elif paramName in {"itemsList", "rptSeriesClassInfo.seriesIds", "newClass2.seriesIds"}: v = v.split() val.params[paramName] = v if "CIK" in val.params: # change to lower case key val.params["cik"] = val.params["CIK"] del val.params["CIK"] for paramName, p in parameters.items(): # allow ELOparams to be in any namespace (no xmlns="" required) if paramName and paramName.localName == "ELOparams" and len(p) == 2 and p[1] not in ("null", "None", None): try: for key, value in json.loads(p[1]).items(): val.params[{"CIK":"cik"}.get(key,key)] = value # change upper case CIK to lower case except (ValueError, AttributeError, TypeError): val.modelXbrl.error("arelle.testcaseVariationParameters", _("parameter ELOparams has malformed JSON %(json)s object"), modelXbrl=val.modelXbrl, json=p[1][:100]) break # parameters may also come from report entryPoint (such as exhibitType for SDR) if hasattr(val.modelXbrl.modelManager, "efmFiling"): efmFiling = val.modelXbrl.modelManager.efmFiling if efmFiling.reports: # possible that there are no reports entryPoint = efmFiling.reports[-1].entryPoint for paramName in parameterNames: # cik is lower case here if paramName in entryPoint and entryPoint[paramName] not in (None, ""): val.params[paramName] = entryPoint[paramName] # if not set uses prior value # exhibitType may be an attachmentType, if so remove ".INS" if val.params.get("exhibitType", "").endswith(".INS"): val.params["exhibitType"] = val.params["exhibitType"][:-4] if isinstance(val.params.get("cikNameList", None), str): # cik1, cik2, cik3 in cikList and name1|Edgar|name2|Edgar|name3 in cikNameList strings _filerIdentifiers = val.params["cikList"].split(",") if "cikList" in val.params else [] _filerNames = val.params["cikNameList"].split("|Edgar|") if "cikNameList" in val.params else [] if _filerIdentifiers: if len(_filerNames) not in (0, len(_filerIdentifiers)): val.modelXbrl.error(("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikList and cikNameList different list entry counts: %(cikList)s, %(cikNameList)s"), modelXbrl=val.modelXbrl, cikList=_filerIdentifiers, cikNameList=_filerNames) if _filerNames: val.params["cikNameList"]=dict((_cik,_filerNames[i] if i < len(_filerNames) else None) for i, _cik in enumerate(_filerIdentifiers)) else: val.params["cikNameList"]=dict((_cik,None) for _cik in _filerIdentifiers) del val.params["cikList"] elif _filerNames: val.modelXbrl.error(("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikNameList provided but missing corresponding cikList: %(cikNameList)s"), modelXbrl=val.modelXbrl, cikNameList=_filerNames) del val.params["cikNameList"] # can't process without cik's as keys if val.params.get("exhibitType", "") == "EX-2.01": # only applicable for edgar production and parameterized testcases val.EFM60303 = "EFM.6.23.01" else: val.EFM60303 = "EFM.6.03.03" if any((concept.qname.namespaceURI in val.disclosureSystem.standardTaxonomiesDict and concept.modelDocument.inDTS) for concept in val.modelXbrl.nameConcepts.get("UTR",())): val.validateUTR = True modelManager = val.modelXbrl.modelManager if hasattr(modelManager, "efmFiling"): efmFiling = modelManager.efmFiling efmFiling.submissionType = val.params.get("submissionType")
def MeasureQName(node): # Return the qame of the content of the measure element assert node.nodeType == xml.dom.Node.ELEMENT_NODE assert node.localName == "measure" assert node.namespaceUri == XbrlConst.xbrli return ModelValue.qname(node, node.text)
def dereference(self): ref = self.get("ref") if ref: return self.modelXbrl.qnameConcepts.get(ModelValue.qname(self, ref)) return self
def dereference(self): ref = self.get("ref") if ref: return self.modelXbrl.qnameGroupDefinitions.get(ModelValue.qname(self, ref)) return self
def validateXbrlStart(val, parameters=None, *args, **kwargs): val.validateEFMplugin = val.validateDisclosureSystem and getattr(val.disclosureSystem, "EFMplugin", False) if not (val.validateEFMplugin): return val.paramExhibitType = None # e.g., EX-101, EX-201 val.paramFilerIdentifier = None val.paramFilerIdentifierNames = None val.paramSubmissionType = None _cik = _cikList = _cikNameList = _exhibitType = _submissionType = None if parameters: # parameter-provided CIKs and registrant names p = parameters.get(ModelValue.qname("CIK",noPrefixIsNoNamespace=True)) if p and len(p) == 2 and p[1] not in ("null", "None"): _cik = p[1] p = parameters.get(ModelValue.qname("cikList",noPrefixIsNoNamespace=True)) if p and len(p) == 2: _cikList = p[1] else: _cikList = [] p = parameters.get(ModelValue.qname("cikNameList",noPrefixIsNoNamespace=True)) if p and len(p) == 2: _cikNameList = p[1] p = parameters.get(ModelValue.qname("submissionType",noPrefixIsNoNamespace=True)) if p and len(p) == 2: _submissionType = p[1] p = parameters.get(ModelValue.qname("exhibitType",noPrefixIsNoNamespace=True)) if p and len(p) == 2: _exhibitType = p[1] # parameters may also come from report entryPoint (such as exhibitType for SDR) if hasattr(val.modelXbrl.modelManager, "efmFiling"): efmFiling = val.modelXbrl.modelManager.efmFiling if efmFiling.reports: # possible that there are no reports entryPoint = efmFiling.reports[-1].entryPoint _cik = entryPoint.get("cik", None) or _cik _cikList = entryPoint.get("cikList", None) or _cikList _cikNameList = entryPoint.get("cikNameList",None) or _cikNameList _exhibitType = entryPoint.get("exhibitType", None) or _exhibitType # exhibitType may be an attachmentType, if so remove ".INS" if _exhibitType and _exhibitType.endswith(".INS"): _exhibitType = _exhibitType[:-4] _submissionType = entryPoint.get("submissionType", None) or _submissionType if _cik and _cik not in ("null", "None"): val.paramFilerIdentifier = _cik if isinstance(_cikNameList, dict): # {cik1: name1, cik2:name2, ...} provided by json cikNameList dict parameter val.paramFilerIdentifierNames = _cikNameList else: # cik1, cik2, cik3 in cikList and name1|Edgar|name2|Edgar|name3 in cikNameList strings _filerIdentifiers = _cikList.split(",") if _cikList else [] _filerNames = _cikNameList.split("|Edgar|") if _cikNameList else [] if _filerIdentifiers: if len(_filerNames) not in (0, len(_filerIdentifiers)): val.modelXbrl.error(("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikList and cikNameList different list entry counts: %(cikList)s, %(cikNameList)s"), modelXbrl=val.modelXbrl, cikList=_filerIdentifiers, cikNameList=_filerNames) elif _filerNames: val.paramFilerIdentifierNames=dict((_cik,_filerNames[i]) for i, _cik in enumerate(_filerIdentifiers)) else: val.paramFilerIdentifierNames=dict((_cik,None) for _cik in _filerIdentifiers) elif _filerNames: val.modelXbrl.error(("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikNameList provided but missing corresponding cikList: %(cikNameList)s"), modelXbrl=val.modelXbrl, cikNameList=_filerNames) if _exhibitType: val.paramExhibitType = _exhibitType if _submissionType: val.paramSubmissionType = _submissionType if val.paramExhibitType == "EX-2.01": # only applicable for edgar production and parameterized testcases val.EFM60303 = "EFM.6.23.01" else: val.EFM60303 = "EFM.6.03.03" if any((concept.qname.namespaceURI in val.disclosureSystem.standardTaxonomiesDict) for concept in val.modelXbrl.nameConcepts.get("UTR",())): val.validateUTR = True modelManager = val.modelXbrl.modelManager if hasattr(modelManager, "efmFiling"): efmFiling = modelManager.efmFiling efmFiling.submissionType = val.paramSubmissionType
def dereference(self): ref = self.get("ref") if ref: return self.modelXbrl.qnameGroupDefinitions.get( ModelValue.qname(self, ref)) return self