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
arelle/WebCache.py CHANGED
@@ -6,20 +6,42 @@ e.g., User-Agent: Sample Company Name AdminContact@<sample company domain>.com
6
6
 
7
7
  '''
8
8
  from __future__ import annotations
9
- from typing import TYPE_CHECKING, Any, Optional
10
- import os, posixpath, sys, time, calendar, io, json, logging, shutil, zlib
11
- import regex as re
12
- from urllib.parse import quote, unquote
13
- from urllib.error import URLError, HTTPError, ContentTooShortError
9
+
10
+ import calendar
11
+ import contextlib
12
+ import io
13
+ import json
14
+ import logging
15
+ import os
16
+ import posixpath
17
+ import shutil
18
+ import sys
19
+ import time
20
+ import zlib
14
21
  from http.client import IncompleteRead
22
+ from pathlib import Path
23
+ from typing import TYPE_CHECKING, Any
15
24
  from urllib import request as proxyhandlers
25
+ from urllib.error import ContentTooShortError, HTTPError, URLError
26
+ from urllib.parse import quote, unquote, urlsplit, urlunsplit
16
27
 
17
28
  import certifi
29
+ import regex as re
30
+ from filelock import FileLock, Timeout
31
+
32
+ from arelle.PythonUtil import isLegacyAbs
18
33
 
19
34
  try:
20
35
  import ssl
21
36
  except ImportError:
22
37
  ssl = None
38
+
39
+ try:
40
+ import truststore
41
+ except ImportError:
42
+ # truststore requires Python > 3.9
43
+ truststore = None
44
+
23
45
  from arelle.FileSource import SERVER_WEB_CACHE, archiveFilenameParts
24
46
  from arelle.PluginManager import pluginClassMethods
25
47
  from arelle.UrlUtil import isHttpUrl
@@ -31,9 +53,23 @@ if TYPE_CHECKING:
31
53
  addServerWebCache = None
32
54
 
33
55
  DIRECTORY_INDEX_FILE = "!~DirectoryIndex~!"
56
+ FILE_LOCK_TIMEOUT = 30
34
57
  INF = float("inf")
35
58
  RETRIEVAL_RETRY_COUNT = 5
36
- HTTP_USER_AGENT = 'Mozilla/5.0 (Arelle/{})'.format(__version__)
59
+ HTTP_USER_AGENT = 'Mozilla/5.0 (Arelle/{}) Email/NotRegistered@arelle.org'.format(__version__)
60
+
61
+ # The xbrl.org server accepts requests for both http and https as well as with or without the WWW subdomain.
62
+ # Don't require duplicating these files in the cache.
63
+ _XBRL_ORG_URL_PREFIXES = frozenset([
64
+ "http://www.xbrl.org/",
65
+ "http://xbrl.org/",
66
+ "https://www.xbrl.org/",
67
+ "https://xbrl.org/",
68
+ ])
69
+ XBRL_ORG_CACHE_REDIRECTS = {
70
+ prefix: _XBRL_ORG_URL_PREFIXES.difference({prefix})
71
+ for prefix in _XBRL_ORG_URL_PREFIXES
72
+ }
37
73
 
38
74
  def proxyDirFmt(httpProxyTuple):
39
75
  if isinstance(httpProxyTuple,(tuple,list)) and len(httpProxyTuple) == 5:
@@ -94,6 +130,7 @@ class WebCache:
94
130
  self._noCertificateCheck = False
95
131
  self._httpUserAgent = HTTP_USER_AGENT # default user agent for product
96
132
  self._httpsRedirect = False
133
+ self._redirectFallbackMap = {}
97
134
  self.resetProxies(httpProxyTuple)
98
135
 
99
136
  self.opener.addheaders = [('User-agent', self.httpUserAgent)]
@@ -113,6 +150,7 @@ class WebCache:
113
150
  self.encodeFileChars = re.compile(r'[<>:"\\|?*^]')
114
151
  else:
115
152
  self.encodeFileChars = re.compile(r'[:^]')
153
+ self.builtInCacheDir = os.path.abspath(os.path.join(__file__, '..', 'resources', 'cache'))
116
154
  self.decodeFileChars = re.compile(r'\^[0-9]{3}')
117
155
  self.workOffline: bool = False
118
156
  self._logDownloads = False
@@ -206,6 +244,9 @@ class WebCache:
206
244
  def httpsRedirect(self, value):
207
245
  self._httpsRedirect = value
208
246
 
247
+ def redirectFallback(self, matchPattern: re.Pattern, replaceFormat: str):
248
+ self._redirectFallbackMap[matchPattern] = replaceFormat
249
+
209
250
  def resetProxies(self, httpProxyTuple):
210
251
  # for ntlm user and password are required
211
252
  self.hasNTLM = False
@@ -241,12 +282,10 @@ class WebCache:
241
282
  self.http_auth_handler = proxyhandlers.HTTPBasicAuthHandler()
242
283
  proxyHandlers = [self.proxy_handler, self.proxy_auth_handler, self.http_auth_handler]
243
284
  if ssl:
244
- # Attempts to load the default CA certificates from the OS.
245
- context = ssl.create_default_context()
285
+ # Attempt to load the default CA certificates from the OS using truststore if available, else fallback to OpenSSL's default context.
286
+ context = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) if truststore else ssl.create_default_context()
246
287
  # Include certifi certificates (Mozilla’s carefully curated
247
- # collection) for systems with outdated certs and for platforms
248
- # that we're unable to load certs from (macOS and some Linux
249
- # distros.)
288
+ # collection) for systems with outdated certs.
250
289
  context.load_verify_locations(cafile=certifi.where())
251
290
  if self.noCertificateCheck: # this is required in some Akamai environments, such as sec.gov
252
291
  context.check_hostname = False
@@ -261,11 +300,37 @@ class WebCache:
261
300
  #self.opener.close()
262
301
  #self.opener = WebCacheUrlOpener(self.cntlr, proxyDirFmt(httpProxyTuple))
263
302
 
264
- def normalizeUrl(self, url: Optional[str], base: Optional[str] = None) -> Any:
303
+ def normalizeFilepath(self, filepath: str, url: str, cacheDir: str = None) -> str:
304
+ """
305
+ Perform any necessary transformations to filepath.
306
+ :param filepath: Filepath to normalize.
307
+ :param url: Original URL (for http/https redirect).
308
+ :param cacheDir: Cache root directory.
309
+ :return: Normalized filepath.
310
+ """
311
+ if cacheDir is None:
312
+ cacheDir = self.cacheDir
313
+ if self.httpsRedirect:
314
+ if not os.path.exists(filepath):
315
+ # if enabled, check for missing files in their inverse http/https cache directory
316
+ redirect = None
317
+ if url.startswith('http://'):
318
+ redirect = self.urlToCacheFilepath('https' + url[4:], cacheDir=cacheDir)
319
+ elif url.startswith('https://'):
320
+ redirect = self.urlToCacheFilepath('http' + url[5:], cacheDir=cacheDir)
321
+ if redirect and os.path.exists(redirect):
322
+ filepath = redirect
323
+ if filepath.endswith("/"):
324
+ filepath += DIRECTORY_INDEX_FILE
325
+ if os.sep == '\\':
326
+ filepath = filepath.replace('/', '\\')
327
+ return filepath
328
+
329
+ def normalizeUrl(self, url: str | None, base: str | None = None) -> Any:
265
330
  if url:
266
331
  if url.startswith("file://"): url = url[7:]
267
332
  elif url.startswith("file:\\"): url = url[6:]
268
- if url and not (isHttpUrl(url) or os.path.isabs(url)):
333
+ if url and not (isHttpUrl(url) or isLegacyAbs(url)):
269
334
  if base is not None and not isHttpUrl(base) and '%' in url:
270
335
  url = unquote(url)
271
336
  if base:
@@ -282,7 +347,7 @@ class WebCache:
282
347
  elif normedPath.startswith("file:\\"): normedPath = normedPath[6:]
283
348
 
284
349
  # no base, not normalized, must be relative to current working directory
285
- if base is None and not os.path.isabs(url):
350
+ if base is None and not isLegacyAbs(url):
286
351
  normedPath = os.path.abspath(normedPath)
287
352
  else:
288
353
  normedPath = url
@@ -301,9 +366,70 @@ class WebCache:
301
366
  def encodeForFilename(self, pathpart):
302
367
  return self.encodeFileChars.sub(lambda m: '^{0:03}'.format(ord(m.group(0))), pathpart)
303
368
 
304
- def urlToCacheFilepath(self, url: str) -> str:
369
+ def _fallbackRedirect(self, url: str, originalFilepath: str, cacheDir: str) -> str:
370
+ """
371
+ If the original URL does not map to an existing cache file,
372
+ we'll check each fallback redirect pattern to see if modifying
373
+ the URL yields a path to a file that does exist in the cache.
374
+ If none is found, the original filepath is returned.
375
+ :param url: The requested URL.
376
+ :param originalFilepath: The original mapped filepath.
377
+ :return: An existing redirected path or the original filepath.
378
+ """
379
+ if os.path.exists(originalFilepath):
380
+ return originalFilepath
381
+ for fromPattern, toPattern in self._redirectFallbackMap.items():
382
+ match = fromPattern.match(url)
383
+ if not match:
384
+ continue
385
+ redirectUrl = toPattern.format(*match[1:])
386
+ redirectFilepath = self.urlToCacheFilepath(
387
+ redirectUrl,
388
+ cacheDir,
389
+ useRedirectFallback=False # prevent infinite recursion
390
+ )
391
+ if os.path.exists(redirectFilepath):
392
+ if self.cntlr.modelManager.modelXbrl:
393
+ self.cntlr.modelManager.modelXbrl.warning(
394
+ codes='arelle:redirectedUrl',
395
+ msg='Redirected URL from %(url)s to %(redirectUrl)s',
396
+ args={'url': url, 'redirectUrl': redirectUrl},
397
+ file=redirectUrl
398
+ )
399
+ else:
400
+ self.cntlr.addToLog(
401
+ messageCode='arelle:redirectedUrl',
402
+ message='Redirected URL from %(url)s to %(redirectUrl)s',
403
+ messageArgs={'url': url, 'redirectUrl': redirectUrl},
404
+ file=redirectUrl,
405
+ level=logging.WARNING,
406
+ )
407
+ return redirectFilepath
408
+ for fromUrlPrefix, toUrlPrefixes in XBRL_ORG_CACHE_REDIRECTS.items():
409
+ if url.startswith(fromUrlPrefix):
410
+ for toUrlPrefix in toUrlPrefixes:
411
+ redirectFilepath = self.urlToCacheFilepath(
412
+ toUrlPrefix + url[len(fromUrlPrefix):],
413
+ cacheDir,
414
+ useRedirectFallback=False
415
+ )
416
+ if os.path.exists(redirectFilepath):
417
+ return redirectFilepath
418
+ break
419
+ return originalFilepath
420
+
421
+ def urlToCacheFilepath(self, url: str, cacheDir: str | None = None, useRedirectFallback: bool = True) -> str:
422
+ """
423
+ Converts `url` into the corresponding cache filepath in `cacheDir.
424
+ :param url: URL to convert.
425
+ :param cacheDir: Cache root directory.
426
+ :param useRedirectFallback: Whether to use fallback redirects.
427
+ :return: Cache filepath.
428
+ """
429
+ if cacheDir is None:
430
+ cacheDir = self.cacheDir
305
431
  scheme, sep, path = url.partition("://")
306
- filepath = [self.cacheDir, scheme]
432
+ filepath = [cacheDir, scheme]
307
433
  pathparts = path.split('/')
308
434
  user, sep, server = pathparts[0].partition("@")
309
435
  if not sep:
@@ -318,10 +444,15 @@ class WebCache:
318
444
  filepath.extend(self.encodeForFilename(pathpart) for pathpart in pathparts[1:])
319
445
  if url.endswith("/"): # default index file
320
446
  filepath.append(DIRECTORY_INDEX_FILE)
321
- return os.sep.join(filepath)
322
-
323
- def cacheFilepathToUrl(self, cacheFilepath):
324
- urlparts = cacheFilepath[len(self.cacheDir)+1:].split(os.sep)
447
+ joined_filepath = os.sep.join(filepath)
448
+ if useRedirectFallback:
449
+ return self._fallbackRedirect(url, joined_filepath, cacheDir)
450
+ return joined_filepath
451
+
452
+ def cacheFilepathToUrl(self, cacheFilepath: str, cacheDir: str | None = None) -> str:
453
+ if cacheDir is None:
454
+ cacheDir = self.cacheDir
455
+ urlparts = cacheFilepath[len(cacheDir)+1:].split(os.sep)
325
456
  urlparts[0] += ':/' # add separator between http and file parts, less one '/'
326
457
  if len(urlparts) > 2:
327
458
  if urlparts[2].startswith("^port"):
@@ -339,271 +470,377 @@ class WebCache:
339
470
  def getfilename(
340
471
  self, url: str | None, base: str | None = None,
341
472
  reload: bool = False, checkModifiedTime: bool = False,
342
- normalize: bool = False, filenameOnly: bool = False) -> str | None:
473
+ normalize: bool = False, filenameOnly: bool = False,
474
+ allowTransformation: bool = True) -> str | None:
475
+ if allowTransformation:
476
+ for pluginXbrlMethod in pluginClassMethods("WebCache.TransformURL"):
477
+ url, final = pluginXbrlMethod(self.cntlr, url, base)
478
+ if final:
479
+ return url
343
480
  if url is None:
344
481
  return url
345
482
  if base is not None or normalize:
346
483
  url = self.normalizeUrl(url, base)
484
+
485
+ # Handle non-http, non-https URLS
347
486
  urlScheme, schemeSep, urlSchemeSpecificPart = url.partition("://")
348
- if schemeSep and urlScheme in ("http", "https"):
349
- # is this a mapped archive file contents?
350
- _archiveFileNameParts = archiveFilenameParts(url)
351
- if _archiveFileNameParts:
352
- _archiveFilename = self.getfilename(_archiveFileNameParts[0], reload=reload, checkModifiedTime=checkModifiedTime)
353
- if _archiveFilename:
354
- return os.path.join(_archiveFilename, _archiveFileNameParts[1])
355
- return None
356
- # form cache file name (substituting _ for any illegal file characters)
357
- filepath = self.urlToCacheFilepath(url)
358
- if self.httpsRedirect:
359
- if not os.path.exists(filepath):
360
- # if enabled, check for missing files in their inverse http/https cache directory
361
- redirect = None
362
- if url.startswith('http://'):
363
- redirect = self.urlToCacheFilepath('https' + url[4:])
364
- elif url.startswith('https://'):
365
- redirect = self.urlToCacheFilepath('http' + url[5:])
366
- if redirect and os.path.exists(redirect):
367
- filepath = redirect
368
- if self.cacheDir == SERVER_WEB_CACHE:
369
- # server web-cached files are downloaded when opening to prevent excessive memcache api calls
370
- return filepath
371
- # quotedUrl has scheme-specific-part quoted except for parameter separators
372
- quotedUrl = urlScheme + schemeSep + quote(urlSchemeSpecificPart, '/?=&')
373
- # handle default directory requests
374
- if filepath.endswith("/"):
375
- filepath += DIRECTORY_INDEX_FILE
487
+ if not schemeSep or urlScheme not in ("http", "https"):
488
+ if url.startswith("file://"): url = url[7:]
489
+ elif url.startswith("file:\\"): url = url[6:]
376
490
  if os.sep == '\\':
377
- filepath = filepath.replace('/', '\\')
378
- if self.workOffline or filenameOnly:
379
- return filepath
380
- filepathtmp = filepath + ".tmp"
381
- fileExt = os.path.splitext(filepath)[1]
382
- timeNow = time.time()
383
- timeNowStr = time.strftime('%Y-%m-%dT%H:%M:%S UTC', time.gmtime(timeNow))
384
- retrievingDueToRecheckInterval = False
385
- if not reload and os.path.exists(filepath):
386
- if url in self.cachedUrlCheckTimes and not checkModifiedTime:
387
- cachedTime = calendar.timegm(time.strptime(self.cachedUrlCheckTimes[url], '%Y-%m-%dT%H:%M:%S UTC'))
388
- else:
389
- cachedTime = 0
390
- if timeNow - cachedTime > self.maxAgeSeconds:
391
- # weekly check if newer file exists
392
- newerOnWeb = False
393
- try: # no provision here for proxy authentication!!!
394
- remoteFileTime = lastModifiedTime( self.getheaders(quotedUrl) )
395
- if remoteFileTime and remoteFileTime > os.path.getmtime(filepath):
396
- newerOnWeb = True
397
- except:
398
- pass # for now, forget about authentication here
399
- if not newerOnWeb:
400
- # update ctime by copying file and return old file
401
- self.cachedUrlCheckTimes[url] = timeNowStr
402
- self.cachedUrlCheckTimesModified = True
403
- return filepath
404
- retrievingDueToRecheckInterval = True
491
+ url = url.replace('/', '\\')
492
+ return url
493
+
494
+ # Handle archive URLs with recursive call
495
+ _archiveFileNameParts = archiveFilenameParts(url)
496
+ if _archiveFileNameParts:
497
+ _archiveFilename = self.getfilename(_archiveFileNameParts[0], reload=reload, checkModifiedTime=checkModifiedTime)
498
+ if _archiveFilename:
499
+ return os.path.join(_archiveFilename, _archiveFileNameParts[1])
500
+ return None
501
+
502
+ # Generate cache filepath from url
503
+ filepath = self.urlToCacheFilepath(url)
504
+
505
+ # Handle server web cache
506
+ if self.cacheDir == SERVER_WEB_CACHE:
507
+ # server web-cached files are downloaded when opening to prevent excessive memcache api calls
508
+ return filepath
509
+
510
+ # Make any necessary transformations to filepath
511
+ filepath = self.normalizeFilepath(filepath, url)
512
+ filepathExists = os.path.exists(filepath)
513
+
514
+ # If cache filepath does not exist, try built-in cache
515
+ if self.workOffline and not filepathExists:
516
+ builtInFilepath = self.normalizeFilepath(self.urlToCacheFilepath(url, cacheDir=self.builtInCacheDir), url)
517
+ if os.path.exists(builtInFilepath):
518
+ return builtInFilepath
519
+
520
+ # Return filepath now if configured not to download
521
+ if self.workOffline or filenameOnly:
522
+ return filepath
523
+
524
+ # Download without checking age if configured to do so or file does not exist
525
+ if reload or not filepathExists:
526
+ return filepath if self._downloadFileWithLock(url, filepath) else None
527
+
528
+ # Determine if file has aged out of cache, return filepath if not
529
+ if url in self.cachedUrlCheckTimes and not checkModifiedTime:
530
+ cachedTime = calendar.timegm(time.strptime(self.cachedUrlCheckTimes[url], '%Y-%m-%dT%H:%M:%S UTC'))
531
+ else:
532
+ cachedTime = 0
533
+ timeNow = time.time()
534
+ if timeNow - cachedTime <= self.maxAgeSeconds:
535
+ return filepath
536
+
537
+ # If we determine that the web version is newer, download it
538
+ if self._checkIfNewerOnWeb(url, filepath):
539
+ self._downloadFileWithLock(url, filepath, retrievingDueToRecheckInterval=True)
540
+ # Whether the download is successful or not, we know `filepath` exists, so return it.
541
+ return filepath
542
+ # Otherwise, use existing file
543
+ self.cachedUrlCheckTimes[url] = WebCache._getTimeString(timeNow)
544
+ self.cachedUrlCheckTimesModified = True
545
+ return filepath
546
+
547
+ def _checkIfNewerOnWeb(self, url: str, filepath: str) -> bool:
548
+ """
549
+
550
+ :param url: URL to retrieve web timestamp from
551
+ :param filepath: Filepath to retrieve local timestamp from
552
+ :return:
553
+ """
554
+ # quotedUrl has scheme-specific-part quoted except for parameter separators
555
+ quotedUrl = WebCache._quotedUrl(url)
556
+ try: # no provision here for proxy authentication!!!
557
+ remoteFileTime = lastModifiedTime(self.getheaders(quotedUrl))
558
+ if remoteFileTime and remoteFileTime > os.path.getmtime(filepath):
559
+ return True
560
+ except:
561
+ pass # for now, forget about authentication here
562
+ return False
563
+
564
+ @staticmethod
565
+ def _getTimeString(timeValue: time.time) -> str:
566
+ """
567
+ :param timeValue:
568
+ :return: UTC-formatted string representation of `timeValue`
569
+ """
570
+ return time.strftime('%Y-%m-%dT%H:%M:%S UTC', time.gmtime(timeValue))
571
+
572
+ @staticmethod
573
+ def _quotedUrl(url: str) -> str:
574
+ """
575
+ :param url:
576
+ :return: `url` with scheme-specific-part quoted except for parameter separators
577
+ """
578
+ parts = urlsplit(url)
579
+
580
+ # RFC 3986 safe characters: https://www.ietf.org/rfc/rfc3986.txt
581
+ pathSafe = "/:@!$&'()*+,;=" # path allows sub-delims, ":" and "@"
582
+ querySafe = "&=:/?@!$'()*+,;[]" # query allows pchar + "/" + "?"
583
+
584
+ quotedPath = quote(parts.path, safe=pathSafe)
585
+ quotedQuery = quote(parts.query, safe=querySafe)
586
+
587
+ return urlunsplit((parts.scheme, parts.netloc, quotedPath, quotedQuery, parts.fragment))
588
+
589
+ @staticmethod
590
+ def _getFileTimestamp(path: str) -> float:
591
+ try:
592
+ stats = Path(path).stat()
593
+ return max(stats.st_ctime, stats.st_mtime)
594
+ except FileNotFoundError:
595
+ return 0
596
+
597
+ def _downloadFileWithLock(
598
+ self,
599
+ url: str,
600
+ filepath: str,
601
+ retrievingDueToRecheckInterval: bool = False,
602
+ retryCount: int = 5) -> bool:
603
+ before_timestamp = WebCache._getFileTimestamp(filepath)
604
+ fileInCache = False
605
+ lock = FileLock(filepath + '.lock', timeout=FILE_LOCK_TIMEOUT)
606
+ try:
607
+ with lock.acquire():
608
+ after_timestamp = WebCache._getFileTimestamp(filepath)
609
+ if after_timestamp > before_timestamp:
610
+ # Another process just downloaded the file, use it instead.
611
+ fileInCache = True
405
612
  else:
406
- return filepath
407
- filedir = os.path.dirname(filepath)
408
- if not os.path.exists(filedir):
409
- os.makedirs(filedir)
410
- # Retrieve over HTTP and cache, using rename to avoid collisions
411
- # self.modelManager.addToLog('web caching: {0}'.format(url))
412
-
413
- # download to a temporary name so it is not left readable corrupted if download fails
414
- retryCount = 5
415
- while retryCount > 0:
416
- try:
417
- self.progressUrl = url
418
- savedfile, headers, initialBytes = self.retrieve(
613
+ fileInCache = self._downloadFile(url, filepath, retrievingDueToRecheckInterval, retryCount)
614
+ # Clean up the lock file. The lock context manager releases the file lock but does not delete the lock file.
615
+ # There is a minor race condition when multiple Arelle processes run concurrently. One process may release
616
+ # its lock, and another may acquire it before the first process can delete the lock file. In this case, the
617
+ # first process will suppress the OSError and continue, while the second process will skip downloading the
618
+ # file because the file timestamp has updated, and then remove the lock file before returning.
619
+ with contextlib.suppress(OSError):
620
+ os.remove(lock.lock_file)
621
+ except Timeout:
622
+ self.cntlr.addToLog(_("Unable to obtain exclusive write access to download file. Delete file and retry: %(lockfile)s"),
623
+ messageCode="webCache:cacheFileLocked",
624
+ messageArgs={"lockfile": lock.lock_file},
625
+ level=logging.ERROR)
626
+ return fileInCache
627
+
628
+ def _downloadFile(
629
+ self,
630
+ url: str,
631
+ filepath: str,
632
+ retrievingDueToRecheckInterval: bool = False,
633
+ retryCount: int = 5) -> bool:
634
+ """
635
+ Downloads the file at `url` to a temporary location before copying it to `filepath`.
636
+ :param url: Web resource to download.
637
+ :param filepath: End destination for downloaded file.
638
+ :param retrievingDueToRecheckInterval: Determines how errors are handled when download is part of a cache recheck.
639
+ :param retryCount: Number of times to retry download.
640
+ :return: Whether `filepath` should now be used.
641
+ """
642
+ temporaryFilename = Path(f'{filepath}.tmp')
643
+ fileExt = os.path.splitext(filepath)[1]
644
+ timeNowStr = WebCache._getTimeString(time.time())
645
+ quotedUrl = WebCache._quotedUrl(url)
646
+
647
+ filedir = os.path.dirname(filepath)
648
+ os.makedirs(filedir, exist_ok=True)
649
+ # Retrieve over HTTP and cache, using rename to avoid collisions
650
+ # self.modelManager.addToLog('web caching: {0}'.format(url))
651
+
652
+ # download to a temporary name so it is not left readable corrupted if download fails
653
+ while retryCount > 0:
654
+ try:
655
+ self.progressUrl = url
656
+ savedfile, headers, initialBytes = self.retrieve(
419
657
  #savedfile, headers = self.opener.retrieve(
420
- quotedUrl,
421
- filename=filepathtmp,
422
- reporthook=self.reportProgress)
423
-
424
- # check if this is a real file or a wifi or web logon screen
425
- if fileExt in {".xsd", ".xml", ".xbrl"}:
426
- if b"<html" in initialBytes:
427
- if retrievingDueToRecheckInterval:
428
- return self.internetRecheckFailedRecovery(filepath, url,
429
- "file contents appear to be an html logon request",
430
- timeNowStr)
431
- response = None # found possible logon request
432
- if self.cntlr.hasGui:
433
- response = self.cntlr.internet_logon(url, quotedUrl,
434
- _("Unexpected HTML in {0}").format(url),
435
- _("Is this a logon page? If so, click 'yes', else click 'no' if it is the expected XBRL content, or 'cancel' to abort retrieval: \n\n{0}")
436
- .format(initialBytes[:1500]))
437
- if response == "retry":
438
- retryCount -= 1
439
- continue
440
- elif response != "no":
441
- self.cntlr.addToLog(_("Web file appears to be an html logon request, not retrieved: %(URL)s \nContents: \n%(contents)s"),
442
- messageCode="webCache:invalidRetrieval",
443
- messageArgs={"URL": url, "contents": initialBytes},
444
- level=logging.ERROR)
445
- return None
658
+ quotedUrl,
659
+ filename=str(temporaryFilename),
660
+ reporthook=self.reportProgress)
446
661
 
447
- retryCount = 0
448
- except (ContentTooShortError, IncompleteRead) as err:
449
- if retrievingDueToRecheckInterval:
450
- return self.internetRecheckFailedRecovery(filepath, url, err, timeNowStr)
451
- if retryCount > 1:
452
- self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s \n%(retryCount)s retries remaining"),
453
- messageCode="webCache:retryingOperation",
454
- messageArgs={"error": err, "URL": url, "retryCount": retryCount},
455
- level=logging.ERROR)
456
- retryCount -= 1
457
- continue
458
- self.cntlr.addToLog(_("%(error)s \nretrieving %(URL)s"),
459
- messageCode="webCache:contentTooShortError",
460
- messageArgs={"URL": url, "error": err},
461
- level=logging.ERROR)
462
- if os.path.exists(filepathtmp):
463
- os.remove(filepathtmp)
464
- return None
465
- # handle file is bad
466
- except (HTTPError, URLError) as err:
467
- try:
468
- tryWebAuthentication = False
469
- if isinstance(err, HTTPError) and err.code == 401:
470
- tryWebAuthentication = True
471
- if 'www-authenticate' in err.hdrs:
472
- match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', err.hdrs['www-authenticate'])
473
- if match:
474
- scheme, realm = match.groups()
475
- if scheme.lower() == 'basic':
476
- host = os.path.dirname(quotedUrl)
477
- userPwd = self.cntlr.internet_user_password(host, realm)
478
- if isinstance(userPwd,(tuple,list)):
479
- self.http_auth_handler.add_password(realm=realm,uri=host,user=userPwd[0],passwd=userPwd[1])
480
- retryCount -= 1
481
- continue
482
- self.cntlr.addToLog(_("'%(scheme)s' www-authentication for realm '%(realm)s' is required to access %(URL)s\n%(error)s"),
483
- messageCode="webCache:unsupportedWWWAuthentication",
484
- messageArgs={"scheme": scheme, "realm": realm, "URL": url, "error": err},
485
- level=logging.ERROR)
486
- elif isinstance(err, HTTPError) and err.code == 407:
487
- tryWebAuthentication = True
488
- if 'proxy-authenticate' in err.hdrs:
489
- match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', err.hdrs['proxy-authenticate'])
490
- if match:
491
- scheme, realm = match.groups()
492
- host = self.proxy_handler.proxies.get('http')
493
- if scheme.lower() == 'basic':
494
- userPwd = self.cntlr.internet_user_password(host, realm)
495
- if isinstance(userPwd,(tuple,list)):
496
- self.proxy_auth_handler.add_password(realm=realm,uri=host,user=userPwd[0],passwd=userPwd[1])
497
- retryCount -= 1
498
- continue
499
- self.cntlr.addToLog(_("'%(scheme)s' proxy-authentication for realm '%(realm)s' is required to access %(URL)s\n%(error)s"),
500
- messageCode="webCache:unsupportedProxyAuthentication",
501
- messageArgs={"scheme": scheme, "realm": realm, "URL": url, "error": err},
502
- level=logging.ERROR)
662
+ # check if this is a real file or a wifi or web logon screen
663
+ if fileExt in {".xsd", ".xml", ".xbrl"}:
664
+ if b"<html" in initialBytes:
503
665
  if retrievingDueToRecheckInterval:
504
- return self.internetRecheckFailedRecovery(filepath, url, err, timeNowStr)
505
- if tryWebAuthentication:
506
- # check if single signon is requested (on first retry)
507
- if retryCount == RETRIEVAL_RETRY_COUNT:
508
- for pluginXbrlMethod in pluginClassMethods("Proxy.HTTPAuthenticate"):
509
- if pluginXbrlMethod(self.cntlr): # true if succeessful single sign on
666
+ err = "file contents appear to be an html logon request"
667
+ self.internetRecheckFailedRecovery(url, err, timeNowStr)
668
+ return True
669
+ response = None # found possible logon request
670
+ if self.cntlr.hasGui:
671
+ response = self.cntlr.internet_logon(url, quotedUrl,
672
+ _("Unexpected HTML in {0}").format(url),
673
+ _("Is this a logon page? If so, click 'yes', else click 'no' if it is the expected XBRL content, or 'cancel' to abort retrieval: \n\n{0}")
674
+ .format(initialBytes[:1500]))
675
+ if response == "retry":
676
+ retryCount -= 1
677
+ continue
678
+ elif response != "no":
679
+ self.cntlr.addToLog(_("Web file appears to be an html logon request, not retrieved: %(URL)s \nContents: \n%(contents)s"),
680
+ messageCode="webCache:invalidRetrieval",
681
+ messageArgs={"URL": url, "contents": initialBytes},
682
+ level=logging.ERROR)
683
+ return False
684
+
685
+ retryCount = 0
686
+ except (ContentTooShortError, IncompleteRead) as err:
687
+ if retrievingDueToRecheckInterval:
688
+ self.internetRecheckFailedRecovery(url, err, timeNowStr)
689
+ return True
690
+ if retryCount > 1:
691
+ self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s \n%(retryCount)s retries remaining"),
692
+ messageCode="webCache:retryingOperation",
693
+ messageArgs={"error": err, "URL": url, "retryCount": retryCount},
694
+ level=logging.ERROR)
695
+ retryCount -= 1
696
+ continue
697
+ self.cntlr.addToLog(_("%(error)s \nretrieving %(URL)s"),
698
+ messageCode="webCache:contentTooShortError",
699
+ messageArgs={"URL": url, "error": err},
700
+ level=logging.ERROR)
701
+ temporaryFilename.unlink(missing_ok=True)
702
+ return False
703
+ # handle file is bad
704
+ except (HTTPError, URLError) as err:
705
+ try:
706
+ tryWebAuthentication = False
707
+ if isinstance(err, HTTPError) and err.code == 401:
708
+ tryWebAuthentication = True
709
+ if 'www-authenticate' in err.hdrs:
710
+ match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', err.hdrs['www-authenticate'])
711
+ if match:
712
+ scheme, realm = match.groups()
713
+ if scheme.lower() == 'basic':
714
+ host = os.path.dirname(quotedUrl)
715
+ userPwd = self.cntlr.internet_user_password(host, realm)
716
+ if isinstance(userPwd,(tuple,list)):
717
+ self.http_auth_handler.add_password(realm=realm,uri=host,user=userPwd[0],passwd=userPwd[1])
510
718
  retryCount -= 1
511
- break
512
- if retryCount < RETRIEVAL_RETRY_COUNT:
513
- continue # succeeded
514
- # may be a web login authentication request
515
- response = None # found possible logon request
516
- if self.cntlr.hasGui:
517
- response = self.cntlr.internet_logon(url, quotedUrl,
518
- _("HTTP {0} authentication request").format(err.code),
519
- _("Is browser-based internet access authentication possible? If so, click 'yes', or 'cancel' to abort retrieval: \n\n{0}")
520
- .format(url))
521
- if response == "retry":
522
- retryCount -= 1
523
- continue
524
- elif response != "no":
525
- self.cntlr.addToLog(_("Web file HTTP 401 (authentication required) response, not retrieved: %(URL)s"),
526
- messageCode="webCache:authenticationRequired",
527
- messageArgs={"URL": url},
719
+ continue
720
+ self.cntlr.addToLog(_("'%(scheme)s' www-authentication for realm '%(realm)s' is required to access %(URL)s\n%(error)s"),
721
+ messageCode="webCache:unsupportedWWWAuthentication",
722
+ messageArgs={"scheme": scheme, "realm": realm, "URL": url, "error": err},
723
+ level=logging.ERROR)
724
+ elif isinstance(err, HTTPError) and err.code == 407:
725
+ tryWebAuthentication = True
726
+ if 'proxy-authenticate' in err.hdrs:
727
+ match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', err.hdrs['proxy-authenticate'])
728
+ if match:
729
+ scheme, realm = match.groups()
730
+ host = self.proxy_handler.proxies.get('http')
731
+ if scheme.lower() == 'basic':
732
+ userPwd = self.cntlr.internet_user_password(host, realm)
733
+ if isinstance(userPwd,(tuple,list)):
734
+ self.proxy_auth_handler.add_password(realm=realm,uri=host,user=userPwd[0],passwd=userPwd[1])
735
+ retryCount -= 1
736
+ continue
737
+ self.cntlr.addToLog(_("'%(scheme)s' proxy-authentication for realm '%(realm)s' is required to access %(URL)s\n%(error)s"),
738
+ messageCode="webCache:unsupportedProxyAuthentication",
739
+ messageArgs={"scheme": scheme, "realm": realm, "URL": url, "error": err},
528
740
  level=logging.ERROR)
529
- return None
530
-
531
- except AttributeError:
532
- pass
533
741
  if retrievingDueToRecheckInterval:
534
- return self.internetRecheckFailedRecovery(filepath, url, err, timeNowStr)
535
- self.cntlr.addToLog(_("%(error)s \nretrieving %(URL)s"),
536
- messageCode="webCache:retrievalError",
537
- messageArgs={"error": err.reason if hasattr(err, "reason") else err,
538
- "URL": url},
742
+ self.internetRecheckFailedRecovery(url, err, timeNowStr)
743
+ return True
744
+ if tryWebAuthentication:
745
+ # check if single signon is requested (on first retry)
746
+ if retryCount == RETRIEVAL_RETRY_COUNT:
747
+ for pluginXbrlMethod in pluginClassMethods("Proxy.HTTPAuthenticate"):
748
+ if pluginXbrlMethod(self.cntlr): # true if succeessful single sign on
749
+ retryCount -= 1
750
+ break
751
+ if retryCount < RETRIEVAL_RETRY_COUNT:
752
+ continue # succeeded
753
+ # may be a web login authentication request
754
+ response = None # found possible logon request
755
+ if self.cntlr.hasGui:
756
+ response = self.cntlr.internet_logon(url, quotedUrl,
757
+ _("HTTP {0} authentication request").format(err.code),
758
+ _("Is browser-based internet access authentication possible? If so, click 'yes', or 'cancel' to abort retrieval: \n\n{0}")
759
+ .format(url))
760
+ if response == "retry":
761
+ retryCount -= 1
762
+ continue
763
+ elif response != "no":
764
+ self.cntlr.addToLog(_("Web file HTTP 401 (authentication required) response, not retrieved: %(URL)s"),
765
+ messageCode="webCache:authenticationRequired",
766
+ messageArgs={"URL": url},
767
+ level=logging.ERROR)
768
+ return False
769
+
770
+ except AttributeError:
771
+ pass
772
+ if retrievingDueToRecheckInterval:
773
+ self.internetRecheckFailedRecovery(url, err, timeNowStr)
774
+ return True
775
+ self.cntlr.addToLog(_("%(error)s \nretrieving %(URL)s"),
776
+ messageCode="webCache:retrievalError",
777
+ messageArgs={"error": err.reason if hasattr(err, "reason") else err,
778
+ "URL": url},
779
+ level=logging.ERROR)
780
+ return False
781
+
782
+ except Exception as err:
783
+ if retryCount > 1:
784
+ self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s \n%(retryCount)s retries remaining"),
785
+ messageCode="webCache:retryingOperation",
786
+ messageArgs={"error": err, "URL": url, "retryCount": retryCount},
539
787
  level=logging.ERROR)
540
- return None
541
-
542
- except Exception as err:
543
- if retryCount > 1:
544
- self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s \n%(retryCount)s retries remaining"),
545
- messageCode="webCache:retryingOperation",
546
- messageArgs={"error": err, "URL": url, "retryCount": retryCount},
547
- level=logging.ERROR)
548
- retryCount -= 1
549
- continue
550
- if retrievingDueToRecheckInterval:
551
- return self.internetRecheckFailedRecovery(filepath, url, err, timeNowStr)
552
- if self.cntlr.hasGui:
553
- self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s \nswitching to work offline"),
554
- messageCode="webCache:attemptingOfflineOperation",
555
- messageArgs={"error": err, "URL": url},
556
- level=logging.ERROR)
557
- # try working offline
558
- self.workOffline = True
559
- return filepath
560
- else: # don't switch offline unexpectedly in scripted (batch) operation
561
- self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s"),
562
- messageCode="webCache:unsuccessfulRetrieval",
563
- messageArgs={"error": err, "URL": url},
564
- level=logging.ERROR)
565
- if os.path.exists(filepathtmp):
566
- os.remove(filepathtmp)
567
- return None
568
-
569
- # rename temporarily named downloaded file to desired name
570
- if os.path.exists(filepath):
571
- try:
572
- if os.path.isfile(filepath) or os.path.islink(filepath):
573
- os.remove(filepath)
574
- elif os.path.isdir(filepath):
575
- shutil.rmtree(filepath)
576
- except Exception as err:
577
- self.cntlr.addToLog(_("%(error)s \nUnsuccessful removal of prior file %(filepath)s \nPlease remove with file manager."),
578
- messageCode="webCache:cachedPriorFileLocked",
579
- messageArgs={"error": err, "filepath": filepath},
580
- level=logging.ERROR)
581
- try:
582
- os.rename(filepathtmp, filepath)
583
- if self._logDownloads:
584
- self.cntlr.addToLog(_("Downloaded %(URL)s"),
585
- messageCode="webCache:download",
586
- messageArgs={"URL": url, "filepath": filepath},
587
- level=logging.INFO)
588
- except Exception as err:
589
- self.cntlr.addToLog(_("%(error)s \nUnsuccessful renaming of downloaded file to active file %(filepath)s \nPlease remove with file manager."),
590
- messageCode="webCache:cacheDownloadRenamingError",
591
- messageArgs={"error": err, "filepath": filepath},
788
+ retryCount -= 1
789
+ continue
790
+ if retrievingDueToRecheckInterval:
791
+ self.internetRecheckFailedRecovery(url, err, timeNowStr)
792
+ return True
793
+ if self.cntlr.hasGui:
794
+ self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s \nswitching to work offline"),
795
+ messageCode="webCache:attemptingOfflineOperation",
796
+ messageArgs={"error": err, "URL": url},
592
797
  level=logging.ERROR)
593
- webFileTime = lastModifiedTime(headers)
594
- if webFileTime: # set mtime to web mtime
595
- os.utime(filepath,(webFileTime,webFileTime))
596
- self.cachedUrlCheckTimes[url] = timeNowStr
597
- self.cachedUrlCheckTimesModified = True
598
- return filepath
599
-
600
- if url.startswith("file://"): url = url[7:]
601
- elif url.startswith("file:\\"): url = url[6:]
602
- if os.sep == '\\':
603
- url = url.replace('/', '\\')
604
- return url
798
+ # try working offline
799
+ self.workOffline = True
800
+ return False
801
+ else: # don't switch offline unexpectedly in scripted (batch) operation
802
+ self.cntlr.addToLog(_("%(error)s \nunsuccessful retrieval of %(URL)s"),
803
+ messageCode="webCache:unsuccessfulRetrieval",
804
+ messageArgs={"error": err, "URL": url},
805
+ level=logging.ERROR)
806
+ temporaryFilename.unlink(missing_ok=True)
807
+ return False
605
808
 
606
- def internetRecheckFailedRecovery(self, filepath, url, err, timeNowStr):
809
+ # rename temporarily named downloaded file to desired name
810
+ try:
811
+ if os.path.isdir(filepath):
812
+ try:
813
+ shutil.rmtree(filepath)
814
+ except FileNotFoundError:
815
+ pass
816
+ else:
817
+ Path(filepath).unlink(missing_ok=True)
818
+ except Exception as err:
819
+ self.cntlr.addToLog(_("%(error)s \nUnsuccessful removal of prior file %(filepath)s \nPlease remove with file manager."),
820
+ messageCode="webCache:cachedPriorFileLocked",
821
+ messageArgs={"error": err, "filepath": filepath},
822
+ level=logging.ERROR)
823
+ try:
824
+ temporaryFilename.rename(filepath)
825
+ if self._logDownloads:
826
+ self.cntlr.addToLog(_("Downloaded %(URL)s"),
827
+ messageCode="webCache:download",
828
+ messageArgs={"URL": url, "filepath": filepath},
829
+ level=logging.INFO)
830
+ except Exception as err:
831
+ self.cntlr.addToLog(_("%(error)s \nUnsuccessful renaming of downloaded file to active file %(filepath)s \nPlease remove with file manager."),
832
+ messageCode="webCache:cacheDownloadRenamingError",
833
+ messageArgs={"error": err, "filepath": filepath},
834
+ level=logging.ERROR)
835
+ webFileTime = lastModifiedTime(headers)
836
+ if webFileTime: # set mtime to web mtime
837
+ os.utime(filepath,(webFileTime,webFileTime))
838
+ self.cachedUrlCheckTimes[url] = timeNowStr
839
+ self.cachedUrlCheckTimesModified = True
840
+ return True
841
+ return False
842
+
843
+ def internetRecheckFailedRecovery(self, url: str, err: str | Exception, timeNowStr: str) -> None:
607
844
  self.cntlr.addToLog(_("During refresh of web file ignoring error: %(error)s for %(URL)s"),
608
845
  messageCode="webCache:unableToRefreshFile",
609
846
  messageArgs={"URL": url, "error": err},
@@ -611,7 +848,6 @@ class WebCache:
611
848
  # skip this checking cycle, act as if retrieval was ok
612
849
  self.cachedUrlCheckTimes[url] = timeNowStr
613
850
  self.cachedUrlCheckTimesModified = True
614
- return filepath
615
851
 
616
852
  def reportProgress(self, blockCount, blockSize, totalSize):
617
853
  if totalSize > 0:
@@ -627,8 +863,10 @@ class WebCache:
627
863
  def clear(self):
628
864
  for cachedProtocol in ("http", "https"):
629
865
  cachedProtocolDir = os.path.join(self.cacheDir, cachedProtocol)
630
- if os.path.exists(cachedProtocolDir):
631
- shutil.rmtree(cachedProtocolDir, True)
866
+ try:
867
+ shutil.rmtree(cachedProtocolDir)
868
+ except FileNotFoundError:
869
+ pass
632
870
 
633
871
  def getheaders(self, url):
634
872
  if url and isHttpUrl(url):