def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspects, yChildrenFirst): if yParentStructuralNode is not None: rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables dimDefaults = self.modelXbrl.qnameDimensionDefaults for yStructuralNode in yParentStructuralNode.childStructuralNodes: if yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) if not yStructuralNode.isAbstract: yAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)): if yStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): yAspects[dim].add(yStructuralNode) else: yAspects[ruleAspect].add(yStructuralNode) gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER) # data for columns of row ignoreDimValidity = self.ignoreDimValidity.get() for i, xStructuralNode in enumerate(xStructuralNodes): xAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)): if xStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): xAspects[dim].add(xStructuralNode) else: xAspects[ruleAspect].add(xStructuralNode) cellAspectValues = {} matchableAspects = set() for aspect in _DICT_SET(xAspects.keys()) | _DICT_SET(yAspects.keys()) | _DICT_SET(zAspects.keys()): aspectValue = inheritedAspectValue(self, aspect, xAspects, yAspects, zAspects, xStructuralNode, yStructuralNode) if dimDefaults.get(aspect) != aspectValue: # don't include defaulted dimensions cellAspectValues[aspect] = aspectValue matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys()) priItemQname = cellAspectValues.get(Aspect.CONCEPT) concept = self.modelXbrl.qnameConcepts.get(priItemQname) conceptNotAbstract = concept is None or not concept.isAbstract from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None fp = FactPrototype(self, cellAspectValues) if conceptNotAbstract: # reduce set of matchable facts to those with pri item qname and have dimension aspects facts = self.modelXbrl.factsByQname[priItemQname] if priItemQname else self.modelXbrl.factsInInstance for aspect in matchableAspects: # trim down facts with explicit dimensions match or just present if isinstance(aspect, QName): aspectValue = cellAspectValues.get(aspect, None) if isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: dimMemQname = aspectValue.memberQname # match facts with this explicit value else: dimMemQname = None # match facts that report this dimension elif isinstance(aspectValue, QName): dimMemQname = aspectValue # match facts that have this explicit value else: dimMemQname = None # match facts that report this dimension facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname) for fact in facts: if (all(aspectMatches(rendrCntx, fact, fp, aspect) for aspect in matchableAspects) and all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None) for dim in cellDefaultedDims)): if yStructuralNode.hasValueExpression(xStructuralNode): value = yStructuralNode.evalValueExpression(fact, xStructuralNode) else: value = fact.effectiveValue objectId = fact.objectId() justify = "right" if fact.isNumeric else "left" break if (conceptNotAbstract and (value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp))): if objectId is None: objectId = "f{0}".format(len(self.factPrototypes)) self.factPrototypes.append(fp) # for property views gridCell(self.gridBody, self.dataFirstCol + i, row, value, justify=justify, width=12, # width is in characters, not screen units objectId=objectId, onClick=self.onClick) else: fp.clear() # dereference gridSpacer(self.gridBody, self.dataFirstCol + i, row, CENTERCELL) gridSpacer(self.gridBody, self.dataFirstCol + i, row, RIGHTBORDER) gridSpacer(self.gridBody, self.dataFirstCol + i, row, BOTTOMBORDER) row += 1 if not yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) return row
def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspects, yChildrenFirst): if yParentStructuralNode is not None: rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables dimDefaults = self.modelXbrl.qnameDimensionDefaults for yStructuralNode in yParentStructuralNode.childStructuralNodes: if yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) if not yStructuralNode.isAbstract: yAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get( aspect, (aspect, )): if yStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in (yStructuralNode.aspectValue( Aspect.DIMENSIONS) or emptyList): yAspects[dim].add(yStructuralNode) else: yAspects[ruleAspect].add(yStructuralNode) gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER) # data for columns of row ignoreDimValidity = self.ignoreDimValidity.get() for i, xStructuralNode in enumerate(xStructuralNodes): xAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get( aspect, (aspect, )): if xStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in ( xStructuralNode.aspectValue( Aspect.DIMENSIONS) or emptyList): xAspects[dim].add(xStructuralNode) else: xAspects[ruleAspect].add( xStructuralNode) cellAspectValues = {} matchableAspects = set() for aspect in _DICT_SET(xAspects.keys()) | _DICT_SET( yAspects.keys()) | _DICT_SET(zAspects.keys()): aspectValue = inheritedAspectValue( self, aspect, xAspects, yAspects, zAspects, xStructuralNode, yStructuralNode) if dimDefaults.get( aspect ) != aspectValue: # don't include defaulted dimensions cellAspectValues[aspect] = aspectValue matchableAspects.add( aspectModelAspect.get(aspect, aspect) ) #filterable aspect from rule aspect cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET( cellAspectValues.keys()) priItemQname = cellAspectValues.get(Aspect.CONCEPT) concept = self.modelXbrl.qnameConcepts.get( priItemQname) conceptNotAbstract = concept is None or not concept.isAbstract from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None fp = FactPrototype(self, cellAspectValues) if conceptNotAbstract: # reduce set of matchable facts to those with pri item qname and have dimension aspects facts = self.modelXbrl.factsByQname[ priItemQname] if priItemQname else self.modelXbrl.factsInInstance for aspect in matchableAspects: # trim down facts with explicit dimensions match or just present if isinstance(aspect, QName): aspectValue = cellAspectValues.get( aspect, None) if isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: dimMemQname = aspectValue.memberQname # match facts with this explicit value else: dimMemQname = None # match facts that report this dimension elif isinstance(aspectValue, QName): dimMemQname = aspectValue # match facts that have this explicit value else: dimMemQname = None # match facts that report this dimension facts = facts & self.modelXbrl.factsByDimMemQname( aspect, dimMemQname) for fact in facts: if (all( aspectMatches(rendrCntx, fact, fp, aspect) for aspect in matchableAspects) and all( fact.context.dimMemberQname( dim, includeDefaults=True) in ( dimDefaults[dim], None) for dim in cellDefaultedDims)): if yStructuralNode.hasValueExpression( xStructuralNode): value = yStructuralNode.evalValueExpression( fact, xStructuralNode) else: value = fact.effectiveValue objectId = fact.objectId() justify = "right" if fact.isNumeric else "left" break if (conceptNotAbstract and (value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp))): if objectId is None: objectId = "f{0}".format( len(self.factPrototypes)) self.factPrototypes.append( fp) # for property views gridCell( self.gridBody, self.dataFirstCol + i, row, value, justify=justify, width= 12, # width is in characters, not screen units objectId=objectId, onClick=self.onClick) else: fp.clear() # dereference gridSpacer(self.gridBody, self.dataFirstCol + i, row, CENTERCELL) gridSpacer(self.gridBody, self.dataFirstCol + i, row, RIGHTBORDER) gridSpacer(self.gridBody, self.dataFirstCol + i, row, BOTTOMBORDER) row += 1 if not yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) return row
def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR): if yParentStructuralNode is not None: dimDefaults = self.modelXbrl.qnameDimensionDefaults for yStructuralNode in yParentStructuralNode.childStructuralNodes: if yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR) if not (yStructuralNode.isAbstract or (yStructuralNode.childStructuralNodes and not isinstance(yStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord)))) and yStructuralNode.isLabeled: yAspectStructuralNodes = defaultdict(set) for aspect in aspectModels[self.aspectModel]: if yStructuralNode.hasAspect(aspect): if aspect == Aspect.DIMENSIONS: for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): yAspectStructuralNodes[dim].add(yStructuralNode) else: yAspectStructuralNodes[aspect].add(yStructuralNode) yTagSelectors = yStructuralNode.tagSelectors # data for columns of rows for _, xStructuralNode in enumerate(xStructuralNodes): xAspectStructuralNodes = defaultdict(set) for aspect in aspectModels[self.aspectModel]: if xStructuralNode.hasAspect(aspect): if aspect == Aspect.DIMENSIONS: for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): xAspectStructuralNodes[dim].add(xStructuralNode) else: xAspectStructuralNodes[aspect].add(xStructuralNode) cellTagSelectors = yTagSelectors | xStructuralNode.tagSelectors cellAspectValues = {} matchableAspects = set() for aspect in _DICT_SET(xAspectStructuralNodes.keys()) | _DICT_SET(yAspectStructuralNodes.keys()) | _DICT_SET(zAspectStructuralNodes.keys()): # @UndefinedVariable aspectValue = xStructuralNode.inheritedAspectValue(yStructuralNode, self, aspect, cellTagSelectors, xAspectStructuralNodes, yAspectStructuralNodes, zAspectStructuralNodes) # value is None for a dimension whose value is to be not reported in this slice if (isinstance(aspect, _INT) or # not a dimension @UndefinedVariable dimDefaults.get(aspect) != aspectValue or # explicit dim defaulted will equal the value aspectValue is not None): # typed dim absent will be none cellAspectValues[aspect] = aspectValue matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys()) # @UndefinedVariable priItemQname = cellAspectValues.get(Aspect.CONCEPT) concept = self.modelXbrl.qnameConcepts.get(priItemQname) conceptNotAbstract = concept is None or not concept.isAbstract fact = None value = None fp = FactPrototype(self, cellAspectValues) if conceptNotAbstract: # reduce set of matchable facts to those with pri item qname and have dimension aspects facts = self.modelXbrl.factsByQname(priItemQname, set()) if priItemQname else self.modelXbrl.factsInInstance if self.hasTableFilters: facts = self.modelTable.filterFacts(self.rendrCntx, facts) for aspect in matchableAspects: # trim down facts with explicit dimensions match or just present if isinstance(aspect, QName): aspectValue = cellAspectValues.get(aspect, None) if isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: dimMemQname = aspectValue.memberQname # match facts with this explicit value else: dimMemQname = None # match facts that report this dimension elif isinstance(aspectValue, QName): dimMemQname = aspectValue # match facts that have this explicit value elif aspectValue is None: # match typed dims that don't report this value dimMemQname = DEFAULT else: dimMemQname = None # match facts that report this dimension facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname) if len(facts)==0: break; for fact in facts: if (all(aspectMatches(self.rendrCntx, fact, fp, aspect) for aspect in matchableAspects) and all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None) for dim in cellDefaultedDims) and len(fp.context.qnameDims) == len(fact.context.qnameDims)): if yStructuralNode.hasValueExpression(xStructuralNode): value = yStructuralNode.evalValueExpression(fact, xStructuralNode) else: value = fact.effectiveValue self.factWalkingAction.onFactEvent(fact, value, tblELR) break fp.clear() # dereference row += 1 if not yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR) return row
def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst): if yParentStructuralNode is not None: rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables dimDefaults = self.modelXbrl.qnameDimensionDefaults for yStructuralNode in yParentStructuralNode.childStructuralNodes: if yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst) if not (yStructuralNode.isAbstract or (yStructuralNode.childStructuralNodes and not isinstance(yStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord)))) and yStructuralNode.isLabeled: isEntryPrototype = yStructuralNode.isEntryPrototype(default=False) # row to enter open aspects yAspectStructuralNodes = defaultdict(set) for aspect in aspectModels[self.aspectModel]: if yStructuralNode.hasAspect(aspect): if aspect == Aspect.DIMENSIONS: for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): yAspectStructuralNodes[dim].add(yStructuralNode) else: yAspectStructuralNodes[aspect].add(yStructuralNode) yTagSelectors = yStructuralNode.tagSelectors gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER) # data for columns of row #print ("row " + str(row) + "yNode " + yStructuralNode.definitionNode.objectId() ) ignoreDimValidity = self.ignoreDimValidity.get() for i, xStructuralNode in enumerate(xStructuralNodes): xAspectStructuralNodes = defaultdict(set) for aspect in aspectModels[self.aspectModel]: if xStructuralNode.hasAspect(aspect): if aspect == Aspect.DIMENSIONS: for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): xAspectStructuralNodes[dim].add(xStructuralNode) else: xAspectStructuralNodes[aspect].add(xStructuralNode) cellTagSelectors = yTagSelectors | xStructuralNode.tagSelectors cellAspectValues = {} matchableAspects = set() for aspect in _DICT_SET(xAspectStructuralNodes.keys()) | _DICT_SET(yAspectStructuralNodes.keys()) | _DICT_SET(zAspectStructuralNodes.keys()): aspectValue = xStructuralNode.inheritedAspectValue(yStructuralNode, self, aspect, cellTagSelectors, xAspectStructuralNodes, yAspectStructuralNodes, zAspectStructuralNodes) # value is None for a dimension whose value is to be not reported in this slice if (isinstance(aspect, _INT) or # not a dimension dimDefaults.get(aspect) != aspectValue or # explicit dim defaulted will equal the value aspectValue is not None): # typed dim absent will be none cellAspectValues[aspect] = aspectValue matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys()) priItemQname = cellAspectValues.get(Aspect.CONCEPT) concept = self.modelXbrl.qnameConcepts.get(priItemQname) conceptNotAbstract = concept is None or not concept.isAbstract from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None fp = FactPrototype(self, cellAspectValues) if conceptNotAbstract: # reduce set of matchable facts to those with pri item qname and have dimension aspects facts = self.modelXbrl.factsByQname[priItemQname] if priItemQname else self.modelXbrl.factsInInstance for aspect in matchableAspects: # trim down facts with explicit dimensions match or just present if isinstance(aspect, QName): aspectValue = cellAspectValues.get(aspect, None) if isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: dimMemQname = aspectValue.memberQname # match facts with this explicit value else: dimMemQname = None # match facts that report this dimension elif isinstance(aspectValue, QName): dimMemQname = aspectValue # match facts that have this explicit value elif aspectValue is None: # match typed dims that don't report this value dimMemQname = ModelXbrl.DEFAULT else: dimMemQname = None # match facts that report this dimension facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname) for fact in facts: if (all(aspectMatches(rendrCntx, fact, fp, aspect) for aspect in matchableAspects) and all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None) for dim in cellDefaultedDims)): if yStructuralNode.hasValueExpression(xStructuralNode): value = yStructuralNode.evalValueExpression(fact, xStructuralNode) else: value = fact.effectiveValue objectId = fact.objectId() justify = "right" if fact.isNumeric else "left" break if (conceptNotAbstract and (value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp) or isEntryPrototype)): if objectId is None: objectId = "f{0}".format(len(self.factPrototypes)) self.factPrototypes.append(fp) # for property views for aspect, aspectValue in cellAspectValues.items(): if isinstance(aspectValue, str) and aspectValue.startswith(OPEN_ASPECT_ENTRY_SURROGATE): self.factPrototypeAspectEntryObjectIds[objectId].add(aspectValue) gridCell(self.gridBody, self.dataFirstCol + i, row, value, justify=justify, width=12, # width is in characters, not screen units objectId=objectId, onClick=self.onClick) else: fp.clear() # dereference gridSpacer(self.gridBody, self.dataFirstCol + i, row, CENTERCELL) gridSpacer(self.gridBody, self.dataFirstCol + i, row, RIGHTBORDER) gridSpacer(self.gridBody, self.dataFirstCol + i, row, BOTTOMBORDER) row += 1 if not yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst) return row
def createContext(self, entityIdentScheme, entityIdentValue, periodType, periodStart, periodEndInstant, priItem, dims, segOCCs, scenOCCs, afterSibling=None, beforeSibling=None): xbrlElt = self.modelDocument.xmlRootElement if afterSibling == AUTO_LOCATE_ELEMENT: afterSibling = XmlUtil.lastChild( xbrlElt, XbrlConst.xbrli, ("schemaLocation", "roleType", "arcroleType", "context")) cntxId = 'c-{0:02n}'.format(len(self.contexts) + 1) newCntxElt = XmlUtil.addChild(xbrlElt, XbrlConst.xbrli, "context", attributes=("id", cntxId), afterSibling=afterSibling, beforeSibling=beforeSibling) entityElt = XmlUtil.addChild(newCntxElt, XbrlConst.xbrli, "entity") XmlUtil.addChild(entityElt, XbrlConst.xbrli, "identifier", attributes=("scheme", entityIdentScheme), text=entityIdentValue) periodElt = XmlUtil.addChild(newCntxElt, XbrlConst.xbrli, "period") if periodType == "forever": XmlUtil.addChild(periodElt, XbrlConst.xbrli, "forever") elif periodType == "instant": XmlUtil.addChild(periodElt, XbrlConst.xbrli, "instant", text=XmlUtil.dateunionValue(periodEndInstant, subtractOneDay=True)) elif periodType == "duration": XmlUtil.addChild(periodElt, XbrlConst.xbrli, "startDate", text=XmlUtil.dateunionValue(periodStart)) XmlUtil.addChild(periodElt, XbrlConst.xbrli, "endDate", text=XmlUtil.dateunionValue(periodEndInstant, subtractOneDay=True)) segmentElt = None scenarioElt = None from arelle.ModelInstanceObject import ModelDimensionValue if dims: # requires primary item to determin ambiguous concepts ''' in theory we have to check full set of dimensions for validity in source or any other context element, but for shortcut will see if each dimension is already reported in an unambiguous valid contextElement ''' from arelle.PrototypeInstanceObject import FactPrototype, ContextPrototype, DimValuePrototype fp = FactPrototype(self, priItem, dims.items()) # force trying a valid prototype's context Elements if not isFactDimensionallyValid( self, fp, setPrototypeContextElements=True): self.info( "arelleLinfo", _("Create context for %(priItem)s, cannot determine valid context elements, no suitable hypercubes" ), modelObject=self, priItem=priItem) fpDims = fp.context.qnameDims for dimQname in sorted(fpDims.keys()): dimValue = fpDims[dimQname] if isinstance(dimValue, DimValuePrototype): dimMemberQname = dimValue.memberQname # None if typed dimension contextEltName = dimValue.contextElement else: # qname for explicit or node for typed dimMemberQname = None contextEltName = None if contextEltName == "segment": if segmentElt is None: segmentElt = XmlUtil.addChild(entityElt, XbrlConst.xbrli, "segment") contextElt = segmentElt elif contextEltName == "scenario": if scenarioElt is None: scenarioElt = XmlUtil.addChild(newCntxElt, XbrlConst.xbrli, "scenario") contextElt = scenarioElt else: self.info( "arelleLinfo", _("Create context, %(dimension)s, cannot determine context element, either no all relationship or validation issue" ), modelObject=self, dimension=dimQname), continue dimConcept = self.qnameConcepts[dimQname] dimAttr = ("dimension", XmlUtil.addQnameValue(xbrlElt, dimConcept.qname)) if dimConcept.isTypedDimension: dimElt = XmlUtil.addChild(contextElt, XbrlConst.xbrldi, "xbrldi:typedMember", attributes=dimAttr) if isinstance(dimValue, (ModelDimensionValue, DimValuePrototype)) and dimValue.isTyped: XmlUtil.copyNodes(dimElt, dimValue.typedMember) elif dimMemberQname: dimElt = XmlUtil.addChild(contextElt, XbrlConst.xbrldi, "xbrldi:explicitMember", attributes=dimAttr, text=XmlUtil.addQnameValue( xbrlElt, dimMemberQname)) if segOCCs: if segmentElt is None: segmentElt = XmlUtil.addChild(entityElt, XbrlConst.xbrli, "segment") XmlUtil.copyNodes(segmentElt, segOCCs) if scenOCCs: if scenarioElt is None: scenarioElt = XmlUtil.addChild(newCntxElt, XbrlConst.xbrli, "scenario") XmlUtil.copyNodes(scenarioElt, scenOCCs) self.modelDocument.contextDiscover(newCntxElt) XmlValidate.validate(self, newCntxElt) return newCntxElt
def bodyCells(self, row, yAxisParentObj, xFilters, zFilters, yChildrenFirst): dimDefaults = self.modelXbrl.qnameDimensionDefaults priItemQnameErrors = set() dimQnameErrors = set() memQnameErrors = set() for axisMbrRel in self.axisMbrRelSet.fromModelObject(yAxisParentObj): yAxisHdrObj = axisMbrRel.toModelObject if yChildrenFirst: row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters, yChildrenFirst) if yAxisHdrObj.abstract == "false": yAxisPriItemQname = inheritedPrimaryItemQname( self, yAxisHdrObj) yAxisExplicitDims = inheritedExplicitDims(self, yAxisHdrObj) gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER) # data for columns of row ignoreDimValidity = self.ignoreDimValidity.get() zPriItemQname = None zDims = set() for zIndex in self.zFilterIndex: zFilter = zFilters[zIndex] if zFilter[0]: zPriItemQname = zFilter[0] # inherit pri item zDims |= zFilter[1] # or in z-dims for i, colFilter in enumerate(xFilters): colPriItemQname = colFilter[0] # y axis pri item if not colPriItemQname: colPriItemQname = yAxisPriItemQname # y axis if not colPriItemQname: colPriItemQname = zPriItemQname # z axis fp = FactPrototype( self, colPriItemQname, yAxisExplicitDims | colFilter[1] | zDims) from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None for fact in self.modelXbrl.facts: if fact.qname == fp.qname: factDimMem = fact.context.dimMemberQname defaultedDims = _DICT_SET( dimDefaults.keys()) - fp.dimKeys if (all( factDimMem(dim, includeDefaults=True) == mem for dim, mem in fp.dims) and all( factDimMem(dim, includeDefaults=True) in (dimDefaults[dim], None) for dim in defaultedDims)): value = fact.effectiveValue objectId = fact.objectId() justify = "right" if fact.isNumeric else "left" break if value is not None or ignoreDimValidity or isFactDimensionallyValid( self, fp): if objectId is None: objectId = "f{0}".format(len(self.factPrototypes)) self.factPrototypes.append( fp) # for property views gridCell( self.gridBody, self.dataFirstCol + i, row, value, justify=justify, width=12, # width is in characters, not screen units objectId=objectId, onClick=self.onClick) else: gridSpacer(self.gridBody, self.dataFirstCol + i, row, CENTERCELL) gridSpacer(self.gridBody, self.dataFirstCol + i, row, RIGHTBORDER) gridSpacer(self.gridBody, self.dataFirstCol + i, row, BOTTOMBORDER) row += 1 if not yChildrenFirst: row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters, yChildrenFirst) return row
def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspects, yChildrenFirst): if yParentStructuralNode is not None: rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables dimDefaults = self.modelXbrl.qnameDimensionDefaults for yStructuralNode in yParentStructuralNode.childStructuralNodes: if yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) if not yStructuralNode.isAbstract: if self.type == XML: self.xCells = etree.SubElement(self.yCells, tableModelQName("cells"), attrib={"disposition": "x"}) yAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)): if yStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): yAspects[dim].add(yStructuralNode) else: yAspects[ruleAspect].add(yStructuralNode) # data for columns of rows ignoreDimValidity = self.ignoreDimValidity.get() for i, xStructuralNode in enumerate(xStructuralNodes): xAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)): if xStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): xAspects[dim].add(xStructuralNode) else: xAspects[ruleAspect].add(xStructuralNode) cellAspectValues = {} matchableAspects = set() for aspect in _DICT_SET(xAspects.keys()) | _DICT_SET(yAspects.keys()) | _DICT_SET(zAspects.keys()): aspectValue = inheritedAspectValue(self, aspect, xAspects, yAspects, zAspects, xStructuralNode, yStructuralNode) if dimDefaults.get(aspect) != aspectValue: # don't include defaulted dimensions cellAspectValues[aspect] = aspectValue matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys()) priItemQname = cellAspectValues.get(Aspect.CONCEPT) concept = self.modelXbrl.qnameConcepts.get(priItemQname) conceptNotAbstract = concept is None or not concept.isAbstract from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None fp = FactPrototype(self, cellAspectValues) if conceptNotAbstract: # reduce set of matchable facts to those with pri item qname and have dimension aspects facts = self.modelXbrl.factsByQname[priItemQname] if priItemQname else self.modelXbrl.factsInInstance for aspect in matchableAspects: # trim down facts with explicit dimensions match or just present if isinstance(aspect, QName): aspectValue = cellAspectValues.get(aspect, None) if isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: dimMemQname = aspectValue.memberQname # match facts with this explicit value else: dimMemQname = None # match facts that report this dimension elif isinstance(aspectValue, QName): dimMemQname = aspectValue # match facts that have this explicit value else: dimMemQname = None # match facts that report this dimension facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname) for fact in facts: if (all(aspectMatches(rendrCntx, fact, fp, aspect) for aspect in matchableAspects) and all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None) for dim in cellDefaultedDims)): if yStructuralNode.hasValueExpression(xStructuralNode): value = yStructuralNode.evalValueExpression(fact, xStructuralNode) else: value = fact.effectiveValue justify = "right" if fact.isNumeric else "left" break if conceptNotAbstract: if value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp): if self.type == HTML: etree.SubElement(self.rowElts[row - 1], "{http://www.w3.org/1999/xhtml}td", attrib={"class":"cell", "style":"text-align:{0};width:8em".format(justify)} ).text = value or "\u00A0" elif self.type == XML: if value is not None and fact is not None: self.xCells.append(etree.Comment("{0}: context {1}, value {2}, file {3}, line {4}" .format(fact.qname, fact.contextID, value, fact.modelDocument.basename, fact.sourceline))) cellElt = etree.SubElement(self.xCells, tableModelQName("cell")) etree.SubElement(cellElt, tableModelQName("fact") ).text = '#' + elementFragmentIdentifier(fact) else: if self.type == HTML: etree.SubElement(self.rowElts[row - 1], "{http://www.w3.org/1999/xhtml}td", attrib={"class":"blockedCell", "style":"text-align:{0};width:8em".format(justify)} ).text = "\u00A0\u00A0" elif self.type == XML: etree.SubElement(self.xCells, tableModelQName("cell"), attrib={"blocked":"true"}) else: # concept is abstract if self.type == HTML: etree.SubElement(self.rowElts[row - 1], "{http://www.w3.org/1999/xhtml}td", attrib={"class":"abstractCell", "style":"text-align:{0};width:8em".format(justify)} ).text = "\u00A0\u00A0" elif self.type == XML: etree.SubElement(self.xCells, tableModelQName("cell"), attrib={"abstract":"true"}) fp.clear() # dereference row += 1 if not yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) return row
def bodyCells(self, row, yAxisParentObj, xFilters, zFilters, yChildrenFirst): dimDefaults = self.modelXbrl.qnameDimensionDefaults for axisMbrRel in self.axisMbrRelSet.fromModelObject(yAxisParentObj): yAxisHdrObj = axisMbrRel.toModelObject if yChildrenFirst: row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters, yChildrenFirst) if yAxisHdrObj.abstract == "false": yAxisPriItemQname = inheritedPrimaryItemQname( self, yAxisHdrObj) yAxisExplicitDims = inheritedExplicitDims(self, yAxisHdrObj) # data for columns of row ignoreDimValidity = self.ignoreDimValidity.get() zPriItemQname = None zDims = set() for zIndex in self.zFilterIndex: zFilter = zFilters[zIndex] if zFilter[0]: zPriItemQname = zFilter[0] # inherit pri item zDims |= zFilter[1] # or in z-dims for i, colFilter in enumerate(xFilters): colPriItemQname = colFilter[0] # y axis pri item if not colPriItemQname: colPriItemQname = yAxisPriItemQname # y axis if not colPriItemQname: colPriItemQname = zPriItemQname # z axis fp = FactPrototype( self, colPriItemQname, yAxisExplicitDims | colFilter[1] | zDims) from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None for fact in self.modelXbrl.facts: if fact.qname == fp.qname: factDimMem = fact.context.dimMemberQname defaultedDims = dimDefaults.keys() - fp.dimKeys if (all( factDimMem(dim, includeDefaults=True) == mem for dim, mem in fp.dims) and all( factDimMem(dim, includeDefaults=True) in (dimDefaults[dim], None) for dim in defaultedDims)): value = fact.effectiveValue objectId = fact.objectId() justify = "right" if fact.isNumeric else "left" break if value is not None or ignoreDimValidity or isFactDimensionallyValid( self, fp): etree.SubElement( self.rowElts[row - 1], "{http://www.w3.org/1999/xhtml}td", attrib={ "class": "cell", "style": "text-align:{0};width:8em".format(justify) }).text = value if value else "\u00A0" else: etree.SubElement( self.rowElts[row - 1], "{http://www.w3.org/1999/xhtml}td", attrib={ "class": "blockedCell", "style": "text-align:{0};width:8em".format(justify) }).text = "\u00A0\u00A0" row += 1 if not yChildrenFirst: row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters, yChildrenFirst) return row
def expandDefinition(view, structuralNode, breakdownNode, definitionNode, depth, axisDisposition, facts, i=None, tblAxisRels=None, processOpenDefinitionNode=True): subtreeRelationships = view.axisSubtreeRelSet.fromModelObject( definitionNode) def checkLabelWidth(structuralNode, checkBoundFact=False): if axisDisposition == "y": # messages can't be evaluated, just use the text portion of format string label = structuralNode.header( lang=view.lang, returnGenLabel=not checkBoundFact, returnMsgFormatString=not checkBoundFact) if label: # need to et more exact word length in screen units widestWordLen = max( len(w) * RENDER_UNITS_PER_CHAR for w in label.split()) # abstract only pertains to subtree of closed nodesbut not cartesian products or open nodes while structuralNode.depth >= len(view.rowHdrColWidth): view.rowHdrColWidth.append(0) if definitionNode.isAbstract or not subtreeRelationships: # isinstance(definitionNode, ModelOpenDefinitionNode): if widestWordLen > view.rowHdrColWidth[ structuralNode.depth]: view.rowHdrColWidth[ structuralNode.depth] = widestWordLen else: if widestWordLen > view.rowNonAbstractHdrSpanMin[ structuralNode.depth]: view.rowNonAbstractHdrSpanMin[ structuralNode.depth] = widestWordLen if structuralNode and isinstance( definitionNode, (ModelBreakdown, ModelEuAxisCoord, ModelDefinitionNode)): try: #cartesianProductNestedArgs = (view, depth, axisDisposition, facts, tblAxisRels, i) ordCardinality, ordDepth = definitionNode.cardinalityAndDepth( structuralNode) if (not definitionNode.isAbstract and isinstance(definitionNode, ModelClosedDefinitionNode) and ordCardinality == 0): view.modelXbrl.error( "xbrlte:closedDefinitionNodeZeroCardinality", _("Closed definition node %(xlinkLabel)s does not contribute at least one structural node" ), modelObject=(view.modelTable, definitionNode), xlinkLabel=definitionNode.xlinkLabel, axis=definitionNode.localName) nestedDepth = depth + ordDepth # HF test cartesianProductNestedArgs = [ view, nestedDepth, axisDisposition, facts, tblAxisRels, i ] if axisDisposition == "z": if depth == 1: # choices (combo boxes) don't add to z row count view.zAxisRows += 1 elif axisDisposition == "x": if ordDepth: if nestedDepth - 1 > view.colHdrRows: view.colHdrRows = nestedDepth - 1 ''' if not view.colHdrDocRow: if definitionNode.header(role="http://www.xbrl.org/2008/role/documentation", lang=view.lang): view.colHdrDocRow = True if not view.colHdrCodeRow: if definitionNode.header(role="http://www.eurofiling.info/role/2010/coordinate-code"): view.colHdrCodeRow = True ''' hdrNonStdRoles = view.colHdrNonStdRoles elif axisDisposition == "y": if ordDepth: #if not definitionNode.isAbstract: # view.dataRows += ordCardinality if nestedDepth - 1 > view.rowHdrCols: view.rowHdrCols = nestedDepth - 1 for j in range(1 + ordDepth): view.rowHdrColWidth.append( RENDER_UNITS_PER_CHAR ) # min width for 'tail' of nonAbstract coordinate view.rowNonAbstractHdrSpanMin.append(0) checkLabelWidth(structuralNode, checkBoundFact=False) ''' if not view.rowHdrDocCol: if definitionNode.header(role="http://www.xbrl.org/2008/role/documentation", lang=view.lang): view.rowHdrDocCol = True if not view.rowHdrCodeCol: if definitionNode.header(role="http://www.eurofiling.info/role/2010/coordinate-code"): view.rowHdrCodeCol = True ''' hdrNonStdRoles = view.rowHdrNonStdRoles if axisDisposition in ("x", "y"): hdrNonStdPosition = -1 # where a match last occured for rel in view.modelXbrl.relationshipSet( XbrlConst.elementLabel).fromModelObject( definitionNode): if rel.toModelObject is not None and rel.toModelObject.role != XbrlConst.genStandardLabel: labelLang = rel.toModelObject.xmlLang labelRole = rel.toModelObject.role if (labelLang == view.lang or labelLang.startswith(view.lang) or view.lang.startswith(labelLang) or ("code" in labelRole)): labelRole = rel.toModelObject.role if labelRole in hdrNonStdRoles: hdrNonStdPosition = hdrNonStdRoles.index( labelRole) else: hdrNonStdRoles.insert(hdrNonStdPosition + 1, labelRole) isCartesianProductExpanded = False if not isinstance(definitionNode, ModelFilterDefinitionNode): isCartesianProductExpanded = True # note: reduced set of facts should always be passed to subsequent open nodes for axisSubtreeRel in subtreeRelationships: childDefinitionNode = axisSubtreeRel.toModelObject if childDefinitionNode.isRollUp: structuralNode.rollUpStructuralNode = StructuralNode( structuralNode, breakdownNode, childDefinitionNode, ) if not structuralNode.childStructuralNodes: # first sub ordinate is the roll up structuralNode.subtreeRollUp = CHILD_ROLLUP_FIRST else: structuralNode.subtreeRollUp = CHILD_ROLLUP_LAST if not view.topRollup.get(axisDisposition): view.topRollup[ axisDisposition] = structuralNode.subtreeRollUp else: if ( isinstance(definitionNode, (ModelBreakdown, ModelCompositionDefinitionNode)) and isinstance( childDefinitionNode, ModelRelationshipDefinitionNode) ): # append list products to composititionAxes subObjCntxs childStructuralNode = structuralNode else: childStructuralNode = StructuralNode( structuralNode, breakdownNode, childDefinitionNode ) # others are nested structuralNode if axisDisposition != "z": structuralNode.childStructuralNodes.append( childStructuralNode) if axisDisposition != "z": expandDefinition(view, childStructuralNode, breakdownNode, childDefinitionNode, depth + ordDepth, axisDisposition, facts, i, tblAxisRels) #recurse cartesianProductExpander( childStructuralNode, *cartesianProductNestedArgs) else: childStructuralNode.indent = depth - 1 if structuralNode.choiceStructuralNodes is not None: structuralNode.choiceStructuralNodes.append( childStructuralNode) expandDefinition(view, childStructuralNode, breakdownNode, childDefinitionNode, depth + 1, axisDisposition, facts) #recurse # required when switching from abstract to roll up to determine abstractness #if not structuralNode.subtreeRollUp and structuralNode.childStructuralNodes and definitionNode.tag.endswith("Node"): # structuralNode.subtreeRollUp = CHILDREN_BUT_NO_ROLLUP #if not hasattr(structuralNode, "indent"): # probably also for multiple open axes if processOpenDefinitionNode: if isinstance(definitionNode, ModelRelationshipDefinitionNode): structuralNode.isLabeled = False selfStructuralNodes = {} if definitionNode.axis.endswith( '-or-self') else None for rel in definitionNode.relationships(structuralNode): if not isinstance(rel, list): relChildStructuralNode = addRelationship( breakdownNode, definitionNode, rel, structuralNode, cartesianProductNestedArgs, selfStructuralNodes) else: addRelationships(breakdownNode, definitionNode, rel, relChildStructuralNode, cartesianProductNestedArgs) if axisDisposition == "z": # if definitionNode is first structural node child remove it if structuralNode.choiceStructuralNodes and structuralNode.choiceStructuralNodes[ 0].definitionNode == definitionNode: del structuralNode.choiceStructuralNodes[0] # flatten hierarchy of nested structural nodes inot choice nodes (for single listbox) def flattenChildNodesToChoices(childStructuralNodes, indent): while childStructuralNodes: choiceStructuralNode = childStructuralNodes.pop( 0) choiceStructuralNode.indent = indent structuralNode.choiceStructuralNodes.append( choiceStructuralNode) flattenChildNodesToChoices( choiceStructuralNode.childStructuralNodes, indent + 1) if structuralNode.childStructuralNodes: flattenChildNodesToChoices( structuralNode.childStructuralNodes, 0) # set up by definitionNode.relationships if isinstance(definitionNode, ModelConceptRelationshipDefinitionNode): if (definitionNode._sourceQname != XbrlConst.qnXfiRoot and definitionNode._sourceQname not in view.modelXbrl.qnameConcepts): view.modelXbrl.error( "xbrlte:invalidConceptRelationshipSource", _("Concept relationship rule node %(xlinkLabel)s source %(source)s does not refer to an existing concept." ), modelObject=definitionNode, xlinkLabel=definitionNode.xlinkLabel, source=definitionNode._sourceQname) elif isinstance(definitionNode, ModelDimensionRelationshipDefinitionNode): dim = view.modelXbrl.qnameConcepts.get( definitionNode._dimensionQname) if dim is None or not dim.isExplicitDimension: view.modelXbrl.error( "xbrlte:invalidExplicitDimensionQName", _("Dimension relationship rule node %(xlinkLabel)s dimension %(dimension)s does not refer to an existing explicit dimension." ), modelObject=definitionNode, xlinkLabel=definitionNode.xlinkLabel, dimension=definitionNode._dimensionQname) domMbr = view.modelXbrl.qnameConcepts.get( definitionNode._sourceQname) if domMbr is None or not domMbr.isDomainMember: view.modelXbrl.error( "xbrlte:invalidDimensionRelationshipSource", _("Dimension relationship rule node %(xlinkLabel)s source %(source)s does not refer to an existing domain member." ), modelObject=definitionNode, xlinkLabel=definitionNode.xlinkLabel, source=definitionNode._sourceQname) if (definitionNode._axis in ("child", "child-or-self", "parent", "parent-or-self", "sibling", "sibling-or-self") and (not isinstance(definitionNode._generations, _NUM_TYPES) or definitionNode._generations > 1)): view.modelXbrl.error( "xbrlte:relationshipNodeTooManyGenerations ", _("Relationship rule node %(xlinkLabel)s formulaAxis %(axis)s implies a single generation tree walk but generations %(generations)s is greater than one." ), modelObject=definitionNode, xlinkLabel=definitionNode.xlinkLabel, axis=definitionNode._axis, generations=definitionNode._generations) elif isinstance(definitionNode, ModelSelectionDefinitionNode): structuralNode.setHasOpenNode() structuralNode.isLabeled = False isCartesianProductExpanded = True varQn = definitionNode.variableQname if varQn: selections = sorted(structuralNode.evaluate( definitionNode, definitionNode.evaluate) or [], key=lambda obj: sortkey(obj)) if isinstance( selections, (list, set, tuple)) and len(selections) > 1: for selection in selections: # nested choices from selection list childStructuralNode = StructuralNode( structuralNode, breakdownNode, definitionNode, contextItemFact=selection) childStructuralNode.variables[ varQn] = selection childStructuralNode.indent = 0 if axisDisposition == "z": structuralNode.choiceStructuralNodes.append( childStructuralNode) childStructuralNode.zSelection = True else: structuralNode.childStructuredNodeList.append( childStructuralNode) expandDefinition( view, childStructuralNode, breakdownNode, definitionNode, depth, axisDisposition, facts, processOpenDefinitionNode=False ) #recurse cartesianProductExpander( childStructuralNode, *cartesianProductNestedArgs) else: structuralNode.variables[varQn] = selections elif isinstance(definitionNode, ModelFilterDefinitionNode): structuralNode.setHasOpenNode() structuralNode.isLabeled = False isCartesianProductExpanded = True structuralNode.abstract = True # spanning ordinate acts as a subtitle filteredFactsPartitions = structuralNode.evaluate( definitionNode, definitionNode.filteredFactsPartitions, evalArgs=(facts, )) if structuralNode._rendrCntx.formulaOptions.traceVariableFilterWinnowing: view.modelXbrl.info( "table:trace", _("Filter node %(xlinkLabel)s facts partitions: %(factsPartitions)s" ), modelObject=definitionNode, xlinkLabel=definitionNode.xlinkLabel, factsPartitions=str(filteredFactsPartitions)) # ohly for fact entry (true if no parent open nodes or all are on entry prototype row) if axisDisposition != "z": childList = structuralNode.childStructuralNodes if structuralNode.isEntryPrototype(default=True): for i in range( getattr( view, "openBreakdownLines", # for file output, 1 entry row if no facts 0 if filteredFactsPartitions else 1)): view.aspectEntryObjectId += 1 filteredFactsPartitions.append([ FactPrototype( view, { "aspectEntryObjectId": OPEN_ASPECT_ENTRY_SURROGATE + str(view.aspectEntryObjectId) }) ]) if structuralNode.isEntryPrototype( default=False): break # only one node per cartesian product under outermost nested open entry row else: childList = structuralNode.choiceStructuralNodes for factsPartition in filteredFactsPartitions: childStructuralNode = StructuralNode( structuralNode, breakdownNode, definitionNode, contextItemFact=factsPartition[0]) childStructuralNode.indent = 0 childStructuralNode.depth -= 1 # for label width; parent is merged/invisible childList.append(childStructuralNode) checkLabelWidth(childStructuralNode, checkBoundFact=True) #expandDefinition(view, childStructuralNode, breakdownNode, definitionNode, depth, axisDisposition, factsPartition, processOpenDefinitionNode=False) #recurse cartesianProductNestedArgs[3] = factsPartition # note: reduced set of facts should always be passed to subsequent open nodes if subtreeRelationships: for axisSubtreeRel in subtreeRelationships: child2DefinitionNode = axisSubtreeRel.toModelObject child2StructuralNode = StructuralNode( childStructuralNode, breakdownNode, child2DefinitionNode ) # others are nested structuralNode childStructuralNode.childStructuredNodeList.append( child2StructuralNode) expandDefinition(view, child2StructuralNode, breakdownNode, child2DefinitionNode, depth + ordDepth, axisDisposition, factsPartition) #recurse cartesianProductExpander( child2StructuralNode, *cartesianProductNestedArgs) else: cartesianProductExpander( childStructuralNode, *cartesianProductNestedArgs) # sort by header (which is likely to be typed dim value, for example) childList.sort( key=lambda childStructuralNode: childStructuralNode. header(lang=view.lang, returnGenLabel=False, returnMsgFormatString=False) or '' ) # exception on trying to sort if header returns None # TBD if there is no abstract 'sub header' for these subOrdCntxs, move them in place of parent structuralNode elif isinstance(definitionNode, ModelTupleDefinitionNode): structuralNode.abstract = True # spanning ordinate acts as a subtitle matchingTupleFacts = structuralNode.evaluate( definitionNode, definitionNode.filteredFacts, evalArgs=(facts, )) for tupleFact in matchingTupleFacts: childStructuralNode = StructuralNode( structuralNode, breakdownNode, definitionNode, contextItemFact=tupleFact) childStructuralNode.indent = 0 structuralNode.childStructuredNodeList.append( childStructuralNode) expandDefinition(view, childStructuralNode, breakdownNode, definitionNode, depth, axisDisposition, [tupleFact]) #recurse # sort by header (which is likely to be typed dim value, for example) if (structuralNode.childStructuralNodes and any( sOC.header(lang=view.lang) for sOC in structuralNode.childStructuralNodes)): structuralNode.childStructuralNodes.sort( key=lambda childStructuralNode: childStructuralNode .header(lang=view.lang) or '') elif isinstance(definitionNode, ModelRuleDefinitionNode): for constraintSet in definitionNode.constraintSets.values( ): for aspect in constraintSet.aspectsCovered(): if not constraintSet.aspectValueDependsOnVars( aspect): if aspect == Aspect.CONCEPT: conceptQname = definitionNode.aspectValue( view.rendrCntx, Aspect.CONCEPT) concept = view.modelXbrl.qnameConcepts.get( conceptQname) if concept is None or not concept.isItem or concept.isDimensionItem or concept.isHypercubeItem: view.modelXbrl.error( "xbrlte:invalidQNameAspectValue", _("Rule node %(xlinkLabel)s specifies concept %(concept)s does not refer to an existing primary item concept." ), modelObject=definitionNode, xlinkLabel=definitionNode. xlinkLabel, concept=conceptQname) elif isinstance(aspect, QName): dim = view.modelXbrl.qnameConcepts.get( aspect) memQname = definitionNode.aspectValue( view.rendrCntx, aspect) mem = view.modelXbrl.qnameConcepts.get( memQname) if dim is None or not dim.isDimensionItem: view.modelXbrl.error( "xbrlte:invalidQNameAspectValue", _("Rule node %(xlinkLabel)s specifies dimension %(concept)s does not refer to an existing dimension concept." ), modelObject=definitionNode, xlinkLabel=definitionNode. xlinkLabel, concept=aspect) if isinstance(memQname, QName) and ( mem is None or not mem.isDomainMember): view.modelXbrl.error( "xbrlte:invalidQNameAspectValue", _("Rule node %(xlinkLabel)s specifies domain member %(concept)s does not refer to an existing domain member concept." ), modelObject=definitionNode, xlinkLabel=definitionNode. xlinkLabel, concept=memQname) if axisDisposition == "z": if structuralNode.choiceStructuralNodes: choiceNodeIndex = view.zOrdinateChoices.get( definitionNode, 0) if isinstance(choiceNodeIndex, dict): # aspect entry for open node structuralNode.aspects = choiceNodeIndex structuralNode.choiceNodeIndex = -1 elif choiceNodeIndex < len( structuralNode.choiceStructuralNodes): structuralNode.choiceNodeIndex = choiceNodeIndex else: structuralNode.choiceNodeIndex = 0 view.zmostOrdCntx = structuralNode if not isCartesianProductExpanded or ( axisDisposition == "z" and structuralNode.choiceStructuralNodes is not None): cartesianProductExpander(structuralNode, *cartesianProductNestedArgs) if not structuralNode.childStructuralNodes: # childless root ordinate, make a child to iterate in producing table subOrdContext = StructuralNode(structuralNode, breakdownNode, definitionNode) except ResolutionException as ex: if sys.version[0] >= '3': #import traceback #traceback.print_tb(ex.__traceback__) raise ex.with_traceback( ex.__traceback__) # provide original traceback information else: raise ex except Exception as ex: e = ResolutionException( "arelle:resolutionException", _("Exception in resolution of definition node %(node)s: %(error)s" ), modelObject=definitionNode, node=definitionNode.qname, error=str(ex)) if sys.version[0] >= '3': raise e.with_traceback( ex.__traceback__) # provide original traceback information else: raise e
def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR): if yParentStructuralNode is not None: dimDefaults = self.modelXbrl.qnameDimensionDefaults for yStructuralNode in yParentStructuralNode.childStructuralNodes: if yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR) if not (yStructuralNode.isAbstract or (yStructuralNode.childStructuralNodes and not isinstance( yStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord))) ) and yStructuralNode.isLabeled: yAspectStructuralNodes = defaultdict(set) for aspect in aspectModels[self.aspectModel]: if yStructuralNode.hasAspect(aspect): if aspect == Aspect.DIMENSIONS: for dim in (yStructuralNode.aspectValue( Aspect.DIMENSIONS) or emptyList): yAspectStructuralNodes[dim].add( yStructuralNode) else: yAspectStructuralNodes[aspect].add( yStructuralNode) yTagSelectors = yStructuralNode.tagSelectors # data for columns of rows for _, xStructuralNode in enumerate(xStructuralNodes): xAspectStructuralNodes = defaultdict(set) for aspect in aspectModels[self.aspectModel]: if xStructuralNode.hasAspect(aspect): if aspect == Aspect.DIMENSIONS: for dim in (xStructuralNode.aspectValue( Aspect.DIMENSIONS) or emptyList): xAspectStructuralNodes[dim].add( xStructuralNode) else: xAspectStructuralNodes[aspect].add( xStructuralNode) cellTagSelectors = yTagSelectors | xStructuralNode.tagSelectors cellAspectValues = {} matchableAspects = set() for aspect in _DICT_SET( xAspectStructuralNodes.keys()) | _DICT_SET( yAspectStructuralNodes.keys()) | _DICT_SET( zAspectStructuralNodes.keys( )): # @UndefinedVariable aspectValue = xStructuralNode.inheritedAspectValue( yStructuralNode, self, aspect, cellTagSelectors, xAspectStructuralNodes, yAspectStructuralNodes, zAspectStructuralNodes) # value is None for a dimension whose value is to be not reported in this slice if (isinstance(aspect, _INT) or # not a dimension @UndefinedVariable dimDefaults.get(aspect) != aspectValue or # explicit dim defaulted will equal the value aspectValue is not None ): # typed dim absent will be none cellAspectValues[aspect] = aspectValue matchableAspects.add( aspectModelAspect.get(aspect, aspect) ) #filterable aspect from rule aspect cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET( cellAspectValues.keys()) # @UndefinedVariable priItemQname = cellAspectValues.get(Aspect.CONCEPT) concept = self.modelXbrl.qnameConcepts.get( priItemQname) conceptNotAbstract = concept is None or not concept.isAbstract fact = None value = None fp = FactPrototype(self, cellAspectValues) if conceptNotAbstract: # reduce set of matchable facts to those with pri item qname and have dimension aspects facts = self.modelXbrl.factsByQname( priItemQname, set() ) if priItemQname else self.modelXbrl.factsInInstance if self.hasTableFilters: facts = self.modelTable.filterFacts( self.rendrCntx, facts) for aspect in matchableAspects: # trim down facts with explicit dimensions match or just present if isinstance(aspect, QName): aspectValue = cellAspectValues.get( aspect, None) if isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: dimMemQname = aspectValue.memberQname # match facts with this explicit value else: dimMemQname = None # match facts that report this dimension elif isinstance(aspectValue, QName): dimMemQname = aspectValue # match facts that have this explicit value elif aspectValue is None: # match typed dims that don't report this value dimMemQname = DEFAULT else: dimMemQname = None # match facts that report this dimension facts = facts & self.modelXbrl.factsByDimMemQname( aspect, dimMemQname) if len(facts) == 0: break for fact in facts: if (all( aspectMatches(self.rendrCntx, fact, fp, aspect) for aspect in matchableAspects) and all( fact.context.dimMemberQname( dim, includeDefaults=True) in ( dimDefaults[dim], None) for dim in cellDefaultedDims) and len(fp.context.qnameDims) == len( fact.context.qnameDims)): if yStructuralNode.hasValueExpression( xStructuralNode): value = yStructuralNode.evalValueExpression( fact, xStructuralNode) else: value = fact.effectiveValue self.factWalkingAction.onFactEvent( fact, value, tblELR) break fp.clear() # dereference row += 1 if not yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR) return row