def substring(xc, p, contextItem, args): l = len(args) if l < 2 or l > 3: raise XPathContext.FunctionNumArgs() string = stringArg(xc, args, 0, "xs:string?") start = _INT(round( numericArg(xc, p, args, 1) )) - 1 if l == 3: length = _INT(round( numericArg(xc, p, args, 2) )) if start < 0: length += start if length < 0: length = 0 start = 0 return string[start:start + length] if start < 0: start = 0 return string[start:]
def subsequence(xc, p, contextItem, args): if len(args) not in (2,3): raise XPathContext.FunctionNumArgs() l = len(args) if l < 2 or l > 3: raise XPathContext.FunctionNumArgs() sequence = args[0] start = _INT(round( numericArg(xc, p, args, 1) )) - 1 if l == 3: length = _INT(round( numericArg(xc, p, args, 2) )) if start < 0: length += start if length < 0: length = 0 start = 0 return sequence[start:start + length] if start < 0: start = 0 return sequence[start:]
def number(xc, p, contextItem, args): return numericArg(xc, p, args, missingArgFallback=contextItem, emptyFallback=nan, convertFallback=nan)
def fn_round(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args) if math.isinf(x) or math.isnan(x): return x return _INT( x + (DECIMAL_5 if isinstance(x, Decimal) else .5)) # round towards +inf
def xfm_tan(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args, 0, emptyFallback=()) if x != (): if math.isinf(x): return NaN return math.tan(x) return ()
def xfm_sin(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args, 0, emptyFallback=()) if x != (): if math.isinf(x): return NaN return math.sin(x) return ()
def fn_abs(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args) if math.isinf(x): x = float('inf') elif not math.isnan(x): x = abs(x) return x
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 xfm_atan(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args, 0, emptyFallback=()) if x != (): try: return math.atan(x) except ValueError: return NaN return ()
def fn_round_half_to_even(xc, p, contextItem, args): if len(args) > 2 or len(args) == 0: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args) if len(args) == 2: precision = args[1] if len(precision) != 1 or not isinstance(precision[0],_INT_TYPES): raise XPathContext.FunctionArgType(2,"integer") precision = precision[0] return round(x, precision) return round(x)
def number(xc, p, contextItem, args): # TBD: add argument of type of number to convert to (fallback is float) n = numericArg(xc, p, args, missingArgFallback=contextItem, emptyFallback=NaN, convertFallback=NaN) return float(n)
def xfm_sqrt(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args, 0, emptyFallback=()) if x != (): if x == MINUSINF: return NaN elif x < 0: return INF return math.sqrt(x) return ()
def insert_before(xc, p, contextItem, args): if len(args) != 3: raise XPathContext.FunctionNumArgs() sequence = args[0] if isinstance(sequence, tuple): sequence = list(sequence) elif not isinstance(sequence, list): sequence = [sequence] index = numericArg(xc, p, args, 1, "xs:integer", convertFallback=0) - 1 insertion = args[2] if isinstance(insertion, tuple): insertion = list(insertion) elif not isinstance(insertion, list): insertion = [insertion] return sequence[:index] + insertion + sequence[index:]
def xfm_pow(xc, p, contextItem, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args, 0, emptyFallback=()) if x != (): y = numericArg(xc, p, args, 1) if x == 0: if math.copysign(1, x) < 0: # e.g., value is -0.0 if y < 0: return MINUSINF elif y == 0: return 0.0 else: return -0.0 else: # value is +0.0 if y < 0: return INF else: return 0.0 try: return math.pow(x, y) except ValueError: return NaN # pow(-2.5e0, 2.00000001e0) returns xs:double('NaN'). return ()
def xfm_exp10(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args, 0, emptyFallback=()) if x != (): return math.pow(10.0, x) return ()
def remove(xc, p, contextItem, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() sequence = args[0] index = numericArg(xc, p, args, 1, "xs:integer", convertFallback=0) - 1 return sequence[:index] + sequence[index+1:]
def fn_round(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args) if math.isinf(x) or math.isnan(x): return x return _INT(x + .5) # round towards +inf
def xfm_atan2(xc, p, contextItem, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() y = numericArg(xc, p, args, 0) x = numericArg(xc, p, args, 1) return math.atan2(y, x)
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 fn_round(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() x = numericArg(xc, p, args) if math.isinf(x) or math.isnan(x): return x return _INT(x + (DECIMAL_5 if isinstance(x,Decimal) else .5)) # round towards +inf
def fn_ceiling(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() math.ceil(numericArg(xc, p, args))
def fn_floor(xc, p, contextItem, args): if len(args) != 1: raise XPathContext.FunctionNumArgs() math.floor(numericArg(xc, p, args))
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 number(xc, p, contextItem, args): return numericArg(xc, p, args, missingArgFallback=contextItem, emptyFallback=NaN, convertFallback=NaN)