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/Validate.py
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
'''
|
|
2
2
|
See COPYRIGHT.md for copyright information.
|
|
3
3
|
'''
|
|
4
|
+
import bisect
|
|
5
|
+
import fnmatch
|
|
4
6
|
import os, sys, traceback, logging
|
|
7
|
+
import time
|
|
8
|
+
from urllib.parse import unquote
|
|
9
|
+
import zipfile
|
|
10
|
+
|
|
5
11
|
import regex as re
|
|
6
12
|
from collections import defaultdict, OrderedDict
|
|
7
13
|
from arelle import (FileSource, ModelXbrl, ModelDocument, ModelVersReport, XbrlConst,
|
|
8
14
|
ValidateXbrl, ValidateVersReport,
|
|
9
|
-
ValidateInfoset,
|
|
15
|
+
ValidateInfoset, ViewFileRenderedLayout, UrlUtil)
|
|
16
|
+
from arelle.PythonUtil import isLegacyAbs
|
|
17
|
+
from arelle.ValidateFileSource import ValidateFileSource
|
|
10
18
|
from arelle.formula import ValidateFormula
|
|
11
19
|
from arelle.ModelDocument import Type, ModelDocumentReference, load as modelDocumentLoad
|
|
12
20
|
from arelle.ModelDtsObject import ModelResource
|
|
13
21
|
from arelle.ModelInstanceObject import ModelFact
|
|
14
22
|
from arelle.ModelObject import ModelObject
|
|
15
23
|
from arelle.ModelRelationshipSet import ModelRelationshipSet
|
|
16
|
-
from arelle.ModelTestcaseObject import testcaseVariationsByTarget
|
|
24
|
+
from arelle.ModelTestcaseObject import testcaseVariationsByTarget, ModelTestcaseVariation
|
|
17
25
|
from arelle.ModelValue import (qname, QName)
|
|
18
26
|
from arelle.PluginManager import pluginClassMethods
|
|
27
|
+
from arelle.packages.report.DetectReportPackage import isReportPackageExtension
|
|
28
|
+
from arelle.rendering import RenderingEvaluator
|
|
29
|
+
from arelle.utils.EntryPointDetection import filesourceEntrypointFiles
|
|
19
30
|
from arelle.XmlUtil import collapseWhitespace, xmlstring
|
|
20
31
|
|
|
21
32
|
def validate(modelXbrl):
|
|
@@ -52,6 +63,16 @@ class Validate:
|
|
|
52
63
|
else:
|
|
53
64
|
self.useFileSource = None
|
|
54
65
|
|
|
66
|
+
def filterTestcaseVariation(self, modelTestcaseVariation: ModelTestcaseVariation):
|
|
67
|
+
patterns = self.modelXbrl.modelManager.formulaOptions.testcaseFilters
|
|
68
|
+
if not patterns:
|
|
69
|
+
return True
|
|
70
|
+
variationIdPath = f'{unquote(modelTestcaseVariation.base)}:{modelTestcaseVariation.id}'
|
|
71
|
+
for pattern in patterns:
|
|
72
|
+
if fnmatch.fnmatch(variationIdPath, pattern):
|
|
73
|
+
return True
|
|
74
|
+
return False
|
|
75
|
+
|
|
55
76
|
def close(self):
|
|
56
77
|
self.instValidator.close(reusable=False)
|
|
57
78
|
self.formulaValidator.close(reusable=False)
|
|
@@ -112,7 +133,8 @@ class Validate:
|
|
|
112
133
|
self.modelXbrl.error("exception:" + type(err).__name__,
|
|
113
134
|
_("Instance validation exception: %(error)s, instance: %(instance)s"),
|
|
114
135
|
modelXbrl=self.modelXbrl,
|
|
115
|
-
instance=self.modelXbrl.modelDocument.basename,
|
|
136
|
+
instance=self.modelXbrl.modelDocument.basename if hasattr(self.modelXbrl, "modelDocument") and hasattr(self.modelXbrl.modelDocument, "basename") else "(closed)",
|
|
137
|
+
error=err,
|
|
116
138
|
# traceback=traceback.format_tb(sys.exc_info()[2]),
|
|
117
139
|
exc_info=(type(err) is not AssertionError))
|
|
118
140
|
self.close()
|
|
@@ -121,6 +143,10 @@ class Validate:
|
|
|
121
143
|
self.modelXbrl.info("info", "RSS Feed", modelDocument=self.modelXbrl)
|
|
122
144
|
from arelle.FileSource import openFileSource
|
|
123
145
|
reloadCache = getattr(self.modelXbrl, "reloadCache", False)
|
|
146
|
+
if self.modelXbrl.modelManager.formulaOptions.testcaseResultsCaptureWarnings:
|
|
147
|
+
errorCaptureLevel = logging._checkLevel("WARNING")
|
|
148
|
+
else:
|
|
149
|
+
errorCaptureLevel = logging._checkLevel("INCONSISTENCY")# default is INCONSISTENCY
|
|
124
150
|
for rssItem in self.modelXbrl.modelDocument.rssItems:
|
|
125
151
|
if getattr(rssItem, "skipRssItem", False):
|
|
126
152
|
self.modelXbrl.info("info", _("skipping RSS Item %(accessionNumber)s %(formType)s %(companyName)s %(period)s"),
|
|
@@ -130,9 +156,27 @@ class Validate:
|
|
|
130
156
|
modelObject=rssItem, accessionNumber=rssItem.accessionNumber, formType=rssItem.formType, companyName=rssItem.companyName, period=rssItem.period)
|
|
131
157
|
modelXbrl = None
|
|
132
158
|
try:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
159
|
+
rssItemUrl = rssItem.zippedUrl
|
|
160
|
+
if self.useFileSource.isArchive and (isLegacyAbs(rssItemUrl) or not rssItemUrl.endswith(".zip")):
|
|
161
|
+
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
162
|
+
openFileSource(rssItemUrl, self.modelXbrl.modelManager.cntlr, reloadCache=reloadCache),
|
|
163
|
+
_("validating"), rssItem=rssItem)
|
|
164
|
+
else: # need own file source, may need instance discovery
|
|
165
|
+
filesource = FileSource.openFileSource(rssItemUrl, self.modelXbrl.modelManager.cntlr)
|
|
166
|
+
if filesource and not filesource.selection and filesource.isArchive:
|
|
167
|
+
try:
|
|
168
|
+
entrypoints = filesourceEntrypointFiles(filesource)
|
|
169
|
+
if entrypoints:
|
|
170
|
+
# resolve an IXDS in entrypoints
|
|
171
|
+
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ArchiveIxds"):
|
|
172
|
+
pluginXbrlMethod(self, filesource,entrypoints)
|
|
173
|
+
filesource.select(entrypoints[0].get("file", None) )
|
|
174
|
+
except Exception as err:
|
|
175
|
+
self.modelXbrl.error("exception:" + type(err).__name__,
|
|
176
|
+
_("RSS item validation exception: %(error)s, entry URL: %(instance)s"),
|
|
177
|
+
modelXbrl=self.modelXbrl, instance=rssItemUrl, error=err)
|
|
178
|
+
continue # don't try to load this entry URL
|
|
179
|
+
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager, filesource, _("validating"), rssItem=rssItem, errorCaptureLevel=errorCaptureLevel)
|
|
136
180
|
for pluginXbrlMethod in pluginClassMethods("RssItem.Xbrl.Loaded"):
|
|
137
181
|
pluginXbrlMethod(modelXbrl, {}, rssItem)
|
|
138
182
|
if getattr(rssItem, "doNotProcessRSSitem", False) or modelXbrl.modelDocument is None:
|
|
@@ -166,377 +210,17 @@ class Validate:
|
|
|
166
210
|
for doc in sorted(testcase.referencesDocument.keys(), key=lambda doc: doc.uri):
|
|
167
211
|
self.validateTestcase(doc) # testcases doc's are sorted by their uri (file names), e.g., for formula
|
|
168
212
|
elif hasattr(testcase, "testcaseVariations"):
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
self.
|
|
172
|
-
|
|
173
|
-
resultIsVersioningReport = modelTestcaseVariation.resultIsVersioningReport
|
|
174
|
-
resultIsXbrlInstance = modelTestcaseVariation.resultIsXbrlInstance
|
|
175
|
-
resultIsTaxonomyPackage = modelTestcaseVariation.resultIsTaxonomyPackage
|
|
176
|
-
formulaOutputInstance = None
|
|
177
|
-
inputDTSes = defaultdict(list)
|
|
178
|
-
baseForElement = testcase.baseForElement(modelTestcaseVariation)
|
|
179
|
-
# try to load instance document
|
|
180
|
-
self.modelXbrl.info("info", _("Variation %(id)s%(name)s%(target)s: %(expected)s - %(description)s"),
|
|
181
|
-
modelObject=modelTestcaseVariation,
|
|
182
|
-
id=modelTestcaseVariation.id,
|
|
183
|
-
name=(" {}".format(modelTestcaseVariation.name) if modelTestcaseVariation.name else ""),
|
|
184
|
-
target=(" target {}".format(modelTestcaseVariation.ixdsTarget) if modelTestcaseVariation.ixdsTarget else ""),
|
|
185
|
-
expected=modelTestcaseVariation.expected,
|
|
186
|
-
description=modelTestcaseVariation.description)
|
|
187
|
-
if self.modelXbrl.modelManager.formulaOptions.testcaseResultsCaptureWarnings:
|
|
188
|
-
errorCaptureLevel = logging._checkLevel("WARNING")
|
|
213
|
+
testcaseVariations = []
|
|
214
|
+
for testcaseVariation in testcaseVariationsByTarget(testcase.testcaseVariations):
|
|
215
|
+
if self.filterTestcaseVariation(testcaseVariation):
|
|
216
|
+
testcaseVariations.append(testcaseVariation)
|
|
189
217
|
else:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
readMeFirstElements[i].qname.localName == "taxonomyPackage")
|
|
197
|
-
if isinstance(readMeFirstUri,tuple):
|
|
198
|
-
# dtsName is for formula instances, but is from/to dts if versioning
|
|
199
|
-
dtsName, readMeFirstUri = readMeFirstUri
|
|
200
|
-
elif resultIsVersioningReport:
|
|
201
|
-
if inputDTSes: dtsName = "to"
|
|
202
|
-
else: dtsName = "from"
|
|
203
|
-
else:
|
|
204
|
-
dtsName = None
|
|
205
|
-
if resultIsVersioningReport and dtsName: # build multi-schemaRef containing document
|
|
206
|
-
if dtsName in inputDTSes:
|
|
207
|
-
dtsName = inputDTSes[dtsName]
|
|
208
|
-
else:
|
|
209
|
-
modelXbrl = ModelXbrl.create(self.modelXbrl.modelManager,
|
|
210
|
-
Type.DTSENTRIES,
|
|
211
|
-
self.modelXbrl.modelManager.cntlr.webCache.normalizeUrl(readMeFirstUri[:-4] + ".dts", baseForElement),
|
|
212
|
-
isEntry=True,
|
|
213
|
-
errorCaptureLevel=errorCaptureLevel)
|
|
214
|
-
DTSdoc = modelXbrl.modelDocument
|
|
215
|
-
DTSdoc.inDTS = True
|
|
216
|
-
doc = modelDocumentLoad(modelXbrl, readMeFirstUri, base=baseForElement)
|
|
217
|
-
if doc is not None:
|
|
218
|
-
DTSdoc.referencesDocument[doc] = ModelDocumentReference("import", DTSdoc.xmlRootElement) #fake import
|
|
219
|
-
doc.inDTS = True
|
|
220
|
-
elif resultIsTaxonomyPackage:
|
|
221
|
-
from arelle import PackageManager, PrototypeInstanceObject
|
|
222
|
-
dtsName = readMeFirstUri
|
|
223
|
-
modelXbrl = PrototypeInstanceObject.XbrlPrototype(self.modelXbrl.modelManager, readMeFirstUri)
|
|
224
|
-
PackageManager.packageInfo(self.modelXbrl.modelManager.cntlr, readMeFirstUri, reload=True, errors=modelXbrl.errors)
|
|
225
|
-
else: # not a multi-schemaRef versioning report
|
|
226
|
-
if self.useFileSource.isArchive and (os.path.isabs(readMeFirstUri) or not readMeFirstUri.endswith(".zip")):
|
|
227
|
-
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
228
|
-
readMeFirstUri,
|
|
229
|
-
_("validating"),
|
|
230
|
-
base=baseForElement,
|
|
231
|
-
useFileSource=self.useFileSource,
|
|
232
|
-
errorCaptureLevel=errorCaptureLevel,
|
|
233
|
-
ixdsTarget=modelTestcaseVariation.ixdsTarget)
|
|
234
|
-
else: # need own file source, may need instance discovery
|
|
235
|
-
sourceFileSource = None
|
|
236
|
-
newSourceFileSource = False
|
|
237
|
-
if (
|
|
238
|
-
self.useFileSource
|
|
239
|
-
and not os.path.isabs(readMeFirstUri)
|
|
240
|
-
and readMeFirstUri.endswith('.zip')
|
|
241
|
-
):
|
|
242
|
-
if self.useFileSource.isArchive:
|
|
243
|
-
sourceFileSource = self.useFileSource
|
|
244
|
-
elif expectTaxonomyPackage:
|
|
245
|
-
archiveFilenameParts = FileSource.archiveFilenameParts(baseForElement)
|
|
246
|
-
if archiveFilenameParts is not None:
|
|
247
|
-
sourceFileSource = FileSource.openFileSource(archiveFilenameParts[0], self.modelXbrl.modelManager.cntlr)
|
|
248
|
-
newSourceFileSource = True
|
|
249
|
-
|
|
250
|
-
filesource = FileSource.openFileSource(readMeFirstUri, self.modelXbrl.modelManager.cntlr, base=baseForElement,
|
|
251
|
-
sourceFileSource=sourceFileSource)
|
|
252
|
-
if newSourceFileSource:
|
|
253
|
-
sourceFileSource.close()
|
|
254
|
-
_errors = [] # accumulate pre-loading errors, such as during taxonomy package loading
|
|
255
|
-
if filesource and not filesource.selection and filesource.isArchive:
|
|
256
|
-
try:
|
|
257
|
-
if filesource.isTaxonomyPackage or expectTaxonomyPackage:
|
|
258
|
-
_rptPkgIxdsOptions = {}
|
|
259
|
-
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ReportPackageIxdsOptions"):
|
|
260
|
-
pluginXbrlMethod(self, _rptPkgIxdsOptions)
|
|
261
|
-
filesource.loadTaxonomyPackageMappings(errors=_errors, expectTaxonomyPackage=expectTaxonomyPackage)
|
|
262
|
-
filesource.select(None) # must select loadable reports (not the taxonomy package itself)
|
|
263
|
-
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ReportPackageIxds"):
|
|
264
|
-
filesource.select(pluginXbrlMethod(filesource, **_rptPkgIxdsOptions))
|
|
265
|
-
else:
|
|
266
|
-
from arelle.CntlrCmdLine import filesourceEntrypointFiles
|
|
267
|
-
entrypoints = filesourceEntrypointFiles(filesource)
|
|
268
|
-
if entrypoints:
|
|
269
|
-
# resolve an IXDS in entrypoints
|
|
270
|
-
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ArchiveIxds"):
|
|
271
|
-
pluginXbrlMethod(self, filesource,entrypoints)
|
|
272
|
-
filesource.select(entrypoints[0].get("file", None) )
|
|
273
|
-
except Exception as err:
|
|
274
|
-
self.modelXbrl.error("exception:" + type(err).__name__,
|
|
275
|
-
_("Testcase variation validation exception: %(error)s, entry URL: %(instance)s"),
|
|
276
|
-
modelXbrl=self.modelXbrl, instance=readMeFirstUri, error=err)
|
|
277
|
-
continue # don't try to load this entry URL
|
|
278
|
-
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
279
|
-
filesource,
|
|
280
|
-
_("validating"),
|
|
281
|
-
base=baseForElement,
|
|
282
|
-
errorCaptureLevel=errorCaptureLevel,
|
|
283
|
-
ixdsTarget=modelTestcaseVariation.ixdsTarget,
|
|
284
|
-
isLoadable=modelTestcaseVariation.variationDiscoversDTS or filesource.url,
|
|
285
|
-
errors=_errors)
|
|
286
|
-
modelXbrl.isTestcaseVariation = True
|
|
287
|
-
if not modelTestcaseVariation.variationDiscoversDTS and modelXbrl.modelDocument is None: # e.g., taxonomyPackage test
|
|
288
|
-
self.determineTestStatus(modelTestcaseVariation, modelXbrl.errors)
|
|
289
|
-
modelXbrl.close()
|
|
290
|
-
elif modelXbrl.modelDocument is None:
|
|
291
|
-
modelXbrl.info("arelle:notLoaded",
|
|
292
|
-
_("Variation %(id)s %(name)s readMeFirst document not loaded: %(file)s"),
|
|
293
|
-
modelXbrl=testcase, id=modelTestcaseVariation.id, name=modelTestcaseVariation.name, file=os.path.basename(readMeFirstUri))
|
|
294
|
-
self.determineNotLoadedTestStatus(modelTestcaseVariation, modelXbrl.errors)
|
|
295
|
-
modelXbrl.close()
|
|
296
|
-
elif resultIsVersioningReport or resultIsTaxonomyPackage:
|
|
297
|
-
inputDTSes[dtsName] = modelXbrl
|
|
298
|
-
elif modelXbrl.modelDocument.type == Type.VERSIONINGREPORT:
|
|
299
|
-
ValidateVersReport.ValidateVersReport(self.modelXbrl).validate(modelXbrl)
|
|
300
|
-
self.determineTestStatus(modelTestcaseVariation, modelXbrl.errors)
|
|
301
|
-
modelXbrl.close()
|
|
302
|
-
elif testcase.type == Type.REGISTRYTESTCASE:
|
|
303
|
-
self.instValidator.validate(modelXbrl) # required to set up dimensions, etc
|
|
304
|
-
self.instValidator.executeCallTest(modelXbrl, modelTestcaseVariation.id,
|
|
305
|
-
modelTestcaseVariation.cfcnCall, modelTestcaseVariation.cfcnTest)
|
|
306
|
-
self.determineTestStatus(modelTestcaseVariation, modelXbrl.errors)
|
|
307
|
-
self.instValidator.close()
|
|
308
|
-
modelXbrl.close()
|
|
309
|
-
else:
|
|
310
|
-
inputDTSes[dtsName].append(modelXbrl)
|
|
311
|
-
# validate except for formulas
|
|
312
|
-
_hasFormulae = modelXbrl.hasFormulae
|
|
313
|
-
modelXbrl.hasFormulae = False
|
|
314
|
-
try:
|
|
315
|
-
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.Xbrl.Loaded"):
|
|
316
|
-
pluginXbrlMethod(self.modelXbrl, modelXbrl, modelTestcaseVariation)
|
|
317
|
-
self.instValidator.validate(modelXbrl, parameters)
|
|
318
|
-
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.Xbrl.Validated"):
|
|
319
|
-
pluginXbrlMethod(self.modelXbrl, modelXbrl)
|
|
320
|
-
except Exception as err:
|
|
321
|
-
modelXbrl.error("exception:" + type(err).__name__,
|
|
322
|
-
_("Testcase variation validation exception: %(error)s, instance: %(instance)s"),
|
|
323
|
-
modelXbrl=modelXbrl, instance=modelXbrl.modelDocument.basename, error=err, exc_info=(type(err) is not AssertionError))
|
|
324
|
-
modelXbrl.hasFormulae = _hasFormulae
|
|
325
|
-
if resultIsVersioningReport and modelXbrl.modelDocument:
|
|
326
|
-
versReportFile = modelXbrl.modelManager.cntlr.webCache.normalizeUrl(
|
|
327
|
-
modelTestcaseVariation.versioningReportUri, baseForElement)
|
|
328
|
-
if os.path.exists(versReportFile): #validate existing
|
|
329
|
-
modelVersReport = ModelXbrl.load(self.modelXbrl.modelManager, versReportFile, _("validating existing version report"))
|
|
330
|
-
if modelVersReport and modelVersReport.modelDocument and modelVersReport.modelDocument.type == Type.VERSIONINGREPORT:
|
|
331
|
-
ValidateVersReport.ValidateVersReport(self.modelXbrl).validate(modelVersReport)
|
|
332
|
-
self.determineTestStatus(modelTestcaseVariation, modelVersReport.errors)
|
|
333
|
-
modelVersReport.close()
|
|
334
|
-
elif len(inputDTSes) == 2:
|
|
335
|
-
ModelVersReport.ModelVersReport(self.modelXbrl).diffDTSes(
|
|
336
|
-
versReportFile, inputDTSes["from"], inputDTSes["to"])
|
|
337
|
-
modelTestcaseVariation.status = "generated"
|
|
338
|
-
else:
|
|
339
|
-
modelXbrl.error("arelle:notLoaded",
|
|
340
|
-
_("Variation %(id)s %(name)s input DTSes not loaded, unable to generate versioning report: %(file)s"),
|
|
341
|
-
modelXbrl=testcase, id=modelTestcaseVariation.id, name=modelTestcaseVariation.name, file=os.path.basename(readMeFirstUri))
|
|
342
|
-
modelTestcaseVariation.status = "failed"
|
|
343
|
-
for inputDTS in inputDTSes.values():
|
|
344
|
-
inputDTS.close()
|
|
345
|
-
del inputDTSes # dereference
|
|
346
|
-
elif resultIsTaxonomyPackage:
|
|
347
|
-
self.determineTestStatus(modelTestcaseVariation, modelXbrl.errors)
|
|
348
|
-
modelXbrl.close()
|
|
349
|
-
elif inputDTSes:
|
|
350
|
-
# validate schema, linkbase, or instance
|
|
351
|
-
modelXbrl = inputDTSes[None][0]
|
|
352
|
-
expectedDataFiles = set(modelXbrl.modelManager.cntlr.webCache.normalizeUrl(uri, baseForElement)
|
|
353
|
-
for d in modelTestcaseVariation.dataUris.values() for uri in d
|
|
354
|
-
if not UrlUtil.isAbsolute(uri))
|
|
355
|
-
foundDataFiles = set()
|
|
356
|
-
variationBase = os.path.dirname(baseForElement)
|
|
357
|
-
for dtsName, inputDTS in inputDTSes.items(): # input instances are also parameters
|
|
358
|
-
if dtsName: # named instance
|
|
359
|
-
parameters[dtsName] = (None, inputDTS) #inputDTS is a list of modelXbrl's (instance DTSes)
|
|
360
|
-
elif len(inputDTS) > 1: # standard-input-instance with multiple instance documents
|
|
361
|
-
parameters[XbrlConst.qnStandardInputInstance] = (None, inputDTS) # allow error detection in validateFormula
|
|
362
|
-
for _inputDTS in inputDTS:
|
|
363
|
-
for docUrl, doc in _inputDTS.urlDocs.items():
|
|
364
|
-
if docUrl.startswith(variationBase) and not doc.type == Type.INLINEXBRLDOCUMENTSET:
|
|
365
|
-
if getattr(doc,"loadedFromXbrlFormula", False): # may have been sourced from xf file
|
|
366
|
-
if docUrl.replace("-formula.xml", ".xf") in expectedDataFiles:
|
|
367
|
-
docUrl = docUrl.replace("-formula.xml", ".xf")
|
|
368
|
-
foundDataFiles.add(docUrl)
|
|
369
|
-
if expectedDataFiles - foundDataFiles:
|
|
370
|
-
modelXbrl.info("arelle:testcaseDataNotUsed",
|
|
371
|
-
_("Variation %(id)s %(name)s data files not used: %(missingDataFiles)s"),
|
|
372
|
-
modelObject=modelTestcaseVariation, name=modelTestcaseVariation.name, id=modelTestcaseVariation.id,
|
|
373
|
-
missingDataFiles=", ".join(sorted(os.path.basename(f) for f in expectedDataFiles - foundDataFiles)))
|
|
374
|
-
if foundDataFiles - expectedDataFiles:
|
|
375
|
-
modelXbrl.info("arelle:testcaseDataUnexpected",
|
|
376
|
-
_("Variation %(id)s %(name)s files not in variation data: %(unexpectedDataFiles)s"),
|
|
377
|
-
modelObject=modelTestcaseVariation, name=modelTestcaseVariation.name, id=modelTestcaseVariation.id,
|
|
378
|
-
unexpectedDataFiles=", ".join(sorted(os.path.basename(f) for f in foundDataFiles - expectedDataFiles)))
|
|
379
|
-
if modelXbrl.hasTableRendering or modelTestcaseVariation.resultIsTable:
|
|
380
|
-
try:
|
|
381
|
-
RenderingEvaluator.init(modelXbrl)
|
|
382
|
-
except Exception as err:
|
|
383
|
-
modelXbrl.error("exception:" + type(err).__name__,
|
|
384
|
-
_("Testcase RenderingEvaluator.init exception: %(error)s, instance: %(instance)s"),
|
|
385
|
-
modelXbrl=modelXbrl, instance=modelXbrl.modelDocument.basename, error=err, exc_info=True)
|
|
386
|
-
modelXbrlHasFormulae = modelXbrl.hasFormulae
|
|
387
|
-
if modelXbrlHasFormulae and self.modelXbrl.modelManager.formulaOptions.formulaAction != "none":
|
|
388
|
-
try:
|
|
389
|
-
# validate only formulae
|
|
390
|
-
self.instValidator.parameters = parameters
|
|
391
|
-
ValidateFormula.validate(self.instValidator)
|
|
392
|
-
except Exception as err:
|
|
393
|
-
modelXbrl.error("exception:" + type(err).__name__,
|
|
394
|
-
_("Testcase formula variation validation exception: %(error)s, instance: %(instance)s"),
|
|
395
|
-
modelXbrl=modelXbrl, instance=modelXbrl.modelDocument.basename, error=err, exc_info=(type(err) is not AssertionError))
|
|
396
|
-
if modelTestcaseVariation.resultIsInfoset and self.modelXbrl.modelManager.validateInfoset:
|
|
397
|
-
for pluginXbrlMethod in pluginClassMethods("Validate.Infoset"):
|
|
398
|
-
pluginXbrlMethod(modelXbrl, modelTestcaseVariation.resultInfosetUri)
|
|
399
|
-
infoset = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
400
|
-
modelTestcaseVariation.resultInfosetUri,
|
|
401
|
-
_("loading result infoset"),
|
|
402
|
-
base=baseForElement,
|
|
403
|
-
useFileSource=self.useFileSource,
|
|
404
|
-
errorCaptureLevel=errorCaptureLevel)
|
|
405
|
-
if infoset.modelDocument is None:
|
|
406
|
-
modelXbrl.error("arelle:notLoaded",
|
|
407
|
-
_("Variation %(id)s %(name)s result infoset not loaded: %(file)s"),
|
|
408
|
-
modelXbrl=testcase, id=modelTestcaseVariation.id, name=modelTestcaseVariation.name,
|
|
409
|
-
file=os.path.basename(modelTestcaseVariation.resultXbrlInstance))
|
|
410
|
-
modelTestcaseVariation.status = "result infoset not loadable"
|
|
411
|
-
else: # check infoset
|
|
412
|
-
ValidateInfoset.validate(self.instValidator, modelXbrl, infoset)
|
|
413
|
-
infoset.close()
|
|
414
|
-
if modelXbrl.hasTableRendering or modelTestcaseVariation.resultIsTable: # and self.modelXbrl.modelManager.validateInfoset:
|
|
415
|
-
# diff (or generate) table infoset
|
|
416
|
-
resultTableUri = modelXbrl.modelManager.cntlr.webCache.normalizeUrl(modelTestcaseVariation.resultTableUri, baseForElement)
|
|
417
|
-
if not any(alternativeValidation(modelXbrl, resultTableUri)
|
|
418
|
-
for alternativeValidation in pluginClassMethods("Validate.TableInfoset")):
|
|
419
|
-
try:
|
|
420
|
-
ViewFileRenderedGrid.viewRenderedGrid(modelXbrl, resultTableUri, diffToFile=True) # false to save infoset files
|
|
421
|
-
except Exception as err:
|
|
422
|
-
modelXbrl.error("exception:" + type(err).__name__,
|
|
423
|
-
_("Testcase table linkbase validation exception: %(error)s, instance: %(instance)s"),
|
|
424
|
-
modelXbrl=modelXbrl, instance=modelXbrl.modelDocument.basename, error=err, exc_info=True)
|
|
425
|
-
self.instValidator.close()
|
|
426
|
-
extraErrors = []
|
|
427
|
-
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.Validated"):
|
|
428
|
-
pluginXbrlMethod(self.modelXbrl, modelXbrl, extraErrors, inputDTSes)
|
|
429
|
-
self.determineTestStatus(modelTestcaseVariation, [e for inputDTSlist in inputDTSes.values() for inputDTS in inputDTSlist for e in inputDTS.errors] + extraErrors) # include infoset errors in status
|
|
430
|
-
if modelXbrl.formulaOutputInstance and self.noErrorCodes(modelTestcaseVariation.actual):
|
|
431
|
-
# if an output instance is created, and no string error codes, ignoring dict of assertion results, validate it
|
|
432
|
-
modelXbrl.formulaOutputInstance.hasFormulae = False # block formulae on output instance (so assertion of input is not lost)
|
|
433
|
-
self.instValidator.validate(modelXbrl.formulaOutputInstance, modelTestcaseVariation.parameters)
|
|
434
|
-
self.determineTestStatus(modelTestcaseVariation, modelXbrl.formulaOutputInstance.errors)
|
|
435
|
-
if self.noErrorCodes(modelTestcaseVariation.actual): # if still 'clean' pass it forward for comparison to expected result instance
|
|
436
|
-
formulaOutputInstance = modelXbrl.formulaOutputInstance
|
|
437
|
-
modelXbrl.formulaOutputInstance = None # prevent it from being closed now
|
|
438
|
-
self.instValidator.close()
|
|
439
|
-
compareIxResultInstance = (modelXbrl.modelDocument.type in (Type.INLINEXBRL, Type.INLINEXBRLDOCUMENTSET) and
|
|
440
|
-
modelTestcaseVariation.resultXbrlInstanceUri is not None)
|
|
441
|
-
if compareIxResultInstance:
|
|
442
|
-
formulaOutputInstance = modelXbrl # compare modelXbrl to generated output instance
|
|
443
|
-
errMsgPrefix = "ix"
|
|
444
|
-
else: # delete input instances before formula output comparision
|
|
445
|
-
for inputDTSlist in inputDTSes.values():
|
|
446
|
-
for inputDTS in inputDTSlist:
|
|
447
|
-
inputDTS.close()
|
|
448
|
-
del inputDTSes # dereference
|
|
449
|
-
errMsgPrefix = "formula"
|
|
450
|
-
if resultIsXbrlInstance and formulaOutputInstance and formulaOutputInstance.modelDocument:
|
|
451
|
-
_matchExpectedResultIDs = not modelXbrlHasFormulae # formula restuls have inconsistent IDs
|
|
452
|
-
expectedInstance = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
453
|
-
modelTestcaseVariation.resultXbrlInstanceUri,
|
|
454
|
-
_("loading expected result XBRL instance"),
|
|
455
|
-
base=baseForElement,
|
|
456
|
-
useFileSource=self.useFileSource,
|
|
457
|
-
errorCaptureLevel=errorCaptureLevel)
|
|
458
|
-
if expectedInstance.modelDocument is None:
|
|
459
|
-
self.modelXbrl.error("{}:expectedResultNotLoaded".format(errMsgPrefix),
|
|
460
|
-
_("Testcase \"%(name)s\" %(id)s expected result instance not loaded: %(file)s"),
|
|
461
|
-
modelXbrl=testcase, id=modelTestcaseVariation.id, name=modelTestcaseVariation.name,
|
|
462
|
-
file=os.path.basename(modelTestcaseVariation.resultXbrlInstanceUri),
|
|
463
|
-
messageCodes=("formula:expectedResultNotLoaded","ix:expectedResultNotLoaded"))
|
|
464
|
-
modelTestcaseVariation.status = "result not loadable"
|
|
465
|
-
else: # compare facts
|
|
466
|
-
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.ExpectedInstance.Loaded"):
|
|
467
|
-
pluginXbrlMethod(expectedInstance, formulaOutputInstance)
|
|
468
|
-
if len(expectedInstance.facts) != len(formulaOutputInstance.facts):
|
|
469
|
-
formulaOutputInstance.error("{}:resultFactCounts".format(errMsgPrefix),
|
|
470
|
-
_("Formula output %(countFacts)s facts, expected %(expectedFacts)s facts"),
|
|
471
|
-
modelXbrl=modelXbrl, countFacts=len(formulaOutputInstance.facts),
|
|
472
|
-
expectedFacts=len(expectedInstance.facts),
|
|
473
|
-
messageCodes=("formula:resultFactCounts","ix:resultFactCounts"))
|
|
474
|
-
else:
|
|
475
|
-
formulaOutputFootnotesRelSet = ModelRelationshipSet(formulaOutputInstance, "XBRL-footnotes")
|
|
476
|
-
expectedFootnotesRelSet = ModelRelationshipSet(expectedInstance, "XBRL-footnotes")
|
|
477
|
-
def factFootnotes(fact, footnotesRelSet):
|
|
478
|
-
footnotes = {}
|
|
479
|
-
footnoteRels = footnotesRelSet.fromModelObject(fact)
|
|
480
|
-
if footnoteRels:
|
|
481
|
-
# most process rels in same order between two instances, use labels to sort
|
|
482
|
-
for i, footnoteRel in enumerate(sorted(footnoteRels,
|
|
483
|
-
key=lambda r: (r.fromLabel,r.toLabel))):
|
|
484
|
-
modelObject = footnoteRel.toModelObject
|
|
485
|
-
if isinstance(modelObject, ModelResource):
|
|
486
|
-
xml = collapseWhitespace(modelObject.viewText().strip())
|
|
487
|
-
footnotes["Footnote {}".format(i+1)] = xml #re.sub(r'\s+', ' ', collapseWhitespace(modelObject.stringValue))
|
|
488
|
-
elif isinstance(modelObject, ModelFact):
|
|
489
|
-
footnotes["Footnoted fact {}".format(i+1)] = \
|
|
490
|
-
"{} context: {} value: {}".format(
|
|
491
|
-
modelObject.qname,
|
|
492
|
-
modelObject.contextID,
|
|
493
|
-
collapseWhitespace(modelObject.value))
|
|
494
|
-
return footnotes
|
|
495
|
-
for expectedInstanceFact in expectedInstance.facts:
|
|
496
|
-
unmatchedFactsStack = []
|
|
497
|
-
formulaOutputFact = formulaOutputInstance.matchFact(expectedInstanceFact, unmatchedFactsStack, deemP0inf=True, matchId=_matchExpectedResultIDs, matchLang=False)
|
|
498
|
-
#formulaOutputFact = formulaOutputInstance.matchFact(expectedInstanceFact, unmatchedFactsStack, deemP0inf=True, matchId=True, matchLang=True)
|
|
499
|
-
if formulaOutputFact is None:
|
|
500
|
-
if unmatchedFactsStack: # get missing nested tuple fact, if possible
|
|
501
|
-
missingFact = unmatchedFactsStack[-1]
|
|
502
|
-
else:
|
|
503
|
-
missingFact = expectedInstanceFact
|
|
504
|
-
# is it possible to show value mismatches?
|
|
505
|
-
expectedFacts = formulaOutputInstance.factsByQname.get(missingFact.qname)
|
|
506
|
-
if expectedFacts and len(expectedFacts) == 1:
|
|
507
|
-
formulaOutputInstance.error("{}:expectedFactMissing".format(errMsgPrefix),
|
|
508
|
-
_("Output missing expected fact %(fact)s, extracted value \"%(value1)s\", expected value \"%(value2)s\""),
|
|
509
|
-
modelXbrl=missingFact, fact=missingFact.qname, value1=missingFact.xValue, value2=next(iter(expectedFacts)).xValue,
|
|
510
|
-
messageCodes=("formula:expectedFactMissing","ix:expectedFactMissing"))
|
|
511
|
-
else:
|
|
512
|
-
formulaOutputInstance.error("{}:expectedFactMissing".format(errMsgPrefix),
|
|
513
|
-
_("Output missing expected fact %(fact)s"),
|
|
514
|
-
modelXbrl=missingFact, fact=missingFact.qname,
|
|
515
|
-
messageCodes=("formula:expectedFactMissing","ix:expectedFactMissing"))
|
|
516
|
-
else: # compare footnotes
|
|
517
|
-
expectedInstanceFactFootnotes = factFootnotes(expectedInstanceFact, expectedFootnotesRelSet)
|
|
518
|
-
formulaOutputFactFootnotes = factFootnotes(formulaOutputFact, formulaOutputFootnotesRelSet)
|
|
519
|
-
if (len(expectedInstanceFactFootnotes) != len(formulaOutputFactFootnotes) or
|
|
520
|
-
set(expectedInstanceFactFootnotes.values()) != set(formulaOutputFactFootnotes.values())):
|
|
521
|
-
formulaOutputInstance.error("{}:expectedFactFootnoteDifference".format(errMsgPrefix),
|
|
522
|
-
_("Output expected fact %(fact)s expected footnotes %(footnotes1)s produced footnotes %(footnotes2)s"),
|
|
523
|
-
modelXbrl=(formulaOutputFact,expectedInstanceFact), fact=expectedInstanceFact.qname, footnotes1=sorted(expectedInstanceFactFootnotes.items()), footnotes2=sorted(formulaOutputFactFootnotes.items()),
|
|
524
|
-
messageCodes=("formula:expectedFactFootnoteDifference","ix:expectedFactFootnoteDifference"))
|
|
525
|
-
|
|
526
|
-
# for debugging uncomment next line to save generated instance document
|
|
527
|
-
# formulaOutputInstance.saveInstance(r"c:\temp\test-out-inst.xml")
|
|
528
|
-
expectedInstance.close()
|
|
529
|
-
del expectedInstance # dereference
|
|
530
|
-
self.determineTestStatus(modelTestcaseVariation, formulaOutputInstance.errors)
|
|
531
|
-
formulaOutputInstance.close()
|
|
532
|
-
del formulaOutputInstance
|
|
533
|
-
if compareIxResultInstance:
|
|
534
|
-
for inputDTSlist in inputDTSes.values():
|
|
535
|
-
for inputDTS in inputDTSlist:
|
|
536
|
-
inputDTS.close()
|
|
537
|
-
del inputDTSes # dereference
|
|
538
|
-
# update ui thread via modelManager (running in background here)
|
|
539
|
-
self.modelXbrl.modelManager.viewModelObject(self.modelXbrl, modelTestcaseVariation.objectId())
|
|
218
|
+
testcaseVariation.status = 'skip'
|
|
219
|
+
self.modelXbrl.info("info", "Skipped testcase variation %(variationId)s.",
|
|
220
|
+
modelObject=testcaseVariation,
|
|
221
|
+
variationId=testcaseVariation.id)
|
|
222
|
+
for modelTestcaseVariation in testcaseVariations:
|
|
223
|
+
self._validateTestcaseVariation(testcase, modelTestcaseVariation)
|
|
540
224
|
|
|
541
225
|
_statusCounts = OrderedDict((("pass",0),("fail",0)))
|
|
542
226
|
for tv in getattr(testcase, "testcaseVariations", ()):
|
|
@@ -545,22 +229,538 @@ class Validate:
|
|
|
545
229
|
|
|
546
230
|
self.modelXbrl.modelManager.showStatus(_("ready"), 2000)
|
|
547
231
|
|
|
232
|
+
def _validateTestcaseVariation(self, testcase, modelTestcaseVariation):
|
|
233
|
+
# update ui thread via modelManager (running in background here)
|
|
234
|
+
startTime = time.perf_counter()
|
|
235
|
+
self.modelXbrl.modelManager.viewModelObject(self.modelXbrl, modelTestcaseVariation.objectId())
|
|
236
|
+
# is this a versioning report?
|
|
237
|
+
resultIsVersioningReport = modelTestcaseVariation.resultIsVersioningReport
|
|
238
|
+
resultIsXbrlInstance = modelTestcaseVariation.resultIsXbrlInstance
|
|
239
|
+
resultIsTaxonomyPackage = modelTestcaseVariation.resultIsTaxonomyPackage
|
|
240
|
+
inputDTSes = defaultdict(list)
|
|
241
|
+
baseForElement = testcase.baseForElement(modelTestcaseVariation)
|
|
242
|
+
# try to load instance document
|
|
243
|
+
self.modelXbrl.info("info", _("Variation %(id)s%(name)s%(target)s: %(expected)s - %(description)s"),
|
|
244
|
+
modelObject=modelTestcaseVariation,
|
|
245
|
+
id=modelTestcaseVariation.id,
|
|
246
|
+
name=(" {}".format(modelTestcaseVariation.name) if modelTestcaseVariation.name else ""),
|
|
247
|
+
target=(" target {}".format(modelTestcaseVariation.ixdsTarget) if modelTestcaseVariation.ixdsTarget else ""),
|
|
248
|
+
expected=modelTestcaseVariation.expected,
|
|
249
|
+
description=modelTestcaseVariation.description)
|
|
250
|
+
if self.modelXbrl.modelManager.formulaOptions.testcaseResultsCaptureWarnings:
|
|
251
|
+
errorCaptureLevel = logging._checkLevel("WARNING")
|
|
252
|
+
else:
|
|
253
|
+
errorCaptureLevel = modelTestcaseVariation.severityLevel # default is INCONSISTENCY
|
|
254
|
+
parameters = modelTestcaseVariation.parameters.copy()
|
|
255
|
+
loadedModels = []
|
|
256
|
+
for i, readMeFirstUri in enumerate(modelTestcaseVariation.readMeFirstUris):
|
|
257
|
+
loadedModels.extend(self._testcaseLoadReadMeFirstUri(
|
|
258
|
+
testcase=testcase,
|
|
259
|
+
modelTestcaseVariation=modelTestcaseVariation,
|
|
260
|
+
index=i,
|
|
261
|
+
readMeFirstUri=readMeFirstUri,
|
|
262
|
+
resultIsVersioningReport=resultIsVersioningReport,
|
|
263
|
+
resultIsTaxonomyPackage=resultIsTaxonomyPackage,
|
|
264
|
+
inputDTSes=inputDTSes,
|
|
265
|
+
errorCaptureLevel=errorCaptureLevel,
|
|
266
|
+
baseForElement=baseForElement,
|
|
267
|
+
parameters=parameters,
|
|
268
|
+
))
|
|
269
|
+
validateInputDTS = False
|
|
270
|
+
for modelXbrl in loadedModels:
|
|
271
|
+
if resultIsVersioningReport and modelXbrl.modelDocument:
|
|
272
|
+
versReportFile = modelXbrl.modelManager.cntlr.webCache.normalizeUrl(
|
|
273
|
+
modelTestcaseVariation.versioningReportUri, baseForElement)
|
|
274
|
+
if os.path.exists(versReportFile): #validate existing
|
|
275
|
+
modelVersReport = ModelXbrl.load(self.modelXbrl.modelManager, versReportFile, _("validating existing version report"))
|
|
276
|
+
if modelVersReport and modelVersReport.modelDocument and modelVersReport.modelDocument.type == Type.VERSIONINGREPORT:
|
|
277
|
+
ValidateVersReport.ValidateVersReport(self.modelXbrl).validate(modelVersReport)
|
|
278
|
+
self.determineTestStatus(modelTestcaseVariation, modelVersReport.errors)
|
|
279
|
+
modelVersReport.close()
|
|
280
|
+
elif len(inputDTSes) == 2:
|
|
281
|
+
ModelVersReport.ModelVersReport(self.modelXbrl).diffDTSes(
|
|
282
|
+
versReportFile, inputDTSes["from"], inputDTSes["to"])
|
|
283
|
+
modelTestcaseVariation.status = "generated"
|
|
284
|
+
else:
|
|
285
|
+
modelXbrl.error("arelle:notLoaded",
|
|
286
|
+
_("Variation %(id)s %(name)s input DTSes not loaded, unable to generate versioning report: %(file)s"),
|
|
287
|
+
modelXbrl=testcase, id=modelTestcaseVariation.id, name=modelTestcaseVariation.name, file=os.path.basename(readMeFirstUri))
|
|
288
|
+
modelTestcaseVariation.status = "failed"
|
|
289
|
+
elif resultIsTaxonomyPackage:
|
|
290
|
+
self.determineTestStatus(modelTestcaseVariation, modelXbrl.errors)
|
|
291
|
+
modelXbrl.close()
|
|
292
|
+
elif inputDTSes:
|
|
293
|
+
validateInputDTS = True
|
|
294
|
+
if validateInputDTS:
|
|
295
|
+
self._testcaseValidateInputDTS(testcase, modelTestcaseVariation, errorCaptureLevel, parameters, inputDTSes, baseForElement, resultIsXbrlInstance)
|
|
296
|
+
# update ui thread via modelManager (running in background here)
|
|
297
|
+
self.modelXbrl.modelManager.viewModelObject(self.modelXbrl, modelTestcaseVariation.objectId())
|
|
298
|
+
self.modelXbrl.modelManager.cntlr.testcaseVariationReset()
|
|
299
|
+
modelTestcaseVariation.duration = time.perf_counter() - startTime
|
|
300
|
+
|
|
301
|
+
def _testcaseLoadReadMeFirstUri(self, testcase, modelTestcaseVariation, index, readMeFirstUri, resultIsVersioningReport, resultIsTaxonomyPackage, inputDTSes, errorCaptureLevel, baseForElement, parameters):
|
|
302
|
+
preLoadingErrors = [] # accumulate pre-loading errors, such as during taxonomy package loading
|
|
303
|
+
loadedModels = []
|
|
304
|
+
filesource = None
|
|
305
|
+
readMeFirstElements = modelTestcaseVariation.readMeFirstElements
|
|
306
|
+
expectTaxonomyPackage = (index < len(readMeFirstElements) and
|
|
307
|
+
readMeFirstElements[index] is not None and
|
|
308
|
+
readMeFirstElements[index].qname.localName == "taxonomyPackage")
|
|
309
|
+
if isinstance(readMeFirstUri,tuple):
|
|
310
|
+
# dtsName is for formula instances, but is from/to dts if versioning
|
|
311
|
+
dtsName, readMeFirstUri = readMeFirstUri
|
|
312
|
+
elif resultIsVersioningReport:
|
|
313
|
+
if inputDTSes: dtsName = "to"
|
|
314
|
+
else: dtsName = "from"
|
|
315
|
+
else:
|
|
316
|
+
dtsName = None
|
|
317
|
+
if resultIsVersioningReport and dtsName: # build multi-schemaRef containing document
|
|
318
|
+
if dtsName in inputDTSes:
|
|
319
|
+
dtsName = inputDTSes[dtsName]
|
|
320
|
+
else:
|
|
321
|
+
modelXbrl = ModelXbrl.create(self.modelXbrl.modelManager,
|
|
322
|
+
Type.DTSENTRIES,
|
|
323
|
+
self.modelXbrl.modelManager.cntlr.webCache.normalizeUrl(readMeFirstUri[:-4] + ".dts", baseForElement),
|
|
324
|
+
isEntry=True,
|
|
325
|
+
errorCaptureLevel=errorCaptureLevel)
|
|
326
|
+
loadedModels.append(modelXbrl)
|
|
327
|
+
DTSdoc = modelXbrl.modelDocument
|
|
328
|
+
DTSdoc.inDTS = True
|
|
329
|
+
doc = modelDocumentLoad(modelXbrl, readMeFirstUri, base=baseForElement)
|
|
330
|
+
if doc is not None:
|
|
331
|
+
DTSdoc.referencesDocument[doc] = ModelDocumentReference("import", DTSdoc.xmlRootElement) #fake import
|
|
332
|
+
doc.inDTS = True
|
|
333
|
+
elif resultIsTaxonomyPackage:
|
|
334
|
+
from arelle import PackageManager, PrototypeInstanceObject
|
|
335
|
+
dtsName = readMeFirstUri
|
|
336
|
+
modelXbrl = PrototypeInstanceObject.XbrlPrototype(self.modelXbrl.modelManager, readMeFirstUri)
|
|
337
|
+
loadedModels.append(modelXbrl)
|
|
338
|
+
PackageManager.packageInfo(self.modelXbrl.modelManager.cntlr, readMeFirstUri, reload=True, errors=modelXbrl.errors)
|
|
339
|
+
else: # not a multi-schemaRef versioning report
|
|
340
|
+
readMeFirstUriIsArchive = isReportPackageExtension(readMeFirstUri)
|
|
341
|
+
readMeFirstUriIsEmbeddedZipFile = False
|
|
342
|
+
if self.useFileSource.isArchive and not isLegacyAbs(readMeFirstUri):
|
|
343
|
+
if readMeFirstUriIsArchive:
|
|
344
|
+
readMeFirstUriIsEmbeddedZipFile = True
|
|
345
|
+
else:
|
|
346
|
+
normalizedReadMeFirstUri = self.modelXbrl.modelManager.cntlr.webCache.normalizeUrl(readMeFirstUri, baseForElement)
|
|
347
|
+
archivePath = FileSource.archiveFilenameParts(normalizedReadMeFirstUri)
|
|
348
|
+
if archivePath:
|
|
349
|
+
with self.useFileSource.fs.open(archivePath[1]) as embeddedFile:
|
|
350
|
+
readMeFirstUriIsArchive = readMeFirstUriIsEmbeddedZipFile = zipfile.is_zipfile(embeddedFile)
|
|
351
|
+
if not readMeFirstUriIsArchive:
|
|
352
|
+
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
353
|
+
readMeFirstUri,
|
|
354
|
+
_("validating"),
|
|
355
|
+
base=baseForElement,
|
|
356
|
+
useFileSource=self.useFileSource,
|
|
357
|
+
errorCaptureLevel=errorCaptureLevel,
|
|
358
|
+
ixdsTarget=modelTestcaseVariation.ixdsTarget)
|
|
359
|
+
loadedModels.append(modelXbrl)
|
|
360
|
+
else: # need own file source, may need instance discovery
|
|
361
|
+
sourceFileSource = None
|
|
362
|
+
newSourceFileSource = False
|
|
363
|
+
if (
|
|
364
|
+
self.useFileSource
|
|
365
|
+
and not isLegacyAbs(readMeFirstUri)
|
|
366
|
+
and (readMeFirstUriIsEmbeddedZipFile or isReportPackageExtension(readMeFirstUri))
|
|
367
|
+
):
|
|
368
|
+
if self.useFileSource.isArchive:
|
|
369
|
+
sourceFileSource = self.useFileSource
|
|
370
|
+
elif expectTaxonomyPackage:
|
|
371
|
+
archiveFilenameParts = FileSource.archiveFilenameParts(baseForElement)
|
|
372
|
+
if archiveFilenameParts is not None:
|
|
373
|
+
sourceFileSource = FileSource.openFileSource(archiveFilenameParts[0], self.modelXbrl.modelManager.cntlr)
|
|
374
|
+
newSourceFileSource = True
|
|
375
|
+
|
|
376
|
+
filesource = FileSource.openFileSource(readMeFirstUri, self.modelXbrl.modelManager.cntlr, base=baseForElement,
|
|
377
|
+
sourceFileSource=sourceFileSource)
|
|
378
|
+
if filesource.isReportPackage:
|
|
379
|
+
expectTaxonomyPackage = filesource.isTaxonomyPackage
|
|
380
|
+
|
|
381
|
+
if newSourceFileSource:
|
|
382
|
+
sourceFileSource.close()
|
|
383
|
+
_rptPkgIxdsOptions = {}
|
|
384
|
+
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ReportPackageIxdsOptions"):
|
|
385
|
+
pluginXbrlMethod(self, _rptPkgIxdsOptions)
|
|
386
|
+
reportPackageErrors = False
|
|
387
|
+
if (filesource.isReportPackage or self.modelXbrl.modelManager.validateAllFilesAsReportPackages) and not _rptPkgIxdsOptions:
|
|
388
|
+
preLoadingErrorsCount = len(preLoadingErrors)
|
|
389
|
+
fileSourceValidator = ValidateFileSource(self.modelXbrl.modelManager.cntlr, filesource)
|
|
390
|
+
fileSourceValidator.validate(self.modelXbrl.modelManager.validateAllFilesAsReportPackages, preLoadingErrors)
|
|
391
|
+
if len(preLoadingErrors) > preLoadingErrorsCount:
|
|
392
|
+
reportPackageErrors = True
|
|
393
|
+
if filesource and not filesource.selection and filesource.isArchive:
|
|
394
|
+
try:
|
|
395
|
+
if filesource.isTaxonomyPackage or expectTaxonomyPackage:
|
|
396
|
+
filesource.loadTaxonomyPackageMappings(errors=preLoadingErrors, expectTaxonomyPackage=expectTaxonomyPackage)
|
|
397
|
+
filesource.select(None) # must select loadable reports (not the taxonomy package itself)
|
|
398
|
+
elif not filesource.isReportPackage:
|
|
399
|
+
entrypoints = filesourceEntrypointFiles(filesource)
|
|
400
|
+
fileSourceValidator = ValidateFileSource(self.modelXbrl.modelManager.cntlr, filesource)
|
|
401
|
+
fileSourceValidator.validate(self.modelXbrl.modelManager.validateAllFilesAsReportPackages, preLoadingErrors)
|
|
402
|
+
if entrypoints:
|
|
403
|
+
# resolve an IXDS in entrypoints
|
|
404
|
+
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ArchiveIxds"):
|
|
405
|
+
pluginXbrlMethod(self, filesource,entrypoints)
|
|
406
|
+
for entrypoint in entrypoints:
|
|
407
|
+
filesource.select(entrypoint.get("file", None))
|
|
408
|
+
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
409
|
+
filesource,
|
|
410
|
+
_("validating"),
|
|
411
|
+
base=filesource.basefile + "/",
|
|
412
|
+
errorCaptureLevel=errorCaptureLevel,
|
|
413
|
+
ixdsTarget=modelTestcaseVariation.ixdsTarget,
|
|
414
|
+
errors=preLoadingErrors)
|
|
415
|
+
loadedModels.append(modelXbrl)
|
|
416
|
+
except Exception as err:
|
|
417
|
+
self.modelXbrl.error("exception:" + type(err).__name__,
|
|
418
|
+
_("Testcase variation validation exception: %(error)s, entry URL: %(instance)s"),
|
|
419
|
+
modelXbrl=self.modelXbrl, instance=readMeFirstUri, error=err)
|
|
420
|
+
return [] # don't try to load this entry URL
|
|
421
|
+
if filesource and filesource.isReportPackage and not _rptPkgIxdsOptions:
|
|
422
|
+
if not reportPackageErrors:
|
|
423
|
+
assert isinstance(filesource.basefile, str)
|
|
424
|
+
if entrypoints := filesourceEntrypointFiles(filesource):
|
|
425
|
+
fileSourceValidator = ValidateFileSource(self.modelXbrl.modelManager.cntlr, filesource)
|
|
426
|
+
fileSourceValidator.validate(self.modelXbrl.modelManager.validateAllFilesAsReportPackages, preLoadingErrors)
|
|
427
|
+
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ArchiveIxds"):
|
|
428
|
+
pluginXbrlMethod(self, filesource, entrypoints)
|
|
429
|
+
for entrypoint in entrypoints:
|
|
430
|
+
filesource.select(entrypoint.get("file", None))
|
|
431
|
+
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
432
|
+
filesource,
|
|
433
|
+
_("validating"),
|
|
434
|
+
base=filesource.basefile + "/",
|
|
435
|
+
errorCaptureLevel=errorCaptureLevel,
|
|
436
|
+
ixdsTarget=modelTestcaseVariation.ixdsTarget,
|
|
437
|
+
errors=preLoadingErrors)
|
|
438
|
+
loadedModels.append(modelXbrl)
|
|
439
|
+
else:
|
|
440
|
+
if _rptPkgIxdsOptions and filesource.isTaxonomyPackage:
|
|
441
|
+
# Legacy ESEF conformance suite logic.
|
|
442
|
+
for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ReportPackageIxds"):
|
|
443
|
+
filesource.select(pluginXbrlMethod(filesource, **_rptPkgIxdsOptions))
|
|
444
|
+
if len(loadedModels) == 0:
|
|
445
|
+
modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
446
|
+
filesource,
|
|
447
|
+
_("validating"),
|
|
448
|
+
base=baseForElement,
|
|
449
|
+
errorCaptureLevel=errorCaptureLevel,
|
|
450
|
+
ixdsTarget=modelTestcaseVariation.ixdsTarget,
|
|
451
|
+
isLoadable=modelTestcaseVariation.variationDiscoversDTS or filesource.url,
|
|
452
|
+
errors=preLoadingErrors)
|
|
453
|
+
loadedModels.append(modelXbrl)
|
|
454
|
+
|
|
455
|
+
for model in loadedModels:
|
|
456
|
+
modelXbrl.isTestcaseVariation = True
|
|
457
|
+
if model.modelDocument is None:
|
|
458
|
+
if modelTestcaseVariation.expected not in ("EFM.6.03.04", "EFM.6.03.05"):
|
|
459
|
+
level = "ERROR" if modelTestcaseVariation.variationDiscoversDTS else "INFO"
|
|
460
|
+
model.log(
|
|
461
|
+
level,
|
|
462
|
+
"arelle:notLoaded",
|
|
463
|
+
_("Variation %(id)s %(name)s readMeFirst document not loaded: %(file)s"),
|
|
464
|
+
modelXbrl=testcase,
|
|
465
|
+
id=modelTestcaseVariation.id,
|
|
466
|
+
name=modelTestcaseVariation.name,
|
|
467
|
+
file=os.path.basename(readMeFirstUri),
|
|
468
|
+
)
|
|
469
|
+
elif resultIsVersioningReport or resultIsTaxonomyPackage:
|
|
470
|
+
inputDTSes['dtsName'].append(model)
|
|
471
|
+
elif model.modelDocument.type == Type.VERSIONINGREPORT:
|
|
472
|
+
ValidateVersReport.ValidateVersReport(self.modelXbrl).validate(model)
|
|
473
|
+
elif testcase.type == Type.REGISTRYTESTCASE:
|
|
474
|
+
self.instValidator.validate(model) # required to set up dimensions, etc
|
|
475
|
+
self.instValidator.executeCallTest(model, modelTestcaseVariation.id,
|
|
476
|
+
modelTestcaseVariation.cfcnCall, modelTestcaseVariation.cfcnTest)
|
|
477
|
+
self.instValidator.close()
|
|
478
|
+
else:
|
|
479
|
+
inputDTSes[dtsName].append(model)
|
|
480
|
+
# validate except for formulas
|
|
481
|
+
_hasFormulae = model.hasFormulae
|
|
482
|
+
model.hasFormulae = False
|
|
483
|
+
try:
|
|
484
|
+
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.Xbrl.Loaded"):
|
|
485
|
+
pluginXbrlMethod(self.modelXbrl, model, modelTestcaseVariation)
|
|
486
|
+
self.instValidator.validate(model, parameters)
|
|
487
|
+
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.Xbrl.Validated"):
|
|
488
|
+
pluginXbrlMethod(self.modelXbrl, model)
|
|
489
|
+
except Exception as err:
|
|
490
|
+
model.error("exception:" + type(err).__name__,
|
|
491
|
+
_("Testcase variation validation exception: %(error)s, instance: %(instance)s"),
|
|
492
|
+
modelXbrl=model, instance=model.modelDocument.basename, error=err, exc_info=(type(err) is not AssertionError))
|
|
493
|
+
model.hasFormulae = _hasFormulae
|
|
494
|
+
for pluginXbrlMethod in pluginClassMethods("Validate.Complete"):
|
|
495
|
+
pluginXbrlMethod(self.modelXbrl.modelManager.cntlr, filesource)
|
|
496
|
+
errors = [error for model in loadedModels for error in model.errors]
|
|
497
|
+
for err in preLoadingErrors:
|
|
498
|
+
if err not in errors:
|
|
499
|
+
# include errors from models which failed to load.
|
|
500
|
+
errors.append(err)
|
|
501
|
+
reportModelCount = len([
|
|
502
|
+
model for model in loadedModels
|
|
503
|
+
if model.modelDocument is not None and (model.fileSource.isReportPackage or not model.fileSource.isTaxonomyPackage)
|
|
504
|
+
])
|
|
505
|
+
self.determineTestStatus(modelTestcaseVariation, errors, validateModelCount=reportModelCount)
|
|
506
|
+
if not inputDTSes:
|
|
507
|
+
for model in loadedModels:
|
|
508
|
+
model.close()
|
|
509
|
+
return loadedModels
|
|
510
|
+
|
|
511
|
+
def _testcaseValidateInputDTS(self, testcase, modelTestcaseVariation, errorCaptureLevel, parameters, inputDTSes, baseForElement, resultIsXbrlInstance):
|
|
512
|
+
# validate schema, linkbase, or instance
|
|
513
|
+
formulaOutputInstance = None
|
|
514
|
+
modelXbrl = inputDTSes[None][0]
|
|
515
|
+
expectedDataFiles = set()
|
|
516
|
+
expectedTaxonomyPackages = []
|
|
517
|
+
for localName, d in modelTestcaseVariation.dataUris.items():
|
|
518
|
+
for uri in d:
|
|
519
|
+
if not UrlUtil.isAbsolute(uri):
|
|
520
|
+
normalizedUri = self.modelXbrl.modelManager.cntlr.webCache.normalizeUrl(uri, baseForElement)
|
|
521
|
+
if localName == "taxonomyPackage":
|
|
522
|
+
expectedTaxonomyPackages.append(normalizedUri)
|
|
523
|
+
else:
|
|
524
|
+
expectedDataFiles.add(normalizedUri)
|
|
525
|
+
expectedTaxonomyPackages.sort()
|
|
526
|
+
foundDataFiles = set()
|
|
527
|
+
variationBase = os.path.dirname(baseForElement)
|
|
528
|
+
for dtsName, inputDTS in inputDTSes.items(): # input instances are also parameters
|
|
529
|
+
if dtsName: # named instance
|
|
530
|
+
parameters[dtsName] = (None, inputDTS) #inputDTS is a list of modelXbrl's (instance DTSes)
|
|
531
|
+
elif len(inputDTS) > 1: # standard-input-instance with multiple instance documents
|
|
532
|
+
parameters[XbrlConst.qnStandardInputInstance] = (None, inputDTS) # allow error detection in validateFormula
|
|
533
|
+
for _inputDTS in inputDTS:
|
|
534
|
+
for docUrl, doc in _inputDTS.urlDocs.items():
|
|
535
|
+
if docUrl.startswith(variationBase) and not doc.type == Type.INLINEXBRLDOCUMENTSET:
|
|
536
|
+
if getattr(doc,"loadedFromXbrlFormula", False): # may have been sourced from xf file
|
|
537
|
+
if docUrl.replace("-formula.xml", ".xf") in expectedDataFiles:
|
|
538
|
+
docUrl = docUrl.replace("-formula.xml", ".xf")
|
|
539
|
+
foundDataFiles.add(docUrl)
|
|
540
|
+
|
|
541
|
+
foundDataFilesInTaxonomyPackages = set()
|
|
542
|
+
foundTaxonomyPackages = set()
|
|
543
|
+
for f in foundDataFiles:
|
|
544
|
+
if i := bisect.bisect(expectedTaxonomyPackages, f):
|
|
545
|
+
package = expectedTaxonomyPackages[i-1]
|
|
546
|
+
if f.startswith(package + "/"):
|
|
547
|
+
foundDataFilesInTaxonomyPackages.add(f)
|
|
548
|
+
foundTaxonomyPackages.add(package)
|
|
549
|
+
|
|
550
|
+
expectedNotFound = expectedDataFiles.union(expectedTaxonomyPackages) - foundDataFiles - foundTaxonomyPackages
|
|
551
|
+
if expectedNotFound:
|
|
552
|
+
modelXbrl.info("arelle:testcaseDataNotUsed",
|
|
553
|
+
_("Variation %(id)s %(name)s data files not used: %(missingDataFiles)s"),
|
|
554
|
+
modelObject=modelTestcaseVariation, name=modelTestcaseVariation.name, id=modelTestcaseVariation.id,
|
|
555
|
+
missingDataFiles=", ".join(sorted(os.path.basename(f) for f in expectedNotFound)))
|
|
556
|
+
foundNotExpected = foundDataFiles - expectedDataFiles - foundDataFilesInTaxonomyPackages
|
|
557
|
+
if foundNotExpected:
|
|
558
|
+
modelXbrl.info("arelle:testcaseDataUnexpected",
|
|
559
|
+
_("Variation %(id)s %(name)s files not in variation data: %(unexpectedDataFiles)s"),
|
|
560
|
+
modelObject=modelTestcaseVariation, name=modelTestcaseVariation.name, id=modelTestcaseVariation.id,
|
|
561
|
+
unexpectedDataFiles=", ".join(sorted(os.path.basename(f) for f in foundNotExpected)))
|
|
562
|
+
if modelXbrl.hasTableRendering or modelTestcaseVariation.resultIsTable:
|
|
563
|
+
try:
|
|
564
|
+
RenderingEvaluator.init(modelXbrl)
|
|
565
|
+
except Exception as err:
|
|
566
|
+
modelXbrl.error("exception:" + type(err).__name__,
|
|
567
|
+
_("Testcase RenderingEvaluator.init exception: %(error)s, instance: %(instance)s"),
|
|
568
|
+
modelXbrl=modelXbrl, instance=modelXbrl.modelDocument.basename, error=err, exc_info=True)
|
|
569
|
+
modelXbrlHasFormulae = modelXbrl.hasFormulae
|
|
570
|
+
if modelXbrlHasFormulae and self.modelXbrl.modelManager.formulaOptions.formulaAction != "none":
|
|
571
|
+
try:
|
|
572
|
+
# validate only formulae
|
|
573
|
+
self.instValidator.parameters = parameters
|
|
574
|
+
ValidateFormula.validate(self.instValidator)
|
|
575
|
+
except Exception as err:
|
|
576
|
+
modelXbrl.error("exception:" + type(err).__name__,
|
|
577
|
+
_("Testcase formula variation validation exception: %(error)s, instance: %(instance)s"),
|
|
578
|
+
modelXbrl=modelXbrl, instance=modelXbrl.modelDocument.basename, error=err, exc_info=(type(err) is not AssertionError))
|
|
579
|
+
if modelTestcaseVariation.resultIsInfoset and self.modelXbrl.modelManager.validateInfoset:
|
|
580
|
+
for pluginXbrlMethod in pluginClassMethods("Validate.Infoset"):
|
|
581
|
+
pluginXbrlMethod(modelXbrl, modelTestcaseVariation.resultInfosetUri)
|
|
582
|
+
infoset = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
583
|
+
modelTestcaseVariation.resultInfosetUri,
|
|
584
|
+
_("loading result infoset"),
|
|
585
|
+
base=baseForElement,
|
|
586
|
+
useFileSource=self.useFileSource,
|
|
587
|
+
errorCaptureLevel=errorCaptureLevel)
|
|
588
|
+
if infoset.modelDocument is None:
|
|
589
|
+
modelXbrl.error("arelle:notLoaded",
|
|
590
|
+
_("Variation %(id)s %(name)s result infoset not loaded: %(file)s"),
|
|
591
|
+
modelXbrl=testcase, id=modelTestcaseVariation.id, name=modelTestcaseVariation.name,
|
|
592
|
+
file=os.path.basename(modelTestcaseVariation.resultXbrlInstance))
|
|
593
|
+
modelTestcaseVariation.status = "result infoset not loadable"
|
|
594
|
+
else: # check infoset
|
|
595
|
+
ValidateInfoset.validate(self.instValidator, modelXbrl, infoset)
|
|
596
|
+
infoset.close()
|
|
597
|
+
if modelXbrl.hasTableRendering or modelTestcaseVariation.resultIsTable: # and self.modelXbrl.modelManager.validateInfoset:
|
|
598
|
+
# diff (or generate) table infoset
|
|
599
|
+
resultTableUri = modelXbrl.modelManager.cntlr.webCache.normalizeUrl(modelTestcaseVariation.resultTableUri, baseForElement)
|
|
600
|
+
if not any(alternativeValidation(modelXbrl, resultTableUri)
|
|
601
|
+
for alternativeValidation in pluginClassMethods("Validate.TableInfoset")):
|
|
602
|
+
try:
|
|
603
|
+
ViewFileRenderedLayout.viewRenderedLayout(modelXbrl, resultTableUri, diffToFile=True) # false to save infoset files
|
|
604
|
+
except Exception as err:
|
|
605
|
+
modelXbrl.error("exception:" + type(err).__name__,
|
|
606
|
+
_("Testcase table linkbase validation exception: %(error)s, instance: %(instance)s"),
|
|
607
|
+
modelXbrl=modelXbrl, instance=modelXbrl.modelDocument.basename, error=err, exc_info=True)
|
|
608
|
+
self.instValidator.close()
|
|
609
|
+
extraErrors = []
|
|
610
|
+
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.Validated"):
|
|
611
|
+
pluginXbrlMethod(self.modelXbrl, modelXbrl, extraErrors, inputDTSes)
|
|
612
|
+
self.determineTestStatus(modelTestcaseVariation, [e for inputDTSlist in inputDTSes.values() for inputDTS in inputDTSlist for e in inputDTS.errors] + extraErrors) # include infoset errors in status
|
|
613
|
+
if modelXbrl.formulaOutputInstance and self.noErrorCodes(modelTestcaseVariation.actual):
|
|
614
|
+
# if an output instance is created, and no string error codes, ignoring dict of assertion results, validate it
|
|
615
|
+
modelXbrl.formulaOutputInstance.hasFormulae = False # block formulae on output instance (so assertion of input is not lost)
|
|
616
|
+
self.instValidator.validate(modelXbrl.formulaOutputInstance, modelTestcaseVariation.parameters)
|
|
617
|
+
self.determineTestStatus(modelTestcaseVariation, modelXbrl.formulaOutputInstance.errors)
|
|
618
|
+
if self.noErrorCodes(modelTestcaseVariation.actual): # if still 'clean' pass it forward for comparison to expected result instance
|
|
619
|
+
formulaOutputInstance = modelXbrl.formulaOutputInstance
|
|
620
|
+
modelXbrl.formulaOutputInstance = None # prevent it from being closed now
|
|
621
|
+
self.instValidator.close()
|
|
622
|
+
compareIxResultInstance = (modelXbrl.modelDocument.type in (Type.INLINEXBRL, Type.INLINEXBRLDOCUMENTSET) and
|
|
623
|
+
modelTestcaseVariation.resultXbrlInstanceUri is not None)
|
|
624
|
+
if compareIxResultInstance:
|
|
625
|
+
formulaOutputInstance = modelXbrl # compare modelXbrl to generated output instance
|
|
626
|
+
errMsgPrefix = "ix"
|
|
627
|
+
else: # delete input instances before formula output comparision
|
|
628
|
+
for inputDTSlist in inputDTSes.values():
|
|
629
|
+
for inputDTS in inputDTSlist:
|
|
630
|
+
inputDTS.close()
|
|
631
|
+
del inputDTSes # dereference
|
|
632
|
+
errMsgPrefix = "formula"
|
|
633
|
+
if resultIsXbrlInstance and formulaOutputInstance and formulaOutputInstance.modelDocument:
|
|
634
|
+
_matchExpectedResultIDs = not modelXbrlHasFormulae # formula restuls have inconsistent IDs
|
|
635
|
+
expectedInstance = ModelXbrl.load(self.modelXbrl.modelManager,
|
|
636
|
+
modelTestcaseVariation.resultXbrlInstanceUri,
|
|
637
|
+
_("loading expected result XBRL instance"),
|
|
638
|
+
base=baseForElement,
|
|
639
|
+
useFileSource=self.useFileSource,
|
|
640
|
+
errorCaptureLevel=errorCaptureLevel)
|
|
641
|
+
if expectedInstance.modelDocument is None:
|
|
642
|
+
self.modelXbrl.error("{}:expectedResultNotLoaded".format(errMsgPrefix),
|
|
643
|
+
_("Testcase \"%(name)s\" %(id)s expected result instance not loaded: %(file)s"),
|
|
644
|
+
modelXbrl=testcase, id=modelTestcaseVariation.id, name=modelTestcaseVariation.name,
|
|
645
|
+
file=os.path.basename(modelTestcaseVariation.resultXbrlInstanceUri),
|
|
646
|
+
messageCodes=("formula:expectedResultNotLoaded","ix:expectedResultNotLoaded"))
|
|
647
|
+
modelTestcaseVariation.status = "result not loadable"
|
|
648
|
+
else: # compare facts
|
|
649
|
+
for pluginXbrlMethod in pluginClassMethods("TestcaseVariation.ExpectedInstance.Loaded"):
|
|
650
|
+
pluginXbrlMethod(expectedInstance, formulaOutputInstance)
|
|
651
|
+
if len(expectedInstance.facts) != len(formulaOutputInstance.facts):
|
|
652
|
+
formulaOutputInstance.error("{}:resultFactCounts".format(errMsgPrefix),
|
|
653
|
+
_("Formula output %(countFacts)s facts, expected %(expectedFacts)s facts"),
|
|
654
|
+
modelXbrl=modelXbrl, countFacts=len(formulaOutputInstance.facts),
|
|
655
|
+
expectedFacts=len(expectedInstance.facts),
|
|
656
|
+
messageCodes=("formula:resultFactCounts","ix:resultFactCounts"))
|
|
657
|
+
else:
|
|
658
|
+
formulaOutputFootnotesRelSet = ModelRelationshipSet(formulaOutputInstance, "XBRL-footnotes")
|
|
659
|
+
expectedFootnotesRelSet = ModelRelationshipSet(expectedInstance, "XBRL-footnotes")
|
|
660
|
+
def factFootnotes(fact, footnotesRelSet):
|
|
661
|
+
footnotes = {}
|
|
662
|
+
footnoteRels = footnotesRelSet.fromModelObject(fact)
|
|
663
|
+
if footnoteRels:
|
|
664
|
+
# most process rels in same order between two instances, use labels to sort
|
|
665
|
+
for i, footnoteRel in enumerate(sorted(footnoteRels,
|
|
666
|
+
key=lambda r: (r.fromLabel,r.toLabel))):
|
|
667
|
+
modelObject = footnoteRel.toModelObject
|
|
668
|
+
if isinstance(modelObject, ModelResource):
|
|
669
|
+
xml = collapseWhitespace(modelObject.viewText().strip())
|
|
670
|
+
footnotes["Footnote {}".format(i+1)] = xml #re.sub(r'\s+', ' ', collapseWhitespace(modelObject.stringValue))
|
|
671
|
+
elif isinstance(modelObject, ModelFact):
|
|
672
|
+
footnotes["Footnoted fact {}".format(i+1)] = \
|
|
673
|
+
"{} context: {} value: {}".format(
|
|
674
|
+
modelObject.qname,
|
|
675
|
+
modelObject.contextID,
|
|
676
|
+
collapseWhitespace(modelObject.value))
|
|
677
|
+
return footnotes
|
|
678
|
+
for expectedInstanceFact in expectedInstance.facts:
|
|
679
|
+
unmatchedFactsStack = []
|
|
680
|
+
formulaOutputFact = formulaOutputInstance.matchFact(expectedInstanceFact, unmatchedFactsStack, deemP0inf=True, matchId=_matchExpectedResultIDs, matchLang=False)
|
|
681
|
+
#formulaOutputFact = formulaOutputInstance.matchFact(expectedInstanceFact, unmatchedFactsStack, deemP0inf=True, matchId=True, matchLang=True)
|
|
682
|
+
if formulaOutputFact is None:
|
|
683
|
+
if unmatchedFactsStack: # get missing nested tuple fact, if possible
|
|
684
|
+
missingFact = unmatchedFactsStack[-1]
|
|
685
|
+
else:
|
|
686
|
+
missingFact = expectedInstanceFact
|
|
687
|
+
# is it possible to show value mismatches?
|
|
688
|
+
expectedFacts = formulaOutputInstance.factsByQname.get(missingFact.qname)
|
|
689
|
+
if expectedFacts and len(expectedFacts) == 1:
|
|
690
|
+
formulaOutputInstance.error("{}:expectedFactMissing".format(errMsgPrefix),
|
|
691
|
+
_("Output missing expected fact %(fact)s, extracted value \"%(value1)s\", expected value \"%(value2)s\""),
|
|
692
|
+
modelXbrl=missingFact, fact=missingFact.qname, value1=missingFact.xValue, value2=next(iter(expectedFacts)).xValue,
|
|
693
|
+
messageCodes=("formula:expectedFactMissing","ix:expectedFactMissing"))
|
|
694
|
+
else:
|
|
695
|
+
formulaOutputInstance.error("{}:expectedFactMissing".format(errMsgPrefix),
|
|
696
|
+
_("Output missing expected fact %(fact)s"),
|
|
697
|
+
modelXbrl=missingFact, fact=missingFact.qname,
|
|
698
|
+
messageCodes=("formula:expectedFactMissing","ix:expectedFactMissing"))
|
|
699
|
+
else: # compare footnotes
|
|
700
|
+
expectedInstanceFactFootnotes = factFootnotes(expectedInstanceFact, expectedFootnotesRelSet)
|
|
701
|
+
formulaOutputFactFootnotes = factFootnotes(formulaOutputFact, formulaOutputFootnotesRelSet)
|
|
702
|
+
if (len(expectedInstanceFactFootnotes) != len(formulaOutputFactFootnotes) or
|
|
703
|
+
set(expectedInstanceFactFootnotes.values()) != set(formulaOutputFactFootnotes.values())):
|
|
704
|
+
formulaOutputInstance.error("{}:expectedFactFootnoteDifference".format(errMsgPrefix),
|
|
705
|
+
_("Output expected fact %(fact)s expected footnotes %(footnotes1)s produced footnotes %(footnotes2)s"),
|
|
706
|
+
modelXbrl=(formulaOutputFact,expectedInstanceFact), fact=expectedInstanceFact.qname, footnotes1=sorted(expectedInstanceFactFootnotes.items()), footnotes2=sorted(formulaOutputFactFootnotes.items()),
|
|
707
|
+
messageCodes=("formula:expectedFactFootnoteDifference","ix:expectedFactFootnoteDifference"))
|
|
708
|
+
|
|
709
|
+
# for debugging uncomment next line to save generated instance document
|
|
710
|
+
# formulaOutputInstance.saveInstance(r"c:\temp\test-out-inst.xml")
|
|
711
|
+
expectedInstance.close()
|
|
712
|
+
del expectedInstance # dereference
|
|
713
|
+
self.determineTestStatus(modelTestcaseVariation, formulaOutputInstance.errors)
|
|
714
|
+
formulaOutputInstance.close()
|
|
715
|
+
del formulaOutputInstance
|
|
716
|
+
if compareIxResultInstance:
|
|
717
|
+
for inputDTSlist in inputDTSes.values():
|
|
718
|
+
for inputDTS in inputDTSlist:
|
|
719
|
+
inputDTS.close()
|
|
720
|
+
del inputDTSes # dereference
|
|
721
|
+
|
|
548
722
|
def noErrorCodes(self, modelTestcaseVariationActual):
|
|
549
723
|
return not any(not isinstance(actual,dict) for actual in modelTestcaseVariationActual)
|
|
550
724
|
|
|
551
|
-
def determineTestStatus(self, modelTestcaseVariation, errors):
|
|
725
|
+
def determineTestStatus(self, modelTestcaseVariation, errors, validateModelCount=None):
|
|
552
726
|
testcaseResultOptions = self.modelXbrl.modelManager.formulaOptions.testcaseResultOptions
|
|
553
|
-
|
|
727
|
+
testcaseExpectedErrors = self.modelXbrl.modelManager.formulaOptions.testcaseExpectedErrors or {}
|
|
728
|
+
matchAllExpected = testcaseResultOptions == "match-all" or modelTestcaseVariation.match == 'all'
|
|
729
|
+
expectedReportCount = modelTestcaseVariation.expectedReportCount
|
|
730
|
+
expectedWarnings = modelTestcaseVariation.expectedWarnings if self.modelXbrl.modelManager.formulaOptions.testcaseResultsCaptureWarnings else []
|
|
731
|
+
if expectedReportCount is not None and validateModelCount is not None and expectedReportCount != validateModelCount:
|
|
732
|
+
errors.append("conf:testcaseExpectedReportCountError")
|
|
554
733
|
_blockedMessageCodes = modelTestcaseVariation.blockedMessageCodes # restricts codes examined when provided
|
|
555
734
|
if _blockedMessageCodes:
|
|
556
735
|
_blockPattern = re.compile(_blockedMessageCodes)
|
|
557
736
|
_errors = [e for e in errors if isinstance(e,str) and not _blockPattern.match(e)]
|
|
558
737
|
else:
|
|
559
738
|
_errors = errors
|
|
739
|
+
_errors.extend(self.modelXbrl.modelManager.cntlr.errors)
|
|
560
740
|
numErrors = sum(isinstance(e,(QName,str)) for e in _errors) # does not include asserton dict results
|
|
561
741
|
hasAssertionResult = any(isinstance(e,dict) for e in _errors)
|
|
562
742
|
expected = modelTestcaseVariation.expected
|
|
563
743
|
expectedCount = modelTestcaseVariation.expectedCount
|
|
744
|
+
indexPath = modelTestcaseVariation.document.filepath
|
|
745
|
+
if self.useFileSource is not None and self.useFileSource.isZip:
|
|
746
|
+
baseZipFile = self.useFileSource.basefile
|
|
747
|
+
if indexPath.startswith(baseZipFile):
|
|
748
|
+
indexPath = indexPath[len(baseZipFile) + 1:]
|
|
749
|
+
indexPath = indexPath.replace("\\", "/")
|
|
750
|
+
variationIdPath = f'{indexPath}:{modelTestcaseVariation.id}'
|
|
751
|
+
userExpectedErrors = []
|
|
752
|
+
for userPattern, userErrors in testcaseExpectedErrors.items():
|
|
753
|
+
if fnmatch.fnmatch(variationIdPath, userPattern):
|
|
754
|
+
userExpectedErrors.extend(userErrors)
|
|
755
|
+
if userExpectedErrors:
|
|
756
|
+
if expected is None:
|
|
757
|
+
expected = []
|
|
758
|
+
if isinstance(expected, str):
|
|
759
|
+
assert expected in {"valid", "invalid"}, f"unhandled expected value string '{expected}'"
|
|
760
|
+
expected = []
|
|
761
|
+
expected.extend(userExpectedErrors)
|
|
762
|
+
if expectedCount is not None:
|
|
763
|
+
expectedCount += len(userExpectedErrors)
|
|
564
764
|
if matchAllExpected:
|
|
565
765
|
if isinstance(expected, list):
|
|
566
766
|
if not expectedCount:
|
|
@@ -568,27 +768,30 @@ class Validate:
|
|
|
568
768
|
elif expectedCount is None:
|
|
569
769
|
expectedCount = 0
|
|
570
770
|
if expected == "valid":
|
|
571
|
-
if numErrors == 0
|
|
572
|
-
status = "pass"
|
|
573
|
-
else:
|
|
574
|
-
status = "fail"
|
|
771
|
+
status = "pass" if numErrors == 0 else "fail"
|
|
575
772
|
elif expected == "invalid":
|
|
576
|
-
if numErrors == 0
|
|
577
|
-
|
|
578
|
-
else:
|
|
579
|
-
status = "pass"
|
|
580
|
-
elif expected in (None, []) and numErrors == 0:
|
|
773
|
+
status = "fail" if numErrors == 0 else "pass"
|
|
774
|
+
elif expected in (None, []) and numErrors == 0 and not expectedWarnings:
|
|
581
775
|
status = "pass"
|
|
582
|
-
elif isinstance(expected,(QName,str,dict,list))
|
|
776
|
+
elif isinstance(expected, (QName, str, dict, list)) or expectedWarnings:
|
|
583
777
|
status = "fail"
|
|
584
778
|
_passCount = 0
|
|
585
779
|
if isinstance(expected, list):
|
|
586
|
-
_expectedList = expected.copy()
|
|
780
|
+
_expectedList = expected.copy()
|
|
781
|
+
elif not expected:
|
|
782
|
+
_expectedList = []
|
|
587
783
|
else:
|
|
588
784
|
_expectedList = [expected]
|
|
589
|
-
if
|
|
785
|
+
if expectedWarnings:
|
|
786
|
+
_expectedList.extend(expectedWarnings)
|
|
787
|
+
if expectedCount is not None:
|
|
788
|
+
expectedCount += len(expectedWarnings)
|
|
789
|
+
else:
|
|
790
|
+
expectedCount = len(expectedWarnings)
|
|
791
|
+
if not isinstance(expected, list):
|
|
792
|
+
expected = [expected]
|
|
590
793
|
for testErr in _errors:
|
|
591
|
-
if isinstance(testErr,str) and testErr.startswith("ESEF."): # compared as list of strings to QName localname
|
|
794
|
+
if isinstance(testErr, str) and testErr.startswith(("ESEF.", "NL.NL-KVK")): # compared as list of strings to QName localname
|
|
592
795
|
testErr = testErr.rpartition(".")[2]
|
|
593
796
|
for _exp in _expectedList:
|
|
594
797
|
_expMatched = False
|
|
@@ -601,7 +804,7 @@ class Validate:
|
|
|
601
804
|
# XDT xml schema tests expected results
|
|
602
805
|
(_exp.namespaceURI == XbrlConst.xdtSchemaErrorNS and errPrefix == "xmlSchema")):
|
|
603
806
|
_expMatched = True
|
|
604
|
-
elif type(testErr)
|
|
807
|
+
elif type(testErr) is type(_exp):
|
|
605
808
|
if isinstance(testErr,dict):
|
|
606
809
|
if len(testErr) == len(_exp) and all(
|
|
607
810
|
k in testErr and counts == testErr[k][:len(counts)]
|
|
@@ -615,6 +818,7 @@ class Validate:
|
|
|
615
818
|
(_exp == "EFM.6.04.03" and (testErr.startswith("xmlSchema:") or testErr.startswith("utr:") or testErr.startswith("xbrl.") or testErr.startswith("xlink:"))) or
|
|
616
819
|
(_exp == "EFM.6.05.35" and testErr.startswith("utre:")) or
|
|
617
820
|
(_exp.startswith("EFM.") and testErr.startswith(_exp)) or
|
|
821
|
+
(_exp.startswith("EXG.") and testErr.startswith(_exp)) or
|
|
618
822
|
(_exp == "vere:invalidDTSIdentifier" and testErr.startswith("xbrl"))
|
|
619
823
|
))):
|
|
620
824
|
_expMatched = True
|
|
@@ -665,16 +869,6 @@ class Validate:
|
|
|
665
869
|
if isinstance(error,dict):
|
|
666
870
|
modelTestcaseVariation.actual.append(error)
|
|
667
871
|
|
|
668
|
-
def determineNotLoadedTestStatus(self, modelTestcaseVariation, errors):
|
|
669
|
-
if errors:
|
|
670
|
-
self.determineTestStatus(modelTestcaseVariation, errors)
|
|
671
|
-
return
|
|
672
|
-
expected = modelTestcaseVariation.expected
|
|
673
|
-
status = "not loadable"
|
|
674
|
-
if expected in ("EFM.6.03.04", "EFM.6.03.05"):
|
|
675
|
-
status = "pass"
|
|
676
|
-
modelTestcaseVariation.status = status
|
|
677
|
-
|
|
678
872
|
import logging
|
|
679
873
|
class ValidationLogListener(logging.Handler):
|
|
680
874
|
def __init__(self, logView):
|