arelle-release 2.37.46__py3-none-any.whl → 2.38.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- arelle/BetaFeatures.py +0 -21
- arelle/Cntlr.py +15 -8
- arelle/CntlrCmdLine.py +121 -56
- arelle/CntlrWinMain.py +143 -70
- arelle/DialogFind.py +1 -1
- arelle/DialogPluginManager.py +6 -4
- arelle/DisclosureSystem.py +7 -0
- arelle/ErrorManager.py +21 -6
- arelle/FileSource.py +11 -4
- arelle/FunctionIxt.py +16 -11
- arelle/HtmlUtil.py +5 -4
- arelle/LeiUtil.py +63 -43
- arelle/ModelDocument.py +20 -15
- arelle/ModelDtsObject.py +8 -0
- arelle/ModelInstanceObject.py +1 -1
- arelle/ModelObject.py +16 -18
- arelle/ModelObjectFactory.py +35 -17
- arelle/ModelXbrl.py +28 -11
- arelle/PluginManager.py +130 -105
- arelle/RuntimeOptions.py +1 -0
- arelle/UrlUtil.py +14 -0
- arelle/Validate.py +17 -12
- arelle/ValidateDuplicateFacts.py +3 -1
- arelle/ValidateFileSource.py +38 -0
- arelle/ValidateFilingText.py +3 -3
- arelle/ValidateXbrl.py +5 -2
- arelle/ValidateXbrlCalcs.py +210 -186
- arelle/ValidateXbrlDTS.py +1 -1
- arelle/ViewFile.py +1 -0
- arelle/ViewFileFactTable.py +2 -2
- arelle/ViewWinDTS.py +4 -1
- arelle/WebCache.py +28 -24
- arelle/XbrlConst.py +22 -0
- arelle/XmlUtil.py +16 -21
- arelle/XmlValidate.py +6 -9
- arelle/_version.py +16 -3
- arelle/api/Session.py +11 -2
- arelle/config/disclosuresystems.xsd +2 -0
- arelle/config/rosettaEntitlements.plist +8 -0
- arelle/conformance/CSVTestcaseLoader.py +1 -1
- arelle/formula/XPathContext.py +3 -3
- arelle/logging/formatters/LogFormatter.py +3 -1
- arelle/packages/report/ReportPackage.py +26 -13
- arelle/packages/report/ReportPackageConst.py +0 -1
- arelle/plugin/inlineXbrlDocumentSet.py +19 -5
- arelle/plugin/validate/DBA/DisclosureSystems.py +19 -1
- arelle/plugin/validate/DBA/PluginValidationDataExtension.py +2 -4
- arelle/plugin/validate/DBA/ValidationPluginExtension.py +2 -1
- arelle/plugin/validate/DBA/resources/config.xml +5 -0
- arelle/plugin/validate/DBA/rules/__init__.py +2 -2
- arelle/plugin/validate/DBA/rules/fr.py +19 -2
- arelle/plugin/validate/DBA/rules/tc.py +2 -0
- arelle/plugin/validate/DBA/rules/th.py +6 -0
- arelle/plugin/validate/DBA/rules/tm.py +18 -5
- arelle/plugin/validate/DBA/rules/tr.py +11 -5
- arelle/plugin/validate/EDINET/Constants.py +193 -9
- arelle/plugin/validate/EDINET/ContextRequirement.py +58 -0
- arelle/plugin/validate/EDINET/ControllerPluginData.py +220 -1
- arelle/plugin/validate/EDINET/CoverItemRequirements.py +42 -0
- arelle/plugin/validate/EDINET/DeiRequirements.py +118 -0
- arelle/plugin/validate/EDINET/FilingFormat.py +275 -0
- arelle/plugin/validate/EDINET/FormType.py +134 -0
- arelle/plugin/validate/EDINET/ManifestInstance.py +72 -5
- arelle/plugin/validate/EDINET/NamespaceConfig.py +50 -0
- arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +493 -132
- arelle/plugin/validate/EDINET/{InstanceType.py → ReportFolderType.py} +72 -15
- arelle/plugin/validate/EDINET/Statement.py +139 -0
- arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +595 -0
- arelle/plugin/validate/EDINET/UploadContents.py +48 -0
- arelle/plugin/validate/EDINET/ValidationPluginExtension.py +20 -2
- arelle/plugin/validate/EDINET/__init__.py +31 -6
- arelle/plugin/validate/EDINET/resources/config.xml +8 -1
- arelle/plugin/validate/EDINET/resources/cover-item-requirements.json +793 -0
- arelle/plugin/validate/EDINET/resources/dei-requirements.csv +27 -0
- arelle/plugin/validate/EDINET/resources/edinet-taxonomies.xml +2 -0
- arelle/plugin/validate/EDINET/rules/contexts.py +375 -14
- arelle/plugin/validate/EDINET/rules/edinet.py +1934 -45
- arelle/plugin/validate/EDINET/rules/frta.py +122 -3
- arelle/plugin/validate/EDINET/rules/gfm.py +1907 -11
- arelle/plugin/validate/EDINET/rules/upload.py +989 -141
- arelle/plugin/validate/ESEF/Const.py +3 -1
- arelle/plugin/validate/ESEF/ESEF_2021/DTS.py +5 -0
- arelle/plugin/validate/ESEF/ESEF_2021/Image.py +2 -2
- arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +23 -20
- arelle/plugin/validate/ESEF/ESEF_Current/DTS.py +47 -14
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +100 -25
- arelle/plugin/validate/ESEF/__init__.py +20 -6
- arelle/plugin/validate/ESEF/resources/authority-validations.json +76 -9
- arelle/plugin/validate/ESEF/resources/config.xml +20 -0
- arelle/plugin/validate/NL/DisclosureSystems.py +22 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +27 -9
- arelle/plugin/validate/NL/ValidationPluginExtension.py +51 -7
- arelle/plugin/validate/NL/resources/config.xml +18 -0
- arelle/plugin/validate/NL/rules/br_kvk.py +17 -61
- arelle/plugin/validate/NL/rules/fg_nl.py +7 -38
- arelle/plugin/validate/NL/rules/fr_kvk.py +7 -42
- arelle/plugin/validate/NL/rules/fr_nl.py +31 -147
- arelle/plugin/validate/NL/rules/nl_kvk.py +142 -28
- arelle/plugin/validate/ROS/PluginValidationDataExtension.py +2 -0
- arelle/plugin/validate/ROS/ValidationPluginExtension.py +4 -1
- arelle/plugin/validate/ROS/rules/ros.py +41 -9
- arelle/plugin/validate/UK/ValidateUK.py +130 -66
- arelle/plugin/validate/UK/__init__.py +89 -103
- arelle/utils/EntryPointDetection.py +79 -13
- arelle/utils/PluginHooks.py +125 -0
- arelle/utils/validate/ESEFImage.py +6 -6
- arelle/utils/validate/Validation.py +18 -0
- arelle/utils/validate/ValidationPlugin.py +76 -11
- arelle/utils/validate/ValidationUtil.py +35 -3
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/METADATA +30 -20
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/RECORD +115 -191
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/licenses/LICENSE.md +0 -3
- arelle/archive/CustomLogger.py +0 -43
- arelle/archive/LoadEFMvalidate.py +0 -32
- arelle/archive/LoadSavePreLbCsv.py +0 -26
- arelle/archive/LoadValidate.cs +0 -31
- arelle/archive/LoadValidate.py +0 -36
- arelle/archive/LoadValidateCmdLine.java +0 -69
- arelle/archive/LoadValidatePostedZip.java +0 -57
- arelle/archive/LoadValidateWebService.java +0 -34
- arelle/archive/SaveTableToExelle.py +0 -140
- arelle/archive/TR3toTR4.py +0 -88
- arelle/archive/plugin/ESEF_2022/__init__.py +0 -47
- arelle/archive/plugin/bigInstance.py +0 -394
- arelle/archive/plugin/cmdWebServerExtension.py +0 -43
- arelle/archive/plugin/crashTest.py +0 -38
- arelle/archive/plugin/functionsXmlCreation.py +0 -106
- arelle/archive/plugin/hello_i18n.pot +0 -26
- arelle/archive/plugin/hello_i18n.py +0 -32
- arelle/archive/plugin/importTestChild1.py +0 -21
- arelle/archive/plugin/importTestChild2.py +0 -22
- arelle/archive/plugin/importTestGrandchild1.py +0 -21
- arelle/archive/plugin/importTestGrandchild2.py +0 -21
- arelle/archive/plugin/importTestImported1.py +0 -23
- arelle/archive/plugin/importTestImported11.py +0 -22
- arelle/archive/plugin/importTestParent.py +0 -48
- arelle/archive/plugin/instanceInfo.py +0 -306
- arelle/archive/plugin/loadFromOIM-2018.py +0 -1282
- arelle/archive/plugin/locale/fr/LC_MESSAGES/hello_i18n.po +0 -25
- arelle/archive/plugin/objectmaker.py +0 -285
- arelle/archive/plugin/packagedImportTest/__init__.py +0 -47
- arelle/archive/plugin/packagedImportTest/importTestChild1.py +0 -21
- arelle/archive/plugin/packagedImportTest/importTestChild2.py +0 -22
- arelle/archive/plugin/packagedImportTest/importTestGrandchild1.py +0 -21
- arelle/archive/plugin/packagedImportTest/importTestGrandchild2.py +0 -21
- arelle/archive/plugin/packagedImportTest/importTestImported1.py +0 -24
- arelle/archive/plugin/packagedImportTest/importTestImported11.py +0 -21
- arelle/archive/plugin/packagedImportTest/subdir/importTestImported111.py +0 -21
- arelle/archive/plugin/packagedImportTest/subdir/subsubdir/importTestImported1111.py +0 -21
- arelle/archive/plugin/sakaCalendar.py +0 -215
- arelle/archive/plugin/saveInstanceInfoset.py +0 -121
- arelle/archive/plugin/sphinx/FormulaGenerator.py +0 -823
- arelle/archive/plugin/sphinx/SphinxContext.py +0 -404
- arelle/archive/plugin/sphinx/SphinxEvaluator.py +0 -783
- arelle/archive/plugin/sphinx/SphinxMethods.py +0 -1287
- arelle/archive/plugin/sphinx/SphinxParser.py +0 -1093
- arelle/archive/plugin/sphinx/SphinxValidator.py +0 -163
- arelle/archive/plugin/sphinx/US-GAAP Ratios Example.xsr +0 -52
- arelle/archive/plugin/sphinx/__init__.py +0 -285
- arelle/archive/plugin/streamingExtensions.py +0 -335
- arelle/archive/plugin/updateTableLB.py +0 -242
- arelle/archive/plugin/validate/SBRnl/CustomLoader.py +0 -19
- arelle/archive/plugin/validate/SBRnl/DTS.py +0 -305
- arelle/archive/plugin/validate/SBRnl/Dimensions.py +0 -357
- arelle/archive/plugin/validate/SBRnl/Document.py +0 -799
- arelle/archive/plugin/validate/SBRnl/Filing.py +0 -467
- arelle/archive/plugin/validate/SBRnl/__init__.py +0 -75
- arelle/archive/plugin/validate/SBRnl/config.xml +0 -26
- arelle/archive/plugin/validate/SBRnl/sbr-nl-taxonomies.xml +0 -754
- arelle/archive/plugin/validate/USBestPractices.py +0 -570
- arelle/archive/plugin/validate/USCorpAction.py +0 -557
- arelle/archive/plugin/validate/USSecTagging.py +0 -337
- arelle/archive/plugin/validate/XDC/__init__.py +0 -77
- arelle/archive/plugin/validate/XDC/config.xml +0 -20
- arelle/archive/plugin/validate/XFsyntax/__init__.py +0 -64
- arelle/archive/plugin/validate/XFsyntax/xf.py +0 -2227
- arelle/archive/plugin/validate/calc2.py +0 -536
- arelle/archive/plugin/validateSchemaLxml.py +0 -156
- arelle/archive/plugin/validateTableInfoset.py +0 -52
- arelle/archive/us-gaap-dei-docType-extraction-frm.xml +0 -90
- arelle/archive/us-gaap-dei-ratio-cash-frm.xml +0 -150
- arelle/examples/plugin/formulaSuiteConverter.py +0 -212
- arelle/examples/plugin/functionsCustom.py +0 -59
- arelle/examples/plugin/hello_dolly.py +0 -64
- arelle/examples/plugin/multi.py +0 -58
- arelle/examples/plugin/rssSaveOim.py +0 -96
- arelle/examples/plugin/validate/XYZ/DisclosureSystems.py +0 -2
- arelle/examples/plugin/validate/XYZ/PluginValidationDataExtension.py +0 -10
- arelle/examples/plugin/validate/XYZ/ValidationPluginExtension.py +0 -49
- arelle/examples/plugin/validate/XYZ/__init__.py +0 -75
- arelle/examples/plugin/validate/XYZ/resources/config.xml +0 -16
- arelle/examples/plugin/validate/XYZ/rules/__init__.py +0 -0
- arelle/examples/plugin/validate/XYZ/rules/rules01.py +0 -110
- arelle/examples/plugin/validate/XYZ/rules/rules02.py +0 -59
- arelle/model/CommentBase.py +0 -9
- arelle/model/ElementBase.py +0 -11
- arelle/model/PIBase.py +0 -10
- arelle/model/__init__.py +0 -15
- arelle/scripts-macOS/startWebServer.command +0 -3
- arelle/scripts-unix/startWebServer.sh +0 -1
- arelle/scripts-windows/startWebServer.bat +0 -5
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/top_level.txt +0 -0
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
See COPYRIGHT.md for copyright information.
|
|
3
|
-
'''
|
|
4
|
-
from collections import defaultdict
|
|
5
|
-
from arelle import XbrlConst
|
|
6
|
-
from arelle.ModelDtsObject import ModelConcept
|
|
7
|
-
import os
|
|
8
|
-
emptySet = set()
|
|
9
|
-
|
|
10
|
-
def checkFilingDimensions(val, drsELRs):
|
|
11
|
-
|
|
12
|
-
fromConceptELRs = defaultdict(set)
|
|
13
|
-
hypercubes = set()
|
|
14
|
-
hypercubesInLinkrole = defaultdict(set)
|
|
15
|
-
domainsInLinkrole = defaultdict(set)
|
|
16
|
-
for ELR in drsELRs:
|
|
17
|
-
domainMemberRelationshipSet = val.modelXbrl.relationshipSet( XbrlConst.domainMember, ELR)
|
|
18
|
-
|
|
19
|
-
# check Hypercubes in ELR, accumulate list of primary items
|
|
20
|
-
positiveAxisTableSources = defaultdict(set)
|
|
21
|
-
positiveHypercubes = set()
|
|
22
|
-
primaryItems = set()
|
|
23
|
-
for hasHypercubeArcrole in (XbrlConst.all, XbrlConst.notAll):
|
|
24
|
-
hasHypercubeRelationships = val.modelXbrl.relationshipSet(
|
|
25
|
-
hasHypercubeArcrole, ELR).fromModelObjects()
|
|
26
|
-
for hasHcRels in hasHypercubeRelationships.values():
|
|
27
|
-
for hasHcRel in hasHcRels:
|
|
28
|
-
sourceConcept = hasHcRel.fromModelObject
|
|
29
|
-
primaryItems.add(sourceConcept)
|
|
30
|
-
hc = hasHcRel.toModelObject
|
|
31
|
-
hypercubes.add(hc)
|
|
32
|
-
if hasHypercubeArcrole == XbrlConst.all:
|
|
33
|
-
positiveHypercubes.add(hc)
|
|
34
|
-
if not hasHcRel.isClosed:
|
|
35
|
-
val.modelXbrl.error("SBR.NL.2.3.6.04",
|
|
36
|
-
_("All hypercube %(hypercube)s in DRS role %(linkrole)s, does not have closed='true'"),
|
|
37
|
-
modelObject=hasHcRel, hypercube=hc.qname, linkrole=ELR)
|
|
38
|
-
dimELR = hasHcRel.targetRole
|
|
39
|
-
if not dimELR:
|
|
40
|
-
dimELR = ELR
|
|
41
|
-
hypercubesInLinkrole[dimELR].add(hc) # this is the elr containing the HC-dim relations
|
|
42
|
-
hcDimRels = val.modelXbrl.relationshipSet(
|
|
43
|
-
XbrlConst.hypercubeDimension, dimELR).fromModelObject(hc)
|
|
44
|
-
for hcDimRel in hcDimRels:
|
|
45
|
-
dim = hcDimRel.toModelObject
|
|
46
|
-
if isinstance(dim, ModelConcept):
|
|
47
|
-
domELR = hcDimRel.targetRole
|
|
48
|
-
if not domELR:
|
|
49
|
-
if dim.isExplicitDimension:
|
|
50
|
-
domELR = dimELR
|
|
51
|
-
val.modelXbrl.error("SBR.NL.2.3.5.04",
|
|
52
|
-
_("Hypercube %(hypercube)s in DRS role %(linkrole)s, missing targetrole to dimension %(dimension)s consecutive relationship"),
|
|
53
|
-
modelObject=hcDimRel, hypercube=hc.qname, linkrole=ELR, dimension=dim.qname)
|
|
54
|
-
else:
|
|
55
|
-
if dim.isTypedDimension:
|
|
56
|
-
val.modelXbrl.error("SBR.NL.2.3.5.07",
|
|
57
|
-
_("Typed dimension %(dimension)s in DRS role %(linkrole)s, has targetrole consecutive relationship"),
|
|
58
|
-
modelObject=hcDimRel, dimension=dim.qname, linkrole=ELR)
|
|
59
|
-
if hasHypercubeArcrole == XbrlConst.all:
|
|
60
|
-
positiveAxisTableSources[dim].add(sourceConcept)
|
|
61
|
-
dimDomRels = val.modelXbrl.relationshipSet(
|
|
62
|
-
XbrlConst.dimensionDomain, domELR).fromModelObject(dim)
|
|
63
|
-
checkSBRNLMembers(val, hc, dim, domELR, dimDomRels, ELR, True)
|
|
64
|
-
for dimDomRel in dimDomRels:
|
|
65
|
-
dom = dimDomRel.toModelObject
|
|
66
|
-
if isinstance(dom, ModelConcept):
|
|
67
|
-
domainsInLinkrole[domELR].add(dom) # this is the elr containing the HC-dim relations
|
|
68
|
-
|
|
69
|
-
# check for primary item dimension-member graph undirected cycles
|
|
70
|
-
fromRelationships = domainMemberRelationshipSet.fromModelObjects()
|
|
71
|
-
for relFrom, rels in fromRelationships.items():
|
|
72
|
-
if relFrom in primaryItems:
|
|
73
|
-
drsRelsFrom = defaultdict(list)
|
|
74
|
-
drsRelsTo = defaultdict(list)
|
|
75
|
-
getDrsRels(val, ELR, rels, ELR, drsRelsFrom, drsRelsTo)
|
|
76
|
-
fromConceptELRs[relFrom].add(ELR)
|
|
77
|
-
cycleCausingConcept = undirectedFwdCycle(val, ELR, rels, ELR, drsRelsFrom, drsRelsTo, fromConceptELRs)
|
|
78
|
-
fromConceptELRs.clear()
|
|
79
|
-
for rel in rels:
|
|
80
|
-
fromMbr = rel.fromModelObject
|
|
81
|
-
toMbr = rel.toModelObject
|
|
82
|
-
toELR = rel.targetRole
|
|
83
|
-
|
|
84
|
-
# check hypercubes for unique set of members
|
|
85
|
-
for hc in hypercubes:
|
|
86
|
-
for priHcRel in val.modelXbrl.relationshipSet(XbrlConst.all).toModelObject(hc):
|
|
87
|
-
priItem = priHcRel.fromModelObject
|
|
88
|
-
ELR = priHcRel.linkrole
|
|
89
|
-
checkSBRNLMembers(val, hc, priItem, ELR,
|
|
90
|
-
val.modelXbrl.relationshipSet(XbrlConst.domainMember, ELR).fromModelObject(priItem),
|
|
91
|
-
ELR, False)
|
|
92
|
-
if priHcRel.contextElement == 'segment':
|
|
93
|
-
val.modelXbrl.error("SBR.NL.2.3.5.06",
|
|
94
|
-
_("hypercube %(hypercube)s in segment not allowed, ELR role %(linkrole)s"),
|
|
95
|
-
modelObject=priHcRel, linkrole=ELR, hypercube=hc.qname)
|
|
96
|
-
for notAllRel in val.modelXbrl.relationshipSet(XbrlConst.notAll).modelRelationships:
|
|
97
|
-
val.modelXbrl.error("SBR.NL.2.3.5.05",
|
|
98
|
-
_("Notall from primary item %(primaryItem)s in ELR role %(linkrole)s to %(hypercube)s"),
|
|
99
|
-
modelObject=val.modelXbrl, primaryItem=notAllRel.fromModelObject.qname, linkrole=notAllRel.linkrole, hypercube=notAllRel.toModelObject.qname)
|
|
100
|
-
for ELR, hypercubes in hypercubesInLinkrole.items():
|
|
101
|
-
'''removed RH 2011-12-06
|
|
102
|
-
for modelRel in val.modelXbrl.relationshipSet("XBRL-dimensions", ELR).modelRelationships:
|
|
103
|
-
if modelRel.fromModelObject != hc:
|
|
104
|
-
val.modelXbrl.error("SBR.NL.2.3.5.03",
|
|
105
|
-
_("ELR role %(linkrole)s, is not dedicated to %(hypercube)s, but also has %(otherQname)s"),
|
|
106
|
-
modelObject=val.modelXbrl, linkrole=ELR, hypercube=hc.qname, otherQname=modelRel.fromModelObject.qname)
|
|
107
|
-
'''
|
|
108
|
-
domains = domainsInLinkrole.get(ELR, emptySet)
|
|
109
|
-
for hc in hypercubes: # only one member
|
|
110
|
-
for arcrole in (XbrlConst.parentChild, "XBRL-dimensions"):
|
|
111
|
-
for modelRel in val.modelXbrl.relationshipSet(arcrole, ELR).modelRelationships:
|
|
112
|
-
if (modelRel.fromModelObject != hc and modelRel.toModelObject != hc and
|
|
113
|
-
modelRel.fromModelObject not in domains and modelRel.toModelObject not in domains):
|
|
114
|
-
val.modelXbrl.error("SBR.NL.2.2.3.05",
|
|
115
|
-
_("ELR role %(linkrole)s, has hypercube %(hypercube)s and a %(arcrole)s relationship not involving the hypercube or primary domain, from %(fromConcept)s to %(toConcept)s"),
|
|
116
|
-
modelObject=modelRel, linkrole=ELR, hypercube=hc.qname, arcrole=os.path.basename(modelRel.arcrole),
|
|
117
|
-
fromConcept=modelRel.fromModelObject.qname,
|
|
118
|
-
toConcept=(modelRel.toModelObject.qname if isinstance(modelRel.toModelObject, ModelConcept) else "unknown"))
|
|
119
|
-
domainsInLinkrole = defaultdict(set)
|
|
120
|
-
dimDomMemsByLinkrole = defaultdict(set)
|
|
121
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.dimensionDomain).modelRelationships:
|
|
122
|
-
relFrom = rel.fromModelObject
|
|
123
|
-
relTo = rel.toModelObject
|
|
124
|
-
if isinstance(relFrom, ModelConcept) and isinstance(relTo, ModelConcept):
|
|
125
|
-
domainsInLinkrole[rel.targetRole].add(relFrom)
|
|
126
|
-
domMems = set() # determine usable dom and mems of dimension in this linkrole
|
|
127
|
-
if rel.isUsable:
|
|
128
|
-
domMems.add(relTo)
|
|
129
|
-
for relMem in val.modelXbrl.relationshipSet(XbrlConst.domainMember, (rel.targetRole or rel.linkrole)).fromModelObject(relTo):
|
|
130
|
-
if relMem.isUsable:
|
|
131
|
-
domMems.add(relMem.toModelObject)
|
|
132
|
-
dimDomMemsByLinkrole[(rel.linkrole,relFrom)].update(domMems)
|
|
133
|
-
if rel.isUsable and val.modelXbrl.relationshipSet(XbrlConst.domainMember, rel.targetRole).fromModelObject(relTo):
|
|
134
|
-
val.modelXbrl.error("SBR.NL.2.3.7.05",
|
|
135
|
-
_("Dimension %(dimension)s in DRS role %(linkrole)s, has usable domain with members %(domain)s"),
|
|
136
|
-
modelObject=rel, dimension=relFrom.qname, linkrole=rel.linkrole, domain=relTo.qname)
|
|
137
|
-
if not relTo.isAbstract:
|
|
138
|
-
val.modelXbrl.error("SBR.NL.2.3.7.02",
|
|
139
|
-
_("Dimension %(dimension)s in DRS role %(linkrole)s, has nonAbsract domain %(domain)s"),
|
|
140
|
-
modelObject=rel, dimension=relFrom.qname, linkrole=rel.linkrole, domain=relTo.qname)
|
|
141
|
-
if relTo.substitutionGroupQname.localName not in ("domainItem","domainMemberItem"):
|
|
142
|
-
val.modelXbrl.error("SBR.NL.2.2.2.19",
|
|
143
|
-
_("Domain item %(domain)s in DRS role %(linkrole)s, in dimension %(dimension)s is not a domainItem"),
|
|
144
|
-
modelObject=rel, domain=relTo.qname, linkrole=rel.linkrole, dimension=relFrom.qname)
|
|
145
|
-
if not rel.targetRole and relTo.substitutionGroupQname.localName == "domainItem":
|
|
146
|
-
val.modelXbrl.error("SBR.NL.2.3.6.03",
|
|
147
|
-
_("Dimension %(dimension)s in DRS role %(linkrole)s, missing targetrole to consecutive domain relationship"),
|
|
148
|
-
modelObject=rel, dimension=relFrom.qname, linkrole=rel.linkrole)
|
|
149
|
-
for linkrole, domains in domainsInLinkrole.items():
|
|
150
|
-
if linkrole and len(domains) > 1:
|
|
151
|
-
val.modelXbrl.error("SBR.NL.2.3.7.04",
|
|
152
|
-
_("Linkrole %(linkrole)s, has multiple domains %(domains)s"),
|
|
153
|
-
modelObject=val.modelXbrl, linkrole=linkrole, domains=", ".join([str(dom.qname) for dom in domains]))
|
|
154
|
-
del domainsInLinkrole # dereference
|
|
155
|
-
linkrolesByDimDomMems = defaultdict(set)
|
|
156
|
-
for linkroleDim, domMems in dimDomMemsByLinkrole.items():
|
|
157
|
-
linkrole, dim = linkroleDim
|
|
158
|
-
linkrolesByDimDomMems[(dim,tuple(domMems))].add(linkrole)
|
|
159
|
-
for dimDomMems, linkroles in linkrolesByDimDomMems.items():
|
|
160
|
-
if len(linkroles) > 1:
|
|
161
|
-
val.modelXbrl.error("SBR.NL.2.3.6.02",
|
|
162
|
-
_("Dimension %(dimension)s usable members same in linkroles %(linkroles)s"),
|
|
163
|
-
modelObject=val.modelXbrl, dimension=dimDomMems[0].qname, linkroles=', '.join(l for l in linkroles))
|
|
164
|
-
del dimDomMemsByLinkrole, linkrolesByDimDomMems
|
|
165
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.domainMember).modelRelationships:
|
|
166
|
-
if val.modelXbrl.relationshipSet(XbrlConst.domainMember, rel.targetRole).fromModelObject(rel.toModelObject):
|
|
167
|
-
val.modelXbrl.error("SBR.NL.2.3.7.03",
|
|
168
|
-
_("Domain member %(member)s in DRS role %(linkrole)s, has nested members"),
|
|
169
|
-
modelObject=rel, member=(rel.toModelObject.qname if isinstance(rel.toModelObject, ModelConcept) else None), linkrole=rel.linkrole)
|
|
170
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.domainMember).modelRelationships:
|
|
171
|
-
relFrom = rel.fromModelObject
|
|
172
|
-
relTo = rel.toModelObject
|
|
173
|
-
if isinstance(relTo, ModelConcept):
|
|
174
|
-
# avoid primary item relationships in these tests
|
|
175
|
-
if relFrom.substitutionGroupQname.localName == "domainItem":
|
|
176
|
-
if relTo.substitutionGroupQname.localName != "domainMemberItem":
|
|
177
|
-
val.modelXbrl.error("SBR.NL.2.2.2.19",
|
|
178
|
-
_("Domain member item %(member)s in DRS role %(linkrole)s is not a domainMemberItem"),
|
|
179
|
-
modelObject=rel, member=relTo.qname, linkrole=rel.linkrole)
|
|
180
|
-
else:
|
|
181
|
-
if relTo.substitutionGroupQname.localName == "domainMemberItem":
|
|
182
|
-
val.modelXbrl.error("SBR.NL.2.2.2.19",
|
|
183
|
-
_("Domain item %(domain)s in DRS role %(linkrole)s is not a domainItem"),
|
|
184
|
-
modelObject=rel, domain=relFrom.qname, linkrole=rel.linkrole)
|
|
185
|
-
break # don't repeat parent's error on rest of child members
|
|
186
|
-
elif relFrom.isAbstract and relFrom.substitutionGroupQname.localName != "primaryDomainItem":
|
|
187
|
-
val.modelXbrl.error("SBR.NL.2.2.2.19",
|
|
188
|
-
_("Abstract domain item %(domain)s in DRS role %(linkrole)s is not a primaryDomainItem"),
|
|
189
|
-
modelObject=rel, domain=relFrom.qname, linkrole=rel.linkrole)
|
|
190
|
-
break # don't repeat parent's error on rest of child members
|
|
191
|
-
hypercubeDRSDimensions = defaultdict(dict)
|
|
192
|
-
for hcDimRel in val.modelXbrl.relationshipSet(XbrlConst.hypercubeDimension).modelRelationships:
|
|
193
|
-
hc = hcDimRel.fromModelObject
|
|
194
|
-
if isinstance(hc, ModelConcept):
|
|
195
|
-
ELR = hcDimRel.linkrole
|
|
196
|
-
try:
|
|
197
|
-
hcDRSdims = hypercubeDRSDimensions[hc][ELR]
|
|
198
|
-
except KeyError:
|
|
199
|
-
hcDRSdims = set()
|
|
200
|
-
hypercubeDRSDimensions[hc][ELR] = hcDRSdims
|
|
201
|
-
hcDRSdims.add(hcDimRel.toModelObject)
|
|
202
|
-
for hc, DRSdims in hypercubeDRSDimensions.items():
|
|
203
|
-
hcELRdimSets = {}
|
|
204
|
-
for ELR, mutableDims in DRSdims.items():
|
|
205
|
-
dims = frozenset(mutableDims)
|
|
206
|
-
if dims not in hcELRdimSets:
|
|
207
|
-
hcELRdimSets[dims] = ELR
|
|
208
|
-
else:
|
|
209
|
-
val.modelXbrl.error("SBR.NL.2.3.5.02",
|
|
210
|
-
_("Hypercube %(hypercube)s has same dimensions in ELR roles %(linkrole)s and %(linkrole2)s: %(dimensions)s"),
|
|
211
|
-
modelObject=hc, hypercube=hc.qname, linkrole=ELR, linkrole2=hcELRdimSets[dims],
|
|
212
|
-
dimensions=", ".join([str(dim.qname) for dim in dims]))
|
|
213
|
-
del hypercubeDRSDimensions # dereference
|
|
214
|
-
|
|
215
|
-
def getDrsRels(val, fromELR, rels, drsELR, drsRelsFrom, drsRelsTo, fromConcepts=None):
|
|
216
|
-
if not fromConcepts: fromConcepts = set()
|
|
217
|
-
for rel in rels:
|
|
218
|
-
relTo = rel.toModelObject
|
|
219
|
-
if isinstance(relTo, ModelConcept):
|
|
220
|
-
drsRelsFrom[rel.fromModelObject].append(rel)
|
|
221
|
-
drsRelsTo[relTo].append(rel)
|
|
222
|
-
toELR = rel.targetRole
|
|
223
|
-
if not toELR: toELR = fromELR
|
|
224
|
-
if relTo not in fromConcepts:
|
|
225
|
-
fromConcepts.add(relTo)
|
|
226
|
-
domMbrRels = val.modelXbrl.relationshipSet(
|
|
227
|
-
XbrlConst.domainMember, toELR).fromModelObject(relTo)
|
|
228
|
-
getDrsRels(val, toELR, domMbrRels, drsELR, drsRelsFrom, drsRelsTo, fromConcepts)
|
|
229
|
-
fromConcepts.discard(relTo)
|
|
230
|
-
return False
|
|
231
|
-
|
|
232
|
-
def undirectedFwdCycle(val, fromELR, rels, drsELR, drsRelsFrom, drsRelsTo, fromConceptELRs, ELRsVisited=None):
|
|
233
|
-
if not ELRsVisited: ELRsVisited = set()
|
|
234
|
-
ELRsVisited.add(fromELR)
|
|
235
|
-
for rel in rels:
|
|
236
|
-
if rel.linkrole == fromELR:
|
|
237
|
-
relTo = rel.toModelObject
|
|
238
|
-
if isinstance(relTo, ModelConcept):
|
|
239
|
-
toELR = rel.targetRole
|
|
240
|
-
if not toELR:
|
|
241
|
-
toELR = fromELR
|
|
242
|
-
if relTo in fromConceptELRs and toELR in fromConceptELRs[relTo]: #forms a directed cycle
|
|
243
|
-
return [rel,True]
|
|
244
|
-
fromConceptELRs[relTo].add(toELR)
|
|
245
|
-
if drsRelsFrom:
|
|
246
|
-
domMbrRels = drsRelsFrom[relTo]
|
|
247
|
-
else:
|
|
248
|
-
domMbrRels = val.modelXbrl.relationshipSet(
|
|
249
|
-
XbrlConst.domainMember, toELR).fromModelObject(relTo)
|
|
250
|
-
cycleCausingConcept = undirectedFwdCycle(val, toELR, domMbrRels, drsELR, drsRelsFrom, drsRelsTo, fromConceptELRs, ELRsVisited)
|
|
251
|
-
if cycleCausingConcept is not None:
|
|
252
|
-
cycleCausingConcept.append(rel)
|
|
253
|
-
cycleCausingConcept.append(True)
|
|
254
|
-
return cycleCausingConcept
|
|
255
|
-
fromConceptELRs[relTo].discard(toELR)
|
|
256
|
-
# look for back path in any of the ELRs visited (pass None as ELR)
|
|
257
|
-
cycleCausingConcept = undirectedRevCycle(val, None, relTo, rel, drsELR, drsRelsFrom, drsRelsTo, fromConceptELRs, ELRsVisited)
|
|
258
|
-
if cycleCausingConcept is not None:
|
|
259
|
-
cycleCausingConcept.append(rel)
|
|
260
|
-
cycleCausingConcept.append(True)
|
|
261
|
-
return cycleCausingConcept
|
|
262
|
-
return None
|
|
263
|
-
|
|
264
|
-
def undirectedRevCycle(val, fromELR, mbrConcept, turnbackRel, drsELR, drsRelsFrom, drsRelsTo, fromConceptELRs, ELRsVisited):
|
|
265
|
-
for arcrole in (XbrlConst.domainMember, XbrlConst.dimensionDomain):
|
|
266
|
-
'''
|
|
267
|
-
for ELR in ELRsVisited if (not fromELR) else (fromELR,):
|
|
268
|
-
for rel in val.modelXbrl.relationshipSet(arcrole, ELR).toModelObject(mbrConcept):
|
|
269
|
-
if not rel.isIdenticalTo(turnbackRel):
|
|
270
|
-
relFrom = rel.fromModelObject
|
|
271
|
-
relELR = rel.linkrole
|
|
272
|
-
if relFrom in fromConcepts and relELR == drsELR:
|
|
273
|
-
return True
|
|
274
|
-
if undirectedRevCycle(val, relELR, relFrom, turnbackRel, drsELR, fromConcepts, ELRsVisited):
|
|
275
|
-
return True
|
|
276
|
-
'''
|
|
277
|
-
if drsRelsTo:
|
|
278
|
-
mbrDomRels = drsRelsTo[mbrConcept]
|
|
279
|
-
else:
|
|
280
|
-
mbrDomRels = val.modelXbrl.relationshipSet(arcrole, None).toModelObject(mbrConcept)
|
|
281
|
-
for rel in mbrDomRels:
|
|
282
|
-
if not rel.isIdenticalTo(turnbackRel):
|
|
283
|
-
relFrom = rel.fromModelObject
|
|
284
|
-
relELR = rel.linkrole
|
|
285
|
-
if relFrom in fromConceptELRs and relELR in fromConceptELRs[relFrom]:
|
|
286
|
-
return [rel, False] # turnbackRel.toModelObject
|
|
287
|
-
cycleCausingConcept = undirectedRevCycle(val, relELR, relFrom, turnbackRel, drsELR, drsRelsFrom, drsRelsTo, fromConceptELRs, ELRsVisited)
|
|
288
|
-
if cycleCausingConcept is not None:
|
|
289
|
-
cycleCausingConcept.append(rel)
|
|
290
|
-
cycleCausingConcept.append(False)
|
|
291
|
-
return cycleCausingConcept
|
|
292
|
-
return None
|
|
293
|
-
|
|
294
|
-
def cyclePath(source, cycles):
|
|
295
|
-
isForward = True
|
|
296
|
-
path = []
|
|
297
|
-
for rel in reversed(cycles):
|
|
298
|
-
if isinstance(rel,bool):
|
|
299
|
-
isForward = rel
|
|
300
|
-
else:
|
|
301
|
-
path.append("{0}:{1} {2}".format(rel.modelDocument.basename,
|
|
302
|
-
rel.sourceline,
|
|
303
|
-
rel.toModelObject.qname if isForward else rel.fromModelObject.qname))
|
|
304
|
-
return str(source.qname) + " " + " - ".join(path)
|
|
305
|
-
|
|
306
|
-
def commonAncestor(domainMemberRelationshipSet,
|
|
307
|
-
negSourceConcept, posSourceConcepts):
|
|
308
|
-
negAncestors = ancestorOrSelf(domainMemberRelationshipSet,negSourceConcept)
|
|
309
|
-
for posSourceConcept in posSourceConcepts:
|
|
310
|
-
if len(negAncestors & ancestorOrSelf(domainMemberRelationshipSet,posSourceConcept)):
|
|
311
|
-
return True
|
|
312
|
-
return False
|
|
313
|
-
|
|
314
|
-
def ancestorOrSelf(domainMemberRelationshipSet,sourceConcept,result=None):
|
|
315
|
-
if not result:
|
|
316
|
-
result = set()
|
|
317
|
-
if not sourceConcept in result:
|
|
318
|
-
result.add(sourceConcept)
|
|
319
|
-
for rels in domainMemberRelationshipSet.toModelObject(sourceConcept):
|
|
320
|
-
ancestorOrSelf(domainMemberRelationshipSet, rels.fromModelObject, result)
|
|
321
|
-
return result
|
|
322
|
-
|
|
323
|
-
def checkSBRNLMembers(val, hc, dim, domELR, rels, ELR, isDomMbr, members=None, ancestors=None):
|
|
324
|
-
if members is None: members = set()
|
|
325
|
-
if ancestors is None: ancestors = set()
|
|
326
|
-
for rel in rels:
|
|
327
|
-
relFrom = rel.fromModelObject
|
|
328
|
-
relTo = rel.toModelObject
|
|
329
|
-
if isinstance(relFrom, ModelConcept) and isinstance(relTo, ModelConcept):
|
|
330
|
-
toELR = (rel.targetRole or rel.linkrole)
|
|
331
|
-
|
|
332
|
-
if isDomMbr or not relTo.isAbstract:
|
|
333
|
-
if relTo in members:
|
|
334
|
-
val.modelXbrl.relationshipSet(XbrlConst.all).toModelObject(hc)
|
|
335
|
-
if isDomMbr:
|
|
336
|
-
pass # removed by RH, now checking dom/mem usable set in entirety for 2.3.6.02 above
|
|
337
|
-
#val.modelXbrl.error("SBR.NL.2.3.6.02",
|
|
338
|
-
# _("Dimension %(dimension)s in DRS role %(linkrole)s for hypercube %(hypercube)s, non-unique member %(concept)s"),
|
|
339
|
-
# modelObject=relTo, dimension=dim.qname, linkrole=ELR, hypercube=hc.qname, concept=relTo.qname)
|
|
340
|
-
else:
|
|
341
|
-
val.modelXbrl.error("SBR.NL.2.3.5.01",
|
|
342
|
-
_("Primary items for hypercube %(hypercube)s ELR %(ELR)s, have non-unique (inheritance) member %(concept)s in DRS role %(linkrole)s"),
|
|
343
|
-
modelObject=relTo, hypercube=hc.qname, ELR=domELR, concept=relTo.qname, linkrole=ELR)
|
|
344
|
-
members.add(relTo)
|
|
345
|
-
if not isDomMbr: # pri item relationships
|
|
346
|
-
if (relTo.isAbstract and not relFrom.isAbstract or
|
|
347
|
-
relFrom.substitutionGroupQname.localName != "primaryDomainItem"):
|
|
348
|
-
val.modelXbrl.error("SBR.NL.2.3.7.01",
|
|
349
|
-
_("Primary item %(concept)s in DRS role %(linkrole)s for hypercube %(hypercube)s, has parent %(concept2)s which is not a primaryDomainItem"),
|
|
350
|
-
modelObject=rel, concept=relTo.qname, linkrole=ELR, hypercube=hc.qname, concept2=relFrom.qname)
|
|
351
|
-
if relTo not in ancestors:
|
|
352
|
-
ancestors.add(relTo)
|
|
353
|
-
domMbrRels = val.modelXbrl.relationshipSet(
|
|
354
|
-
XbrlConst.domainMember, toELR).fromModelObject(relTo)
|
|
355
|
-
checkSBRNLMembers(val, hc, dim, domELR, domMbrRels, ELR, isDomMbr, members, ancestors)
|
|
356
|
-
ancestors.discard(relTo)
|
|
357
|
-
return False
|