arelle-release 2.37.47__py3-none-any.whl → 2.37.49__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.
Potentially problematic release.
This version of arelle-release might be problematic. Click here for more details.
- arelle/CntlrCmdLine.py +5 -1
- arelle/ModelObjectFactory.py +18 -2
- arelle/_version.py +2 -2
- arelle/plugin/validate/EDINET/Constants.py +6 -0
- arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +134 -7
- arelle/plugin/validate/EDINET/Statement.py +139 -0
- arelle/plugin/validate/EDINET/rules/contexts.py +5 -10
- arelle/plugin/validate/EDINET/rules/edinet.py +89 -51
- arelle/plugin/validate/EDINET/rules/gfm.py +41 -0
- {arelle_release-2.37.47.dist-info → arelle_release-2.37.49.dist-info}/METADATA +3 -1
- {arelle_release-2.37.47.dist-info → arelle_release-2.37.49.dist-info}/RECORD +15 -99
- 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 -50
- 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/scripts-macOS/startWebServer.command +0 -3
- arelle/scripts-unix/startWebServer.sh +0 -1
- arelle/scripts-windows/startWebServer.bat +0 -5
- {arelle_release-2.37.47.dist-info → arelle_release-2.37.49.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.47.dist-info → arelle_release-2.37.49.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.47.dist-info → arelle_release-2.37.49.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.47.dist-info → arelle_release-2.37.49.dist-info}/top_level.txt +0 -0
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
See COPYRIGHT.md for copyright information.
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
from arelle import PluginManager
|
|
6
|
-
from arelle.ModelValue import qname
|
|
7
|
-
from arelle import XbrlConst
|
|
8
|
-
from arelle.Version import copyrightLabel
|
|
9
|
-
import regex as re
|
|
10
|
-
from collections import defaultdict
|
|
11
|
-
|
|
12
|
-
def compile(list, traceRows):
|
|
13
|
-
if traceRows:
|
|
14
|
-
# compile so each row can be traced by separate expression (slow)
|
|
15
|
-
return [(rowNbr, re.compile(r"(^|\s)" + pattern + r"($|\W+)", re.IGNORECASE))
|
|
16
|
-
for rowNbr, pattern in list]
|
|
17
|
-
else:
|
|
18
|
-
# compile single expression for fast execution
|
|
19
|
-
return re.compile(r"(^|\s)" + # always be sure first word starts at start or after space
|
|
20
|
-
r"($|\W+)|(^|\s)".join(pattern for rowNbr, pattern in list)
|
|
21
|
-
.replace(r" ",r"\W+") + r"($|\W+)",
|
|
22
|
-
re.IGNORECASE)
|
|
23
|
-
|
|
24
|
-
def setup(val, traceRows=False, *args, **kwargs):
|
|
25
|
-
if not val.validateLoggingSemantic: # all checks herein are SEMANTIC
|
|
26
|
-
return
|
|
27
|
-
# determiniation of two way concept label based on pattern
|
|
28
|
-
# definitions (from documentation label) are used if present, otherwise standard label for these tests
|
|
29
|
-
val.twoWayPriItemDefLabelPattern = compile([
|
|
30
|
-
# from http://www.sec.gov/spotlight/xbrl/staff-review-observations-061511.shtml
|
|
31
|
-
# Cash Flow
|
|
32
|
-
(4, r"increase (\w+ )?decrease"),
|
|
33
|
-
(5, r"provided by (\w+ )?used in"),
|
|
34
|
-
(7, r"net cash inflow or outflow"),
|
|
35
|
-
(6, r"net"),
|
|
36
|
-
(8, r"change in"),
|
|
37
|
-
(9, r"proceeds from (\w+ )?payments (for|to)"),
|
|
38
|
-
# Income statement
|
|
39
|
-
(13, r"(gain|profit) loss"),
|
|
40
|
-
(16, r"income (expense|loss)"),
|
|
41
|
-
(18, r"per share"),
|
|
42
|
-
# Statement of Stockholders Equity
|
|
43
|
-
(22, r"equity"),
|
|
44
|
-
(23, r"retained earnings"),
|
|
45
|
-
# removed? r"conversion of units",
|
|
46
|
-
], traceRows)
|
|
47
|
-
# standard label tests, indicate two-way label
|
|
48
|
-
val.twoWayPriItemStdLabelPattern = compile([
|
|
49
|
-
# from Eric Cohen
|
|
50
|
-
(4, r"Increase \(Decrease\)"),
|
|
51
|
-
(5, r"Provided by \(Used in\)"),
|
|
52
|
-
(6, r"Net"),
|
|
53
|
-
(8, r"Change in"),
|
|
54
|
-
(9, r"Proceeds from \(Payments for\)"),
|
|
55
|
-
(10, r"Proceeds from \(Payments to\)"),
|
|
56
|
-
(11, r"Payments for \(Proceeds from\)"),
|
|
57
|
-
(12, r"Proceeds from \(Repayments of\)"),
|
|
58
|
-
(13, r"Gain \(Loss\)"),
|
|
59
|
-
(14, r"Profit \(Loss\)"),
|
|
60
|
-
(15, r"Loss \(Gain\)"),
|
|
61
|
-
(16, r"Income \(Loss\)"),
|
|
62
|
-
(17, r"Income \(Expense\)"),
|
|
63
|
-
(18, r"Per Share"),
|
|
64
|
-
(19, r"Per Basic Share"),
|
|
65
|
-
(20, r"Per Diluted Share"),
|
|
66
|
-
(21, r"Per Basic and Diluted"),
|
|
67
|
-
(24, r"Appreciation \(Depreciation\)"),
|
|
68
|
-
(25, r"Asset \(Liability\)"),
|
|
69
|
-
(26, r"Assets Acquired \(Liabilities Assumed\)"),
|
|
70
|
-
(27, r"Benefit \(Expense\)"),
|
|
71
|
-
(28, r"Expense \(Benefit\)"),
|
|
72
|
-
(29, r"Cost[s] \(Credit[s]\)"),
|
|
73
|
-
(30, r"Deductions \(Charges\)"),
|
|
74
|
-
(31, r"Discount \(Premium\)"),
|
|
75
|
-
(32, r"Due from \(to\)"),
|
|
76
|
-
(33, r"Earnings \(Losses\)"),
|
|
77
|
-
(34, r"Earnings \(Deficit\)"),
|
|
78
|
-
(35, r"Excess \(Shortage\)"),
|
|
79
|
-
(36, r"Gains \(Losses\)"),
|
|
80
|
-
(37, r"Impairment \(Recovery\)"),
|
|
81
|
-
(38, r"Income \(Loss\)"),
|
|
82
|
-
(39, r"Liability \(Refund\)"),
|
|
83
|
-
(40, r"Loss \(Recovery\)"),
|
|
84
|
-
(41, r"Obligation[s] \(Asset[s]\)"),
|
|
85
|
-
(42, r"Proceeds from \(Repayments of\)"),
|
|
86
|
-
(43, r"Proceeds from \(Repurchase of\)"),
|
|
87
|
-
(44, r"Provided by \(Used in\)"),
|
|
88
|
-
(45, r"Provisions \(Recoveries\)"),
|
|
89
|
-
(46, r"Retained Earnings \(Accumulated Deficit\)"),
|
|
90
|
-
(47, r"per (\w+ )+"),
|
|
91
|
-
(70, r"Conversion of Units"),
|
|
92
|
-
(71, r"Effective (\w+ )?Rate"),
|
|
93
|
-
], traceRows)
|
|
94
|
-
# determination of a one-way concept based on standard label
|
|
95
|
-
val.oneWayPriItemDefLabelPattern = compile([
|
|
96
|
-
(49, r"dividend (\w+ )*(paid|received)"),
|
|
97
|
-
], traceRows)
|
|
98
|
-
|
|
99
|
-
val.oneWayPriItemStdLabelPattern = compile([
|
|
100
|
-
(48, r"Payments of (\w+ )*\((Dividends|Capital)\)"),
|
|
101
|
-
(49, r"Dividends (\w+ )*\((Pay(ment)?|Receive|Outstanding)\)"),
|
|
102
|
-
(50, r"(Stock|Shares) Issued"),
|
|
103
|
-
(51, r"Stock (\w+ )*Repurchased"),
|
|
104
|
-
(52, r"(Stock|Shares) (\w+ )*Repurchase[d]?"),
|
|
105
|
-
(53, r"Treasury Stock (\w+ )*(Beginning (\w+ )*Balance[s]?|Ending (\w+ )*Balance[s]?)"),
|
|
106
|
-
(54, r"Treasury Stock (\w+ )*Acquired"),
|
|
107
|
-
(55, r"Treasury Stock (\w+ )*Reissued"),
|
|
108
|
-
(56, r"Treasury Stock (\w+ )*Retired"),
|
|
109
|
-
(57, r"Accumulated Depreciation (\w+ )*Amortization"),
|
|
110
|
-
(58, r"Accumulated Other Than Temporary Impairments"),
|
|
111
|
-
(59, r"Allowance (\w+ )*Doubtful Accounts"),
|
|
112
|
-
(60, r"Amortization (\w+ )*Pension Costs"),
|
|
113
|
-
(61, r"Available for Sale Securities (\w+ )*Continuous Loss Position"),
|
|
114
|
-
(62, r"Available for Sale Securities Bross Unrealized Losses"),
|
|
115
|
-
(63, r"Accounts"),
|
|
116
|
-
], traceRows)
|
|
117
|
-
# determination of a two way fact based on any of fact's dimension member label
|
|
118
|
-
val.twoWayMemberStdLabelPattern = compile([
|
|
119
|
-
# per Eric Cohen
|
|
120
|
-
(64, r"Change (in|during) \w+"), # don't match word with change in it like exchange
|
|
121
|
-
(65, r"\w+ Elimination \w+"),
|
|
122
|
-
(66, r"Adjustment"),
|
|
123
|
-
(67, r"Effect\s"),
|
|
124
|
-
(68, r"Gain(s)? (\w+ )*Loss(es)?"),
|
|
125
|
-
(69, r"Income \(Loss\)"),
|
|
126
|
-
(70, r"Net(ting)?"), # don't want to match word with net in it like internet
|
|
127
|
-
], traceRows)
|
|
128
|
-
val.schedules = {}
|
|
129
|
-
val.elrMatches = (("1statement", re.compile(r"-\s+Statement\s+-\s+", re.IGNORECASE)),
|
|
130
|
-
("2disclosure", re.compile(r"-\s+Disclosure\s+-\s+", re.IGNORECASE)),
|
|
131
|
-
("3schedule", re.compile(r"-\s+Schedule\s+-\s+", re.IGNORECASE)))
|
|
132
|
-
|
|
133
|
-
def schedules(val, concept):
|
|
134
|
-
try:
|
|
135
|
-
return val.schedules[concept.qname]
|
|
136
|
-
except KeyError:
|
|
137
|
-
schedules = defaultdict(int)
|
|
138
|
-
for rel in val.modelXbrl.relationshipSet(XbrlConst.parentChild).toModelObject(concept):
|
|
139
|
-
for roleType in val.modelXbrl.roleTypes.get(rel.linkrole,()):
|
|
140
|
-
for elrType, elrPattern in val.elrMatches:
|
|
141
|
-
if elrPattern.search(roleType.definition):
|
|
142
|
-
schedules[elrType] += 1
|
|
143
|
-
scheduleStr = ""
|
|
144
|
-
for elrType, num in sorted(schedules.items()):
|
|
145
|
-
scheduleStr += ", {0} {1}{2}".format(num, elrType[1:], "s" if num > 1 else "")
|
|
146
|
-
val.schedules[concept.qname] = scheduleStr
|
|
147
|
-
return scheduleStr
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def factCheck(val, fact, *args, **kwargs):
|
|
151
|
-
if not val.validateLoggingSemantic: # all checks herein are SEMANTIC
|
|
152
|
-
return
|
|
153
|
-
concept = fact.concept
|
|
154
|
-
context = fact.context
|
|
155
|
-
stdLabel = concept.label(lang="en-US", fallbackToQname=False)
|
|
156
|
-
defLabel = concept.label(preferredLabel=XbrlConst.documentationLabel, lang="en-US", fallbackToQname=False)
|
|
157
|
-
|
|
158
|
-
try:
|
|
159
|
-
if fact.isNumeric and not fact.isNil and fact.xValue is not None and fact.xValue < 0:
|
|
160
|
-
# is fact an explicit non neg
|
|
161
|
-
if ((defLabel is not None and val.oneWayPriItemDefLabelPattern.search(defLabel)) or
|
|
162
|
-
(stdLabel is not None and val.oneWayPriItemStdLabelPattern.search(stdLabel))):
|
|
163
|
-
if context.qnameDims: # if fact has a member
|
|
164
|
-
if any((val.twoWayMemberStdLabelPattern.search(dim.member.label(lang="en-US", fallbackToQname=False))
|
|
165
|
-
for dim in context.qnameDims.values()
|
|
166
|
-
if dim.isExplicit)): # any two way exception member
|
|
167
|
-
val.modelXbrl.log('INFO-SEMANTIC', "secStaffObservation.nonNegativeFact.info.A",
|
|
168
|
-
_("Negative fact of an explicit non-negative concept is tagged with a member expected to allow negative values: %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s%(elrTypes)s"),
|
|
169
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
170
|
-
value=fact.effectiveValue, elrTypes=schedules(val,concept))
|
|
171
|
-
else:
|
|
172
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "secStaffObservation.nonNegativeFact.warning.B",
|
|
173
|
-
_("Negative fact of an explicit non-negative concept, member may or not justify a negative value: %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s%(elrTypes)s"),
|
|
174
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
175
|
-
value=fact.effectiveValue, elrTypes=schedules(val,concept))
|
|
176
|
-
else: # no member
|
|
177
|
-
val.modelXbrl.log('INCONSISTENCY', "secStaffObservation.nonNegativeFact.inconsistency.C",
|
|
178
|
-
_("Negative fact of an explicit non-negative concept: %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s %(elrTypes)s"),
|
|
179
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
180
|
-
value=fact.effectiveValue, elrTypes=schedules(val,concept))
|
|
181
|
-
# else test if fact meets two way rules
|
|
182
|
-
elif ((defLabel is not None and val.twoWayPriItemDefLabelPattern.search(defLabel)) or
|
|
183
|
-
(stdLabel is not None and val.twoWayPriItemStdLabelPattern.search(stdLabel))):
|
|
184
|
-
val.modelXbrl.log('INFO-SEMANTIC', "secStaffObservation.nonNegativeFact.info.D",
|
|
185
|
-
_("Negative fact of concept expected to have positive and negative values: %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s%(elrTypes)s"),
|
|
186
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
187
|
-
value=fact.effectiveValue, elrTypes=schedules(val,concept))
|
|
188
|
-
else:
|
|
189
|
-
if context.qnameDims: # if fact has a member
|
|
190
|
-
if any((val.twoWayMemberStdLabelPattern.search(dim.member.label(lang="en-US", fallbackToQname=False))
|
|
191
|
-
for dim in context.qnameDims.values()
|
|
192
|
-
if dim.isExplicit)): # any two way exception member
|
|
193
|
-
val.modelXbrl.log('INFO-SEMANTIC', "secStaffObservation.nonNegativeFact.info.E",
|
|
194
|
-
_("Negative fact for typically non-negative concept, but tagged with a member expected to allow negative values: %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s%(elrTypes)s"),
|
|
195
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
196
|
-
value=fact.effectiveValue, elrTypes=schedules(val,concept))
|
|
197
|
-
else:
|
|
198
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "secStaffObservation.nonNegativeFact.warning.F",
|
|
199
|
-
_("Negative fact of a typically non-negative concept, member may or not justify a negative value: %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s%(elrTypes)s"),
|
|
200
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
201
|
-
value=fact.effectiveValue, elrTypes=schedules(val,concept))
|
|
202
|
-
else: # no member
|
|
203
|
-
val.modelXbrl.log('INCONSISTENCY', "secStaffObservation.nonNegativeFact.inconsistency.G",
|
|
204
|
-
_("Negative fact of a \"presumed by default\" non-negative concept: %(fact)s in context %(contextID)s unit %(unitID)s value %(value)s%(elrTypes)s"),
|
|
205
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
206
|
-
value=fact.effectiveValue, elrTypes=schedules(val,concept))
|
|
207
|
-
except Exception as ex:
|
|
208
|
-
val.modelXbrl.log('WARNING-SEMANTIC', "arelle:nonNegFactTestException",
|
|
209
|
-
_("%(fact)s in context %(contextID)s unit %(unitID)s value %(value)s%(elrTypes)s cannot be tested nonnegative"),
|
|
210
|
-
modelObject=fact, fact=fact.qname, contextID=fact.contextID, unitID=fact.unitID,
|
|
211
|
-
value=fact.effectiveValue, elrTypes=schedules(val,fact))
|
|
212
|
-
|
|
213
|
-
def final(val, conceptsUsed, *args, **kwargs):
|
|
214
|
-
if not val.validateLoggingSemantic: # all checks herein are SEMANTIC
|
|
215
|
-
return
|
|
216
|
-
del val.twoWayPriItemDefLabelPattern
|
|
217
|
-
del val.twoWayPriItemStdLabelPattern
|
|
218
|
-
del val.oneWayPriItemStdLabelPattern
|
|
219
|
-
del val.twoWayMemberStdLabelPattern
|
|
220
|
-
del val.schedules
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
def saveDtsMatches(dts, secDtsTagMatchesFile):
|
|
224
|
-
setup(dts, True)
|
|
225
|
-
import sys, csv
|
|
226
|
-
csvOpenMode = 'w'
|
|
227
|
-
csvOpenNewline = ''
|
|
228
|
-
csvFile = open(secDtsTagMatchesFile, csvOpenMode, newline=csvOpenNewline)
|
|
229
|
-
csvWriter = csv.writer(csvFile, dialect="excel")
|
|
230
|
-
csvWriter.writerow(("Concept", "Rule", "Row", "Pattern", "Label", "Documentation"))
|
|
231
|
-
num1wayConcepts = 0
|
|
232
|
-
num2wayConcepts = 0
|
|
233
|
-
num2wayMembers = 0
|
|
234
|
-
|
|
235
|
-
for qname, concept in sorted(dts.qnameConcepts.items(), key=lambda item: item[0]):
|
|
236
|
-
if concept.isItem and concept.isPrimaryItem: # both pri item and domain members
|
|
237
|
-
stdLabel = concept.label(lang="en-US", fallbackToQname=False)
|
|
238
|
-
defLabel = concept.label(preferredLabel=XbrlConst.documentationLabel, lang="en-US", fallbackToQname=False)
|
|
239
|
-
if concept.type is not None and concept.type.isDomainItemType:
|
|
240
|
-
if stdLabel is not None:
|
|
241
|
-
for rowNbr, pattern in dts.twoWayMemberStdLabelPattern:
|
|
242
|
-
if pattern.search(stdLabel):
|
|
243
|
-
csvWriter.writerow((str(qname), "member-2-way", rowNbr, pattern.pattern[6:-7], stdLabel, defLabel))
|
|
244
|
-
num2wayMembers += 1
|
|
245
|
-
elif concept.isNumeric and not concept.isAbstract: # not dimension domain/member
|
|
246
|
-
if defLabel is not None:
|
|
247
|
-
for rowNbr, pattern in dts.twoWayPriItemDefLabelPattern:
|
|
248
|
-
if pattern.search(defLabel):
|
|
249
|
-
csvWriter.writerow((str(qname), "concept-2-way-doc", rowNbr, pattern.pattern[6:-7], stdLabel, defLabel))
|
|
250
|
-
num2wayConcepts += 1
|
|
251
|
-
for rowNbr, pattern in dts.oneWayPriItemDefLabelPattern:
|
|
252
|
-
if pattern.search(defLabel):
|
|
253
|
-
csvWriter.writerow((str(qname), "concept-1-way-doc", rowNbr, pattern.pattern[6:-7], stdLabel, defLabel))
|
|
254
|
-
num1wayConcepts += 1
|
|
255
|
-
if stdLabel is not None:
|
|
256
|
-
for rowNbr, pattern in dts.twoWayPriItemStdLabelPattern:
|
|
257
|
-
if pattern.search(stdLabel):
|
|
258
|
-
csvWriter.writerow((str(qname), "concept-2-way-lbl", rowNbr, pattern.pattern[6:-7], stdLabel, defLabel))
|
|
259
|
-
num2wayConcepts += 1
|
|
260
|
-
for rowNbr, pattern in dts.oneWayPriItemStdLabelPattern:
|
|
261
|
-
if pattern.search(stdLabel):
|
|
262
|
-
csvWriter.writerow((str(qname), "concept-1-way-lbl", rowNbr, pattern.pattern[6:-7], stdLabel, defLabel))
|
|
263
|
-
num1wayConcepts += 1
|
|
264
|
-
|
|
265
|
-
csvFile.close()
|
|
266
|
-
|
|
267
|
-
dts.log('INFO-SEMANTIC', "info:saveSecDtsTagMatches",
|
|
268
|
-
_("SecDtsTagMatches entry %(entryFile)s has %(numberOfTwoWayPriItems)s two way primary items, %(numberOfOneWayPriItems)s one way primary items, %(numberOfTwoWayMembers)s two way members in output file %(secDtsTagMatchesFile)s."),
|
|
269
|
-
modelObject=dts,
|
|
270
|
-
entryFile=dts.uri,
|
|
271
|
-
numberOfTwoWayPriItems=num2wayConcepts,
|
|
272
|
-
numberOfOneWayPriItems=num1wayConcepts,
|
|
273
|
-
numberOfTwoWayMembers=num2wayMembers,
|
|
274
|
-
secDtsTagMatchesFile=secDtsTagMatchesFile)
|
|
275
|
-
|
|
276
|
-
final(dts)
|
|
277
|
-
|
|
278
|
-
def saveDtsMatchesMenuEntender(cntlr, menu, *args, **kwargs):
|
|
279
|
-
# Extend menu with an item for the savedts plugin
|
|
280
|
-
menu.add_command(label="Save SEC tag matches",
|
|
281
|
-
underline=0,
|
|
282
|
-
command=lambda: saveDtsMatchesMenuCommand(cntlr) )
|
|
283
|
-
|
|
284
|
-
def saveDtsMatchesMenuCommand(cntlr):
|
|
285
|
-
# save DTS menu item has been invoked
|
|
286
|
-
if cntlr.modelManager is None or cntlr.modelManager.modelXbrl is None:
|
|
287
|
-
cntlr.addToLog("No taxonomy loaded.")
|
|
288
|
-
return
|
|
289
|
-
|
|
290
|
-
# get file name into which to save log file while in foreground thread
|
|
291
|
-
secDtsTagMatchesFile = cntlr.uiFileDialog("save",
|
|
292
|
-
title=_("Save SEC DTS tag matches file"),
|
|
293
|
-
filetypes=[(_("DTS tag matches .csv file"), "*.csv")],
|
|
294
|
-
defaultextension=".txt")
|
|
295
|
-
if not secDtsTagMatchesFile:
|
|
296
|
-
return False
|
|
297
|
-
|
|
298
|
-
try:
|
|
299
|
-
saveDtsMatches(cntlr.modelManager.modelXbrl, secDtsTagMatchesFile)
|
|
300
|
-
except Exception as ex:
|
|
301
|
-
dts = cntlr.modelManager.modelXbrl
|
|
302
|
-
dts.error("exception",
|
|
303
|
-
_("SEC DTS Tags Matches exception: %(error)s"), error=ex,
|
|
304
|
-
modelXbrl=dts,
|
|
305
|
-
exc_info=True)
|
|
306
|
-
|
|
307
|
-
def saveDtsMatchesCommandLineOptionExtender(parser, *args, **kwargs):
|
|
308
|
-
# extend command line options with a save DTS option
|
|
309
|
-
parser.add_option("--save-sec-tag-dts-matches",
|
|
310
|
-
action="store",
|
|
311
|
-
dest="secDtsTagMatchesFile",
|
|
312
|
-
help=_("Save SEC DTS tag matches CSV file."))
|
|
313
|
-
|
|
314
|
-
def saveDtsMatchesCommandLineXbrlRun(cntlr, options, modelXbrl, *args, **kwargs):
|
|
315
|
-
# extend XBRL-loaded run processing for this option
|
|
316
|
-
if getattr(options, "secDtsTagMatchesFile", False):
|
|
317
|
-
if cntlr.modelManager is None or cntlr.modelManager.modelXbrl is None:
|
|
318
|
-
cntlr.addToLog("No taxonomy loaded.")
|
|
319
|
-
return
|
|
320
|
-
saveDtsMatches(cntlr.modelManager.modelXbrl, options.secDtsTagMatchesFile)
|
|
321
|
-
|
|
322
|
-
__pluginInfo__ = {
|
|
323
|
-
# Do not use _( ) in pluginInfo itself (it is applied later, after loading
|
|
324
|
-
'name': 'Validate US SEC Tagging',
|
|
325
|
-
'version': '0.9',
|
|
326
|
-
'description': '''US SEC Tagging Validation. Includes non-negative rules.''',
|
|
327
|
-
'license': 'Apache-2',
|
|
328
|
-
'author': 'Ewe S. Gap',
|
|
329
|
-
'copyright': copyrightLabel,
|
|
330
|
-
# classes of mount points (required)
|
|
331
|
-
'Validate.EFM.Start': setup,
|
|
332
|
-
'Validate.EFM.Fact': factCheck,
|
|
333
|
-
'Validate.EFM.Finally': final,
|
|
334
|
-
'CntlrWinMain.Menu.Tools': saveDtsMatchesMenuEntender,
|
|
335
|
-
'CntlrCmdLine.Options': saveDtsMatchesCommandLineOptionExtender,
|
|
336
|
-
'CntlrCmdLine.Xbrl.Run': saveDtsMatchesCommandLineXbrlRun,
|
|
337
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
See COPYRIGHT.md for copyright information.
|
|
3
|
-
'''
|
|
4
|
-
import os
|
|
5
|
-
from arelle import ModelDocument, XbrlConst
|
|
6
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
7
|
-
|
|
8
|
-
def dislosureSystemTypes(disclosureSystem, *args, **kwargs):
|
|
9
|
-
# return ((disclosure system name, variable name), ...)
|
|
10
|
-
return (("XDC", "XDCplugin"),)
|
|
11
|
-
|
|
12
|
-
def disclosureSystemConfigURL(disclosureSystem, *args, **kwargs):
|
|
13
|
-
return os.path.join(os.path.dirname(__file__), "config.xml")
|
|
14
|
-
|
|
15
|
-
def validateXbrlStart(val, parameters=None, *args, **kwargs):
|
|
16
|
-
val.validateXDCplugin = val.validateDisclosureSystem and getattr(val.disclosureSystem, "XDCplugin", False)
|
|
17
|
-
if not (val.validateXDCplugin):
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def validateXbrlFinally(val, *args, **kwargs):
|
|
22
|
-
if not (val.validateXDCplugin):
|
|
23
|
-
return
|
|
24
|
-
|
|
25
|
-
modelXbrl = val.modelXbrl
|
|
26
|
-
modelDocument = modelXbrl.modelDocument
|
|
27
|
-
|
|
28
|
-
_statusMsg = _("validating {0} filing rules").format(val.disclosureSystem.name)
|
|
29
|
-
modelXbrl.profileActivity()
|
|
30
|
-
modelXbrl.modelManager.showStatus(_statusMsg)
|
|
31
|
-
|
|
32
|
-
if modelDocument.type in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL):
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
parentChildRels = modelXbrl.relationshipSet(XbrlConst.parentChild)
|
|
36
|
-
referenceRels = modelXbrl.relationshipSet(XbrlConst.conceptReference)
|
|
37
|
-
|
|
38
|
-
for qn, facts in modelXbrl.factsByQname.items():
|
|
39
|
-
concept = modelXbrl.qnameConcepts[qn]
|
|
40
|
-
if not parentChildRels.toModelObject(concept):
|
|
41
|
-
modelXbrl.error("XDC:factElementNotPresented",
|
|
42
|
-
_("Element %(concept)s is used in a fact in the instance, but is not in any presentation relationships."),
|
|
43
|
-
modelObject=facts, concept=qn)
|
|
44
|
-
|
|
45
|
-
requiredConcepts = set(preRel.toModelObject.qname
|
|
46
|
-
for preRel in parentChildRels.modelRelationships
|
|
47
|
-
for refRel in referenceRels.fromModelObject(preRel.toModelObject)
|
|
48
|
-
if refRel.toModelObject.role == "http://www.changhong.com/XDC/role/definitionalAttribute"
|
|
49
|
-
for refPart in refRel.toModelObject.iterchildren()
|
|
50
|
-
if refPart.localName == "RequiredInDocument"
|
|
51
|
-
if refPart.textValue.strip().lower() == "true")
|
|
52
|
-
|
|
53
|
-
missingConcepts = requiredConcepts - modelXbrl.factsByQname.keys()
|
|
54
|
-
if missingConcepts:
|
|
55
|
-
modelXbrl.error("XDC:missingRequiredFacts",
|
|
56
|
-
_("Required facts missing from document: %(concepts)s."),
|
|
57
|
-
modelObject=modelXbrl, concepts=", ".join(sorted(str(qn) for qn in missingConcepts)))
|
|
58
|
-
|
|
59
|
-
modelXbrl.profileActivity(_statusMsg, minTimeToShow=0.0)
|
|
60
|
-
modelXbrl.modelManager.showStatus(None)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
__pluginInfo__ = {
|
|
64
|
-
# Do not use _( ) in pluginInfo itself (it is applied later, after loading
|
|
65
|
-
'name': 'Validate XDC',
|
|
66
|
-
'version': '1.0',
|
|
67
|
-
'description': '''XDC Validation.''',
|
|
68
|
-
'license': 'Apache-2',
|
|
69
|
-
'author': authorLabel,
|
|
70
|
-
'copyright': copyrightLabel,
|
|
71
|
-
# classes of mount points (required)
|
|
72
|
-
'DisclosureSystem.Types': dislosureSystemTypes,
|
|
73
|
-
'DisclosureSystem.ConfigURL': disclosureSystemConfigURL,
|
|
74
|
-
|
|
75
|
-
'Validate.XBRL.Start': validateXbrlStart,
|
|
76
|
-
'Validate.XBRL.Finally': validateXbrlFinally,
|
|
77
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<DisclosureSystems xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
-
xsi:noNamespaceSchemaLocation="../../../config/disclosuresystems.xsd" >
|
|
4
|
-
<!-- see ../config/disclosuresystem.xml for full comments -->
|
|
5
|
-
|
|
6
|
-
<DisclosureSystem
|
|
7
|
-
names="XDC (China)|xdc"
|
|
8
|
-
description="XDC Validation Checks\n
|
|
9
|
-
Default language cn\n
|
|
10
|
-
Disallowed references are processed"
|
|
11
|
-
validationType="XDC"
|
|
12
|
-
blockDisallowedReferences="false"
|
|
13
|
-
defaultXmlLang="cn"
|
|
14
|
-
defaultLanguage="Chinese"
|
|
15
|
-
validateFileText="false"
|
|
16
|
-
contextElement="segment"
|
|
17
|
-
/>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
</DisclosureSystems>
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
XBRL Formula language syntax checker using ebnf parser
|
|
3
|
-
|
|
4
|
-
for execution of xf formula, please instead use plug-in formulaLoader.py
|
|
5
|
-
|
|
6
|
-
requires xf.py from XII conformance-formula/tf/syntax
|
|
7
|
-
|
|
8
|
-
See COPYRIGHT.md for copyright information.
|
|
9
|
-
'''
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
from arelle.Version import authorLabel, copyrightLabel
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# interfaces for Arelle plugin operation
|
|
16
|
-
def isXfLoadable(modelXbrl, mappedUri, normalizedUri, filepath, **kwargs):
|
|
17
|
-
return os.path.splitext(mappedUri)[1] == ".xf"
|
|
18
|
-
|
|
19
|
-
def xfLoader(modelXbrl, mappedUri, filepath, *args, **kwargs):
|
|
20
|
-
if os.path.splitext(filepath)[1] != ".xf":
|
|
21
|
-
return None # not an XBRL formula syntax file
|
|
22
|
-
|
|
23
|
-
cntlr = modelXbrl.modelManager.cntlr
|
|
24
|
-
cntlr.showStatus(_("Loading XBRL Formula file: {0}").format(os.path.basename(filepath)))
|
|
25
|
-
|
|
26
|
-
try:
|
|
27
|
-
import tatsu.exceptions
|
|
28
|
-
except ImportError:
|
|
29
|
-
modelXbrl.error("xf:missingTatsu",
|
|
30
|
-
"Python library module Tatsu must be installed.")
|
|
31
|
-
from .xf import XFParser
|
|
32
|
-
with open(filepath, "r") as f:
|
|
33
|
-
xf = f.read()
|
|
34
|
-
parser = XFParser()
|
|
35
|
-
try:
|
|
36
|
-
ast = parser.parse(xf, rule_name='module')
|
|
37
|
-
except tatsu.exceptions.FailedParse as err:
|
|
38
|
-
modelXbrl.error("xf:syntax",
|
|
39
|
-
"Unrecoverable error: %(error)s",
|
|
40
|
-
modelObject=modelXbrl, error=err)
|
|
41
|
-
|
|
42
|
-
# create dummy modelDocument for successful plugin execution by ModelDopcument
|
|
43
|
-
from arelle.ModelDocument import Type, create as createModelDocument
|
|
44
|
-
doc = createModelDocument(modelXbrl, Type.LINKBASE, filepath, documentEncoding="utf-8", initialXml='''
|
|
45
|
-
<!-- Dummy linkbase -->
|
|
46
|
-
<link:linkbase
|
|
47
|
-
xmlns:link="http://www.xbrl.org/2003/linkbase"
|
|
48
|
-
xsi:schemaLocation="http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd"
|
|
49
|
-
/>
|
|
50
|
-
''')
|
|
51
|
-
return doc
|
|
52
|
-
|
|
53
|
-
__pluginInfo__ = {
|
|
54
|
-
# Do not use _( ) in pluginInfo itself (it is applied later, after loading
|
|
55
|
-
'name': 'Validate XF Syntax',
|
|
56
|
-
'version': '1.0',
|
|
57
|
-
'description': '''XBRL Formula XF Syntax Validation only, not execution of formulae.''',
|
|
58
|
-
'license': 'Apache-2',
|
|
59
|
-
'author': authorLabel,
|
|
60
|
-
'copyright': copyrightLabel,
|
|
61
|
-
# classes of mount points (required)
|
|
62
|
-
'ModelDocument.IsPullLoadable': isXfLoadable,
|
|
63
|
-
'ModelDocument.PullLoader': xfLoader,
|
|
64
|
-
}
|