arelle-release 2.37.20__py3-none-any.whl → 2.37.21__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 +8 -0
- arelle/RuntimeOptions.py +0 -6
- arelle/XbrlConst.py +2 -0
- arelle/_version.py +2 -2
- arelle/api/Session.py +7 -5
- arelle/plugin/validate/NL/LinkbaseType.py +77 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +195 -26
- arelle/plugin/validate/NL/ValidationPluginExtension.py +1 -0
- arelle/plugin/validate/NL/__init__.py +0 -4
- arelle/plugin/validate/NL/rules/nl_kvk.py +405 -17
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.21.dist-info}/METADATA +1 -1
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.21.dist-info}/RECORD +18 -17
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +19 -16
- tests/unit_tests/arelle/test_runtimeoptions.py +0 -13
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.21.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.21.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.21.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.21.dist-info}/top_level.txt +0 -0
arelle/CntlrCmdLine.py
CHANGED
|
@@ -537,6 +537,14 @@ def parseArgs(args):
|
|
|
537
537
|
runtimeOptions = RuntimeOptions(pluginOptions=pluginOptions, **baseOptions)
|
|
538
538
|
except RuntimeOptionsException as e:
|
|
539
539
|
parser.error(f"{e}, please try\n python CntlrCmdLine.py --help")
|
|
540
|
+
if (
|
|
541
|
+
runtimeOptions.entrypointFile is None and
|
|
542
|
+
not runtimeOptions.proxy and
|
|
543
|
+
not runtimeOptions.plugins and
|
|
544
|
+
not pluginOptions and
|
|
545
|
+
not runtimeOptions.webserver
|
|
546
|
+
):
|
|
547
|
+
parser.error("No entrypoint specified, please try\n python CntlrCmdLine.py --help")
|
|
540
548
|
return runtimeOptions, arellePluginModules
|
|
541
549
|
|
|
542
550
|
|
arelle/RuntimeOptions.py
CHANGED
|
@@ -183,12 +183,6 @@ class RuntimeOptions:
|
|
|
183
183
|
raise RuntimeOptionsException('Provided plugin options already exist as base options {}'.format(existingBaseOptions))
|
|
184
184
|
for optionName, optionValue in pluginOptions.items():
|
|
185
185
|
setattr(self, optionName, optionValue)
|
|
186
|
-
if (self.entrypointFile is None and
|
|
187
|
-
not self.proxy and
|
|
188
|
-
not self.plugins and
|
|
189
|
-
not pluginOptions and
|
|
190
|
-
not self.webserver):
|
|
191
|
-
raise RuntimeOptionsException('Incorrect arguments')
|
|
192
186
|
if self.webserver and not hasWebServer():
|
|
193
187
|
raise RuntimeOptionsException("Webserver option requires webserver module")
|
|
194
188
|
if self.webserver and any((
|
arelle/XbrlConst.py
CHANGED
|
@@ -101,6 +101,7 @@ elementLabel = "http://xbrl.org/arcrole/2008/element-label"
|
|
|
101
101
|
genLabel = "http://xbrl.org/2008/label"
|
|
102
102
|
qnGenLabel = qname("{http://xbrl.org/2008/label}label")
|
|
103
103
|
xbrldt = "http://xbrl.org/2005/xbrldt"
|
|
104
|
+
qnXbrldtClosed = qname("{http://xbrl.org/2005/xbrldt}xbrldt:closed")
|
|
104
105
|
qnXbrldtHypercubeItem = qname("{http://xbrl.org/2005/xbrldt}xbrldt:hypercubeItem")
|
|
105
106
|
qnXbrldtDimensionItem = qname("{http://xbrl.org/2005/xbrldt}xbrldt:dimensionItem")
|
|
106
107
|
qnXbrldtContextElement = qname("{http://xbrl.org/2005/xbrldt}xbrldt:contextElement")
|
|
@@ -108,6 +109,7 @@ xbrldi = "http://xbrl.org/2006/xbrldi"
|
|
|
108
109
|
qnXbrldiExplicitMember = qname("{http://xbrl.org/2006/xbrldi}xbrldi:explicitMember")
|
|
109
110
|
qnXbrldiTypedMember = qname("{http://xbrl.org/2006/xbrldi}xbrldi:typedMember")
|
|
110
111
|
xlink = "http://www.w3.org/1999/xlink"
|
|
112
|
+
qnXlinkArcRole = qname("{http://www.w3.org/1999/xlink}xlink:arcrole")
|
|
111
113
|
xl = "http://www.xbrl.org/2003/XLink"
|
|
112
114
|
qnXlExtended = qname("{http://www.xbrl.org/2003/XLink}xl:extended")
|
|
113
115
|
qnXlLocator = qname("{http://www.xbrl.org/2003/XLink}xl:locator")
|
arelle/_version.py
CHANGED
arelle/api/Session.py
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
See COPYRIGHT.md for copyright information.
|
|
3
3
|
|
|
4
|
-
The
|
|
5
|
-
A roadmap for this API is in development.
|
|
6
|
-
|
|
7
|
-
Users of this API should expect changes in future releases.
|
|
4
|
+
The `arelle.api` module is the supported method for integrating Arelle into other Python applications.
|
|
8
5
|
"""
|
|
9
6
|
from __future__ import annotations
|
|
10
7
|
|
|
@@ -12,7 +9,7 @@ import logging
|
|
|
12
9
|
from types import TracebackType
|
|
13
10
|
from typing import Any, BinaryIO
|
|
14
11
|
|
|
15
|
-
from arelle import
|
|
12
|
+
from arelle import PackageManager, PluginManager
|
|
16
13
|
from arelle.CntlrCmdLine import CntlrCmdLine, createCntlrAndPreloadPlugins
|
|
17
14
|
from arelle.ModelXbrl import ModelXbrl
|
|
18
15
|
from arelle.RuntimeOptions import RuntimeOptions
|
|
@@ -81,6 +78,7 @@ class Session:
|
|
|
81
78
|
responseZipStream: BinaryIO | None = None,
|
|
82
79
|
logHandler: logging.Handler | None = None,
|
|
83
80
|
logFilters: list[logging.Filter] | None = None,
|
|
81
|
+
sourceZipStreamFileName: str | None = None,
|
|
84
82
|
) -> bool:
|
|
85
83
|
"""
|
|
86
84
|
Perform a run using the given options.
|
|
@@ -88,8 +86,11 @@ class Session:
|
|
|
88
86
|
:param sourceZipStream: Optional stream to read source data from.
|
|
89
87
|
:param responseZipStream: Options stream to write response data to.
|
|
90
88
|
:param logHandler: Optional log handler to use for logging.
|
|
89
|
+
:param sourceZipStreamFileName: Optional file name to use for the passed zip stream.
|
|
91
90
|
:return: True if the run was successful, False otherwise.
|
|
92
91
|
"""
|
|
92
|
+
if sourceZipStreamFileName is not None and sourceZipStream is None:
|
|
93
|
+
raise ValueError("sourceZipStreamFileName may only be provided if sourceZipStream is not None.")
|
|
93
94
|
PackageManager.reset()
|
|
94
95
|
PluginManager.reset()
|
|
95
96
|
if self._cntlr is None:
|
|
@@ -143,4 +144,5 @@ class Session:
|
|
|
143
144
|
options,
|
|
144
145
|
sourceZipStream=sourceZipStream,
|
|
145
146
|
responseZipStream=responseZipStream,
|
|
147
|
+
sourceZipStreamFileName=sourceZipStreamFileName,
|
|
146
148
|
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'''
|
|
2
|
+
See COPYRIGHT.md for copyright information.
|
|
3
|
+
'''
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from enum import Enum
|
|
7
|
+
|
|
8
|
+
from arelle import XbrlConst
|
|
9
|
+
from arelle.ModelValue import QName
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LinkbaseType(Enum):
|
|
13
|
+
CALCULATION = "calculation"
|
|
14
|
+
DEFINITION = "definition"
|
|
15
|
+
LABEL = "label"
|
|
16
|
+
PRESENTATION = "presentation"
|
|
17
|
+
REFERENCE = "reference"
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def fromRefUri(refUri: str | None) -> LinkbaseType | None:
|
|
21
|
+
"""
|
|
22
|
+
Returns the LinkbaseType corresponding to the given ref URI.
|
|
23
|
+
If the URI does not match any known linkbase reference type, returns None.
|
|
24
|
+
"""
|
|
25
|
+
if refUri is None:
|
|
26
|
+
return None
|
|
27
|
+
return LINKBASE_TYPE_BY_REF_URI.get(refUri, None)
|
|
28
|
+
|
|
29
|
+
def getArcQn(self) -> QName:
|
|
30
|
+
"""
|
|
31
|
+
Returns the qname of the arc associated with this LinkbaseType.
|
|
32
|
+
"""
|
|
33
|
+
return LINKBASE_ARC_QN[self]
|
|
34
|
+
|
|
35
|
+
def getLinkQn(self) -> QName:
|
|
36
|
+
"""
|
|
37
|
+
Returns the qname of the link associated with this LinkbaseType.
|
|
38
|
+
"""
|
|
39
|
+
return LINKBASE_LINK_QN[self]
|
|
40
|
+
|
|
41
|
+
def getLowerName(self) -> str:
|
|
42
|
+
"""
|
|
43
|
+
Returns the lower-case name of this LinkbaseType.
|
|
44
|
+
"""
|
|
45
|
+
return self.value.lower()
|
|
46
|
+
|
|
47
|
+
def getRefUri(self) -> str:
|
|
48
|
+
"""
|
|
49
|
+
Returns the ref URI associated with this LinkbaseType.
|
|
50
|
+
"""
|
|
51
|
+
return LINKBASE_REF_URIS[self]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
LINKBASE_ARC_QN = {
|
|
55
|
+
LinkbaseType.CALCULATION: XbrlConst.qnLinkCalculationArc,
|
|
56
|
+
LinkbaseType.DEFINITION: XbrlConst.qnLinkDefinitionArc,
|
|
57
|
+
LinkbaseType.LABEL: XbrlConst.qnLinkLabelArc,
|
|
58
|
+
LinkbaseType.PRESENTATION: XbrlConst.qnLinkPresentationArc,
|
|
59
|
+
LinkbaseType.REFERENCE: XbrlConst.qnLinkReferenceArc,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
LINKBASE_LINK_QN = {
|
|
63
|
+
LinkbaseType.CALCULATION: XbrlConst.qnLinkCalculationLink,
|
|
64
|
+
LinkbaseType.DEFINITION: XbrlConst.qnLinkDefinitionLink,
|
|
65
|
+
LinkbaseType.LABEL: XbrlConst.qnLinkLabelLink,
|
|
66
|
+
LinkbaseType.PRESENTATION: XbrlConst.qnLinkPresentationLink,
|
|
67
|
+
LinkbaseType.REFERENCE: XbrlConst.qnLinkReferenceLink,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
LINKBASE_REF_URIS = {
|
|
71
|
+
LinkbaseType.CALCULATION: "http://www.xbrl.org/2003/role/calculationLinkbaseRef",
|
|
72
|
+
LinkbaseType.DEFINITION: "http://www.xbrl.org/2003/role/definitionLinkbaseRef",
|
|
73
|
+
LinkbaseType.LABEL: "http://www.xbrl.org/2003/role/labelLinkbaseRef",
|
|
74
|
+
LinkbaseType.PRESENTATION: "http://www.xbrl.org/2003/role/presentationLinkbaseRef",
|
|
75
|
+
LinkbaseType.REFERENCE: "http://www.xbrl.org/2003/role/referenceLinkbaseRef",
|
|
76
|
+
}
|
|
77
|
+
LINKBASE_TYPE_BY_REF_URI = {v: k for k, v in LINKBASE_REF_URIS.items()}
|
|
@@ -7,14 +7,15 @@ from collections import defaultdict
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from functools import lru_cache
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import Any, TYPE_CHECKING, cast
|
|
10
|
+
from typing import Any, TYPE_CHECKING, cast, Iterable
|
|
11
11
|
|
|
12
12
|
import regex as re
|
|
13
|
-
from lxml.etree import _Comment, _ElementTree, _Entity, _ProcessingInstruction
|
|
13
|
+
from lxml.etree import _Comment, _ElementTree, _Entity, _ProcessingInstruction, _Element
|
|
14
14
|
|
|
15
|
+
from arelle import XbrlConst
|
|
15
16
|
from arelle.FunctionIxt import ixtNamespaces
|
|
16
|
-
from arelle import ModelDocument as
|
|
17
|
-
from arelle.
|
|
17
|
+
from arelle.ModelDocument import ModelDocument, Type as ModelDocumentType
|
|
18
|
+
from arelle.ModelDtsObject import ModelConcept
|
|
18
19
|
from arelle.ModelInstanceObject import ModelContext, ModelFact, ModelInlineFootnote, ModelUnit, ModelInlineFact
|
|
19
20
|
from arelle.ModelObject import ModelObject
|
|
20
21
|
from arelle.ModelValue import QName
|
|
@@ -22,10 +23,10 @@ from arelle.ModelXbrl import ModelXbrl
|
|
|
22
23
|
from arelle.typing import assert_type
|
|
23
24
|
from arelle.utils.PluginData import PluginData
|
|
24
25
|
from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
|
|
25
|
-
from arelle.ValidateXbrl import ValidateXbrl
|
|
26
26
|
from arelle.XbrlConst import ixbrl11, xhtmlBaseIdentifier, xmlBaseIdentifier
|
|
27
27
|
from arelle.XmlValidate import lexicalPatterns
|
|
28
28
|
from arelle.XmlValidateConst import VALID
|
|
29
|
+
from .LinkbaseType import LinkbaseType
|
|
29
30
|
|
|
30
31
|
XBRLI_IDENTIFIER_PATTERN = re.compile(r"^(?!00)\d{8}$")
|
|
31
32
|
XBRLI_IDENTIFIER_SCHEMA = 'http://www.kvk.nl/kvk-id'
|
|
@@ -57,11 +58,43 @@ ALLOWABLE_LANGUAGES = frozenset((
|
|
|
57
58
|
'fr'
|
|
58
59
|
))
|
|
59
60
|
|
|
60
|
-
|
|
61
|
+
EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES = frozenset((
|
|
61
62
|
'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd',
|
|
62
63
|
'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd',
|
|
63
64
|
))
|
|
64
65
|
|
|
66
|
+
TAXONOMY_URLS_BY_YEAR = {
|
|
67
|
+
'2024': {
|
|
68
|
+
'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd',
|
|
69
|
+
'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd',
|
|
70
|
+
'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-other-gaap.xsd',
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
STANDARD_TAXONOMY_URLS = frozenset((
|
|
75
|
+
'http://www.nltaxonomie.nl/ifrs/20',
|
|
76
|
+
'https://www.nltaxonomie.nl/ifrs/20',
|
|
77
|
+
'http://www.nltaxonomie.nl/',
|
|
78
|
+
'https://www.nltaxonomie.nl/',
|
|
79
|
+
'http://www.xbrl.org/taxonomy/int/lei/',
|
|
80
|
+
'https://www.xbrl.org/taxonomy/int/lei/',
|
|
81
|
+
'http://www.xbrl.org/20',
|
|
82
|
+
'https://www.xbrl.org/20',
|
|
83
|
+
'http://www.xbrl.org/lrr/',
|
|
84
|
+
'https://www.xbrl.org/lrr/',
|
|
85
|
+
'http://xbrl.org/20',
|
|
86
|
+
'https://xbrl.org/20',
|
|
87
|
+
'http://xbrl.ifrs.org/',
|
|
88
|
+
'https://xbrl.ifrs.org/',
|
|
89
|
+
'http://www.xbrl.org/dtr/',
|
|
90
|
+
'https://www.xbrl.org/dtr/',
|
|
91
|
+
'http://xbrl.org/2020/extensible-enumerations-2.0',
|
|
92
|
+
'https://xbrl.org/2020/extensible-enumerations-2.0',
|
|
93
|
+
'http://www.w3.org/1999/xlink',
|
|
94
|
+
'https://www.w3.org/1999/xlink'
|
|
95
|
+
))
|
|
96
|
+
|
|
97
|
+
|
|
65
98
|
@dataclass(frozen=True)
|
|
66
99
|
class ContextData:
|
|
67
100
|
contextsWithImproperContent: list[ModelContext | None]
|
|
@@ -69,6 +102,48 @@ class ContextData:
|
|
|
69
102
|
contextsWithPeriodTimeZone: list[ModelContext | None]
|
|
70
103
|
contextsWithSegments: list[ModelContext | None]
|
|
71
104
|
|
|
105
|
+
|
|
106
|
+
@dataclass(frozen=True)
|
|
107
|
+
class ExtensionData:
|
|
108
|
+
extensionConcepts: list[ModelConcept]
|
|
109
|
+
extensionDocuments: dict[ModelDocument, ExtensionDocumentData]
|
|
110
|
+
extensionImportedUrls: frozenset[str]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass(frozen=True)
|
|
114
|
+
class ExtensionDocumentData:
|
|
115
|
+
basename: str
|
|
116
|
+
hrefXlinkRole: str | None
|
|
117
|
+
linkbases: list[LinkbaseData]
|
|
118
|
+
|
|
119
|
+
def iterArcsByType(
|
|
120
|
+
self,
|
|
121
|
+
linkbaseType: LinkbaseType,
|
|
122
|
+
includeArcroles: set[str] | None = None,
|
|
123
|
+
excludeArcroles: set[str] | None = None,
|
|
124
|
+
) -> Iterable[_Element]:
|
|
125
|
+
"""
|
|
126
|
+
Returns a list of LinkbaseData objects for the specified LinkbaseType.
|
|
127
|
+
"""
|
|
128
|
+
for linkbase in self.iterLinkbasesByType(linkbaseType):
|
|
129
|
+
for arc in linkbase.arcs:
|
|
130
|
+
if includeArcroles is not None:
|
|
131
|
+
if arc.get(XbrlConst.qnXlinkArcRole.clarkNotation) not in includeArcroles:
|
|
132
|
+
continue
|
|
133
|
+
if excludeArcroles is not None:
|
|
134
|
+
if arc.get(XbrlConst.qnXlinkArcRole.clarkNotation) in excludeArcroles:
|
|
135
|
+
continue
|
|
136
|
+
yield arc
|
|
137
|
+
|
|
138
|
+
def iterLinkbasesByType(self, linkbaseType: LinkbaseType) -> Iterable[LinkbaseData]:
|
|
139
|
+
"""
|
|
140
|
+
Returns a list of LinkbaseData objects for the specified LinkbaseType.
|
|
141
|
+
"""
|
|
142
|
+
for linkbase in self.linkbases:
|
|
143
|
+
if linkbase.linkbaseType == linkbaseType:
|
|
144
|
+
yield linkbase
|
|
145
|
+
|
|
146
|
+
|
|
72
147
|
@dataclass(frozen=True)
|
|
73
148
|
class HiddenElementsData:
|
|
74
149
|
cssHiddenFacts: set[ModelInlineFact]
|
|
@@ -76,6 +151,7 @@ class HiddenElementsData:
|
|
|
76
151
|
hiddenFactsOutsideHiddenSection: set[ModelInlineFact]
|
|
77
152
|
requiredToDisplayFacts: set[ModelInlineFact]
|
|
78
153
|
|
|
154
|
+
|
|
79
155
|
@dataclass(frozen=True)
|
|
80
156
|
class InlineHTMLData:
|
|
81
157
|
baseElements: set[Any]
|
|
@@ -85,6 +161,19 @@ class InlineHTMLData:
|
|
|
85
161
|
factLangFootnotes: dict[ModelInlineFootnote, set[str]]
|
|
86
162
|
fractionElements: set[Any]
|
|
87
163
|
|
|
164
|
+
|
|
165
|
+
@dataclass(frozen=True)
|
|
166
|
+
class LinkbaseData:
|
|
167
|
+
arcs: list[_Element]
|
|
168
|
+
basename: str
|
|
169
|
+
element: _Element
|
|
170
|
+
linkbaseType: LinkbaseType | None
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def hasArcs(self) -> bool:
|
|
174
|
+
return len(self.arcs) > 0
|
|
175
|
+
|
|
176
|
+
|
|
88
177
|
@dataclass
|
|
89
178
|
class PluginValidationDataExtension(PluginData):
|
|
90
179
|
chamberOfCommerceRegistrationNumberQn: QName
|
|
@@ -93,6 +182,7 @@ class PluginValidationDataExtension(PluginData):
|
|
|
93
182
|
documentResubmissionUnsurmountableInaccuraciesQn: QName
|
|
94
183
|
entrypointRoot: str
|
|
95
184
|
entrypoints: set[str]
|
|
185
|
+
financialReportingPeriodQn: QName
|
|
96
186
|
financialReportingPeriodCurrentStartDateQn: QName
|
|
97
187
|
financialReportingPeriodCurrentEndDateQn: QName
|
|
98
188
|
financialReportingPeriodPreviousStartDateQn: QName
|
|
@@ -144,21 +234,6 @@ class PluginValidationDataExtension(PluginData):
|
|
|
144
234
|
contextsWithSegments=contextsWithSegments,
|
|
145
235
|
)
|
|
146
236
|
|
|
147
|
-
def checkFilingDTS(
|
|
148
|
-
self,
|
|
149
|
-
val: ValidateXbrl,
|
|
150
|
-
modelDocument: ModelDocument,
|
|
151
|
-
visited: list[ModelDocument]
|
|
152
|
-
) -> None:
|
|
153
|
-
visited.append(modelDocument)
|
|
154
|
-
for referencedDocument, modelDocumentReference in modelDocument.referencesDocument.items():
|
|
155
|
-
if referencedDocument not in visited and referencedDocument.inDTS:
|
|
156
|
-
self.checkFilingDTS(val, referencedDocument, visited)
|
|
157
|
-
if modelDocument.type == ModelDocumentFile.Type.SCHEMA:
|
|
158
|
-
for doc, docRef in modelDocument.referencesDocument.items():
|
|
159
|
-
if "import" in docRef.referenceTypes:
|
|
160
|
-
val.extensionImportedUrls.add(doc.uri)
|
|
161
|
-
|
|
162
237
|
@lru_cache(1)
|
|
163
238
|
def checkHiddenElements(self, modelXbrl: ModelXbrl) -> HiddenElementsData:
|
|
164
239
|
cssHiddenFacts = set()
|
|
@@ -169,7 +244,7 @@ class PluginValidationDataExtension(PluginData):
|
|
|
169
244
|
presentedHiddenEltIds = defaultdict(list)
|
|
170
245
|
requiredToDisplayFacts = set()
|
|
171
246
|
for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
|
|
172
|
-
ixNStag = getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11)
|
|
247
|
+
ixNStag = str(getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11))
|
|
173
248
|
for ixHiddenElt in ixdsHtmlRootElt.iterdescendants(tag=ixNStag + "hidden"):
|
|
174
249
|
for tag in (ixNStag + "nonNumeric", ixNStag+"nonFraction"):
|
|
175
250
|
for ixElt in ixHiddenElt.iterdescendants(tag=tag):
|
|
@@ -218,7 +293,7 @@ class PluginValidationDataExtension(PluginData):
|
|
|
218
293
|
tupleElements = set()
|
|
219
294
|
orphanedFootnotes = set()
|
|
220
295
|
for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
|
|
221
|
-
ixNStag = getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11)
|
|
296
|
+
ixNStag = str(getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11))
|
|
222
297
|
ixTupleTag = ixNStag + "tuple"
|
|
223
298
|
ixFractionTag = ixNStag + "fraction"
|
|
224
299
|
for elts in modelXbrl.ixdsEltById.values(): # type: ignore[attr-defined]
|
|
@@ -291,6 +366,24 @@ class PluginValidationDataExtension(PluginData):
|
|
|
291
366
|
def getContextsWithSegments(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
|
|
292
367
|
return self.checkContexts(modelXbrl).contextsWithSegments
|
|
293
368
|
|
|
369
|
+
@lru_cache(1)
|
|
370
|
+
def getDocumentsInDts(self, modelXbrl: ModelXbrl) -> dict[ModelDocument, str | None]:
|
|
371
|
+
modelDocuments: dict[ModelDocument, str | None] = {}
|
|
372
|
+
if modelXbrl.modelDocument is None:
|
|
373
|
+
return modelDocuments
|
|
374
|
+
|
|
375
|
+
def _getDocumentsInDts(modelDocument: ModelDocument) -> None:
|
|
376
|
+
for referencedDocument, modelDocumentReference in modelDocument.referencesDocument.items():
|
|
377
|
+
if referencedDocument in modelDocuments:
|
|
378
|
+
continue
|
|
379
|
+
if referencedDocument.inDTS:
|
|
380
|
+
modelDocuments[referencedDocument] = modelDocumentReference.referringXlinkRole
|
|
381
|
+
_getDocumentsInDts(referencedDocument)
|
|
382
|
+
|
|
383
|
+
modelDocuments[modelXbrl.modelDocument] = None
|
|
384
|
+
_getDocumentsInDts(modelXbrl.modelDocument)
|
|
385
|
+
return modelDocuments
|
|
386
|
+
|
|
294
387
|
def getEligibleForTransformHiddenFacts(self, modelXbrl: ModelXbrl) -> set[ModelInlineFact]:
|
|
295
388
|
return self.checkHiddenElements(modelXbrl).eligibleForTransformHiddenFacts
|
|
296
389
|
|
|
@@ -321,8 +414,19 @@ class PluginValidationDataExtension(PluginData):
|
|
|
321
414
|
)
|
|
322
415
|
|
|
323
416
|
@lru_cache(1)
|
|
324
|
-
def
|
|
325
|
-
|
|
417
|
+
def getExtensionFilenameFormatPattern(self) -> re.Pattern[str]:
|
|
418
|
+
return re.compile(
|
|
419
|
+
r"^(?<base>[^-]*)"
|
|
420
|
+
r"-(?<year>\d{4})-(?<month>0[1-9]|1[012])-(?<day>0?[1-9]|[12][0-9]|3[01])"
|
|
421
|
+
r"(?<suffix>[_pre|_cal|_lab|_def]*)"
|
|
422
|
+
r"(?<lang>-*[^-]*)"
|
|
423
|
+
r"\.(?<extension>xsd|xml)$",
|
|
424
|
+
flags=re.ASCII
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
@lru_cache(1)
|
|
428
|
+
def getFilenameParts(self, filename: str, filenamePattern: re.Pattern[str]) -> dict[str, Any] | None:
|
|
429
|
+
match = filenamePattern.match(filename)
|
|
326
430
|
if match:
|
|
327
431
|
return match.groupdict()
|
|
328
432
|
return None
|
|
@@ -331,6 +435,56 @@ class PluginValidationDataExtension(PluginData):
|
|
|
331
435
|
def getIxdsDocBasenames(self, modelXbrl: ModelXbrl) -> set[str]:
|
|
332
436
|
return set(Path(url).name for url in getattr(modelXbrl, "ixdsDocUrls", []))
|
|
333
437
|
|
|
438
|
+
def getExtensionConcepts(self, modelXbrl: ModelXbrl) -> list[ModelConcept]:
|
|
439
|
+
"""
|
|
440
|
+
Returns a list of extension concepts in the DTS.
|
|
441
|
+
"""
|
|
442
|
+
extensionConcepts = []
|
|
443
|
+
for concepts in modelXbrl.nameConcepts.values():
|
|
444
|
+
for concept in concepts:
|
|
445
|
+
if self.isExtensionUri(concept.qname.namespaceURI, modelXbrl):
|
|
446
|
+
extensionConcepts.append(concept)
|
|
447
|
+
return extensionConcepts
|
|
448
|
+
|
|
449
|
+
@lru_cache(1)
|
|
450
|
+
def getExtensionData(self, modelXbrl: ModelXbrl) -> ExtensionData:
|
|
451
|
+
extensionDocuments = {}
|
|
452
|
+
extensionImportedUrls = set()
|
|
453
|
+
documentsInDts = self.getDocumentsInDts(modelXbrl)
|
|
454
|
+
for modelDocument, hrefXlinkRole in documentsInDts.items():
|
|
455
|
+
if not self.isExtensionUri(modelDocument.uri, modelDocument.modelXbrl):
|
|
456
|
+
# Skip non-extension documents
|
|
457
|
+
continue
|
|
458
|
+
if modelDocument.type in (ModelDocumentType.LINKBASE, ModelDocumentType.SCHEMA):
|
|
459
|
+
extensionDocuments[modelDocument] = ExtensionDocumentData(
|
|
460
|
+
basename=modelDocument.basename,
|
|
461
|
+
hrefXlinkRole=hrefXlinkRole,
|
|
462
|
+
linkbases=self.getLinkbaseData(modelDocument),
|
|
463
|
+
)
|
|
464
|
+
if modelDocument.type == ModelDocumentType.SCHEMA:
|
|
465
|
+
for doc, docRef in modelDocument.referencesDocument.items():
|
|
466
|
+
if "import" in docRef.referenceTypes:
|
|
467
|
+
extensionImportedUrls.add(doc.uri)
|
|
468
|
+
return ExtensionData(
|
|
469
|
+
extensionConcepts=self.getExtensionConcepts(modelXbrl),
|
|
470
|
+
extensionDocuments=extensionDocuments,
|
|
471
|
+
extensionImportedUrls=frozenset(sorted(extensionImportedUrls)),
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
def getLinkbaseData(self, modelDocument: ModelDocument) -> list[LinkbaseData]:
|
|
475
|
+
linkbases = []
|
|
476
|
+
for linkbaseType in LinkbaseType:
|
|
477
|
+
for linkElt in modelDocument.xmlRootElement.iterdescendants(tag=linkbaseType.getLinkQn().clarkNotation):
|
|
478
|
+
arcQn = linkbaseType.getArcQn()
|
|
479
|
+
arcs = list(linkElt.iterdescendants(tag=arcQn.clarkNotation))
|
|
480
|
+
linkbases.append(LinkbaseData(
|
|
481
|
+
arcs=arcs,
|
|
482
|
+
basename=modelDocument.basename,
|
|
483
|
+
element=linkElt,
|
|
484
|
+
linkbaseType=linkbaseType,
|
|
485
|
+
))
|
|
486
|
+
return linkbases
|
|
487
|
+
|
|
334
488
|
def getNoMatchLangFootnotes(self, modelXbrl: ModelXbrl) -> set[ModelInlineFootnote]:
|
|
335
489
|
return self.checkInlineHTMLElements(modelXbrl).noMatchLangFootnotes
|
|
336
490
|
|
|
@@ -346,6 +500,14 @@ class PluginValidationDataExtension(PluginData):
|
|
|
346
500
|
def getTupleElements(self, modelXbrl: ModelXbrl) -> set[tuple[Any]]:
|
|
347
501
|
return self.checkInlineHTMLElements(modelXbrl).tupleElements
|
|
348
502
|
|
|
503
|
+
@lru_cache(1)
|
|
504
|
+
def getReportingPeriod(self, modelXbrl: ModelXbrl) -> str | None:
|
|
505
|
+
reportingPeriodFacts = modelXbrl.factsByQname.get(self.financialReportingPeriodQn, set())
|
|
506
|
+
for fact in reportingPeriodFacts:
|
|
507
|
+
if fact.xValid >= VALID:
|
|
508
|
+
return cast(str, fact.xValue)
|
|
509
|
+
return None
|
|
510
|
+
|
|
349
511
|
@lru_cache(1)
|
|
350
512
|
def getReportXmlLang(self, modelXbrl: ModelXbrl) -> str | None:
|
|
351
513
|
reportXmlLang = None
|
|
@@ -365,13 +527,20 @@ class PluginValidationDataExtension(PluginData):
|
|
|
365
527
|
def getTargetElements(self, modelXbrl: ModelXbrl) -> list[Any]:
|
|
366
528
|
targetElements = []
|
|
367
529
|
for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
|
|
368
|
-
ixNStag = getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11)
|
|
530
|
+
ixNStag = str(getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11))
|
|
369
531
|
ixTags = set(ixNStag + ln for ln in ("nonNumeric", "nonFraction", "references", "relationship"))
|
|
370
532
|
for elt, depth in etreeIterWithDepth(ixdsHtmlRootElt):
|
|
371
533
|
if elt.tag in ixTags and elt.get("target"):
|
|
372
534
|
targetElements.append(elt)
|
|
373
535
|
return targetElements
|
|
374
536
|
|
|
537
|
+
def isExtensionUri(self, uri: str, modelXbrl: ModelXbrl) -> bool:
|
|
538
|
+
if uri.startswith(modelXbrl.uriDir):
|
|
539
|
+
return True
|
|
540
|
+
if not any(uri.startswith(taxonomyUri) for taxonomyUri in STANDARD_TAXONOMY_URLS):
|
|
541
|
+
return True
|
|
542
|
+
return False
|
|
543
|
+
|
|
375
544
|
@lru_cache(1)
|
|
376
545
|
def isFilenameValidCharacters(self, filename: str) -> bool:
|
|
377
546
|
match = self.getFilenameAllowedCharactersPattern().match(filename)
|
|
@@ -186,6 +186,7 @@ class ValidationPluginExtension(ValidationPlugin):
|
|
|
186
186
|
documentResubmissionUnsurmountableInaccuraciesQn=qname(f'{{{kvkINamespace}}}DocumentResubmissionDueToUnsurmountableInaccuracies'),
|
|
187
187
|
entrypointRoot=entrypointRoot,
|
|
188
188
|
entrypoints=entrypoints,
|
|
189
|
+
financialReportingPeriodQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriod'),
|
|
189
190
|
financialReportingPeriodCurrentStartDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodCurrentStartDate'),
|
|
190
191
|
financialReportingPeriodCurrentEndDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodCurrentEndDate'),
|
|
191
192
|
financialReportingPeriodPreviousStartDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodPreviousStartDate'),
|
|
@@ -46,9 +46,6 @@ def modelXbrlLoadComplete(*args: Any, **kwargs: Any) -> ModelDocument | LoadingE
|
|
|
46
46
|
def validateFinally(*args: Any, **kwargs: Any) -> None:
|
|
47
47
|
return validationPlugin.validateFinally(*args, **kwargs)
|
|
48
48
|
|
|
49
|
-
def validateXbrlStart(val: ValidateXbrl, parameters: dict[Any, Any], *args: Any, **kwargs: Any) -> None:
|
|
50
|
-
val.extensionImportedUrls = set()
|
|
51
|
-
|
|
52
49
|
def validateXbrlFinally(*args: Any, **kwargs: Any) -> None:
|
|
53
50
|
return validationPlugin.validateXbrlFinally(*args, **kwargs)
|
|
54
51
|
|
|
@@ -64,7 +61,6 @@ __pluginInfo__ = {
|
|
|
64
61
|
"DisclosureSystem.Types": disclosureSystemTypes,
|
|
65
62
|
"DisclosureSystem.ConfigURL": disclosureSystemConfigURL,
|
|
66
63
|
"ModelXbrl.LoadComplete": modelXbrlLoadComplete,
|
|
67
|
-
"Validate.XBRL.Start": validateXbrlStart,
|
|
68
64
|
"Validate.XBRL.Finally": validateXbrlFinally,
|
|
69
65
|
"ValidateFormula.Finished": validateFinally,
|
|
70
66
|
}
|
|
@@ -12,7 +12,7 @@ from arelle.XmlValidateConst import VALID
|
|
|
12
12
|
from collections.abc import Iterable
|
|
13
13
|
from typing import Any, cast, TYPE_CHECKING
|
|
14
14
|
|
|
15
|
-
from arelle import XmlUtil
|
|
15
|
+
from arelle import XmlUtil, XbrlConst
|
|
16
16
|
from arelle.ValidateXbrl import ValidateXbrl
|
|
17
17
|
from arelle.typing import TypeGetText
|
|
18
18
|
from arelle.utils.PluginHooks import ValidationHook
|
|
@@ -21,10 +21,11 @@ from arelle.utils.validate.Validation import Validation
|
|
|
21
21
|
from arelle.ValidateDuplicateFacts import getHashEquivalentFactGroups, getAspectEqualFacts
|
|
22
22
|
from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
|
|
23
23
|
from ..DisclosureSystems import DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
24
|
+
from ..LinkbaseType import LinkbaseType
|
|
24
25
|
from ..PluginValidationDataExtension import (PluginValidationDataExtension, ALLOWABLE_LANGUAGES,
|
|
25
|
-
DISALLOWED_IXT_NAMESPACES,
|
|
26
|
-
MAX_REPORT_PACKAGE_SIZE_MBS,
|
|
27
|
-
XBRLI_IDENTIFIER_SCHEMA)
|
|
26
|
+
DISALLOWED_IXT_NAMESPACES, EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES,
|
|
27
|
+
MAX_REPORT_PACKAGE_SIZE_MBS, TAXONOMY_URLS_BY_YEAR,
|
|
28
|
+
XBRLI_IDENTIFIER_PATTERN, XBRLI_IDENTIFIER_SCHEMA)
|
|
28
29
|
|
|
29
30
|
if TYPE_CHECKING:
|
|
30
31
|
from arelle.ModelXbrl import ModelXbrl
|
|
@@ -532,7 +533,7 @@ def rule_nl_kvk_3_4_1_3 (
|
|
|
532
533
|
if len(facts) > 0:
|
|
533
534
|
yield Validation.error(
|
|
534
535
|
codes='NL.NL-KVK.3.4.1.3.transformableElementIncludedInHiddenSection',
|
|
535
|
-
msg=_('The ix:hidden section should not include elements that are eligible for transformation'
|
|
536
|
+
msg=_('The ix:hidden section should not include elements that are eligible for transformation '
|
|
536
537
|
'according to the latest recommended Transformation Rules Registry.'),
|
|
537
538
|
modelObject=facts
|
|
538
539
|
)
|
|
@@ -770,7 +771,7 @@ def rule_nl_kvk_3_6_3_1(
|
|
|
770
771
|
"""
|
|
771
772
|
invalidBasenames = []
|
|
772
773
|
for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
|
|
773
|
-
filenameParts = pluginData.getFilenameParts(basename)
|
|
774
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
|
|
774
775
|
if not filenameParts:
|
|
775
776
|
continue # Filename is not formatted correctly enough to determine {base}
|
|
776
777
|
if len(filenameParts.get('base', '')) > 20:
|
|
@@ -803,7 +804,7 @@ def rule_nl_kvk_3_6_3_2(
|
|
|
803
804
|
"""
|
|
804
805
|
invalidBasenames = []
|
|
805
806
|
for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
|
|
806
|
-
filenameParts = pluginData.getFilenameParts(basename)
|
|
807
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
|
|
807
808
|
if not filenameParts:
|
|
808
809
|
invalidBasenames.append(basename)
|
|
809
810
|
if len(invalidBasenames) > 0:
|
|
@@ -907,6 +908,96 @@ def rule_nl_kvk_3_7_1_2(
|
|
|
907
908
|
)
|
|
908
909
|
|
|
909
910
|
|
|
911
|
+
@validation(
|
|
912
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
913
|
+
disclosureSystems=[
|
|
914
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
915
|
+
],
|
|
916
|
+
)
|
|
917
|
+
def rule_nl_kvk_4_1_1_1(
|
|
918
|
+
pluginData: PluginValidationDataExtension,
|
|
919
|
+
val: ValidateXbrl,
|
|
920
|
+
*args: Any,
|
|
921
|
+
**kwargs: Any,
|
|
922
|
+
) -> Iterable[Validation]:
|
|
923
|
+
"""
|
|
924
|
+
NL-KVK.4.1.1.1: Extension taxonomies MUST consist of at least a schema file and presentation,
|
|
925
|
+
calculation and definition linkbases.
|
|
926
|
+
A label linkbase is also required if extension elements are present.
|
|
927
|
+
"""
|
|
928
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
929
|
+
linkbaseIsMissing = {
|
|
930
|
+
LinkbaseType.CALCULATION: True,
|
|
931
|
+
LinkbaseType.DEFINITION: True,
|
|
932
|
+
LinkbaseType.LABEL: len(extensionData.extensionConcepts) > 0,
|
|
933
|
+
LinkbaseType.PRESENTATION: True,
|
|
934
|
+
}
|
|
935
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
936
|
+
hasArcs = False
|
|
937
|
+
linkbaseType = LinkbaseType.fromRefUri(extensionDocumentData.hrefXlinkRole)
|
|
938
|
+
for linkbaseData in extensionDocumentData.linkbases:
|
|
939
|
+
if linkbaseType is not None:
|
|
940
|
+
if linkbaseType == linkbaseData.linkbaseType:
|
|
941
|
+
if linkbaseData.hasArcs:
|
|
942
|
+
hasArcs = True
|
|
943
|
+
break
|
|
944
|
+
elif linkbaseData.hasArcs:
|
|
945
|
+
linkbaseType = linkbaseData.linkbaseType
|
|
946
|
+
hasArcs = True
|
|
947
|
+
break
|
|
948
|
+
if linkbaseType is None:
|
|
949
|
+
continue
|
|
950
|
+
if hasArcs and linkbaseIsMissing.get(linkbaseType, False):
|
|
951
|
+
linkbaseIsMissing[linkbaseType] = False
|
|
952
|
+
missingFiles = set(linkbaseType.getLowerName() for linkbaseType, isMissing in linkbaseIsMissing.items() if isMissing)
|
|
953
|
+
if len(missingFiles) > 0:
|
|
954
|
+
yield Validation.error(
|
|
955
|
+
codes='NL.NL-KVK.4.1.1.1.extensionTaxonomyWrongFilesStructure',
|
|
956
|
+
msg=_('The extension taxonomy is missing one or more required components: %(missingFiles)s '
|
|
957
|
+
'Review to ensure that the schema file, presentation, calculation, '
|
|
958
|
+
'and definition linkbases are included and not empty. '
|
|
959
|
+
'A label linkbase is also required if extension elements are present.'),
|
|
960
|
+
modelObject=val.modelXbrl, missingFiles=", ".join(missingFiles)
|
|
961
|
+
)
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
@validation(
|
|
965
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
966
|
+
disclosureSystems=[
|
|
967
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
968
|
+
],
|
|
969
|
+
)
|
|
970
|
+
def rule_nl_kvk_4_1_1_2(
|
|
971
|
+
pluginData: PluginValidationDataExtension,
|
|
972
|
+
val: ValidateXbrl,
|
|
973
|
+
*args: Any,
|
|
974
|
+
**kwargs: Any,
|
|
975
|
+
) -> Iterable[Validation]:
|
|
976
|
+
"""
|
|
977
|
+
NL-KVK.4.1.1.2: Each linkbase type MUST be provided in a separate linkbase file.
|
|
978
|
+
"""
|
|
979
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
980
|
+
errors = []
|
|
981
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
982
|
+
linkbasesFound = set(
|
|
983
|
+
linkbase.linkbaseType.getLowerName()
|
|
984
|
+
for linkbase in extensionDocumentData.linkbases
|
|
985
|
+
if linkbase.linkbaseType is not None
|
|
986
|
+
)
|
|
987
|
+
if len(linkbasesFound) > 1:
|
|
988
|
+
errors.append((modelDocument, linkbasesFound))
|
|
989
|
+
for modelDocument, linkbasesFound in errors:
|
|
990
|
+
yield Validation.error(
|
|
991
|
+
codes='NL.NL-KVK.4.1.1.2.linkbasesNotSeparateFiles',
|
|
992
|
+
msg=_('Linkbase types are not stored in separate files. '
|
|
993
|
+
'Review linkbase files and ensure they are provided as individual files. '
|
|
994
|
+
'Found: %(linkbasesFound)s. in %(basename)s.'),
|
|
995
|
+
modelObject=modelDocument.xmlRootElement,
|
|
996
|
+
basename=modelDocument.basename,
|
|
997
|
+
linkbasesFound=", ".join(sorted(linkbasesFound))
|
|
998
|
+
)
|
|
999
|
+
|
|
1000
|
+
|
|
910
1001
|
@validation(
|
|
911
1002
|
hook=ValidationHook.XBRL_FINALLY,
|
|
912
1003
|
disclosureSystems=[
|
|
@@ -921,17 +1012,314 @@ def rule_nl_kvk_4_1_2_1(
|
|
|
921
1012
|
) -> Iterable[Validation]:
|
|
922
1013
|
"""
|
|
923
1014
|
NL-KVK.4.1.2.1: Validate that the imported taxonomy matches the KVK-specified entry point.
|
|
924
|
-
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd
|
|
925
|
-
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd
|
|
1015
|
+
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd
|
|
1016
|
+
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd
|
|
926
1017
|
"""
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1018
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1019
|
+
matches = extensionData.extensionImportedUrls & EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES
|
|
1020
|
+
if not matches:
|
|
1021
|
+
yield Validation.error(
|
|
1022
|
+
codes='NL.NL-KVK.4.1.2.1.requiredEntryPointNotImported',
|
|
1023
|
+
msg=_('The extension taxonomy must import the entry point of the taxonomy files prepared by KVK.'),
|
|
1024
|
+
modelObject=val.modelXbrl.modelDocument
|
|
1025
|
+
)
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
@validation(
|
|
1029
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1030
|
+
disclosureSystems=[
|
|
1031
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1032
|
+
],
|
|
1033
|
+
)
|
|
1034
|
+
def rule_nl_kvk_4_1_2_2(
|
|
1035
|
+
pluginData: PluginValidationDataExtension,
|
|
1036
|
+
val: ValidateXbrl,
|
|
1037
|
+
*args: Any,
|
|
1038
|
+
**kwargs: Any,
|
|
1039
|
+
) -> Iterable[Validation]:
|
|
1040
|
+
"""
|
|
1041
|
+
NL-KVK.4.1.2.2: The legal entity’s extension taxonomy MUST import the applicable version of
|
|
1042
|
+
the taxonomy files prepared by KVK.
|
|
1043
|
+
"""
|
|
1044
|
+
reportingPeriod = pluginData.getReportingPeriod(val.modelXbrl)
|
|
1045
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1046
|
+
matches = extensionData.extensionImportedUrls & TAXONOMY_URLS_BY_YEAR.get(reportingPeriod or '', set())
|
|
1047
|
+
if not reportingPeriod or not matches:
|
|
1048
|
+
yield Validation.error(
|
|
1049
|
+
codes='NL.NL-KVK.4.1.2.2.incorrectKvkTaxonomyVersionUsed',
|
|
1050
|
+
msg=_('The extension taxonomy MUST import the applicable version of the taxonomy files prepared by KVK '
|
|
1051
|
+
'for the reported financial reporting period of %(reportingPeriod)s.'),
|
|
1052
|
+
modelObject=val.modelXbrl.modelDocument
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
@validation(
|
|
1057
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1058
|
+
disclosureSystems=[
|
|
1059
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1060
|
+
],
|
|
1061
|
+
)
|
|
1062
|
+
def rule_nl_kvk_4_1_5_1(
|
|
1063
|
+
pluginData: PluginValidationDataExtension,
|
|
1064
|
+
val: ValidateXbrl,
|
|
1065
|
+
*args: Any,
|
|
1066
|
+
**kwargs: Any,
|
|
1067
|
+
) -> Iterable[Validation]:
|
|
1068
|
+
"""
|
|
1069
|
+
NL-KVK.4.1.5.1: The `{base}` component of the extension document filename SHOULD not exceed twenty characters.
|
|
1070
|
+
"""
|
|
1071
|
+
invalidBasenames = []
|
|
1072
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1073
|
+
for extensionDocument in extensionData.extensionDocuments.values():
|
|
1074
|
+
basename = extensionDocument.basename
|
|
1075
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getExtensionFilenameFormatPattern())
|
|
1076
|
+
if not filenameParts:
|
|
1077
|
+
continue # Filename is not formatted correctly enough to determine {base}
|
|
1078
|
+
if len(filenameParts.get('base', '')) > 20:
|
|
1079
|
+
invalidBasenames.append(basename)
|
|
1080
|
+
if len(invalidBasenames) > 0:
|
|
1081
|
+
yield Validation.warning(
|
|
1082
|
+
codes='NL.NL-KVK.4.1.5.1.baseComponentInNameOfTaxonomyFileExceedsTwentyCharacters',
|
|
1083
|
+
invalidBasenames=', '.join(invalidBasenames),
|
|
1084
|
+
msg=_('The {base} component of the extension document filename is greater than twenty characters. '
|
|
1085
|
+
'The {base} component can either be the KVK number or the legal entity\'s name. '
|
|
1086
|
+
'If the legal entity\'s name has been utilized, review to shorten the name to twenty characters or less. '
|
|
1087
|
+
'Invalid filenames: %(invalidBasenames)s'))
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
@validation(
|
|
1091
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1092
|
+
disclosureSystems=[
|
|
1093
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1094
|
+
],
|
|
1095
|
+
)
|
|
1096
|
+
def rule_nl_kvk_4_1_5_2(
|
|
1097
|
+
pluginData: PluginValidationDataExtension,
|
|
1098
|
+
val: ValidateXbrl,
|
|
1099
|
+
*args: Any,
|
|
1100
|
+
**kwargs: Any,
|
|
1101
|
+
) -> Iterable[Validation]:
|
|
1102
|
+
"""
|
|
1103
|
+
NL-KVK.4.1.5.2: Extension document filename SHOULD match the {base}-{date}_{suffix}-{lang}.{extension} pattern.
|
|
1104
|
+
"""
|
|
1105
|
+
invalidBasenames = []
|
|
1106
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1107
|
+
for extensionDocument in extensionData.extensionDocuments.values():
|
|
1108
|
+
basename = extensionDocument.basename
|
|
1109
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getExtensionFilenameFormatPattern())
|
|
1110
|
+
if not filenameParts:
|
|
1111
|
+
invalidBasenames.append(basename)
|
|
1112
|
+
if len(invalidBasenames) > 0:
|
|
1113
|
+
yield Validation.warning(
|
|
1114
|
+
codes='NL.NL-KVK.4.1.5.2.extensionTaxonomyDocumentNameDoesNotFollowNamingConvention',
|
|
1115
|
+
invalidBasenames=', '.join(invalidBasenames),
|
|
1116
|
+
msg=_('The extension document filename does not match the naming convention outlined by the KVK. '
|
|
1117
|
+
'It is recommended to be in the {base}-{date}_{suffix}-{lang}.{extension} format. '
|
|
1118
|
+
'{extension} must be one of the following: html, htm, xhtml. '
|
|
1119
|
+
'Review formatting and update as appropriate. '
|
|
1120
|
+
'Invalid filenames: %(invalidBasenames)s'))
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
@validation(
|
|
1124
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1125
|
+
disclosureSystems=[
|
|
1126
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1127
|
+
],
|
|
1128
|
+
)
|
|
1129
|
+
def rule_nl_kvk_4_2_0_1(
|
|
1130
|
+
pluginData: PluginValidationDataExtension,
|
|
1131
|
+
val: ValidateXbrl,
|
|
1132
|
+
*args: Any,
|
|
1133
|
+
**kwargs: Any,
|
|
1134
|
+
) -> Iterable[Validation]:
|
|
1135
|
+
"""
|
|
1136
|
+
NL-KVK.4.2.0.1: Tuples MUST NOT be defined in extension taxonomy.
|
|
1137
|
+
"""
|
|
1138
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1139
|
+
tupleConcepts = [
|
|
1140
|
+
concept for concept in extensionData.extensionConcepts if concept.isTuple
|
|
1141
|
+
]
|
|
1142
|
+
if len(tupleConcepts) > 0:
|
|
1143
|
+
yield Validation.error(
|
|
1144
|
+
codes='NL.NL-KVK.4.2.0.1.tupleElementUsed',
|
|
1145
|
+
modelObject=tupleConcepts,
|
|
1146
|
+
msg=_('The extension taxonomy must not define tuple concepts.'))
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
@validation(
|
|
1150
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1151
|
+
disclosureSystems=[
|
|
1152
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1153
|
+
],
|
|
1154
|
+
)
|
|
1155
|
+
def rule_nl_kvk_4_2_0_2(
|
|
1156
|
+
pluginData: PluginValidationDataExtension,
|
|
1157
|
+
val: ValidateXbrl,
|
|
1158
|
+
*args: Any,
|
|
1159
|
+
**kwargs: Any,
|
|
1160
|
+
) -> Iterable[Validation]:
|
|
1161
|
+
"""
|
|
1162
|
+
NL-KVK.4.2.0.2: Items with xbrli:fractionItemType data type MUST NOT be defined in extension taxonomy
|
|
1163
|
+
"""
|
|
1164
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1165
|
+
fractionConcepts = [
|
|
1166
|
+
concept for concept in extensionData.extensionConcepts if concept.isFraction
|
|
1167
|
+
]
|
|
1168
|
+
if len(fractionConcepts) > 0:
|
|
1169
|
+
yield Validation.error(
|
|
1170
|
+
codes='NL.NL-KVK.4.2.0.2.fractionElementUsed',
|
|
1171
|
+
modelObject=fractionConcepts,
|
|
1172
|
+
msg=_('The extension taxonomy must not define fraction concepts.'))
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
@validation(
|
|
1176
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1177
|
+
disclosureSystems=[
|
|
1178
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1179
|
+
],
|
|
1180
|
+
)
|
|
1181
|
+
def rule_nl_kvk_4_2_1_1(
|
|
1182
|
+
pluginData: PluginValidationDataExtension,
|
|
1183
|
+
val: ValidateXbrl,
|
|
1184
|
+
*args: Any,
|
|
1185
|
+
**kwargs: Any,
|
|
1186
|
+
) -> Iterable[Validation]:
|
|
1187
|
+
"""
|
|
1188
|
+
NL-KVK.4.2.1.1: Extension taxonomy MUST set xbrli:scenario as context element on definition arcs with
|
|
1189
|
+
http://xbrl.org/int/dim/arcrole/all and http://xbrl.org/int/dim/arcrole/notAll arcroles.
|
|
1190
|
+
"""
|
|
1191
|
+
errors = []
|
|
1192
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1193
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1194
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.all, XbrlConst.notAll}):
|
|
1195
|
+
if arc.get(XbrlConst.qnXbrldtContextElement.clarkNotation) != "scenario":
|
|
1196
|
+
errors.append(arc)
|
|
1197
|
+
if len(errors) > 0:
|
|
1198
|
+
yield Validation.error(
|
|
1199
|
+
codes='NL.NL-KVK.4.2.1.1.scenarioNotUsedInExtensionTaxonomy',
|
|
1200
|
+
modelObject=errors,
|
|
1201
|
+
msg=_('The definition linkbase is missing xbrli:scenario in extension taxonomy. '
|
|
1202
|
+
'Review definition linkbase and update as appropriate.'),
|
|
1203
|
+
)
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
@validation(
|
|
1207
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1208
|
+
disclosureSystems=[
|
|
1209
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1210
|
+
],
|
|
1211
|
+
)
|
|
1212
|
+
def rule_nl_kvk_4_4_1_1(
|
|
1213
|
+
pluginData: PluginValidationDataExtension,
|
|
1214
|
+
val: ValidateXbrl,
|
|
1215
|
+
*args: Any,
|
|
1216
|
+
**kwargs: Any,
|
|
1217
|
+
) -> Iterable[Validation]:
|
|
1218
|
+
"""
|
|
1219
|
+
NL-KVK.4.4.1.1: Arithmetical relationships defined in the calculation linkbase of an extension taxonomy
|
|
1220
|
+
MUST use the https://xbrl.org/2023/arcrole/summation-item arcrole as defined in Calculation 1.1 specification.
|
|
1221
|
+
"""
|
|
1222
|
+
errors = []
|
|
1223
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1224
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1225
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.CALCULATION, excludeArcroles={XbrlConst.summationItem11}):
|
|
1226
|
+
errors.append(arc)
|
|
1227
|
+
if len(errors) > 0:
|
|
1228
|
+
yield Validation.error(
|
|
1229
|
+
codes='NL.NL-KVK.4.4.1.1.incorrectSummationItemArcroleUsed',
|
|
1230
|
+
modelObject=errors,
|
|
1231
|
+
msg=_('Calculation relationships should follow the requirements of the Calculation 1.1 specification. '
|
|
1232
|
+
'Update to ensure use of summation-item arcrole in the calculation linkbase.'),
|
|
1233
|
+
)
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
@validation(
|
|
1237
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1238
|
+
disclosureSystems=[
|
|
1239
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1240
|
+
],
|
|
1241
|
+
)
|
|
1242
|
+
def rule_nl_kvk_4_4_2_1(
|
|
1243
|
+
pluginData: PluginValidationDataExtension,
|
|
1244
|
+
val: ValidateXbrl,
|
|
1245
|
+
*args: Any,
|
|
1246
|
+
**kwargs: Any,
|
|
1247
|
+
) -> Iterable[Validation]:
|
|
1248
|
+
"""
|
|
1249
|
+
NL-KVK.4.4.2.1: Extension taxonomies MUST NOT define definition arcs
|
|
1250
|
+
with http://xbrl.org/int/dim/arcrole/notAll arcrole.
|
|
1251
|
+
"""
|
|
1252
|
+
errors = []
|
|
1253
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1254
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1255
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.notAll}):
|
|
1256
|
+
errors.append(arc)
|
|
1257
|
+
if len(errors) > 0:
|
|
1258
|
+
yield Validation.error(
|
|
1259
|
+
codes='NL.NL-KVK.4.4.2.1.notAllArcroleUsedInDefinitionLinkbase',
|
|
1260
|
+
modelObject=errors,
|
|
1261
|
+
msg=_('Incorrect hypercube settings are found. Ensure that positive hypercubes are in use.'),
|
|
1262
|
+
)
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
@validation(
|
|
1266
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1267
|
+
disclosureSystems=[
|
|
1268
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1269
|
+
],
|
|
1270
|
+
)
|
|
1271
|
+
def rule_nl_kvk_4_4_2_2(
|
|
1272
|
+
pluginData: PluginValidationDataExtension,
|
|
1273
|
+
val: ValidateXbrl,
|
|
1274
|
+
*args: Any,
|
|
1275
|
+
**kwargs: Any,
|
|
1276
|
+
) -> Iterable[Validation]:
|
|
1277
|
+
"""
|
|
1278
|
+
NL-KVK.4.4.2.2: Hypercubes appearing as target of definition arc with
|
|
1279
|
+
http://xbrl.org/int/dim/arcrole/all arcrole MUST have xbrldt:closed attribute set to “true”.
|
|
1280
|
+
"""
|
|
1281
|
+
errors = []
|
|
1282
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1283
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1284
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.all}):
|
|
1285
|
+
if arc.get(XbrlConst.qnXbrldtClosed.clarkNotation, "false") != "true":
|
|
1286
|
+
errors.append(arc)
|
|
1287
|
+
if len(errors) > 0:
|
|
1288
|
+
yield Validation.error(
|
|
1289
|
+
codes='NL.NL-KVK.4.4.2.2.openPositiveHypercubeInDefinitionLinkbase',
|
|
1290
|
+
modelObject=errors,
|
|
1291
|
+
msg=_('Incorrect hypercube settings are found. Ensure that positive hypercubes are closed.'),
|
|
1292
|
+
)
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
@validation(
|
|
1296
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1297
|
+
disclosureSystems=[
|
|
1298
|
+
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1299
|
+
],
|
|
1300
|
+
)
|
|
1301
|
+
def rule_nl_kvk_4_4_2_3(
|
|
1302
|
+
pluginData: PluginValidationDataExtension,
|
|
1303
|
+
val: ValidateXbrl,
|
|
1304
|
+
*args: Any,
|
|
1305
|
+
**kwargs: Any,
|
|
1306
|
+
) -> Iterable[Validation]:
|
|
1307
|
+
"""
|
|
1308
|
+
NL-KVK.4.4.2.3: Hypercubes appearing as target of definition arc with
|
|
1309
|
+
http://xbrl.org/int/dim/arcrole/notAll arcrole MUST have xbrldt:closed attribute set to “false”.
|
|
1310
|
+
"""
|
|
1311
|
+
errors = []
|
|
1312
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1313
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1314
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.notAll}):
|
|
1315
|
+
if arc.get(XbrlConst.qnXbrldtClosed.clarkNotation, "true") != "false":
|
|
1316
|
+
errors.append(arc)
|
|
1317
|
+
if len(errors) > 0:
|
|
1318
|
+
yield Validation.error(
|
|
1319
|
+
codes='NL.NL-KVK.4.4.2.3.closedNegativeHypercubeInDefinitionLinkbase',
|
|
1320
|
+
modelObject=errors,
|
|
1321
|
+
msg=_('Incorrect hypercube settings are found. Ensure that negative hypercubes are not closed.'),
|
|
1322
|
+
)
|
|
935
1323
|
|
|
936
1324
|
|
|
937
1325
|
@validation(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
arelle/Aspect.py,sha256=Pn9I91D1os1RTVj6htuxTfRzVMhmVDtrbKvV_zy9xMI,5470
|
|
2
2
|
arelle/BetaFeatures.py,sha256=T_tPac-FiozHyYLCemt0RoHJ1JahUE71L-0tHmIRKpE,858
|
|
3
3
|
arelle/Cntlr.py,sha256=sf5Xe19t5E0wKzhdlXl1p5r6gMtCmPhYAi8RVY0jz7Y,30449
|
|
4
|
-
arelle/CntlrCmdLine.py,sha256=
|
|
4
|
+
arelle/CntlrCmdLine.py,sha256=uCpv_MaDGwMX1A3EZdN5h678aDaI0MTgRCQwOEKlimY,90250
|
|
5
5
|
arelle/CntlrComServer.py,sha256=h1KPf31uMbErpxTZn_iklDqUMGFgQnjZkFkFjd8gtLQ,1888
|
|
6
6
|
arelle/CntlrProfiler.py,sha256=2VQJudiUhxryVypxjODx2ccP1-n60icTiWs5lSEokhQ,972
|
|
7
7
|
arelle/CntlrQuickBooks.py,sha256=BMqd5nkNQOZyNFPefkTeWUUDCYNS6BQavaG8k1Lepu4,31543
|
|
@@ -56,7 +56,7 @@ arelle/PluginUtils.py,sha256=0vFQ29wVVpU0cTY3YOBL6FhNQhhCTwShBH4qTJGLnvc,2426
|
|
|
56
56
|
arelle/PrototypeDtsObject.py,sha256=0lf60VcXR_isx57hBPrc7vEMkFpYkVuK4JVBSmopzkQ,7989
|
|
57
57
|
arelle/PrototypeInstanceObject.py,sha256=CXUoDllhDqpMvSQjqIYi1Ywp-J8fLhQRV9wVD2YXgVo,13204
|
|
58
58
|
arelle/PythonUtil.py,sha256=pkh3-XixCOiVHhGlrt8l0va-iWCtkyO5ZMjEvNAadRA,12524
|
|
59
|
-
arelle/RuntimeOptions.py,sha256=
|
|
59
|
+
arelle/RuntimeOptions.py,sha256=XjTxA2tcdc_P2v7xZGTx_-imjOqtcl48ch3S-Q-q-7Y,8462
|
|
60
60
|
arelle/SocketUtils.py,sha256=1wa2sA_QhM8F1klHFq90V1AgO1-hY9pJm0554FiF7Lc,677
|
|
61
61
|
arelle/SystemInfo.py,sha256=6330pNedRkAPlEKl-ZdaZHiGuucEGZMI-Jrdy7B1rrU,2454
|
|
62
62
|
arelle/TableStructure.py,sha256=PABOHJiTa56cHyF9qRLD7TohmCHyDTrGEltW8toP_rk,29409
|
|
@@ -114,7 +114,7 @@ arelle/ViewWinVersReport.py,sha256=aYfsOgynVZpMzl6f2EzQCBLzdihYGycwb5SiTghkgMQ,9
|
|
|
114
114
|
arelle/ViewWinXml.py,sha256=4ZGKtjaoCwU9etKYm9ZAS7jSmUxba1rqNEdv0OIyjTY,1250
|
|
115
115
|
arelle/WatchRss.py,sha256=5Ih4igH2MM4hpOuAXy9eO0QAyZ7jZR3S5bPzo2sdFpw,14097
|
|
116
116
|
arelle/WebCache.py,sha256=B62IxIHLX4hcDr_0MJGfmzUXau2ONqiMk6vLVLxAIhA,45057
|
|
117
|
-
arelle/XbrlConst.py,sha256=
|
|
117
|
+
arelle/XbrlConst.py,sha256=7Pk386ZP5-zeQspyajgl-y34hq9LxpaYHTKrHq5Km-8,56958
|
|
118
118
|
arelle/XbrlUtil.py,sha256=s2Vmrh-sZI5TeuqsziKignOc3ao-uUgnCNoelP4dDj0,9212
|
|
119
119
|
arelle/XhtmlValidate.py,sha256=0gtm7N-kXK0RB5o3c1AQXjfFuRp1w2fKZZAeyruNANw,5727
|
|
120
120
|
arelle/XmlUtil.py,sha256=1VToOOylF8kbEorEdZLThmq35j9bmuF_DS2q9NthnHU,58774
|
|
@@ -123,9 +123,9 @@ arelle/XmlValidateConst.py,sha256=U_wN0Q-nWKwf6dKJtcu_83FXPn9c6P8JjzGA5b0w7P0,33
|
|
|
123
123
|
arelle/XmlValidateParticles.py,sha256=Mn6vhFl0ZKC_vag1mBwn1rH_x2jmlusJYqOOuxFPO2k,9231
|
|
124
124
|
arelle/XmlValidateSchema.py,sha256=6frtZOc1Yrx_5yYF6V6oHbScnglWrVbWr6xW4EHtLQI,7428
|
|
125
125
|
arelle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
126
|
-
arelle/_version.py,sha256=
|
|
126
|
+
arelle/_version.py,sha256=7J7GR3gzAoXDRoz2kLGCfdxRcD180tJLB4oVmPwBN4k,515
|
|
127
127
|
arelle/typing.py,sha256=PRe-Fxwr2SBqYYUVPCJ3E7ddDX0_oOISNdT5Q97EbRM,1246
|
|
128
|
-
arelle/api/Session.py,sha256=
|
|
128
|
+
arelle/api/Session.py,sha256=DE45eTuhPkIPsLj0IFqDc9gMq2XoUf-aMBgW19MeGbE,6523
|
|
129
129
|
arelle/archive/CustomLogger.py,sha256=v_JXOCQLDZcfaFWzxC9FRcEf9tQi4rCI4Sx7jCuAVQI,1231
|
|
130
130
|
arelle/archive/LoadEFMvalidate.py,sha256=HR1ZJmOvWGUlWEsWd0tGCa2TTtZSNzeL6tgN1TFfrl0,986
|
|
131
131
|
arelle/archive/LoadSavePreLbCsv.py,sha256=mekr1R6OE5d3xdUCZIVfSeolyet0HO8R6wsHnW4eyaA,767
|
|
@@ -410,16 +410,17 @@ arelle/plugin/validate/FERC/__init__.py,sha256=V4fXcFKBsjFFPs9_1NhvDjWpEQCoQM0tR
|
|
|
410
410
|
arelle/plugin/validate/FERC/config.xml,sha256=bn9b8eCqJA1J62rYq1Nz85wJrMGAahVmmnIUQZyerjo,1919
|
|
411
411
|
arelle/plugin/validate/FERC/resources/ferc-utr.xml,sha256=OCRj9IUpdXATCBXKbB71apYx9kxcNtZW-Hq4s-avsRY,2663
|
|
412
412
|
arelle/plugin/validate/NL/DisclosureSystems.py,sha256=kTjpxkgwn58wHCbaLRBInirOy-2cpK9MLWEFJ_193y4,180
|
|
413
|
-
arelle/plugin/validate/NL/
|
|
414
|
-
arelle/plugin/validate/NL/
|
|
415
|
-
arelle/plugin/validate/NL/
|
|
413
|
+
arelle/plugin/validate/NL/LinkbaseType.py,sha256=csXEqLaU43tN58RUG3oeD3nUYcdHl1OWSKaxpOhbTXk,2515
|
|
414
|
+
arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=bvyz-GKCaHs-Y0ifIxIh5FqN73Eqd3OPW4O8HWtup5E,24065
|
|
415
|
+
arelle/plugin/validate/NL/ValidationPluginExtension.py,sha256=0Ze1RFTlnHeAeDnMG-dAVT7WKrgNQ2iflMm87ZnVwLQ,15601
|
|
416
|
+
arelle/plugin/validate/NL/__init__.py,sha256=23cF5ih2wu0RO_S0B52nVB7LrdlmnYcctOUezF0kKQ8,2874
|
|
416
417
|
arelle/plugin/validate/NL/resources/config.xml,sha256=i_ns2wHmQYjhkRItevRR8tzfkl31ASfbWlc5t6pDB-w,1117
|
|
417
418
|
arelle/plugin/validate/NL/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
418
419
|
arelle/plugin/validate/NL/rules/br_kvk.py,sha256=0SwKieWzTDm3YMsXPS6zTdgbk7_Z9CzqRkRmCRz1OiQ,15789
|
|
419
420
|
arelle/plugin/validate/NL/rules/fg_nl.py,sha256=4Puq5wAjtK_iNd4wisH_R0Z_EKJ7MT2OCai5g4t1MPE,10714
|
|
420
421
|
arelle/plugin/validate/NL/rules/fr_kvk.py,sha256=-_BLeWGoZ_f56p5VO4X40S45Ny3Ej-WK6Srei1KVSxU,8170
|
|
421
422
|
arelle/plugin/validate/NL/rules/fr_nl.py,sha256=-M1WtXp06khhtkfOVPCa-b8UbC281gk4YfDhvtAVlnI,31424
|
|
422
|
-
arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=
|
|
423
|
+
arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=0jiagDyV1x7Qh6evVLz9eeJLbyAD9ZUI9Wk_yX0mVNU,50380
|
|
423
424
|
arelle/plugin/validate/ROS/DisclosureSystems.py,sha256=rJ81mwQDYTi6JecFZ_zhqjjz3VNQRgjHNSh0wcQWAQE,18
|
|
424
425
|
arelle/plugin/validate/ROS/PluginValidationDataExtension.py,sha256=IV7ILhNvgKwQXqbpSA6HRNt9kEnejCyMADI3wyyIgk0,4036
|
|
425
426
|
arelle/plugin/validate/ROS/ValidationPluginExtension.py,sha256=FBhEp8t396vGdvCbMEimfcxmGiGnhXMen-yVLWnkFaI,758
|
|
@@ -741,7 +742,7 @@ arelle/utils/validate/ValidationUtil.py,sha256=9vmSvShn-EdQy56dfesyV8JjSRVPj7txr
|
|
|
741
742
|
arelle/utils/validate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
742
743
|
arelle/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
743
744
|
arelle/webserver/bottle.py,sha256=P-JECd9MCTNcxCnKoDUvGcoi03ezYVOgoWgv2_uH-6M,362
|
|
744
|
-
arelle_release-2.37.
|
|
745
|
+
arelle_release-2.37.21.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
|
|
745
746
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
746
747
|
tests/integration_tests/download_cache.py,sha256=jVMIVICsZjcVc9DCPPu3fCjF9_cWSS3tqSynhFs3oAM,4097
|
|
747
748
|
tests/integration_tests/integration_test_util.py,sha256=H7mncbv0T9ZeVyrtk9Hohe3k6jgcYykHkt-LGE-Q9aQ,10270
|
|
@@ -796,7 +797,7 @@ tests/integration_tests/validation/conformance_suite_configurations/kvk_nt16.py,
|
|
|
796
797
|
tests/integration_tests/validation/conformance_suite_configurations/kvk_nt17.py,sha256=lmEZonthFm0YKFmp1dwXtdJ2T7txUeSpL4mbAo8fl4Y,1292
|
|
797
798
|
tests/integration_tests/validation/conformance_suite_configurations/kvk_nt18.py,sha256=EG2RQVkvFENhzUF3fl3QvDnH7ZPYS1n1Fo8bhfmSczM,1205
|
|
798
799
|
tests/integration_tests/validation/conformance_suite_configurations/kvk_nt19.py,sha256=FAzf9RhRmn_8yowpplJho2zEspX9FxJiVq8SjZT3Dsc,1199
|
|
799
|
-
tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py,sha256=
|
|
800
|
+
tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py,sha256=K24GT014o_d3-cvuAkkkzGeo_JDxBh_pWuyYWXo9xLI,10470
|
|
800
801
|
tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py,sha256=O_LFVBZPkjxmbrU7_C7VTLtrdoCUx2bYXOXw6_MlRtQ,846
|
|
801
802
|
tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py,sha256=aTN3Ez6lPsZsuypHZP84DneOtYxUZSjUiGypHy6ofHQ,846
|
|
802
803
|
tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py,sha256=sqHLjrHc95dTu0guTgKkphaKM1zNfKGnN4GKkZDLzeU,845
|
|
@@ -1579,7 +1580,7 @@ tests/unit_tests/arelle/test_ordered_set.py,sha256=GkJgvdWIME5g5f3MD0tWJmAI6-aej
|
|
|
1579
1580
|
tests/unit_tests/arelle/test_packagemanager.py,sha256=Gs4J0cmB35czCIXj7xXhDlPLG9r68D5GGfZH8PKjMfw,2566
|
|
1580
1581
|
tests/unit_tests/arelle/test_pluginmanager.py,sha256=_Gi03PP-6FZ7mWqe2ysS_N_suOQamRHYhAuWolfKGug,5920
|
|
1581
1582
|
tests/unit_tests/arelle/test_qname.py,sha256=0aKh6jYWmY4Xg3wOS839Tdqa1SHwHuha6akv5T6qddY,4892
|
|
1582
|
-
tests/unit_tests/arelle/test_runtimeoptions.py,sha256=
|
|
1583
|
+
tests/unit_tests/arelle/test_runtimeoptions.py,sha256=OB4ds28ODYjzgm9wlojd_fIRf7iRGOmDaPgxm4kiCwM,1315
|
|
1583
1584
|
tests/unit_tests/arelle/test_system_info.py,sha256=G9VtKX9WCaas2D2s-Yw-4kcq6_zcY-LkjOveGvQNvZI,655
|
|
1584
1585
|
tests/unit_tests/arelle/test_updater.py,sha256=8DDHTpog8l9T8fHhHtrE9coPWTyFCgf-BCDm9nTtr6E,16163
|
|
1585
1586
|
tests/unit_tests/arelle/test_urlutil.py,sha256=3WTHxic3XiiOGZQxkHm9m97kFbLHOc27oXypU8fFt1w,914
|
|
@@ -1594,8 +1595,8 @@ tests/unit_tests/arelle/oim/test_load.py,sha256=NxiUauQwJVfWAHbbpsMHGSU2d3Br8Pki
|
|
|
1594
1595
|
tests/unit_tests/arelle/plugin/test_plugin_imports.py,sha256=bdhIs9frAnFsdGU113yBk09_jis-z43dwUItMFYuSYM,1064
|
|
1595
1596
|
tests/unit_tests/arelle/plugin/validate/ESEF/ESEF_Current/test_validate_css_url.py,sha256=XHABmejQt7RlZ0udh7v42f2Xb2STGk_fSaIaJ9i2xo0,878
|
|
1596
1597
|
tests/unit_tests/arelle/utils/validate/test_decorator.py,sha256=ZS8FqIY1g-2FCbjF4UYm609dwViax6qBMRJSi0vfuhY,2482
|
|
1597
|
-
arelle_release-2.37.
|
|
1598
|
-
arelle_release-2.37.
|
|
1599
|
-
arelle_release-2.37.
|
|
1600
|
-
arelle_release-2.37.
|
|
1601
|
-
arelle_release-2.37.
|
|
1598
|
+
arelle_release-2.37.21.dist-info/METADATA,sha256=XKmpRZx95BpPCfr3HGOZd2y9DH8Rypx2up7QJSp_bgY,9134
|
|
1599
|
+
arelle_release-2.37.21.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
1600
|
+
arelle_release-2.37.21.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
|
|
1601
|
+
arelle_release-2.37.21.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
|
|
1602
|
+
arelle_release-2.37.21.dist-info/RECORD,,
|
|
@@ -19,10 +19,15 @@ config = ConformanceSuiteConfig(
|
|
|
19
19
|
*NL_PACKAGES['NL-INLINE-2024'],
|
|
20
20
|
],
|
|
21
21
|
expected_additional_testcase_errors={f"conformance-suite-2024-sbr-domein-handelsregister/tests/{s}": val for s, val in {
|
|
22
|
+
'G3-1-3_1/index.xml:TC2_invalid': {
|
|
23
|
+
'scenarioNotUsedInExtensionTaxonomy': 1, # Also fails 4.2.1.1
|
|
24
|
+
},
|
|
22
25
|
'G3-5-3_1/index.xml:TC2_invalid': {
|
|
23
26
|
'arelle:ixdsTargetNotDefined': 1,
|
|
27
|
+
'extensionTaxonomyWrongFilesStructure': 1,
|
|
24
28
|
# This test is looking at the usage of the target attribute and does not import the correct taxonomy urls
|
|
25
29
|
'requiredEntryPointNotImported': 1,
|
|
30
|
+
'incorrectKvkTaxonomyVersionUsed': 1,
|
|
26
31
|
},
|
|
27
32
|
'G3-6-3_3/index.xml:TC2_invalid': {
|
|
28
33
|
# Testcase expects only 3.6.3.3, but has a filename that has invalid characters (3.6.3.3)
|
|
@@ -37,15 +42,27 @@ config = ConformanceSuiteConfig(
|
|
|
37
42
|
'undefinedLanguageForTextFact': 1,
|
|
38
43
|
'taggedTextFactOnlyInLanguagesOtherThanLanguageOfAReport': 5,
|
|
39
44
|
},
|
|
45
|
+
'G4-1-2_2/index.xml:TC2_invalid': {
|
|
46
|
+
'incorrectSummationItemArcroleUsed': 1, # Also fails 4.4.1.1
|
|
47
|
+
# Test imports https://www.nltaxonomie.nl/kvk/2024-03-31/kvk-annual-report-nlgaap-ext.xsd which is the draft taxonomy and not the final
|
|
48
|
+
'requiredEntryPointNotImported': 1,
|
|
49
|
+
},
|
|
50
|
+
'G4-4-2_1/index.xml:TC2_invalid': {
|
|
51
|
+
'closedNegativeHypercubeInDefinitionLinkbase': 1, # Also fails 4.4.2.3
|
|
52
|
+
},
|
|
40
53
|
'G5-1-3_1/index.xml:TC1_valid': {
|
|
54
|
+
'extensionTaxonomyWrongFilesStructure': 1,
|
|
41
55
|
# This test is looking at the import of the Other GAAP entry point and thus does not import
|
|
42
56
|
# the standard GAAP or IFRS
|
|
43
57
|
'requiredEntryPointNotImported': 1,
|
|
58
|
+
'incorrectKvkTaxonomyVersionUsed': 1,
|
|
44
59
|
},
|
|
45
60
|
'G5-1-3_2/index.xml:TC1_valid': {
|
|
61
|
+
'extensionTaxonomyWrongFilesStructure': 1,
|
|
46
62
|
# This test is looking at the import of the Other GAAP entry point and thus does not import
|
|
47
63
|
# the standard GAAP or IFRS
|
|
48
64
|
'requiredEntryPointNotImported': 1,
|
|
65
|
+
'incorrectKvkTaxonomyVersionUsed': 1,
|
|
49
66
|
},
|
|
50
67
|
'RTS_Annex_II_Par_1_RTS_Annex_IV_par_7/index.xml:TC2_valid': {
|
|
51
68
|
'undefinedLanguageForTextFact': 1,
|
|
@@ -73,6 +90,8 @@ config = ConformanceSuiteConfig(
|
|
|
73
90
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_1/index.xml:TC2_invalid', # Produces: [err:XPTY0004] Variable set Het entity identifier scheme dat bij dit feit hoort MOET het standaard KVK identifier scheme zijn
|
|
74
91
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_2/index.xml:TC2_invalid', # Expects fractionElementUsed”. Note the double quote at the end.
|
|
75
92
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-2_1/index.xml:TC2_invalid', # Produces 'EFM.6.03.11' and 'NL.NL-KVK.3.4.2.1.htmlOrXmlBaseUsed'
|
|
93
|
+
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-0_2/index.xml:TC2_invalid', # Expects fractionElementUsed”. Note the double quote at the end.
|
|
94
|
+
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-1_1/index.xml:TC2_invalid', # Expects IncorrectSummationItemArcroleUsed. Note the capital first character.
|
|
76
95
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_2_G3-1-1_1/index.xml:TC2_invalid', # Expects NonIdenticalIdentifier instead of nonIdenticalIdentifier (note the cap N)
|
|
77
96
|
|
|
78
97
|
|
|
@@ -85,27 +104,12 @@ config = ConformanceSuiteConfig(
|
|
|
85
104
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_5/index.xml:TC2_invalid',
|
|
86
105
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_5/index.xml:TC3_invalid',
|
|
87
106
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-6-2_1/index.xml:TC2_invalid',
|
|
88
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC3_invalid',
|
|
89
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC4_invalid',
|
|
90
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC5_invalid',
|
|
91
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC6_invalid',
|
|
92
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC7_invalid',
|
|
93
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_2/index.xml:TC2_invalid',
|
|
94
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_2/index.xml:TC3_invalid',
|
|
95
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-2_2/index.xml:TC2_invalid',
|
|
96
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-0_1/index.xml:TC2_invalid',
|
|
97
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-0_2/index.xml:TC2_invalid',
|
|
98
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-1_1/index.xml:TC2_invalid', # Expects scenarioNotUsedInExtensionTaxonomy and segmentUsed errors. scenarioNotUsedInExtensionTaxonomy not yet implemented.
|
|
99
107
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-2_2/index.xml:TC2_invalid',
|
|
100
108
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-3_1/index.xml:TC2_invalid',
|
|
101
109
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-1_1/index.xml:TC2_invalid',
|
|
102
110
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-1_1/index.xml:TC3_invalid',
|
|
103
111
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-1_1/index.xml:TC4_invalid',
|
|
104
112
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-2_1/index.xml:TC2_invalid',
|
|
105
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-1_1/index.xml:TC2_invalid',
|
|
106
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_1/index.xml:TC2_invalid',
|
|
107
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_2/index.xml:TC2_invalid',
|
|
108
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_3/index.xml:TC2_invalid',
|
|
109
113
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_4/index.xml:TC2_invalid',
|
|
110
114
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-3_1/index.xml:TC2_invalid',
|
|
111
115
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-3_1/index.xml:TC3_invalid',
|
|
@@ -130,7 +134,6 @@ config = ConformanceSuiteConfig(
|
|
|
130
134
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_3/index.xml:TC5_invalid',
|
|
131
135
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_5/index.xml:TC2_invalid',
|
|
132
136
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_5/index.xml:TC3_invalid',
|
|
133
|
-
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_6/index.xml:TC3_invalid',
|
|
134
137
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_6/index.xml:TC4_invalid',
|
|
135
138
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_8_G4-4-5/index.xml:TC2_invalid',
|
|
136
139
|
'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_8_G4-4-5/index.xml:TC3_invalid',
|
|
@@ -32,19 +32,6 @@ def test_incorrect_arguments_with_webserver():
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
@patch('arelle.RuntimeOptions.hasWebServer')
|
|
36
|
-
def test_incorrect_arguments(mockwebserver):
|
|
37
|
-
with pytest.raises(RuntimeOptionsException, match="Incorrect arguments"):
|
|
38
|
-
mockwebserver.return_value = False
|
|
39
|
-
RuntimeOptions(
|
|
40
|
-
entrypointFile=None,
|
|
41
|
-
proxy=None,
|
|
42
|
-
plugins=None,
|
|
43
|
-
pluginOptions=None,
|
|
44
|
-
webserver=None,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
|
|
48
35
|
def test_set_runtime_options():
|
|
49
36
|
runtimeOptions = RuntimeOptions(
|
|
50
37
|
abortOnMajorError=True,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|