Skip to content

Commit

Permalink
prevent crash when EFM validation selected and role types definitions
Browse files Browse the repository at this point in the history
do not have the pattern sequence - type - title
  • Loading branch information
Herm Fischer authored and Herm Fischer committed Feb 1, 2015
1 parent 1d5c91d commit 01a8d4f
Showing 1 changed file with 65 additions and 3 deletions.
68 changes: 65 additions & 3 deletions arelle/TableStructure.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
except ImportError:
import re
from collections import defaultdict
import os, io, json
from datetime import datetime, timedelta
from arelle import XbrlConst
from arelle.ModelDtsObject import ModelConcept
Expand All @@ -35,6 +36,8 @@
notPAR = "(?!.*" + rePARENTHETICAL + ")"
isPAR = "(?=.*" + rePARENTHETICAL + ")"

UGT_TOPICS = None

def RE(*args):
return re.compile(''.join(args), re.IGNORECASE)

Expand Down Expand Up @@ -183,9 +186,10 @@ def evaluateTableIndex(modelXbrl):
firstDocumentLinkroleURI = None
sortedRoleTypes = sorted(definitionElrs.items(), key=lambda item: item[0])
for roleDefinition, roleType in sortedRoleTypes:
roleType._tableChildren = []
match = roleDefinitionPattern.match(roleDefinition) if roleDefinition else None
if not match:
roleType._tableIndex = (UNCATEG, roleType.roleURI)
roleType._tableIndex = (UNCATEG, "", roleType.roleURI)
continue
seq, tblType, tblName = match.groups()
if isRR:
Expand Down Expand Up @@ -220,7 +224,6 @@ def evaluateTableIndex(modelXbrl):
if tblType == "Document" and not firstDocumentLinkroleURI:
firstDocumentLinkroleURI = roleType.roleURI
roleType._tableIndex = (tableGroup, seq, tblName)
roleType._tableChildren = []

# flow allocate facts to roles (SEC presentation groups)
if not modelXbrl.qnameDimensionDefaults: # may not have run validatino yet
Expand Down Expand Up @@ -257,7 +260,7 @@ def evaluateTableIndex(modelXbrl):
endOfMonth = False
startYr = endDatetime.year
startMo = endDatetime.month - 3
if startMo < 0:
if startMo <= 0:
startMo += 12
startYr -= 1
startDatetime = datetime(startYr, startMo, endDatetime.day, endDatetime.hour, endDatetime.minute, endDatetime.second)
Expand Down Expand Up @@ -343,8 +346,67 @@ def evaluateTableIndex(modelXbrl):

for unmatchedChildRole in unmatchedChildRoles:
roleType._tableChildren.remove(unmatchedChildRole)

for childRoleType in roleType._tableChildren:
childRoleType._tableParent = roleType

unmatchedChildRoles = None # dereference

global UGT_TOPICS
if UGT_TOPICS is None:
try:
from arelle import FileSource
fh = FileSource.openFileStream(modelXbrl.modelManager.cntlr,
os.path.join(modelXbrl.modelManager.cntlr.configDir, "ugt-topics.zip/ugt-topics.json"),
'r', 'utf-8')
UGT_TOPICS = json.load(fh)
fh.close()
for topic in UGT_TOPICS:
topic[6] = set(topic[6]) # change concept abstracts list into concept abstracts set
topic[7] = set(topic[7]) # change concept text blocks list into concept text blocks set
topic[8] = set(topic[8]) # change concept names list into concept names set
except Exception as ex:
UGT_TOPICS = None

if UGT_TOPICS is not None:
def roleUgtConcepts(roleType):
roleConcepts = set()
for rel in modelXbrl.relationshipSet(XbrlConst.parentChild, roleType.roleURI).modelRelationships:
if rel.toModelObject is not None:
roleConcepts.add(rel.toModelObject.name)
if rel.fromModelObject is not None:
roleConcepts.add(rel.fromModelObject.name)
if hasattr(roleType, "_tableChildren"):
for _tableChild in roleType._tableChildren:
roleConcepts |= roleUgtConcepts(_tableChild)
return roleConcepts
topicMatches = {} # topicNum: (best score, roleType)

for roleDefinition, roleType in sortedRoleTypes:
roleTopicType = 'S' if roleDefinition.startswith('S') else 'D'
if getattr(roleType, "_tableParent", None) is None:
# rooted tables in reverse order
concepts = roleUgtConcepts(roleType)
for i, ugtTopic in enumerate(UGT_TOPICS):
if ugtTopic[0] == roleTopicType:
countAbstracts = len(concepts & ugtTopic[6])
countTextBlocks = len(concepts & ugtTopic[7])
countLineItems = len(concepts & ugtTopic[8])
if countAbstracts or countTextBlocks or countLineItems:
_score = (10 * countAbstracts +
1000 * countTextBlocks +
countLineItems / len(concepts))
if i not in topicMatches or _score > topicMatches[i][0]:
topicMatches[i] = (_score, roleType)
for topicNum, scoredRoleType in topicMatches.items():
_score, roleType = scoredRoleType
if _score > getattr(roleType, "_tableTopicScore", 0):
ugtTopic = UGT_TOPICS[topicNum]
roleType._tableTopicScore = _score
roleType._tableTopicType = ugtTopic[0]
roleType._tableTopicName = ugtTopic[3]
roleType._tableTopicCode = ugtTopic[4]
# print ("Match score {:.2f} topic {} preGrp {}".format(_score, ugtTopic[3], roleType.definition))
return firstTableLinkroleURI or firstDocumentLinkroleURI # did build _tableIndex attributes
return None

Expand Down

0 comments on commit 01a8d4f

Please sign in to comment.