arelle-release 2.37.46__py3-none-any.whl → 2.38.0__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/BetaFeatures.py +0 -21
- arelle/Cntlr.py +15 -8
- arelle/CntlrCmdLine.py +121 -56
- arelle/CntlrWinMain.py +143 -70
- arelle/DialogFind.py +1 -1
- arelle/DialogPluginManager.py +6 -4
- arelle/DisclosureSystem.py +7 -0
- arelle/ErrorManager.py +21 -6
- arelle/FileSource.py +11 -4
- arelle/FunctionIxt.py +16 -11
- arelle/HtmlUtil.py +5 -4
- arelle/LeiUtil.py +63 -43
- arelle/ModelDocument.py +20 -15
- arelle/ModelDtsObject.py +8 -0
- arelle/ModelInstanceObject.py +1 -1
- arelle/ModelObject.py +16 -18
- arelle/ModelObjectFactory.py +35 -17
- arelle/ModelXbrl.py +28 -11
- arelle/PluginManager.py +130 -105
- arelle/RuntimeOptions.py +1 -0
- arelle/UrlUtil.py +14 -0
- arelle/Validate.py +17 -12
- arelle/ValidateDuplicateFacts.py +3 -1
- arelle/ValidateFileSource.py +38 -0
- arelle/ValidateFilingText.py +3 -3
- arelle/ValidateXbrl.py +5 -2
- arelle/ValidateXbrlCalcs.py +210 -186
- arelle/ValidateXbrlDTS.py +1 -1
- arelle/ViewFile.py +1 -0
- arelle/ViewFileFactTable.py +2 -2
- arelle/ViewWinDTS.py +4 -1
- arelle/WebCache.py +28 -24
- arelle/XbrlConst.py +22 -0
- arelle/XmlUtil.py +16 -21
- arelle/XmlValidate.py +6 -9
- arelle/_version.py +16 -3
- arelle/api/Session.py +11 -2
- arelle/config/disclosuresystems.xsd +2 -0
- arelle/config/rosettaEntitlements.plist +8 -0
- arelle/conformance/CSVTestcaseLoader.py +1 -1
- arelle/formula/XPathContext.py +3 -3
- arelle/logging/formatters/LogFormatter.py +3 -1
- arelle/packages/report/ReportPackage.py +26 -13
- arelle/packages/report/ReportPackageConst.py +0 -1
- arelle/plugin/inlineXbrlDocumentSet.py +19 -5
- arelle/plugin/validate/DBA/DisclosureSystems.py +19 -1
- arelle/plugin/validate/DBA/PluginValidationDataExtension.py +2 -4
- arelle/plugin/validate/DBA/ValidationPluginExtension.py +2 -1
- arelle/plugin/validate/DBA/resources/config.xml +5 -0
- arelle/plugin/validate/DBA/rules/__init__.py +2 -2
- arelle/plugin/validate/DBA/rules/fr.py +19 -2
- arelle/plugin/validate/DBA/rules/tc.py +2 -0
- arelle/plugin/validate/DBA/rules/th.py +6 -0
- arelle/plugin/validate/DBA/rules/tm.py +18 -5
- arelle/plugin/validate/DBA/rules/tr.py +11 -5
- arelle/plugin/validate/EDINET/Constants.py +193 -9
- arelle/plugin/validate/EDINET/ContextRequirement.py +58 -0
- arelle/plugin/validate/EDINET/ControllerPluginData.py +220 -1
- arelle/plugin/validate/EDINET/CoverItemRequirements.py +42 -0
- arelle/plugin/validate/EDINET/DeiRequirements.py +118 -0
- arelle/plugin/validate/EDINET/FilingFormat.py +275 -0
- arelle/plugin/validate/EDINET/FormType.py +134 -0
- arelle/plugin/validate/EDINET/ManifestInstance.py +72 -5
- arelle/plugin/validate/EDINET/NamespaceConfig.py +50 -0
- arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +493 -132
- arelle/plugin/validate/EDINET/{InstanceType.py → ReportFolderType.py} +72 -15
- arelle/plugin/validate/EDINET/Statement.py +139 -0
- arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +595 -0
- arelle/plugin/validate/EDINET/UploadContents.py +48 -0
- arelle/plugin/validate/EDINET/ValidationPluginExtension.py +20 -2
- arelle/plugin/validate/EDINET/__init__.py +31 -6
- arelle/plugin/validate/EDINET/resources/config.xml +8 -1
- 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 +2 -0
- arelle/plugin/validate/EDINET/rules/contexts.py +375 -14
- arelle/plugin/validate/EDINET/rules/edinet.py +1934 -45
- arelle/plugin/validate/EDINET/rules/frta.py +122 -3
- arelle/plugin/validate/EDINET/rules/gfm.py +1907 -11
- arelle/plugin/validate/EDINET/rules/upload.py +989 -141
- arelle/plugin/validate/ESEF/Const.py +3 -1
- arelle/plugin/validate/ESEF/ESEF_2021/DTS.py +5 -0
- arelle/plugin/validate/ESEF/ESEF_2021/Image.py +2 -2
- arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +23 -20
- arelle/plugin/validate/ESEF/ESEF_Current/DTS.py +47 -14
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +100 -25
- arelle/plugin/validate/ESEF/__init__.py +20 -6
- arelle/plugin/validate/ESEF/resources/authority-validations.json +76 -9
- arelle/plugin/validate/ESEF/resources/config.xml +20 -0
- arelle/plugin/validate/NL/DisclosureSystems.py +22 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +27 -9
- arelle/plugin/validate/NL/ValidationPluginExtension.py +51 -7
- arelle/plugin/validate/NL/resources/config.xml +18 -0
- arelle/plugin/validate/NL/rules/br_kvk.py +17 -61
- arelle/plugin/validate/NL/rules/fg_nl.py +7 -38
- arelle/plugin/validate/NL/rules/fr_kvk.py +7 -42
- arelle/plugin/validate/NL/rules/fr_nl.py +31 -147
- arelle/plugin/validate/NL/rules/nl_kvk.py +142 -28
- arelle/plugin/validate/ROS/PluginValidationDataExtension.py +2 -0
- arelle/plugin/validate/ROS/ValidationPluginExtension.py +4 -1
- arelle/plugin/validate/ROS/rules/ros.py +41 -9
- arelle/plugin/validate/UK/ValidateUK.py +130 -66
- arelle/plugin/validate/UK/__init__.py +89 -103
- arelle/utils/EntryPointDetection.py +79 -13
- arelle/utils/PluginHooks.py +125 -0
- arelle/utils/validate/ESEFImage.py +6 -6
- arelle/utils/validate/Validation.py +18 -0
- arelle/utils/validate/ValidationPlugin.py +76 -11
- arelle/utils/validate/ValidationUtil.py +35 -3
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/METADATA +30 -20
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/RECORD +115 -191
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/licenses/LICENSE.md +0 -3
- arelle/archive/CustomLogger.py +0 -43
- arelle/archive/LoadEFMvalidate.py +0 -32
- arelle/archive/LoadSavePreLbCsv.py +0 -26
- arelle/archive/LoadValidate.cs +0 -31
- arelle/archive/LoadValidate.py +0 -36
- arelle/archive/LoadValidateCmdLine.java +0 -69
- arelle/archive/LoadValidatePostedZip.java +0 -57
- arelle/archive/LoadValidateWebService.java +0 -34
- arelle/archive/SaveTableToExelle.py +0 -140
- arelle/archive/TR3toTR4.py +0 -88
- arelle/archive/plugin/ESEF_2022/__init__.py +0 -47
- arelle/archive/plugin/bigInstance.py +0 -394
- arelle/archive/plugin/cmdWebServerExtension.py +0 -43
- arelle/archive/plugin/crashTest.py +0 -38
- arelle/archive/plugin/functionsXmlCreation.py +0 -106
- arelle/archive/plugin/hello_i18n.pot +0 -26
- arelle/archive/plugin/hello_i18n.py +0 -32
- arelle/archive/plugin/importTestChild1.py +0 -21
- arelle/archive/plugin/importTestChild2.py +0 -22
- arelle/archive/plugin/importTestGrandchild1.py +0 -21
- arelle/archive/plugin/importTestGrandchild2.py +0 -21
- arelle/archive/plugin/importTestImported1.py +0 -23
- arelle/archive/plugin/importTestImported11.py +0 -22
- arelle/archive/plugin/importTestParent.py +0 -48
- arelle/archive/plugin/instanceInfo.py +0 -306
- arelle/archive/plugin/loadFromOIM-2018.py +0 -1282
- arelle/archive/plugin/locale/fr/LC_MESSAGES/hello_i18n.po +0 -25
- arelle/archive/plugin/objectmaker.py +0 -285
- arelle/archive/plugin/packagedImportTest/__init__.py +0 -47
- arelle/archive/plugin/packagedImportTest/importTestChild1.py +0 -21
- arelle/archive/plugin/packagedImportTest/importTestChild2.py +0 -22
- arelle/archive/plugin/packagedImportTest/importTestGrandchild1.py +0 -21
- arelle/archive/plugin/packagedImportTest/importTestGrandchild2.py +0 -21
- arelle/archive/plugin/packagedImportTest/importTestImported1.py +0 -24
- arelle/archive/plugin/packagedImportTest/importTestImported11.py +0 -21
- arelle/archive/plugin/packagedImportTest/subdir/importTestImported111.py +0 -21
- arelle/archive/plugin/packagedImportTest/subdir/subsubdir/importTestImported1111.py +0 -21
- arelle/archive/plugin/sakaCalendar.py +0 -215
- arelle/archive/plugin/saveInstanceInfoset.py +0 -121
- arelle/archive/plugin/sphinx/FormulaGenerator.py +0 -823
- arelle/archive/plugin/sphinx/SphinxContext.py +0 -404
- arelle/archive/plugin/sphinx/SphinxEvaluator.py +0 -783
- arelle/archive/plugin/sphinx/SphinxMethods.py +0 -1287
- arelle/archive/plugin/sphinx/SphinxParser.py +0 -1093
- arelle/archive/plugin/sphinx/SphinxValidator.py +0 -163
- arelle/archive/plugin/sphinx/US-GAAP Ratios Example.xsr +0 -52
- arelle/archive/plugin/sphinx/__init__.py +0 -285
- arelle/archive/plugin/streamingExtensions.py +0 -335
- arelle/archive/plugin/updateTableLB.py +0 -242
- arelle/archive/plugin/validate/SBRnl/CustomLoader.py +0 -19
- arelle/archive/plugin/validate/SBRnl/DTS.py +0 -305
- arelle/archive/plugin/validate/SBRnl/Dimensions.py +0 -357
- arelle/archive/plugin/validate/SBRnl/Document.py +0 -799
- arelle/archive/plugin/validate/SBRnl/Filing.py +0 -467
- arelle/archive/plugin/validate/SBRnl/__init__.py +0 -75
- arelle/archive/plugin/validate/SBRnl/config.xml +0 -26
- arelle/archive/plugin/validate/SBRnl/sbr-nl-taxonomies.xml +0 -754
- arelle/archive/plugin/validate/USBestPractices.py +0 -570
- arelle/archive/plugin/validate/USCorpAction.py +0 -557
- arelle/archive/plugin/validate/USSecTagging.py +0 -337
- arelle/archive/plugin/validate/XDC/__init__.py +0 -77
- arelle/archive/plugin/validate/XDC/config.xml +0 -20
- arelle/archive/plugin/validate/XFsyntax/__init__.py +0 -64
- arelle/archive/plugin/validate/XFsyntax/xf.py +0 -2227
- arelle/archive/plugin/validate/calc2.py +0 -536
- arelle/archive/plugin/validateSchemaLxml.py +0 -156
- arelle/archive/plugin/validateTableInfoset.py +0 -52
- arelle/archive/us-gaap-dei-docType-extraction-frm.xml +0 -90
- arelle/archive/us-gaap-dei-ratio-cash-frm.xml +0 -150
- 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/multi.py +0 -58
- arelle/examples/plugin/rssSaveOim.py +0 -96
- 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/__init__.py +0 -0
- arelle/examples/plugin/validate/XYZ/rules/rules01.py +0 -110
- arelle/examples/plugin/validate/XYZ/rules/rules02.py +0 -59
- arelle/model/CommentBase.py +0 -9
- arelle/model/ElementBase.py +0 -11
- arelle/model/PIBase.py +0 -10
- arelle/model/__init__.py +0 -15
- arelle/scripts-macOS/startWebServer.command +0 -3
- arelle/scripts-unix/startWebServer.sh +0 -1
- arelle/scripts-windows/startWebServer.bat +0 -5
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.46.dist-info → arelle_release-2.38.0.dist-info}/top_level.txt +0 -0
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
pluginPackages test case
|
|
3
|
-
|
|
4
|
-
See COPYRIGHT.md for copyright information.
|
|
5
|
-
'''
|
|
6
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
7
|
-
|
|
8
|
-
def foo():
|
|
9
|
-
print ("imported unpackaged plug-in grandchild 1")
|
|
10
|
-
|
|
11
|
-
__pluginInfo__ = {
|
|
12
|
-
'name': 'Unpackaged Listed Import Grandchild 1.1',
|
|
13
|
-
'version': '0.9',
|
|
14
|
-
'description': "This is a packages-containing unpackaged child plugin.",
|
|
15
|
-
'license': 'Apache-2',
|
|
16
|
-
'author': authorLabel,
|
|
17
|
-
'copyright': copyrightLabel,
|
|
18
|
-
# classes of mount points (required)
|
|
19
|
-
'Import.Unpackaged.Entry4': foo,
|
|
20
|
-
# imported plugins
|
|
21
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
pluginPackages test case
|
|
3
|
-
|
|
4
|
-
See COPYRIGHT.md for copyright information.
|
|
5
|
-
'''
|
|
6
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
7
|
-
|
|
8
|
-
def foo():
|
|
9
|
-
print ("imported unpackaged plug-in grandchild 2")
|
|
10
|
-
|
|
11
|
-
__pluginInfo__ = {
|
|
12
|
-
'name': 'Unpackaged Listed Import Grandchild 1.2',
|
|
13
|
-
'version': '0.9',
|
|
14
|
-
'description': "This is a packages-containing child plugin.",
|
|
15
|
-
'license': 'Apache-2',
|
|
16
|
-
'author': authorLabel,
|
|
17
|
-
'copyright': copyrightLabel,
|
|
18
|
-
# classes of mount points (required)
|
|
19
|
-
'Import.Unpackaged.Entry5': foo,
|
|
20
|
-
# imported plugins
|
|
21
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
pluginPackages test case
|
|
3
|
-
|
|
4
|
-
See COPYRIGHT.md for copyright information.
|
|
5
|
-
'''
|
|
6
|
-
# this module would raise system error due to PEP 366 after python 3.4.3
|
|
7
|
-
from . import importTestImported11
|
|
8
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
9
|
-
|
|
10
|
-
def foo():
|
|
11
|
-
print ("imported unpackaged plug-in relative imported 1")
|
|
12
|
-
|
|
13
|
-
__pluginInfo__ = {
|
|
14
|
-
'name': 'Unpackaged Relative Import 1',
|
|
15
|
-
'version': '0.9',
|
|
16
|
-
'description': "This is a unpackaged relative imported plugin.",
|
|
17
|
-
'license': 'Apache-2',
|
|
18
|
-
'author': authorLabel,
|
|
19
|
-
'copyright': copyrightLabel,
|
|
20
|
-
# classes of mount points (required)
|
|
21
|
-
'Import.Unpackaged.Entry6': foo,
|
|
22
|
-
# imported plugins
|
|
23
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
pluginPackages test case
|
|
3
|
-
|
|
4
|
-
See COPYRIGHT.md for copyright information.
|
|
5
|
-
'''
|
|
6
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
7
|
-
# this module would raise system error due to PEP 366 after python 3.4.3
|
|
8
|
-
|
|
9
|
-
def foo():
|
|
10
|
-
print ("imported unpackaged plug-in imported relative 1.1")
|
|
11
|
-
|
|
12
|
-
__pluginInfo__ = {
|
|
13
|
-
'name': 'Unpackaged Relative Import 1.1',
|
|
14
|
-
'version': '0.9',
|
|
15
|
-
'description': "This is a packages-containing unpackaged imported plugin.",
|
|
16
|
-
'license': 'Apache-2',
|
|
17
|
-
'author': authorLabel,
|
|
18
|
-
'copyright': copyrightLabel,
|
|
19
|
-
# classes of mount points (required)
|
|
20
|
-
'Import.Unpackaged.Entry7': foo,
|
|
21
|
-
# imported plugins
|
|
22
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
pluginPackages test case
|
|
3
|
-
|
|
4
|
-
See COPYRIGHT.md for copyright information.
|
|
5
|
-
'''
|
|
6
|
-
from arelle.PluginManager import pluginClassMethods
|
|
7
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
8
|
-
# . relative import only works inside a package now, see https://www.python.org/dev/peps/pep-0366/
|
|
9
|
-
# following two imports raise system error due to PEP 366 after python 3.4.3
|
|
10
|
-
# from . import importTestImported1
|
|
11
|
-
# from .importTestImported1 import foo
|
|
12
|
-
|
|
13
|
-
def parentMenuEntender(cntlr, menu):
|
|
14
|
-
menu.add_command(label="Unpackaged Parent exercise descendants", underline=0, command=lambda: parentMenuCommand(cntlr) )
|
|
15
|
-
|
|
16
|
-
def parentMenuCommand(cntl):
|
|
17
|
-
for i in range(1,100):
|
|
18
|
-
for pluginMethod in pluginClassMethods("Import.Unpackaged.Entry{}".format(i)):
|
|
19
|
-
pluginMethod()
|
|
20
|
-
|
|
21
|
-
def parentCommandLineOptionExtender(parser):
|
|
22
|
-
parser.add_option("--unpackageParentImportExample",
|
|
23
|
-
action="store_true",
|
|
24
|
-
dest="unpackageParentImportExample",
|
|
25
|
-
help=_('Test that unpackaged imported plug-ins were actually loaded and activated"'))
|
|
26
|
-
|
|
27
|
-
def parentCommandLineUtilityRun(cntlr, options, **kwargs):
|
|
28
|
-
if options.unpackageParentImportExample:
|
|
29
|
-
parentMenuCommand(cntlr)
|
|
30
|
-
|
|
31
|
-
def foo():
|
|
32
|
-
print ("parent of imported unpackaged plug-ins")
|
|
33
|
-
|
|
34
|
-
__pluginInfo__ = {
|
|
35
|
-
'name': 'Import Test Unpackaged Parent',
|
|
36
|
-
'version': '0.9',
|
|
37
|
-
'description': "This is a imports-containing unpackaged parent plugin.",
|
|
38
|
-
'license': 'Apache-2',
|
|
39
|
-
'author': authorLabel,
|
|
40
|
-
'copyright': copyrightLabel,
|
|
41
|
-
# classes of mount points (required)
|
|
42
|
-
'CntlrWinMain.Menu.Tools': parentMenuEntender,
|
|
43
|
-
'CntlrCmdLine.Options': parentCommandLineOptionExtender,
|
|
44
|
-
'CntlrCmdLine.Utility.Run': parentCommandLineUtilityRun,
|
|
45
|
-
'Import.Unpackaged.Entry1': foo,
|
|
46
|
-
# imported plugins
|
|
47
|
-
'import': ('importTestChild1.py', 'importTestChild2.py', "module_import_subtree")
|
|
48
|
-
}
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
instanceInfo.py provides information about an XBRL instance
|
|
3
|
-
|
|
4
|
-
See COPYRIGHT.md for copyright information.
|
|
5
|
-
|
|
6
|
-
Operation with arelleCmdLine: --plugin instanceInfo -f entryUrl
|
|
7
|
-
|
|
8
|
-
'''
|
|
9
|
-
import sys, os, time, math, logging
|
|
10
|
-
import regex as re
|
|
11
|
-
from math import isnan
|
|
12
|
-
from collections import defaultdict
|
|
13
|
-
from arelle.ValidateXbrlCalcs import inferredDecimals, rangeValue
|
|
14
|
-
from arelle import ModelDocument
|
|
15
|
-
from arelle.ModelInstanceObject import ModelFact
|
|
16
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
17
|
-
from arelle.XbrlConst import xhtml
|
|
18
|
-
from arelle.XmlUtil import ancestors, xmlstring
|
|
19
|
-
|
|
20
|
-
memoryAtStartup = 0
|
|
21
|
-
timeAtStart = 0
|
|
22
|
-
styleIxHiddenPattern = re.compile(r"(.*[^\w]|^)-(sec|esef)-ix-hidden\s*:\s*([\w.-]+).*")
|
|
23
|
-
|
|
24
|
-
def startup(cntlr, options, *args, **kwargs):
|
|
25
|
-
global memoryAtStartup, timeAtStart
|
|
26
|
-
memoryAtStartup = cntlr.memoryUsed
|
|
27
|
-
timeAtStart = time.time()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def showInfo(cntlr, options, modelXbrl, _entrypoint, *args, **kwargs):
|
|
32
|
-
for url, doc in sorted(modelXbrl.urlDocs.items(), key=lambda i: i[0]):
|
|
33
|
-
if not any(url.startswith(w) for w in ("https://xbrl.sec.gov/", "http://xbrl.sec.gov/", "http://xbrl.fasb.org/", "http://www.xbrl.org/",
|
|
34
|
-
"http://xbrl.ifrs.org/", "http://www.esma.europa.eu/")):
|
|
35
|
-
if os.path.exists(doc.filepath): # skip if in an archive or stream
|
|
36
|
-
cntlr.addToLog("File {} size {:,}".format(doc.basename, os.path.getsize(doc.filepath)), messageCode="info", level=logging.DEBUG)
|
|
37
|
-
cntlr.addToLog("Heap memory before loading {:,}".format(memoryAtStartup), messageCode="info", level=logging.DEBUG)
|
|
38
|
-
cntlr.addToLog("Heap memory after loading {:,}".format(cntlr.memoryUsed), messageCode="info", level=logging.DEBUG)
|
|
39
|
-
cntlr.addToLog("Time to load {:.2f} seconds".format(time.time() - timeAtStart), messageCode="info", level=logging.DEBUG)
|
|
40
|
-
isInlineXbrl = modelXbrl.modelDocument.type in (ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INLINEXBRLDOCUMENTSET)
|
|
41
|
-
if isInlineXbrl:
|
|
42
|
-
instanceType = "inline XBRL, number of documents {}".format(len(modelXbrl.ixdsHtmlElements))
|
|
43
|
-
else:
|
|
44
|
-
instanceType = "xBRL-XML"
|
|
45
|
-
cntlr.addToLog("Instance type {}".format(instanceType), messageCode="info", level=logging.DEBUG)
|
|
46
|
-
numContexts = len(modelXbrl.contexts)
|
|
47
|
-
numLongContexts = 0
|
|
48
|
-
bytesSaveableInline = 0
|
|
49
|
-
bytesSaveableInlineWithCsv = 0
|
|
50
|
-
frequencyOfDims = {}
|
|
51
|
-
sumNumDims = 0
|
|
52
|
-
distinctDurations = set()
|
|
53
|
-
distinctInstants = set()
|
|
54
|
-
shortContextIdLen = int(math.log10(numContexts or 1)) + 2 # if no contexts, use 1 for log function to work
|
|
55
|
-
xbrlQnameCountInline = 0
|
|
56
|
-
xbrlQnameCountInlineWithCsv = 0
|
|
57
|
-
xbrlQnameLengthsInline = 0
|
|
58
|
-
xbrlQnameLengthsInlineWithCsv = 0
|
|
59
|
-
for c in modelXbrl.contexts.values():
|
|
60
|
-
sumNumDims += len(c.qnameDims)
|
|
61
|
-
for d in c.qnameDims.values():
|
|
62
|
-
dimQname = str(d.dimensionQname)
|
|
63
|
-
frequencyOfDims[dimQname] = frequencyOfDims.get(dimQname,0) + 1
|
|
64
|
-
xbrlQnameCountInline += 1
|
|
65
|
-
xbrlQnameCountInlineWithCsv += 1
|
|
66
|
-
xbrlQnameLengthsInline += len(d.dimensionQname.localName)
|
|
67
|
-
xbrlQnameLengthsInlineWithCsv += len(d.dimensionQname.localName)
|
|
68
|
-
if c.isInstantPeriod:
|
|
69
|
-
distinctInstants.add(c.instantDatetime)
|
|
70
|
-
elif c.isStartEndPeriod:
|
|
71
|
-
distinctDurations.add((c.startDatetime, c.endDatetime))
|
|
72
|
-
if len(c.id) > shortContextIdLen:
|
|
73
|
-
bytesSaveableInline += len(c.id) - shortContextIdLen
|
|
74
|
-
bytesSaveableInlineWithCsv += len(c.id) - shortContextIdLen
|
|
75
|
-
cntlr.addToLog("Number of contexts {:,}".format(numContexts), messageCode="info", level=logging.DEBUG)
|
|
76
|
-
cntlr.addToLog("Number of distinct durations {:,}".format(len(distinctDurations)), messageCode="info", level=logging.DEBUG)
|
|
77
|
-
cntlr.addToLog("Number of distinct instants {:,}".format(len(distinctInstants)), messageCode="info", level=logging.DEBUG)
|
|
78
|
-
cntlr.addToLog("Avg number dimensions per contexts {:,.2f}".format(sumNumDims/numContexts if numContexts else 0), messageCode="info", level=logging.DEBUG)
|
|
79
|
-
mostPopularDims = sorted(frequencyOfDims.items(), key=lambda i:"{:0>9},{}".format(999999999-i[1],i[0]))
|
|
80
|
-
for dimName, count in mostPopularDims[0:3]:
|
|
81
|
-
cntlr.addToLog("Dimension {} used in {:,} contexts".format(dimName, count), messageCode="info", level=logging.DEBUG)
|
|
82
|
-
|
|
83
|
-
# analyze for tables which could be composed from CSV data
|
|
84
|
-
tblFacts = defaultdict(set)
|
|
85
|
-
tblNestedTables = defaultdict(set)
|
|
86
|
-
factSize = {}
|
|
87
|
-
for f in modelXbrl.factsInInstance:
|
|
88
|
-
for tdElt in ancestors(f, xhtml, "td"):
|
|
89
|
-
factSize[f] = len(xmlstring(tdElt,stripXmlns=True))
|
|
90
|
-
break
|
|
91
|
-
childTblElt = None
|
|
92
|
-
for tblElt in ancestors(f, xhtml, "table"):
|
|
93
|
-
tblFacts[tblElt].add(f)
|
|
94
|
-
if childTblElt:
|
|
95
|
-
tblNestedTables[tblElt].add(childTblElt)
|
|
96
|
-
|
|
97
|
-
# find tables containing only numeric facts
|
|
98
|
-
def tblNestedFactCount(tbl):
|
|
99
|
-
c = len(tblFacts.get(tbl, ()))
|
|
100
|
-
for nestedTbl in tblNestedTables.get(tbl,()):
|
|
101
|
-
c += tblNestedFactCount(nestedTbl)
|
|
102
|
-
return c
|
|
103
|
-
|
|
104
|
-
factsInInstance = len(modelXbrl.factsInInstance)
|
|
105
|
-
factsInTables = len(set.union(*(fset for fset in tblFacts.values())))
|
|
106
|
-
cntlr.addToLog("Facts in instance: {:,}, facts in tables: {:,}".format(factsInInstance,factsInTables), messageCode="info", level=logging.DEBUG)
|
|
107
|
-
|
|
108
|
-
numTblsEligible = 0
|
|
109
|
-
numFactsEligible = 0
|
|
110
|
-
bytesCsvSavings = 0
|
|
111
|
-
factsEligibleForCsv = set()
|
|
112
|
-
tablesWithEligibleFacts = set()
|
|
113
|
-
if tblFacts and factSize:
|
|
114
|
-
# find eligible tables, have facts and not nested tables with other facts
|
|
115
|
-
for tbl, facts in tblFacts.items():
|
|
116
|
-
if len(facts) == tblNestedFactCount(tbl):
|
|
117
|
-
s = sum(factSize.get(f,0) for f in facts) - sum(len(str(f.value)) for f in facts)
|
|
118
|
-
if s > 10000:
|
|
119
|
-
numTblsEligible += 1
|
|
120
|
-
bytesCsvSavings += s
|
|
121
|
-
numFactsEligible += len(facts)
|
|
122
|
-
factsEligibleForCsv |= facts
|
|
123
|
-
tablesWithEligibleFacts.add(tbl)
|
|
124
|
-
numFacts = 0
|
|
125
|
-
numTableTextBlockFacts = 0
|
|
126
|
-
lenTableTextBlockFacts = 0
|
|
127
|
-
numTextBlockFacts = 0
|
|
128
|
-
lenTextBlockFacts = 0
|
|
129
|
-
distinctElementsInFacts = set()
|
|
130
|
-
factsPerContext = {}
|
|
131
|
-
factForConceptContextUnitHash = defaultdict(list)
|
|
132
|
-
for f in modelXbrl.factsInInstance:
|
|
133
|
-
context = f.context
|
|
134
|
-
concept = f.concept
|
|
135
|
-
distinctElementsInFacts.add(f.qname)
|
|
136
|
-
numFacts += 1
|
|
137
|
-
if f.qname.localName.endswith("TableTextBlock"):
|
|
138
|
-
numTableTextBlockFacts += 1
|
|
139
|
-
lenTableTextBlockFacts += len(f.xValue)
|
|
140
|
-
elif f.qname.localName.endswith("TextBlock"):
|
|
141
|
-
numTextBlockFacts += 1
|
|
142
|
-
lenTextBlockFacts += len(f.xValue)
|
|
143
|
-
if context is not None and concept is not None:
|
|
144
|
-
factsPerContext[context.id] = factsPerContext.get(context.id,0) + 1
|
|
145
|
-
factForConceptContextUnitHash[f.conceptContextUnitHash].append(f)
|
|
146
|
-
bytesSaveableInline += len(context.id) - shortContextIdLen
|
|
147
|
-
if f not in factsEligibleForCsv:
|
|
148
|
-
bytesSaveableInlineWithCsv += len(context.id) - shortContextIdLen
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if numTblsEligible:
|
|
152
|
-
cntlr.addToLog("Tables eligible for facts in CSV: {:,}, facts eligible for CSV: {:,}, bytes saveable by facts in CSV {:,}".format(numTblsEligible, numFactsEligible, bytesCsvSavings), messageCode="info", level=logging.DEBUG)
|
|
153
|
-
else:
|
|
154
|
-
cntlr.addToLog("No tables eligible for facts in CSV", messageCode="info", level=logging.DEBUG)
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
mostPopularContexts = sorted(factsPerContext.items(), key=lambda i:"{:0>9},{}".format(999999999-i[1],i[0]))
|
|
158
|
-
cntlr.addToLog("Number of facts {:,}".format(numFacts), messageCode="info", level=logging.DEBUG)
|
|
159
|
-
cntlr.addToLog("Number of TableTextBlock facts {:,} avg len {:,.0f}".format(numTableTextBlockFacts, lenTableTextBlockFacts/numTableTextBlockFacts if numTableTextBlockFacts else 0), messageCode="info", level=logging.DEBUG)
|
|
160
|
-
cntlr.addToLog("Number of TextBlock facts {:,} avg len {:,.0f}".format(numTextBlockFacts, lenTextBlockFacts/numTableTextBlockFacts if numTableTextBlockFacts else 0), messageCode="info", level=logging.DEBUG)
|
|
161
|
-
cntlr.addToLog("Max number facts per context {:,}".format(mostPopularContexts[0][1] if mostPopularContexts else 0), messageCode="info", level=logging.DEBUG)
|
|
162
|
-
cntlr.addToLog("Avg number facts per context {:,.2f}".format(sum([v for v in factsPerContext.values()])/numContexts if numContexts else 0), messageCode="info", level=logging.DEBUG)
|
|
163
|
-
cntlr.addToLog("Distinct elements in facts {:,}".format(len(distinctElementsInFacts)), messageCode="info", level=logging.DEBUG)
|
|
164
|
-
cntlr.addToLog("Number of bytes saveable context id of {} length is {:,}".format(shortContextIdLen, bytesSaveableInline), messageCode="info", level=logging.DEBUG)
|
|
165
|
-
cntlr.addToLog("Excepting facts eligible for CSV, number of bytes saveable context id of {} length is {:,}".format(shortContextIdLen, bytesSaveableInlineWithCsv), messageCode="info", level=logging.DEBUG)
|
|
166
|
-
|
|
167
|
-
aspectEqualFacts = defaultdict(list)
|
|
168
|
-
decVals = {}
|
|
169
|
-
numConsistentDupFacts = numInConsistentDupFacts = 0
|
|
170
|
-
for hashEquivalentFacts in factForConceptContextUnitHash.values():
|
|
171
|
-
if len(hashEquivalentFacts) > 1:
|
|
172
|
-
for f in hashEquivalentFacts:
|
|
173
|
-
aspectEqualFacts[(f.qname,f.contextID,f.unitID,
|
|
174
|
-
f.xmlLang.lower() if f.concept.type.isWgnStringFactType else None)].append(f)
|
|
175
|
-
for fList in aspectEqualFacts.values():
|
|
176
|
-
f0 = fList[0]
|
|
177
|
-
if f0.concept.isNumeric:
|
|
178
|
-
if any(f.isNil for f in fList):
|
|
179
|
-
_inConsistent = not all(f.isNil for f in fList)
|
|
180
|
-
else: # not all have same decimals
|
|
181
|
-
_d = inferredDecimals(f0)
|
|
182
|
-
_v = f0.xValue
|
|
183
|
-
_inConsistent = isnan(_v) # NaN is incomparable, always makes dups inconsistent
|
|
184
|
-
decVals[_d] = _v
|
|
185
|
-
aMax, bMin, _inclA, _inclB = rangeValue(_v, _d)
|
|
186
|
-
for f in fList[1:]:
|
|
187
|
-
_d = inferredDecimals(f)
|
|
188
|
-
_v = f.xValue
|
|
189
|
-
if isnan(_v):
|
|
190
|
-
_inConsistent = True
|
|
191
|
-
break
|
|
192
|
-
if _d in decVals:
|
|
193
|
-
_inConsistent |= _v != decVals[_d]
|
|
194
|
-
else:
|
|
195
|
-
decVals[_d] = _v
|
|
196
|
-
a, b, _inclA, _inclB = rangeValue(_v, _d)
|
|
197
|
-
if a > aMax: aMax = a
|
|
198
|
-
if b < bMin: bMin = b
|
|
199
|
-
if not _inConsistent:
|
|
200
|
-
_inConsistent = (bMin < aMax)
|
|
201
|
-
decVals.clear()
|
|
202
|
-
else:
|
|
203
|
-
_inConsistent = any(not f.isVEqualTo(f0) for f in fList[1:])
|
|
204
|
-
if _inConsistent:
|
|
205
|
-
numInConsistentDupFacts += 1
|
|
206
|
-
else:
|
|
207
|
-
numConsistentDupFacts += 1
|
|
208
|
-
|
|
209
|
-
aspectEqualFacts.clear()
|
|
210
|
-
cntlr.addToLog("Number of duplicate facts consistent {:,} inconsistent {:,}".format(numConsistentDupFacts, numInConsistentDupFacts), messageCode="info", level=logging.DEBUG)
|
|
211
|
-
|
|
212
|
-
styleAttrCountsInline = {}
|
|
213
|
-
styleAttrCountsInlineWithCsv = {}
|
|
214
|
-
totalStyleLenInline = 0
|
|
215
|
-
totalStyleLenInlineWithCsv = 0
|
|
216
|
-
continuationElements = {}
|
|
217
|
-
ixNsPrefix = "{http://www.xbrl.org/2013/inlineXBRL}"
|
|
218
|
-
for ixdsHtmlRootElt in getattr(modelXbrl, "ixdsHtmlElements", ()): # ix root elements if inline
|
|
219
|
-
for ixElt in ixdsHtmlRootElt.iterdescendants():
|
|
220
|
-
inEligibleTableForCsv = any(p in tablesWithEligibleFacts for p in ixElt.iterancestors("{http://www.w3.org/1999/xhtml}table"))
|
|
221
|
-
style = ixElt.get("style")
|
|
222
|
-
ixEltTag = str(ixElt.tag)
|
|
223
|
-
if style:
|
|
224
|
-
styleAttrCountsInline[style] = styleAttrCountsInline.get(style,0) + 1
|
|
225
|
-
if not inEligibleTableForCsv:
|
|
226
|
-
styleAttrCountsInlineWithCsv[style] = styleAttrCountsInlineWithCsv.get(style,0) + 1
|
|
227
|
-
if styleIxHiddenPattern.match(style) is None:
|
|
228
|
-
totalStyleLenInline += len(style)
|
|
229
|
-
if not inEligibleTableForCsv:
|
|
230
|
-
totalStyleLenInlineWithCsv += len(style)
|
|
231
|
-
if ixEltTag == "{http://www.xbrl.org/2013/inlineXBRL}continuation" and ixElt.id:
|
|
232
|
-
continuationElements[ixElt.id] = ixElt
|
|
233
|
-
if ixEltTag.startswith(ixNsPrefix):
|
|
234
|
-
localName = ixEltTag[len(ixNsPrefix):]
|
|
235
|
-
if localName == "continuation" and ixElt.id:
|
|
236
|
-
continuationElements[ixElt.id] = ixElt
|
|
237
|
-
elif localName in ("nonFraction", "nonNumeric", "fraction"):
|
|
238
|
-
xbrlQnameCountInline += 1
|
|
239
|
-
xbrlQnameLengthsInline += len(ixElt.qname.localName)
|
|
240
|
-
if not inEligibleTableForCsv:
|
|
241
|
-
xbrlQnameCountInlineWithCsv += 1
|
|
242
|
-
xbrlQnameLengthsInlineWithCsv += len(ixElt.qname.localName)
|
|
243
|
-
elif isinstance(ixElt, ModelFact):
|
|
244
|
-
xbrlQnameCountInline += 2
|
|
245
|
-
xbrlQnameLengthsInline += len(ixElt.qname.localName)
|
|
246
|
-
if not inEligibleTableForCsv:
|
|
247
|
-
xbrlQnameCountInlineWithCsv += 2
|
|
248
|
-
xbrlQnameLengthsInlineWithCsv += len(ixElt.qname.localName)
|
|
249
|
-
|
|
250
|
-
def locateContinuation(element, chain=None):
|
|
251
|
-
contAt = element.get("continuedAt")
|
|
252
|
-
if contAt:
|
|
253
|
-
if contAt in continuationElements:
|
|
254
|
-
if chain is None: chain = [element]
|
|
255
|
-
contElt = continuationElements[contAt]
|
|
256
|
-
if contElt not in chain:
|
|
257
|
-
chain.append(contElt)
|
|
258
|
-
element._continuationElement = contElt
|
|
259
|
-
return locateContinuation(contElt, chain)
|
|
260
|
-
elif chain: # end of chain
|
|
261
|
-
return len(chain)
|
|
262
|
-
|
|
263
|
-
numContinuations = 0
|
|
264
|
-
maxLenLen = 0
|
|
265
|
-
maxLenHops = 0
|
|
266
|
-
maxHops = 0
|
|
267
|
-
maxHopsLen = 0
|
|
268
|
-
for f in modelXbrl.factsInInstance:
|
|
269
|
-
if f.get("continuedAt"):
|
|
270
|
-
numContinuations += 1
|
|
271
|
-
_len = len(f.xValue)
|
|
272
|
-
_hops = locateContinuation(f)
|
|
273
|
-
if _hops > maxHops:
|
|
274
|
-
maxHops = _hops
|
|
275
|
-
maxHopsLen = _len
|
|
276
|
-
if _len > maxLenLen:
|
|
277
|
-
maxLenLen = _len
|
|
278
|
-
maxLenHops = _hops
|
|
279
|
-
|
|
280
|
-
cntlr.addToLog("Number of continuation facts {:,}".format(numContinuations), messageCode="info", level=logging.DEBUG)
|
|
281
|
-
cntlr.addToLog("Longest continuation fact {:,} number of hops {:,}".format(maxLenLen, maxLenHops), messageCode="info", level=logging.DEBUG)
|
|
282
|
-
cntlr.addToLog("Most continuation hops {:,} fact len {:,}".format(maxHops, maxHopsLen), messageCode="info", level=logging.DEBUG)
|
|
283
|
-
|
|
284
|
-
numDupStyles = sum(1 for n in styleAttrCountsInline.values() if n > 1)
|
|
285
|
-
bytesSaveableByCssInline = sum(len(s)*(n-1) for s,n in styleAttrCountsInline.items() if n > 1)
|
|
286
|
-
cntlr.addToLog("Number of duplicate styles {:,}, bytes saveable by CSS {:,}, len of all non-ix-hidden @styles {:,}".format(numDupStyles, bytesSaveableByCssInline, totalStyleLenInline), messageCode="info", level=logging.DEBUG)
|
|
287
|
-
cntlr.addToLog("Number of XBRL QNames {:,}, bytes saveable by EBA-style element names {:,}".format(xbrlQnameCountInline, xbrlQnameLengthsInline - (5*xbrlQnameCountInline)), messageCode="info", level=logging.DEBUG)
|
|
288
|
-
numDupStyles = sum(1 for n in styleAttrCountsInlineWithCsv.values() if n > 1)
|
|
289
|
-
bytesSaveableByCssInlineWithCsv = sum(len(s)*(n-1) for s,n in styleAttrCountsInlineWithCsv.items() if n > 1)
|
|
290
|
-
cntlr.addToLog("Excepting facts eligible for CSV, number of duplicate styles {:,}, bytes saveable by CSS {:,}, len of all non-ix-hidden @styles {:,}".format(numDupStyles, bytesSaveableByCssInlineWithCsv, totalStyleLenInlineWithCsv), messageCode="info", level=logging.DEBUG)
|
|
291
|
-
cntlr.addToLog("Excepting facts eligible for CSV, number of XBRL QNames {:,}, bytes saveable by EBA-style element names {:,}".format(xbrlQnameCountInlineWithCsv, xbrlQnameLengthsInlineWithCsv - (5*xbrlQnameCountInlineWithCsv)), messageCode="info", level=logging.DEBUG)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
__pluginInfo__ = {
|
|
296
|
-
'name': 'Instance Info',
|
|
297
|
-
'version': '1.0',
|
|
298
|
-
'description': "This plug-in displays instance information for sizing and performance issues.",
|
|
299
|
-
'license': 'Apache-2',
|
|
300
|
-
'author': authorLabel,
|
|
301
|
-
'copyright': copyrightLabel,
|
|
302
|
-
'import': ('inlineXbrlDocumentSet',),
|
|
303
|
-
# classes of mount points (required)
|
|
304
|
-
'CntlrCmdLine.Filing.Start': startup,
|
|
305
|
-
'CntlrCmdLine.Xbrl.Loaded': showInfo
|
|
306
|
-
}
|