def uncovered_aspect(xc, p, args): from arelle.ModelFormulaObject import aspectFromToken, Aspect from arelle.FormulaEvaluator import uncoveredAspectValue if len(args) not in (1,2): raise XPathContext.FunctionNumArgs() aspect = aspectFromToken.get(stringArg(xc, args, 0, "xs:token").strip()) if aspect == Aspect.DIMENSIONS: qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) # check function use after checking argument types if xc.progHeader is not None and xc.progHeader.element is not None: if xc.progHeader.element.localName not in ("formula", "consistencyAssertion", "valueAssertion", "message"): raise XPathContext.XPathException(p, 'xffe:invalidFunctionUse', _('Function xff:uncovered-aspect cannot be used on an XPath expression associated with a {0}').format(xc.progHeader.element.localName)) if xc.variableSet is not None and xc.variableSet.implicitFiltering == "false": raise XPathContext.XPathException(p, 'xffe:invalidFunctionUse', _('Function xff:uncovered-aspect cannot be used with implicitFiltering=false')) if aspect == Aspect.DIMENSIONS: if qn: modelConcept = xc.modelXbrl.qnameConcepts.get(qn) if modelConcept is not None and modelConcept.isDimensionItem: aspect = qn else: return () # not a dimension dimValue = uncoveredAspectValue(xc, aspect) if isinstance(dimValue, ModelDimensionValue): if dimValue.isExplicit: return dimValue.memberQname elif dimValue.isTyped: return dimValue # return the typedMember element, not its contents elif isinstance(dimValue, QName): # qname for explicit or node for typed return dimValue return () aspectValue = uncoveredAspectValue(xc, aspect) if aspectValue is None: return () return aspectValue
def QName_functions(xc, p, args, prefix=False, localName=False, namespaceURI=False): qn = qnameArg(xc, p, args, 0, 'QName?', emptyFallback=()) if qn != (): if prefix: return qn.prefix if localName: return qn.localName if namespaceURI: return qn.namespaceURI return ()
def fact_explicit_dimension_value_value(xc, p, args): context = item_context(xc, args) if context: qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=()) if qn == (): raise XPathContext.FunctionArgType(2, "xbrl:QName") dimConcept = xc.modelXbrl.qnameConcepts.get( qn) # check qname is explicit dimension if not dimConcept or not dimConcept.isExplicitDimension: raise XPathContext.XPathException( p, 'xfie:invalidExplicitDimensionQName', _('dimension does not specify an explicit dimension')) dimValue = context.dimValue(qn) if isinstance(dimValue, ModelObject.ModelDimensionValue) and dimValue.isExplicit: return dimValue.memberQname # known to be valid given instance is valid elif isinstance(dimValue, QName): #default, check if this is valid ''' removed 2011-03-01 FWG clarification that default always applies modelItem = xc.modelItem(args[0][0]) itemConcept = modelItem.concept from arelle.ValidateXbrlDimensions import checkPriItemDimValueValidity memConcept = xc.modelXbrl.qnameConcepts.get(dimValue) # remove check for pri item validity per FWG meeting notes 2011-01-13 if itemConcept: # and checkPriItemDimValueValidity(xc, itemConcept, dimConcept, memConcept): return dimValue ''' return dimValue return () # not an applicable primary item for default dimension raise XPathContext.FunctionArgType(1, "xbrl:item")
def xfxc_element(xc, p, contextItem, args): if not 2 <= len(args) <= 4: raise XPathContext.FunctionNumArgs() qn = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) attrArg = args[1] if isinstance(args[1], (list, tuple)) else (args[1], ) # attributes have to be pairs if attrArg: if len(attrArg) & 1 or any( not isinstance(attrArg[i], (QName, _STR_BASE)) for i in range(0, len(attrArg), 2)): raise XPathContext.FunctionArgType( 1, "((xs:qname|xs:string),xs:anyAtomicValue)", errCode="xfxce:AttributesNotNameValuePairs") else: attrParam = [ (attrArg[i], attrArg[i + 1] ) # need name-value pairs for XmlUtil function for i in range(0, len(attrArg), 2) ] else: attrParam = None value = atomicArg(xc, p, args, 2, "xs:anyAtomicType", emptyFallback='') if not value: # be sure '' is None so no text node is created value = None if len(args) < 4: childElements = None else: childElements = xc.flattenSequence(args[3]) # scratchpad instance document emulates fn:doc( ) to hold XML nodes scratchpadXmlDocUrl = "http://www.xbrl.org/2012/function/creation/xml_scratchpad.xml" if scratchpadXmlDocUrl in xc.modelXbrl.urlDocs: modelDocument = xc.modelXbrl.urlDocs[scratchpadXmlDocUrl] else: # create scratchpad xml document # this will get the fake instance document in the list of modelXbrl docs so that it is garbage collected from arelle import ModelDocument modelDocument = ModelDocument.create( xc.modelXbrl, ModelDocument.Type.UnknownXML, scratchpadXmlDocUrl, initialXml= "<xfc:dummy xmlns:xfc='http://www.xbrl.org/2012/function/creation'/>" ) newElement = XmlUtil.addChild(modelDocument.xmlRootElement, qn, attributes=attrParam, text=value) if childElements: for element in childElements: if isinstance(element, etree.ElementBase): newElement.append(element) # node myst be validated for use in instance creation (typed dimension references) XmlValidate.validate(xc.modelXbrl, newElement) return newElement
def concept(xc, p, args): qnConcept = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) srcConcept = xc.modelXbrl.qnameConcepts.get(qnConcept) if not (srcConcept and (srcConcept.isItem or srcConcept.isTuple)): raise XPathContext.XPathException( p, 'xfie:invalidConceptQName', _('Argument 1 {0} is not a concept in the DTS.').format(qnConcept)) return srcConcept
def relationship_element_attribute(xc, p, args, elementParent=False): if len(args) != 2: raise XPathContext.FunctionNumArgs() modelRel = anytypeArg(xc, args, 0, "arelle:ModelRelationship", None) if modelRel is None: raise XPathContext.FunctionArgType(1,"arelle:modelRelationship") qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if qnAttr is None: raise XPathContext.FunctionArgType(2,"xs:QName") element = modelRel.arcElement if elementParent: element = element.getparent() return element_attribute(element, qnAttr)
def filter_member_network_selection(xc, p, args): if len(args) != 5: raise XPathContext.FunctionNumArgs() qnDim = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) qnMem = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) linkroleURI = stringArg(xc, args, 2, "xs:string") arcroleURI = stringArg(xc, args, 3, "xs:string") axis = stringArg(xc, args, 4, "xs:string") if not axis in ('descendant-or-self', 'child-or-self', 'descendant', 'child'): return () dimConcept = xc.modelXbrl.qnameConcepts.get(qnDim) if not dimConcept or not dimConcept.isDimensionItem: raise XPathContext.XPathException( p, 'xfie:invalidDimensionQName', _('Argument 1 {0} is not a dimension concept QName.').format( qnDim)) memConcept = xc.modelXbrl.qnameConcepts.get(qnMem) if not memConcept or not memConcept.isDomainMember: # removed error 2011-03-10: raise XPathContext.XPathException(p, 'xfie:unrecognisedExplicitDimensionValueQName', _('Argument 1 {0} is not a member concept QName.').format(qnMem)) return () relationshipSet = xc.modelXbrl.relationshipSet(arcroleURI, linkroleURI) if relationshipSet: members = set() linkQnames = set() arcQnames = set() if axis.endswith("-or-self"): members.add(qnMem) fromRels = relationshipSet.fromModelObject(memConcept) if fromRels: filter_member_network_members(relationshipSet, fromRels, axis.startswith("descendant"), members, linkQnames, arcQnames) ''' removed 2011-03-10: if len(linkQnames) > 1 or len(arcQnames) > 1: raise XPathContext.XPathException(p, 'xfie:ambiguousFilterMemberNetwork', _('Network of linkrole {0} and arcrole {1} dimension {2} from {3} is ambiguous because of multiple link elements, {4}, or arc elements {5}').format( linkroleURI, arcroleURI, qnDim, qnMem, linkQnames, arcQnames)) ''' return members # no fromRels, must be a toRel or else the qname is not in the member network if relationshipSet.toModelObject(memConcept): return members # valid situation, the member exists as a leaf node # removed error 2011-03-10: raise XPathContext.XPathException(p, 'xfie:unrecognisedExplicitDimensionValueQName', _('Argument 1 {0} member is not in the network.').format(qnMem)) return ()
def conceptProperty(xc, p, args, property): if len(args) != 1: raise XPathContext.FunctionNumArgs() qn = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) if qn: modelConcept = xc.modelXbrl.qnameConcepts.get(qn) if modelConcept: if property == "numeric": return modelConcept.isNumeric if property == "non-numeric": return not modelConcept.isNumeric if property == "fraction": return modelConcept.isFraction return False
def conceptProperty(xc, p, args, property): if len(args) != 1: raise XPathContext.FunctionNumArgs() qn = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) if qn: modelConcept = xc.modelXbrl.qnameConcepts.get(qn) if modelConcept is not None: if property == "numeric": return modelConcept.isNumeric or modelConcept.isFraction if property == "non-numeric": return modelConcept.isItem and not (modelConcept.isNumeric or modelConcept.isFraction) if property == "fraction": return modelConcept.isFraction return False
def fact_dim_value(xc, p, args, dimType): context = item_context(xc, args) qnDim = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) dimConcept = xc.modelXbrl.qnameConcepts.get(qnDim) if dimConcept is None or not dimConcept.isDimensionItem: raise XPathContext.XPathException(p, 'xfie:invalid{0}DimensionQName'.format(dimType), _('Argument 1 {0} is not a dimension concept QName.').format(qnDim)) if context is not None: return context.dimValue(qnDim) raise XPathContext.FunctionArgType(1,"xbrl:item")
def fact_dim_value(xc, p, args, dimType): context = item_context(xc, args) qnDim = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) dimConcept = xc.modelXbrl.qnameConcepts.get(qnDim) if not dimConcept or not dimConcept.isDimensionItem: raise XPathContext.XPathException( p, 'xfie:invalid{0}DimensionQName'.format(dimType), _('Argument 1 {0} is not a dimension concept QName.').format( qnDim)) if context: return context.dimValue(qnDim) raise XPathContext.FunctionArgType(1, "xbrl:item")
def fact_typed_dimension_value(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() context = item_context(xc, args) if context is not None: qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=()) if qn == (): raise XPathContext.FunctionArgType(2,"xbrl:QName") modelConcept = xc.modelXbrl.qnameConcepts.get(qn) # check qname is explicit dimension if modelConcept is None or not modelConcept.isTypedDimension: raise XPathContext.XPathException(p, 'xfie:invalidTypedDimensionQName', _('dimension does not specify a typed dimension')) result = context.dimValue(qn) return result if result is not None else () raise XPathContext.FunctionArgType(1,"xbrl:item")
def concept_custom_attribute(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if not qnAttr: raise XPathContext.FunctionArgType(2,"xs:QName") element = concept(xc,p,args).element if qnAttr.namespaceURI: if not element.hasAttributeNS(qnAttr.namespaceURI, qnAttr.localName): return () return xc.atomize(p, element.getAttributeNodeNS(qnAttr.namespaceURI, qnAttr.localName)) else: if not element.hasAttribute(qnAttr.localName): return () return xc.atomize(p, element.getAttributeNode(qnAttr.localName))
def filter_member_network_selection(xc, p, args): if len(args) != 5: raise XPathContext.FunctionNumArgs() qnDim = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) qnMem = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) linkroleURI = stringArg(xc, args, 2, "xs:string") arcroleURI = stringArg(xc, args, 3, "xs:string") axis = stringArg(xc, args, 4, "xs:string") if not axis in ('descendant-or-self', 'child-or-self', 'descendant', 'child'): return () dimConcept = xc.modelXbrl.qnameConcepts.get(qnDim) if dimConcept is None or not dimConcept.isDimensionItem: raise XPathContext.XPathException(p, 'xfie:invalidDimensionQName', _('Argument 1 {0} is not a dimension concept QName.').format(qnDim)) memConcept = xc.modelXbrl.qnameConcepts.get(qnMem) if memConcept is None or not memConcept.isDomainMember: # removed error 2011-03-10: raise XPathContext.XPathException(p, 'xfie:unrecognisedExplicitDimensionValueQName', _('Argument 1 {0} is not a member concept QName.').format(qnMem)) return () relationshipSet = xc.modelXbrl.relationshipSet(arcroleURI, linkroleURI) if relationshipSet is not None: members = set() linkQnames = set() arcQnames = set() if axis.endswith("-or-self"): members.add(qnMem) fromRels = relationshipSet.fromModelObject(memConcept) if fromRels is not None: filter_member_network_members(relationshipSet, fromRels, axis.startswith("descendant"), members, linkQnames, arcQnames) ''' removed 2011-03-10: if len(linkQnames) > 1 or len(arcQnames) > 1: raise XPathContext.XPathException(p, 'xfie:ambiguousFilterMemberNetwork', _('Network of linkrole {0} and arcrole {1} dimension {2} from {3} is ambiguous because of multiple link elements, {4}, or arc elements {5}').format( linkroleURI, arcroleURI, qnDim, qnMem, linkQnames, arcQnames)) ''' return members # no fromRels, must be a toRel or else the qname is not in the member network if relationshipSet.toModelObject(memConcept): return members # valid situation, the member exists as a leaf node # removed error 2011-03-10: raise XPathContext.XPathException(p, 'xfie:unrecognisedExplicitDimensionValueQName', _('Argument 1 {0} member is not in the network.').format(qnMem)) return ()
def xfxc_element(xc, p, contextItem, args): if not 2 <= len(args) <= 4: raise XPathContext.FunctionNumArgs() qn = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) attrArg = args[1] if isinstance(args[1],(list,tuple)) else (args[1],) # attributes have to be pairs if attrArg: if len(attrArg) & 1 or any(not isinstance(attrArg[i], (QName, _STR_BASE)) for i in range(0, len(attrArg),2)): raise XPathContext.FunctionArgType(1,"((xs:qname|xs:string),xs:anyAtomicValue)", errCode="xfxce:AttributesNotNameValuePairs") else: attrParam = [(attrArg[i],attrArg[i+1]) # need name-value pairs for XmlUtil function for i in range(0, len(attrArg),2)] else: attrParam = None value = atomicArg(xc, p, args, 2, "xs:anyAtomicType", emptyFallback='') if not value: # be sure '' is None so no text node is created value = None if len(args) < 4: childElements = None else: childElements = xc.flattenSequence(args[3]) # scratchpad instance document emulates fn:doc( ) to hold XML nodes scratchpadXmlDocUrl = "http://www.xbrl.org/2012/function/creation/xml_scratchpad.xml" if scratchpadXmlDocUrl in xc.modelXbrl.urlDocs: modelDocument = xc.modelXbrl.urlDocs[scratchpadXmlDocUrl] else: # create scratchpad xml document # this will get the fake instance document in the list of modelXbrl docs so that it is garbage collected from arelle import ModelDocument modelDocument = ModelDocument.create(xc.modelXbrl, ModelDocument.Type.UnknownXML, scratchpadXmlDocUrl, initialXml="<xfc:dummy xmlns:xfc='http://www.xbrl.org/2012/function/creation'/>") newElement = XmlUtil.addChild(modelDocument.xmlRootElement, qn, attributes=attrParam, text=value) if childElements: for element in childElements: if isinstance(element, etree.ElementBase): newElement.append(element) # node myst be validated for use in instance creation (typed dimension references) XmlValidate.validate(xc.modelXbrl, newElement) return newElement
def fact_typed_dimension_value(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() context = item_context(xc, args) if context: qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=()) if qn == (): raise XPathContext.FunctionArgType(2, "xbrl:QName") modelConcept = xc.modelXbrl.qnameConcepts.get( qn) # check qname is explicit dimension if not modelConcept or not modelConcept.isTypedDimension: raise XPathContext.XPathException( p, 'xfie:invalidTypedDimensionQName', _('dimension does not specify a typed dimension')) result = context.dimValue(qn) return result.typedMember if result else () raise XPathContext.FunctionArgType(1, "xbrl:item")
def concept_custom_attribute(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if not qnAttr: raise XPathContext.FunctionArgType(2, "xs:QName") element = concept(xc, p, args).element if qnAttr.namespaceURI: if not element.hasAttributeNS(qnAttr.namespaceURI, qnAttr.localName): return () return xc.atomize( p, element.getAttributeNodeNS(qnAttr.namespaceURI, qnAttr.localName)) else: if not element.hasAttribute(qnAttr.localName): return () return xc.atomize(p, element.getAttributeNode(qnAttr.localName))
def element_attribute(xc, p, args, elementParent=False): if len(args) != 2: raise XPathContext.FunctionNumArgs() modelRel = anytypeArg(xc, args, 0, "arelle:ModelRelationship", None) if not modelRel: raise XPathContext.FunctionArgType(1,"arelle:modelRelationship") qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if not qnAttr: raise XPathContext.FunctionArgType(2,"xs:QName") element = modelRel.element if elementParent: element = element.parentNode if qnAttr.namespaceURI: if not element.hasAttributeNS(qnAttr.namespaceURI, qnAttr.localName): return () return xc.atomize(p, element.getAttributeNodeNS(qnAttr.namespaceURI, qnAttr.localName)) else: if not element.hasAttribute(qnAttr.localName): return () return xc.atomize(p, element.getAttributeNode(qnAttr.localName))
def concept_label(xc, p, args): if len(args) == 5: raise xfiFunctionNotAvailable() if len(args) != 4: raise XPathContext.FunctionNumArgs() qnSource = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) srcConcept = xc.modelXbrl.qnameConcepts.get(qnSource) if srcConcept is None: return "" linkroleURI = stringArg(xc, args, 1, "xs:string", emptyFallback='') if not linkroleURI: linkroleURI = XbrlConst.defaultLinkRole labelroleURI = stringArg(xc, args, 2, "xs:string", emptyFallback='') if not labelroleURI: labelroleURI = XbrlConst.standardLabel lang = stringArg(xc, args, 3, "xs:string", emptyFallback='') relationshipSet = xc.modelXbrl.relationshipSet(XbrlConst.conceptLabel,linkroleURI) if relationshipSet is not None: label = relationshipSet.label(srcConcept, labelroleURI, lang) if label is not None: return label return ""
def uncovered_aspect(xc, p, args): from arelle.ModelFormulaObject import aspectFromToken, Aspect from arelle.FormulaEvaluator import uncoveredAspectValue if len(args) not in (1, 2): raise XPathContext.FunctionNumArgs() aspect = aspectFromToken.get(stringArg(xc, args, 0, "xs:token").strip()) if aspect == Aspect.DIMENSIONS: qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) # check function use after checking argument types if xc.progHeader and xc.progHeader.element: if xc.progHeader.element.localName not in ("formula", "consistencyAssertion", "valueAssertion", "message"): raise XPathContext.XPathException( p, 'xffe:invalidFunctionUse', _('Function xff:uncovered-aspect cannot be used on an XPath expression associated with a {0}' ).format(xc.progHeader.element.localName)) if xc.variableSet and xc.variableSet.implicitFiltering == "false": raise XPathContext.XPathException( p, 'xffe:invalidFunctionUse', _('Function xff:uncovered-aspect cannot be used with implicitFiltering=false' )) if aspect == Aspect.DIMENSIONS: if qn: modelConcept = xc.modelXbrl.qnameConcepts.get(qn) if modelConcept and modelConcept.isDimensionItem: aspect = qn else: return () # not a dimension dimValue = uncoveredAspectValue(xc, aspect) if isinstance(dimValue, ModelObject.ModelDimensionValue): if dimValue.isExplicit: return dimValue.memberQname elif dimValue.isTyped: return dimValue.typedMember elif isinstance(dimValue, QName): # qname for explicit or node for typed return dimValue return () aspectValue = uncoveredAspectValue(xc, aspect) if aspectValue is None: return () return aspectValue
def concept_label(xc, p, args): if len(args) == 5: raise xfiFunctionNotAvailable() if len(args) != 4: raise XPathContext.FunctionNumArgs() qnSource = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) srcConcept = xc.modelXbrl.qnameConcepts.get(qnSource) if not srcConcept: return "" linkroleURI = stringArg(xc, args, 1, "xs:string", emptyFallback='') if not linkroleURI: linkroleURI = XbrlConst.defaultLinkRole labelroleURI = stringArg(xc, args, 2, "xs:string", emptyFallback='') if not labelroleURI: labelroleURI = XbrlConst.standardLabel lang = stringArg(xc, args, 3, "xs:string", emptyFallback='') relationshipSet = xc.modelXbrl.relationshipSet(XbrlConst.conceptLabel, linkroleURI) if relationshipSet: label = relationshipSet.label(srcConcept, labelroleURI, lang) if label is not None: return label return ""
def element_attribute(xc, p, args, elementParent=False): if len(args) != 2: raise XPathContext.FunctionNumArgs() modelRel = anytypeArg(xc, args, 0, "arelle:ModelRelationship", None) if not modelRel: raise XPathContext.FunctionArgType(1, "arelle:modelRelationship") qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if not qnAttr: raise XPathContext.FunctionArgType(2, "xs:QName") element = modelRel.element if elementParent: element = element.parentNode if qnAttr.namespaceURI: if not element.hasAttributeNS(qnAttr.namespaceURI, qnAttr.localName): return () return xc.atomize( p, element.getAttributeNodeNS(qnAttr.namespaceURI, qnAttr.localName)) else: if not element.hasAttribute(qnAttr.localName): return () return xc.atomize(p, element.getAttributeNode(qnAttr.localName))
def fact_dimension_s_equal2(xc, p, args): if len(args) != 3: raise XPathContext.FunctionNumArgs() context1 = item_context(xc, args, i=0) context2 = item_context(xc, args, i=1) if context1 is not None: if context2 is not None: qn = qnameArg(xc, p, args, 2, 'QName', emptyFallback=()) if qn == (): raise XPathContext.FunctionArgType(3,"xbrl:QName") modelConcept = xc.modelXbrl.qnameConcepts.get(qn) # check qname is explicit dimension if modelConcept is None or not modelConcept.isDimensionItem: # raise XPathContext.XPathException(p, 'xfie:invalidTypedDimensionQName', _('dimension does not specify a typed dimension')) return False dimValue1 = context1.dimValue(qn) dimValue2 = context2.dimValue(qn) if dimValue1 is not None and isinstance(dimValue1,ModelDimensionValue): return dimValue1.isEqualTo(dimValue2, equalMode=XbrlUtil.S_EQUAL2) elif dimValue2 is not None and isinstance(dimValue2,ModelDimensionValue): return dimValue2.isEqualTo(dimValue1, equalMode=XbrlUtil.S_EQUAL2) return dimValue1 == dimValue2 raise XPathContext.FunctionArgType(2,"xbrl:item") raise XPathContext.FunctionArgType(1,"xbrl:item")
def fact_explicit_dimension_value_value(xc, p, args): context = item_context(xc, args) if context is not None: qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=()) if qn == (): raise XPathContext.FunctionArgType(2,"xbrl:QName") dimConcept = xc.modelXbrl.qnameConcepts.get(qn) # check qname is explicit dimension if dimConcept is None or not dimConcept.isExplicitDimension: raise XPathContext.XPathException(p, 'xfie:invalidExplicitDimensionQName', _('dimension does not specify an explicit dimension')) dimValue = context.dimValue(qn) if isinstance(dimValue, ModelDimensionValue) and dimValue.isExplicit: return dimValue.memberQname # known to be valid given instance is valid elif isinstance(dimValue, QName): #default, check if this is valid ''' removed 2011-03-01 FWG clarification that default always applies modelItem = xc.modelItem(args[0][0]) itemConcept = modelItem.concept from arelle.ValidateXbrlDimensions import checkPriItemDimValueValidity memConcept = xc.modelXbrl.qnameConcepts.get(dimValue) # remove check for pri item validity per FWG meeting notes 2011-01-13 if itemConcept: # and checkPriItemDimValueValidity(xc, itemConcept, dimConcept, memConcept): return dimValue ''' return dimValue return () # not an applicable primary item for default dimension raise XPathContext.FunctionArgType(1,"xbrl:item")
def fact_dimension_s_equal2(xc, p, args): if len(args) != 3: raise XPathContext.FunctionNumArgs() context1 = item_context(xc, args, i=0) context2 = item_context(xc, args, i=1) if context1: if context2: qn = qnameArg(xc, p, args, 2, 'QName', emptyFallback=()) if qn == (): raise XPathContext.FunctionArgType(3, "xbrl:QName") modelConcept = xc.modelXbrl.qnameConcepts.get( qn) # check qname is explicit dimension if not modelConcept or not modelConcept.isTypedDimension: # raise XPathContext.XPathException(p, 'xfie:invalidTypedDimensionQName', _('dimension does not specify a typed dimension')) return False dimValue1 = context1.dimValue(qn) dimValue2 = context1.dimValue(qn) if dimValue1 and isinstance(dimValue1, ModelObject.ModelDimensionValue): return dimValue1.isEqualTo(dimValue2) elif dimValue2 and isinstance(dimValue2, ModelObject.ModelDimensionValue): return dimValue2.isEqualTo(dimValue1) return dimValue1 == dimValue2 raise XPathContext.FunctionArgType(2, "xbrl:item") raise XPathContext.FunctionArgType(1, "xbrl:item")
def concept_relationships(xc, p, args): lenArgs = len(args) if lenArgs < 4 or lenArgs > 8: raise XPathContext.FunctionNumArgs() qnSource = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) linkroleURI = stringArg(xc, args, 1, "xs:string") if not linkroleURI: linkroleURI = XbrlConst.defaultLinkRole arcroleURI = stringArg(xc, args, 2, "xs:string") axis = stringArg(xc, args, 3, "xs:string") if not axis in ('descendant', 'child', 'ancestor', 'parent', 'sibling', 'sibling-or-self'): return () if qnSource != XbrlConst.qnXfiRoot: srcConcept = xc.modelXbrl.qnameConcepts.get(qnSource) if srcConcept is None: return () if lenArgs > 4: generations = numericArg(xc, p, args, 4, "xs:integer", convertFallback=0) elif axis in ('child', 'parent', 'sibling', 'sibling-or-self'): generations = 1 else: generations = 0 if axis in ('child','parent','sibling', 'sibling-or-self'): generations = 1 if axis == 'child': axis = 'descendant' elif axis == 'parent': axis = 'ancestor' if lenArgs > 5: qnLink = qnameArg(xc, p, args, 5, 'QName', emptyFallback=None) else: qnLink = None if lenArgs > 5: qnArc = qnameArg(xc, p, args, 6, 'QName', emptyFallback=None) else: qnArc = None removeSelf = axis == 'sibling' relationshipSet = xc.modelXbrl.relationshipSet(arcroleURI, linkroleURI, qnLink, qnArc) if relationshipSet: result = [] visited = {qnSource} if qnSource == XbrlConst.qnXfiRoot: if axis in ('sibling', 'sibling-or-self', 'ancestor'): return [] roots = relationshipSet.rootConcepts visited = {c.qname for c in roots} rels = [rel for c in roots for rel in relationshipSet.fromModelObject(c)] if generations == 1: return rels if generations > 1: generations -= 1 elif axis == 'descendant': rels = relationshipSet.fromModelObject(srcConcept) elif axis == 'ancestor': # includes first pass on parents of object to get sibling rels = relationshipSet.toModelObject(srcConcept) elif axis in ('sibling', 'sibling-or-self'): rels = relationshipSet.toModelObject(srcConcept) if rels: rels = relationshipSet.fromModelObject(rels[0].fromModelObject) axis = 'descendant' else: # must be a root, never has any siblings return [] if rels: concept_relationships_step(xc, relationshipSet, rels, axis, generations, result, visited) if removeSelf: for i, rel in enumerate(result): if rel.toModelObject == srcConcept: result.pop(i) break return result return ()
def concept_data_type_derived_from(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() qnType = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if not qnType: raise XPathContext.FunctionArgType(2, "xs:QName") return concept(xc, p, args).instanceOfType(qnType)
def fact_has_explicit_dimension_value(xc, p, args): if len(args) != 3: raise XPathContext.FunctionNumArgs() return qnameArg(xc, p, args, 2, 'QName', emptyFallback=()) == fact_explicit_dimension_value_value(xc, p, args)
def concept_data_type_derived_from(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() qnType = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if qnType is None: raise XPathContext.FunctionArgType(2,"xs:QName") return concept(xc,p,args).instanceOfType(qnType)
def concept_custom_attribute(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None) if qnAttr is None: raise XPathContext.FunctionArgType(2,"xs:QName") element = concept(xc,p,args) return element_attribute(element, qnAttr)
def concept(xc, p, args): qnConcept = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) srcConcept = xc.modelXbrl.qnameConcepts.get(qnConcept) if srcConcept is None or not (srcConcept.isItem or srcConcept.isTuple): raise XPathContext.XPathException(p, 'xfie:invalidConceptQName', _('Argument 1 {0} is not a concept in the DTS.').format(qnConcept)) return srcConcept
def concept_relationships(xc, p, args): lenArgs = len(args) if lenArgs < 4 or lenArgs > 8: raise XPathContext.FunctionNumArgs() qnSource = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None) linkroleURI = stringArg(xc, args, 1, "xs:string") if not linkroleURI: linkroleURI = XbrlConst.defaultLinkRole arcroleURI = stringArg(xc, args, 2, "xs:string") axis = stringArg(xc, args, 3, "xs:string") if not axis in ('descendant', 'child', 'ancestor', 'parent', 'sibling', 'sibling-or-self'): return () if qnSource != XbrlConst.qnXfiRoot: srcConcept = xc.modelXbrl.qnameConcepts.get(qnSource) if not srcConcept: return () if lenArgs > 4: generations = numericArg(xc, p, args, 4, "xs:integer", convertFallback=0) elif axis in ('child', 'parent', 'sibling', 'sibling-or-self'): generations = 1 else: generations = 0 if axis in ('child', 'parent', 'sibling', 'sibling-or-self'): generations = 1 if axis == 'child': axis = 'descendant' elif axis == 'parent': axis = 'ancestor' if lenArgs > 5: qnLink = qnameArg(xc, p, args, 5, 'QName', emptyFallback=None) else: qnLink = None if lenArgs > 5: qnArc = qnameArg(xc, p, args, 6, 'QName', emptyFallback=None) else: qnArc = None removeSelf = axis == 'sibling' relationshipSet = xc.modelXbrl.relationshipSet(arcroleURI, linkroleURI, qnLink, qnArc) if relationshipSet: result = [] visited = {qnSource} if qnSource == XbrlConst.qnXfiRoot: if axis in ('sibling', 'sibling-or-self', 'ancestor'): return [] roots = relationshipSet.rootConcepts visited = {c.qname for c in roots} rels = [ rel for c in roots for rel in relationshipSet.fromModelObject(c) ] if generations == 1: return rels if generations > 1: generations -= 1 elif axis == 'descendant': rels = relationshipSet.fromModelObject(srcConcept) elif axis == 'ancestor': # includes first pass on parents of object to get sibling rels = relationshipSet.toModelObject(srcConcept) elif axis in ('sibling', 'sibling-or-self'): rels = relationshipSet.toModelObject(srcConcept) if rels: rels = relationshipSet.fromModelObject(rels[0].fromModelObject) axis = 'descendant' else: # must be a root, never has any siblings return [] if rels: concept_relationships_step(xc, relationshipSet, rels, axis, generations, result, visited) if removeSelf: for i, rel in enumerate(result): if rel.toModelObject == srcConcept: result.pop(i) break return result return ()
def error(xc, p, contextItem, args): if len(args) > 2: raise XPathContext.FunctionNumArgs() qn = qnameArg(xc, p, args, 0, 'QName?', emptyFallback=None) msg = stringArg(xc, args, 1, "xs:string", emptyFallback='') raise XPathContext.XPathException(p, (qn or "err:FOER0000"), msg)
def fact_has_explicit_dimension_value(xc, p, args): if len(args) != 3: raise XPathContext.FunctionNumArgs() return qnameArg(xc, p, args, 2, 'QName', emptyFallback=()) == fact_explicit_dimension_value_value( xc, p, args)