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,570 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
See COPYRIGHT.md for copyright information.
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
# changed from reporting locs to reporting relationships: HF 2020-06-23
|
|
6
|
-
|
|
7
|
-
from arelle import PluginManager
|
|
8
|
-
from arelle.ModelDtsObject import ModelConcept
|
|
9
|
-
from arelle.ModelValue import qname
|
|
10
|
-
from arelle.Version import copyrightLabel
|
|
11
|
-
from arelle.XmlValidate import UNVALIDATED, VALID
|
|
12
|
-
from arelle import Locale, ModelXbrl, XbrlConst
|
|
13
|
-
from arelle.FileSource import openFileSource, openFileStream, saveFile
|
|
14
|
-
import os, io, json, time
|
|
15
|
-
import regex as re
|
|
16
|
-
from math import isfinite
|
|
17
|
-
from collections import defaultdict
|
|
18
|
-
|
|
19
|
-
# ((year, ugtNamespace, ugtDocLB, ugtEntryPoint) ...)
|
|
20
|
-
ugtDocs = ({"year": 2012,
|
|
21
|
-
"name": "us-gaap",
|
|
22
|
-
"namespace": "http://fasb.org/us-gaap/2012-01-31",
|
|
23
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2012/us-gaap-2012-01-31.zip/us-gaap-2012-01-31/elts/us-gaap-doc-2012-01-31.xml",
|
|
24
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2012/us-gaap-2012-01-31.zip/us-gaap-2012-01-31/entire/us-gaap-entryPoint-std-2012-01-31.xsd",
|
|
25
|
-
},
|
|
26
|
-
{"year": 2013,
|
|
27
|
-
"name": "us-gaap",
|
|
28
|
-
"namespace": "http://fasb.org/us-gaap/2013-01-31",
|
|
29
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2013/us-gaap-2013-01-31.zip/us-gaap-2013-01-31/elts/us-gaap-doc-2013-01-31.xml",
|
|
30
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2013/us-gaap-2013-01-31.zip/us-gaap-2013-01-31/entire/us-gaap-entryPoint-std-2013-01-31.xsd",
|
|
31
|
-
},
|
|
32
|
-
{"year": 2014,
|
|
33
|
-
"name": "us-gaap",
|
|
34
|
-
"namespace": "http://fasb.org/us-gaap/2014-01-31",
|
|
35
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2014/us-gaap-2014-01-31.zip/us-gaap-2014-01-31/elts/us-gaap-doc-2014-01-31.xml",
|
|
36
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2014/us-gaap-2014-01-31.zip/us-gaap-2014-01-31/entire/us-gaap-entryPoint-std-2014-01-31.xsd",
|
|
37
|
-
},
|
|
38
|
-
{"year": 2015,
|
|
39
|
-
"name": "us-gaap",
|
|
40
|
-
"namespace": "http://fasb.org/us-gaap/2015-01-31",
|
|
41
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2015/us-gaap-2015-01-31.zip/us-gaap-2015-01-31/elts/us-gaap-doc-2015-01-31.xml",
|
|
42
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2015/us-gaap-2015-01-31.zip/us-gaap-2015-01-31/entire/us-gaap-entryPoint-std-2015-01-31.xsd",
|
|
43
|
-
},
|
|
44
|
-
{"year": 2016,
|
|
45
|
-
"name": "us-gaap",
|
|
46
|
-
"namespace": "http://fasb.org/us-gaap/2016-01-31",
|
|
47
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2016/us-gaap-2016-01-31.zip/us-gaap-2016-01-31/elts/us-gaap-doc-2016-01-31.xml",
|
|
48
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2016/us-gaap-2016-01-31.zip/us-gaap-2016-01-31/entire/us-gaap-entryPoint-std-2016-01-31.xsd",
|
|
49
|
-
},
|
|
50
|
-
{"year": 2017,
|
|
51
|
-
"namespace": "http://fasb.org/us-gaap/2017-01-31",
|
|
52
|
-
"name": "us-gaap",
|
|
53
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2017/us-gaap-2017-01-31.zip/us-gaap-2017-01-31/elts/us-gaap-doc-2017-01-31.xml",
|
|
54
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2017/us-gaap-2017-01-31.zip/us-gaap-2017-01-31/entire/us-gaap-entryPoint-std-2017-01-31.xsd",
|
|
55
|
-
},
|
|
56
|
-
{"year": 2018,
|
|
57
|
-
"name": "us-gaap",
|
|
58
|
-
"namespace": "http://fasb.org/us-gaap/2018-01-31",
|
|
59
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2018/us-gaap-2018-01-31.zip/us-gaap-2018-01-31/elts/us-gaap-doc-2018-01-31.xml",
|
|
60
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2018/us-gaap-2018-01-31.zip/us-gaap-2018-01-31/entire/us-gaap-entryPoint-std-2018-01-31.xsd",
|
|
61
|
-
},
|
|
62
|
-
{"year": 2018,
|
|
63
|
-
"name": "srt",
|
|
64
|
-
"namespace": "http://fasb.org/srt/2018-01-31",
|
|
65
|
-
"docLB": "http://xbrl.fasb.org/srt/2018/srt-2018-01-31.zip/srt-2018-01-31/elts/srt-doc-2018-01-31.xml",
|
|
66
|
-
"entryXsd": "http://xbrl.fasb.org/srt/2018/srt-2018-01-31.zip/srt-2018-01-31/entire/srt-entryPoint-std-2018-01-31.xsd",
|
|
67
|
-
},
|
|
68
|
-
{"year": 2019,
|
|
69
|
-
"name": "us-gaap",
|
|
70
|
-
"namespace": "http://fasb.org/us-gaap/2019-01-31",
|
|
71
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2019/us-gaap-2019-01-31.zip/us-gaap-2019-01-31/elts/us-gaap-doc-2019-01-31.xml",
|
|
72
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2019/us-gaap-2019-01-31.zip/us-gaap-2019-01-31/entire/us-gaap-entryPoint-std-2019-01-31.xsd",
|
|
73
|
-
},
|
|
74
|
-
{"year": 2019,
|
|
75
|
-
"name": "srt",
|
|
76
|
-
"namespace": "http://fasb.org/srt/2019-01-31",
|
|
77
|
-
"docLB": "http://xbrl.fasb.org/srt/2019/srt-2019-01-31.zip/srt-2019-01-31/elts/srt-doc-2019-01-31.xml",
|
|
78
|
-
"entryXsd": "http://xbrl.fasb.org/srt/2019/srt-2019-01-31.zip/srt-2019-01-31/entire/srt-entryPoint-std-2019-01-31.xsd",
|
|
79
|
-
},
|
|
80
|
-
{"year": 2020,
|
|
81
|
-
"name": "us-gaap",
|
|
82
|
-
"namespace": "http://fasb.org/us-gaap/2020-01-31",
|
|
83
|
-
"docLB": "http://xbrl.fasb.org/us-gaap/2020/us-gaap-2020-01-31.zip/us-gaap-2020-01-31/elts/us-gaap-doc-2020-01-31.xml",
|
|
84
|
-
"entryXsd": "http://xbrl.fasb.org/us-gaap/2020/us-gaap-2020-01-31.zip/us-gaap-2020-01-31/entire/us-gaap-entryPoint-std-2020-01-31.xsd",
|
|
85
|
-
},
|
|
86
|
-
{"year": 2020,
|
|
87
|
-
"name": "srt",
|
|
88
|
-
"namespace": "http://fasb.org/srt/2020-01-31",
|
|
89
|
-
"docLB": "http://xbrl.fasb.org/srt/2020/srt-2020-01-31.zip/srt-2020-01-31/elts/srt-doc-2020-01-31.xml",
|
|
90
|
-
"entryXsd": "http://xbrl.fasb.org/srt/2020/srt-2020-01-31.zip/srt-2020-01-31/entire/srt-entryPoint-std-2020-01-31.xsd",
|
|
91
|
-
},
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
def setup(val, *args, **kwargs):
|
|
95
|
-
if not val.validateLoggingSemantic: # all checks herein are SEMANTIC
|
|
96
|
-
return
|
|
97
|
-
|
|
98
|
-
val.linroleDefinitionIsDisclosure = re.compile(r"-\s+Disclosure\s+-\s",
|
|
99
|
-
re.IGNORECASE)
|
|
100
|
-
val.linkroleDefinitionStatementSheet = re.compile(r"[^-]+-\s+Statement\s+-\s+.*", # no restriction to type of statement
|
|
101
|
-
re.IGNORECASE)
|
|
102
|
-
val.ugtNamespace = None
|
|
103
|
-
cntlr = val.modelXbrl.modelManager.cntlr
|
|
104
|
-
# load deprecated concepts for filed year of us-gaap
|
|
105
|
-
for ugt in ugtDocs:
|
|
106
|
-
ugtNamespace = ugt["namespace"]
|
|
107
|
-
if ugtNamespace in val.modelXbrl.namespaceDocs and len(val.modelXbrl.namespaceDocs[ugtNamespace]) > 0:
|
|
108
|
-
val.ugtNamespace = ugtNamespace
|
|
109
|
-
usgaapDoc = val.modelXbrl.namespaceDocs[ugtNamespace][0]
|
|
110
|
-
deprecationsJsonFile = usgaapDoc.filepathdir + os.sep + "deprecated-concepts.json"
|
|
111
|
-
file = None
|
|
112
|
-
try:
|
|
113
|
-
file = openFileStream(cntlr, deprecationsJsonFile, 'rt', encoding='utf-8')
|
|
114
|
-
val.usgaapDeprecations = json.load(file)
|
|
115
|
-
file.close()
|
|
116
|
-
except Exception:
|
|
117
|
-
if file:
|
|
118
|
-
file.close()
|
|
119
|
-
val.modelXbrl.modelManager.addToLog(_("loading {} {} deprecated concepts into cache").format(ugt["name"], ugt["year"]))
|
|
120
|
-
startedAt = time.time()
|
|
121
|
-
ugtDocLB = ugt["docLB"]
|
|
122
|
-
val.usgaapDeprecations = {}
|
|
123
|
-
# load without SEC/EFM validation (doc file would not be acceptable)
|
|
124
|
-
priorValidateDisclosureSystem = val.modelXbrl.modelManager.validateDisclosureSystem
|
|
125
|
-
val.modelXbrl.modelManager.validateDisclosureSystem = False
|
|
126
|
-
deprecationsInstance = ModelXbrl.load(val.modelXbrl.modelManager,
|
|
127
|
-
# "http://xbrl.fasb.org/us-gaap/2012/elts/us-gaap-doc-2012-01-31.xml",
|
|
128
|
-
# load from zip (especially after caching) is incredibly faster
|
|
129
|
-
openFileSource(ugtDocLB, cntlr),
|
|
130
|
-
_("built deprecations table in cache"))
|
|
131
|
-
val.modelXbrl.modelManager.validateDisclosureSystem = priorValidateDisclosureSystem
|
|
132
|
-
if deprecationsInstance is None:
|
|
133
|
-
val.modelXbrl.error("arelle:notLoaded",
|
|
134
|
-
_("%(name)s documentation not loaded: %(file)s"),
|
|
135
|
-
modelXbrl=val, file=os.path.basename(ugtDocLB), name=ugt["name"])
|
|
136
|
-
else:
|
|
137
|
-
# load deprecations
|
|
138
|
-
for labelRel in deprecationsInstance.relationshipSet(XbrlConst.conceptLabel).modelRelationships:
|
|
139
|
-
modelDocumentation = labelRel.toModelObject
|
|
140
|
-
conceptName = labelRel.fromModelObject.name
|
|
141
|
-
if modelDocumentation.role == 'http://www.xbrl.org/2009/role/deprecatedLabel':
|
|
142
|
-
val.usgaapDeprecations[conceptName] = (val.usgaapDeprecations.get(conceptName, ('',''))[0], modelDocumentation.text)
|
|
143
|
-
elif modelDocumentation.role == 'http://www.xbrl.org/2009/role/deprecatedDateLabel':
|
|
144
|
-
val.usgaapDeprecations[conceptName] = (modelDocumentation.text, val.usgaapDeprecations.get(conceptName, ('',''))[1])
|
|
145
|
-
jsonStr = str(json.dumps(val.usgaapDeprecations, ensure_ascii=False, indent=0)) # might not be unicode in 2.7
|
|
146
|
-
saveFile(cntlr, deprecationsJsonFile, jsonStr) # 2.7 gets unicode this way
|
|
147
|
-
deprecationsInstance.close()
|
|
148
|
-
del deprecationsInstance # dereference closed modelXbrl
|
|
149
|
-
val.modelXbrl.profileStat(_("build us-gaap deprecated concepts cache"), time.time() - startedAt)
|
|
150
|
-
ugtCalcsJsonFile = usgaapDoc.filepathdir + os.sep + "ugt-calculations.json"
|
|
151
|
-
ugtDefaultDimensionsJsonFile = usgaapDoc.filepathdir + os.sep + "ugt-default-dimensions.json"
|
|
152
|
-
file = None
|
|
153
|
-
try:
|
|
154
|
-
file = openFileStream(cntlr, ugtCalcsJsonFile, 'rt', encoding='utf-8')
|
|
155
|
-
val.usgaapCalculations = json.load(file)
|
|
156
|
-
file.close()
|
|
157
|
-
file = openFileStream(cntlr, ugtDefaultDimensionsJsonFile, 'rt', encoding='utf-8')
|
|
158
|
-
val.usgaapDefaultDimensions = json.load(file)
|
|
159
|
-
file.close()
|
|
160
|
-
except Exception:
|
|
161
|
-
if file:
|
|
162
|
-
file.close()
|
|
163
|
-
val.modelXbrl.modelManager.addToLog(_("loading {} {} calculations and default dimensions into cache").format(ugt["name"], ugt["year"]))
|
|
164
|
-
startedAt = time.time()
|
|
165
|
-
ugtEntryXsd = ugt["entryXsd"]
|
|
166
|
-
val.usgaapCalculations = {}
|
|
167
|
-
val.usgaapDefaultDimensions = {}
|
|
168
|
-
# load without SEC/EFM validation (doc file would not be acceptable)
|
|
169
|
-
priorValidateDisclosureSystem = val.modelXbrl.modelManager.validateDisclosureSystem
|
|
170
|
-
val.modelXbrl.modelManager.validateDisclosureSystem = False
|
|
171
|
-
calculationsInstance = ModelXbrl.load(val.modelXbrl.modelManager,
|
|
172
|
-
# "http://xbrl.fasb.org/us-gaap/2012/entire/us-gaap-entryPoint-std-2012-01-31.xsd",
|
|
173
|
-
# load from zip (especially after caching) is incredibly faster
|
|
174
|
-
openFileSource(ugtEntryXsd, cntlr),
|
|
175
|
-
_("built us-gaap calculations cache"))
|
|
176
|
-
val.modelXbrl.modelManager.validateDisclosureSystem = priorValidateDisclosureSystem
|
|
177
|
-
if calculationsInstance is None:
|
|
178
|
-
val.modelXbrl.error("arelle:notLoaded",
|
|
179
|
-
_("US-GAAP calculations not loaded: %(file)s"),
|
|
180
|
-
modelXbrl=val, file=os.path.basename(ugtEntryXsd))
|
|
181
|
-
else:
|
|
182
|
-
# load calculations
|
|
183
|
-
for ELR in calculationsInstance.relationshipSet(XbrlConst.summationItem).linkRoleUris:
|
|
184
|
-
elrRelSet = calculationsInstance.relationshipSet(XbrlConst.summationItem, ELR)
|
|
185
|
-
definition = ""
|
|
186
|
-
for roleType in calculationsInstance.roleTypes.get(ELR,()):
|
|
187
|
-
definition = roleType.definition
|
|
188
|
-
break
|
|
189
|
-
isStatementSheet = bool(val.linkroleDefinitionStatementSheet.match(definition))
|
|
190
|
-
elrUgtCalcs = {"#roots": [c.name for c in elrRelSet.rootConcepts],
|
|
191
|
-
"#definition": definition,
|
|
192
|
-
"#isStatementSheet": isStatementSheet}
|
|
193
|
-
for relFrom, rels in elrRelSet.fromModelObjects().items():
|
|
194
|
-
elrUgtCalcs[relFrom.name] = [rel.toModelObject.name for rel in rels]
|
|
195
|
-
val.usgaapCalculations[ELR] = elrUgtCalcs
|
|
196
|
-
jsonStr = str(json.dumps(val.usgaapCalculations, ensure_ascii=False, indent=0)) # might not be unicode in 2.7
|
|
197
|
-
saveFile(cntlr, ugtCalcsJsonFile, jsonStr) # 2.7 gets unicode this way
|
|
198
|
-
# load default dimensions
|
|
199
|
-
for defaultDimRel in calculationsInstance.relationshipSet(XbrlConst.dimensionDefault).modelRelationships:
|
|
200
|
-
if isinstance(defaultDimRel.fromModelObject, ModelConcept) and isinstance(defaultDimRel.toModelObject, ModelConcept):
|
|
201
|
-
val.usgaapDefaultDimensions[defaultDimRel.fromModelObject.name] = defaultDimRel.toModelObject.name
|
|
202
|
-
jsonStr = str(json.dumps(val.usgaapDefaultDimensions, ensure_ascii=False, indent=0)) # might not be unicode in 2.7
|
|
203
|
-
saveFile(cntlr, ugtDefaultDimensionsJsonFile, jsonStr) # 2.7 gets unicode this way
|
|
204
|
-
calculationsInstance.close()
|
|
205
|
-
del calculationsInstance # dereference closed modelXbrl
|
|
206
|
-
val.modelXbrl.profileStat(_("build us-gaap calculations and default dimensions cache"), time.time() - startedAt)
|
|
207
|
-
break
|
|
208
|
-
val.deprecatedFactConcepts = defaultdict(list)
|
|
209
|
-
val.deprecatedDimensions = defaultdict(list)
|
|
210
|
-
val.deprecatedMembers = defaultdict(list)
|
|
211
|
-
|
|
212
|
-
def factCheck(val, fact, *args, **kwargs):
|
|
213
|
-
concept = fact.concept
|
|
214
|
-
context = fact.context
|
|
215
|
-
if concept is None or context is None or not val.validateLoggingSemantic:
|
|
216
|
-
return # not checkable
|
|
217
|
-
|
|
218
|
-
try:
|
|
219
|
-
if fact.isNumeric:
|
|
220
|
-
# 2.3.3 additional unit tests beyond UTR spec
|
|
221
|
-
unit = fact.unit
|
|
222
|
-
if unit is not None and concept.type is not None and val.validateUTR:
|
|
223
|
-
typeName = concept.type.name
|
|
224
|
-
if typeName == "perUnitItemType" and any(m.namespaceURI == XbrlConst.iso4217 or
|
|
225
|
-
m in (XbrlConst.qnXbrliPure, XbrlConst.qnXbrliShares)
|
|
226
|
-
for m in unit.measures[1]):
|
|
227
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "US-BPG.2.3.3.perUnitItemType",
|
|
228
|
-
_("PureItemType fact %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s has disallowed unit denominator %(denominator)s"),
|
|
229
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
230
|
-
value=fact.effectiveValue, denominator=", ".join((str(m) for m in unit.measures[1])))
|
|
231
|
-
|
|
232
|
-
if not fact.isNil and getattr(fact, "xValue", None) is not None:
|
|
233
|
-
|
|
234
|
-
# 2.4.1 decimal disagreement
|
|
235
|
-
if fact.decimals and fact.decimals != "INF":
|
|
236
|
-
vf = float(fact.value)
|
|
237
|
-
if isfinite(vf):
|
|
238
|
-
dec = int(fact.decimals)
|
|
239
|
-
vround = round(vf, dec)
|
|
240
|
-
if vf != vround:
|
|
241
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "US-BPG.2.4.1",
|
|
242
|
-
_("Decimal disagreement %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s has insignificant value %(insignificantValue)s"),
|
|
243
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
244
|
-
value=fact.effectiveValue, insignificantValue=Locale.format(val.modelXbrl.locale, "%.*f",
|
|
245
|
-
(dec + 2 if dec > 0 else 0, vf - vround),
|
|
246
|
-
True))
|
|
247
|
-
# 2.5.1 fractions disallowed on a disclosure
|
|
248
|
-
if fact.isFraction:
|
|
249
|
-
if any(val.linroleDefinitionIsDisclosure.match(roleType.definition)
|
|
250
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.parentChild).toModelObject(concept)
|
|
251
|
-
for roleType in val.modelXbrl.roleTypes.get(rel.linkrole,())):
|
|
252
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "US-BPG.2.5.1",
|
|
253
|
-
_("Disclosure %(fact)s in context %(contextID)s value %(value)s is a fraction"),
|
|
254
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, value=fact.value)
|
|
255
|
-
|
|
256
|
-
# deprecated concept
|
|
257
|
-
if concept.qname.namespaceURI == val.ugtNamespace:
|
|
258
|
-
if concept.name in val.usgaapDeprecations:
|
|
259
|
-
val.deprecatedFactConcepts[concept].append(fact)
|
|
260
|
-
elif concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"):
|
|
261
|
-
val.deprecatedFactConcepts[concept].append(fact)
|
|
262
|
-
if fact.isItem and fact.context is not None:
|
|
263
|
-
for dimConcept, modelDim in fact.context.segDimValues.items():
|
|
264
|
-
if dimConcept.qname.namespaceURI == val.ugtNamespace:
|
|
265
|
-
if dimConcept.name in val.usgaapDeprecations:
|
|
266
|
-
val.deprecatedDimensions[dimConcept].append(fact)
|
|
267
|
-
elif dimConcept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"):
|
|
268
|
-
val.deprecatedDimensions[dimConcept].append(fact)
|
|
269
|
-
if modelDim.isExplicit:
|
|
270
|
-
member = modelDim.member
|
|
271
|
-
if member is not None:
|
|
272
|
-
if member.qname.namespaceURI == val.ugtNamespace:
|
|
273
|
-
if member.name in val.usgaapDeprecations:
|
|
274
|
-
val.deprecatedMembers[member].append(fact)
|
|
275
|
-
elif member.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"):
|
|
276
|
-
val.deprecatedMembers[member].append(fact)
|
|
277
|
-
except Exception as err:
|
|
278
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "US-BPG.testingException",
|
|
279
|
-
_("%(fact)s in context %(contextID)s unit %(unitID)s value %(value)s cannot be tested due to: %(err)s"),
|
|
280
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
281
|
-
value=fact.effectiveValue, err=err)
|
|
282
|
-
|
|
283
|
-
def final(val, conceptsUsed, *args, **kwargs):
|
|
284
|
-
if not val.validateLoggingSemantic: # all checks herein are SEMANTIC
|
|
285
|
-
return
|
|
286
|
-
ugtNamespace = val.ugtNamespace
|
|
287
|
-
standardTaxonomiesDict = val.disclosureSystem.standardTaxonomiesDict
|
|
288
|
-
startedAt = time.time()
|
|
289
|
-
for depType, depItems in (("Concept", val.deprecatedFactConcepts),
|
|
290
|
-
("Dimension", val.deprecatedDimensions),
|
|
291
|
-
("Member", val.deprecatedMembers)):
|
|
292
|
-
for concept, facts in depItems.items():
|
|
293
|
-
if concept.qname.namespaceURI == ugtNamespace:
|
|
294
|
-
if concept.name in val.usgaapDeprecations:
|
|
295
|
-
deprecation = val.usgaapDeprecations[concept.name]
|
|
296
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "FASB:deprecated{0}".format(depType),
|
|
297
|
-
_("%(deprecation)s of fact(s) %(fact)s (e.g., in context %(contextID)s value %(value)s) was deprecated on %(date)s: %(documentation)s"),
|
|
298
|
-
modelObject=facts, fact=facts[0].qname, contextID=facts[0].contextID, value=facts[0].value,
|
|
299
|
-
deprecation=depType,
|
|
300
|
-
date=deprecation[0], documentation=deprecation[1])
|
|
301
|
-
elif concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"):
|
|
302
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "FASB:deprecated{0}".format(depType),
|
|
303
|
-
_("%(deprecation)s of facts %(fact)s in context %(contextID)s value %(value)s was deprecated on %(date)s"),
|
|
304
|
-
modelObject=facts, fact=facts[0].qname, contextID=facts[0].contextID, value=facts[0].value,
|
|
305
|
-
deprecation=depType,
|
|
306
|
-
date=concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"))
|
|
307
|
-
|
|
308
|
-
# check for unused extension concepts
|
|
309
|
-
dimensionDefaults = set()
|
|
310
|
-
def defaultParentCheck(mem, ELR=None):
|
|
311
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.domainMember, ELR).toModelObject(mem):
|
|
312
|
-
memParent = rel.fromModelObject
|
|
313
|
-
isCycle = memParent in dimensionDefaults
|
|
314
|
-
dimensionDefaults.add(memParent)
|
|
315
|
-
if not isCycle:
|
|
316
|
-
defaultParentCheck(memParent, rel.linkrole)
|
|
317
|
-
for defaultMemConcept in val.modelXbrl.dimensionDefaultConcepts.values():
|
|
318
|
-
dimensionDefaults.add(defaultMemConcept)
|
|
319
|
-
# also add any domain or intermediate parents of dimension default in any ELR as they likely will be unused
|
|
320
|
-
defaultParentCheck(defaultMemConcept)
|
|
321
|
-
extensionConceptsUnused = [concept
|
|
322
|
-
for qn, concept in val.modelXbrl.qnameConcepts.items()
|
|
323
|
-
if concept.isItem and
|
|
324
|
-
qn.namespaceURI not in standardTaxonomiesDict
|
|
325
|
-
if concept not in conceptsUsed and
|
|
326
|
-
# don't report dimension that has a default member
|
|
327
|
-
concept not in val.modelXbrl.dimensionDefaultConcepts and
|
|
328
|
-
# don't report default members
|
|
329
|
-
concept not in dimensionDefaults and
|
|
330
|
-
(concept.isDimensionItem or
|
|
331
|
-
(concept.type is not None and concept.type.isDomainItemType) or
|
|
332
|
-
# this or branch only pertains to fact concepts
|
|
333
|
-
not concept.isAbstract)
|
|
334
|
-
]
|
|
335
|
-
if extensionConceptsUnused:
|
|
336
|
-
for concept in sorted(extensionConceptsUnused, key=lambda c: str(c.qname)):
|
|
337
|
-
val.modelXbrl.log('INFO-SEMANTIC', "US-BPG.1.7.1.unusedExtensionConcept",
|
|
338
|
-
_("Company extension concept is unused: %(concept)s"),
|
|
339
|
-
modelObject=concept, concept=concept.qname)
|
|
340
|
-
|
|
341
|
-
# check for unused concept relationships of standard taxonomy elements
|
|
342
|
-
standardRelationships = val.modelXbrl.relationshipSet((XbrlConst.parentChild, XbrlConst.summationItem, XbrlConst.dimensionDomain, XbrlConst.domainMember, XbrlConst.dimensionDefault))
|
|
343
|
-
standardConceptsUnused = defaultdict(set) # dict by concept of relationship where unused
|
|
344
|
-
standardConceptsDeprecated = defaultdict(set)
|
|
345
|
-
for rel in standardRelationships.modelRelationships:
|
|
346
|
-
for concept in (rel.fromModelObject, rel.toModelObject):
|
|
347
|
-
if (isinstance(concept, ModelConcept) and concept.qname is not None and
|
|
348
|
-
concept.qname.namespaceURI in standardTaxonomiesDict and
|
|
349
|
-
concept not in conceptsUsed):
|
|
350
|
-
if (not concept.isAbstract or
|
|
351
|
-
concept.isDimensionItem or
|
|
352
|
-
(concept.type is not None and concept.type.isDomainItemType)):
|
|
353
|
-
standardConceptsUnused[concept].add(rel)
|
|
354
|
-
elif ((concept.qname.namespaceURI == ugtNamespace and
|
|
355
|
-
concept.name in val.usgaapDeprecations) or
|
|
356
|
-
concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate")):
|
|
357
|
-
# catches abstract deprecated concepts in linkbases
|
|
358
|
-
standardConceptsDeprecated[concept].add(rel)
|
|
359
|
-
for concept, rels in standardConceptsUnused.items():
|
|
360
|
-
if concept.qname.namespaceURI == ugtNamespace and concept.name in val.usgaapDeprecations:
|
|
361
|
-
deprecation = val.usgaapDeprecations[concept.name]
|
|
362
|
-
val.modelXbrl.log('INFO-SEMANTIC', "FASB:deprecatedConcept",
|
|
363
|
-
_("Unused concept %(concept)s has extension relationships and was deprecated on %(date)s: %(documentation)s"),
|
|
364
|
-
modelObject=rels, concept=concept.qname,
|
|
365
|
-
date=deprecation[0], documentation=deprecation[1])
|
|
366
|
-
elif concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"):
|
|
367
|
-
val.modelXbrl.log('INFO-SEMANTIC', "FASB:deprecatedConcept",
|
|
368
|
-
_("Unused concept %(concept)s has extension relationships was deprecated on %(date)s"),
|
|
369
|
-
modelObject=rels, concept=concept.qname,
|
|
370
|
-
date=concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"))
|
|
371
|
-
elif (concept not in val.modelXbrl.dimensionDefaultConcepts and # don't report dimension that has a default member
|
|
372
|
-
concept not in dimensionDefaults and # don't report default members
|
|
373
|
-
(concept.isDimensionItem or
|
|
374
|
-
(concept.type is not None and concept.type.isDomainItemType) or
|
|
375
|
-
# this or branch only pertains to fact concepts
|
|
376
|
-
not concept.isAbstract)):
|
|
377
|
-
val.modelXbrl.log('INFO-SEMANTIC', "US-BPG.1.7.1.unusedStandardConceptInExtensionRelationship",
|
|
378
|
-
_("Company extension relationships of unused standard concept: %(concept)s"),
|
|
379
|
-
modelObject=rels, concept=concept.qname)
|
|
380
|
-
for concept, rels in standardConceptsDeprecated.items():
|
|
381
|
-
if concept.qname.namespaceURI == ugtNamespace and concept.name in val.usgaapDeprecations:
|
|
382
|
-
deprecation = val.usgaapDeprecations[concept.name]
|
|
383
|
-
val.modelXbrl.log('INFO-SEMANTIC', "FASB:deprecatedConcept",
|
|
384
|
-
_("Concept %(concept)s has extension relationships and was deprecated on %(date)s: %(documentation)s"),
|
|
385
|
-
modelObject=rels, concept=concept.qname,
|
|
386
|
-
date=deprecation[0], documentation=deprecation[1])
|
|
387
|
-
elif concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"):
|
|
388
|
-
val.modelXbrl.log('INFO-SEMANTIC', "FASB:deprecatedConcept",
|
|
389
|
-
_("Concept %(concept)s has extension relationships was deprecated on %(date)s"),
|
|
390
|
-
modelObject=rels, concept=concept.qname,
|
|
391
|
-
date=concept.get("{http://fasb.org/us-gaap/attributes}deprecatedDate"))
|
|
392
|
-
val.modelXbrl.profileStat(_("validate US-BGP unused concepts"), time.time() - startedAt)
|
|
393
|
-
|
|
394
|
-
del standardRelationships, extensionConceptsUnused, standardConceptsUnused, standardConceptsDeprecated, dimensionDefaults
|
|
395
|
-
del val.deprecatedFactConcepts
|
|
396
|
-
del val.deprecatedDimensions
|
|
397
|
-
del val.deprecatedMembers
|
|
398
|
-
|
|
399
|
-
if hasattr(val, 'usgaapCalculations'):
|
|
400
|
-
"""
|
|
401
|
-
The UGT calcuations are loaded and cached from the US-GAAP.
|
|
402
|
-
|
|
403
|
-
UGT calculation link roles are presumed to (and do) reflect the statement sheets they
|
|
404
|
-
correspond to, and therefore each set of UGT summation-item arc-sets are cached and
|
|
405
|
-
identified as to whether a statement sheet or other.
|
|
406
|
-
|
|
407
|
-
A concept that has facts in the instance and is a total concept with summation-item
|
|
408
|
-
arc-sets in UGT is examined if it appears on any submission face statement
|
|
409
|
-
parent-child link role. (No examination is made if the concept is only on
|
|
410
|
-
non-face statements of the submission, even if on some UGT face statement.)
|
|
411
|
-
|
|
412
|
-
Each UGT link role that has facts reported with a total concept has its
|
|
413
|
-
summation-item arc-sets examained to see if any compatible pair of UGT total
|
|
414
|
-
and item facts in the instance document do not have any submission calculation
|
|
415
|
-
sibling or descendant relationship. (Compatible here only means context and unit
|
|
416
|
-
equivalence.) Addition of descendancy in the submission was needed to avoid
|
|
417
|
-
excessive false positives. Each such issue is reported by filing parent-child
|
|
418
|
-
link role, UGT calculation link role, contributing item, and total item. The
|
|
419
|
-
report of these items is sorted by contributing item.
|
|
420
|
-
"""
|
|
421
|
-
startedAt = time.time()
|
|
422
|
-
# check for usgaap calculations missing from extension
|
|
423
|
-
ugtTotalConceptNames = set(totalConceptName
|
|
424
|
-
for ugtRels in val.usgaapCalculations.values()
|
|
425
|
-
for totalConceptName in ugtRels.keys())
|
|
426
|
-
issues = []
|
|
427
|
-
for totalConcept in conceptsUsed:
|
|
428
|
-
# is it ugt concept on a filing face sheet statement
|
|
429
|
-
if (totalConcept.qname.namespaceURI == ugtNamespace and
|
|
430
|
-
totalConcept.qname.localName in ugtTotalConceptNames and
|
|
431
|
-
any(val.linkroleDefinitionStatementSheet.match(roleType.definition)
|
|
432
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.parentChild).toModelObject(totalConcept)
|
|
433
|
-
for roleType in val.modelXbrl.roleTypes.get(rel.linkrole,()))):
|
|
434
|
-
# is it a total in usgaap-calculations on a statement
|
|
435
|
-
for ugtELR, ugtRels in val.usgaapCalculations.items():
|
|
436
|
-
if ugtRels["#isStatementSheet"] and totalConcept.name in ugtRels:
|
|
437
|
-
# find compatible filed concepts on ugt summation items
|
|
438
|
-
for itemName in ugtRels[totalConcept.name]:
|
|
439
|
-
itemQname = qname(ugtNamespace,itemName)
|
|
440
|
-
itemConcept = val.modelXbrl.qnameConcepts.get(itemQname)
|
|
441
|
-
if itemConcept is not None and itemConcept in conceptsUsed:
|
|
442
|
-
# and item concept appears on a same face statement with total concept
|
|
443
|
-
filingELR = None
|
|
444
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.parentChild).toModelObject(itemConcept):
|
|
445
|
-
for roleType in val.modelXbrl.roleTypes.get(rel.linkrole,()):
|
|
446
|
-
if (val.linkroleDefinitionStatementSheet.match(roleType.definition) and
|
|
447
|
-
val.modelXbrl.relationshipSet(XbrlConst.parentChild,rel.linkrole)
|
|
448
|
-
.isRelated(totalConcept,'sibling-or-descendant',itemConcept)):
|
|
449
|
-
filingELR = rel.linkrole
|
|
450
|
-
break
|
|
451
|
-
if filingELR:
|
|
452
|
-
break
|
|
453
|
-
if filingELR:
|
|
454
|
-
# are there any compatible facts for this sum?
|
|
455
|
-
for totalFact in val.modelXbrl.factsByQname[totalConcept.qname]:
|
|
456
|
-
for itemFact in val.modelXbrl.factsByQname[itemQname]:
|
|
457
|
-
if (totalFact.context is not None and totalFact.context.isEqualTo(itemFact.context) and
|
|
458
|
-
totalFact.unit is not None and totalFact.unit.isEqualTo(itemFact.unit)):
|
|
459
|
-
foundFiledItemCalc = False
|
|
460
|
-
# is there a summation in the filing
|
|
461
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.summationItem).fromModelObject(totalConcept):
|
|
462
|
-
if rel.toModelObject is itemConcept:
|
|
463
|
-
foundFiledItemCalc = True
|
|
464
|
-
if not foundFiledItemCalc:
|
|
465
|
-
issues.append((filingELR,
|
|
466
|
-
ugtELR,
|
|
467
|
-
itemName,
|
|
468
|
-
totalFact,
|
|
469
|
-
itemFact))
|
|
470
|
-
if issues:
|
|
471
|
-
filingELRs = set()
|
|
472
|
-
ugtELRs = set()
|
|
473
|
-
itemIssuesELRs = defaultdict(set)
|
|
474
|
-
contextIDs = set()
|
|
475
|
-
for issue in issues:
|
|
476
|
-
filingELR, ugtELR, itemName, totalFact, itemFact = issue
|
|
477
|
-
filingELRs.add(filingELR)
|
|
478
|
-
ugtELRs.add(ugtELR)
|
|
479
|
-
contextIDs.add(totalFact.contextID)
|
|
480
|
-
contextIDs.add(itemFact.contextID)
|
|
481
|
-
itemIssuesELRs[itemName].add((filingELR, ugtELR))
|
|
482
|
-
|
|
483
|
-
msg = [_("Financial statement calculation missing relationships from total concept to item concepts that are in us-gaap taxonomy. "),
|
|
484
|
-
_("\n\nTotal concept: \n%(conceptSum)s. ")]
|
|
485
|
-
args = {"conceptSum": totalConcept.qname}
|
|
486
|
-
if len(filingELRs) == 1:
|
|
487
|
-
msg.append(_("\n\nfiling schedule link role: \n%(filingLinkrole)s. "))
|
|
488
|
-
args["filingLinkrole"] = filingELR
|
|
489
|
-
if len(ugtELRs) == 1:
|
|
490
|
-
msg.append(_("\n\nus-gaap calc link role: \n%(usgaapLinkrole)s. "))
|
|
491
|
-
args["usgaapLinkrole"] = ugtELR
|
|
492
|
-
if len(filingELRs) == 1 and len(ugtELRs) == 1:
|
|
493
|
-
msg.append(_("\n\nSummation items missing: \n"))
|
|
494
|
-
for i, itemName in enumerate(sorted(itemIssuesELRs.keys())):
|
|
495
|
-
for j, itemIssueELRs in enumerate(sorted(itemIssuesELRs[itemName])):
|
|
496
|
-
filingELR, ugtELR = itemIssueELRs
|
|
497
|
-
if j == 0:
|
|
498
|
-
argName = "missingConcept_{0}".format(i)
|
|
499
|
-
if len(filingELRs) == 1 and len(ugtELRs) == 1:
|
|
500
|
-
msg.append(_("\n%({0})s. ").format(argName))
|
|
501
|
-
else:
|
|
502
|
-
msg.append(_("\n\nSummation item: %({0})s. ").format(argName))
|
|
503
|
-
args[argName] = itemFact.qname
|
|
504
|
-
if len(filingELRs) > 1:
|
|
505
|
-
argName = "filingLinkrole_{0}_{1}".format(i,j)
|
|
506
|
-
msg.append(_("\n filing schedule: %({0})s. ").format(argName))
|
|
507
|
-
args[argName] = filingELR
|
|
508
|
-
if len(ugtELRs) > 1:
|
|
509
|
-
argName = "usgaapLinkrole_{0}_{1}".format(i,j)
|
|
510
|
-
msg.append(_("\n us-gaap linkrole: %({0})s. ").format(argName))
|
|
511
|
-
args[argName] = ugtELR
|
|
512
|
-
msg.append(_("\n\nCorresponding facts in contexts: \n%(contextIDs)s\n"))
|
|
513
|
-
args["contextIDs"] = ", ".join(sorted(contextIDs))
|
|
514
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "US-BPG:missingCalculation",
|
|
515
|
-
''.join(msg),
|
|
516
|
-
**args)
|
|
517
|
-
issues = []
|
|
518
|
-
val.modelXbrl.profileStat(_("validate US-BGP missing calcs"), time.time() - startedAt)
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
if hasattr(val, 'usgaapDefaultDimensions'):
|
|
522
|
-
"""
|
|
523
|
-
The UGT default dimensions are loaded and cached from US-GAAP.
|
|
524
|
-
|
|
525
|
-
Question E.16 (Updated 02/05/2013):
|
|
526
|
-
|
|
527
|
-
Filers SHOULD also avoid creating new domains or changing default member elements for pre-defined dimensions.
|
|
528
|
-
"""
|
|
529
|
-
for defaultDimRel in val.modelXbrl.relationshipSet(XbrlConst.dimensionDefault).modelRelationships:
|
|
530
|
-
if (isinstance(defaultDimRel.fromModelObject, ModelConcept) and isinstance(defaultDimRel.toModelObject, ModelConcept) and
|
|
531
|
-
defaultDimRel.fromModelObject.qname.namespaceURI == ugtNamespace and
|
|
532
|
-
defaultDimRel.fromModelObject.name in val.usgaapDefaultDimensions and
|
|
533
|
-
(defaultDimRel.toModelObject.qname.namespaceURI not in standardTaxonomiesDict or
|
|
534
|
-
defaultDimRel.toModelObject.name != val.usgaapDefaultDimensions[defaultDimRel.fromModelObject.name])):
|
|
535
|
-
if defaultDimRel.toModelObject.qname.namespaceURI not in standardTaxonomiesDict:
|
|
536
|
-
msgObjects = (defaultDimRel, defaultDimRel.toModelObject)
|
|
537
|
-
else:
|
|
538
|
-
msgObjects = defaultDimRel
|
|
539
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "secStaffObservation.E.16.defaultDimension",
|
|
540
|
-
_("UGT-defined dimension %(dimension)s has extension defined default %(extensionDefault)s, predefined default is %(predefinedDefault)s"),
|
|
541
|
-
modelObject=msgObjects,
|
|
542
|
-
dimension=defaultDimRel.fromModelObject.qname,
|
|
543
|
-
extensionDefault=defaultDimRel.toModelObject.qname,
|
|
544
|
-
predefinedDefault=defaultDimRel.fromModelObject.qname.prefix + ":" + val.usgaapDefaultDimensions[defaultDimRel.fromModelObject.name])
|
|
545
|
-
|
|
546
|
-
val.modelXbrl.profileStat(_("validate SEC staff observation E.16 dimensions"), time.time() - startedAt)
|
|
547
|
-
|
|
548
|
-
del val.linroleDefinitionIsDisclosure
|
|
549
|
-
del val.linkroleDefinitionStatementSheet
|
|
550
|
-
del val.ugtNamespace
|
|
551
|
-
if hasattr(val, 'usgaapDeprecations'):
|
|
552
|
-
del val.usgaapDeprecations
|
|
553
|
-
if hasattr(val, 'usgaapDefaultDimensions'):
|
|
554
|
-
del val.usgaapDefaultDimensions
|
|
555
|
-
if hasattr(val, 'usgaapCalculations'):
|
|
556
|
-
del val.usgaapCalculations
|
|
557
|
-
|
|
558
|
-
__pluginInfo__ = {
|
|
559
|
-
# Do not use _( ) in pluginInfo itself (it is applied later, after loading
|
|
560
|
-
'name': 'Validate XBRL-US Best Practice Guidance',
|
|
561
|
-
'version': '0.9',
|
|
562
|
-
'description': '''XBRL-US Best Practice Guidance Validation.''',
|
|
563
|
-
'license': 'Apache-2',
|
|
564
|
-
'author': 'Ewe S. Gap',
|
|
565
|
-
'copyright': copyrightLabel,
|
|
566
|
-
# classes of mount points (required)
|
|
567
|
-
'Validate.EFM.Start': setup,
|
|
568
|
-
'Validate.EFM.Fact': factCheck,
|
|
569
|
-
'Validate.EFM.Finally': final
|
|
570
|
-
}
|