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.
Files changed (204) hide show
  1. arelle/BetaFeatures.py +0 -21
  2. arelle/Cntlr.py +15 -8
  3. arelle/CntlrCmdLine.py +121 -56
  4. arelle/CntlrWinMain.py +143 -70
  5. arelle/DialogFind.py +1 -1
  6. arelle/DialogPluginManager.py +6 -4
  7. arelle/DisclosureSystem.py +7 -0
  8. arelle/ErrorManager.py +21 -6
  9. arelle/FileSource.py +11 -4
  10. arelle/FunctionIxt.py +16 -11
  11. arelle/HtmlUtil.py +5 -4
  12. arelle/LeiUtil.py +63 -43
  13. arelle/ModelDocument.py +20 -15
  14. arelle/ModelDtsObject.py +8 -0
  15. arelle/ModelInstanceObject.py +1 -1
  16. arelle/ModelObject.py +16 -18
  17. arelle/ModelObjectFactory.py +35 -17
  18. arelle/ModelXbrl.py +28 -11
  19. arelle/PluginManager.py +130 -105
  20. arelle/RuntimeOptions.py +1 -0
  21. arelle/UrlUtil.py +14 -0
  22. arelle/Validate.py +17 -12
  23. arelle/ValidateDuplicateFacts.py +3 -1
  24. arelle/ValidateFileSource.py +38 -0
  25. arelle/ValidateFilingText.py +3 -3
  26. arelle/ValidateXbrl.py +5 -2
  27. arelle/ValidateXbrlCalcs.py +210 -186
  28. arelle/ValidateXbrlDTS.py +1 -1
  29. arelle/ViewFile.py +1 -0
  30. arelle/ViewFileFactTable.py +2 -2
  31. arelle/ViewWinDTS.py +4 -1
  32. arelle/WebCache.py +28 -24
  33. arelle/XbrlConst.py +22 -0
  34. arelle/XmlUtil.py +16 -21
  35. arelle/XmlValidate.py +6 -9
  36. arelle/_version.py +16 -3
  37. arelle/api/Session.py +11 -2
  38. arelle/config/disclosuresystems.xsd +2 -0
  39. arelle/config/rosettaEntitlements.plist +8 -0
  40. arelle/conformance/CSVTestcaseLoader.py +1 -1
  41. arelle/formula/XPathContext.py +3 -3
  42. arelle/logging/formatters/LogFormatter.py +3 -1
  43. arelle/packages/report/ReportPackage.py +26 -13
  44. arelle/packages/report/ReportPackageConst.py +0 -1
  45. arelle/plugin/inlineXbrlDocumentSet.py +19 -5
  46. arelle/plugin/validate/DBA/DisclosureSystems.py +19 -1
  47. arelle/plugin/validate/DBA/PluginValidationDataExtension.py +2 -4
  48. arelle/plugin/validate/DBA/ValidationPluginExtension.py +2 -1
  49. arelle/plugin/validate/DBA/resources/config.xml +5 -0
  50. arelle/plugin/validate/DBA/rules/__init__.py +2 -2
  51. arelle/plugin/validate/DBA/rules/fr.py +19 -2
  52. arelle/plugin/validate/DBA/rules/tc.py +2 -0
  53. arelle/plugin/validate/DBA/rules/th.py +6 -0
  54. arelle/plugin/validate/DBA/rules/tm.py +18 -5
  55. arelle/plugin/validate/DBA/rules/tr.py +11 -5
  56. arelle/plugin/validate/EDINET/Constants.py +193 -9
  57. arelle/plugin/validate/EDINET/ContextRequirement.py +58 -0
  58. arelle/plugin/validate/EDINET/ControllerPluginData.py +220 -1
  59. arelle/plugin/validate/EDINET/CoverItemRequirements.py +42 -0
  60. arelle/plugin/validate/EDINET/DeiRequirements.py +118 -0
  61. arelle/plugin/validate/EDINET/FilingFormat.py +275 -0
  62. arelle/plugin/validate/EDINET/FormType.py +134 -0
  63. arelle/plugin/validate/EDINET/ManifestInstance.py +72 -5
  64. arelle/plugin/validate/EDINET/NamespaceConfig.py +50 -0
  65. arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +493 -132
  66. arelle/plugin/validate/EDINET/{InstanceType.py → ReportFolderType.py} +72 -15
  67. arelle/plugin/validate/EDINET/Statement.py +139 -0
  68. arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +595 -0
  69. arelle/plugin/validate/EDINET/UploadContents.py +48 -0
  70. arelle/plugin/validate/EDINET/ValidationPluginExtension.py +20 -2
  71. arelle/plugin/validate/EDINET/__init__.py +31 -6
  72. arelle/plugin/validate/EDINET/resources/config.xml +8 -1
  73. arelle/plugin/validate/EDINET/resources/cover-item-requirements.json +793 -0
  74. arelle/plugin/validate/EDINET/resources/dei-requirements.csv +27 -0
  75. arelle/plugin/validate/EDINET/resources/edinet-taxonomies.xml +2 -0
  76. arelle/plugin/validate/EDINET/rules/contexts.py +375 -14
  77. arelle/plugin/validate/EDINET/rules/edinet.py +1934 -45
  78. arelle/plugin/validate/EDINET/rules/frta.py +122 -3
  79. arelle/plugin/validate/EDINET/rules/gfm.py +1907 -11
  80. arelle/plugin/validate/EDINET/rules/upload.py +989 -141
  81. arelle/plugin/validate/ESEF/Const.py +3 -1
  82. arelle/plugin/validate/ESEF/ESEF_2021/DTS.py +5 -0
  83. arelle/plugin/validate/ESEF/ESEF_2021/Image.py +2 -2
  84. arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +23 -20
  85. arelle/plugin/validate/ESEF/ESEF_Current/DTS.py +47 -14
  86. arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +100 -25
  87. arelle/plugin/validate/ESEF/__init__.py +20 -6
  88. arelle/plugin/validate/ESEF/resources/authority-validations.json +76 -9
  89. arelle/plugin/validate/ESEF/resources/config.xml +20 -0
  90. arelle/plugin/validate/NL/DisclosureSystems.py +22 -0
  91. arelle/plugin/validate/NL/PluginValidationDataExtension.py +27 -9
  92. arelle/plugin/validate/NL/ValidationPluginExtension.py +51 -7
  93. arelle/plugin/validate/NL/resources/config.xml +18 -0
  94. arelle/plugin/validate/NL/rules/br_kvk.py +17 -61
  95. arelle/plugin/validate/NL/rules/fg_nl.py +7 -38
  96. arelle/plugin/validate/NL/rules/fr_kvk.py +7 -42
  97. arelle/plugin/validate/NL/rules/fr_nl.py +31 -147
  98. arelle/plugin/validate/NL/rules/nl_kvk.py +142 -28
  99. arelle/plugin/validate/ROS/PluginValidationDataExtension.py +2 -0
  100. arelle/plugin/validate/ROS/ValidationPluginExtension.py +4 -1
  101. arelle/plugin/validate/ROS/rules/ros.py +41 -9
  102. arelle/plugin/validate/UK/ValidateUK.py +130 -66
  103. arelle/plugin/validate/UK/__init__.py +89 -103
  104. arelle/utils/EntryPointDetection.py +79 -13
  105. arelle/utils/PluginHooks.py +125 -0
  106. arelle/utils/validate/ESEFImage.py +6 -6
  107. arelle/utils/validate/Validation.py +18 -0
  108. arelle/utils/validate/ValidationPlugin.py +76 -11
  109. arelle/utils/validate/ValidationUtil.py +35 -3
  110. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/METADATA +30 -20
  111. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/RECORD +115 -191
  112. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/licenses/LICENSE.md +0 -3
  113. arelle/archive/CustomLogger.py +0 -43
  114. arelle/archive/LoadEFMvalidate.py +0 -32
  115. arelle/archive/LoadSavePreLbCsv.py +0 -26
  116. arelle/archive/LoadValidate.cs +0 -31
  117. arelle/archive/LoadValidate.py +0 -36
  118. arelle/archive/LoadValidateCmdLine.java +0 -69
  119. arelle/archive/LoadValidatePostedZip.java +0 -57
  120. arelle/archive/LoadValidateWebService.java +0 -34
  121. arelle/archive/SaveTableToExelle.py +0 -140
  122. arelle/archive/TR3toTR4.py +0 -88
  123. arelle/archive/plugin/ESEF_2022/__init__.py +0 -47
  124. arelle/archive/plugin/bigInstance.py +0 -394
  125. arelle/archive/plugin/cmdWebServerExtension.py +0 -43
  126. arelle/archive/plugin/crashTest.py +0 -38
  127. arelle/archive/plugin/functionsXmlCreation.py +0 -106
  128. arelle/archive/plugin/hello_i18n.pot +0 -26
  129. arelle/archive/plugin/hello_i18n.py +0 -32
  130. arelle/archive/plugin/importTestChild1.py +0 -21
  131. arelle/archive/plugin/importTestChild2.py +0 -22
  132. arelle/archive/plugin/importTestGrandchild1.py +0 -21
  133. arelle/archive/plugin/importTestGrandchild2.py +0 -21
  134. arelle/archive/plugin/importTestImported1.py +0 -23
  135. arelle/archive/plugin/importTestImported11.py +0 -22
  136. arelle/archive/plugin/importTestParent.py +0 -48
  137. arelle/archive/plugin/instanceInfo.py +0 -306
  138. arelle/archive/plugin/loadFromOIM-2018.py +0 -1282
  139. arelle/archive/plugin/locale/fr/LC_MESSAGES/hello_i18n.po +0 -25
  140. arelle/archive/plugin/objectmaker.py +0 -285
  141. arelle/archive/plugin/packagedImportTest/__init__.py +0 -47
  142. arelle/archive/plugin/packagedImportTest/importTestChild1.py +0 -21
  143. arelle/archive/plugin/packagedImportTest/importTestChild2.py +0 -22
  144. arelle/archive/plugin/packagedImportTest/importTestGrandchild1.py +0 -21
  145. arelle/archive/plugin/packagedImportTest/importTestGrandchild2.py +0 -21
  146. arelle/archive/plugin/packagedImportTest/importTestImported1.py +0 -24
  147. arelle/archive/plugin/packagedImportTest/importTestImported11.py +0 -21
  148. arelle/archive/plugin/packagedImportTest/subdir/importTestImported111.py +0 -21
  149. arelle/archive/plugin/packagedImportTest/subdir/subsubdir/importTestImported1111.py +0 -21
  150. arelle/archive/plugin/sakaCalendar.py +0 -215
  151. arelle/archive/plugin/saveInstanceInfoset.py +0 -121
  152. arelle/archive/plugin/sphinx/FormulaGenerator.py +0 -823
  153. arelle/archive/plugin/sphinx/SphinxContext.py +0 -404
  154. arelle/archive/plugin/sphinx/SphinxEvaluator.py +0 -783
  155. arelle/archive/plugin/sphinx/SphinxMethods.py +0 -1287
  156. arelle/archive/plugin/sphinx/SphinxParser.py +0 -1093
  157. arelle/archive/plugin/sphinx/SphinxValidator.py +0 -163
  158. arelle/archive/plugin/sphinx/US-GAAP Ratios Example.xsr +0 -52
  159. arelle/archive/plugin/sphinx/__init__.py +0 -285
  160. arelle/archive/plugin/streamingExtensions.py +0 -335
  161. arelle/archive/plugin/updateTableLB.py +0 -242
  162. arelle/archive/plugin/validate/SBRnl/CustomLoader.py +0 -19
  163. arelle/archive/plugin/validate/SBRnl/DTS.py +0 -305
  164. arelle/archive/plugin/validate/SBRnl/Dimensions.py +0 -357
  165. arelle/archive/plugin/validate/SBRnl/Document.py +0 -799
  166. arelle/archive/plugin/validate/SBRnl/Filing.py +0 -467
  167. arelle/archive/plugin/validate/SBRnl/__init__.py +0 -75
  168. arelle/archive/plugin/validate/SBRnl/config.xml +0 -26
  169. arelle/archive/plugin/validate/SBRnl/sbr-nl-taxonomies.xml +0 -754
  170. arelle/archive/plugin/validate/USBestPractices.py +0 -570
  171. arelle/archive/plugin/validate/USCorpAction.py +0 -557
  172. arelle/archive/plugin/validate/USSecTagging.py +0 -337
  173. arelle/archive/plugin/validate/XDC/__init__.py +0 -77
  174. arelle/archive/plugin/validate/XDC/config.xml +0 -20
  175. arelle/archive/plugin/validate/XFsyntax/__init__.py +0 -64
  176. arelle/archive/plugin/validate/XFsyntax/xf.py +0 -2227
  177. arelle/archive/plugin/validate/calc2.py +0 -536
  178. arelle/archive/plugin/validateSchemaLxml.py +0 -156
  179. arelle/archive/plugin/validateTableInfoset.py +0 -52
  180. arelle/archive/us-gaap-dei-docType-extraction-frm.xml +0 -90
  181. arelle/archive/us-gaap-dei-ratio-cash-frm.xml +0 -150
  182. arelle/examples/plugin/formulaSuiteConverter.py +0 -212
  183. arelle/examples/plugin/functionsCustom.py +0 -59
  184. arelle/examples/plugin/hello_dolly.py +0 -64
  185. arelle/examples/plugin/multi.py +0 -58
  186. arelle/examples/plugin/rssSaveOim.py +0 -96
  187. arelle/examples/plugin/validate/XYZ/DisclosureSystems.py +0 -2
  188. arelle/examples/plugin/validate/XYZ/PluginValidationDataExtension.py +0 -10
  189. arelle/examples/plugin/validate/XYZ/ValidationPluginExtension.py +0 -49
  190. arelle/examples/plugin/validate/XYZ/__init__.py +0 -75
  191. arelle/examples/plugin/validate/XYZ/resources/config.xml +0 -16
  192. arelle/examples/plugin/validate/XYZ/rules/__init__.py +0 -0
  193. arelle/examples/plugin/validate/XYZ/rules/rules01.py +0 -110
  194. arelle/examples/plugin/validate/XYZ/rules/rules02.py +0 -59
  195. arelle/model/CommentBase.py +0 -9
  196. arelle/model/ElementBase.py +0 -11
  197. arelle/model/PIBase.py +0 -10
  198. arelle/model/__init__.py +0 -15
  199. arelle/scripts-macOS/startWebServer.command +0 -3
  200. arelle/scripts-unix/startWebServer.sh +0 -1
  201. arelle/scripts-windows/startWebServer.bat +0 -5
  202. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/WHEEL +0 -0
  203. {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/entry_points.txt +0 -0
  204. {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