arelle-release 2.37.46__py3-none-any.whl → 2.37.48__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 +10 -1
- arelle/ErrorManager.py +14 -5
- arelle/ModelObjectFactory.py +18 -2
- arelle/Validate.py +4 -0
- arelle/_version.py +2 -2
- arelle/plugin/validate/DBA/ValidationPluginExtension.py +2 -1
- arelle/plugin/validate/EDINET/ControllerPluginData.py +84 -0
- arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +0 -114
- arelle/plugin/validate/EDINET/UploadContents.py +17 -0
- arelle/plugin/validate/EDINET/ValidationPluginExtension.py +8 -2
- arelle/plugin/validate/EDINET/__init__.py +5 -0
- arelle/plugin/validate/EDINET/rules/upload.py +66 -75
- arelle/plugin/validate/NL/ValidationPluginExtension.py +3 -1
- arelle/plugin/validate/ROS/ValidationPluginExtension.py +3 -1
- arelle/utils/PluginHooks.py +32 -0
- arelle/utils/validate/ValidationPlugin.py +54 -8
- {arelle_release-2.37.46.dist-info → arelle_release-2.37.48.dist-info}/METADATA +1 -1
- {arelle_release-2.37.46.dist-info → arelle_release-2.37.48.dist-info}/RECORD +22 -106
- 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/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.37.48.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.46.dist-info → arelle_release-2.37.48.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.46.dist-info → arelle_release-2.37.48.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.46.dist-info → arelle_release-2.37.48.dist-info}/top_level.txt +0 -0
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
sphinxContext provides the validation and execution context for Sphinx language expressions.
|
|
3
|
-
|
|
4
|
-
See COPYRIGHT.md for copyright information.
|
|
5
|
-
|
|
6
|
-
Sphinx is a Rules Language for XBRL described by a Sphinx 2 Primer
|
|
7
|
-
(c) Copyright 2012 CoreFiling, Oxford UK.
|
|
8
|
-
Sphinx copyright applies to the Sphinx language, not to this software.
|
|
9
|
-
Workiva, Inc. conveys neither rights nor license for the Sphinx language.
|
|
10
|
-
'''
|
|
11
|
-
|
|
12
|
-
from collections import OrderedDict
|
|
13
|
-
from .SphinxParser import astNode, astWith
|
|
14
|
-
from arelle.ModelFormulaObject import aspectModels, Aspect, aspectStr
|
|
15
|
-
from arelle.ModelInstanceObject import ModelFact, ModelDimensionValue
|
|
16
|
-
from arelle.formula.FormulaEvaluator import implicitFilter, aspectsMatch
|
|
17
|
-
from arelle.ModelValue import QName
|
|
18
|
-
from arelle.ModelXbrl import DEFAULT, NONDEFAULT
|
|
19
|
-
from arelle import XmlUtil
|
|
20
|
-
|
|
21
|
-
class SphinxContext:
|
|
22
|
-
def __init__(self, sphinxProgs, modelXbrl=None):
|
|
23
|
-
self.modelXbrl = modelXbrl # the DTS and input instance (if any)
|
|
24
|
-
self.sphinxProgs = sphinxProgs
|
|
25
|
-
self.rules = []
|
|
26
|
-
self.transformQnames = {}
|
|
27
|
-
self.transformNamespaces = {}
|
|
28
|
-
self.constants = {}
|
|
29
|
-
self.taggedConstants = {}
|
|
30
|
-
self.functions = {}
|
|
31
|
-
self.preconditions = {}
|
|
32
|
-
self.localVariables = {}
|
|
33
|
-
self.tags = {}
|
|
34
|
-
self.hyperspaceBindings = None
|
|
35
|
-
self.staticSeverity = None
|
|
36
|
-
self.dynamicSeverity = None
|
|
37
|
-
self.dimensionIsExplicit = {} # qname of dimension (axis), True if explicit, False if typed
|
|
38
|
-
if modelXbrl is not None:
|
|
39
|
-
self.formulaOptions = modelXbrl.modelManager.formulaOptions
|
|
40
|
-
self.defaultDimensionAspects = set(modelXbrl.qnameDimensionDefaults.keys())
|
|
41
|
-
|
|
42
|
-
def close(self):
|
|
43
|
-
# dereference grammar
|
|
44
|
-
for prog in self.sphinxProgs:
|
|
45
|
-
for node in prog:
|
|
46
|
-
if isinstance(node, astNode):
|
|
47
|
-
node.clear()
|
|
48
|
-
prog.clear
|
|
49
|
-
del self.sphinxProgs[:]
|
|
50
|
-
self.__dict__.clear() # delete local attributes
|
|
51
|
-
|
|
52
|
-
class HyperspaceBindings:
|
|
53
|
-
def __init__(self, sphinxContext):
|
|
54
|
-
self.sCtx = sphinxContext
|
|
55
|
-
self.parentHyperspaceBindings = sphinxContext.hyperspaceBindings
|
|
56
|
-
sphinxContext.hyperspaceBindings = self
|
|
57
|
-
self.hyperspaceBindings = []
|
|
58
|
-
self.nodeBindings = {}
|
|
59
|
-
self.withRestrictionBindings = []
|
|
60
|
-
self.aspectBoundFacts = {}
|
|
61
|
-
self.aggregationNode = None
|
|
62
|
-
self.isValuesIteration = False
|
|
63
|
-
|
|
64
|
-
def close(self):
|
|
65
|
-
if self.sCtx.hyperspaceBindings is self:
|
|
66
|
-
self.sCtx.hyperspaceBindings = self.parentHyperspaceBindings
|
|
67
|
-
for hsBinding in self.hyperspaceBindings:
|
|
68
|
-
hsBinding.close()
|
|
69
|
-
self.__dict__.clear() # dereference
|
|
70
|
-
|
|
71
|
-
def nodeBinding(self, node, isWithRestrictionNode=False):
|
|
72
|
-
if node in self.nodeBindings:
|
|
73
|
-
return self.nodeBindings[node]
|
|
74
|
-
if self.aggregationNode and self.aggregationNode not in self.nodeBindings and not self.isValuesIteration:
|
|
75
|
-
agrgBalNode = HyperspaceBinding(self, node, isBalancingBinding=True)
|
|
76
|
-
self.nodeBindings[self.aggregationNode] = agrgBalNode
|
|
77
|
-
nodeBinding = HyperspaceBinding(self, node, isWithRestrictionNode=isWithRestrictionNode)
|
|
78
|
-
self.nodeBindings[node] = nodeBinding
|
|
79
|
-
self.hyperspaceBindings.append(nodeBinding)
|
|
80
|
-
return nodeBinding
|
|
81
|
-
|
|
82
|
-
def forBinding(self, node):
|
|
83
|
-
if node in self.nodeBindings:
|
|
84
|
-
return self.nodeBindings[node]
|
|
85
|
-
nodeBinding = ForBinding(self, node)
|
|
86
|
-
self.nodeBindings[node] = nodeBinding
|
|
87
|
-
self.hyperspaceBindings.append(nodeBinding)
|
|
88
|
-
return nodeBinding
|
|
89
|
-
|
|
90
|
-
def next(self, iterateAbove=-1, bindingsLen=-1):
|
|
91
|
-
# iterate hyperspace bindings
|
|
92
|
-
if not self.hyperspaceBindings:
|
|
93
|
-
raise StopIteration
|
|
94
|
-
hsBsToReset = []
|
|
95
|
-
if bindingsLen == -1:
|
|
96
|
-
bindingsLen = len(self.hyperspaceBindings)
|
|
97
|
-
for iHsB in range(bindingsLen - 1, iterateAbove, -1):
|
|
98
|
-
hsB = self.hyperspaceBindings[iHsB]
|
|
99
|
-
try:
|
|
100
|
-
hsB.next()
|
|
101
|
-
for hsB in hsBsToReset:
|
|
102
|
-
hsB.reset()
|
|
103
|
-
return # hsB has another value to return
|
|
104
|
-
except StopIteration:
|
|
105
|
-
hsBsToReset.insert(0, hsB) # reset after outer iterator advanced
|
|
106
|
-
raise StopIteration # no more outermost loop of iteration
|
|
107
|
-
|
|
108
|
-
@property
|
|
109
|
-
def boundFacts(self):
|
|
110
|
-
return [binding.yieldedFact
|
|
111
|
-
for binding in self.hyperspaceBindings
|
|
112
|
-
if isinstance(binding, HyperspaceBinding) and
|
|
113
|
-
not binding.fallenBack and binding.yieldedFact is not None]
|
|
114
|
-
|
|
115
|
-
class HyperspaceBinding:
|
|
116
|
-
def __init__(self, hyperspaceBindings, node, fallback=False, isWithRestrictionNode=False, isBalancingBinding=False):
|
|
117
|
-
self.hyperspaceBindings = hyperspaceBindings
|
|
118
|
-
self.sCtx = hyperspaceBindings.sCtx
|
|
119
|
-
self.node = node
|
|
120
|
-
self.isWithRestrictionNode = isWithRestrictionNode
|
|
121
|
-
self.isBalancingBinding = isBalancingBinding
|
|
122
|
-
self.isValuesIteration = hyperspaceBindings.isValuesIteration
|
|
123
|
-
self.fallback = fallback
|
|
124
|
-
self.aspectsQualified = set()
|
|
125
|
-
self.aspectsDefined = set(aspectModels["dimensional"])
|
|
126
|
-
if hyperspaceBindings.withRestrictionBindings:
|
|
127
|
-
withAspectsQualified = hyperspaceBindings.withRestrictionBindings[-1].aspectsQualified
|
|
128
|
-
else:
|
|
129
|
-
withAspectsQualified = set()
|
|
130
|
-
# axes from macros need to be expanded
|
|
131
|
-
self.aspectAxisTuples = []
|
|
132
|
-
self.axesAspects = set()
|
|
133
|
-
for hsAxis in node.axes:
|
|
134
|
-
if hsAxis.aspect: # no aspect if just a where clause
|
|
135
|
-
aspect = evaluate(hsAxis.aspect, self.sCtx, value=True)
|
|
136
|
-
if aspect not in self.aspectsDefined and not isinstance(aspect, QName):
|
|
137
|
-
raise SphinxException(node, "sphinx:aspectValue",
|
|
138
|
-
_("Hyperspace aspect indeterminate %(aspect)s"),
|
|
139
|
-
aspect=aspect)
|
|
140
|
-
if isinstance(aspect, QName):
|
|
141
|
-
if aspect not in self.sCtx.dimensionIsExplicit: # probably dynamic macro aspect
|
|
142
|
-
concept = self.sCtx.modelXbrl.qnameConcepts.get(aspect)
|
|
143
|
-
if concept is None or not concept.isDimensionItem:
|
|
144
|
-
raise SphinxException(node, "sphinxDynamicHyperspace:axisNotDimension",
|
|
145
|
-
_("Axis aspect is not a dimension in the DTS %(aspect)s"),
|
|
146
|
-
aspect=aspect)
|
|
147
|
-
self.sCtx.dimensionIsExplicit[aspect] = concept.isExplicitDimension
|
|
148
|
-
self.axesAspects.add(aspect) # resolved aspect value
|
|
149
|
-
self.aspectAxisTuples.append( (aspect, hsAxis) )
|
|
150
|
-
self.aspectsQualified = self.axesAspects | withAspectsQualified
|
|
151
|
-
self.reset() # will raise StopIteration if no facts or fallback
|
|
152
|
-
|
|
153
|
-
def close(self):
|
|
154
|
-
self.__dict__.clear() # dereference
|
|
155
|
-
|
|
156
|
-
@property
|
|
157
|
-
def value(self):
|
|
158
|
-
if self.fallenBack:
|
|
159
|
-
return None
|
|
160
|
-
if self.yieldedFact is not None:
|
|
161
|
-
return self.yieldedFact.xValue
|
|
162
|
-
return None
|
|
163
|
-
|
|
164
|
-
@property
|
|
165
|
-
def var(self): # used in implicitFilter winnowing trace
|
|
166
|
-
return []
|
|
167
|
-
|
|
168
|
-
@property
|
|
169
|
-
def qname(self): # used in implicitFilter winnowing trace
|
|
170
|
-
return ''
|
|
171
|
-
|
|
172
|
-
def __repr__(self):
|
|
173
|
-
if self.fallenBack:
|
|
174
|
-
return "fallen-back"
|
|
175
|
-
if self.yieldedFact is not None:
|
|
176
|
-
return self.yieldedFact.__repr__()
|
|
177
|
-
return "none"
|
|
178
|
-
|
|
179
|
-
def reset(self):
|
|
180
|
-
# start with all facts
|
|
181
|
-
if self.hyperspaceBindings.withRestrictionBindings:
|
|
182
|
-
facts = self.hyperspaceBindings.withRestrictionBindings[-1].yieldedFactsPartition
|
|
183
|
-
else:
|
|
184
|
-
facts = self.sCtx.modelXbrl.nonNilFactsInInstance
|
|
185
|
-
if self.sCtx.formulaOptions.traceVariableFilterWinnowing:
|
|
186
|
-
self.sCtx.modelXbrl.info("sphinx:trace",
|
|
187
|
-
_("Hyperspace %(variable)s binding: start with %(factCount)s facts"),
|
|
188
|
-
sourceFileLine=self.node.sourceFileLine, variable=str(self.node), factCount=len(facts))
|
|
189
|
-
# filter by hyperspace aspects
|
|
190
|
-
facts = self.filterFacts(facts)
|
|
191
|
-
for fact in facts:
|
|
192
|
-
if fact.isItem:
|
|
193
|
-
self.aspectsDefined |= fact.context.dimAspects(self.sCtx.defaultDimensionAspects)
|
|
194
|
-
self.unQualifiedAspects = self.aspectsDefined - self.aspectsQualified - {Aspect.DIMENSIONS}
|
|
195
|
-
# implicitly filter by prior uncoveredAspectFacts
|
|
196
|
-
if self.hyperspaceBindings.aspectBoundFacts and not self.isValuesIteration:
|
|
197
|
-
facts = implicitFilter(self.sCtx, self, facts, self.unQualifiedAspects, self.hyperspaceBindings.aspectBoundFacts)
|
|
198
|
-
if self.sCtx.formulaOptions.traceVariableFiltersResult:
|
|
199
|
-
self.sCtx.modelXbrl.info("sphinx:trace",
|
|
200
|
-
_("Hyperspace %(variable)s binding: filters result %(factCount)s facts"),
|
|
201
|
-
sourceFileLine=self.node.sourceFileLine, variable=str(self.node), factCount=len(facts))
|
|
202
|
-
if self.isWithRestrictionNode: # if withNode, combine facts into partitions by qualified aspects
|
|
203
|
-
factsPartitions = []
|
|
204
|
-
for fact in facts:
|
|
205
|
-
matched = False
|
|
206
|
-
for partition in factsPartitions:
|
|
207
|
-
if aspectsMatch(self.sCtx, fact, partition[0], self.aspectsQualified):
|
|
208
|
-
partition.append(fact)
|
|
209
|
-
matched = True
|
|
210
|
-
break
|
|
211
|
-
if not matched:
|
|
212
|
-
factsPartitions.append([fact,])
|
|
213
|
-
self.factIter = iter([set(p) for p in factsPartitions]) # must be sets
|
|
214
|
-
self.yieldedFactsPartition = []
|
|
215
|
-
else: # just a hyperspaceExpression node
|
|
216
|
-
self.factIter = iter(facts)
|
|
217
|
-
self.yieldedFact = None
|
|
218
|
-
self.fallenBack = False
|
|
219
|
-
self.next()
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
def next(self): # will raise StopIteration if no (more) facts or fallback
|
|
223
|
-
uncoveredAspectFacts = self.hyperspaceBindings.aspectBoundFacts
|
|
224
|
-
if self.yieldedFact is not None and self.hyperspaceBindings.aggregationNode is None:
|
|
225
|
-
for aspect, priorFact in self.evaluationContributedUncoveredAspects.items():
|
|
226
|
-
if priorFact == "none":
|
|
227
|
-
del uncoveredAspectFacts[aspect]
|
|
228
|
-
else:
|
|
229
|
-
uncoveredAspectFacts[aspect] = priorFact
|
|
230
|
-
self.evaluationContributedUncoveredAspects.clear()
|
|
231
|
-
try:
|
|
232
|
-
if self.isWithRestrictionNode:
|
|
233
|
-
self.yieldedFactsPartition = next(self.factIter)
|
|
234
|
-
for self.yieldedFact in self.yieldedFactsPartition:
|
|
235
|
-
break
|
|
236
|
-
else:
|
|
237
|
-
self.yieldedFact = next(self.factIter)
|
|
238
|
-
self.evaluationContributedUncoveredAspects = {}
|
|
239
|
-
if not self.isValuesIteration:
|
|
240
|
-
for aspect in self.unQualifiedAspects: # covered aspects may not be defined e.g., test 12062 v11, undefined aspect is a complemented aspect
|
|
241
|
-
if uncoveredAspectFacts.get(aspect) is None:
|
|
242
|
-
self.evaluationContributedUncoveredAspects[aspect] = uncoveredAspectFacts.get(aspect,"none")
|
|
243
|
-
uncoveredAspectFacts[aspect] = None if aspect in self.axesAspects else self.yieldedFact
|
|
244
|
-
if self.sCtx.formulaOptions.traceVariableFiltersResult:
|
|
245
|
-
self.sCtx.modelXbrl.info("sphinx:trace",
|
|
246
|
-
_("Hyperspace %(variable)s: bound value %(result)s"),
|
|
247
|
-
sourceFileLine=self.node.sourceFileLine, variable=str(self.node), result=str(self.yieldedFact))
|
|
248
|
-
except StopIteration:
|
|
249
|
-
self.yieldedFact = None
|
|
250
|
-
if self.isWithRestrictionNode:
|
|
251
|
-
self.yieldedFactsPartition = []
|
|
252
|
-
if self.fallback and not self.fallenBack:
|
|
253
|
-
self.fallenBack = True
|
|
254
|
-
if self.sCtx.formulaOptions.traceVariableExpressionResult:
|
|
255
|
-
self.sCtx.modelXbrl.info("sphinx:trace",
|
|
256
|
-
_("Hyperspace %(variable)s: fallbackValue result %(result)s"),
|
|
257
|
-
sourceFileLine=self.node.sourceFileLine, variable=str(self.node), result=0)
|
|
258
|
-
else:
|
|
259
|
-
raise StopIteration
|
|
260
|
-
|
|
261
|
-
def filterFacts(self, facts):
|
|
262
|
-
modelXbrl = self.sCtx.modelXbrl
|
|
263
|
-
# process with bindings and this node
|
|
264
|
-
for i, aspectAxis in enumerate(self.aspectAxisTuples):
|
|
265
|
-
aspect, hsAxis = aspectAxis
|
|
266
|
-
# value is an astHyperspaceAxis
|
|
267
|
-
if hsAxis.restriction:
|
|
268
|
-
restriction = evaluate(hsAxis.restriction, self.sCtx, value=True)
|
|
269
|
-
if aspect == Aspect.CONCEPT:
|
|
270
|
-
aspectQualifiedFacts = [modelXbrl.factsByQname[qn]
|
|
271
|
-
for qn in restriction
|
|
272
|
-
if isinstance(qn, QName)]
|
|
273
|
-
facts = facts & set.union(*aspectQualifiedFacts) if aspectQualifiedFacts else set()
|
|
274
|
-
elif aspect == Aspect.PERIOD:
|
|
275
|
-
facts = set(f for f in facts if isPeriodEqualTo(f, restriction))
|
|
276
|
-
elif aspect == Aspect.ENTITY_IDENTIFIER:
|
|
277
|
-
facts = set(f for f in facts if isEntityIdentifierEqualTo(f, restriction))
|
|
278
|
-
elif isinstance(aspect, QName):
|
|
279
|
-
if self.sCtx.dimensionIsExplicit.get(aspect):
|
|
280
|
-
# explicit dim facts (value None will match the default member)
|
|
281
|
-
aspectQualifiedFacts = []
|
|
282
|
-
for qn in restriction:
|
|
283
|
-
if self.isBalancingBinding: # complement dimension for aggregation balancing binding
|
|
284
|
-
if isinstance(qn, QName) or qn is NONDEFAULT:
|
|
285
|
-
qn = DEFAULT
|
|
286
|
-
else:
|
|
287
|
-
qn = NONDEFAULT
|
|
288
|
-
if qn is NONE:
|
|
289
|
-
qn = DEFAULT
|
|
290
|
-
elif not (isinstance(qn, QName) or qn is DEFAULT or qn is NONDEFAULT):
|
|
291
|
-
continue
|
|
292
|
-
aspectQualifiedFacts.append(modelXbrl.factsByDimMemQname(aspect, qn))
|
|
293
|
-
facts = facts & set.union(*aspectQualifiedFacts) if aspectQualifiedFacts else set()
|
|
294
|
-
else:
|
|
295
|
-
facts = facts & set(fact
|
|
296
|
-
for fact in facts
|
|
297
|
-
for typedDimValue in hsAxis.restriction
|
|
298
|
-
if typedDimTest(aspect, typedDimValue, fact))
|
|
299
|
-
if hsAxis.whereExpr and facts: # process where against facts passing restriction
|
|
300
|
-
whereMatchedFacts = set()
|
|
301
|
-
asVars = set()
|
|
302
|
-
for fact in facts:
|
|
303
|
-
for asAspectAxis in self.aspectAxisTuples[0:i+1]:
|
|
304
|
-
asAspect, asHsAxis = asAspectAxis
|
|
305
|
-
if asHsAxis.asVariableName:
|
|
306
|
-
self.sCtx.localVariables[asHsAxis.asVariableName] = factAspectValue(fact, asAspect)
|
|
307
|
-
asVars.add(asHsAxis.asVariableName)
|
|
308
|
-
self.sCtx.localVariables["item"] = fact
|
|
309
|
-
if evaluate(hsAxis.whereExpr, self.sCtx) ^ self.isBalancingBinding:
|
|
310
|
-
whereMatchedFacts.add(fact)
|
|
311
|
-
del self.sCtx.localVariables["item"]
|
|
312
|
-
for asVar in asVars:
|
|
313
|
-
del self.sCtx.localVariables[asVar]
|
|
314
|
-
facts = whereMatchedFacts
|
|
315
|
-
if self.sCtx.formulaOptions.traceVariableFilterWinnowing:
|
|
316
|
-
self.sCtx.modelXbrl.info("sphinx:trace",
|
|
317
|
-
_("Hyperspace %(variable)s: %(filter)s filter passes %(factCount)s facts"),
|
|
318
|
-
sourceFileLine=self.node.sourceFileLine, variable=str(self.node), filter=aspectStr(aspect), factCount=len(facts))
|
|
319
|
-
if self.node.isClosed: # winnow out non-qualified dimension breakdowns
|
|
320
|
-
facts = facts - set(fact
|
|
321
|
-
for fact in facts
|
|
322
|
-
if fact.dimAspects - self.aspectsQualified )
|
|
323
|
-
if self.sCtx.formulaOptions.traceVariableFilterWinnowing:
|
|
324
|
-
self.sCtx.modelXbrl.info("sphinx:trace",
|
|
325
|
-
_("Hyperspace %(variable)s: closed selection filter passes %(factCount)s facts"),
|
|
326
|
-
sourceFileLine=self.node.sourceFileLine, variable=str(self.node), factCount=len(facts))
|
|
327
|
-
return facts
|
|
328
|
-
|
|
329
|
-
def isPeriodEqualTo(fact, periodRestriction):
|
|
330
|
-
context = fact.context
|
|
331
|
-
if context is not None:
|
|
332
|
-
for period in periodRestriction:
|
|
333
|
-
if ((context.isInstantPeriod and context.instantDatetime == period) or
|
|
334
|
-
(context.isStartEndPeriod and (context.startDatetime, context.endDatetime) == period) or
|
|
335
|
-
(context.isForeverPeriod and period == (None, None))):
|
|
336
|
-
return True
|
|
337
|
-
return False
|
|
338
|
-
|
|
339
|
-
def isEntityIdentifierEqualTo(fact, entityIdentifierRestriction):
|
|
340
|
-
context = fact.context
|
|
341
|
-
if context is not None:
|
|
342
|
-
for entityIdentifier in entityIdentifierRestriction:
|
|
343
|
-
if context.entityIdentifier == entityIdentifier:
|
|
344
|
-
return True
|
|
345
|
-
return False
|
|
346
|
-
|
|
347
|
-
def typedDimTest(aspect, value, fact):
|
|
348
|
-
if fact.context is None:
|
|
349
|
-
return False
|
|
350
|
-
modelDim = fact.context.dimValue(aspect)
|
|
351
|
-
if isinstance(modelDim, ModelDimensionValue):
|
|
352
|
-
memElt = modelDim.typedMember
|
|
353
|
-
if memElt is None or memElt.get("{http://www.w3.org/2001/XMLSchema-instance}nil") == "true":
|
|
354
|
-
return value is NONE or value is DEFAULT
|
|
355
|
-
if value is NONDEFAULT:
|
|
356
|
-
return True
|
|
357
|
-
return memElt.textValue == value
|
|
358
|
-
else:
|
|
359
|
-
return value is NONE or value is DEFAULT
|
|
360
|
-
|
|
361
|
-
class ForBinding:
|
|
362
|
-
def __init__(self, hyperspaceBindings, node):
|
|
363
|
-
self.hyperspaceBindings = hyperspaceBindings
|
|
364
|
-
self.sCtx = hyperspaceBindings.sCtx
|
|
365
|
-
self.node = node
|
|
366
|
-
self.collection = evaluate(node.collectionExpr, self.sCtx)
|
|
367
|
-
self.reset() # will raise StopIteration if no for items
|
|
368
|
-
|
|
369
|
-
def close(self):
|
|
370
|
-
self.__dict__.clear() # dereference
|
|
371
|
-
|
|
372
|
-
@property
|
|
373
|
-
def value(self):
|
|
374
|
-
if self.yieldedValue is not None:
|
|
375
|
-
return self.yieldedValue
|
|
376
|
-
return None
|
|
377
|
-
|
|
378
|
-
def __repr__(self):
|
|
379
|
-
if self.yieldedValue is not None:
|
|
380
|
-
return self.yieldedValue.__repr__()
|
|
381
|
-
return "none"
|
|
382
|
-
|
|
383
|
-
def reset(self):
|
|
384
|
-
self.forIter = iter(self.collection)
|
|
385
|
-
self.yieldedValue = None
|
|
386
|
-
self.next()
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
def next(self): # will raise StopIteration if no (more) facts or fallback
|
|
390
|
-
try:
|
|
391
|
-
self.yieldedValue = next(self.forIter)
|
|
392
|
-
# set next value here as well as in for node, because may be cleared above context of for node
|
|
393
|
-
self.sCtx.localVariables[self.node.name] = self.yieldedValue
|
|
394
|
-
if self.sCtx.formulaOptions.traceVariableFiltersResult:
|
|
395
|
-
self.sCtx.modelXbrl.info("sphinx:trace",
|
|
396
|
-
_("For loop %(variable)s: bound value %(result)s"),
|
|
397
|
-
sourceFileLine=self.node.sourceFileLine, variable=str(self.node.name), result=str(self.yieldedValue))
|
|
398
|
-
except StopIteration:
|
|
399
|
-
if self.yieldedValue is not None:
|
|
400
|
-
del self.sCtx.localVariables[self.node.name]
|
|
401
|
-
self.yieldedValue = None
|
|
402
|
-
raise StopIteration
|
|
403
|
-
|
|
404
|
-
from .SphinxEvaluator import evaluate, factAspectValue, SphinxException, NONE
|