def __init__(self, parentOrdinateContext, axisObject, zInheritance=None, contextItemFact=None): self.parentOrdinateContext = parentOrdinateContext self._axisObject = axisObject self._rendrCntx = getattr(axisObject.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases self.variables = {} self.aspects = {} self.subOrdinateContexts = [] self.choiceOrdinateContexts = [] self.zInheritance = zInheritance if contextItemFact is not None: self.contextItemBinding = VariableBinding(self._rendrCntx, boundFact=contextItemFact) else: self.contextItemBinding = None
def __init__(self, parentStructuralNode, definitionNode, zInheritance=None, contextItemFact=None): self.parentStructuralNode = parentStructuralNode self._definitionNode = definitionNode self._rendrCntx = getattr(definitionNode.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases self.variables = {} self.aspects = {} self.childStructuralNodes = [] self.rollUpStructuralNode = None self.choiceStructuralNodes = [] self.zInheritance = zInheritance if contextItemFact is not None: self.contextItemBinding = VariableBinding(self._rendrCntx, boundFact=contextItemFact) else: self.contextItemBinding = None self.subtreeRollUp = ROLLUP_NOT_ANALYZED self.depth = parentStructuralNode.depth + 1 if parentStructuralNode else 0
class StructuralNode: def __init__(self, parentStructuralNode, definitionNode, zInheritance=None, contextItemFact=None): self.parentStructuralNode = parentStructuralNode self._definitionNode = definitionNode self._rendrCntx = getattr(definitionNode.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases self.variables = {} self.aspects = {} self.childStructuralNodes = [] self.rollUpStructuralNode = None self.choiceStructuralNodes = [] self.zInheritance = zInheritance if contextItemFact is not None: self.contextItemBinding = VariableBinding(self._rendrCntx, boundFact=contextItemFact) else: self.contextItemBinding = None self.subtreeRollUp = ROLLUP_NOT_ANALYZED self.depth = parentStructuralNode.depth + 1 if parentStructuralNode else 0 @property def modelXbrl(self): return self._definitionNode.modelXbrl @property def isAbstract(self): if self.subtreeRollUp: return self.subtreeRollUp == CHILDREN_BUT_NO_ROLLUP try: try: return self.abstract # ordinate may have an abstract attribute except AttributeError: # if none use axis object return self.definitionNode.isAbstract except AttributeError: # axis may never be abstract return False @property def isRollUp(self): return self.definitionNode.isRollUp @property def cardinalityAndDepth(self): return self.definitionNode.cardinalityAndDepth(self) @property def definitionNode(self): if self.choiceStructuralNodes: return self.choiceStructuralNodes[getattr(self,"choiceNodeIndex",0)]._definitionNode return self._definitionNode def aspectsCovered(self): return _DICT_SET(self.aspects.keys()) | self.definitionNode.aspectsCovered() def hasAspect(self, aspect, inherit=True): return (aspect in self.aspects or self.definitionNode.hasAspect(self, aspect) or (inherit and self.parentStructuralNode is not None and self.parentStructuralNode.hasAspect(aspect, inherit))) def aspectValue(self, aspect, inherit=True, dims=None): xc = self._rendrCntx if self.choiceStructuralNodes: # use aspects from choice structural node aspects = self.choiceStructuralNodes[self.choiceNodeIndex].aspects else: aspects = self.aspects if aspect == Aspect.DIMENSIONS: if dims is None: dims = set() if inherit and self.parentStructuralNode is not None: dims |= self.parentStructuralNode.aspectValue(aspect, dims=dims) if aspect in aspects: dims |= aspects[aspect] elif self.definitionNode.hasAspect(self, aspect): dims |= set(self.definitionNode.aspectValue(xc, aspect) or {}) if self.definitionNode.hasAspect(self, Aspect.OMIT_DIMENSIONS): dims -= set(self.definitionNode.aspectValue(xc, Aspect.OMIT_DIMENSIONS)) return dims if aspect in aspects: return aspects[aspect] elif self.definitionNode.hasAspect(self, aspect): if isinstance(self._definitionNode, ModelSelectionDefinitionNode): # result is in the indicated variable of ordCntx return self.variables.get(self._definitionNode.variableQname) elif isinstance(self._definitionNode, ModelFilterDefinitionNode): if self.contextItemBinding: return self.contextItemBinding.aspectValue(aspect) elif isinstance(self._definitionNode, ModelTupleDefinitionNode): if aspect == Aspect.LOCATION and self.contextItemBinding: return self.contextItemBinding.yieldedFact # non-location tuple aspects don't leak into cell bindings else: return self.definitionNode.aspectValue(xc, aspect) elif inherit and self.parentStructuralNode is not None: return self.parentStructuralNode.aspectValue(aspect) return None ''' @property def primaryItemQname(self): # for compatibility with viewRelationsihps if Aspect.CONCEPT in self.aspects: return self.aspects[Aspect.CONCEPT] return self.definitionNode.primaryItemQname @property def explicitDims(self): return self.definitionNode.explicitDims ''' def objectId(self, refId=""): return self._definitionNode.objectId(refId) def header(self, role=None, lang=None, evaluate=True, returnGenLabel=True, returnMsgFormatString=False): # if ord is a nested selectionAxis selection, use selection-message or text contents instead of axis headers isZSelection = isinstance(self._definitionNode, ModelSelectionDefinitionNode) and hasattr(self, "zSelection") if role is None: # check for message before checking for genLabel msgsRelationshipSet = self._definitionNode.modelXbrl.relationshipSet( (XbrlConst.tableDefinitionNodeSelectionMessage, XbrlConst.tableAxisSelectionMessage2011) if isZSelection else (XbrlConst.tableDefinitionNodeMessage, XbrlConst.tableAxisMessage2011)) if msgsRelationshipSet: msg = msgsRelationshipSet.label(self._definitionNode, XbrlConst.standardMessage, lang, returnText=False) if msg is not None: if evaluate: if returnMsgFormatString: return msg.formatString # not possible to evaluate (during resolution) else: return self.evaluate(msg, msg.evaluate) else: return XmlUtil.text(msg) if isZSelection: # no message, return text of selection return self.variables.get(self._definitionNode.variableQname, "selection") if returnGenLabel: label = self._definitionNode.genLabel(role=role, lang=lang) if label: return label # if there's a child roll up, check for it if self.rollUpStructuralNode is not None: # check the rolling-up child too return self.rollUpStructuralNode.header(role, lang, evaluate, returnGenLabel, returnMsgFormatString) # if aspect is a concept of dimension, return its standard label concept = None for aspect in self.aspectsCovered(): if isinstance(aspect, QName) or aspect == Aspect.CONCEPT: # dimension or concept aspectValue = self.aspectValue(aspect) if isinstance(aspectValue, QName): concept = self.modelXbrl.qnameConcepts[aspectValue] break elif isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: concept = aspectValue.member elif aspectValue.isTyped: return XmlUtil.innerTextList(aspectValue.typedMember) if concept is not None: label = concept.label(lang=lang) if label: return label # if there is a role, check if it's available on a parent node if role and self.parentStructuralNode is not None: return self.parentStructuralNode.header(role, lang, evaluate, returnGenLabel, returnMsgFormatString) return None def evaluate(self, evalObject, evalMethod, otherOrdinate=None, evalArgs=()): xc = self._rendrCntx if self.contextItemBinding and not isinstance(xc.contextItem, ModelFact): previousContextItem = xc.contextItem # xbrli.xbrl xc.contextItem = self.contextItemBinding.yieldedFact else: previousContextItem = None if self.choiceStructuralNodes and hasattr(self,"choiceNodeIndex"): variables = self.choiceStructuralNodes[self.choiceNodeIndex].variables else: variables = self.variables removeVarQnames = [] for qn, value in variables.items(): if qn not in xc.inScopeVars: removeVarQnames.append(qn) xc.inScopeVars[qn] = value if self.parentStructuralNode is not None: result = self.parentStructuralNode.evaluate(evalObject, evalMethod, otherOrdinate, evalArgs) elif otherOrdinate is not None: # recurse to other ordinate (which will recurse to z axis) result = otherOrdinate.evaluate(evalObject, evalMethod, None, evalArgs) elif self.zInheritance is not None: result = self.zInheritance.evaluate(evalObject, evalMethod, None, evalArgs) else: try: result = evalMethod(xc, *evalArgs) except XPathContext.XPathException as err: xc.modelXbrl.error(err.code, _("%(element)s set %(xlinkLabel)s \nException: %(error)s"), modelObject=evalObject, element=evalObject.localName, xlinkLabel=evalObject.xlinkLabel, error=err.message) result = '' for qn in removeVarQnames: xc.inScopeVars.pop(qn) if previousContextItem is not None: xc.contextItem = previousContextItem # xbrli.xbrl return result def hasValueExpression(self, otherOrdinate=None): return (self.definitionNode.hasValueExpression or (otherOrdinate is not None and otherOrdinate.definitionNode.hasValueExpression)) def evalValueExpression(self, fact, otherOrdinate=None): for ordinate in (self, otherOrdinate): if ordinate is not None and ordinate.definitionNode.hasValueExpression: return self.evaluate(self.definitionNode, ordinate.definitionNode.evalValueExpression, otherOrdinate=otherOrdinate, evalArgs=(fact,)) return None def __repr__(self): return ("structuralNode[{0}]{1})".format(self.objectId(),self.definitionNode))
class OrdinateContext: def __init__(self, parentOrdinateContext, axisObject, zInheritance=None, contextItemFact=None): self.parentOrdinateContext = parentOrdinateContext self._axisObject = axisObject self._rendrCntx = getattr(axisObject.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases self.variables = {} self.aspects = {} self.subOrdinateContexts = [] self.choiceOrdinateContexts = [] self.zInheritance = zInheritance if contextItemFact is not None: self.contextItemBinding = VariableBinding(self._rendrCntx, boundFact=contextItemFact) else: self.contextItemBinding = None @property def isAbstract(self): try: try: return self.abstract # ordinate may have an abstract attribute except AttributeError: # if none use axis object return self.axisObject.abstract == "true" except AttributeError: # axis may never be abstract return False @property def cardinalityAndDepth(self): return self.axisObject.cardinalityAndDepth(self) @property def axisObject(self): if self.choiceOrdinateContexts: return self.choiceOrdinateContexts[getattr(self,"choiceOrdinateIndex",0)]._axisObject return self._axisObject def aspectsCovered(self): return _DICT_SET(self.aspects.keys()) | self.axisObject.aspectsCovered() def hasAspect(self, aspect, inherit=True): return (aspect in self.aspects or self.axisObject.hasAspect(aspect) or (inherit and self.parentOrdinateContext is not None and self.parentOrdinateContext.hasAspect(aspect))) def aspectValue(self, aspect, inherit=True, dims=None): if aspect == Aspect.DIMENSIONS: if dims is None: dims = set() if inherit and self.parentOrdinateContext is not None: dims |= self.parentOrdinateContext.aspectValue(aspect, dims=dims) if aspect in self.aspects: dims |= self.aspects[aspect] elif self.axisObject.hasAspect(aspect): dims |= set(self.axisObject.aspectValue(self._rendrCntx, aspect) or {}) if self.axisObject.hasAspect(Aspect.OMIT_DIMENSIONS): dims -= set(self.axisObject.aspectValue(self._rendrCntx, Aspect.OMIT_DIMENSIONS)) return dims if aspect in self.aspects: return self.aspects[aspect] elif self.axisObject.hasAspect(aspect): if isinstance(self._axisObject, ModelSelectionAxis): # result is in the indicated variable of ordCntx return self.variables.get(self._axisObject.variableQname) elif isinstance(self._axisObject, ModelFilterAxis): if self.contextItemBinding: return self.contextItemBinding.aspectValue(aspect) elif isinstance(self._axisObject, ModelTupleAxis): if aspect == Aspect.LOCATION and self.contextItemBinding: return self.contextItemBinding.yieldedFact # non-location tuple aspects don't leak into cell bindings else: return self.axisObject.aspectValue(self._rendrCntx, aspect) elif inherit and self.parentOrdinateContext is not None: return self.parentOrdinateContext.aspectValue(aspect) return None ''' @property def primaryItemQname(self): # for compatibility with viewRelationsihps if Aspect.CONCEPT in self.aspects: return self.aspects[Aspect.CONCEPT] return self.axisObject.primaryItemQname @property def explicitDims(self): return self.axisObject.explicitDims ''' def objectId(self, refId=""): return self._axisObject.objectId(refId) def header(self, role=None, lang=None, evaluate=True, returnGenLabel=True): # if ord is a nested selectionAxis selection, use selection-message or text contents instead of axis headers isZSelection = isinstance(self._axisObject, ModelSelectionAxis) and hasattr(self, "zSelection") if role is None: # check for message before checking for genLabel msgsRelationshipSet = self._axisObject.modelXbrl.relationshipSet( XbrlConst.tableAxisSelectionMessage if isZSelection else XbrlConst.tableAxisMessage) if msgsRelationshipSet: msg = msgsRelationshipSet.label(self._axisObject, XbrlConst.standardMessage, lang, returnText=False) if msg is not None: if evaluate: return self.evaluate(msg, msg.evaluate) else: return XmlUtil.text(msg) if isZSelection: # no message, return text of selection return self.variables.get(self._axisObject.variableQname, "selection") if returnGenLabel: return self._axisObject.genLabel(role=role, lang=lang) return None def evaluate(self, evalObject, evalMethod, otherOrdinate=None, evalArgs=()): xc = self._rendrCntx if self.contextItemBinding and not isinstance(xc.contextItem, ModelFact): previousContextItem = xc.contextItem # xbrli.xbrl xc.contextItem = self.contextItemBinding.yieldedFact else: previousContextItem = None if self.choiceOrdinateContexts and hasattr(self,"choiceOrdinateIndex"): variables = self.choiceOrdinateContexts[self.choiceOrdinateIndex].variables else: variables = self.variables removeVarQnames = [] for qn, value in variables.items(): if qn not in xc.inScopeVars: removeVarQnames.append(qn) xc.inScopeVars[qn] = value if self.parentOrdinateContext is not None: result = self.parentOrdinateContext.evaluate(evalObject, evalMethod, otherOrdinate, evalArgs) elif otherOrdinate is not None: # recurse to other ordinate (which will recurse to z axis) result = otherOrdinate.evaluate(evalObject, evalMethod, None, evalArgs) elif self.zInheritance is not None: result = self.zInheritance.evaluate(evalObject, evalMethod, None, evalArgs) else: try: result = evalMethod(xc, *evalArgs) except XPathContext.XPathException as err: xc.modelXbrl.error(err.code, _("%(element)s set %(xlinkLabel)s \nException: %(error)s"), modelObject=evalObject, element=evalObject.localName, xlinkLabel=evalObject.xlinkLabel, error=err.message) result = '' for qn in removeVarQnames: xc.inScopeVars.pop(qn) if previousContextItem is not None: xc.contextItem = previousContextItem # xbrli.xbrl return result def hasValueExpression(self, otherOrdinate=None): return (self.axisObject.hasValueExpression or (otherOrdinate is not None and otherOrdinate.axisObject.hasValueExpression)) def evalValueExpression(self, fact, otherOrdinate=None): for ordinate in (self, otherOrdinate): if ordinate is not None and ordinate.axisObject.hasValueExpression: return self.evaluate(self.axisObject, ordinate.axisObject.evalValueExpression, otherOrdinate=otherOrdinate, evalArgs=(fact,)) return None def __repr__(self): return ("ordinateContext[{0}]{1})".format(self.objectId(),self.axisObject))