def doc(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() uri = stringArg(xc, args, 0, "xs:string", emptyFallback=None) if uri is None: return () if xc.progHeader is None or xc.progHeader.element is None: raise XPathContext.XPathException( p, 'err:FODC0005', _('Function xf:doc no formula resource element for {0}').format( uri)) if not UrlUtil.isValid(uri): raise XPathContext.XPathException( p, 'err:FODC0005', _('Function xf:doc $uri is not valid {0}').format(uri)) normalizedUri = xc.modelXbrl.modelManager.cntlr.webCache.normalizeUrl( uri, xc.progHeader.element.modelDocument.baseForElement( xc.progHeader.element)) if normalizedUri in xc.modelXbrl.urlDocs: return xc.modelXbrl.urlDocs[normalizedUri].xmlDocument modelDocument = ModelDocument.load(xc.modelXbrl, normalizedUri) if modelDocument is None: raise XPathContext.XPathException( p, 'err:FODC0005', _('Function xf:doc $uri not successfully loaded {0}').format(uri)) # assure that document is validated XmlValidate.validate(xc.modelXbrl, modelDocument.xmlRootElement) return modelDocument.xmlDocument
def replace(xc, p, contextItem, args): if not 3 <= len(args) <= 4: raise XPathContext.FunctionNumArgs() input = stringArg(xc, args, 0, "xs:string?", emptyFallback=()) pattern = stringArg(xc, args, 1, "xs:string", emptyFallback=()) fnReplacement = stringArg(xc, args, 2, "xs:string", emptyFallback=()) if re.findall(r"(^|[^\\])[$]|[$][^0-9]", fnReplacement): raise XPathContext.XPathException(p, 'err:FORX0004', _('fn:replace pattern \'$\' error in: {0}').format(fnReplacement)) reReplacement = re.sub(r"[\\][$]", "$", re.sub(r"(^|[^\\])[$]([1-9])", r"\\\2", fnReplacement)) try: return re.sub(pattern,reReplacement,input,flags=regexFlags(xc, p, args, 3)) except sre_constants.error as err: raise XPathContext.XPathException(p, 'err:FORX0002', _('fn:replace regular expression pattern error: {0}').format(err))
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 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 format_number(xc, p, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() value = numericArg(xc, p, args, 0, missingArgFallback='NaN', emptyFallback='NaN') picture = stringArg(xc, args, 1, "xs:string", missingArgFallback='', emptyFallback='') try: return format_picture(xc.modelXbrl.locale, value, picture) except ValueError as err: raise XPathContext.XPathException(p, 'err:FODF1310', str(err) )
def period_datetime(p, args, periodElement, addOneDay): if len(args) != 1: raise XPathContext.FunctionNumArgs() if len(args[0]) != 1: raise XPathContext.FunctionArgType(1, "xbrl:period") period = args[0][0] if (isinstance(period, xml.dom.Node) and period.nodeType == 1 and period.localName == "period" and period.namespaceURI == XbrlConst.xbrli): child = XmlUtil.child(period, XbrlConst.xbrli, periodElement) if child: return dateTime(child, addOneDay=addOneDay, type=DATETIME) elif periodElement == "instant": raise XPathContext.XPathException(p, 'xfie:PeriodIsNotInstant', _('Period is not instant')) else: raise XPathContext.XPathException(p, 'xfie:PeriodIsForever', _('Period is forever')) raise XPathContext.FunctionArgType(1, "xbrl:period")
def matches(xc, p, contextItem, args): if not 2 <= len(args) <= 3: raise XPathContext.FunctionNumArgs() input = stringArg(xc, args, 0, "xs:string?", emptyFallback=()) pattern = stringArg(xc, args, 1, "xs:string", emptyFallback=()) try: return bool(re.search(pattern,input,flags=regexFlags(xc, p, args, 2))) except sre_constants.error as err: raise XPathContext.XPathException(p, 'err:FORX0002', _('fn:matches regular expression pattern error: {0}').format(err))
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 regexFlags(xc, p, args, n): f = 0 flagsArg = stringArg(xc, args, n, "xs:string", missingArgFallback="", emptyFallback="") for c in flagsArg: if c == 's': f |= re.S elif c == 'm': f |= re.M elif c == 'i': f |= re.I elif c == 'x': f |= re.X else: raise XPathContext.XPathException(p, 'err:FORX0001', _('Regular expression interpretation flag unrecognized: {0}').format(flagsArg)) return f
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 call(xc, p, localname, args): source = atomicArg(xc, p, args, 0, "value?", missingArgFallback=() ) if source == (): return source try: if localname not in xsFunctions: raise xsFunctionNotAvailable return xsFunctions[localname](xc, p, source) except (FORG0001, ValueError, TypeError): raise XPathContext.XPathException(p, 'err:FORG0001', _('invalid cast from {0} to xs:{1}').format( type(source).__name__, localname)) except xsFunctionNotAvailable: raise XPathContext.FunctionNotAvailable("xs:{0}".format(localname))
def infer_precision_decimals(xc, p, args, attrName): if len(args) != 1: raise XPathContext.FunctionNumArgs() if len(args[0]) != 1: raise XPathContext.FunctionArgType(1, "xbrl:item") modelItem = xc.modelItem(args[0][0]) if modelItem: modelConcept = modelItem.concept if modelConcept.isNumeric: if modelConcept.isFraction: return 'INF' from arelle.ValidateXbrlCalcs import (inferredDecimals, inferredPrecision) p = inferredPrecision( modelItem) if attrName == "precision" else inferredDecimals( modelItem) if isinf(p): return 'INF' if isnan(p): raise XPathContext.XPathException( p, 'xfie:ItemIsNotNumeric', _('Argument 1 {0} is not inferrable.').format(attrName)) return p raise XPathContext.XPathException( p, 'xfie:ItemIsNotNumeric', _('Argument 1 is not reported with {0}.').format(attrName))
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 boolean(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() inputSequence = args[0] if inputSequence is None or len(inputSequence) == 0: return False item = inputSequence[0] if isinstance(item, (ModelObject, ModelAttribute, etree._ElementTree)): return True if len(inputSequence) == 1: if isinstance(item, bool): return item if isinstance(item, _STR_BASE): return len(item) > 0 if isinstance(item, _NUM_TYPES): return not math.isnan(item) and item != 0 raise XPathContext.XPathException(p, 'err:FORG0006', _('Effective boolean value indeterminate'))
def boolean(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() inputSequence = args[0] if inputSequence is None or len(inputSequence) == 0: return False item = inputSequence[0] if isinstance(item, ModelObject.ModelObject) or isinstance( item, xml.dom.Node): return True if len(inputSequence) == 1: if isinstance(item, bool): return item if isinstance(item, str): return len(item) > 0 if isinstance(item, int) or isinstance(item, float): return not math.isnan(item) and item != 0 raise XPathContext.XPathException( p, 'err:FORG0006', _('Effective boolean value indeterminate'))
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 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)