arelle-release 2.17.1__py3-none-any.whl → 2.37.71__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 (893) hide show
  1. arelle/Aspect.py +6 -3
  2. arelle/BetaFeatures.py +3 -0
  3. arelle/Cntlr.py +117 -413
  4. arelle/CntlrCmdLine.py +364 -227
  5. arelle/CntlrQuickBooks.py +4 -2
  6. arelle/CntlrWebMain.py +179 -119
  7. arelle/CntlrWinMain.py +342 -124
  8. arelle/DialogAbout.py +1 -1
  9. arelle/DialogArcroleGroup.py +1 -1
  10. arelle/DialogFind.py +1 -1
  11. arelle/DialogFormulaParameters.py +2 -2
  12. arelle/DialogLanguage.py +45 -36
  13. arelle/DialogNewFactItem.py +1 -1
  14. arelle/DialogOpenArchive.py +30 -34
  15. arelle/DialogPackageManager.py +11 -8
  16. arelle/DialogPluginManager.py +43 -89
  17. arelle/DialogRssWatch.py +2 -2
  18. arelle/DialogURL.py +1 -1
  19. arelle/DialogUserPassword.py +1 -1
  20. arelle/DisclosureSystem.py +69 -1
  21. arelle/ErrorManager.py +321 -0
  22. arelle/FileSource.py +201 -99
  23. arelle/FunctionFn.py +44 -5
  24. arelle/FunctionIxt.py +16 -13
  25. arelle/FunctionUtil.py +1 -1
  26. arelle/FunctionXfi.py +68 -24
  27. arelle/FunctionXs.py +1 -1
  28. arelle/HtmlUtil.py +5 -4
  29. arelle/LeiUtil.py +63 -43
  30. arelle/LinkbaseType.py +94 -0
  31. arelle/LocalViewer.py +8 -2
  32. arelle/Locale.py +239 -79
  33. arelle/ModelDocument.py +180 -48
  34. arelle/ModelDtsObject.py +32 -27
  35. arelle/ModelFormulaObject.py +14 -6
  36. arelle/ModelInstanceObject.py +43 -14
  37. arelle/ModelManager.py +6 -1
  38. arelle/ModelObject.py +12 -8
  39. arelle/ModelObjectFactory.py +18 -2
  40. arelle/ModelRelationshipSet.py +46 -3
  41. arelle/ModelRenderingObject.py +899 -951
  42. arelle/ModelRssItem.py +2 -4
  43. arelle/ModelTestcaseObject.py +41 -4
  44. arelle/ModelValue.py +42 -14
  45. arelle/ModelVersReport.py +1 -1
  46. arelle/ModelXbrl.py +133 -273
  47. arelle/PackageManager.py +202 -176
  48. arelle/PluginManager.py +551 -239
  49. arelle/PluginUtils.py +54 -0
  50. arelle/PrototypeInstanceObject.py +53 -12
  51. arelle/PythonUtil.py +166 -25
  52. arelle/RuntimeOptions.py +32 -18
  53. arelle/SocketUtils.py +3 -0
  54. arelle/SystemInfo.py +1 -1
  55. arelle/TkTableWrapper.py +33 -5
  56. arelle/UITkTable.py +27 -21
  57. arelle/Updater.py +7 -3
  58. arelle/UrlUtil.py +6 -2
  59. arelle/Validate.py +596 -402
  60. arelle/ValidateDuplicateFacts.py +584 -0
  61. arelle/ValidateFileSource.py +38 -0
  62. arelle/ValidateFilingText.py +46 -29
  63. arelle/ValidateInfoset.py +104 -32
  64. arelle/ValidateUtr.py +31 -4
  65. arelle/ValidateXbrl.py +144 -120
  66. arelle/ValidateXbrlCalcs.py +51 -66
  67. arelle/ValidateXbrlDTS.py +98 -29
  68. arelle/Version.py +2 -7
  69. arelle/ViewFile.py +2 -0
  70. arelle/ViewFileDTS.py +7 -2
  71. arelle/ViewFileFactList.py +1 -1
  72. arelle/ViewFileFactTable.py +4 -4
  73. arelle/ViewFileRelationshipSet.py +36 -19
  74. arelle/ViewFileRenderedGrid.py +164 -753
  75. arelle/ViewFileRenderedLayout.py +174 -0
  76. arelle/ViewFileRenderedStructure.py +108 -0
  77. arelle/ViewWinDTS.py +4 -1
  78. arelle/ViewWinFactList.py +1 -1
  79. arelle/ViewWinFactTable.py +1 -1
  80. arelle/ViewWinRelationshipSet.py +14 -8
  81. arelle/ViewWinRenderedGrid.py +397 -287
  82. arelle/ViewWinRssFeed.py +4 -0
  83. arelle/ViewWinTree.py +15 -9
  84. arelle/ViewWinXml.py +1 -1
  85. arelle/WebCache.py +510 -272
  86. arelle/XbrlConst.py +202 -196
  87. arelle/XbrlUtil.py +2 -1
  88. arelle/XhtmlValidate.py +9 -23
  89. arelle/XmlUtil.py +24 -19
  90. arelle/XmlValidate.py +95 -67
  91. arelle/XmlValidateParticles.py +4 -4
  92. arelle/_version.py +33 -3
  93. arelle/api/Session.py +183 -0
  94. arelle/config/creationSoftwareNames.json +24 -10
  95. arelle/config/disclosuresystems.xml +1 -1
  96. arelle/config/disclosuresystems.xsd +3 -0
  97. arelle/config/sbr-text-formatting.xsd +737 -0
  98. arelle/conformance/CSVTestcaseLoader.py +102 -0
  99. arelle/formula/FactAspectsCache.py +10 -4
  100. arelle/formula/ValidateFormula.py +82 -194
  101. arelle/formula/XPathContext.py +42 -28
  102. arelle/formula/XPathParser.py +15 -9
  103. arelle/locale/ar_EG/LC_MESSAGES/ar_EG.po +3 -4
  104. arelle/locale/messages.pot +1 -2
  105. arelle/locale/ru/LC_MESSAGES/ru.po +2 -2
  106. arelle/logging/formatters/LogFormatter.py +47 -0
  107. arelle/logging/handlers/LogHandlerWithXml.py +94 -0
  108. arelle/logging/handlers/LogToBufferHandler.py +20 -0
  109. arelle/logging/handlers/LogToPrintHandler.py +41 -0
  110. arelle/logging/handlers/LogToXmlHandler.py +244 -0
  111. arelle/logging/handlers/StructuredMessageLogHandler.py +74 -0
  112. arelle/model/CommentBase.py +3 -0
  113. arelle/model/ElementBase.py +3 -0
  114. arelle/model/PIBase.py +3 -0
  115. arelle/model/__init__.py +3 -0
  116. arelle/oim/Load.py +2869 -0
  117. arelle/oim/Validate.py +155 -0
  118. arelle/oim/xml/Save.py +21 -0
  119. arelle/packages/PackageConst.py +7 -0
  120. arelle/packages/PackageType.py +13 -0
  121. arelle/packages/PackageUtils.py +22 -0
  122. arelle/packages/PackageValidation.py +200 -0
  123. arelle/packages/report/DetectReportPackage.py +13 -0
  124. arelle/packages/report/ReportPackage.py +265 -0
  125. arelle/packages/report/ReportPackageConst.py +79 -0
  126. arelle/packages/report/ReportPackageValidator.py +207 -0
  127. arelle/plugin/EdgarRendererAllReports.py +12 -12
  128. arelle/plugin/OimTaxonomy/ModelValueMore.py +15 -0
  129. arelle/plugin/OimTaxonomy/ValidateDTS.py +484 -0
  130. arelle/plugin/OimTaxonomy/ViewXbrlTxmyObj.py +239 -0
  131. arelle/plugin/OimTaxonomy/XbrlAbstract.py +16 -0
  132. arelle/plugin/OimTaxonomy/XbrlConcept.py +68 -0
  133. arelle/plugin/OimTaxonomy/XbrlConst.py +261 -0
  134. arelle/plugin/OimTaxonomy/XbrlCube.py +91 -0
  135. arelle/plugin/OimTaxonomy/XbrlDimension.py +38 -0
  136. arelle/plugin/OimTaxonomy/XbrlDts.py +152 -0
  137. arelle/plugin/OimTaxonomy/XbrlEntity.py +16 -0
  138. arelle/plugin/OimTaxonomy/XbrlGroup.py +22 -0
  139. arelle/plugin/OimTaxonomy/XbrlImportedTaxonomy.py +22 -0
  140. arelle/plugin/OimTaxonomy/XbrlLabel.py +31 -0
  141. arelle/plugin/OimTaxonomy/XbrlNetwork.py +100 -0
  142. arelle/plugin/OimTaxonomy/XbrlProperty.py +28 -0
  143. arelle/plugin/OimTaxonomy/XbrlReference.py +33 -0
  144. arelle/plugin/OimTaxonomy/XbrlReport.py +24 -0
  145. arelle/plugin/OimTaxonomy/XbrlTableTemplate.py +35 -0
  146. arelle/plugin/OimTaxonomy/XbrlTaxonomy.py +93 -0
  147. arelle/plugin/OimTaxonomy/XbrlTaxonomyObject.py +154 -0
  148. arelle/plugin/OimTaxonomy/XbrlTransform.py +17 -0
  149. arelle/plugin/OimTaxonomy/XbrlTypes.py +23 -0
  150. arelle/plugin/OimTaxonomy/XbrlUnit.py +17 -0
  151. arelle/plugin/OimTaxonomy/__init__.py +1037 -0
  152. arelle/plugin/OimTaxonomy/resources/iso4217.json +4479 -0
  153. arelle/plugin/OimTaxonomy/resources/oim-taxonomy-schema.json +935 -0
  154. arelle/plugin/OimTaxonomy/resources/ref.json +333 -0
  155. arelle/plugin/OimTaxonomy/resources/transform-types.json +2481 -0
  156. arelle/plugin/OimTaxonomy/resources/types.json +727 -0
  157. arelle/plugin/OimTaxonomy/resources/utr.json +3046 -0
  158. arelle/plugin/OimTaxonomy/resources/xbrlSpec.json +1082 -0
  159. arelle/plugin/formulaLoader.py +3 -3
  160. arelle/plugin/formulaSaver.py +4 -4
  161. arelle/plugin/inlineXbrlDocumentSet.py +331 -102
  162. arelle/plugin/internet/proxyNTLM/HTTPNtlmAuthHandler.py +1 -1
  163. arelle/plugin/loadFromExcel.py +13 -10
  164. arelle/plugin/loadFromOIM.py +16 -3096
  165. arelle/plugin/logging/saveMessages.py +1 -1
  166. arelle/plugin/saveHtmlEBAtables.py +293 -213
  167. arelle/plugin/saveLoadableOIM.py +652 -361
  168. arelle/plugin/saveOIMTaxonomy.py +311 -0
  169. arelle/plugin/streamingExtensions.py +1 -1
  170. arelle/plugin/systemInfo.py +46 -0
  171. arelle/plugin/transforms/tester.py +4 -4
  172. arelle/plugin/validate/CIPC/Const.py +18 -0
  173. arelle/plugin/validate/CIPC/__init__.py +34 -13
  174. arelle/plugin/validate/DBA/DisclosureSystems.py +12 -0
  175. arelle/plugin/validate/DBA/PluginValidationDataExtension.py +165 -0
  176. arelle/plugin/validate/DBA/ValidationPluginExtension.py +545 -0
  177. arelle/plugin/validate/DBA/__init__.py +49 -0
  178. arelle/plugin/validate/DBA/resources/config.xml +21 -0
  179. arelle/plugin/validate/DBA/rules/__init__.py +323 -0
  180. arelle/plugin/validate/DBA/rules/fr.py +1377 -0
  181. arelle/plugin/validate/DBA/rules/tc.py +45 -0
  182. arelle/plugin/validate/DBA/rules/th.py +172 -0
  183. arelle/plugin/validate/DBA/rules/tm.py +351 -0
  184. arelle/plugin/validate/DBA/rules/tr.py +373 -0
  185. arelle/plugin/validate/EBA/__init__.py +11 -12
  186. arelle/plugin/validate/EDINET/Constants.py +208 -0
  187. arelle/plugin/validate/EDINET/ContextRequirement.py +58 -0
  188. arelle/plugin/validate/EDINET/ControllerPluginData.py +298 -0
  189. arelle/plugin/validate/EDINET/CoverItemRequirements.py +42 -0
  190. arelle/plugin/validate/EDINET/DeiRequirements.py +118 -0
  191. arelle/plugin/validate/EDINET/DisclosureSystems.py +1 -0
  192. arelle/plugin/validate/EDINET/FilingFormat.py +275 -0
  193. arelle/plugin/validate/EDINET/FormType.py +134 -0
  194. arelle/plugin/validate/EDINET/ManifestInstance.py +236 -0
  195. arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +640 -0
  196. arelle/plugin/validate/EDINET/ReportFolderType.py +162 -0
  197. arelle/plugin/validate/EDINET/Statement.py +139 -0
  198. arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +493 -0
  199. arelle/plugin/validate/EDINET/UploadContents.py +48 -0
  200. arelle/plugin/validate/EDINET/ValidationPluginExtension.py +64 -0
  201. arelle/plugin/validate/EDINET/__init__.py +109 -0
  202. arelle/plugin/validate/EDINET/resources/config.xml +22 -0
  203. arelle/plugin/validate/EDINET/resources/cover-item-requirements.json +793 -0
  204. arelle/plugin/validate/EDINET/resources/dei-requirements.csv +27 -0
  205. arelle/plugin/validate/EDINET/resources/edinet-taxonomies.xml +62 -0
  206. arelle/plugin/validate/EDINET/rules/contexts.py +547 -0
  207. arelle/plugin/validate/EDINET/rules/edinet.py +1991 -0
  208. arelle/plugin/validate/EDINET/rules/frta.py +301 -0
  209. arelle/plugin/validate/EDINET/rules/gfm.py +2394 -0
  210. arelle/plugin/validate/EDINET/rules/manifests.py +88 -0
  211. arelle/plugin/validate/EDINET/rules/upload.py +1370 -0
  212. arelle/plugin/validate/ESEF/Const.py +16 -75
  213. arelle/plugin/validate/ESEF/Dimensions.py +2 -2
  214. arelle/plugin/validate/ESEF/ESEF_2021/DTS.py +6 -1
  215. arelle/plugin/validate/ESEF/ESEF_2021/Image.py +7 -4
  216. arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +80 -57
  217. arelle/plugin/validate/ESEF/ESEF_Current/DTS.py +60 -22
  218. arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +272 -133
  219. arelle/plugin/validate/ESEF/Util.py +5 -19
  220. arelle/plugin/validate/ESEF/__init__.py +61 -46
  221. arelle/plugin/validate/ESEF/resources/authority-validations.json +120 -10
  222. arelle/plugin/validate/ESEF/resources/config.xml +44 -3
  223. arelle/plugin/validate/FERC/__init__.py +31 -18
  224. arelle/plugin/validate/FERC/config.xml +18 -18
  225. arelle/plugin/validate/NL/DisclosureSystems.py +19 -3
  226. arelle/plugin/validate/NL/PluginValidationDataExtension.py +710 -7
  227. arelle/plugin/validate/NL/ValidationPluginExtension.py +117 -12
  228. arelle/plugin/validate/NL/__init__.py +21 -10
  229. arelle/plugin/validate/NL/resources/config.xml +27 -6
  230. arelle/plugin/validate/NL/rules/br_kvk.py +81 -21
  231. arelle/plugin/validate/NL/rules/fg_nl.py +292 -0
  232. arelle/plugin/validate/NL/rules/fr_kvk.py +60 -7
  233. arelle/plugin/validate/NL/rules/fr_nl.py +705 -24
  234. arelle/plugin/validate/NL/rules/nl_kvk.py +2182 -0
  235. arelle/plugin/validate/ROS/DisclosureSystems.py +1 -0
  236. arelle/plugin/validate/ROS/PluginValidationDataExtension.py +109 -0
  237. arelle/plugin/validate/ROS/ValidationPluginExtension.py +27 -0
  238. arelle/plugin/validate/ROS/__init__.py +28 -341
  239. arelle/plugin/validate/ROS/resources/config.xml +20 -0
  240. arelle/plugin/validate/ROS/rules/__init__.py +56 -0
  241. arelle/plugin/validate/ROS/rules/ros.py +393 -0
  242. arelle/plugin/validate/UK/ValidateUK.py +1372 -0
  243. arelle/plugin/validate/{HMRC → UK}/__init__.py +195 -189
  244. arelle/plugin/validate/{HMRC → UK}/config.xml +1 -1
  245. arelle/plugin/xbrlDB/SqlDb.py +1 -1
  246. arelle/plugin/xbrlDB/XbrlOpenSqlDB.py +5 -5
  247. arelle/plugin/xbrlDB/XbrlPublicPostgresDB.py +1 -1
  248. arelle/plugin/xbrlDB/XbrlSemanticJsonDB.py +1 -1
  249. arelle/plugin/xbrlDB/XbrlSemanticRdfDB.py +1 -1
  250. arelle/plugin/xbrlDB/__init__.py +4 -1
  251. arelle/{RenderingEvaluator.py → rendering/RenderingEvaluator.py} +120 -99
  252. arelle/rendering/RenderingLayout.py +476 -0
  253. arelle/rendering/RenderingResolution.py +814 -0
  254. arelle/resources/cache/http/www.eurofiling.info/eu/fr/xbrl/ext/filing-indicators.xsd +20 -0
  255. arelle/resources/cache/http/www.w3.org/2001/03/xml.xsd +117 -0
  256. arelle/resources/cache/http/www.w3.org/2001/XMLSchema.xsd +2534 -0
  257. arelle/resources/cache/http/www.w3.org/2001/xml.xsd +287 -0
  258. arelle/resources/cache/http/www.xbrl.org/2003/xbrl-instance-2003-12-31.xsd +779 -0
  259. arelle/resources/cache/http/www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd +486 -0
  260. arelle/resources/cache/http/www.xbrl.org/2003/xl-2003-12-31.xsd +251 -0
  261. arelle/resources/cache/http/www.xbrl.org/2003/xlink-2003-12-31.xsd +121 -0
  262. arelle/resources/cache/http/www.xbrl.org/2004/ref-2004-08-10.xsd +129 -0
  263. arelle/resources/cache/http/www.xbrl.org/2005/xbrldt-2005.xsd +53 -0
  264. arelle/resources/cache/http/www.xbrl.org/2006/ref-2006-02-27.xsd +120 -0
  265. arelle/resources/cache/http/www.xbrl.org/2006/xbrldi-2006.xsd +41 -0
  266. arelle/resources/cache/http/www.xbrl.org/2008/boolean-filter.xsd +51 -0
  267. arelle/resources/cache/http/www.xbrl.org/2008/concept-filter.xsd +127 -0
  268. arelle/resources/cache/http/www.xbrl.org/2008/conformance.xsd +116 -0
  269. arelle/resources/cache/http/www.xbrl.org/2008/conformanceFunction.xsd +51 -0
  270. arelle/resources/cache/http/www.xbrl.org/2008/consistency-assertion.xsd +66 -0
  271. arelle/resources/cache/http/www.xbrl.org/2008/dimension-filter.xsd +86 -0
  272. arelle/resources/cache/http/www.xbrl.org/2008/entity-filter.xsd +92 -0
  273. arelle/resources/cache/http/www.xbrl.org/2008/existence-assertion.xsd +44 -0
  274. arelle/resources/cache/http/www.xbrl.org/2008/formula.xsd +261 -0
  275. arelle/resources/cache/http/www.xbrl.org/2008/function.xsd +90 -0
  276. arelle/resources/cache/http/www.xbrl.org/2008/general-filter.xsd +38 -0
  277. arelle/resources/cache/http/www.xbrl.org/2008/generic-label.xsd +80 -0
  278. arelle/resources/cache/http/www.xbrl.org/2008/generic-link.xsd +81 -0
  279. arelle/resources/cache/http/www.xbrl.org/2008/generic-reference.xsd +63 -0
  280. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xbrl-instance-2003-12-31-ixmod.xsd +788 -0
  281. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xbrl-linkbase-2003-12-31-ixmod.xsd +488 -0
  282. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xl-2003-12-31.xsd +248 -0
  283. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xlink-2003-12-31.xsd +117 -0
  284. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xframes-1.xsd +166 -0
  285. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-applet-1.xsd +66 -0
  286. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-attribs-1.xsd +72 -0
  287. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-base-1.xsd +36 -0
  288. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic-form-1.xsd +195 -0
  289. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic-table-1.xsd +169 -0
  290. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10-model-1.xsd +376 -0
  291. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10-module-redefines-1.xsd +61 -0
  292. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10-modules-1.xsd +259 -0
  293. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10.xsd +98 -0
  294. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-bdo-1.xsd +78 -0
  295. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-blkphras-1.xsd +161 -0
  296. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-blkpres-1.xsd +37 -0
  297. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-blkstruct-1.xsd +49 -0
  298. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-charent-1.xsd +38 -0
  299. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-copyright-1.xsd +29 -0
  300. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-csismap-1.xsd +96 -0
  301. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-datatypes-1.xsd +128 -0
  302. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-edit-1.xsd +39 -0
  303. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-events-1.xsd +130 -0
  304. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-form-1.xsd +326 -0
  305. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-frames-1.xsd +113 -0
  306. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-framework-1.xsd +66 -0
  307. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-hypertext-1.xsd +47 -0
  308. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-iframe-1.xsd +68 -0
  309. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-image-1.xsd +45 -0
  310. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlphras-1.xsd +163 -0
  311. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlpres-1.xsd +39 -0
  312. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlstruct-1.xsd +50 -0
  313. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlstyle-1.xsd +27 -0
  314. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-legacy-1.xsd +97 -0
  315. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-link-1.xsd +45 -0
  316. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-list-1.xsd +99 -0
  317. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-meta-1.xsd +42 -0
  318. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-misc-1.xsd +441 -0
  319. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-nameident-1.xsd +63 -0
  320. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-notations-1.xsd +69 -0
  321. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-object-1.xsd +76 -0
  322. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-param-1.xsd +51 -0
  323. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-pres-1.xsd +51 -0
  324. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-ruby-1.xsd +171 -0
  325. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-ruby-basic-1.xsd +89 -0
  326. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-script-1.xsd +70 -0
  327. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-ssismap-1.xsd +43 -0
  328. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-struct-1.xsd +112 -0
  329. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-style-1.xsd +52 -0
  330. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-table-1.xsd +272 -0
  331. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-target-1.xsd +53 -0
  332. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-text-1.xsd +67 -0
  333. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11-model-1.xsd +677 -0
  334. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11-module-redefines-1.xsd +335 -0
  335. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11-modules-1.xsd +528 -0
  336. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11.xsd +104 -0
  337. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml2.xsd +21 -0
  338. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-1.xsd +73 -0
  339. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-2.xsd +74 -0
  340. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-attribs-1.xsd +73 -0
  341. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-attribs-2.xsd +75 -0
  342. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-copyright-1.xsd +34 -0
  343. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-copyright-2.xsd +34 -0
  344. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-handlers-2.xsd +98 -0
  345. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0-definitions.xsd +225 -0
  346. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0-model.xsd +681 -0
  347. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0-modules.xsd +535 -0
  348. arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0.xsd +40 -0
  349. arelle/resources/cache/http/www.xbrl.org/2008/match-filter.xsd +94 -0
  350. arelle/resources/cache/http/www.xbrl.org/2008/period-filter.xsd +86 -0
  351. arelle/resources/cache/http/www.xbrl.org/2008/registry.xsd +145 -0
  352. arelle/resources/cache/http/www.xbrl.org/2008/relative-filter.xsd +38 -0
  353. arelle/resources/cache/http/www.xbrl.org/2008/segment-scenario-filter.xsd +41 -0
  354. arelle/resources/cache/http/www.xbrl.org/2008/tuple-filter.xsd +83 -0
  355. arelle/resources/cache/http/www.xbrl.org/2008/unit-filter.xsd +58 -0
  356. arelle/resources/cache/http/www.xbrl.org/2008/validation.xsd +78 -0
  357. arelle/resources/cache/http/www.xbrl.org/2008/value-assertion.xsd +43 -0
  358. arelle/resources/cache/http/www.xbrl.org/2008/value-filter.xsd +43 -0
  359. arelle/resources/cache/http/www.xbrl.org/2008/variable.xsd +240 -0
  360. arelle/resources/cache/http/www.xbrl.org/2010/aspect-cover-filter.xsd +67 -0
  361. arelle/resources/cache/http/www.xbrl.org/2010/concept-relation-filter.xsd +108 -0
  362. arelle/resources/cache/http/www.xbrl.org/2010/custom-function-implementation.xsd +71 -0
  363. arelle/resources/cache/http/www.xbrl.org/2010/generic-message.xsd +68 -0
  364. arelle/resources/cache/http/www.xbrl.org/2010/validation-message.xsd +50 -0
  365. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xbrl-instance-2003-12-31-ixmod.xsd +788 -0
  366. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xbrl-linkbase-2003-12-31-ixmod.xsd +488 -0
  367. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xl-2003-12-31.xsd +248 -0
  368. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xlink-2003-12-31.xsd +117 -0
  369. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xframes-1.xsd +166 -0
  370. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-applet-1.xsd +66 -0
  371. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-attribs-1.xsd +72 -0
  372. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-base-1.xsd +36 -0
  373. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic-form-1.xsd +195 -0
  374. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic-table-1.xsd +169 -0
  375. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10-model-1.xsd +376 -0
  376. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10-module-redefines-1.xsd +61 -0
  377. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10-modules-1.xsd +259 -0
  378. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10.xsd +98 -0
  379. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-bdo-1.xsd +78 -0
  380. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-blkphras-1.xsd +161 -0
  381. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-blkpres-1.xsd +37 -0
  382. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-blkstruct-1.xsd +49 -0
  383. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-charent-1.xsd +38 -0
  384. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-copyright-1.xsd +29 -0
  385. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-csismap-1.xsd +96 -0
  386. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-datatypes-1.xsd +128 -0
  387. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-edit-1.xsd +39 -0
  388. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-events-1.xsd +130 -0
  389. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-form-1.xsd +326 -0
  390. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-frames-1.xsd +113 -0
  391. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-framework-1.xsd +66 -0
  392. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-hypertext-1.xsd +47 -0
  393. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-iframe-1.xsd +68 -0
  394. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-image-1.xsd +45 -0
  395. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlphras-1.xsd +163 -0
  396. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlpres-1.xsd +39 -0
  397. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlstruct-1.xsd +50 -0
  398. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlstyle-1.xsd +27 -0
  399. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-legacy-1.xsd +97 -0
  400. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-link-1.xsd +45 -0
  401. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-list-1.xsd +99 -0
  402. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-meta-1.xsd +42 -0
  403. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-misc-1.xsd +441 -0
  404. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-nameident-1.xsd +63 -0
  405. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-notations-1.xsd +69 -0
  406. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-object-1.xsd +76 -0
  407. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-param-1.xsd +51 -0
  408. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-pres-1.xsd +51 -0
  409. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-ruby-1.xsd +171 -0
  410. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-ruby-basic-1.xsd +89 -0
  411. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-script-1.xsd +70 -0
  412. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-ssismap-1.xsd +43 -0
  413. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-struct-1.xsd +112 -0
  414. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-style-1.xsd +52 -0
  415. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-table-1.xsd +272 -0
  416. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-target-1.xsd +53 -0
  417. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-text-1.xsd +67 -0
  418. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11-model-1.xsd +677 -0
  419. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11-module-redefines-1.xsd +335 -0
  420. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11-modules-1.xsd +528 -0
  421. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11.xsd +104 -0
  422. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml2.xsd +21 -0
  423. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-1.xsd +73 -0
  424. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-2.xsd +74 -0
  425. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-attribs-1.xsd +73 -0
  426. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-attribs-2.xsd +75 -0
  427. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-copyright-1.xsd +34 -0
  428. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-copyright-2.xsd +34 -0
  429. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-handlers-2.xsd +98 -0
  430. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1-definitions.xsd +252 -0
  431. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1-model.xsd +681 -0
  432. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1-modules.xsd +535 -0
  433. arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1.xsd +40 -0
  434. arelle/resources/cache/http/www.xbrl.org/2013/match-filter.xsd +94 -0
  435. arelle/resources/cache/http/www.xbrl.org/2013/preferred-label.xsd +12 -0
  436. arelle/resources/cache/http/www.xbrl.org/2013/versioning-base.xsd +142 -0
  437. arelle/resources/cache/http/www.xbrl.org/2013/versioning-concept-details.xsd +143 -0
  438. arelle/resources/cache/http/www.xbrl.org/2013/versioning-concept-use.xsd +64 -0
  439. arelle/resources/cache/http/www.xbrl.org/2013/versioning-dimensions.xsd +162 -0
  440. arelle/resources/cache/http/www.xbrl.org/2014/extensible-enumerations.xsd +27 -0
  441. arelle/resources/cache/http/www.xbrl.org/2014/table.xsd +356 -0
  442. arelle/resources/cache/http/www.xbrl.org/2014/tablemodel.xsd +156 -0
  443. arelle/resources/cache/http/www.xbrl.org/2016/assertion-severity.xsd +29 -0
  444. arelle/resources/cache/http/www.xbrl.org/2016/severities.xml +21 -0
  445. arelle/resources/cache/http/www.xbrl.org/2016/taxonomy-package-catalog.xsd +38 -0
  446. arelle/resources/cache/http/www.xbrl.org/2016/taxonomy-package.xsd +154 -0
  447. arelle/resources/cache/http/www.xbrl.org/2022/assertion-severity.xsd +43 -0
  448. arelle/resources/cache/http/www.xbrl.org/2022/severities.xml +21 -0
  449. arelle/resources/cache/http/www.xbrl.org/dtr/type/nonNumeric-2009-12-16.xsd +76 -0
  450. arelle/resources/cache/http/www.xbrl.org/dtr/type/numeric-2009-12-16.xsd +78 -0
  451. arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/accounting-arcrole-2023-01-04.xsd +39 -0
  452. arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/deprecated-2009-12-16.xsd +29 -0
  453. arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/esma-arcrole-2018-11-21.xsd +14 -0
  454. arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/factExplanatory-2009-12-16.xsd +13 -0
  455. arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/jpfr-arcrole-2007-11-07.xsd +27 -0
  456. arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/parent-child-2013-09-19.xsd +12 -0
  457. arelle/resources/cache/http/www.xbrl.org/lrr/role/deprecated-2009-12-16.xsd +17 -0
  458. arelle/resources/cache/http/www.xbrl.org/lrr/role/jpfr-role-2007-11-07.xsd +47 -0
  459. arelle/resources/cache/http/www.xbrl.org/lrr/role/negated-2008-03-31.xsd +30 -0
  460. arelle/resources/cache/http/www.xbrl.org/lrr/role/negated-2009-12-16.xsd +33 -0
  461. arelle/resources/cache/http/www.xbrl.org/lrr/role/negative-2009-12-16.xsd +25 -0
  462. arelle/resources/cache/http/www.xbrl.org/lrr/role/net-2009-12-16.xsd +13 -0
  463. arelle/resources/cache/http/www.xbrl.org/lrr/role/positive-2009-12-16.xsd +25 -0
  464. arelle/resources/cache/http/www.xbrl.org/lrr/role/property-2022-09-28.xsd +15 -0
  465. arelle/resources/cache/http/www.xbrl.org/lrr/role/reference-2009-12-16.xsd +21 -0
  466. arelle/resources/cache/http/www.xbrl.org/lrr/role/restated-2006-02-21.xsd +19 -0
  467. arelle/resources/cache/http/www.xbrl.org/utr/2012-01-30/utr.xml +4543 -0
  468. arelle/resources/cache/http/www.xbrl.org/utr/2012-10-31/utr.xml +4510 -0
  469. arelle/resources/cache/http/www.xbrl.org/utr/2012-11-30/utr.xml +4567 -0
  470. arelle/resources/cache/http/www.xbrl.org/utr/2013-02-28/utr.xml +5180 -0
  471. arelle/resources/cache/http/www.xbrl.org/utr/2013-05-17/utr.xml +5349 -0
  472. arelle/resources/cache/http/www.xbrl.org/utr/2016-08-10/utr.xml +5363 -0
  473. arelle/resources/cache/http/www.xbrl.org/utr/2017-07-12/utr.xml +6164 -0
  474. arelle/resources/cache/http/www.xbrl.org/utr/2021-02-16/utr.xml +6370 -0
  475. arelle/resources/cache/http/www.xbrl.org/utr/2021-12-08/utr.xml +6493 -0
  476. arelle/resources/cache/http/www.xbrl.org/utr/2022-02-16/utr.xml +6551 -0
  477. arelle/resources/cache/http/www.xbrl.org/utr/2022-07-20/utr.xml +6638 -0
  478. arelle/resources/cache/http/www.xbrl.org/utr/2023-12-20/utr.xml +6680 -0
  479. arelle/resources/cache/http/www.xbrl.org/utr/2024-01-31/utr.xml +6680 -0
  480. arelle/resources/cache/http/www.xbrl.org/utr/2024-10-22/utr.xml +6693 -0
  481. arelle/resources/cache/http/www.xbrl.org/utr/utr.xml +6693 -0
  482. arelle/resources/cache/https/www.xbrl.org/2005/conformance.xsd +87 -0
  483. arelle/resources/cache/https/www.xbrl.org/2020/extensible-enumerations-2.0.xsd +51 -0
  484. arelle/resources/cache/https/www.xbrl.org/2023/calculation-1.1.xsd +27 -0
  485. arelle/resources/cache/https/www.xbrl.org/dtr/type/2020-01-21/types.xsd +812 -0
  486. arelle/resources/cache/https/www.xbrl.org/dtr/type/2022-03-31/types.xsd +847 -0
  487. arelle/resources/cache/https/www.xbrl.org/dtr/type/2024-01-31/types.xsd +897 -0
  488. arelle/resources/cache/https/www.xbrl.org/taxonomy/int/filing-indicators/REC/2021-02-03/filing-indicators-def.xml +68 -0
  489. arelle/resources/cache/https/www.xbrl.org/taxonomy/int/filing-indicators/REC/2021-02-03/filing-indicators-label.xml +84 -0
  490. arelle/resources/cache/https/www.xbrl.org/taxonomy/int/filing-indicators/REC/2021-02-03/filing-indicators.xsd +67 -0
  491. arelle/resources/libs/Tktable2.11/linux-x86_64/README.txt +149 -0
  492. arelle/resources/libs/Tktable2.11/linux-x86_64/html/tkTable.html +2039 -0
  493. arelle/resources/libs/Tktable2.11/linux-x86_64/libTktable2.11.so +0 -0
  494. arelle/resources/libs/Tktable2.11/linux-x86_64/license.txt +51 -0
  495. arelle/resources/libs/Tktable2.11/linux-x86_64/pkgIndex.tcl +3 -0
  496. arelle/resources/libs/Tktable2.11/linux-x86_64/tkTable.tcl +825 -0
  497. arelle/resources/libs/Tktable2.11/linux-x86_64/tktable.py +674 -0
  498. arelle/resources/libs/Tktable2.11/macos-arm64/README.txt +149 -0
  499. arelle/resources/libs/Tktable2.11/macos-arm64/html/tkTable.html +2039 -0
  500. arelle/resources/libs/Tktable2.11/macos-arm64/libTktable2.11.dylib +0 -0
  501. arelle/resources/libs/Tktable2.11/macos-arm64/license.txt +51 -0
  502. arelle/resources/libs/Tktable2.11/macos-arm64/pkgIndex.tcl +2 -0
  503. arelle/resources/libs/Tktable2.11/macos-arm64/tkTable.tcl +825 -0
  504. arelle/resources/libs/Tktable2.11/macos-arm64/tktable.py +674 -0
  505. arelle/resources/libs/Tktable2.11/macos-x86_64/README.txt +149 -0
  506. arelle/resources/libs/Tktable2.11/macos-x86_64/html/tkTable.html +2039 -0
  507. arelle/resources/libs/Tktable2.11/macos-x86_64/libTktable2.11.dylib +0 -0
  508. arelle/resources/libs/Tktable2.11/macos-x86_64/license.txt +51 -0
  509. arelle/resources/libs/Tktable2.11/macos-x86_64/pkgIndex.tcl +2 -0
  510. arelle/resources/libs/Tktable2.11/macos-x86_64/tkTable.tcl +825 -0
  511. arelle/resources/libs/Tktable2.11/macos-x86_64/tktable.py +674 -0
  512. arelle/resources/libs/Tktable2.11/win-x86_64/Tktable.dll +0 -0
  513. arelle/resources/libs/Tktable2.11/win-x86_64/pkgIndex.tcl +2 -0
  514. arelle/resources/libs/Tktable2.11/win-x86_64/tkTable.tcl +825 -0
  515. arelle/typing.py +9 -4
  516. arelle/utils/Contexts.py +38 -0
  517. arelle/utils/EntryPointDetection.py +139 -0
  518. arelle/utils/Equivalence.py +22 -0
  519. arelle/utils/{validate/PluginValidationData.py → PluginData.py} +5 -2
  520. arelle/utils/PluginHooks.py +256 -5
  521. arelle/utils/Units.py +36 -0
  522. arelle/utils/validate/Decorator.py +5 -3
  523. arelle/utils/validate/DetectScriptsInXhtml.py +99 -0
  524. arelle/utils/validate/ESEFImage.py +283 -0
  525. arelle/utils/validate/Validation.py +9 -1
  526. arelle/utils/validate/ValidationPlugin.py +74 -11
  527. arelle/utils/validate/ValidationUtil.py +55 -0
  528. arelle/webserver/bottle.py +5 -4424
  529. {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info}/METADATA +51 -42
  530. arelle_release-2.37.71.dist-info/RECORD +697 -0
  531. {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info}/WHEEL +1 -1
  532. {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info/licenses}/LICENSE.md +1 -4
  533. {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info}/top_level.txt +0 -1
  534. arelle/DialogOpenTaxonomyPackage.py +0 -1
  535. arelle/RenderingResolver.py +0 -624
  536. arelle/examples/.pydevproject +0 -5
  537. arelle/examples/CustomLogger.py +0 -43
  538. arelle/examples/LoadEFMvalidate.py +0 -32
  539. arelle/examples/LoadSavePreLbCsv.py +0 -26
  540. arelle/examples/LoadValidate.cs +0 -31
  541. arelle/examples/LoadValidate.py +0 -36
  542. arelle/examples/LoadValidateCmdLine.java +0 -69
  543. arelle/examples/LoadValidatePostedZip.java +0 -57
  544. arelle/examples/LoadValidateWebService.java +0 -34
  545. arelle/examples/SaveTableToExelle.py +0 -140
  546. arelle/examples/TR3toTR4.py +0 -88
  547. arelle/examples/plugin/bigInstance.py +0 -394
  548. arelle/examples/plugin/cmdWebServerExtension.py +0 -42
  549. arelle/examples/plugin/crashTest.py +0 -38
  550. arelle/examples/plugin/formulaSuiteConverter.py +0 -212
  551. arelle/examples/plugin/functionsCustom.py +0 -59
  552. arelle/examples/plugin/hello_dolly.py +0 -64
  553. arelle/examples/plugin/hello_i18n.pot +0 -26
  554. arelle/examples/plugin/hello_i18n.py +0 -32
  555. arelle/examples/plugin/importTestChild1.py +0 -21
  556. arelle/examples/plugin/importTestChild2.py +0 -22
  557. arelle/examples/plugin/importTestGrandchild1.py +0 -21
  558. arelle/examples/plugin/importTestGrandchild2.py +0 -21
  559. arelle/examples/plugin/importTestImported1.py +0 -23
  560. arelle/examples/plugin/importTestImported11.py +0 -22
  561. arelle/examples/plugin/importTestParent.py +0 -48
  562. arelle/examples/plugin/locale/fr/LC_MESSAGES/hello_i18n.po +0 -25
  563. arelle/examples/plugin/packagedImportTest/__init__.py +0 -47
  564. arelle/examples/plugin/packagedImportTest/importTestChild1.py +0 -21
  565. arelle/examples/plugin/packagedImportTest/importTestChild2.py +0 -22
  566. arelle/examples/plugin/packagedImportTest/importTestGrandchild1.py +0 -21
  567. arelle/examples/plugin/packagedImportTest/importTestGrandchild2.py +0 -21
  568. arelle/examples/plugin/packagedImportTest/importTestImported1.py +0 -24
  569. arelle/examples/plugin/packagedImportTest/importTestImported11.py +0 -21
  570. arelle/examples/plugin/packagedImportTest/subdir/importTestImported111.py +0 -21
  571. arelle/examples/plugin/packagedImportTest/subdir/subsubdir/importTestImported1111.py +0 -21
  572. arelle/examples/plugin/sakaCalendar.py +0 -215
  573. arelle/examples/plugin/saveInstanceInfoset.py +0 -121
  574. arelle/examples/plugin/streamingExtensions.py +0 -335
  575. arelle/examples/plugin/testcaseCalc11ValidateSetup.py +0 -32
  576. arelle/examples/plugin/testcaseIxExpectedHtmlFixup.py +0 -45
  577. arelle/examples/plugin/updateTableLB.py +0 -242
  578. arelle/examples/plugin/validate/XYZ/DisclosureSystems.py +0 -2
  579. arelle/examples/plugin/validate/XYZ/PluginValidationDataExtension.py +0 -10
  580. arelle/examples/plugin/validate/XYZ/ValidationPluginExtension.py +0 -49
  581. arelle/examples/plugin/validate/XYZ/__init__.py +0 -75
  582. arelle/examples/plugin/validate/XYZ/resources/config.xml +0 -16
  583. arelle/examples/plugin/validate/XYZ/rules/rules01.py +0 -109
  584. arelle/examples/plugin/validate/XYZ/rules/rules02.py +0 -58
  585. arelle/examples/plugin/validateSchemaLxml.py +0 -156
  586. arelle/examples/plugin/validateTableInfoset.py +0 -52
  587. arelle/examples/us-gaap-dei-docType-extraction-frm.xml +0 -90
  588. arelle/examples/us-gaap-dei-ratio-cash-frm.xml +0 -150
  589. arelle/plugin/functionsXmlCreation.py +0 -106
  590. arelle/plugin/instanceInfo.py +0 -306
  591. arelle/plugin/loadFromOIM-2018.py +0 -1282
  592. arelle/plugin/objectmaker.py +0 -285
  593. arelle/plugin/sphinx/FormulaGenerator.py +0 -823
  594. arelle/plugin/sphinx/SphinxContext.py +0 -404
  595. arelle/plugin/sphinx/SphinxEvaluator.py +0 -783
  596. arelle/plugin/sphinx/SphinxMethods.py +0 -1287
  597. arelle/plugin/sphinx/SphinxParser.py +0 -1093
  598. arelle/plugin/sphinx/SphinxValidator.py +0 -163
  599. arelle/plugin/sphinx/US-GAAP Ratios Example.xsr +0 -52
  600. arelle/plugin/sphinx/__init__.py +0 -285
  601. arelle/plugin/transforms/SEC/__init__.py +0 -308
  602. arelle/plugin/transforms/SEC/conf/README.md +0 -39
  603. arelle/plugin/transforms/SEC/conf/extractTestcase.sh +0 -2
  604. arelle/plugin/transforms/SEC/conf/extractTestcase.xsl +0 -109
  605. arelle/plugin/transforms/SEC/conf/runIxtSecTests.sh +0 -16
  606. arelle/plugin/transforms/SEC/conf/saxon9.jar +0 -0
  607. arelle/plugin/transforms/SEC/conf/testcase.xml +0 -7117
  608. arelle/plugin/transforms/SEC/conf/tests.xml +0 -848
  609. arelle/plugin/transforms/SEC/text2num.py +0 -110
  610. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-boolballotbox.xml +0 -66
  611. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-countrynameen.xml +0 -65
  612. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-datequarterend.xml +0 -66
  613. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durday.xml +0 -61
  614. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durhour.xml +0 -69
  615. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durmonth.xml +0 -71
  616. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durweek.xml +0 -70
  617. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durwordsen.xml +0 -56
  618. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-duryear.xml +0 -64
  619. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-edgarprovcountryen.xml +0 -65
  620. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-entityfilercategoryen.xml +0 -63
  621. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-exchnameen.xml +0 -86
  622. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-numwordsen.xml +0 -55
  623. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-stateprovnameen.xml +0 -64
  624. arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-yesnoballotbox.xml +0 -66
  625. arelle/plugin/transforms/SEC/transformationRegistry/registry/transform-registry.xml +0 -314
  626. arelle/plugin/transforms/SEC/transformationRegistry/schema/inlinexbrl-sec-transformation.xsd +0 -418
  627. arelle/plugin/validate/EFM/Consts.py +0 -362
  628. arelle/plugin/validate/EFM/DTS.py +0 -569
  629. arelle/plugin/validate/EFM/Dimensions.py +0 -264
  630. arelle/plugin/validate/EFM/Document.py +0 -206
  631. arelle/plugin/validate/EFM/Filing.py +0 -4383
  632. arelle/plugin/validate/EFM/IsolateSeparateIXDSes.py +0 -19
  633. arelle/plugin/validate/EFM/MessageNumericId.py +0 -142
  634. arelle/plugin/validate/EFM/PreCalAlignment.py +0 -324
  635. arelle/plugin/validate/EFM/Util.py +0 -688
  636. arelle/plugin/validate/EFM/__init__.py +0 -843
  637. arelle/plugin/validate/EFM/config.xml +0 -333
  638. arelle/plugin/validate/EFM/resources/README.md +0 -57
  639. arelle/plugin/validate/EFM/resources/axiswarnings.json +0 -27
  640. arelle/plugin/validate/EFM/resources/cef-deprecated-concepts.json +0 -8
  641. arelle/plugin/validate/EFM/resources/country-deprecated-concepts.json +0 -19
  642. arelle/plugin/validate/EFM/resources/currency-deprecated-concepts.json +0 -7
  643. arelle/plugin/validate/EFM/resources/dei-deprecated-concepts.json +0 -8
  644. arelle/plugin/validate/EFM/resources/dei-validations.json +0 -2884
  645. arelle/plugin/validate/EFM/resources/dqc-us-rules.json +0 -1389
  646. arelle/plugin/validate/EFM/resources/ecd-deprecated-concepts.json +0 -1
  647. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-16-4.xml +0 -115
  648. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-0-4.xml +0 -300
  649. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-1.xml +0 -304
  650. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-2.xml +0 -290
  651. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-3-1.xml +0 -294
  652. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-18.1.xml +0 -549
  653. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-18.2.xml +0 -506
  654. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-18.3.xml +0 -496
  655. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-19-1.xml +0 -662
  656. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-19-2.xml +0 -3761
  657. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-19-3.xml +0 -3577
  658. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-20-1.xml +0 -4020
  659. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-20-2.xml +0 -3320
  660. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-20-3.xml +0 -2998
  661. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2012.xml +0 -957
  662. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2013.xml +0 -982
  663. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2014.xml +0 -1001
  664. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2015.xml +0 -1076
  665. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2016.xml +0 -120
  666. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-1.xml +0 -3329
  667. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-2.xml +0 -1230
  668. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-3.xml +0 -1113
  669. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-4.xml +0 -1321
  670. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-1-preview.xml +0 -1721
  671. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-1.xml +0 -1841
  672. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-2-2.xml +0 -1450
  673. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-2.xml +0 -1429
  674. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-4.xml +0 -1527
  675. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-1-1.xml +0 -2049
  676. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-1.xml +0 -2065
  677. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-2.xml +0 -1674
  678. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-3.xml +0 -1715
  679. arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-all-years.xml +0 -10671
  680. arelle/plugin/validate/EFM/resources/edgartaxonomies/erxl.xsd +0 -69
  681. arelle/plugin/validate/EFM/resources/edgartaxonomies/extendedtaxonomies-all-years.xml +0 -18
  682. arelle/plugin/validate/EFM/resources/edgartaxonomies/ifrs-taxonomies.xml +0 -3126
  683. arelle/plugin/validate/EFM/resources/edgartaxonomies/ifrstaxonomies-all-years.xml +0 -22
  684. arelle/plugin/validate/EFM/resources/ex26-validations.json +0 -255
  685. arelle/plugin/validate/EFM/resources/exch-deprecated-concepts.json +0 -163
  686. arelle/plugin/validate/EFM/resources/ifrs-full-deprecated-concepts.json +0 -204
  687. arelle/plugin/validate/EFM/resources/invest-deprecated-concepts.json +0 -99
  688. arelle/plugin/validate/EFM/resources/ixbrl-transform-registries.json +0 -16
  689. arelle/plugin/validate/EFM/resources/naics-deprecated-concepts.json +0 -295
  690. arelle/plugin/validate/EFM/resources/oef-deprecated-concepts.json +0 -59
  691. arelle/plugin/validate/EFM/resources/other-standard-taxonomies.json +0 -12
  692. arelle/plugin/validate/EFM/resources/rr-deprecated-concepts.json +0 -14
  693. arelle/plugin/validate/EFM/resources/rxp-deprecated-concepts.json +0 -1
  694. arelle/plugin/validate/EFM/resources/shr-deprecated-concepts.json +0 -1
  695. arelle/plugin/validate/EFM/resources/sic-deprecated-concepts.json +0 -1
  696. arelle/plugin/validate/EFM/resources/signwarnings.json +0 -112
  697. arelle/plugin/validate/EFM/resources/srt-deprecated-concepts.json +0 -1
  698. arelle/plugin/validate/EFM/resources/stpr-deprecated-concepts.json +0 -1
  699. arelle/plugin/validate/EFM/resources/taxonomy-compatibility.json +0 -79
  700. arelle/plugin/validate/EFM/resources/us-gaap-deprecated-concepts.json +0 -2886
  701. arelle/plugin/validate/EFM/resources/us-gaap-rels-2020.json +0 -29068
  702. arelle/plugin/validate/EFM/resources/us-gaap-rels-2021.json +0 -29598
  703. arelle/plugin/validate/EFM/resources/us-gaap-rels-2022.json +0 -29141
  704. arelle/plugin/validate/EFM/resources/us-gaap-rels-2023.json +0 -29400
  705. arelle/plugin/validate/EFM/resources/vip-deprecated-concepts.json +0 -1
  706. arelle/plugin/validate/EFM/tools/CheckTxmyRefs.py +0 -180
  707. arelle/plugin/validate/EFM-htm/Const.py +0 -205
  708. arelle/plugin/validate/EFM-htm/__init__.py +0 -217
  709. arelle/plugin/validate/EFM-htm/config.xml +0 -17
  710. arelle/plugin/validate/EFM-htm/resources/efm-htm.dtd +0 -664
  711. arelle/plugin/validate/ESEF/ESEF_Current/Image.py +0 -199
  712. arelle/plugin/validate/ESEF_2022/__init__.py +0 -47
  713. arelle/plugin/validate/GFM/__init__.py +0 -59
  714. arelle/plugin/validate/GFM/config.xml +0 -82
  715. arelle/plugin/validate/SBRnl/CustomLoader.py +0 -19
  716. arelle/plugin/validate/SBRnl/DTS.py +0 -305
  717. arelle/plugin/validate/SBRnl/Dimensions.py +0 -357
  718. arelle/plugin/validate/SBRnl/Document.py +0 -799
  719. arelle/plugin/validate/SBRnl/Filing.py +0 -467
  720. arelle/plugin/validate/SBRnl/__init__.py +0 -75
  721. arelle/plugin/validate/SBRnl/config.xml +0 -26
  722. arelle/plugin/validate/SBRnl/sbr-nl-taxonomies.xml +0 -754
  723. arelle/plugin/validate/USBestPractices.py +0 -570
  724. arelle/plugin/validate/USCorpAction.py +0 -557
  725. arelle/plugin/validate/USSecTagging.py +0 -337
  726. arelle/plugin/validate/XDC/__init__.py +0 -77
  727. arelle/plugin/validate/XDC/config.xml +0 -20
  728. arelle/plugin/validate/XFsyntax/__init__.py +0 -64
  729. arelle/plugin/validate/XFsyntax/xf.py +0 -2227
  730. arelle/plugin/validate/__init__.py +0 -20
  731. arelle/plugin/validate/calc2.py +0 -536
  732. arelle/plugin/validateSBRnl.py +0 -530
  733. arelle/scripts-macOS/startWebServer.command +0 -3
  734. arelle/scripts-unix/startWebServer.sh +0 -1
  735. arelle/scripts-windows/startWebServer.bat +0 -5
  736. arelle_release-2.17.1.dist-info/RECORD +0 -676
  737. tests/__init__.py +0 -0
  738. tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/ArelleGUITest.csproj +0 -30
  739. tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Tests.cs +0 -381
  740. tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Usings.cs +0 -1
  741. tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest.sln +0 -31
  742. tests/integration_tests/ui_tests/resources/workiva.zip +0 -0
  743. tests/integration_tests/validation/README.md +0 -50
  744. tests/integration_tests/validation/conformance_suite_config.py +0 -59
  745. tests/integration_tests/validation/conformance_suite_configs.py +0 -63
  746. tests/integration_tests/validation/conformance_suite_configurations/efm_current.py +0 -261
  747. tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2021.py +0 -85
  748. tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2022.py +0 -90
  749. tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2021.py +0 -15
  750. tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2022.py +0 -15
  751. tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py +0 -13
  752. tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py +0 -13
  753. tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py +0 -13
  754. tests/integration_tests/validation/conformance_suite_configurations/xbrl_2_1.py +0 -34
  755. tests/integration_tests/validation/conformance_suite_configurations/xbrl_calculations_1_1.py +0 -40
  756. tests/integration_tests/validation/conformance_suite_configurations/xbrl_dimensions_1_0.py +0 -28
  757. tests/integration_tests/validation/conformance_suite_configurations/xbrl_extensible_enumerations_1_0.py +0 -10
  758. tests/integration_tests/validation/conformance_suite_configurations/xbrl_extensible_enumerations_2_0.py +0 -10
  759. tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula_1_0.py +0 -9
  760. tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula_1_0_assertion_severity_2_0.py +0 -9
  761. tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula_1_0_function_registry.py +0 -14
  762. tests/integration_tests/validation/conformance_suite_configurations/xbrl_ixbrl_1_1.py +0 -22
  763. tests/integration_tests/validation/conformance_suite_configurations/xbrl_link_role_registry_1_0.py +0 -11
  764. tests/integration_tests/validation/conformance_suite_configurations/xbrl_oim_1_0.py +0 -19
  765. tests/integration_tests/validation/conformance_suite_configurations/xbrl_table_linkbase_1_0.py +0 -296
  766. tests/integration_tests/validation/conformance_suite_configurations/xbrl_taxonomy_packages_1_0.py +0 -13
  767. tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_3.py +0 -13
  768. tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_4.py +0 -13
  769. tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_5.py +0 -13
  770. tests/integration_tests/validation/conformance_suite_configurations/xbrl_utr_malformed_1_0.py +0 -31
  771. tests/integration_tests/validation/conformance_suite_configurations/xbrl_utr_registry_1_0.py +0 -22
  772. tests/integration_tests/validation/conformance_suite_configurations/xbrl_utr_structure_1_0.py +0 -18
  773. tests/integration_tests/validation/conftest.py +0 -24
  774. tests/integration_tests/validation/discover_tests.py +0 -22
  775. tests/integration_tests/validation/download_conformance_suites.py +0 -47
  776. tests/integration_tests/validation/run_conformance_suites.py +0 -175
  777. tests/integration_tests/validation/test_conformance_suites.py +0 -14
  778. tests/integration_tests/validation/validation_util.py +0 -271
  779. tests/resources/conformance_suites/nl_nt16/br_kvk/2-04-invalid-period.xbrl +0 -63
  780. tests/resources/conformance_suites/nl_nt16/br_kvk/2-04-testcase.xml +0 -22
  781. tests/resources/conformance_suites/nl_nt16/br_kvk/3-01-missing.xbrl +0 -53
  782. tests/resources/conformance_suites/nl_nt16/br_kvk/3-01-multiple.xbrl +0 -60
  783. tests/resources/conformance_suites/nl_nt16/br_kvk/3-01-testcase.xml +0 -33
  784. tests/resources/conformance_suites/nl_nt16/br_kvk/4-07-invalid.xbrl +0 -57
  785. tests/resources/conformance_suites/nl_nt16/br_kvk/4-07-testcase.xml +0 -22
  786. tests/resources/conformance_suites/nl_nt16/br_kvk/4-10-invalid.xbrl +0 -58
  787. tests/resources/conformance_suites/nl_nt16/br_kvk/4-10-testcase.xml +0 -22
  788. tests/resources/conformance_suites/nl_nt16/br_kvk/4-12-invalid.xbrl +0 -63
  789. tests/resources/conformance_suites/nl_nt16/br_kvk/4-12-testcase.xml +0 -22
  790. tests/resources/conformance_suites/nl_nt16/br_kvk/4-16-missing.xbrl +0 -61
  791. tests/resources/conformance_suites/nl_nt16/br_kvk/4-16-testcase.xml +0 -22
  792. tests/resources/conformance_suites/nl_nt16/br_kvk/4-20-invalid-date.xbrl +0 -89
  793. tests/resources/conformance_suites/nl_nt16/br_kvk/4-20-testcase.xml +0 -22
  794. tests/resources/conformance_suites/nl_nt16/fr_kvk/1-01-invalid-file-extension.xml +0 -56
  795. tests/resources/conformance_suites/nl_nt16/fr_kvk/1-01-testcase.xml +0 -22
  796. tests/resources/conformance_suites/nl_nt16/fr_kvk/2-01-invalid-lang.xbrl +0 -56
  797. tests/resources/conformance_suites/nl_nt16/fr_kvk/2-01-missing-lang.xbrl +0 -55
  798. tests/resources/conformance_suites/nl_nt16/fr_kvk/2-01-testcase.xml +0 -33
  799. tests/resources/conformance_suites/nl_nt16/fr_kvk/2-03-entrypoint.xsd +0 -6
  800. tests/resources/conformance_suites/nl_nt16/fr_kvk/2-03-invalid-entrypoint.xbrl +0 -63
  801. tests/resources/conformance_suites/nl_nt16/fr_kvk/2-03-testcase.xml +0 -22
  802. tests/resources/conformance_suites/nl_nt16/fr_kvk/5-01-invalid-decimals.xbrl +0 -49
  803. tests/resources/conformance_suites/nl_nt16/fr_kvk/5-01-testcase.xml +0 -22
  804. tests/resources/conformance_suites/nl_nt16/fr_kvk/5-02-invalid-decimals.xbrl +0 -49
  805. tests/resources/conformance_suites/nl_nt16/fr_kvk/5-02-testcase.xml +0 -22
  806. tests/resources/conformance_suites/nl_nt16/fr_nl/1-01-invalid-file.xbrl +0 -2
  807. tests/resources/conformance_suites/nl_nt16/fr_nl/1-01-invalid-zip.zip +0 -0
  808. tests/resources/conformance_suites/nl_nt16/fr_nl/1-01-testcase.xml +0 -33
  809. tests/resources/conformance_suites/nl_nt16/fr_nl/1-03-invalid-doctype.xbrl +0 -4
  810. tests/resources/conformance_suites/nl_nt16/fr_nl/1-03-testcase.xml +0 -22
  811. tests/resources/conformance_suites/nl_nt16/fr_nl/1-05-invalid-encoding.xbrl +0 -0
  812. tests/resources/conformance_suites/nl_nt16/fr_nl/1-05-testcase.xml +0 -22
  813. tests/resources/conformance_suites/nl_nt16/fr_nl/1-06-testcase.xml +0 -22
  814. tests/resources/conformance_suites/nl_nt16/fr_nl/1-06.invalid.xbrl +0 -2
  815. tests/resources/conformance_suites/nl_nt16/fr_nl/2-06-invalid-file.xbrl +0 -8
  816. tests/resources/conformance_suites/nl_nt16/fr_nl/2-06-invalid-zip.zip +0 -0
  817. tests/resources/conformance_suites/nl_nt16/fr_nl/2-06-testcase.xml +0 -33
  818. tests/resources/conformance_suites/nl_nt16/index.xml +0 -20
  819. tests/resources/conformance_suites/nl_nt17/br_kvk/2-04-invalid-period.xbrl +0 -63
  820. tests/resources/conformance_suites/nl_nt17/br_kvk/2-04-testcase.xml +0 -22
  821. tests/resources/conformance_suites/nl_nt17/br_kvk/3-01-missing.xbrl +0 -53
  822. tests/resources/conformance_suites/nl_nt17/br_kvk/3-01-multiple.xbrl +0 -60
  823. tests/resources/conformance_suites/nl_nt17/br_kvk/3-01-testcase.xml +0 -33
  824. tests/resources/conformance_suites/nl_nt17/br_kvk/4-07-invalid.xbrl +0 -57
  825. tests/resources/conformance_suites/nl_nt17/br_kvk/4-07-testcase.xml +0 -22
  826. tests/resources/conformance_suites/nl_nt17/br_kvk/4-10-invalid.xbrl +0 -58
  827. tests/resources/conformance_suites/nl_nt17/br_kvk/4-10-testcase.xml +0 -22
  828. tests/resources/conformance_suites/nl_nt17/br_kvk/4-12-invalid.xbrl +0 -63
  829. tests/resources/conformance_suites/nl_nt17/br_kvk/4-12-testcase.xml +0 -22
  830. tests/resources/conformance_suites/nl_nt17/br_kvk/4-16-missing.xbrl +0 -61
  831. tests/resources/conformance_suites/nl_nt17/br_kvk/4-16-testcase.xml +0 -22
  832. tests/resources/conformance_suites/nl_nt17/br_kvk/4-20-invalid-date.xbrl +0 -89
  833. tests/resources/conformance_suites/nl_nt17/br_kvk/4-20-testcase.xml +0 -22
  834. tests/resources/conformance_suites/nl_nt17/fr_kvk/1-01-invalid-file-extension.xml +0 -56
  835. tests/resources/conformance_suites/nl_nt17/fr_kvk/1-01-testcase.xml +0 -22
  836. tests/resources/conformance_suites/nl_nt17/fr_kvk/2-01-invalid-lang.xbrl +0 -56
  837. tests/resources/conformance_suites/nl_nt17/fr_kvk/2-01-missing-lang.xbrl +0 -55
  838. tests/resources/conformance_suites/nl_nt17/fr_kvk/2-01-testcase.xml +0 -33
  839. tests/resources/conformance_suites/nl_nt17/fr_kvk/2-03-entrypoint.xsd +0 -6
  840. tests/resources/conformance_suites/nl_nt17/fr_kvk/2-03-invalid-entrypoint.xbrl +0 -63
  841. tests/resources/conformance_suites/nl_nt17/fr_kvk/2-03-testcase.xml +0 -22
  842. tests/resources/conformance_suites/nl_nt17/fr_kvk/5-01-invalid-decimals.xbrl +0 -49
  843. tests/resources/conformance_suites/nl_nt17/fr_kvk/5-01-testcase.xml +0 -22
  844. tests/resources/conformance_suites/nl_nt17/fr_kvk/5-02-invalid-decimals.xbrl +0 -49
  845. tests/resources/conformance_suites/nl_nt17/fr_kvk/5-02-testcase.xml +0 -22
  846. tests/resources/conformance_suites/nl_nt17/fr_nl/1-01-invalid-file.xbrl +0 -2
  847. tests/resources/conformance_suites/nl_nt17/fr_nl/1-01-invalid-zip.zip +0 -0
  848. tests/resources/conformance_suites/nl_nt17/fr_nl/1-01-testcase.xml +0 -33
  849. tests/resources/conformance_suites/nl_nt17/fr_nl/1-03-invalid-doctype.xbrl +0 -4
  850. tests/resources/conformance_suites/nl_nt17/fr_nl/1-03-testcase.xml +0 -22
  851. tests/resources/conformance_suites/nl_nt17/fr_nl/1-05-invalid-encoding.xbrl +0 -0
  852. tests/resources/conformance_suites/nl_nt17/fr_nl/1-05-testcases.xml +0 -22
  853. tests/resources/conformance_suites/nl_nt17/fr_nl/1-06-testcase.xml +0 -22
  854. tests/resources/conformance_suites/nl_nt17/fr_nl/1-06.invalid.xbrl +0 -2
  855. tests/resources/conformance_suites/nl_nt17/fr_nl/2-06-invalid-file.xbrl +0 -8
  856. tests/resources/conformance_suites/nl_nt17/fr_nl/2-06-invalid-zip.zip +0 -0
  857. tests/resources/conformance_suites/nl_nt17/fr_nl/2-06-testcase.xml +0 -33
  858. tests/resources/conformance_suites/nl_nt17/index.xml +0 -20
  859. tests/resources/conformance_suites/nl_nt18/fr_nl/1-03-invalid-doctype.xbrl +0 -4
  860. tests/resources/conformance_suites/nl_nt18/fr_nl/1-03-testcase.xml +0 -22
  861. tests/resources/conformance_suites/nl_nt18/fr_nl/1-05-invalid-encoding.xbrl +0 -0
  862. tests/resources/conformance_suites/nl_nt18/fr_nl/1-05-testcases.xml +0 -22
  863. tests/resources/conformance_suites/nl_nt18/fr_nl/1-06-testcase.xml +0 -22
  864. tests/resources/conformance_suites/nl_nt18/fr_nl/1-06.invalid.xbrl +0 -2
  865. tests/resources/conformance_suites/nl_nt18/fr_nl/1.01-invalid-file.xbrl +0 -2
  866. tests/resources/conformance_suites/nl_nt18/fr_nl/1.01-invalid-zip.zip +0 -0
  867. tests/resources/conformance_suites/nl_nt18/fr_nl/1.01-testcase.xml +0 -33
  868. tests/resources/conformance_suites/nl_nt18/fr_nl/2-06-invalid-file.xbrl +0 -8
  869. tests/resources/conformance_suites/nl_nt18/fr_nl/2-06-invalid-zip.zip +0 -0
  870. tests/resources/conformance_suites/nl_nt18/fr_nl/2-06-testcase.xml +0 -33
  871. tests/resources/conformance_suites/nl_nt18/index.xml +0 -8
  872. tests/unit_tests/arelle/conftest.py +0 -16
  873. tests/unit_tests/arelle/formula/test_fact_aspects_cache.py +0 -170
  874. tests/unit_tests/arelle/plugin/test_loadfromoim.py +0 -40
  875. tests/unit_tests/arelle/plugin/test_plugin_imports.py +0 -27
  876. tests/unit_tests/arelle/test_betafeatures.py +0 -81
  877. tests/unit_tests/arelle/test_cntlr.py +0 -28
  878. tests/unit_tests/arelle/test_import.py +0 -40
  879. tests/unit_tests/arelle/test_locale.py +0 -73
  880. tests/unit_tests/arelle/test_modelmanager.py +0 -15
  881. tests/unit_tests/arelle/test_packagemanager.py +0 -65
  882. tests/unit_tests/arelle/test_pluginmanager.py +0 -176
  883. tests/unit_tests/arelle/test_qname.py +0 -140
  884. tests/unit_tests/arelle/test_runtimeoptions.py +0 -56
  885. tests/unit_tests/arelle/test_system_info.py +0 -26
  886. tests/unit_tests/arelle/test_updater.py +0 -507
  887. tests/unit_tests/arelle/test_urlutil.py +0 -49
  888. tests/unit_tests/arelle/test_version.py +0 -46
  889. tests/unit_tests/arelle/utils/validate/test_decorator.py +0 -59
  890. /arelle/{examples/plugin/validate/XYZ → plugin/validate/EDINET}/rules/__init__.py +0 -0
  891. /arelle/plugin/validate/{HMRC → UK}/consistencyChecksByName.json +0 -0
  892. /arelle/plugin/validate/{HMRC → UK}/hmrc-taxonomies.xml +0 -0
  893. {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info}/entry_points.txt +0 -0
@@ -1,46 +1,123 @@
1
- # -*- coding: utf-8 -*-
1
+ """
2
+ See COPYRIGHT.md for copyright information.
2
3
 
3
- '''
4
- saveLoadableOIM.py is an example of a plug-in that will save a re-loadable JSON or CSV instance.
4
+ ## Overview
5
5
 
6
- When run from GUI a save-as dialog defaults to save .json but can also save .csv and .xlsx files.
6
+ The Save Loadable OIM plugin facilitates the saving of re-loadable instances in JSON or CSV formats, adhering to the
7
+ Open Information Model (OIM) XBRL Specification. It is designed to work seamlessly with the Load From OIM plugin,
8
+ allowing for efficient data handling in Arelle.
7
9
 
8
- When run from command line interface in single-instance mode (a single instance is loaded):
9
- --saveLoadableOIM oim-file-path
10
- specifies file name or full path to save with .json, .csv or .xlsx sufffix
11
- When used to augment test case operation to save oim files when running a test suite
12
- --saveTestcaseOimFileSuffix oim-file-suffix
13
- specifies characters to add to read-me-first file when saving oim file
10
+ ## Key Features
14
11
 
15
- CSV saving produces a single row-per-fact table.
12
+ - **Multiple Formats**: Enables saving data in JSON and CSV OIM formats as well as XLSX.
13
+ - **Seamless Integration**: Compatible with the Load From OIM plugin for saving and loading reports.
14
+ - **GUI and CLI Compatibility**: Available for use in both GUI and CLI modes.
15
+ - **Test Case Augmentation**: Allows saving OIM files with a custom suffix during test suite runs.
16
16
 
17
- Extensions can be added to the results in the following manner:
17
+ ## Usage Instructions
18
18
 
19
- extensionPrefixes - optional dict of prefix/name pairs to extend saved metadata
20
- extensionReportObjects - optional dict of extension report objects
21
- extensionFactPropertiesMethod - method to add extension properties to oimFact
22
- extensionReportFinalizeMethod - (JSON only) method to finalize json object, for example change facts from object to array.
19
+ ### Command Line Usage
23
20
 
24
- See COPYRIGHT.md for copyright information.
25
- '''
26
- import sys, os, io, time, json, csv, zipfile
27
- import regex as re
21
+ - **Single-Instance Mode**:
22
+ Save a file in single-instance mode by specifying the file path and extension:
23
+ ```bash
24
+ python arelleCmdLine.py --plugins saveLoadableOIM --file filing-documents.zip --saveLoadableOIM example.json
25
+ ```
26
+
27
+ - **Test Case Operation**:
28
+ Augment test case operations by specifying a suffix for the read-me-first file in a test suite:
29
+ ```bash
30
+ python arelleCmdLine.py --plugins saveLoadableOIM --file filing-documents.zip --saveTestcaseOimFileSuffix -savedOim.csv
31
+ ```
32
+
33
+ - **Deduplicate facts**
34
+ To save an OIM instance with duplicate fact removed use the `--deduplicateOimFacts` argument with either `complete`,
35
+ `consistent-pairs`, or `consistent-sets` as the value.
36
+ For details on what eaxctly consitutes a duplicate fact and why there are multiple options read the
37
+ [Fact Deduplication][fact-deduplication] documentation.
38
+ ```bash
39
+ python arelleCmdLine.py --plugins saveLoadableOIM --file filing-documents.zip --saveLoadableOIM example.json --deduplicateOimFacts complete
40
+ ```
41
+
42
+ [fact-deduplication]: project:/user_guides/fact_deduplication.md
43
+
44
+ ### GUI Usage
45
+
46
+ - **Save Re-Loadable Output**:
47
+ 1. Load the desired report in Arelle.
48
+ 2. Go to `Tools` > `Save Loadable OIM`.
49
+ 3. Specify a filename and choose the desired file format (JSON, CSV, or XLSX).
50
+
51
+ ## Additional Notes
52
+
53
+ If the loaded report refers to a taxonomy on the local file system, the OIM instance needs to be saved in the same
54
+ directory to maintain the validity of the relative file system path to the taxonomy.
55
+ """
56
+
57
+ from __future__ import annotations
58
+
59
+ import csv
60
+ import io
61
+ import json
62
+ import operator
63
+ import os
64
+ import threading
65
+ import zipfile
66
+ from collections.abc import Iterable
67
+ from dataclasses import dataclass
68
+ from datetime import datetime
28
69
  from decimal import Decimal
29
70
  from math import isinf, isnan
30
- from collections import defaultdict, OrderedDict
31
- from arelle import ModelDocument, XbrlConst
32
- from arelle.ModelInstanceObject import ModelFact
33
- from arelle.ModelValue import (qname, QName, DateTime, YearMonthDuration, tzinfoStr,
34
- dayTimeDuration, DayTimeDuration, yearMonthDayTimeDuration, Time,
35
- gYearMonth, gMonthDay, gYear, gMonth, gDay, IsoDuration)
71
+ from numbers import Number
72
+ from optparse import OptionParser
73
+ from pathlib import Path
74
+ from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Optional, cast
75
+
76
+ import regex as re
77
+ from openpyxl import Workbook
78
+ from openpyxl.cell.cell import WriteOnlyCell
79
+ from openpyxl.styles import Alignment, Color, PatternFill, fills
80
+ from openpyxl.worksheet.dimensions import ColumnDimension
81
+
82
+ from arelle import ModelDocument, ValidateDuplicateFacts, XbrlConst
83
+ from arelle.ModelInstanceObject import ModelContext, ModelFact
36
84
  from arelle.ModelRelationshipSet import ModelRelationshipSet
85
+ from arelle.ModelValue import (
86
+ DateTime,
87
+ DayTimeDuration,
88
+ IsoDuration,
89
+ QName,
90
+ Time,
91
+ YearMonthDuration,
92
+ gDay,
93
+ gMonth,
94
+ gMonthDay,
95
+ gYear,
96
+ gYearMonth,
97
+ qname,
98
+ tzinfoStr,
99
+ )
100
+ from arelle.typing import TypeGetText
37
101
  from arelle.UrlUtil import relativeUri
102
+ from arelle.utils.PluginData import PluginData
103
+ from arelle.utils.PluginHooks import PluginHooks
38
104
  from arelle.ValidateXbrlCalcs import inferredDecimals
39
105
  from arelle.Version import authorLabel, copyrightLabel
40
- from arelle.XmlUtil import dateunionValue, elementIndex, xmlstring
41
- from collections import defaultdict
42
- from numbers import Number
43
106
 
107
+ if TYPE_CHECKING:
108
+ from tkinter import Menu
109
+
110
+ from arelle.Cntlr import Cntlr
111
+ from arelle.CntlrCmdLine import CntlrCmdLine
112
+ from arelle.CntlrWinMain import CntlrWinMain
113
+ from arelle.ModelXbrl import ModelXbrl
114
+ from arelle.RuntimeOptions import RuntimeOptions
115
+
116
+ _: TypeGetText
117
+
118
+ PLUGIN_NAME = "Save Loadable OIM"
119
+
120
+ oimErrorPattern = re.compile("oime|oimce|xbrlje|xbrlce")
44
121
  nsOim = "https://xbrl.org/2021"
45
122
  qnOimConceptAspect = qname("concept", noPrefixIsNoNamespace=True)
46
123
  qnOimLangAspect = qname("language", noPrefixIsNoNamespace=True)
@@ -48,112 +125,178 @@ qnOimPeriodAspect = qname("period", noPrefixIsNoNamespace=True)
48
125
  qnOimEntityAspect = qname("entity", noPrefixIsNoNamespace=True)
49
126
  qnOimUnitAspect = qname("unit", noPrefixIsNoNamespace=True)
50
127
 
128
+ reservedUriAliases = {
129
+ nsOim: "xbrl",
130
+ XbrlConst.defaultLinkRole: "_",
131
+ XbrlConst.factExplanatoryFact: "explanatoryFact",
132
+ XbrlConst.factFootnote: "footnote",
133
+ XbrlConst.iso4217: "iso4217",
134
+ XbrlConst.utr: "utr",
135
+ XbrlConst.xbrli: "xbrli",
136
+ XbrlConst.xsd: "xs",
137
+ }
138
+
51
139
  ONE = Decimal(1)
52
140
  TEN = Decimal(10)
53
141
  NILVALUE = "nil"
54
- SCHEMA_LB_REFS = {qname("{http://www.xbrl.org/2003/linkbase}schemaRef"),
55
- # qname("{http://www.xbrl.org/2003/linkbase}linkbaseRef")
56
- }
57
- ROLE_REFS = {qname("{http://www.xbrl.org/2003/linkbase}roleRef"),
58
- qname("{http://www.xbrl.org/2003/linkbase}arcroleRef")}
142
+ SCHEMA_LB_REFS = {
143
+ qname("{http://www.xbrl.org/2003/linkbase}schemaRef"),
144
+ # qname("{http://www.xbrl.org/2003/linkbase}linkbaseRef")
145
+ }
146
+ ROLE_REFS = {
147
+ qname("{http://www.xbrl.org/2003/linkbase}roleRef"),
148
+ qname("{http://www.xbrl.org/2003/linkbase}arcroleRef"),
149
+ }
59
150
  ENTITY_NA_QNAME = ("https://xbrl.org/entities", "NA")
60
- csvOpenMode = 'w'
61
- csvOpenNewline = ''
62
-
63
-
64
- def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
65
- # arguments to add extension features to OIM document
66
- extensionPrefixes=None,
67
- extensionReportObjects=None,
68
- extensionFactPropertiesMethod=None,
69
- extensionReportFinalizeMethod=None):
70
-
151
+ csvOpenMode = "w"
152
+ csvOpenNewline = ""
153
+
154
+ OimFact = dict[str, Any]
155
+ OimReport = dict[str, Any]
156
+
157
+ class NamespacePrefixes:
158
+ def __init__(self, prefixesByNamespace: dict[str, str] | None = None) -> None:
159
+ self._prefixesByNamespace: dict[str, str] = prefixesByNamespace or {}
160
+ self._usedPrefixes: set[str] = set(self._prefixesByNamespace.values())
161
+
162
+ @property
163
+ def namespaces(self) -> dict[str, str]:
164
+ return {
165
+ prefix: namespace
166
+ for namespace, prefix in sorted(
167
+ self._prefixesByNamespace.items(),
168
+ key=operator.itemgetter(1)
169
+ )
170
+ }
171
+
172
+ def __contains__(self, namespace: str) -> bool:
173
+ return namespace in self._prefixesByNamespace
174
+
175
+ def getPrefix(self, namespace: str) -> str | None:
176
+ return self._prefixesByNamespace.get(namespace)
177
+
178
+ def addNamespace(self, namespace: str, preferredPrefix: str) -> str:
179
+ prefix = self._prefixesByNamespace.get(namespace)
180
+ if prefix is not None:
181
+ return prefix
182
+
183
+ prefix = reservedUriAliases.get(namespace)
184
+ if prefix is None:
185
+ prefix = preferredPrefix
186
+ i = 2
187
+ while prefix in self._usedPrefixes:
188
+ prefix = f"{preferredPrefix}{i}"
189
+ i += 1
190
+ self._prefixesByNamespace[namespace] = prefix
191
+ self._usedPrefixes.add(prefix)
192
+ return prefix
193
+
194
+
195
+ def saveLoadableOIM(
196
+ modelXbrl: ModelXbrl,
197
+ oimFile: str,
198
+ outputZip: zipfile.ZipFile | None = None,
199
+ # arguments to add extension features to OIM document
200
+ extensionPrefixes: dict[str, str] | None = None,
201
+ extensionReportObjects: dict[str, Any] | None = None,
202
+ extensionFactPropertiesMethod: Callable[[ModelFact, OimFact], None] | None = None,
203
+ extensionReportFinalizeMethod: Callable[[OimReport], None] | None = None,
204
+ *args: Any,
205
+ **kwargs: Any,
206
+ ) -> None:
71
207
  isJSON = oimFile.endswith(".json")
72
208
  isCSV = oimFile.endswith(".csv")
73
209
  isXL = oimFile.endswith(".xlsx")
74
210
  isCSVorXL = isCSV or isXL
75
211
  if not isJSON and not isCSVorXL:
76
- return
212
+ oimFile = oimFile + ".json"
213
+ isJSON = True
77
214
 
78
- namespacePrefixes = {nsOim: "xbrl"}
79
- prefixNamespaces = {}
215
+ namespacePrefixes = NamespacePrefixes({nsOim: "xbrl"})
80
216
  if extensionPrefixes:
81
217
  for extensionPrefix, extensionNamespace in extensionPrefixes.items():
82
- namespacePrefixes[extensionNamespace] = extensionPrefix
83
- prefixNamespaces[extensionPrefix] = extensionNamespace
218
+ namespacePrefixes.addNamespace(extensionNamespace, extensionPrefix)
84
219
  linkTypeAliases = {}
85
220
  groupAliases = {}
86
- linkTypePrefixes = {}
87
- linkTypeUris = {}
88
- linkGroupPrefixes = {}
89
- linkGroupUris = {}
90
- def compileQname(qname):
91
- if qname.namespaceURI not in namespacePrefixes:
92
- namespacePrefixes[qname.namespaceURI] = qname.prefix or ""
93
-
94
- aspectsDefined = {
95
- qnOimConceptAspect,
96
- qnOimEntityAspect,
97
- qnOimPeriodAspect}
98
-
99
- def oimValue(object, decimals=None):
100
- if isinstance(object, QName):
101
- if object.namespaceURI not in namespacePrefixes:
102
- if object.prefix:
103
- namespacePrefixes[object.namespaceURI] = object.prefix
104
- else:
105
- _prefix = "_{}".format(sum(1 for p in namespacePrefixes if p.startswith("_")))
106
- namespacePrefixes[object.namespaceURI] = _prefix
107
- return "{}:{}".format(namespacePrefixes[object.namespaceURI], object.localName)
108
- if isinstance(object, (float, Decimal)):
221
+
222
+ def compileQname(qname: QName) -> None:
223
+ if qname.namespaceURI is not None and qname.namespaceURI not in namespacePrefixes:
224
+ namespacePrefixes.addNamespace(qname.namespaceURI, qname.prefix or "")
225
+
226
+ aspectsDefined = {qnOimConceptAspect, qnOimEntityAspect, qnOimPeriodAspect}
227
+
228
+ def oimValue(obj: Any) -> Any:
229
+ if isinstance(obj, list):
230
+ # set-valued enumeration fact
231
+ return " ".join([oimValue(o) for o in obj])
232
+ if isinstance(obj, QName) and obj.namespaceURI is not None:
233
+ if obj.namespaceURI not in namespacePrefixes:
234
+ namespacePrefixes.addNamespace(obj.namespaceURI, obj.prefix or "_")
235
+ return f"{namespacePrefixes.getPrefix(obj.namespaceURI)}:{obj.localName}"
236
+ if isinstance(obj, (float, Decimal)):
109
237
  try:
110
- if isinf(object):
111
- return "-INF" if object < 0 else "INF"
112
- elif isnan(object):
238
+ if isinf(obj):
239
+ return "-INF" if obj < 0 else "INF"
240
+ elif isnan(obj):
113
241
  return "NaN"
242
+ elif isinstance(obj, Decimal):
243
+ # XML canonical representation of decimal requires a decimal point.
244
+ # https://www.w3.org/TR/xmlschema-2/#decimal-canonical-representation
245
+ if obj % 1 == 0:
246
+ return f"{obj:.1f}"
247
+ intPart, fracPart = f"{obj:f}".split(".")
248
+ canonicalFracPart = fracPart.rstrip("0") or "0"
249
+ return f"{intPart}.{canonicalFracPart}"
114
250
  else:
115
- if isinstance(object, Decimal) and object == object.to_integral():
116
- object = object.quantize(ONE) # drop any .0
117
- return "{}".format(object)
118
- except:
119
- return str(object)
120
- if isinstance(object, bool):
121
- return "true" if object else "false"
122
- if isinstance(object, (DateTime, YearMonthDuration, DayTimeDuration, Time,
123
- gYearMonth, gMonthDay, gYear, gMonth, gDay,
124
- IsoDuration, int)):
125
- return str(object)
126
- return object
127
-
128
- def oimPeriodValue(cntx):
251
+ return f"{obj}"
252
+ except Exception:
253
+ return str(obj)
254
+ if isinstance(obj, bool):
255
+ return "true" if obj else "false"
256
+ if isinstance(
257
+ obj,
258
+ (
259
+ DateTime,
260
+ YearMonthDuration,
261
+ DayTimeDuration,
262
+ Time,
263
+ gYearMonth,
264
+ gMonthDay,
265
+ gYear,
266
+ gMonth,
267
+ gDay,
268
+ IsoDuration,
269
+ int,
270
+ ),
271
+ ):
272
+ return str(obj)
273
+ return obj
274
+
275
+ def oimPeriodValue(cntx: ModelContext) -> dict[str, str]:
129
276
  if cntx.isStartEndPeriod:
130
277
  s = cntx.startDatetime
131
278
  e = cntx.endDatetime
132
- else: # instant
279
+ else: # instant
133
280
  s = e = cntx.instantDatetime
134
- return({str(qnOimPeriodAspect):
135
- ("{0:04}-{1:02}-{2:02}T{3:02}:{4:02}:{5:02}{6}/".format(
136
- s.year, s.month, s.day, s.hour, s.minute, s.second, tzinfoStr(s))
137
- if cntx.isStartEndPeriod else "") +
138
- "{0:04}-{1:02}-{2:02}T{3:02}:{4:02}:{5:02}{6}".format(
139
- e.year, e.month, e.day, e.hour, e.minute, e.second, tzinfoStr(e))
140
- })
141
-
142
- hasId = False
281
+ assert isinstance(s, datetime) and isinstance(e, datetime)
282
+ return {
283
+ str(qnOimPeriodAspect): (
284
+ f"{s.year:04}-{s.month:02}-{s.day:02}T{s.hour:02}:{s.minute:02}:{s.second:02}{tzinfoStr(s)}/"
285
+ if cntx.isStartEndPeriod
286
+ else ""
287
+ )
288
+ + f"{e.year:04}-{e.month:02}-{e.day:02}T{e.hour:02}:{e.minute:02}:{e.second:02}{tzinfoStr(e)}"
289
+ }
290
+
143
291
  hasTuple = False
144
- hasType = True
145
292
  hasLang = False
146
293
  hasUnits = False
147
294
  hasNumeric = False
148
295
 
149
296
  footnotesRelationshipSet = ModelRelationshipSet(modelXbrl, "XBRL-footnotes")
150
297
 
151
- #compile QNames in instance for OIM
298
+ # compile QNames in instance for OIM
152
299
  for fact in modelXbrl.factsInInstance:
153
- if (fact.id or fact.isTuple or
154
- footnotesRelationshipSet.toModelObject(fact) or
155
- (isCSVorXL and footnotesRelationshipSet.fromModelObject(fact))):
156
- hasId = True
157
300
  concept = fact.concept
158
301
  if concept is not None:
159
302
  if concept.isNumeric:
@@ -169,9 +312,9 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
169
312
  if fact.modelTupleFacts:
170
313
  hasTuple = True
171
314
  if hasTuple:
172
- modelXbrl.error("arelleOIMsaver:tuplesNotAllowed",
173
- "Tuples are not allowed in an OIM document",
174
- modelObject=modelXbrl)
315
+ modelXbrl.error(
316
+ "arelleOIMsaver:tuplesNotAllowed", "Tuples are not allowed in an OIM document", modelObject=modelXbrl
317
+ )
175
318
  return
176
319
 
177
320
  entitySchemePrefixes = {}
@@ -179,7 +322,7 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
179
322
  if cntx.entityIdentifierElement is not None:
180
323
  scheme = cntx.entityIdentifier[0]
181
324
  if scheme not in entitySchemePrefixes:
182
- if not entitySchemePrefixes: # first one is just scheme
325
+ if not entitySchemePrefixes: # first one is just scheme
183
326
  if scheme == "http://www.sec.gov/CIK":
184
327
  _schemePrefix = "cik"
185
328
  elif scheme == "http://standard.iso.org/iso/17442":
@@ -187,9 +330,9 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
187
330
  else:
188
331
  _schemePrefix = "scheme"
189
332
  else:
190
- _schemePrefix = "scheme{}".format(len(entitySchemePrefixes) + 1)
191
- entitySchemePrefixes[scheme] = _schemePrefix
192
- namespacePrefixes[scheme] = _schemePrefix
333
+ _schemePrefix = f"scheme{len(entitySchemePrefixes) + 1}"
334
+ namespacePrefixes.addNamespace(scheme, _schemePrefix)
335
+ entitySchemePrefixes[scheme] = namespacePrefixes.getPrefix(scheme)
193
336
  for dim in cntx.qnameDims.values():
194
337
  compileQname(dim.dimensionQname)
195
338
  aspectsDefined.add(dim.dimensionQname)
@@ -202,69 +345,72 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
202
345
  for measure in measures:
203
346
  compileQname(measure)
204
347
 
205
- if XbrlConst.xbrli in namespacePrefixes and namespacePrefixes[XbrlConst.xbrli] != "xbrli":
206
- namespacePrefixes[XbrlConst.xbrli] = "xbrli" # normalize xbrli prefix
207
-
208
- if hasLang: aspectsDefined.add(qnOimLangAspect)
209
- if hasUnits: aspectsDefined.add(qnOimUnitAspect)
348
+ if hasLang:
349
+ aspectsDefined.add(qnOimLangAspect)
350
+ if hasUnits:
351
+ aspectsDefined.add(qnOimUnitAspect)
210
352
 
211
353
  for footnoteRel in footnotesRelationshipSet.modelRelationships:
212
- typePrefix = "ftTyp_" + os.path.basename(footnoteRel.arcrole)
213
- if footnoteRel.linkrole == XbrlConst.defaultLinkRole:
214
- groupPrefix = "ftGrp_default"
215
- else:
216
- groupPrefix = "ftGrp_" + os.path.basename(footnoteRel.linkrole)
217
354
  if footnoteRel.arcrole not in linkTypeAliases:
355
+ typePrefix = reservedUriAliases.get(footnoteRel.arcrole, f"ftTyp_{os.path.basename(footnoteRel.arcrole)}")
218
356
  linkTypeAliases[footnoteRel.arcrole] = typePrefix
219
- if groupPrefix not in groupAliases:
357
+ if footnoteRel.linkrole not in groupAliases:
358
+ groupPrefix = reservedUriAliases.get(footnoteRel.linkrole, f"ftGrp_{os.path.basename(footnoteRel.linkrole)}")
220
359
  groupAliases[footnoteRel.linkrole] = groupPrefix
221
360
 
222
361
  dtsReferences = set()
362
+ assert modelXbrl.modelDocument is not None
223
363
  baseUrl = modelXbrl.modelDocument.uri.partition("#")[0]
224
- for doc,ref in sorted(modelXbrl.modelDocument.referencesDocument.items(),
225
- key=lambda _item:_item[0].uri):
364
+ for doc, ref in sorted(modelXbrl.modelDocument.referencesDocument.items(), key=lambda _item: _item[0].uri):
226
365
  if ref.referringModelObject.qname in SCHEMA_LB_REFS:
227
- dtsReferences.add(relativeUri(baseUrl,doc.uri))
366
+ dtsReferences.add(relativeUri(baseUrl, doc.uri))
228
367
  for refType in ("role", "arcrole"):
229
- for refElt in sorted(modelXbrl.modelDocument.xmlRootElement.iterchildren(
230
- "{{http://www.xbrl.org/2003/linkbase}}{}Ref".format(refType)),
231
- key=lambda elt:elt.get(refType+"URI")
232
- ):
368
+ for refElt in sorted(
369
+ modelXbrl.modelDocument.xmlRootElement.iterchildren(f"{{http://www.xbrl.org/2003/linkbase}}{refType}Ref"),
370
+ key=lambda elt: elt.get(refType + "URI"),
371
+ ):
233
372
  dtsReferences.add(refElt.get("{http://www.w3.org/1999/xlink}href").partition("#")[0])
234
- dtsReferences = sorted(dtsReferences) # turn into list
373
+ dtsReferences = sorted(dtsReferences) # turn into list
235
374
  footnoteFacts = set()
236
375
 
237
- def factFootnotes(fact, oimFact=None, csvLinks=None):
376
+ def factFootnotes(
377
+ fact: ModelFact,
378
+ oimFact: dict[str, Any] | None = None,
379
+ csvLinks: dict[str, Any] | None = None,
380
+ ):
238
381
  footnotes = []
239
- if isJSON:
240
- oimLinks = {}
241
- elif isCSVorXL:
382
+ oimLinks = {}
383
+ if isCSVorXL and csvLinks is not None:
242
384
  oimLinks = csvLinks
243
385
  for footnoteRel in footnotesRelationshipSet.fromModelObject(fact):
244
- srcId = fact.id if fact.id else "f{}".format(fact.objectIndex)
386
+ srcId = fact.id if fact.id else f"f{fact.objectIndex}"
245
387
  toObj = footnoteRel.toModelObject
246
388
  # json
247
389
  typePrefix = linkTypeAliases[footnoteRel.arcrole]
248
390
  groupPrefix = groupAliases[footnoteRel.linkrole]
249
391
  if typePrefix not in oimLinks:
250
- oimLinks[typePrefix] = OrderedDict()
392
+ oimLinks[typePrefix] = {}
251
393
  _link = oimLinks[typePrefix]
252
394
  if groupPrefix not in _link:
253
395
  if isJSON:
254
396
  _link[groupPrefix] = []
255
397
  elif isCSVorXL:
256
- _link[groupPrefix] = OrderedDict()
398
+ _link[groupPrefix] = {}
399
+ tgtId = toObj.id if toObj.id else f"f{toObj.objectIndex}"
257
400
  if isJSON:
258
401
  tgtIdList = _link[groupPrefix]
402
+ tgtIdList.append(tgtId)
259
403
  elif isCSVorXL:
260
- tgtIdList = _link[groupPrefix].setdefault(srcId, [])
261
- tgtId = toObj.id if toObj.id else "f{}".format(toObj.objectIndex)
262
- tgtIdList.append(tgtId)
263
- footnote = OrderedDict((("group", footnoteRel.linkrole),
264
- ("footnoteType", footnoteRel.arcrole)))
404
+ # Footnote links in xBRL-CSV include the CSV table identifier.
405
+ tgtIdList = _link[groupPrefix].setdefault(f"facts.r_{srcId}.value", [])
406
+ tgtIdList.append(f"footnotes.r_{tgtId}.footnote")
407
+ footnote = {
408
+ "group": footnoteRel.linkrole,
409
+ "footnoteType": footnoteRel.arcrole,
410
+ }
265
411
  if isinstance(toObj, ModelFact):
266
412
  footnote["factRef"] = tgtId
267
- else: # text footnotes
413
+ else: # text footnotes
268
414
  footnote["id"] = tgtId
269
415
  footnote["footnote"] = toObj.viewText()
270
416
  if toObj.xmlLang:
@@ -272,46 +418,38 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
272
418
  footnoteFacts.add(toObj)
273
419
  footnotes.append(footnote)
274
420
  if oimLinks:
275
- _links = OrderedDict((
276
- (typePrefix, OrderedDict((
277
- (groupPrefix, idList)
278
- for groupPrefix, idList in sorted(groups.items())
279
- )))
421
+ _links = {
422
+ typePrefix: {groupPrefix: idList for groupPrefix, idList in sorted(groups.items())}
280
423
  for typePrefix, groups in sorted(oimLinks.items())
281
- ))
282
- if isJSON:
424
+ }
425
+ if isJSON and oimFact is not None:
283
426
  oimFact["links"] = _links
284
427
 
285
428
  return footnotes
286
429
 
287
- def factAspects(fact):
288
- oimFact = OrderedDict()
289
- aspects = OrderedDict()
430
+ def factAspects(fact: ModelFact) -> dict[str, Any]:
431
+ oimFact = {}
432
+ aspects = {}
290
433
  if isCSVorXL:
291
- oimFact["id"] = fact.id or "f{}".format(fact.objectIndex)
292
- parent = fact.getparent()
434
+ oimFact["id"] = fact.id or f"f{fact.objectIndex}"
293
435
  concept = fact.concept
294
- aspects[str(qnOimConceptAspect)] = oimValue(concept.qname)
295
436
  if concept is not None:
296
- if concept.type.isOimTextFactType and fact.xmlLang:
437
+ aspects[str(qnOimConceptAspect)] = oimValue(concept.qname)
438
+ if concept.type is not None and concept.type.isOimTextFactType and fact.xmlLang:
297
439
  aspects[str(qnOimLangAspect)] = fact.xmlLang
298
440
  if fact.isItem:
299
441
  if fact.isNil:
300
442
  _value = None
301
443
  else:
302
444
  _inferredDecimals = inferredDecimals(fact)
303
- _value = oimValue(fact.xValue, _inferredDecimals)
445
+ _value = oimValue(fact.xValue)
304
446
  oimFact["value"] = _value
305
447
  if fact.concept is not None and fact.concept.isNumeric:
306
448
  _numValue = fact.xValue
307
449
  if isinstance(_numValue, Decimal) and not isinf(_numValue) and not isnan(_numValue):
308
- if _numValue == _numValue.to_integral():
309
- _numValue = int(_numValue)
310
- else:
311
- _numValue = float(_numValue)
312
- if not fact.isNil:
313
- if not isinf(_inferredDecimals): # accuracy omitted if infinite
314
- oimFact["decimals"] = _inferredDecimals
450
+ _numValue = int(_numValue) if _numValue == _numValue.to_integral() else float(_numValue)
451
+ if not fact.isNil and not isinf(_inferredDecimals): # accuracy omitted if infinite
452
+ oimFact["decimals"] = _inferredDecimals
315
453
  oimFact["dimensions"] = aspects
316
454
  cntx = fact.context
317
455
  if cntx is not None:
@@ -322,7 +460,7 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
322
460
  for _qn, dim in sorted(cntx.qnameDims.items(), key=lambda item: item[0]):
323
461
  if dim.isExplicit:
324
462
  dimVal = oimValue(dim.memberQname)
325
- else: # typed
463
+ else: # typed
326
464
  if dim.typedMember.get("{http://www.w3.org/2001/XMLSchema-instance}nil") in ("true", "1"):
327
465
  dimVal = None
328
466
  else:
@@ -331,81 +469,77 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
331
469
  unit = fact.unit
332
470
  if unit is not None:
333
471
  _mMul, _mDiv = unit.measures
334
- _sMul = '*'.join(oimValue(m) for m in sorted(_mMul, key=lambda m: oimValue(m)))
472
+ _sMul = "*".join(oimValue(m) for m in sorted(_mMul, key=lambda m: oimValue(m)))
335
473
  if _mDiv:
336
- _sDiv = '*'.join(oimValue(m) for m in sorted(_mDiv, key=lambda m: oimValue(m)))
474
+ _sDiv = "*".join(oimValue(m) for m in sorted(_mDiv, key=lambda m: oimValue(m)))
337
475
  if len(_mDiv) > 1:
338
- if len(_mMul) > 1:
339
- _sUnit = "({})/({})".format(_sMul,_sDiv)
340
- else:
341
- _sUnit = "{}/({})".format(_sMul,_sDiv)
476
+ _sUnit = f"({_sMul})/({_sDiv})" if len(_mMul) > 1 else f"{_sMul}/({_sDiv})"
342
477
  else:
343
- if len(_mMul) > 1:
344
- _sUnit = "({})/{}".format(_sMul,_sDiv)
345
- else:
346
- _sUnit = "{}/{}".format(_sMul,_sDiv)
478
+ _sUnit = f"({_sMul})/{_sDiv}" if len(_mMul) > 1 else f"{_sMul}/{_sDiv}"
347
479
  else:
348
480
  _sUnit = _sMul
349
481
  if _sUnit != "xbrli:pure":
350
482
  aspects[str(qnOimUnitAspect)] = _sUnit
351
- # Tuples removed from xBRL-JSON
352
- #if parent.qname != XbrlConst.qnXbrliXbrl:
353
- # aspects[str(qnOimTupleParentAspect)] = parent.id if parent.id else "f{}".format(parent.objectIndex)
354
- # aspects[str(qnOimTupleOrderAspect)] = elementIndex(fact)
355
483
 
356
484
  if isJSON:
357
485
  factFootnotes(fact, oimFact=oimFact)
358
486
  return oimFact
359
487
 
360
- namespaces = OrderedDict((p,ns) for ns, p in sorted(namespacePrefixes.items(),
361
- key=lambda item: item[1]))
362
-
363
488
  # common metadata
364
- oimReport = OrderedDict() # top level of oim json output
365
- oimReport["documentInfo"] = oimDocInfo = OrderedDict()
489
+ oimReport = {} # top level of oim json output
490
+ oimReport["documentInfo"] = oimDocInfo = {}
366
491
  oimDocInfo["documentType"] = nsOim + ("/xbrl-json" if isJSON else "/xbrl-csv")
367
492
  if isJSON:
368
- oimDocInfo["features"] = oimFeatures = OrderedDict()
369
- oimDocInfo["namespaces"] = namespaces
493
+ oimDocInfo["features"] = oimFeatures = {}
494
+ oimDocInfo["namespaces"] = namespacePrefixes.namespaces
370
495
  if linkTypeAliases:
371
- oimDocInfo["linkTypes"] = OrderedDict((a,u) for u,a in sorted(linkTypeAliases.items(),
372
- key=lambda item: item[1]))
373
- if linkTypeAliases:
374
- oimDocInfo["linkGroups"] = OrderedDict((a,u) for u,a in sorted(groupAliases.items(),
375
- key=lambda item: item[1]))
496
+ oimDocInfo["linkTypes"] = {a: u for u, a in sorted(linkTypeAliases.items(), key=operator.itemgetter(1))}
497
+ if groupAliases:
498
+ oimDocInfo["linkGroups"] = {a: u for u, a in sorted(groupAliases.items(), key=operator.itemgetter(1))}
376
499
  oimDocInfo["taxonomy"] = dtsReferences
377
500
  if isJSON:
378
501
  oimFeatures["xbrl:canonicalValues"] = True
379
502
 
503
+ factsToSave = modelXbrl.facts
504
+ pluginData = modelXbrl.modelManager.cntlr.getPluginData(PLUGIN_NAME)
505
+ if isinstance(pluginData, SaveLoadableOIMPluginData) and pluginData.deduplicateFactsType is not None:
506
+ deduplicatedFacts = frozenset(ValidateDuplicateFacts.getDeduplicatedFacts(modelXbrl, pluginData.deduplicateFactsType))
507
+ duplicateFacts = frozenset(f for f in modelXbrl.facts if f not in deduplicatedFacts)
508
+ if duplicateFacts:
509
+ for fact in duplicateFacts:
510
+ ValidateDuplicateFacts.logDeduplicatedFact(modelXbrl, fact)
511
+ factsToSave = [f for f in factsToSave if f not in duplicateFacts]
380
512
 
381
513
  if isJSON:
382
514
  # save JSON
383
- oimReport["facts"] = oimFacts = OrderedDict()
515
+ oimReport["facts"] = oimFacts = {}
384
516
  # add in report level extension objects
385
517
  if extensionReportObjects:
386
518
  for extObjQName, extObj in extensionReportObjects.items():
387
519
  oimReport[extObjQName] = extObj
388
520
 
389
- def saveJsonFacts(facts, oimFacts, parentFact):
521
+ def saveJsonFacts(facts: list[ModelFact], oimFacts: dict[str, dict[str, Any]]) -> None:
390
522
  for fact in facts:
391
523
  oimFact = factAspects(fact)
392
524
  # add in fact level extension objects
393
525
  if extensionFactPropertiesMethod:
394
526
  extensionFactPropertiesMethod(fact, oimFact)
395
- id = fact.id if fact.id else "f{}".format(fact.objectIndex)
527
+ id = fact.id if fact.id else f"f{fact.objectIndex}"
396
528
  oimFacts[id] = oimFact
397
529
  if fact.modelTupleFacts:
398
- saveJsonFacts(fact.modelTupleFacts, oimFacts, fact)
530
+ saveJsonFacts(fact.modelTupleFacts, oimFacts)
399
531
 
400
- saveJsonFacts(modelXbrl.facts, oimFacts, None)
532
+ saveJsonFacts(factsToSave, oimFacts)
401
533
 
402
534
  # add footnotes as pseudo facts
403
535
  for ftObj in footnoteFacts:
404
- ftId = ftObj.id if ftObj.id else "f{}".format(ftObj.objectIndex)
405
- oimFacts[ftId] = oimFact = OrderedDict()
536
+ ftId = ftObj.id if ftObj.id else f"f{ftObj.objectIndex}"
537
+ oimFacts[ftId] = oimFact = {}
406
538
  oimFact["value"] = ftObj.viewText()
407
- oimFact["dimensions"] = OrderedDict((("concept", "xbrl:note"),
408
- ("noteId", ftId)))
539
+ oimFact["dimensions"] = {
540
+ "concept": "xbrl:note",
541
+ "noteId": ftId,
542
+ }
409
543
  if ftObj.xmlLang:
410
544
  oimFact["dimensions"]["language"] = ftObj.xmlLang.lower()
411
545
 
@@ -414,55 +548,51 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
414
548
  if extensionReportFinalizeMethod:
415
549
  extensionReportFinalizeMethod(oimReport)
416
550
 
417
- if outputZip:
418
- fh = io.StringIO()
419
- else:
420
- fh = open(oimFile, "w", encoding="utf-8")
421
- fh.write(json.dumps(oimReport, indent=1))
422
- if outputZip:
423
- fh.seek(0)
424
- outputZip.writestr(os.path.basename(oimFile),fh.read())
425
- fh.close()
551
+ with io.StringIO() if outputZip else open(oimFile, "w", encoding="utf-8") as fh:
552
+ fh.write(json.dumps(oimReport, indent=1))
553
+ if outputZip:
554
+ fh.seek(0)
555
+ outputZip.writestr(os.path.basename(oimFile), fh.read())
556
+ if not outputZip:
557
+ modelXbrl.modelManager.cntlr.showStatus(_("Saved JSON OIM file {}").format(oimFile))
426
558
 
427
559
  elif isCSVorXL:
428
560
  # save CSV
429
- oimReport["tables"] = oimTables = OrderedDict()
430
- oimReport["tableTemplates"] = csvTableTemplates = OrderedDict()
431
- oimTables["facts"] = csvTable = OrderedDict()
561
+ oimReport["tables"] = oimTables = {}
562
+ oimReport["tableTemplates"] = csvTableTemplates = {}
563
+ oimTables["facts"] = csvTable = {}
432
564
  csvTable["template"] = "facts"
433
565
  csvTable["url"] = "tbd"
434
- csvTableTemplates["facts"] = csvTableTemplate = OrderedDict()
566
+ csvTableTemplates["facts"] = csvTableTemplate = {}
435
567
  csvTableTemplate["rowIdColumn"] = "id"
436
- csvTableTemplate["dimensions"] = csvTableDimensions = OrderedDict()
437
- csvTableTemplate["columns"] = csvFactColumns = OrderedDict()
568
+ csvTableTemplate["dimensions"] = csvTableDimensions = {}
569
+ csvTableTemplate["columns"] = csvFactColumns = {}
570
+ csvLinks = {}
438
571
  if footnotesRelationshipSet.modelRelationships:
439
- csvLinks = OrderedDict()
440
572
  oimReport["links"] = csvLinks
441
573
  aspectQnCol = {}
442
574
  aspectsHeader = []
443
- factsColumns = []
444
575
 
445
- def addAspectQnCol(aspectQn):
576
+ def addAspectQnCol(aspectQn: QName | str) -> None:
446
577
  colQName = str(aspectQn).replace("xbrl:", "")
447
578
  colNCName = colQName.replace(":", "_")
448
579
  if colNCName not in aspectQnCol:
449
580
  aspectQnCol[colNCName] = len(aspectsHeader)
450
581
  aspectsHeader.append(colNCName)
451
582
  if colNCName == "value":
452
- csvFactColumns[colNCName] = col = OrderedDict()
453
- col["dimensions"] = OrderedDict()
583
+ csvFactColumns[colNCName] = col = {}
584
+ col["dimensions"] = {}
454
585
  elif colNCName == "id":
455
- csvFactColumns[colNCName] = {} # empty object
586
+ csvFactColumns[colNCName] = {} # empty object
456
587
  elif colNCName == "decimals":
457
- csvFactColumns[colNCName] = {} # empty object
588
+ csvFactColumns[colNCName] = {} # empty object
458
589
  csvTableTemplate[colQName] = "$" + colNCName
459
590
  else:
460
- csvFactColumns[colNCName] = {} # empty object
591
+ csvFactColumns[colNCName] = {} # empty object
461
592
  csvTableDimensions[colQName] = "$" + colNCName
462
593
 
463
-
464
594
  # pre-ordered aspect columns
465
- #if hasId:
595
+ # if hasId:
466
596
  addAspectQnCol("id")
467
597
  addAspectQnCol(qnOimConceptAspect)
468
598
  if hasNumeric:
@@ -478,9 +608,10 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
478
608
  addAspectQnCol(aspectQn)
479
609
  addAspectQnCol("value")
480
610
 
481
- def aspectCols(fact):
482
- cols = [None for i in range(len(aspectsHeader))]
483
- def setColValues(aspects):
611
+ def aspectCols(fact: ModelFact) -> list[Any]:
612
+ cols: list[Any] = [None] * len(aspectsHeader)
613
+
614
+ def setColValues(aspects: dict[str, Any]) -> None:
484
615
  for aspectQn, aspectValue in aspects.items():
485
616
  colQName = str(aspectQn).replace("xbrl:", "")
486
617
  colNCName = colQName.replace(":", "_")
@@ -496,209 +627,369 @@ def saveLoadableOIM(modelXbrl, oimFile, outputZip=None,
496
627
  else:
497
628
  _aspectValue = aspectValue
498
629
  cols[aspectQnCol[colNCName]] = _aspectValue
630
+
499
631
  setColValues(factAspects(fact))
500
632
  return cols
501
633
 
502
634
  # metadata
503
635
 
504
- _open = _writerow = _close = None
505
636
  if isCSV:
506
- if oimFile.endswith("-facts.csv"): # strip -facts.csv if a prior -facts.csv file was chosen
637
+ if oimFile.endswith("-facts.csv"): # strip -facts.csv if a prior -facts.csv file was chosen
507
638
  _baseURL = oimFile[:-10]
508
639
  elif oimFile.endswith(".csv"):
509
640
  _baseURL = oimFile[:-4]
510
641
  else:
511
642
  _baseURL = oimFile
512
- _csvinfo = {} # open file, writer
513
- def _open(filesuffix, tabname, csvTable=None):
514
- _filename = _baseURL + filesuffix
643
+ _csvInfo = {} # open file, writer
644
+
645
+ def _open(filesuffix: str | None, tabname: str, csvTable: dict[str, Any] | None = None) -> None:
646
+ _filename = _baseURL if filesuffix is None else _baseURL + filesuffix
515
647
  if csvTable is not None:
516
- csvTable["url"] = os.path.basename(_filename) # located in same directory with metadata
517
- _csvinfo["file"] = open(_filename, csvOpenMode, newline=csvOpenNewline, encoding='utf-8-sig')
518
- _csvinfo["writer"] = csv.writer(_csvinfo["file"], dialect="excel")
519
- def _writerow(row, header=False):
520
- _csvinfo["writer"].writerow(row)
521
- def _close():
522
- _csvinfo["file"].close()
523
- _csvinfo.clear()
648
+ csvTable["url"] = os.path.basename(_filename) # located in same directory with metadata
649
+ _csvInfo["file"] = open(_filename, csvOpenMode, newline=csvOpenNewline, encoding="utf-8-sig")
650
+ _csvInfo["writer"] = csv.writer(_csvInfo["file"], dialect="excel")
651
+
652
+ def _writerow(row: Iterable[str], header: bool = False) -> None:
653
+ _csvInfo["writer"].writerow(row)
654
+
655
+ def _close() -> None:
656
+ _csvInfo["file"].close()
657
+ _csvInfo.clear()
524
658
  elif isXL:
525
- headerWidths = {"concept": 40, "decimals": 8, "language": 9, "value": 50,
526
- "entity": 20, "period": 20, "unit": 20, "metadata": 100}
527
- from openpyxl import Workbook
528
- from openpyxl.cell.cell import WriteOnlyCell
529
- from openpyxl.styles import Font, PatternFill, Border, Alignment, Color, fills, Side
530
- from openpyxl.worksheet.dimensions import ColumnDimension
531
- hdrCellFill = PatternFill(patternType=fills.FILL_SOLID, fgColor=Color("00FFBF5F")) # Excel's light orange fill color = 00FF990
659
+ headerWidths = {
660
+ "concept": 40,
661
+ "decimals": 8,
662
+ "language": 9,
663
+ "value": 50,
664
+ "entity": 20,
665
+ "period": 20,
666
+ "unit": 20,
667
+ "metadata": 100,
668
+ }
669
+
670
+ # Excel's light orange fill color = 00FF990
671
+ hdrCellFill = PatternFill(patternType=fills.FILL_SOLID, fgColor=Color("00FFBF5F"))
532
672
  workbook = Workbook()
533
673
  # remove pre-existing worksheets
534
- while len(workbook.worksheets)>0:
674
+ while len(workbook.worksheets) > 0:
535
675
  workbook.remove(workbook.worksheets[0])
536
- _xlinfo = {} # open file, writer
537
- def _open(filesuffix, tabname, csvTable=None):
676
+ _xlInfo = {} # open file, writer
677
+
678
+ def _open(filesuffix: str | None, tabname: str, csvTable: dict[str, Any] | None = None) -> None:
538
679
  if csvTable is not None:
539
680
  csvTable["url"] = tabname + "!"
540
- _xlinfo["ws"] = workbook.create_sheet(title=tabname)
541
- def _writerow(rowvalues, header=False):
681
+ _xlInfo["ws"] = workbook.create_sheet(title=tabname)
682
+
683
+ def _writerow(rowvalues: Iterable[str], header: bool = False) -> None:
542
684
  row = []
543
- _ws = _xlinfo["ws"]
685
+ _ws = _xlInfo["ws"]
544
686
  for i, v in enumerate(rowvalues):
545
687
  cell = WriteOnlyCell(_ws, value=v)
546
688
  if header:
547
689
  cell.fill = hdrCellFill
548
690
  cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
549
- colLetter = chr(ord('A') + i)
691
+ colLetter = chr(ord("A") + i)
550
692
  _ws.column_dimensions[colLetter] = ColumnDimension(_ws, customWidth=True)
551
693
  _ws.column_dimensions[colLetter].width = headerWidths.get(v, 40)
552
694
 
553
695
  else:
554
- cell.alignment = Alignment(horizontal="right" if isinstance(v, Number)
555
- else "center" if isinstance(v, bool)
556
- else "left",
557
- vertical="top",
558
- wrap_text=isinstance(v, str))
696
+ cell.alignment = Alignment(
697
+ horizontal="right"
698
+ if isinstance(v, Number)
699
+ else "center"
700
+ if isinstance(v, bool)
701
+ else "left",
702
+ vertical="top",
703
+ wrap_text=isinstance(v, str),
704
+ )
559
705
  row.append(cell)
560
706
  _ws.append(row)
561
- def _close():
562
- _xlinfo.clear()
563
707
 
708
+ def _close() -> None:
709
+ _xlInfo.clear()
564
710
 
565
711
  # save facts
566
712
  _open("-facts.csv", "facts", csvTable)
567
713
  _writerow(aspectsHeader, header=True)
568
714
 
569
- def saveCSVfacts(facts):
715
+ def saveCSVfacts(facts: list[ModelFact]) -> None:
570
716
  for fact in facts:
571
717
  _writerow(aspectCols(fact))
572
718
  saveCSVfacts(fact.modelTupleFacts)
573
- saveCSVfacts(modelXbrl.facts)
719
+
720
+ saveCSVfacts(factsToSave)
574
721
  _close()
575
722
 
576
723
  # save footnotes
577
724
  if footnotesRelationshipSet.modelRelationships:
578
- footnotes = sorted((footnote
579
- for fact in modelXbrl.facts
580
- for footnote in factFootnotes(fact, csvLinks=csvLinks)),
581
- key=lambda footnote:footnote["id"])
582
- if footnotes: # text footnotes
583
- oimTables["footnotes"] = csvFtTable = OrderedDict()
584
- csvFtTable["url"] = "tbd"
585
- csvFtTable["tableDimensions"] = csvFtTableDimensions = OrderedDict()
586
- csvFtTable["factColumns"] = csvFtFactColumns = OrderedDict()
587
- csvFtFactColumns["footnote"] = csvFtValCol = OrderedDict()
588
- csvFtValCol["id"] = "$id"
589
- csvFtValCol["noteId"] = "$id"
590
- csvFtValCol["concept"] = "xbrl:note"
591
- csvFtValCol["language"] = "$language"
592
- _open("-footnotes.csv", "footnotes", csvFtTable)
725
+ footnotesDeduplicatedById = {
726
+ footnote["id"]: footnote
727
+ for fact in modelXbrl.facts
728
+ for footnote in factFootnotes(fact, csvLinks=csvLinks)
729
+ }
730
+ footnotes = sorted(footnotesDeduplicatedById.values(), key=operator.itemgetter("id"))
731
+ if footnotes: # text footnotes
732
+ footnotesTable = {"template": "footnotes"}
733
+ oimTables["footnotes"] = footnotesTable
734
+ csvTableTemplates[footnotesTable["template"]] = {
735
+ "rowIdColumn" : "id",
736
+ "dimensions": {
737
+ "language": "$language"
738
+ },
739
+ "columns": {
740
+ "id": {},
741
+ "footnote": {
742
+ "dimensions": {
743
+ "concept": "xbrl:note",
744
+ },
745
+ },
746
+ "language": {},
747
+ }
748
+ }
749
+ _open("-footnotes.csv", "footnotes", footnotesTable)
593
750
  cols = ("id", "footnote", "language")
594
751
  _writerow(cols, header=True)
595
752
  for footnote in footnotes:
596
- _writerow(tuple((footnote.get(col,"") for col in cols)))
753
+ _writerow(tuple(footnote.get(col, "") for col in cols))
597
754
  _close()
598
755
 
599
756
  # save metadata
600
757
  if isCSV:
601
- with open(_baseURL + "-metadata.json", "w", encoding="utf-8") as fh:
758
+ assert isinstance(_baseURL, str)
759
+ csvMetadataFile = _baseURL + "-metadata.json"
760
+ with open(csvMetadataFile, "w", encoding="utf-8") as fh:
602
761
  fh.write(json.dumps(oimReport, ensure_ascii=False, indent=2, sort_keys=False))
762
+ modelXbrl.modelManager.cntlr.showStatus(_("Saved CSV OIM metadata file {}").format(csvMetadataFile))
603
763
  elif isXL:
604
764
  _open(None, "metadata")
605
765
  _writerow(["metadata"], header=True)
606
766
  _writerow([json.dumps(oimReport, ensure_ascii=False, indent=1, sort_keys=False)])
607
767
  _close()
608
-
609
- if isXL:
610
768
  workbook.save(oimFile)
769
+ modelXbrl.modelManager.cntlr.showStatus(_("Saved Excel file {}").format(oimFile))
611
770
 
612
- def saveLoadableOIMMenuEntender(cntlr, menu, *args, **kwargs):
613
- # Extend menu with an item for the savedts plugin
614
- menu.add_command(label="Save Loadable OIM",
615
- underline=0,
616
- command=lambda: saveLoadableOIMMenuCommand(cntlr) )
617
771
 
618
- def saveLoadableOIMMenuCommand(cntlr):
772
+ def saveLoadableOIMMenuCommand(cntlr: CntlrWinMain) -> None:
619
773
  # save DTS menu item has been invoked
620
- if (cntlr.modelManager is None or cntlr.modelManager.modelXbrl is None or cntlr.modelManager.modelXbrl.modelDocument is None or
621
- cntlr.modelManager.modelXbrl.modelDocument.type not in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL)):
774
+ if (
775
+ cntlr.config is None
776
+ or cntlr.modelManager is None
777
+ or cntlr.modelManager.modelXbrl is None
778
+ or cntlr.modelManager.modelXbrl.modelDocument is None
779
+ or cntlr.modelManager.modelXbrl.modelDocument.type
780
+ not in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INLINEXBRLDOCUMENTSET)
781
+ ):
782
+ cntlr.addToLog(
783
+ messageCode="arelleOIMsaver",
784
+ message=_("No supported XBRL instance documents loaded that can be saved to OIM format."),
785
+ )
622
786
  return
623
787
  # get file name into which to save log file while in foreground thread
624
- oimFile = cntlr.uiFileDialog("save",
625
- title=_("arelle - Save Loadable OIM file"),
626
- initialdir=cntlr.config.setdefault("loadableExcelFileDir","."),
627
- filetypes=[(_("JSON file .json"), "*.json"), (_("CSV file .csv"), "*.csv"), (_("XLSX file .xlsx"), "*.xlsx")],
628
- defaultextension=".json")
629
- if not oimFile:
630
- return False
631
- import os
788
+ oimFile = cntlr.uiFileDialog(
789
+ "save",
790
+ title=_("arelle - Save Loadable OIM file"),
791
+ initialdir=cntlr.config.setdefault("loadableOIMFileDir", "."),
792
+ filetypes=[(_("JSON file .json"), "*.json"), (_("CSV file .csv"), "*.csv"), (_("XLSX file .xlsx"), "*.xlsx")],
793
+ defaultextension=".json",
794
+ ) # type: ignore[no-untyped-call]
795
+ if not isinstance(oimFile, str):
796
+ # User cancelled file dialog.
797
+ return
798
+
632
799
  cntlr.config["loadableOIMFileDir"] = os.path.dirname(oimFile)
633
800
  cntlr.saveConfig()
634
801
 
635
- import threading
636
- thread = threading.Thread(target=lambda
637
- _modelXbrl=cntlr.modelManager.modelXbrl,
638
- _oimFile=oimFile:
639
- saveLoadableOIM(_modelXbrl, _oimFile, None))
802
+ thread = threading.Thread(
803
+ target=lambda _modelXbrl=cntlr.modelManager.modelXbrl, _oimFile=oimFile: saveLoadableOIM(
804
+ _modelXbrl, _oimFile, None
805
+ )
806
+ )
640
807
  thread.daemon = True
641
808
  thread.start()
642
809
 
643
- def saveLoadableOIMCommandLineOptionExtender(parser, *args, **kwargs):
644
- # extend command line options with a save DTS option
645
- parser.add_option("--saveLoadableOIM",
646
- action="store",
647
- dest="saveLoadableOIM",
648
- help=_("Save Loadable OIM file (JSON, CSV or XLSX)"))
649
- parser.add_option("--saveTestcaseOIM",
650
- action="store",
651
- dest="saveTestcaseOimFileSuffix",
652
- help=_("Save Testcase Variation OIM file (argument file suffix and type, such as -savedOim.csv"))
653
-
654
- def saveLoadableOIMCaptureOptions(cntlr, options, *args, **kwargs):
655
- cntlr.modelManager.saveTestcaseOimFileSuffix = getattr(options, "saveTestcaseOimFileSuffix", None)
656
-
657
- def saveLoadableOIMCommandLineXbrlRun(cntlr, options, modelXbrl, *args, **kwargs):
658
- # extend XBRL-loaded run processing for this option
659
- oimFile = getattr(options, "saveLoadableOIM", None)
660
- if oimFile:
661
- if (modelXbrl is None or
662
- modelXbrl.modelDocument.type not in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INLINEXBRLDOCUMENTSET)):
810
+
811
+ def saveOimFiles(
812
+ cntlr: Cntlr,
813
+ modelXbrl: ModelXbrl,
814
+ oimFiles: list[str],
815
+ responseZipStream: BinaryIO | None = None,
816
+ ) -> None:
817
+ try:
818
+ if responseZipStream is None:
819
+ for oimFile in oimFiles:
820
+ saveLoadableOIM(modelXbrl, oimFile, None)
821
+ else:
822
+ with zipfile.ZipFile(responseZipStream, "a", zipfile.ZIP_DEFLATED, True) as _zip:
823
+ for oimFile in oimFiles:
824
+ saveLoadableOIM(modelXbrl, oimFile, _zip)
825
+ responseZipStream.seek(0)
826
+ except Exception as ex:
827
+ cntlr.addToLog(f"Exception saving OIM {ex}")
828
+
829
+
830
+ @dataclass
831
+ class SaveLoadableOIMPluginData(PluginData):
832
+ deduplicateFactsType: ValidateDuplicateFacts.DeduplicationType | None
833
+ saveTestcaseOimFileSuffix: str | None
834
+
835
+
836
+ class SaveLoadableOIMPlugin(PluginHooks):
837
+ @staticmethod
838
+ def cntlrCmdLineOptions(
839
+ parser: OptionParser,
840
+ *args: Any,
841
+ **kwargs: Any,
842
+ ) -> None:
843
+ parser.add_option(
844
+ "--saveLoadableOIM",
845
+ action="store",
846
+ dest="saveLoadableOIM",
847
+ help=_("Save Loadable OIM file (JSON, CSV or XLSX)"),
848
+ )
849
+ parser.add_option(
850
+ "--saveLoadableOIMDirectory",
851
+ action="store",
852
+ dest="saveLoadableOIMDirectory",
853
+ help=_("Directory to export all supported OIM formats (JSON and CSV)"),
854
+ )
855
+ parser.add_option(
856
+ "--saveTestcaseOIM",
857
+ action="store",
858
+ dest="saveTestcaseOimFileSuffix",
859
+ help=_("Save Testcase Variation OIM file (argument file suffix and type, such as -savedOim.csv"),
860
+ )
861
+ parser.add_option(
862
+ "--deduplicateOimFacts",
863
+ action="store",
864
+ choices=[a.value for a in ValidateDuplicateFacts.DeduplicationType],
865
+ dest="deduplicateOimFacts",
866
+ help=_("Remove duplicate facts when saving the OIM instance"))
867
+
868
+ @staticmethod
869
+ def cntlrCmdLineUtilityRun(
870
+ cntlr: Cntlr,
871
+ options: RuntimeOptions,
872
+ *args: Any,
873
+ **kwargs: Any,
874
+ ) -> None:
875
+ deduplicateOimFacts = cast(Optional[str], getattr(options, "deduplicateOimFacts", None))
876
+ saveTestcaseOimFileSuffix = cast(Optional[str], getattr(options, "saveTestcaseOimFileSuffix", None))
877
+ deduplicateFactsType = None
878
+ if deduplicateOimFacts is not None:
879
+ deduplicateFactsType = ValidateDuplicateFacts.DeduplicationType(deduplicateOimFacts)
880
+ pluginData = SaveLoadableOIMPluginData(PLUGIN_NAME, deduplicateFactsType, saveTestcaseOimFileSuffix)
881
+ cntlr.setPluginData(pluginData)
882
+
883
+ @staticmethod
884
+ def cntlrWinMainMenuTools(
885
+ cntlr: CntlrWinMain,
886
+ menu: Menu,
887
+ *args: Any,
888
+ **kwargs: Any,
889
+ ) -> None:
890
+ menu.add_command(label="Save Loadable OIM", underline=0, command=lambda: saveLoadableOIMMenuCommand(cntlr))
891
+
892
+ @staticmethod
893
+ def cntlrCmdLineXbrlRun(
894
+ cntlr: CntlrCmdLine,
895
+ options: RuntimeOptions,
896
+ modelXbrl: ModelXbrl,
897
+ entrypoint: dict[str, str] | None = None,
898
+ sourceZipStream: BinaryIO | None = None,
899
+ responseZipStream: BinaryIO | None = None,
900
+ *args: Any,
901
+ **kwargs: Any,
902
+ ) -> None:
903
+ # extend XBRL-loaded run processing for this option
904
+ oimFile = cast(Optional[str], getattr(options, "saveLoadableOIM", None))
905
+ allOimDirectory = cast(Optional[str], getattr(options, "saveLoadableOIMDirectory", None))
906
+ if (oimFile or allOimDirectory) and (
907
+ modelXbrl is None
908
+ or modelXbrl.modelDocument is None
909
+ or modelXbrl.modelDocument.type
910
+ not in {
911
+ ModelDocument.Type.INSTANCE,
912
+ ModelDocument.Type.INLINEXBRL,
913
+ ModelDocument.Type.INLINEXBRLDOCUMENTSET,
914
+ }
915
+ ):
663
916
  cntlr.addToLog("No XBRL instance has been loaded.")
664
917
  return
665
- try:
666
- responseZipStream = kwargs.get("responseZipStream")
667
- if responseZipStream is not None:
668
- _zip = zipfile.ZipFile(responseZipStream, "a", zipfile.ZIP_DEFLATED, True)
669
- else:
670
- _zip = None
671
- saveLoadableOIM(modelXbrl, oimFile, _zip)
672
- if responseZipStream is not None:
673
- _zip.close()
674
- responseZipStream.seek(0)
675
- except Exception as ex:
676
- cntlr.addToLog("Exception saving OIM {}".format(ex))
918
+ if oimFile:
919
+ saveOimFiles(cntlr, modelXbrl, [oimFile], responseZipStream)
920
+ if allOimDirectory:
921
+ oimDir = Path(allOimDirectory)
922
+ try:
923
+ oimDir.mkdir(parents=True, exist_ok=True)
924
+ except OSError as err:
925
+ cntlr.addToLog(
926
+ _("Unable to save OIM files into requested directory: {}, {}").format(allOimDirectory, err.strerror)
927
+ )
928
+ return
929
+ assert modelXbrl.modelDocument is not None
930
+ basefileStem = None
931
+ if hasattr(modelXbrl, "ixdsTarget"):
932
+ ixdsTarget = modelXbrl.ixdsTarget
933
+ for doc in modelXbrl.modelDocument.referencesDocument:
934
+ if doc.type in {ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INSTANCE}:
935
+ instanceFilename = Path(doc.uri)
936
+ if ixdsTarget is not None:
937
+ basefileStem = f"{instanceFilename.stem}.{ixdsTarget}"
938
+ else:
939
+ basefileStem = instanceFilename.stem
940
+ break
941
+ if basefileStem is None:
942
+ basefileStem = Path(modelXbrl.modelDocument.basename).stem
943
+ oimFiles = [str(oimDir.joinpath(basefileStem + ext)) for ext in (".csv", ".json")]
944
+ saveOimFiles(cntlr, modelXbrl, oimFiles, responseZipStream)
945
+
946
+ @staticmethod
947
+ def testcaseVariationValidated(
948
+ testcaseDTS: ModelXbrl,
949
+ testInstanceDTS: ModelXbrl,
950
+ extraErrors: list[str],
951
+ *args: Any,
952
+ **kwargs: Any,
953
+ ) -> None:
954
+ pluginData = testcaseDTS.modelManager.cntlr.getPluginData(PLUGIN_NAME)
955
+ oimFileSuffix = (
956
+ pluginData.saveTestcaseOimFileSuffix if isinstance(pluginData, SaveLoadableOIMPluginData) else None
957
+ )
958
+ if (
959
+ oimFileSuffix
960
+ and testInstanceDTS is not None
961
+ and testInstanceDTS.modelDocument is not None
962
+ and testInstanceDTS.modelDocument.type
963
+ in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INLINEXBRLDOCUMENTSET)
964
+ and not any(oimErrorPattern.match(error) for error in testInstanceDTS.errors if error is not None)
965
+ ): # no OIM errors
966
+ try:
967
+ saveLoadableOIM(testInstanceDTS, testInstanceDTS.modelDocument.uri + oimFileSuffix)
968
+ except Exception as ex:
969
+ testcaseDTS.modelManager.cntlr.addToLog(f"Exception saving OIM {ex}")
677
970
 
678
- oimErrorPattern = re.compile("oime|oimce|xbrlje|xbrlce")
971
+ @staticmethod
972
+ def saveLoadableOimSave(
973
+ modelXbrl: ModelXbrl,
974
+ oimFile: str,
975
+ *args: Any,
976
+ **kwargs: Any,
977
+ ) -> None:
978
+ return saveLoadableOIM(modelXbrl, oimFile, *args, **kwargs)
679
979
 
680
- def saveLoadableOIMAfterTestcaseValidated(testcaseDTS, testInstanceDTS, extraErrors, *args, **kwargs):
681
- oimFileSuffix = getattr(testcaseDTS.modelManager, "saveTestcaseOimFileSuffix", None)
682
- if (oimFileSuffix and testInstanceDTS is not None and
683
- testInstanceDTS.modelDocument.type in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INLINEXBRLDOCUMENTSET) and
684
- not any(oimErrorPattern.match(error) for error in testInstanceDTS.errors)): # no OIM errors
685
- try:
686
- saveLoadableOIM(testInstanceDTS, testInstanceDTS.modelDocument.uri + oimFileSuffix)
687
- except Exception as ex:
688
- cntlr.addToLog("Exception saving OIM {}".format(ex))
689
980
 
690
981
  __pluginInfo__ = {
691
- 'name': 'Save Loadable OIM',
692
- 'version': '1.2',
693
- 'description': "This plug-in saves XBRL in OIM JSON, CSV or XLSX that can be re-loaded per se.",
694
- 'license': 'Apache-2',
695
- 'author': authorLabel,
696
- 'copyright': copyrightLabel,
982
+ "name": PLUGIN_NAME,
983
+ "version": "1.3",
984
+ "description": "This plug-in saves XBRL in OIM JSON, CSV or XLSX that can be re-loaded per se.",
985
+ "license": "Apache-2",
986
+ "author": authorLabel,
987
+ "copyright": copyrightLabel,
697
988
  # classes of mount points (required)
698
- 'CntlrWinMain.Menu.Tools': saveLoadableOIMMenuEntender,
699
- 'CntlrCmdLine.Options': saveLoadableOIMCommandLineOptionExtender,
700
- 'CntlrCmdLine.Utility.Run': saveLoadableOIMCaptureOptions,
701
- 'CntlrCmdLine.Xbrl.Run': saveLoadableOIMCommandLineXbrlRun,
702
- 'TestcaseVariation.Validated': saveLoadableOIMAfterTestcaseValidated,
703
- 'SaveLoadableOim.Save': saveLoadableOIM,
989
+ "CntlrWinMain.Menu.Tools": SaveLoadableOIMPlugin.cntlrWinMainMenuTools,
990
+ "CntlrCmdLine.Options": SaveLoadableOIMPlugin.cntlrCmdLineOptions,
991
+ "CntlrCmdLine.Utility.Run": SaveLoadableOIMPlugin.cntlrCmdLineUtilityRun,
992
+ "CntlrCmdLine.Xbrl.Run": SaveLoadableOIMPlugin.cntlrCmdLineXbrlRun,
993
+ "TestcaseVariation.Validated": SaveLoadableOIMPlugin.testcaseVariationValidated,
994
+ "SaveLoadableOim.Save": SaveLoadableOIMPlugin.saveLoadableOimSave,
704
995
  }