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.
- arelle/Aspect.py +6 -3
- arelle/BetaFeatures.py +3 -0
- arelle/Cntlr.py +117 -413
- arelle/CntlrCmdLine.py +364 -227
- arelle/CntlrQuickBooks.py +4 -2
- arelle/CntlrWebMain.py +179 -119
- arelle/CntlrWinMain.py +342 -124
- arelle/DialogAbout.py +1 -1
- arelle/DialogArcroleGroup.py +1 -1
- arelle/DialogFind.py +1 -1
- arelle/DialogFormulaParameters.py +2 -2
- arelle/DialogLanguage.py +45 -36
- arelle/DialogNewFactItem.py +1 -1
- arelle/DialogOpenArchive.py +30 -34
- arelle/DialogPackageManager.py +11 -8
- arelle/DialogPluginManager.py +43 -89
- arelle/DialogRssWatch.py +2 -2
- arelle/DialogURL.py +1 -1
- arelle/DialogUserPassword.py +1 -1
- arelle/DisclosureSystem.py +69 -1
- arelle/ErrorManager.py +321 -0
- arelle/FileSource.py +201 -99
- arelle/FunctionFn.py +44 -5
- arelle/FunctionIxt.py +16 -13
- arelle/FunctionUtil.py +1 -1
- arelle/FunctionXfi.py +68 -24
- arelle/FunctionXs.py +1 -1
- arelle/HtmlUtil.py +5 -4
- arelle/LeiUtil.py +63 -43
- arelle/LinkbaseType.py +94 -0
- arelle/LocalViewer.py +8 -2
- arelle/Locale.py +239 -79
- arelle/ModelDocument.py +180 -48
- arelle/ModelDtsObject.py +32 -27
- arelle/ModelFormulaObject.py +14 -6
- arelle/ModelInstanceObject.py +43 -14
- arelle/ModelManager.py +6 -1
- arelle/ModelObject.py +12 -8
- arelle/ModelObjectFactory.py +18 -2
- arelle/ModelRelationshipSet.py +46 -3
- arelle/ModelRenderingObject.py +899 -951
- arelle/ModelRssItem.py +2 -4
- arelle/ModelTestcaseObject.py +41 -4
- arelle/ModelValue.py +42 -14
- arelle/ModelVersReport.py +1 -1
- arelle/ModelXbrl.py +133 -273
- arelle/PackageManager.py +202 -176
- arelle/PluginManager.py +551 -239
- arelle/PluginUtils.py +54 -0
- arelle/PrototypeInstanceObject.py +53 -12
- arelle/PythonUtil.py +166 -25
- arelle/RuntimeOptions.py +32 -18
- arelle/SocketUtils.py +3 -0
- arelle/SystemInfo.py +1 -1
- arelle/TkTableWrapper.py +33 -5
- arelle/UITkTable.py +27 -21
- arelle/Updater.py +7 -3
- arelle/UrlUtil.py +6 -2
- arelle/Validate.py +596 -402
- arelle/ValidateDuplicateFacts.py +584 -0
- arelle/ValidateFileSource.py +38 -0
- arelle/ValidateFilingText.py +46 -29
- arelle/ValidateInfoset.py +104 -32
- arelle/ValidateUtr.py +31 -4
- arelle/ValidateXbrl.py +144 -120
- arelle/ValidateXbrlCalcs.py +51 -66
- arelle/ValidateXbrlDTS.py +98 -29
- arelle/Version.py +2 -7
- arelle/ViewFile.py +2 -0
- arelle/ViewFileDTS.py +7 -2
- arelle/ViewFileFactList.py +1 -1
- arelle/ViewFileFactTable.py +4 -4
- arelle/ViewFileRelationshipSet.py +36 -19
- arelle/ViewFileRenderedGrid.py +164 -753
- arelle/ViewFileRenderedLayout.py +174 -0
- arelle/ViewFileRenderedStructure.py +108 -0
- arelle/ViewWinDTS.py +4 -1
- arelle/ViewWinFactList.py +1 -1
- arelle/ViewWinFactTable.py +1 -1
- arelle/ViewWinRelationshipSet.py +14 -8
- arelle/ViewWinRenderedGrid.py +397 -287
- arelle/ViewWinRssFeed.py +4 -0
- arelle/ViewWinTree.py +15 -9
- arelle/ViewWinXml.py +1 -1
- arelle/WebCache.py +510 -272
- arelle/XbrlConst.py +202 -196
- arelle/XbrlUtil.py +2 -1
- arelle/XhtmlValidate.py +9 -23
- arelle/XmlUtil.py +24 -19
- arelle/XmlValidate.py +95 -67
- arelle/XmlValidateParticles.py +4 -4
- arelle/_version.py +33 -3
- arelle/api/Session.py +183 -0
- arelle/config/creationSoftwareNames.json +24 -10
- arelle/config/disclosuresystems.xml +1 -1
- arelle/config/disclosuresystems.xsd +3 -0
- arelle/config/sbr-text-formatting.xsd +737 -0
- arelle/conformance/CSVTestcaseLoader.py +102 -0
- arelle/formula/FactAspectsCache.py +10 -4
- arelle/formula/ValidateFormula.py +82 -194
- arelle/formula/XPathContext.py +42 -28
- arelle/formula/XPathParser.py +15 -9
- arelle/locale/ar_EG/LC_MESSAGES/ar_EG.po +3 -4
- arelle/locale/messages.pot +1 -2
- arelle/locale/ru/LC_MESSAGES/ru.po +2 -2
- arelle/logging/formatters/LogFormatter.py +47 -0
- arelle/logging/handlers/LogHandlerWithXml.py +94 -0
- arelle/logging/handlers/LogToBufferHandler.py +20 -0
- arelle/logging/handlers/LogToPrintHandler.py +41 -0
- arelle/logging/handlers/LogToXmlHandler.py +244 -0
- arelle/logging/handlers/StructuredMessageLogHandler.py +74 -0
- arelle/model/CommentBase.py +3 -0
- arelle/model/ElementBase.py +3 -0
- arelle/model/PIBase.py +3 -0
- arelle/model/__init__.py +3 -0
- arelle/oim/Load.py +2869 -0
- arelle/oim/Validate.py +155 -0
- arelle/oim/xml/Save.py +21 -0
- arelle/packages/PackageConst.py +7 -0
- arelle/packages/PackageType.py +13 -0
- arelle/packages/PackageUtils.py +22 -0
- arelle/packages/PackageValidation.py +200 -0
- arelle/packages/report/DetectReportPackage.py +13 -0
- arelle/packages/report/ReportPackage.py +265 -0
- arelle/packages/report/ReportPackageConst.py +79 -0
- arelle/packages/report/ReportPackageValidator.py +207 -0
- arelle/plugin/EdgarRendererAllReports.py +12 -12
- arelle/plugin/OimTaxonomy/ModelValueMore.py +15 -0
- arelle/plugin/OimTaxonomy/ValidateDTS.py +484 -0
- arelle/plugin/OimTaxonomy/ViewXbrlTxmyObj.py +239 -0
- arelle/plugin/OimTaxonomy/XbrlAbstract.py +16 -0
- arelle/plugin/OimTaxonomy/XbrlConcept.py +68 -0
- arelle/plugin/OimTaxonomy/XbrlConst.py +261 -0
- arelle/plugin/OimTaxonomy/XbrlCube.py +91 -0
- arelle/plugin/OimTaxonomy/XbrlDimension.py +38 -0
- arelle/plugin/OimTaxonomy/XbrlDts.py +152 -0
- arelle/plugin/OimTaxonomy/XbrlEntity.py +16 -0
- arelle/plugin/OimTaxonomy/XbrlGroup.py +22 -0
- arelle/plugin/OimTaxonomy/XbrlImportedTaxonomy.py +22 -0
- arelle/plugin/OimTaxonomy/XbrlLabel.py +31 -0
- arelle/plugin/OimTaxonomy/XbrlNetwork.py +100 -0
- arelle/plugin/OimTaxonomy/XbrlProperty.py +28 -0
- arelle/plugin/OimTaxonomy/XbrlReference.py +33 -0
- arelle/plugin/OimTaxonomy/XbrlReport.py +24 -0
- arelle/plugin/OimTaxonomy/XbrlTableTemplate.py +35 -0
- arelle/plugin/OimTaxonomy/XbrlTaxonomy.py +93 -0
- arelle/plugin/OimTaxonomy/XbrlTaxonomyObject.py +154 -0
- arelle/plugin/OimTaxonomy/XbrlTransform.py +17 -0
- arelle/plugin/OimTaxonomy/XbrlTypes.py +23 -0
- arelle/plugin/OimTaxonomy/XbrlUnit.py +17 -0
- arelle/plugin/OimTaxonomy/__init__.py +1037 -0
- arelle/plugin/OimTaxonomy/resources/iso4217.json +4479 -0
- arelle/plugin/OimTaxonomy/resources/oim-taxonomy-schema.json +935 -0
- arelle/plugin/OimTaxonomy/resources/ref.json +333 -0
- arelle/plugin/OimTaxonomy/resources/transform-types.json +2481 -0
- arelle/plugin/OimTaxonomy/resources/types.json +727 -0
- arelle/plugin/OimTaxonomy/resources/utr.json +3046 -0
- arelle/plugin/OimTaxonomy/resources/xbrlSpec.json +1082 -0
- arelle/plugin/formulaLoader.py +3 -3
- arelle/plugin/formulaSaver.py +4 -4
- arelle/plugin/inlineXbrlDocumentSet.py +331 -102
- arelle/plugin/internet/proxyNTLM/HTTPNtlmAuthHandler.py +1 -1
- arelle/plugin/loadFromExcel.py +13 -10
- arelle/plugin/loadFromOIM.py +16 -3096
- arelle/plugin/logging/saveMessages.py +1 -1
- arelle/plugin/saveHtmlEBAtables.py +293 -213
- arelle/plugin/saveLoadableOIM.py +652 -361
- arelle/plugin/saveOIMTaxonomy.py +311 -0
- arelle/plugin/streamingExtensions.py +1 -1
- arelle/plugin/systemInfo.py +46 -0
- arelle/plugin/transforms/tester.py +4 -4
- arelle/plugin/validate/CIPC/Const.py +18 -0
- arelle/plugin/validate/CIPC/__init__.py +34 -13
- arelle/plugin/validate/DBA/DisclosureSystems.py +12 -0
- arelle/plugin/validate/DBA/PluginValidationDataExtension.py +165 -0
- arelle/plugin/validate/DBA/ValidationPluginExtension.py +545 -0
- arelle/plugin/validate/DBA/__init__.py +49 -0
- arelle/plugin/validate/DBA/resources/config.xml +21 -0
- arelle/plugin/validate/DBA/rules/__init__.py +323 -0
- arelle/plugin/validate/DBA/rules/fr.py +1377 -0
- arelle/plugin/validate/DBA/rules/tc.py +45 -0
- arelle/plugin/validate/DBA/rules/th.py +172 -0
- arelle/plugin/validate/DBA/rules/tm.py +351 -0
- arelle/plugin/validate/DBA/rules/tr.py +373 -0
- arelle/plugin/validate/EBA/__init__.py +11 -12
- arelle/plugin/validate/EDINET/Constants.py +208 -0
- arelle/plugin/validate/EDINET/ContextRequirement.py +58 -0
- arelle/plugin/validate/EDINET/ControllerPluginData.py +298 -0
- arelle/plugin/validate/EDINET/CoverItemRequirements.py +42 -0
- arelle/plugin/validate/EDINET/DeiRequirements.py +118 -0
- arelle/plugin/validate/EDINET/DisclosureSystems.py +1 -0
- arelle/plugin/validate/EDINET/FilingFormat.py +275 -0
- arelle/plugin/validate/EDINET/FormType.py +134 -0
- arelle/plugin/validate/EDINET/ManifestInstance.py +236 -0
- arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +640 -0
- arelle/plugin/validate/EDINET/ReportFolderType.py +162 -0
- arelle/plugin/validate/EDINET/Statement.py +139 -0
- arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +493 -0
- arelle/plugin/validate/EDINET/UploadContents.py +48 -0
- arelle/plugin/validate/EDINET/ValidationPluginExtension.py +64 -0
- arelle/plugin/validate/EDINET/__init__.py +109 -0
- arelle/plugin/validate/EDINET/resources/config.xml +22 -0
- arelle/plugin/validate/EDINET/resources/cover-item-requirements.json +793 -0
- arelle/plugin/validate/EDINET/resources/dei-requirements.csv +27 -0
- arelle/plugin/validate/EDINET/resources/edinet-taxonomies.xml +62 -0
- arelle/plugin/validate/EDINET/rules/contexts.py +547 -0
- arelle/plugin/validate/EDINET/rules/edinet.py +1991 -0
- arelle/plugin/validate/EDINET/rules/frta.py +301 -0
- arelle/plugin/validate/EDINET/rules/gfm.py +2394 -0
- arelle/plugin/validate/EDINET/rules/manifests.py +88 -0
- arelle/plugin/validate/EDINET/rules/upload.py +1370 -0
- arelle/plugin/validate/ESEF/Const.py +16 -75
- arelle/plugin/validate/ESEF/Dimensions.py +2 -2
- arelle/plugin/validate/ESEF/ESEF_2021/DTS.py +6 -1
- arelle/plugin/validate/ESEF/ESEF_2021/Image.py +7 -4
- arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +80 -57
- arelle/plugin/validate/ESEF/ESEF_Current/DTS.py +60 -22
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +272 -133
- arelle/plugin/validate/ESEF/Util.py +5 -19
- arelle/plugin/validate/ESEF/__init__.py +61 -46
- arelle/plugin/validate/ESEF/resources/authority-validations.json +120 -10
- arelle/plugin/validate/ESEF/resources/config.xml +44 -3
- arelle/plugin/validate/FERC/__init__.py +31 -18
- arelle/plugin/validate/FERC/config.xml +18 -18
- arelle/plugin/validate/NL/DisclosureSystems.py +19 -3
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +710 -7
- arelle/plugin/validate/NL/ValidationPluginExtension.py +117 -12
- arelle/plugin/validate/NL/__init__.py +21 -10
- arelle/plugin/validate/NL/resources/config.xml +27 -6
- arelle/plugin/validate/NL/rules/br_kvk.py +81 -21
- arelle/plugin/validate/NL/rules/fg_nl.py +292 -0
- arelle/plugin/validate/NL/rules/fr_kvk.py +60 -7
- arelle/plugin/validate/NL/rules/fr_nl.py +705 -24
- arelle/plugin/validate/NL/rules/nl_kvk.py +2182 -0
- arelle/plugin/validate/ROS/DisclosureSystems.py +1 -0
- arelle/plugin/validate/ROS/PluginValidationDataExtension.py +109 -0
- arelle/plugin/validate/ROS/ValidationPluginExtension.py +27 -0
- arelle/plugin/validate/ROS/__init__.py +28 -341
- arelle/plugin/validate/ROS/resources/config.xml +20 -0
- arelle/plugin/validate/ROS/rules/__init__.py +56 -0
- arelle/plugin/validate/ROS/rules/ros.py +393 -0
- arelle/plugin/validate/UK/ValidateUK.py +1372 -0
- arelle/plugin/validate/{HMRC → UK}/__init__.py +195 -189
- arelle/plugin/validate/{HMRC → UK}/config.xml +1 -1
- arelle/plugin/xbrlDB/SqlDb.py +1 -1
- arelle/plugin/xbrlDB/XbrlOpenSqlDB.py +5 -5
- arelle/plugin/xbrlDB/XbrlPublicPostgresDB.py +1 -1
- arelle/plugin/xbrlDB/XbrlSemanticJsonDB.py +1 -1
- arelle/plugin/xbrlDB/XbrlSemanticRdfDB.py +1 -1
- arelle/plugin/xbrlDB/__init__.py +4 -1
- arelle/{RenderingEvaluator.py → rendering/RenderingEvaluator.py} +120 -99
- arelle/rendering/RenderingLayout.py +476 -0
- arelle/rendering/RenderingResolution.py +814 -0
- arelle/resources/cache/http/www.eurofiling.info/eu/fr/xbrl/ext/filing-indicators.xsd +20 -0
- arelle/resources/cache/http/www.w3.org/2001/03/xml.xsd +117 -0
- arelle/resources/cache/http/www.w3.org/2001/XMLSchema.xsd +2534 -0
- arelle/resources/cache/http/www.w3.org/2001/xml.xsd +287 -0
- arelle/resources/cache/http/www.xbrl.org/2003/xbrl-instance-2003-12-31.xsd +779 -0
- arelle/resources/cache/http/www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd +486 -0
- arelle/resources/cache/http/www.xbrl.org/2003/xl-2003-12-31.xsd +251 -0
- arelle/resources/cache/http/www.xbrl.org/2003/xlink-2003-12-31.xsd +121 -0
- arelle/resources/cache/http/www.xbrl.org/2004/ref-2004-08-10.xsd +129 -0
- arelle/resources/cache/http/www.xbrl.org/2005/xbrldt-2005.xsd +53 -0
- arelle/resources/cache/http/www.xbrl.org/2006/ref-2006-02-27.xsd +120 -0
- arelle/resources/cache/http/www.xbrl.org/2006/xbrldi-2006.xsd +41 -0
- arelle/resources/cache/http/www.xbrl.org/2008/boolean-filter.xsd +51 -0
- arelle/resources/cache/http/www.xbrl.org/2008/concept-filter.xsd +127 -0
- arelle/resources/cache/http/www.xbrl.org/2008/conformance.xsd +116 -0
- arelle/resources/cache/http/www.xbrl.org/2008/conformanceFunction.xsd +51 -0
- arelle/resources/cache/http/www.xbrl.org/2008/consistency-assertion.xsd +66 -0
- arelle/resources/cache/http/www.xbrl.org/2008/dimension-filter.xsd +86 -0
- arelle/resources/cache/http/www.xbrl.org/2008/entity-filter.xsd +92 -0
- arelle/resources/cache/http/www.xbrl.org/2008/existence-assertion.xsd +44 -0
- arelle/resources/cache/http/www.xbrl.org/2008/formula.xsd +261 -0
- arelle/resources/cache/http/www.xbrl.org/2008/function.xsd +90 -0
- arelle/resources/cache/http/www.xbrl.org/2008/general-filter.xsd +38 -0
- arelle/resources/cache/http/www.xbrl.org/2008/generic-label.xsd +80 -0
- arelle/resources/cache/http/www.xbrl.org/2008/generic-link.xsd +81 -0
- arelle/resources/cache/http/www.xbrl.org/2008/generic-reference.xsd +63 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xbrl-instance-2003-12-31-ixmod.xsd +788 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xbrl-linkbase-2003-12-31-ixmod.xsd +488 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xl-2003-12-31.xsd +248 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xbrl/xlink-2003-12-31.xsd +117 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xframes-1.xsd +166 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-applet-1.xsd +66 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-attribs-1.xsd +72 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-base-1.xsd +36 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic-form-1.xsd +195 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic-table-1.xsd +169 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10-model-1.xsd +376 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10-module-redefines-1.xsd +61 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10-modules-1.xsd +259 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-basic10.xsd +98 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-bdo-1.xsd +78 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-blkphras-1.xsd +161 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-blkpres-1.xsd +37 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-blkstruct-1.xsd +49 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-charent-1.xsd +38 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-copyright-1.xsd +29 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-csismap-1.xsd +96 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-datatypes-1.xsd +128 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-edit-1.xsd +39 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-events-1.xsd +130 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-form-1.xsd +326 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-frames-1.xsd +113 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-framework-1.xsd +66 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-hypertext-1.xsd +47 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-iframe-1.xsd +68 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-image-1.xsd +45 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlphras-1.xsd +163 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlpres-1.xsd +39 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlstruct-1.xsd +50 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-inlstyle-1.xsd +27 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-legacy-1.xsd +97 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-link-1.xsd +45 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-list-1.xsd +99 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-meta-1.xsd +42 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-misc-1.xsd +441 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-nameident-1.xsd +63 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-notations-1.xsd +69 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-object-1.xsd +76 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-param-1.xsd +51 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-pres-1.xsd +51 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-ruby-1.xsd +171 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-ruby-basic-1.xsd +89 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-script-1.xsd +70 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-ssismap-1.xsd +43 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-struct-1.xsd +112 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-style-1.xsd +52 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-table-1.xsd +272 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-target-1.xsd +53 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml-text-1.xsd +67 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11-model-1.xsd +677 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11-module-redefines-1.xsd +335 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11-modules-1.xsd +528 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml11.xsd +104 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xhtml2.xsd +21 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-1.xsd +73 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-2.xsd +74 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-attribs-1.xsd +73 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-attribs-2.xsd +75 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-copyright-1.xsd +34 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-events-copyright-2.xsd +34 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml/xml-handlers-2.xsd +98 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0-definitions.xsd +225 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0-model.xsd +681 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0-modules.xsd +535 -0
- arelle/resources/cache/http/www.xbrl.org/2008/inlinexbrl/xhtml-inlinexbrl-1_0.xsd +40 -0
- arelle/resources/cache/http/www.xbrl.org/2008/match-filter.xsd +94 -0
- arelle/resources/cache/http/www.xbrl.org/2008/period-filter.xsd +86 -0
- arelle/resources/cache/http/www.xbrl.org/2008/registry.xsd +145 -0
- arelle/resources/cache/http/www.xbrl.org/2008/relative-filter.xsd +38 -0
- arelle/resources/cache/http/www.xbrl.org/2008/segment-scenario-filter.xsd +41 -0
- arelle/resources/cache/http/www.xbrl.org/2008/tuple-filter.xsd +83 -0
- arelle/resources/cache/http/www.xbrl.org/2008/unit-filter.xsd +58 -0
- arelle/resources/cache/http/www.xbrl.org/2008/validation.xsd +78 -0
- arelle/resources/cache/http/www.xbrl.org/2008/value-assertion.xsd +43 -0
- arelle/resources/cache/http/www.xbrl.org/2008/value-filter.xsd +43 -0
- arelle/resources/cache/http/www.xbrl.org/2008/variable.xsd +240 -0
- arelle/resources/cache/http/www.xbrl.org/2010/aspect-cover-filter.xsd +67 -0
- arelle/resources/cache/http/www.xbrl.org/2010/concept-relation-filter.xsd +108 -0
- arelle/resources/cache/http/www.xbrl.org/2010/custom-function-implementation.xsd +71 -0
- arelle/resources/cache/http/www.xbrl.org/2010/generic-message.xsd +68 -0
- arelle/resources/cache/http/www.xbrl.org/2010/validation-message.xsd +50 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xbrl-instance-2003-12-31-ixmod.xsd +788 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xbrl-linkbase-2003-12-31-ixmod.xsd +488 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xl-2003-12-31.xsd +248 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xbrl/xlink-2003-12-31.xsd +117 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xframes-1.xsd +166 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-applet-1.xsd +66 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-attribs-1.xsd +72 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-base-1.xsd +36 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic-form-1.xsd +195 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic-table-1.xsd +169 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10-model-1.xsd +376 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10-module-redefines-1.xsd +61 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10-modules-1.xsd +259 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-basic10.xsd +98 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-bdo-1.xsd +78 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-blkphras-1.xsd +161 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-blkpres-1.xsd +37 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-blkstruct-1.xsd +49 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-charent-1.xsd +38 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-copyright-1.xsd +29 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-csismap-1.xsd +96 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-datatypes-1.xsd +128 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-edit-1.xsd +39 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-events-1.xsd +130 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-form-1.xsd +326 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-frames-1.xsd +113 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-framework-1.xsd +66 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-hypertext-1.xsd +47 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-iframe-1.xsd +68 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-image-1.xsd +45 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlphras-1.xsd +163 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlpres-1.xsd +39 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlstruct-1.xsd +50 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-inlstyle-1.xsd +27 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-legacy-1.xsd +97 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-link-1.xsd +45 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-list-1.xsd +99 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-meta-1.xsd +42 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-misc-1.xsd +441 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-nameident-1.xsd +63 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-notations-1.xsd +69 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-object-1.xsd +76 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-param-1.xsd +51 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-pres-1.xsd +51 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-ruby-1.xsd +171 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-ruby-basic-1.xsd +89 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-script-1.xsd +70 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-ssismap-1.xsd +43 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-struct-1.xsd +112 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-style-1.xsd +52 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-table-1.xsd +272 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-target-1.xsd +53 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml-text-1.xsd +67 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11-model-1.xsd +677 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11-module-redefines-1.xsd +335 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11-modules-1.xsd +528 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml11.xsd +104 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xhtml2.xsd +21 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-1.xsd +73 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-2.xsd +74 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-attribs-1.xsd +73 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-attribs-2.xsd +75 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-copyright-1.xsd +34 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-events-copyright-2.xsd +34 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml/xml-handlers-2.xsd +98 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1-definitions.xsd +252 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1-model.xsd +681 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1-modules.xsd +535 -0
- arelle/resources/cache/http/www.xbrl.org/2013/inlineXBRL/xhtml-inlinexbrl-1_1.xsd +40 -0
- arelle/resources/cache/http/www.xbrl.org/2013/match-filter.xsd +94 -0
- arelle/resources/cache/http/www.xbrl.org/2013/preferred-label.xsd +12 -0
- arelle/resources/cache/http/www.xbrl.org/2013/versioning-base.xsd +142 -0
- arelle/resources/cache/http/www.xbrl.org/2013/versioning-concept-details.xsd +143 -0
- arelle/resources/cache/http/www.xbrl.org/2013/versioning-concept-use.xsd +64 -0
- arelle/resources/cache/http/www.xbrl.org/2013/versioning-dimensions.xsd +162 -0
- arelle/resources/cache/http/www.xbrl.org/2014/extensible-enumerations.xsd +27 -0
- arelle/resources/cache/http/www.xbrl.org/2014/table.xsd +356 -0
- arelle/resources/cache/http/www.xbrl.org/2014/tablemodel.xsd +156 -0
- arelle/resources/cache/http/www.xbrl.org/2016/assertion-severity.xsd +29 -0
- arelle/resources/cache/http/www.xbrl.org/2016/severities.xml +21 -0
- arelle/resources/cache/http/www.xbrl.org/2016/taxonomy-package-catalog.xsd +38 -0
- arelle/resources/cache/http/www.xbrl.org/2016/taxonomy-package.xsd +154 -0
- arelle/resources/cache/http/www.xbrl.org/2022/assertion-severity.xsd +43 -0
- arelle/resources/cache/http/www.xbrl.org/2022/severities.xml +21 -0
- arelle/resources/cache/http/www.xbrl.org/dtr/type/nonNumeric-2009-12-16.xsd +76 -0
- arelle/resources/cache/http/www.xbrl.org/dtr/type/numeric-2009-12-16.xsd +78 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/accounting-arcrole-2023-01-04.xsd +39 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/deprecated-2009-12-16.xsd +29 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/esma-arcrole-2018-11-21.xsd +14 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/factExplanatory-2009-12-16.xsd +13 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/jpfr-arcrole-2007-11-07.xsd +27 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/arcrole/parent-child-2013-09-19.xsd +12 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/deprecated-2009-12-16.xsd +17 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/jpfr-role-2007-11-07.xsd +47 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/negated-2008-03-31.xsd +30 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/negated-2009-12-16.xsd +33 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/negative-2009-12-16.xsd +25 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/net-2009-12-16.xsd +13 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/positive-2009-12-16.xsd +25 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/property-2022-09-28.xsd +15 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/reference-2009-12-16.xsd +21 -0
- arelle/resources/cache/http/www.xbrl.org/lrr/role/restated-2006-02-21.xsd +19 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2012-01-30/utr.xml +4543 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2012-10-31/utr.xml +4510 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2012-11-30/utr.xml +4567 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2013-02-28/utr.xml +5180 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2013-05-17/utr.xml +5349 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2016-08-10/utr.xml +5363 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2017-07-12/utr.xml +6164 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2021-02-16/utr.xml +6370 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2021-12-08/utr.xml +6493 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2022-02-16/utr.xml +6551 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2022-07-20/utr.xml +6638 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2023-12-20/utr.xml +6680 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2024-01-31/utr.xml +6680 -0
- arelle/resources/cache/http/www.xbrl.org/utr/2024-10-22/utr.xml +6693 -0
- arelle/resources/cache/http/www.xbrl.org/utr/utr.xml +6693 -0
- arelle/resources/cache/https/www.xbrl.org/2005/conformance.xsd +87 -0
- arelle/resources/cache/https/www.xbrl.org/2020/extensible-enumerations-2.0.xsd +51 -0
- arelle/resources/cache/https/www.xbrl.org/2023/calculation-1.1.xsd +27 -0
- arelle/resources/cache/https/www.xbrl.org/dtr/type/2020-01-21/types.xsd +812 -0
- arelle/resources/cache/https/www.xbrl.org/dtr/type/2022-03-31/types.xsd +847 -0
- arelle/resources/cache/https/www.xbrl.org/dtr/type/2024-01-31/types.xsd +897 -0
- arelle/resources/cache/https/www.xbrl.org/taxonomy/int/filing-indicators/REC/2021-02-03/filing-indicators-def.xml +68 -0
- arelle/resources/cache/https/www.xbrl.org/taxonomy/int/filing-indicators/REC/2021-02-03/filing-indicators-label.xml +84 -0
- arelle/resources/cache/https/www.xbrl.org/taxonomy/int/filing-indicators/REC/2021-02-03/filing-indicators.xsd +67 -0
- arelle/resources/libs/Tktable2.11/linux-x86_64/README.txt +149 -0
- arelle/resources/libs/Tktable2.11/linux-x86_64/html/tkTable.html +2039 -0
- arelle/resources/libs/Tktable2.11/linux-x86_64/libTktable2.11.so +0 -0
- arelle/resources/libs/Tktable2.11/linux-x86_64/license.txt +51 -0
- arelle/resources/libs/Tktable2.11/linux-x86_64/pkgIndex.tcl +3 -0
- arelle/resources/libs/Tktable2.11/linux-x86_64/tkTable.tcl +825 -0
- arelle/resources/libs/Tktable2.11/linux-x86_64/tktable.py +674 -0
- arelle/resources/libs/Tktable2.11/macos-arm64/README.txt +149 -0
- arelle/resources/libs/Tktable2.11/macos-arm64/html/tkTable.html +2039 -0
- arelle/resources/libs/Tktable2.11/macos-arm64/libTktable2.11.dylib +0 -0
- arelle/resources/libs/Tktable2.11/macos-arm64/license.txt +51 -0
- arelle/resources/libs/Tktable2.11/macos-arm64/pkgIndex.tcl +2 -0
- arelle/resources/libs/Tktable2.11/macos-arm64/tkTable.tcl +825 -0
- arelle/resources/libs/Tktable2.11/macos-arm64/tktable.py +674 -0
- arelle/resources/libs/Tktable2.11/macos-x86_64/README.txt +149 -0
- arelle/resources/libs/Tktable2.11/macos-x86_64/html/tkTable.html +2039 -0
- arelle/resources/libs/Tktable2.11/macos-x86_64/libTktable2.11.dylib +0 -0
- arelle/resources/libs/Tktable2.11/macos-x86_64/license.txt +51 -0
- arelle/resources/libs/Tktable2.11/macos-x86_64/pkgIndex.tcl +2 -0
- arelle/resources/libs/Tktable2.11/macos-x86_64/tkTable.tcl +825 -0
- arelle/resources/libs/Tktable2.11/macos-x86_64/tktable.py +674 -0
- arelle/resources/libs/Tktable2.11/win-x86_64/Tktable.dll +0 -0
- arelle/resources/libs/Tktable2.11/win-x86_64/pkgIndex.tcl +2 -0
- arelle/resources/libs/Tktable2.11/win-x86_64/tkTable.tcl +825 -0
- arelle/typing.py +9 -4
- arelle/utils/Contexts.py +38 -0
- arelle/utils/EntryPointDetection.py +139 -0
- arelle/utils/Equivalence.py +22 -0
- arelle/utils/{validate/PluginValidationData.py → PluginData.py} +5 -2
- arelle/utils/PluginHooks.py +256 -5
- arelle/utils/Units.py +36 -0
- arelle/utils/validate/Decorator.py +5 -3
- arelle/utils/validate/DetectScriptsInXhtml.py +99 -0
- arelle/utils/validate/ESEFImage.py +283 -0
- arelle/utils/validate/Validation.py +9 -1
- arelle/utils/validate/ValidationPlugin.py +74 -11
- arelle/utils/validate/ValidationUtil.py +55 -0
- arelle/webserver/bottle.py +5 -4424
- {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info}/METADATA +51 -42
- arelle_release-2.37.71.dist-info/RECORD +697 -0
- {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info}/WHEEL +1 -1
- {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info/licenses}/LICENSE.md +1 -4
- {arelle_release-2.17.1.dist-info → arelle_release-2.37.71.dist-info}/top_level.txt +0 -1
- arelle/DialogOpenTaxonomyPackage.py +0 -1
- arelle/RenderingResolver.py +0 -624
- arelle/examples/.pydevproject +0 -5
- arelle/examples/CustomLogger.py +0 -43
- arelle/examples/LoadEFMvalidate.py +0 -32
- arelle/examples/LoadSavePreLbCsv.py +0 -26
- arelle/examples/LoadValidate.cs +0 -31
- arelle/examples/LoadValidate.py +0 -36
- arelle/examples/LoadValidateCmdLine.java +0 -69
- arelle/examples/LoadValidatePostedZip.java +0 -57
- arelle/examples/LoadValidateWebService.java +0 -34
- arelle/examples/SaveTableToExelle.py +0 -140
- arelle/examples/TR3toTR4.py +0 -88
- arelle/examples/plugin/bigInstance.py +0 -394
- arelle/examples/plugin/cmdWebServerExtension.py +0 -42
- arelle/examples/plugin/crashTest.py +0 -38
- arelle/examples/plugin/formulaSuiteConverter.py +0 -212
- arelle/examples/plugin/functionsCustom.py +0 -59
- arelle/examples/plugin/hello_dolly.py +0 -64
- arelle/examples/plugin/hello_i18n.pot +0 -26
- arelle/examples/plugin/hello_i18n.py +0 -32
- arelle/examples/plugin/importTestChild1.py +0 -21
- arelle/examples/plugin/importTestChild2.py +0 -22
- arelle/examples/plugin/importTestGrandchild1.py +0 -21
- arelle/examples/plugin/importTestGrandchild2.py +0 -21
- arelle/examples/plugin/importTestImported1.py +0 -23
- arelle/examples/plugin/importTestImported11.py +0 -22
- arelle/examples/plugin/importTestParent.py +0 -48
- arelle/examples/plugin/locale/fr/LC_MESSAGES/hello_i18n.po +0 -25
- arelle/examples/plugin/packagedImportTest/__init__.py +0 -47
- arelle/examples/plugin/packagedImportTest/importTestChild1.py +0 -21
- arelle/examples/plugin/packagedImportTest/importTestChild2.py +0 -22
- arelle/examples/plugin/packagedImportTest/importTestGrandchild1.py +0 -21
- arelle/examples/plugin/packagedImportTest/importTestGrandchild2.py +0 -21
- arelle/examples/plugin/packagedImportTest/importTestImported1.py +0 -24
- arelle/examples/plugin/packagedImportTest/importTestImported11.py +0 -21
- arelle/examples/plugin/packagedImportTest/subdir/importTestImported111.py +0 -21
- arelle/examples/plugin/packagedImportTest/subdir/subsubdir/importTestImported1111.py +0 -21
- arelle/examples/plugin/sakaCalendar.py +0 -215
- arelle/examples/plugin/saveInstanceInfoset.py +0 -121
- arelle/examples/plugin/streamingExtensions.py +0 -335
- arelle/examples/plugin/testcaseCalc11ValidateSetup.py +0 -32
- arelle/examples/plugin/testcaseIxExpectedHtmlFixup.py +0 -45
- arelle/examples/plugin/updateTableLB.py +0 -242
- arelle/examples/plugin/validate/XYZ/DisclosureSystems.py +0 -2
- arelle/examples/plugin/validate/XYZ/PluginValidationDataExtension.py +0 -10
- arelle/examples/plugin/validate/XYZ/ValidationPluginExtension.py +0 -49
- arelle/examples/plugin/validate/XYZ/__init__.py +0 -75
- arelle/examples/plugin/validate/XYZ/resources/config.xml +0 -16
- arelle/examples/plugin/validate/XYZ/rules/rules01.py +0 -109
- arelle/examples/plugin/validate/XYZ/rules/rules02.py +0 -58
- arelle/examples/plugin/validateSchemaLxml.py +0 -156
- arelle/examples/plugin/validateTableInfoset.py +0 -52
- arelle/examples/us-gaap-dei-docType-extraction-frm.xml +0 -90
- arelle/examples/us-gaap-dei-ratio-cash-frm.xml +0 -150
- arelle/plugin/functionsXmlCreation.py +0 -106
- arelle/plugin/instanceInfo.py +0 -306
- arelle/plugin/loadFromOIM-2018.py +0 -1282
- arelle/plugin/objectmaker.py +0 -285
- arelle/plugin/sphinx/FormulaGenerator.py +0 -823
- arelle/plugin/sphinx/SphinxContext.py +0 -404
- arelle/plugin/sphinx/SphinxEvaluator.py +0 -783
- arelle/plugin/sphinx/SphinxMethods.py +0 -1287
- arelle/plugin/sphinx/SphinxParser.py +0 -1093
- arelle/plugin/sphinx/SphinxValidator.py +0 -163
- arelle/plugin/sphinx/US-GAAP Ratios Example.xsr +0 -52
- arelle/plugin/sphinx/__init__.py +0 -285
- arelle/plugin/transforms/SEC/__init__.py +0 -308
- arelle/plugin/transforms/SEC/conf/README.md +0 -39
- arelle/plugin/transforms/SEC/conf/extractTestcase.sh +0 -2
- arelle/plugin/transforms/SEC/conf/extractTestcase.xsl +0 -109
- arelle/plugin/transforms/SEC/conf/runIxtSecTests.sh +0 -16
- arelle/plugin/transforms/SEC/conf/saxon9.jar +0 -0
- arelle/plugin/transforms/SEC/conf/testcase.xml +0 -7117
- arelle/plugin/transforms/SEC/conf/tests.xml +0 -848
- arelle/plugin/transforms/SEC/text2num.py +0 -110
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-boolballotbox.xml +0 -66
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-countrynameen.xml +0 -65
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-datequarterend.xml +0 -66
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durday.xml +0 -61
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durhour.xml +0 -69
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durmonth.xml +0 -71
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durweek.xml +0 -70
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-durwordsen.xml +0 -56
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-duryear.xml +0 -64
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-edgarprovcountryen.xml +0 -65
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-entityfilercategoryen.xml +0 -63
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-exchnameen.xml +0 -86
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-numwordsen.xml +0 -55
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-stateprovnameen.xml +0 -64
- arelle/plugin/transforms/SEC/transformationRegistry/registry/ixt-sec-yesnoballotbox.xml +0 -66
- arelle/plugin/transforms/SEC/transformationRegistry/registry/transform-registry.xml +0 -314
- arelle/plugin/transforms/SEC/transformationRegistry/schema/inlinexbrl-sec-transformation.xsd +0 -418
- arelle/plugin/validate/EFM/Consts.py +0 -362
- arelle/plugin/validate/EFM/DTS.py +0 -569
- arelle/plugin/validate/EFM/Dimensions.py +0 -264
- arelle/plugin/validate/EFM/Document.py +0 -206
- arelle/plugin/validate/EFM/Filing.py +0 -4383
- arelle/plugin/validate/EFM/IsolateSeparateIXDSes.py +0 -19
- arelle/plugin/validate/EFM/MessageNumericId.py +0 -142
- arelle/plugin/validate/EFM/PreCalAlignment.py +0 -324
- arelle/plugin/validate/EFM/Util.py +0 -688
- arelle/plugin/validate/EFM/__init__.py +0 -843
- arelle/plugin/validate/EFM/config.xml +0 -333
- arelle/plugin/validate/EFM/resources/README.md +0 -57
- arelle/plugin/validate/EFM/resources/axiswarnings.json +0 -27
- arelle/plugin/validate/EFM/resources/cef-deprecated-concepts.json +0 -8
- arelle/plugin/validate/EFM/resources/country-deprecated-concepts.json +0 -19
- arelle/plugin/validate/EFM/resources/currency-deprecated-concepts.json +0 -7
- arelle/plugin/validate/EFM/resources/dei-deprecated-concepts.json +0 -8
- arelle/plugin/validate/EFM/resources/dei-validations.json +0 -2884
- arelle/plugin/validate/EFM/resources/dqc-us-rules.json +0 -1389
- arelle/plugin/validate/EFM/resources/ecd-deprecated-concepts.json +0 -1
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-16-4.xml +0 -115
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-0-4.xml +0 -300
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-1.xml +0 -304
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-2.xml +0 -290
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-17-3-1.xml +0 -294
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-18.1.xml +0 -549
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-18.2.xml +0 -506
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-18.3.xml +0 -496
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-19-1.xml +0 -662
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-19-2.xml +0 -3761
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-19-3.xml +0 -3577
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-20-1.xml +0 -4020
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-20-2.xml +0 -3320
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-20-3.xml +0 -2998
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2012.xml +0 -957
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2013.xml +0 -982
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2014.xml +0 -1001
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2015.xml +0 -1076
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-2016.xml +0 -120
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-1.xml +0 -3329
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-2.xml +0 -1230
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-3.xml +0 -1113
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-21-4.xml +0 -1321
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-1-preview.xml +0 -1721
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-1.xml +0 -1841
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-2-2.xml +0 -1450
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-2.xml +0 -1429
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-22-4.xml +0 -1527
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-1-1.xml +0 -2049
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-1.xml +0 -2065
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-2.xml +0 -1674
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-23-3.xml +0 -1715
- arelle/plugin/validate/EFM/resources/edgartaxonomies/edgartaxonomies-all-years.xml +0 -10671
- arelle/plugin/validate/EFM/resources/edgartaxonomies/erxl.xsd +0 -69
- arelle/plugin/validate/EFM/resources/edgartaxonomies/extendedtaxonomies-all-years.xml +0 -18
- arelle/plugin/validate/EFM/resources/edgartaxonomies/ifrs-taxonomies.xml +0 -3126
- arelle/plugin/validate/EFM/resources/edgartaxonomies/ifrstaxonomies-all-years.xml +0 -22
- arelle/plugin/validate/EFM/resources/ex26-validations.json +0 -255
- arelle/plugin/validate/EFM/resources/exch-deprecated-concepts.json +0 -163
- arelle/plugin/validate/EFM/resources/ifrs-full-deprecated-concepts.json +0 -204
- arelle/plugin/validate/EFM/resources/invest-deprecated-concepts.json +0 -99
- arelle/plugin/validate/EFM/resources/ixbrl-transform-registries.json +0 -16
- arelle/plugin/validate/EFM/resources/naics-deprecated-concepts.json +0 -295
- arelle/plugin/validate/EFM/resources/oef-deprecated-concepts.json +0 -59
- arelle/plugin/validate/EFM/resources/other-standard-taxonomies.json +0 -12
- arelle/plugin/validate/EFM/resources/rr-deprecated-concepts.json +0 -14
- arelle/plugin/validate/EFM/resources/rxp-deprecated-concepts.json +0 -1
- arelle/plugin/validate/EFM/resources/shr-deprecated-concepts.json +0 -1
- arelle/plugin/validate/EFM/resources/sic-deprecated-concepts.json +0 -1
- arelle/plugin/validate/EFM/resources/signwarnings.json +0 -112
- arelle/plugin/validate/EFM/resources/srt-deprecated-concepts.json +0 -1
- arelle/plugin/validate/EFM/resources/stpr-deprecated-concepts.json +0 -1
- arelle/plugin/validate/EFM/resources/taxonomy-compatibility.json +0 -79
- arelle/plugin/validate/EFM/resources/us-gaap-deprecated-concepts.json +0 -2886
- arelle/plugin/validate/EFM/resources/us-gaap-rels-2020.json +0 -29068
- arelle/plugin/validate/EFM/resources/us-gaap-rels-2021.json +0 -29598
- arelle/plugin/validate/EFM/resources/us-gaap-rels-2022.json +0 -29141
- arelle/plugin/validate/EFM/resources/us-gaap-rels-2023.json +0 -29400
- arelle/plugin/validate/EFM/resources/vip-deprecated-concepts.json +0 -1
- arelle/plugin/validate/EFM/tools/CheckTxmyRefs.py +0 -180
- arelle/plugin/validate/EFM-htm/Const.py +0 -205
- arelle/plugin/validate/EFM-htm/__init__.py +0 -217
- arelle/plugin/validate/EFM-htm/config.xml +0 -17
- arelle/plugin/validate/EFM-htm/resources/efm-htm.dtd +0 -664
- arelle/plugin/validate/ESEF/ESEF_Current/Image.py +0 -199
- arelle/plugin/validate/ESEF_2022/__init__.py +0 -47
- arelle/plugin/validate/GFM/__init__.py +0 -59
- arelle/plugin/validate/GFM/config.xml +0 -82
- arelle/plugin/validate/SBRnl/CustomLoader.py +0 -19
- arelle/plugin/validate/SBRnl/DTS.py +0 -305
- arelle/plugin/validate/SBRnl/Dimensions.py +0 -357
- arelle/plugin/validate/SBRnl/Document.py +0 -799
- arelle/plugin/validate/SBRnl/Filing.py +0 -467
- arelle/plugin/validate/SBRnl/__init__.py +0 -75
- arelle/plugin/validate/SBRnl/config.xml +0 -26
- arelle/plugin/validate/SBRnl/sbr-nl-taxonomies.xml +0 -754
- arelle/plugin/validate/USBestPractices.py +0 -570
- arelle/plugin/validate/USCorpAction.py +0 -557
- arelle/plugin/validate/USSecTagging.py +0 -337
- arelle/plugin/validate/XDC/__init__.py +0 -77
- arelle/plugin/validate/XDC/config.xml +0 -20
- arelle/plugin/validate/XFsyntax/__init__.py +0 -64
- arelle/plugin/validate/XFsyntax/xf.py +0 -2227
- arelle/plugin/validate/__init__.py +0 -20
- arelle/plugin/validate/calc2.py +0 -536
- arelle/plugin/validateSBRnl.py +0 -530
- arelle/scripts-macOS/startWebServer.command +0 -3
- arelle/scripts-unix/startWebServer.sh +0 -1
- arelle/scripts-windows/startWebServer.bat +0 -5
- arelle_release-2.17.1.dist-info/RECORD +0 -676
- tests/__init__.py +0 -0
- tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/ArelleGUITest.csproj +0 -30
- tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Tests.cs +0 -381
- tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Usings.cs +0 -1
- tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest.sln +0 -31
- tests/integration_tests/ui_tests/resources/workiva.zip +0 -0
- tests/integration_tests/validation/README.md +0 -50
- tests/integration_tests/validation/conformance_suite_config.py +0 -59
- tests/integration_tests/validation/conformance_suite_configs.py +0 -63
- tests/integration_tests/validation/conformance_suite_configurations/efm_current.py +0 -261
- tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2021.py +0 -85
- tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2022.py +0 -90
- tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2021.py +0 -15
- tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2022.py +0 -15
- tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py +0 -13
- tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py +0 -13
- tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py +0 -13
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_2_1.py +0 -34
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_calculations_1_1.py +0 -40
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_dimensions_1_0.py +0 -28
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_extensible_enumerations_1_0.py +0 -10
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_extensible_enumerations_2_0.py +0 -10
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula_1_0.py +0 -9
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula_1_0_assertion_severity_2_0.py +0 -9
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula_1_0_function_registry.py +0 -14
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_ixbrl_1_1.py +0 -22
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_link_role_registry_1_0.py +0 -11
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_oim_1_0.py +0 -19
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_table_linkbase_1_0.py +0 -296
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_taxonomy_packages_1_0.py +0 -13
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_3.py +0 -13
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_4.py +0 -13
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_5.py +0 -13
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_utr_malformed_1_0.py +0 -31
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_utr_registry_1_0.py +0 -22
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_utr_structure_1_0.py +0 -18
- tests/integration_tests/validation/conftest.py +0 -24
- tests/integration_tests/validation/discover_tests.py +0 -22
- tests/integration_tests/validation/download_conformance_suites.py +0 -47
- tests/integration_tests/validation/run_conformance_suites.py +0 -175
- tests/integration_tests/validation/test_conformance_suites.py +0 -14
- tests/integration_tests/validation/validation_util.py +0 -271
- tests/resources/conformance_suites/nl_nt16/br_kvk/2-04-invalid-period.xbrl +0 -63
- tests/resources/conformance_suites/nl_nt16/br_kvk/2-04-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/br_kvk/3-01-missing.xbrl +0 -53
- tests/resources/conformance_suites/nl_nt16/br_kvk/3-01-multiple.xbrl +0 -60
- tests/resources/conformance_suites/nl_nt16/br_kvk/3-01-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-07-invalid.xbrl +0 -57
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-07-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-10-invalid.xbrl +0 -58
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-10-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-12-invalid.xbrl +0 -63
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-12-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-16-missing.xbrl +0 -61
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-16-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-20-invalid-date.xbrl +0 -89
- tests/resources/conformance_suites/nl_nt16/br_kvk/4-20-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_kvk/1-01-invalid-file-extension.xml +0 -56
- tests/resources/conformance_suites/nl_nt16/fr_kvk/1-01-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_kvk/2-01-invalid-lang.xbrl +0 -56
- tests/resources/conformance_suites/nl_nt16/fr_kvk/2-01-missing-lang.xbrl +0 -55
- tests/resources/conformance_suites/nl_nt16/fr_kvk/2-01-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt16/fr_kvk/2-03-entrypoint.xsd +0 -6
- tests/resources/conformance_suites/nl_nt16/fr_kvk/2-03-invalid-entrypoint.xbrl +0 -63
- tests/resources/conformance_suites/nl_nt16/fr_kvk/2-03-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_kvk/5-01-invalid-decimals.xbrl +0 -49
- tests/resources/conformance_suites/nl_nt16/fr_kvk/5-01-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_kvk/5-02-invalid-decimals.xbrl +0 -49
- tests/resources/conformance_suites/nl_nt16/fr_kvk/5-02-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-01-invalid-file.xbrl +0 -2
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-01-invalid-zip.zip +0 -0
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-01-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-03-invalid-doctype.xbrl +0 -4
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-03-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-05-invalid-encoding.xbrl +0 -0
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-05-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-06-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt16/fr_nl/1-06.invalid.xbrl +0 -2
- tests/resources/conformance_suites/nl_nt16/fr_nl/2-06-invalid-file.xbrl +0 -8
- tests/resources/conformance_suites/nl_nt16/fr_nl/2-06-invalid-zip.zip +0 -0
- tests/resources/conformance_suites/nl_nt16/fr_nl/2-06-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt16/index.xml +0 -20
- tests/resources/conformance_suites/nl_nt17/br_kvk/2-04-invalid-period.xbrl +0 -63
- tests/resources/conformance_suites/nl_nt17/br_kvk/2-04-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/br_kvk/3-01-missing.xbrl +0 -53
- tests/resources/conformance_suites/nl_nt17/br_kvk/3-01-multiple.xbrl +0 -60
- tests/resources/conformance_suites/nl_nt17/br_kvk/3-01-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-07-invalid.xbrl +0 -57
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-07-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-10-invalid.xbrl +0 -58
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-10-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-12-invalid.xbrl +0 -63
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-12-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-16-missing.xbrl +0 -61
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-16-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-20-invalid-date.xbrl +0 -89
- tests/resources/conformance_suites/nl_nt17/br_kvk/4-20-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_kvk/1-01-invalid-file-extension.xml +0 -56
- tests/resources/conformance_suites/nl_nt17/fr_kvk/1-01-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_kvk/2-01-invalid-lang.xbrl +0 -56
- tests/resources/conformance_suites/nl_nt17/fr_kvk/2-01-missing-lang.xbrl +0 -55
- tests/resources/conformance_suites/nl_nt17/fr_kvk/2-01-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt17/fr_kvk/2-03-entrypoint.xsd +0 -6
- tests/resources/conformance_suites/nl_nt17/fr_kvk/2-03-invalid-entrypoint.xbrl +0 -63
- tests/resources/conformance_suites/nl_nt17/fr_kvk/2-03-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_kvk/5-01-invalid-decimals.xbrl +0 -49
- tests/resources/conformance_suites/nl_nt17/fr_kvk/5-01-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_kvk/5-02-invalid-decimals.xbrl +0 -49
- tests/resources/conformance_suites/nl_nt17/fr_kvk/5-02-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-01-invalid-file.xbrl +0 -2
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-01-invalid-zip.zip +0 -0
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-01-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-03-invalid-doctype.xbrl +0 -4
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-03-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-05-invalid-encoding.xbrl +0 -0
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-05-testcases.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-06-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt17/fr_nl/1-06.invalid.xbrl +0 -2
- tests/resources/conformance_suites/nl_nt17/fr_nl/2-06-invalid-file.xbrl +0 -8
- tests/resources/conformance_suites/nl_nt17/fr_nl/2-06-invalid-zip.zip +0 -0
- tests/resources/conformance_suites/nl_nt17/fr_nl/2-06-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt17/index.xml +0 -20
- tests/resources/conformance_suites/nl_nt18/fr_nl/1-03-invalid-doctype.xbrl +0 -4
- tests/resources/conformance_suites/nl_nt18/fr_nl/1-03-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt18/fr_nl/1-05-invalid-encoding.xbrl +0 -0
- tests/resources/conformance_suites/nl_nt18/fr_nl/1-05-testcases.xml +0 -22
- tests/resources/conformance_suites/nl_nt18/fr_nl/1-06-testcase.xml +0 -22
- tests/resources/conformance_suites/nl_nt18/fr_nl/1-06.invalid.xbrl +0 -2
- tests/resources/conformance_suites/nl_nt18/fr_nl/1.01-invalid-file.xbrl +0 -2
- tests/resources/conformance_suites/nl_nt18/fr_nl/1.01-invalid-zip.zip +0 -0
- tests/resources/conformance_suites/nl_nt18/fr_nl/1.01-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt18/fr_nl/2-06-invalid-file.xbrl +0 -8
- tests/resources/conformance_suites/nl_nt18/fr_nl/2-06-invalid-zip.zip +0 -0
- tests/resources/conformance_suites/nl_nt18/fr_nl/2-06-testcase.xml +0 -33
- tests/resources/conformance_suites/nl_nt18/index.xml +0 -8
- tests/unit_tests/arelle/conftest.py +0 -16
- tests/unit_tests/arelle/formula/test_fact_aspects_cache.py +0 -170
- tests/unit_tests/arelle/plugin/test_loadfromoim.py +0 -40
- tests/unit_tests/arelle/plugin/test_plugin_imports.py +0 -27
- tests/unit_tests/arelle/test_betafeatures.py +0 -81
- tests/unit_tests/arelle/test_cntlr.py +0 -28
- tests/unit_tests/arelle/test_import.py +0 -40
- tests/unit_tests/arelle/test_locale.py +0 -73
- tests/unit_tests/arelle/test_modelmanager.py +0 -15
- tests/unit_tests/arelle/test_packagemanager.py +0 -65
- tests/unit_tests/arelle/test_pluginmanager.py +0 -176
- tests/unit_tests/arelle/test_qname.py +0 -140
- tests/unit_tests/arelle/test_runtimeoptions.py +0 -56
- tests/unit_tests/arelle/test_system_info.py +0 -26
- tests/unit_tests/arelle/test_updater.py +0 -507
- tests/unit_tests/arelle/test_urlutil.py +0 -49
- tests/unit_tests/arelle/test_version.py +0 -46
- tests/unit_tests/arelle/utils/validate/test_decorator.py +0 -59
- /arelle/{examples/plugin/validate/XYZ → plugin/validate/EDINET}/rules/__init__.py +0 -0
- /arelle/plugin/validate/{HMRC → UK}/consistencyChecksByName.json +0 -0
- /arelle/plugin/validate/{HMRC → UK}/hmrc-taxonomies.xml +0 -0
- {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
|
-
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 = [
|
|
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
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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
|
|
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
|
|
349
|
-
|
|
350
|
-
|
|
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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
#
|
|
411
|
-
#
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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
|
-
|
|
448
|
-
|
|
449
|
-
if
|
|
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
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
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
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
-
|
|
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
|
-
|
|
631
|
-
shutil.rmtree(cachedProtocolDir
|
|
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):
|