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"),noPrefixIsNoNamespace=True), (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")), # 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 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 typeQname(self): try: return self._typeQname except AttributeError: if self.get("type"): self._typeQname = self.prefixedNameQname(self.get("type")) else: # check if anonymous type exists (clark qname tag + suffix) qn = self.qname if qn is not None: typeQname = ModelValue.QName( qn.prefix, qn.namespaceURI, qn.localName + anonymousTypeSuffix) else: typeQname = None if typeQname in self.modelXbrl.qnameTypes: self._typeQname = typeQname else: # try substitution group for type subs = self.substitutionGroup if subs is not None: self._typeQname = subs.typeQname else: self._typeQname = XbrlConst.qnXsdDefaultType return self._typeQname
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 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 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 dateTimeInstantEnd(xc, p, source): if isinstance(source, datetime.datetime): return source # true for either datetime.date or datetime.datetime return ModelValue.dateTime(source, addOneDay=True, type=ModelValue.DATETIME, castException=FORG0001)
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(self): try: return self._xsdQname except AttributeError: name = self.name if self.name: if self.parentQname == XbrlConst.qnXsdSchema or self.isQualifiedForm: prefix = XmlUtil.xmlnsprefix( self.modelDocument.xmlRootElement, self.modelDocument.targetNamespace) self._xsdQname = ModelValue.QName( prefix, self.modelDocument.targetNamespace, name) else: self._xsdQname = ModelValue.QName(None, None, name) else: self._xsdQname = None return self._xsdQname
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 gYear(xc, p, source): try: match = lexicalPatterns['gYear'].match(source) if match: year, zSign, zHrMin, zHr, zMin = match.groups() return ModelValue.gYear(year) except (ValueError, TypeError): pass raise FORG0001
def gDay(xc, p, source): try: match = lexicalPatterns['gDay'].match(source) if match: day, zSign, zHrMin, zHr, zMin = match.groups() return ModelValue.gDay(day) except (ValueError, TypeError): pass raise FORG0001
def gMonth(xc, p, source): try: match = lexicalPatterns['gMonth'].match(source) if match: month, zSign, zHrMin, zHr, zMin = match.groups() return ModelValue.gMonth(month) except (ValueError, TypeError): pass raise FORG0001
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 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 + "@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 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 gMonthDay(xc, p, source): try: match = lexicalPatterns['gMonthDay'].match(source) if match: month, day, zSign, zHrMin, zHr, zMin = match.groups() if not int(day) > { 2: 29, 4: 30, 6: 30, 9: 30, 11: 30, 1: 31, 3: 31, 5: 31, 7: 31, 8: 31, 10: 31, 12: 31 }[int(month)]: return ModelValue.gMonthDay(month, day) except (ValueError, TypeError): pass raise FORG0001
def dateTimeInstantEnd(xc, p, source): if isinstance(source,datetime.datetime): return source # true for either datetime.date or datetime.datetime return ModelValue.dateTime(source, addOneDay=True, type=ModelValue.DATETIME, castException=FORG0001)
def dateTime(xc, p, source): if isinstance(source, datetime.datetime): return source return ModelValue.dateTime(source, type=ModelValue.DATETIME, castException=FORG0001)
def anyURI(xc, p, source): return ModelValue.anyURI(source)
def dayTimeDuration(xc, p, source): return ModelValue.dayTimeDuration(source)
def variableQname(self): varName = self.variablename return ModelValue.qname(self.arcElement, varName, noPrefixIsNoNamespace=True) if varName else None
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 time(xc, p, source): return ModelValue.time(source, castException=FORG0001)
def xbrliDateUnion(xc, p, source): if isinstance(source, datetime.date): return source # true for either datetime.date or datetime.datetime return ModelValue.dateTime(source, type=ModelValue.DATEUNION, castException=FORG0001)
def dateTime(xc, p, source): if isinstance(source,datetime.datetime): return source return ModelValue.dateTime(source, type=ModelValue.DATETIME, castException=FORG0001)
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 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 dereference(self): ref = self.get("ref") if ref: return self.modelXbrl.qnameConcepts.get(ModelValue.qname(self, ref)) return self
def date(xc, p, source): return ModelValue.dateTime(source, type=ModelValue.DATE, castException=FORG0001)
def xbrliDateUnion(xc, p, source): if isinstance(source,datetime.date): return source # true for either datetime.date or datetime.datetime return ModelValue.dateTime(source, type=ModelValue.DATEUNION, castException=FORG0001)
def yearMonthDuration(xc, p, source): return ModelValue.yearMonthDuration(source)
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.qnameAttributeGroups.get(ModelValue.qname(self, ref)) return self