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/PluginManager.py
CHANGED
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
'''
|
|
2
2
|
See COPYRIGHT.md for copyright information.
|
|
3
|
-
|
|
4
|
-
based on pull request 4
|
|
5
|
-
|
|
6
3
|
'''
|
|
7
4
|
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
|
|
6
|
+
import ast
|
|
7
|
+
import gettext
|
|
8
|
+
from glob import glob
|
|
10
9
|
import importlib.util
|
|
10
|
+
import json
|
|
11
11
|
import logging
|
|
12
|
-
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
import time
|
|
15
|
+
import traceback
|
|
16
|
+
import types
|
|
17
|
+
from collections import defaultdict
|
|
18
|
+
from collections.abc import Callable, Iterator
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from importlib.metadata import EntryPoint, entry_points
|
|
21
|
+
from numbers import Number
|
|
22
|
+
from pathlib import Path
|
|
13
23
|
from types import ModuleType
|
|
14
|
-
from typing import TYPE_CHECKING, Any,
|
|
15
|
-
|
|
24
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
25
|
+
|
|
16
26
|
import arelle.FileSource
|
|
27
|
+
from arelle.Locale import getLanguageCodes
|
|
28
|
+
from arelle.PythonUtil import isLegacyAbs
|
|
29
|
+
from arelle.typing import TypeGetText
|
|
17
30
|
from arelle.UrlUtil import isAbsolute
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
from collections import OrderedDict, defaultdict
|
|
20
|
-
from collections.abc import Callable
|
|
21
|
-
|
|
22
31
|
|
|
23
32
|
if TYPE_CHECKING:
|
|
24
33
|
# Prevent potential circular import error
|
|
25
34
|
from .Cntlr import Cntlr
|
|
26
35
|
|
|
36
|
+
|
|
37
|
+
_: TypeGetText
|
|
38
|
+
|
|
27
39
|
PLUGIN_TRACE_FILE = None
|
|
28
40
|
# PLUGIN_TRACE_FILE = "c:/temp/pluginerr.txt"
|
|
29
41
|
PLUGIN_TRACE_LEVEL = logging.WARNING
|
|
@@ -56,7 +68,7 @@ def init(cntlr: Cntlr, loadPluginConfig: bool = True) -> None:
|
|
|
56
68
|
if loadPluginConfig:
|
|
57
69
|
try:
|
|
58
70
|
pluginJsonFile = cntlr.userAppDir + os.sep + "plugins.json"
|
|
59
|
-
with
|
|
71
|
+
with open(pluginJsonFile, encoding='utf-8') as f:
|
|
60
72
|
pluginConfig = json.load(f)
|
|
61
73
|
freshenModuleInfos()
|
|
62
74
|
except Exception:
|
|
@@ -70,42 +82,63 @@ def init(cntlr: Cntlr, loadPluginConfig: bool = True) -> None:
|
|
|
70
82
|
modulePluginInfos = {} # dict of loaded module pluginInfo objects by module names
|
|
71
83
|
pluginMethodsForClasses = {} # dict by class of list of ordered callable function objects
|
|
72
84
|
|
|
73
|
-
def reset(): # force reloading modules and plugin infos
|
|
74
|
-
modulePluginInfos
|
|
75
|
-
|
|
85
|
+
def reset() -> None: # force reloading modules and plugin infos
|
|
86
|
+
if modulePluginInfos:
|
|
87
|
+
modulePluginInfos.clear() # dict of loaded module pluginInfo objects by module names
|
|
88
|
+
if pluginMethodsForClasses:
|
|
89
|
+
pluginMethodsForClasses.clear() # dict by class of list of ordered callable function objects
|
|
76
90
|
|
|
77
91
|
def orderedPluginConfig():
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
fieldOrder = [
|
|
93
|
+
'name',
|
|
94
|
+
'status',
|
|
95
|
+
'fileDate',
|
|
96
|
+
'version',
|
|
97
|
+
'description',
|
|
98
|
+
'moduleURL',
|
|
99
|
+
'localeURL',
|
|
100
|
+
'localeDomain',
|
|
101
|
+
'license',
|
|
102
|
+
'author',
|
|
103
|
+
'copyright',
|
|
104
|
+
'classMethods',
|
|
105
|
+
]
|
|
106
|
+
priorityIndex = {k: i for i, k in enumerate(fieldOrder)}
|
|
107
|
+
|
|
108
|
+
def sortModuleInfo(moduleInfo):
|
|
109
|
+
# Prioritize known fields by the index in fieldOrder; sort others alphabetically
|
|
110
|
+
orderedKeys = sorted(
|
|
111
|
+
moduleInfo.keys(),
|
|
112
|
+
key=lambda k: (priorityIndex.get(k, len(priorityIndex)), k)
|
|
113
|
+
)
|
|
114
|
+
return {k: moduleInfo[k] for k in orderedKeys}
|
|
115
|
+
|
|
116
|
+
orderedModules = {
|
|
117
|
+
moduleName: sortModuleInfo(pluginConfig['modules'][moduleName])
|
|
118
|
+
for moduleName in sorted(pluginConfig['modules'].keys())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
'modules': orderedModules,
|
|
123
|
+
'classes': dict(sorted(pluginConfig['classes'].items()))
|
|
124
|
+
}
|
|
95
125
|
|
|
96
126
|
def save(cntlr: Cntlr) -> None:
|
|
97
127
|
global pluginConfigChanged
|
|
98
128
|
if pluginConfigChanged and cntlr.hasFileSystem and not cntlr.disablePersistentConfig:
|
|
99
129
|
pluginJsonFile = cntlr.userAppDir + os.sep + "plugins.json"
|
|
100
|
-
with
|
|
130
|
+
with open(pluginJsonFile, 'w', encoding='utf-8') as f:
|
|
101
131
|
jsonStr = str(json.dumps(orderedPluginConfig(), ensure_ascii=False, indent=2)) # might not be unicode in 2.7
|
|
102
132
|
f.write(jsonStr)
|
|
103
133
|
pluginConfigChanged = False
|
|
104
134
|
|
|
105
|
-
def close(): # close all loaded methods
|
|
106
|
-
pluginConfig
|
|
107
|
-
|
|
108
|
-
|
|
135
|
+
def close() -> None: # close all loaded methods
|
|
136
|
+
if pluginConfig is not None:
|
|
137
|
+
pluginConfig.clear()
|
|
138
|
+
if modulePluginInfos is not None:
|
|
139
|
+
modulePluginInfos.clear()
|
|
140
|
+
if pluginMethodsForClasses is not None:
|
|
141
|
+
pluginMethodsForClasses.clear()
|
|
109
142
|
global webCache
|
|
110
143
|
webCache = None
|
|
111
144
|
|
|
@@ -148,7 +181,6 @@ moduleInfo = {
|
|
|
148
181
|
|
|
149
182
|
'''
|
|
150
183
|
|
|
151
|
-
|
|
152
184
|
def logPluginTrace(message: str, level: Number) -> None:
|
|
153
185
|
"""
|
|
154
186
|
If plugin trace file logging is configured, logs `message` to it.
|
|
@@ -156,7 +188,6 @@ def logPluginTrace(message: str, level: Number) -> None:
|
|
|
156
188
|
:param message: Message to be logged
|
|
157
189
|
:param level: Log level of message (e.g. logging.INFO)
|
|
158
190
|
"""
|
|
159
|
-
global pluginTraceFileLogger
|
|
160
191
|
if pluginTraceFileLogger:
|
|
161
192
|
pluginTraceFileLogger.log(level, message)
|
|
162
193
|
if level >= logging.ERROR:
|
|
@@ -188,8 +219,9 @@ def modulesWithNewerFileDates():
|
|
|
188
219
|
|
|
189
220
|
def freshenModuleInfos():
|
|
190
221
|
# for modules with different date-times, re-load module info
|
|
191
|
-
|
|
192
|
-
|
|
222
|
+
missingEnabledModules = []
|
|
223
|
+
for moduleName, moduleInfo in pluginConfig["modules"].items():
|
|
224
|
+
moduleEnabled = moduleInfo["status"] == "enabled"
|
|
193
225
|
freshenedFilename = _cntlr.webCache.getfilename(moduleInfo["moduleURL"], checkModifiedTime=True, normalize=True, base=_pluginBase)
|
|
194
226
|
try: # check if moduleInfo cached may differ from referenced moduleInfo
|
|
195
227
|
if os.path.isdir(freshenedFilename): # if freshenedFilename is a directory containing an __ini__.py file, open that instead
|
|
@@ -199,9 +231,17 @@ def freshenModuleInfos():
|
|
|
199
231
|
freshenedFilename += ".py" # extension module without .py suffix
|
|
200
232
|
if os.path.exists(freshenedFilename):
|
|
201
233
|
if moduleInfo["fileDate"] != time.strftime('%Y-%m-%dT%H:%M:%S UTC', time.gmtime(os.path.getmtime(freshenedFilename))):
|
|
202
|
-
freshenedModuleInfo = moduleModuleInfo(moduleInfo["moduleURL"], reload=True)
|
|
234
|
+
freshenedModuleInfo = moduleModuleInfo(moduleURL=moduleInfo["moduleURL"], reload=True)
|
|
203
235
|
if freshenedModuleInfo is not None:
|
|
204
|
-
|
|
236
|
+
if freshenedModuleInfo["name"] == moduleName:
|
|
237
|
+
pluginConfig["modules"][moduleName] = freshenedModuleInfo
|
|
238
|
+
else:
|
|
239
|
+
# Module has been re-named
|
|
240
|
+
if moduleEnabled:
|
|
241
|
+
missingEnabledModules.append(moduleName)
|
|
242
|
+
# User can avoid pruning by disabling plugin
|
|
243
|
+
elif moduleEnabled:
|
|
244
|
+
missingEnabledModules.append(moduleName)
|
|
205
245
|
else:
|
|
206
246
|
_msg = _("File not found for '{name}' plug-in when attempting to update module info. Path: '{path}'")\
|
|
207
247
|
.format(name=moduleName, path=freshenedFilename)
|
|
@@ -209,135 +249,267 @@ def freshenModuleInfos():
|
|
|
209
249
|
except Exception as err:
|
|
210
250
|
_msg = _("Exception at plug-in method freshenModuleInfos: {error}").format(error=err)
|
|
211
251
|
logPluginTrace(_msg, logging.ERROR)
|
|
252
|
+
for moduleName in missingEnabledModules:
|
|
253
|
+
removePluginModule(moduleName)
|
|
254
|
+
# Try re-adding plugin modules by name (for plugins that moved from built-in to pip installed)
|
|
255
|
+
moduleInfo = addPluginModule(moduleName)
|
|
256
|
+
if moduleInfo:
|
|
257
|
+
pluginConfig["modules"][moduleInfo["name"]] = moduleInfo
|
|
258
|
+
loadModule(moduleInfo)
|
|
259
|
+
logPluginTrace(_("Reloaded plugin that failed loading: {} {}").format(moduleName, moduleInfo), logging.INFO)
|
|
260
|
+
else:
|
|
261
|
+
logPluginTrace(_("Removed plugin that failed loading (plugin may have been archived): {}").format(moduleName), logging.ERROR)
|
|
262
|
+
save(_cntlr)
|
|
263
|
+
|
|
212
264
|
|
|
213
|
-
def
|
|
265
|
+
def normalizeModuleFilename(moduleFilename: str) -> str | None:
|
|
266
|
+
"""
|
|
267
|
+
Attempts to find python script as plugin entry point.
|
|
268
|
+
A value will be returned
|
|
269
|
+
if `moduleFilename` exists as-is,
|
|
270
|
+
if `moduleFilename` is a directory containing __init__.py, or
|
|
271
|
+
if `moduleFilename` with .py extension added exists
|
|
272
|
+
:param moduleFilename:
|
|
273
|
+
:return: Normalized filename, if exists
|
|
274
|
+
"""
|
|
275
|
+
if os.path.isfile(moduleFilename):
|
|
276
|
+
# moduleFilename exists as-is, use it
|
|
277
|
+
return moduleFilename
|
|
278
|
+
if os.path.isdir(moduleFilename):
|
|
279
|
+
# moduleFilename is a directory, only valid script is __init__.py contained inside
|
|
280
|
+
initPath = os.path.join(moduleFilename, "__init__.py")
|
|
281
|
+
if os.path.isfile(initPath):
|
|
282
|
+
return initPath
|
|
283
|
+
else:
|
|
284
|
+
return None
|
|
285
|
+
if not moduleFilename.endswith(".py"):
|
|
286
|
+
# moduleFilename is not a file or directory, try adding .py
|
|
287
|
+
pyPath = moduleFilename + ".py"
|
|
288
|
+
if os.path.exists(pyPath):
|
|
289
|
+
return pyPath
|
|
290
|
+
return None
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def getModuleFilename(moduleURL: str, reload: bool, normalize: bool, base: str | None) -> tuple[str | None, EntryPoint | None]:
|
|
214
294
|
#TODO several directories, eg User Application Data
|
|
215
|
-
moduleFilename = _cntlr.webCache.getfilename(moduleURL, reload=reload, normalize=
|
|
295
|
+
moduleFilename = _cntlr.webCache.getfilename(moduleURL, reload=reload, normalize=normalize, base=base)
|
|
296
|
+
if moduleFilename:
|
|
297
|
+
# `moduleURL` was mapped to a local filepath
|
|
298
|
+
moduleFilename = normalizeModuleFilename(moduleFilename)
|
|
299
|
+
if moduleFilename:
|
|
300
|
+
# `moduleFilename` normalized to an existing script
|
|
301
|
+
return moduleFilename, None
|
|
302
|
+
if base and not _isAbsoluteModuleURL(moduleURL):
|
|
303
|
+
# Search for a matching plugin deeper in the plugin directory tree.
|
|
304
|
+
# Handles cases where a plugin exists in a nested structure, such as
|
|
305
|
+
# when a developer clones an entire repository into the plugin directory.
|
|
306
|
+
# Example: arelle/plugin/xule/plugin/xule/__init__.py
|
|
307
|
+
for path in glob("**/" + moduleURL.replace('\\', '/'), recursive=True):
|
|
308
|
+
if normalizedPath := normalizeModuleFilename(path):
|
|
309
|
+
return normalizedPath, None
|
|
310
|
+
# `moduleFilename` did not map to a local filepath or did not normalize to a script
|
|
311
|
+
# Try using `moduleURL` to search for pip-installed entry point
|
|
312
|
+
entryPointRef = EntryPointRef.get(moduleURL)
|
|
313
|
+
if entryPointRef is not None:
|
|
314
|
+
return entryPointRef.moduleFilename, entryPointRef.entryPoint
|
|
315
|
+
return None, None
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def parsePluginInfo(moduleURL: str, moduleFilename: str, entryPoint: EntryPoint | None) -> dict | None:
|
|
319
|
+
moduleDir, moduleName = os.path.split(moduleFilename)
|
|
320
|
+
f = arelle.FileSource.openFileStream(_cntlr, moduleFilename)
|
|
321
|
+
tree = ast.parse(f.read(), filename=moduleFilename)
|
|
322
|
+
constantStrings = {}
|
|
323
|
+
functionDefNames = set()
|
|
324
|
+
methodDefNamesByClass = defaultdict(set)
|
|
325
|
+
moduleImports = []
|
|
326
|
+
moduleInfo = {"name":None}
|
|
327
|
+
isPlugin = False
|
|
328
|
+
for item in tree.body:
|
|
329
|
+
if isinstance(item, ast.Assign):
|
|
330
|
+
try:
|
|
331
|
+
attr = item.targets[0].id
|
|
332
|
+
except AttributeError:
|
|
333
|
+
# Not plugininfo
|
|
334
|
+
continue
|
|
335
|
+
if attr == "__pluginInfo__":
|
|
336
|
+
isPlugin = True
|
|
337
|
+
f.close()
|
|
338
|
+
classMethods = []
|
|
339
|
+
importURLs = []
|
|
340
|
+
for i, key in enumerate(item.value.keys):
|
|
341
|
+
_key = key.value
|
|
342
|
+
_value = item.value.values[i]
|
|
343
|
+
_valueType = _value.__class__.__name__
|
|
344
|
+
if _key == "import":
|
|
345
|
+
if _valueType == 'Constant':
|
|
346
|
+
importURLs.append(_value.value)
|
|
347
|
+
elif _valueType in ("List", "Tuple"):
|
|
348
|
+
for elt in _value.elts:
|
|
349
|
+
importURLs.append(elt.value)
|
|
350
|
+
elif _valueType == 'Constant':
|
|
351
|
+
moduleInfo[_key] = _value.value
|
|
352
|
+
elif _valueType == 'Name':
|
|
353
|
+
if _value.id in constantStrings:
|
|
354
|
+
moduleInfo[_key] = constantStrings[_value.id]
|
|
355
|
+
elif _value.id in functionDefNames:
|
|
356
|
+
classMethods.append(_key)
|
|
357
|
+
elif _valueType == 'Attribute':
|
|
358
|
+
if _value.attr in methodDefNamesByClass[_value.value.id]:
|
|
359
|
+
classMethods.append(_key)
|
|
360
|
+
elif _valueType in ("List", "Tuple"):
|
|
361
|
+
values = [elt.value for elt in _value.elts]
|
|
362
|
+
if _key == "imports":
|
|
363
|
+
importURLs = values
|
|
364
|
+
else:
|
|
365
|
+
moduleInfo[_key] = values
|
|
366
|
+
|
|
367
|
+
moduleInfo['classMethods'] = classMethods
|
|
368
|
+
moduleInfo['importURLs'] = importURLs
|
|
369
|
+
moduleInfo["moduleURL"] = moduleURL
|
|
370
|
+
moduleInfo["path"] = moduleFilename
|
|
371
|
+
moduleInfo["status"] = 'enabled'
|
|
372
|
+
moduleInfo["fileDate"] = time.strftime('%Y-%m-%dT%H:%M:%S UTC', time.gmtime(os.path.getmtime(moduleFilename)))
|
|
373
|
+
if entryPoint:
|
|
374
|
+
moduleInfo["moduleURL"] = moduleFilename # pip-installed plugins need absolute filepath
|
|
375
|
+
moduleInfo["entryPoint"] = {
|
|
376
|
+
"module": entryPoint.module,
|
|
377
|
+
"name": entryPoint.name,
|
|
378
|
+
"version": entryPoint.dist.version if hasattr(entryPoint, 'dist') else None,
|
|
379
|
+
}
|
|
380
|
+
if not moduleInfo.get("version"):
|
|
381
|
+
moduleInfo["version"] = entryPoint.dist.version # If no explicit version, retrieve from entry point
|
|
382
|
+
elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): # possible constant used in plugininfo, such as VERSION
|
|
383
|
+
for assignmentName in item.targets:
|
|
384
|
+
constantStrings[assignmentName.id] = item.value.value
|
|
385
|
+
elif isinstance(item, ast.ImportFrom):
|
|
386
|
+
if item.level == 1: # starts with .
|
|
387
|
+
if item.module is None: # from . import module1, module2, ...
|
|
388
|
+
for importee in item.names:
|
|
389
|
+
if importee.name == '*': #import all submodules
|
|
390
|
+
for _file in os.listdir(moduleDir):
|
|
391
|
+
if _file != moduleName and os.path.isfile(_file) and _file.endswith(".py"):
|
|
392
|
+
moduleImports.append(_file)
|
|
393
|
+
elif (os.path.isfile(os.path.join(moduleDir, importee.name + ".py"))
|
|
394
|
+
and importee.name not in moduleImports):
|
|
395
|
+
moduleImports.append(importee.name)
|
|
396
|
+
else:
|
|
397
|
+
modulePkgs = item.module.split('.')
|
|
398
|
+
modulePath = os.path.join(*modulePkgs)
|
|
399
|
+
if (os.path.isfile(os.path.join(moduleDir, modulePath) + ".py")
|
|
400
|
+
and modulePath not in moduleImports):
|
|
401
|
+
moduleImports.append(modulePath)
|
|
402
|
+
for importee in item.names:
|
|
403
|
+
_importeePfxName = os.path.join(modulePath, importee.name)
|
|
404
|
+
if (os.path.isfile(os.path.join(moduleDir, _importeePfxName) + ".py")
|
|
405
|
+
and _importeePfxName not in moduleImports):
|
|
406
|
+
moduleImports.append(_importeePfxName)
|
|
407
|
+
elif isinstance(item, ast.FunctionDef): # possible functionDef used in plugininfo
|
|
408
|
+
functionDefNames.add(item.name)
|
|
409
|
+
elif isinstance(item, ast.ClassDef): # possible ClassDef used in plugininfo
|
|
410
|
+
for classItem in item.body:
|
|
411
|
+
if isinstance(classItem, ast.FunctionDef):
|
|
412
|
+
methodDefNamesByClass[item.name].add(classItem.name)
|
|
413
|
+
moduleInfo["moduleImports"] = moduleImports
|
|
414
|
+
f.close()
|
|
415
|
+
return moduleInfo if isPlugin else None
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def moduleModuleInfo(
|
|
419
|
+
moduleURL: str | None = None,
|
|
420
|
+
entryPoint: EntryPoint | None = None,
|
|
421
|
+
reload: bool = False,
|
|
422
|
+
parentImportsSubtree: bool = False) -> dict | None:
|
|
423
|
+
"""
|
|
424
|
+
Generates a module info dict based on the provided `moduleURL` or `entryPoint`
|
|
425
|
+
Exactly one of "moduleURL" or "entryPoint" must be provided, otherwise a RuntimeError will be thrown.
|
|
426
|
+
|
|
427
|
+
When `moduleURL` is provided, it will be treated as a file path and will attempt to be normalized and
|
|
428
|
+
mapped to an existing plugin based on file location. If `moduleURL` fails to be mapped to an existing
|
|
429
|
+
plugin on its own, it will instead be used to search for an entry point. If found, this function will
|
|
430
|
+
proceed as if that entry point was provided for `entryPoint`.
|
|
431
|
+
|
|
432
|
+
When `entryPoint` is provided, it's location and other details will be used to generate the module info
|
|
433
|
+
dictionary.
|
|
434
|
+
|
|
435
|
+
:param moduleURL: A URL that loosely maps to the file location of a plugin (may be transformed)
|
|
436
|
+
:param entryPoint: An `EntryPoint` instance
|
|
437
|
+
:param reload:
|
|
438
|
+
:param parentImportsSubtree:
|
|
439
|
+
:return:s
|
|
440
|
+
"""
|
|
441
|
+
if (moduleURL is None) == (entryPoint is None):
|
|
442
|
+
raise RuntimeError('Exactly one of "moduleURL" or "entryPoint" must be provided')
|
|
443
|
+
if entryPoint:
|
|
444
|
+
# If entry point is provided, use it to retrieve `moduleFilename`
|
|
445
|
+
moduleFilename = moduleURL = entryPoint.load()()
|
|
446
|
+
else:
|
|
447
|
+
# Otherwise, we will verify the path before continuing
|
|
448
|
+
moduleFilename, entryPoint = getModuleFilename(moduleURL, reload=reload, normalize=True, base=_pluginBase)
|
|
449
|
+
|
|
216
450
|
if moduleFilename:
|
|
217
|
-
f = None
|
|
218
451
|
try:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return None
|
|
225
|
-
elif not moduleFilename.endswith(".py") and not os.path.exists(moduleFilename) and os.path.exists(moduleFilename + ".py"):
|
|
226
|
-
moduleFilename += ".py" # extension module without .py suffix
|
|
452
|
+
logPluginTrace(f"Scanning module for plug-in info: {moduleFilename}", logging.INFO)
|
|
453
|
+
moduleInfo = parsePluginInfo(moduleURL, moduleFilename, entryPoint)
|
|
454
|
+
if moduleInfo is None:
|
|
455
|
+
return None
|
|
456
|
+
|
|
227
457
|
moduleDir, moduleName = os.path.split(moduleFilename)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
for
|
|
236
|
-
if
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
elif _url == "module_subtree":
|
|
278
|
-
for _dir in os.listdir(moduleDir):
|
|
279
|
-
_subtreeModule = os.path.join(moduleDir,_dir)
|
|
280
|
-
if os.path.isdir(_subtreeModule) and _dir != "__pycache__":
|
|
281
|
-
mergedImportURLs.append(_subtreeModule)
|
|
282
|
-
else:
|
|
283
|
-
mergedImportURLs.append(_url)
|
|
284
|
-
if parentImportsSubtree and not _moduleImportsSubtree:
|
|
285
|
-
_moduleImportsSubtree = True
|
|
286
|
-
for moduleImport in moduleImports:
|
|
287
|
-
mergedImportURLs.append(moduleImport + ".py")
|
|
288
|
-
imports = []
|
|
289
|
-
for _url in mergedImportURLs:
|
|
290
|
-
if isAbsolute(_url) or os.path.isabs(_url):
|
|
291
|
-
_importURL = _url # URL is absolute http or local file system
|
|
292
|
-
else: # check if exists relative to this module's directory
|
|
293
|
-
_importURL = os.path.join(os.path.dirname(moduleURL), os.path.normpath(_url))
|
|
294
|
-
if not os.path.exists(_importURL): # not relative to this plugin, assume standard plugin base
|
|
295
|
-
_importURL = _url # moduleModuleInfo adjusts relative URL to plugin base
|
|
296
|
-
_importModuleInfo = moduleModuleInfo(_importURL, reload, _moduleImportsSubtree)
|
|
297
|
-
if _importModuleInfo:
|
|
298
|
-
_importModuleInfo["isImported"] = True
|
|
299
|
-
imports.append(_importModuleInfo)
|
|
300
|
-
moduleInfo["imports"] = imports
|
|
301
|
-
return moduleInfo
|
|
302
|
-
elif isinstance(item.value, ast.Str): # possible constant used in plugininfo, such as VERSION
|
|
303
|
-
for assignmentName in item.targets:
|
|
304
|
-
constantStrings[assignmentName.id] = item.value.s
|
|
305
|
-
elif isinstance(item, ast.ImportFrom):
|
|
306
|
-
if item.level == 1: # starts with .
|
|
307
|
-
if item.module is None: # from . import module1, module2, ...
|
|
308
|
-
for importee in item.names:
|
|
309
|
-
if importee.name == '*': #import all submodules
|
|
310
|
-
for _file in os.listdir(moduleDir):
|
|
311
|
-
if _file != moduleFile and os.path.isfile(_file) and _file.endswith(".py"):
|
|
312
|
-
moduleImports.append(_file)
|
|
313
|
-
elif (os.path.isfile(os.path.join(moduleDir, importee.name + ".py"))
|
|
314
|
-
and importee.name not in moduleImports):
|
|
315
|
-
moduleImports.append(importee.name)
|
|
316
|
-
else:
|
|
317
|
-
modulePkgs = item.module.split('.')
|
|
318
|
-
modulePath = os.path.join(*modulePkgs)
|
|
319
|
-
if (os.path.isfile(os.path.join(moduleDir, modulePath) + ".py")
|
|
320
|
-
and modulePath not in moduleImports):
|
|
321
|
-
moduleImports.append(modulePath)
|
|
322
|
-
for importee in item.names:
|
|
323
|
-
_importeePfxName = os.path.join(modulePath, importee.name)
|
|
324
|
-
if (os.path.isfile(os.path.join(moduleDir, _importeePfxName) + ".py")
|
|
325
|
-
and _importeePfxName not in moduleImports):
|
|
326
|
-
moduleImports.append(_importeePfxName)
|
|
327
|
-
elif isinstance(item, ast.FunctionDef): # possible functionDef used in plugininfo
|
|
328
|
-
functionDefNames.add(item.name)
|
|
329
|
-
elif isinstance(item, ast.ClassDef): # possible ClassDef used in plugininfo
|
|
330
|
-
for classItem in item.body:
|
|
331
|
-
if isinstance(classItem, ast.FunctionDef):
|
|
332
|
-
methodDefNamesByClass[item.name].add(classItem.name)
|
|
458
|
+
importURLs = moduleInfo["importURLs"]
|
|
459
|
+
del moduleInfo["importURLs"]
|
|
460
|
+
moduleImports = moduleInfo["moduleImports"]
|
|
461
|
+
del moduleInfo["moduleImports"]
|
|
462
|
+
moduleImportsSubtree = False
|
|
463
|
+
mergedImportURLs = []
|
|
464
|
+
|
|
465
|
+
for url in importURLs:
|
|
466
|
+
if url.startswith("module_import"):
|
|
467
|
+
for moduleImport in moduleImports:
|
|
468
|
+
mergedImportURLs.append(moduleImport + ".py")
|
|
469
|
+
if url == "module_import_subtree":
|
|
470
|
+
moduleImportsSubtree = True
|
|
471
|
+
elif url == "module_subtree":
|
|
472
|
+
for _dir in os.listdir(moduleDir):
|
|
473
|
+
subtreeModule = os.path.join(moduleDir,_dir)
|
|
474
|
+
if os.path.isdir(subtreeModule) and _dir != "__pycache__":
|
|
475
|
+
mergedImportURLs.append(subtreeModule)
|
|
476
|
+
else:
|
|
477
|
+
mergedImportURLs.append(url)
|
|
478
|
+
if parentImportsSubtree and not moduleImportsSubtree:
|
|
479
|
+
moduleImportsSubtree = True
|
|
480
|
+
for moduleImport in moduleImports:
|
|
481
|
+
mergedImportURLs.append(moduleImport + ".py")
|
|
482
|
+
imports = []
|
|
483
|
+
for url in mergedImportURLs:
|
|
484
|
+
importURL = url
|
|
485
|
+
if not _isAbsoluteModuleURL(url):
|
|
486
|
+
# Handle relative imports when plugin is loaded from external directory.
|
|
487
|
+
# When EDGAR/render imports EDGAR/validate, this works if EDGAR is in the plugin directory
|
|
488
|
+
# but fails if loaded externally (e.g., dev repo clone at /dev/path/to/EDGAR/).
|
|
489
|
+
# Solution: Find common path segments to resolve /dev/path/to/EDGAR/validate
|
|
490
|
+
# from the importing module at /dev/path/to/EDGAR/render.
|
|
491
|
+
modulePath = Path(moduleFilename)
|
|
492
|
+
importPath = Path(url)
|
|
493
|
+
if importPath.parts:
|
|
494
|
+
importFirstPart = importPath.parts[0]
|
|
495
|
+
for i, modulePathPart in enumerate(reversed(modulePath.parts)):
|
|
496
|
+
if modulePathPart != importFirstPart:
|
|
497
|
+
continue
|
|
498
|
+
# Found a potential branching point, construct and check a new path
|
|
499
|
+
candidateImportURL = str(modulePath.parents[i] / importPath)
|
|
500
|
+
if normalizeModuleFilename(candidateImportURL):
|
|
501
|
+
importURL = candidateImportURL
|
|
502
|
+
importModuleInfo = moduleModuleInfo(moduleURL=importURL, reload=reload, parentImportsSubtree=moduleImportsSubtree)
|
|
503
|
+
if importModuleInfo:
|
|
504
|
+
importModuleInfo["isImported"] = True
|
|
505
|
+
imports.append(importModuleInfo)
|
|
506
|
+
moduleInfo["imports"] = imports
|
|
333
507
|
logPluginTrace(f"Successful module plug-in info: {moduleFilename}", logging.INFO)
|
|
508
|
+
return moduleInfo
|
|
334
509
|
except Exception as err:
|
|
335
510
|
_msg = _("Exception obtaining plug-in module info: {moduleFilename}\n{error}\n{traceback}").format(
|
|
336
511
|
error=err, moduleFilename=moduleFilename, traceback=traceback.format_tb(sys.exc_info()[2]))
|
|
337
512
|
logPluginTrace(_msg, logging.ERROR)
|
|
338
|
-
|
|
339
|
-
if f:
|
|
340
|
-
f.close()
|
|
341
513
|
return None
|
|
342
514
|
|
|
343
515
|
|
|
@@ -350,43 +522,30 @@ def moduleInfo(pluginInfo):
|
|
|
350
522
|
moduleInfo.getdefault('classes', []).append(name)
|
|
351
523
|
|
|
352
524
|
|
|
353
|
-
def
|
|
354
|
-
|
|
355
|
-
pluginBase: str,
|
|
356
|
-
moduleURL: str,
|
|
357
|
-
packagePrefix: str = "",
|
|
358
|
-
) -> tuple[str, str, str] | tuple[None, None, None]:
|
|
359
|
-
"""Get the name, directory and prefix of a module."""
|
|
360
|
-
moduleFilename: str
|
|
361
|
-
moduleDir: str
|
|
362
|
-
packageImportPrefix: str
|
|
525
|
+
def _isAbsoluteModuleURL(moduleURL: str) -> bool:
|
|
526
|
+
return isAbsolute(moduleURL) or isLegacyAbs(moduleURL)
|
|
363
527
|
|
|
364
|
-
moduleFilename = controller.webCache.getfilename(
|
|
365
|
-
url=moduleURL, normalize=True, base=pluginBase
|
|
366
|
-
)
|
|
367
528
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
os.path.join(moduleFilename, "__init__.py")
|
|
378
|
-
):
|
|
379
|
-
moduleDir = os.path.dirname(moduleFilename)
|
|
380
|
-
moduleName = os.path.basename(moduleFilename)
|
|
381
|
-
packageImportPrefix = moduleName + "."
|
|
382
|
-
else:
|
|
383
|
-
moduleName = os.path.basename(moduleFilename).partition(".")[0]
|
|
384
|
-
moduleDir = os.path.dirname(moduleFilename)
|
|
385
|
-
packageImportPrefix = packagePrefix
|
|
529
|
+
def _get_name_dir_prefix(modulePath: Path, packagePrefix: str = "") -> tuple[str, str, str] | tuple[None, None, None]:
|
|
530
|
+
"""Get the name, directory and prefix of a module."""
|
|
531
|
+
moduleName = None
|
|
532
|
+
moduleDir = None
|
|
533
|
+
packageImportPrefix = None
|
|
534
|
+
initFileName = "__init__.py"
|
|
535
|
+
|
|
536
|
+
if modulePath.is_file() and modulePath.name == initFileName:
|
|
537
|
+
modulePath = modulePath.parent
|
|
386
538
|
|
|
387
|
-
|
|
539
|
+
if modulePath.is_dir() and (modulePath / initFileName).is_file():
|
|
540
|
+
moduleName = modulePath.name
|
|
541
|
+
moduleDir = str(modulePath.parent)
|
|
542
|
+
packageImportPrefix = moduleName + "."
|
|
543
|
+
elif modulePath.is_file() and modulePath.suffix == ".py":
|
|
544
|
+
moduleName = modulePath.stem
|
|
545
|
+
moduleDir = str(modulePath.parent)
|
|
546
|
+
packageImportPrefix = packagePrefix
|
|
388
547
|
|
|
389
|
-
return (
|
|
548
|
+
return (moduleName, moduleDir, packageImportPrefix)
|
|
390
549
|
|
|
391
550
|
def _get_location(moduleDir: str, moduleName: str) -> str:
|
|
392
551
|
"""Get the file name of a plugin."""
|
|
@@ -416,13 +575,9 @@ def _find_and_load_module(moduleDir: str, moduleName: str) -> ModuleType | None:
|
|
|
416
575
|
def loadModule(moduleInfo: dict[str, Any], packagePrefix: str="") -> None:
|
|
417
576
|
name = moduleInfo['name']
|
|
418
577
|
moduleURL = moduleInfo['moduleURL']
|
|
578
|
+
modulePath = Path(moduleInfo['path'])
|
|
419
579
|
|
|
420
|
-
moduleName, moduleDir, packageImportPrefix = _get_name_dir_prefix(
|
|
421
|
-
controller=_cntlr,
|
|
422
|
-
pluginBase=_pluginBase,
|
|
423
|
-
moduleURL=moduleURL,
|
|
424
|
-
packagePrefix=packagePrefix,
|
|
425
|
-
)
|
|
580
|
+
moduleName, moduleDir, packageImportPrefix = _get_name_dir_prefix(modulePath, packagePrefix)
|
|
426
581
|
|
|
427
582
|
if all(p is None for p in [moduleName, moduleDir, packageImportPrefix]):
|
|
428
583
|
_cntlr.addToLog(message=_ERROR_MESSAGE_IMPORT_TEMPLATE.format(name), level=logging.ERROR)
|
|
@@ -439,10 +594,12 @@ def loadModule(moduleInfo: dict[str, Any], packagePrefix: str="") -> None:
|
|
|
439
594
|
localeDir = os.path.dirname(module.__file__) + os.sep + pluginInfo['localeURL']
|
|
440
595
|
try:
|
|
441
596
|
_gettext = gettext.translation(pluginInfo['localeDomain'], localeDir, getLanguageCodes())
|
|
442
|
-
except
|
|
443
|
-
_gettext
|
|
597
|
+
except OSError:
|
|
598
|
+
def _gettext(x):
|
|
599
|
+
return x # no translation
|
|
444
600
|
else:
|
|
445
|
-
_gettext
|
|
601
|
+
def _gettext(x):
|
|
602
|
+
return x
|
|
446
603
|
for key, value in pluginInfo.items():
|
|
447
604
|
if key == 'name':
|
|
448
605
|
if name:
|
|
@@ -474,6 +631,11 @@ def loadModule(moduleInfo: dict[str, Any], packagePrefix: str="") -> None:
|
|
|
474
631
|
name=name, error=err, traceback=traceback.format_tb(sys.exc_info()[2]))
|
|
475
632
|
logPluginTrace(_msg, logging.ERROR)
|
|
476
633
|
|
|
634
|
+
|
|
635
|
+
def hasPluginWithHook(name: str) -> bool:
|
|
636
|
+
return next(pluginClassMethods(name), None) is not None
|
|
637
|
+
|
|
638
|
+
|
|
477
639
|
def pluginClassMethods(className: str) -> Iterator[Callable[..., Any]]:
|
|
478
640
|
if pluginConfig:
|
|
479
641
|
try:
|
|
@@ -495,8 +657,7 @@ def pluginClassMethods(className: str) -> Iterator[Callable[..., Any]]:
|
|
|
495
657
|
if className in pluginInfo:
|
|
496
658
|
pluginMethodsForClass.append(pluginInfo[className])
|
|
497
659
|
pluginMethodsForClasses[className] = pluginMethodsForClass
|
|
498
|
-
|
|
499
|
-
yield method
|
|
660
|
+
yield from pluginMethodsForClass
|
|
500
661
|
|
|
501
662
|
|
|
502
663
|
def addPluginModule(name: str) -> dict[str, Any] | None:
|
|
@@ -505,23 +666,20 @@ def addPluginModule(name: str) -> dict[str, Any] | None:
|
|
|
505
666
|
:param name: The name to search for
|
|
506
667
|
:return: The module information dictionary, if added. Otherwise, None.
|
|
507
668
|
"""
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if not plugin_module_info or not plugin_module_info.get("name"):
|
|
516
|
-
plugin_module_info = moduleModuleInfo(name)
|
|
517
|
-
return addPluginModuleInfo(plugin_module_info)
|
|
669
|
+
entryPointRef = EntryPointRef.get(name)
|
|
670
|
+
pluginModuleInfo = None
|
|
671
|
+
if entryPointRef:
|
|
672
|
+
pluginModuleInfo = entryPointRef.createModuleInfo()
|
|
673
|
+
if not pluginModuleInfo or not pluginModuleInfo.get("name"):
|
|
674
|
+
pluginModuleInfo = moduleModuleInfo(moduleURL=name)
|
|
675
|
+
return addPluginModuleInfo(pluginModuleInfo)
|
|
518
676
|
|
|
519
677
|
|
|
520
678
|
def reloadPluginModule(name):
|
|
521
679
|
if name in pluginConfig["modules"]:
|
|
522
680
|
url = pluginConfig["modules"][name].get("moduleURL")
|
|
523
681
|
if url:
|
|
524
|
-
moduleInfo = moduleModuleInfo(url, reload=True)
|
|
682
|
+
moduleInfo = moduleModuleInfo(moduleURL=url, reload=True)
|
|
525
683
|
if moduleInfo:
|
|
526
684
|
addPluginModule(url)
|
|
527
685
|
return True
|
|
@@ -585,26 +743,180 @@ def addPluginModuleInfo(plugin_module_info: dict[str, Any]) -> dict[str, Any] |
|
|
|
585
743
|
return plugin_module_info
|
|
586
744
|
|
|
587
745
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
return moduleModuleInfo(pluginUrl())
|
|
746
|
+
_entryPointRefCache: list[EntryPointRef] | None = None
|
|
747
|
+
_entryPointRefAliasCache: dict[str, list[EntryPointRef]] | None = None
|
|
748
|
+
_entryPointRefSearchTermEndings = [
|
|
749
|
+
'/__init__.py',
|
|
750
|
+
'.py'
|
|
751
|
+
'/'
|
|
752
|
+
]
|
|
596
753
|
|
|
597
754
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
:
|
|
602
|
-
:
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
755
|
+
@dataclass
|
|
756
|
+
class EntryPointRef:
|
|
757
|
+
aliases: set[str]
|
|
758
|
+
entryPoint: EntryPoint | None
|
|
759
|
+
moduleFilename: str | None
|
|
760
|
+
moduleInfo: dict | None
|
|
761
|
+
|
|
762
|
+
def createModuleInfo(self) -> dict | None:
|
|
763
|
+
"""
|
|
764
|
+
Creates a module information dictionary from the entry point ref.
|
|
765
|
+
:return: A module inforomation dictionary
|
|
766
|
+
"""
|
|
767
|
+
if self.entryPoint is not None:
|
|
768
|
+
return moduleModuleInfo(entryPoint=self.entryPoint)
|
|
769
|
+
return moduleModuleInfo(moduleURL=self.moduleFilename)
|
|
770
|
+
|
|
771
|
+
@staticmethod
|
|
772
|
+
def fromEntryPoint(entryPoint: EntryPoint) -> EntryPointRef | None:
|
|
773
|
+
"""
|
|
774
|
+
Given an entry point, retrieves the subset of information from __pluginInfo__ necessary to
|
|
775
|
+
determine if the entry point should be imported as a plugin.
|
|
776
|
+
:param entryPoint:
|
|
777
|
+
:return:
|
|
778
|
+
"""
|
|
779
|
+
pluginUrlFunc = entryPoint.load()
|
|
780
|
+
pluginUrl = pluginUrlFunc()
|
|
781
|
+
return EntryPointRef.fromFilepath(pluginUrl, entryPoint)
|
|
782
|
+
|
|
783
|
+
@staticmethod
|
|
784
|
+
def fromFilepath(filepath: str, entryPoint: EntryPoint | None = None) -> EntryPointRef | None:
|
|
785
|
+
"""
|
|
786
|
+
Given a filepath, retrieves a subset of information from __pluginInfo__ necessary to
|
|
787
|
+
determine if the entry point should be imported as a plugin.
|
|
788
|
+
:param filepath: Path to plugin, can be a directory or .py filepath
|
|
789
|
+
:param entryPoint: Optional entry point information to include in aliases/moduleInfo
|
|
790
|
+
:return:
|
|
791
|
+
"""
|
|
792
|
+
moduleFilename = _cntlr.webCache.getfilename(filepath)
|
|
793
|
+
if moduleFilename:
|
|
794
|
+
moduleFilename = normalizeModuleFilename(moduleFilename)
|
|
795
|
+
aliases = set()
|
|
796
|
+
if entryPoint:
|
|
797
|
+
aliases.add(entryPoint.name)
|
|
798
|
+
moduleInfo: dict | None = None
|
|
799
|
+
if moduleFilename:
|
|
800
|
+
moduleInfo = parsePluginInfo(moduleFilename, moduleFilename, entryPoint)
|
|
801
|
+
if moduleInfo is None:
|
|
802
|
+
return None
|
|
803
|
+
if "name" in moduleInfo:
|
|
804
|
+
aliases.add(moduleInfo["name"])
|
|
805
|
+
if "aliases" in moduleInfo:
|
|
806
|
+
aliases |= set(moduleInfo["aliases"])
|
|
807
|
+
return EntryPointRef(
|
|
808
|
+
aliases={EntryPointRef._normalizePluginSearchTerm(a) for a in aliases},
|
|
809
|
+
entryPoint=entryPoint,
|
|
810
|
+
moduleFilename=moduleFilename,
|
|
811
|
+
moduleInfo=moduleInfo,
|
|
812
|
+
)
|
|
813
|
+
|
|
814
|
+
@staticmethod
|
|
815
|
+
def discoverAll() -> list[EntryPointRef]:
|
|
816
|
+
"""
|
|
817
|
+
Retrieve all plugin entry points, cached on first run.
|
|
818
|
+
:return: List of all discovered entry points.
|
|
819
|
+
"""
|
|
820
|
+
global _entryPointRefCache
|
|
821
|
+
if _entryPointRefCache is None:
|
|
822
|
+
assert _pluginBase is not None
|
|
823
|
+
_entryPointRefCache = EntryPointRef._discoverBuiltIn([], cast(str, _pluginBase)) + EntryPointRef._discoverInstalled()
|
|
824
|
+
return _entryPointRefCache
|
|
825
|
+
|
|
826
|
+
@staticmethod
|
|
827
|
+
def _discoverBuiltIn(entryPointRefs: list[EntryPointRef], directory: str) -> list[EntryPointRef]:
|
|
828
|
+
"""
|
|
829
|
+
Recursively retrieve all plugin entry points in the given directory.
|
|
830
|
+
:param entryPointRefs: Working list of entry point refs to append to.
|
|
831
|
+
:param directory: Directory to search for entry points within.
|
|
832
|
+
:return: List of discovered entry points.
|
|
833
|
+
"""
|
|
834
|
+
for fileName in sorted(os.listdir(directory)):
|
|
835
|
+
if fileName in (".", "..", "__pycache__", "__init__.py", ".DS_Store", "site-packages"):
|
|
836
|
+
continue # Ignore these entries
|
|
837
|
+
filePath = os.path.join(directory, fileName)
|
|
838
|
+
if os.path.isdir(filePath):
|
|
839
|
+
EntryPointRef._discoverBuiltIn(entryPointRefs, filePath)
|
|
840
|
+
if os.path.isfile(filePath) and os.path.basename(filePath).endswith(".py"):
|
|
841
|
+
# If `filePath` references .py file directly, use it
|
|
842
|
+
moduleFilePath = filePath
|
|
843
|
+
elif os.path.isdir(filePath) and os.path.exists(initFilePath := os.path.join(filePath, "__init__.py")):
|
|
844
|
+
# Otherwise, if `filePath` is a directory containing `__init__.py`, use that
|
|
845
|
+
moduleFilePath = initFilePath
|
|
846
|
+
else:
|
|
847
|
+
continue
|
|
848
|
+
entryPointRef = EntryPointRef.fromFilepath(moduleFilePath)
|
|
849
|
+
if entryPointRef is not None:
|
|
850
|
+
entryPointRefs.append(entryPointRef)
|
|
851
|
+
return entryPointRefs
|
|
852
|
+
|
|
853
|
+
@staticmethod
|
|
854
|
+
def _discoverInstalled() -> list[EntryPointRef]:
|
|
855
|
+
"""
|
|
856
|
+
Retrieve all installed plugin entry points.
|
|
857
|
+
:return: List of all discovered entry points.
|
|
858
|
+
"""
|
|
859
|
+
entryPoints: list[EntryPoint]
|
|
860
|
+
if sys.version_info < (3, 10):
|
|
861
|
+
entryPoints = [e for e in entry_points().get('arelle.plugin', [])]
|
|
862
|
+
else:
|
|
863
|
+
entryPoints = list(entry_points(group='arelle.plugin'))
|
|
864
|
+
entryPointRefs = []
|
|
865
|
+
for entryPoint in entryPoints:
|
|
866
|
+
entryPointRef = EntryPointRef.fromEntryPoint(entryPoint)
|
|
867
|
+
if entryPointRef is not None:
|
|
868
|
+
entryPointRefs.append(entryPointRef)
|
|
869
|
+
return entryPointRefs
|
|
870
|
+
|
|
871
|
+
@staticmethod
|
|
872
|
+
def get(search: str) -> EntryPointRef | None:
|
|
873
|
+
"""
|
|
874
|
+
Retrieve an entry point ref with a matching name or alias.
|
|
875
|
+
May return None of no matches are found.
|
|
876
|
+
Throws an exception if multiple entry point refs match the search term.
|
|
877
|
+
:param search: Only retrieve entry point matching the given search text.
|
|
878
|
+
:return: Matching entry point ref, if found.
|
|
879
|
+
"""
|
|
880
|
+
entryPointRefs = EntryPointRef.search(search)
|
|
881
|
+
if len(entryPointRefs) == 0:
|
|
882
|
+
return None
|
|
883
|
+
elif len(entryPointRefs) > 1:
|
|
884
|
+
paths = [r.moduleFilename for r in entryPointRefs]
|
|
885
|
+
raise Exception(_('Multiple entry points matched search term "{}": {}').format(search, paths))
|
|
886
|
+
return entryPointRefs[0]
|
|
887
|
+
|
|
888
|
+
@staticmethod
|
|
889
|
+
def _normalizePluginSearchTerm(search: str) -> str:
|
|
890
|
+
"""
|
|
891
|
+
Normalizes the given search term or searchable text by:
|
|
892
|
+
Making slashes consistent
|
|
893
|
+
Removing common endings
|
|
894
|
+
:param search: Search term or searchable text
|
|
895
|
+
:return: Normalized string
|
|
896
|
+
"""
|
|
897
|
+
search = search.replace('\\', '/')
|
|
898
|
+
while True:
|
|
899
|
+
for ending in _entryPointRefSearchTermEndings:
|
|
900
|
+
if search.endswith(ending):
|
|
901
|
+
search = search[:-len(ending)]
|
|
902
|
+
break
|
|
903
|
+
return search.lower()
|
|
904
|
+
|
|
905
|
+
@staticmethod
|
|
906
|
+
def search(search: str) -> list[EntryPointRef] | None:
|
|
907
|
+
"""
|
|
908
|
+
Retrieve entry point module information matching provided search text.
|
|
909
|
+
A map of aliases to matching entry points is cached on the first run.
|
|
910
|
+
:param search: Only retrieve entry points matching the given search text.
|
|
911
|
+
:return: List of matching module infos.
|
|
912
|
+
"""
|
|
913
|
+
global _entryPointRefAliasCache
|
|
914
|
+
if _entryPointRefAliasCache is None:
|
|
915
|
+
entryPointRefAliasCache = defaultdict(list)
|
|
916
|
+
entryPointRefs = EntryPointRef.discoverAll()
|
|
917
|
+
for entryPointRef in entryPointRefs:
|
|
918
|
+
for alias in entryPointRef.aliases:
|
|
919
|
+
entryPointRefAliasCache[alias].append(entryPointRef)
|
|
920
|
+
_entryPointRefAliasCache = entryPointRefAliasCache
|
|
921
|
+
search = EntryPointRef._normalizePluginSearchTerm(search)
|
|
922
|
+
return _entryPointRefAliasCache.get(search, [])
|