arelle-release 2.37.19__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/FileSource.py +2 -2
- arelle/ModelInstanceObject.py +1 -1
- arelle/ModelXbrl.py +1 -1
- arelle/RuntimeOptions.py +0 -6
- arelle/XbrlConst.py +2 -0
- arelle/_version.py +2 -2
- arelle/api/Session.py +7 -5
- arelle/formula/XPathContext.py +22 -22
- arelle/formula/XPathParser.py +2 -2
- arelle/plugin/OimTaxonomy/ModelValueMore.py +2 -2
- arelle/plugin/OimTaxonomy/ViewXbrlTxmyObj.py +2 -3
- arelle/plugin/OimTaxonomy/XbrlConcept.py +2 -1
- arelle/plugin/OimTaxonomy/XbrlCube.py +8 -8
- arelle/plugin/OimTaxonomy/XbrlDts.py +5 -5
- arelle/plugin/OimTaxonomy/XbrlImportedTaxonomy.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlNetwork.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlProperty.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlReport.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlTableTemplate.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlTypes.py +1 -1
- arelle/plugin/OimTaxonomy/__init__.py +4 -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 +3 -3
- arelle/plugin/validate/NL/rules/nl_kvk.py +465 -17
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/METADATA +2 -1
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/RECORD +36 -35
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +23 -17
- tests/unit_tests/arelle/test_import.py +0 -30
- tests/unit_tests/arelle/test_runtimeoptions.py +0 -13
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/top_level.txt +0 -0
|
@@ -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'),
|
|
@@ -43,8 +43,8 @@ def disclosureSystemConfigURL(*args: Any, **kwargs: Any) -> str:
|
|
|
43
43
|
def modelXbrlLoadComplete(*args: Any, **kwargs: Any) -> ModelDocument | LoadingException | None:
|
|
44
44
|
return validationPlugin.modelXbrlLoadComplete(*args, **kwargs)
|
|
45
45
|
|
|
46
|
-
def
|
|
47
|
-
|
|
46
|
+
def validateFinally(*args: Any, **kwargs: Any) -> None:
|
|
47
|
+
return validationPlugin.validateFinally(*args, **kwargs)
|
|
48
48
|
|
|
49
49
|
def validateXbrlFinally(*args: Any, **kwargs: Any) -> None:
|
|
50
50
|
return validationPlugin.validateXbrlFinally(*args, **kwargs)
|
|
@@ -61,6 +61,6 @@ __pluginInfo__ = {
|
|
|
61
61
|
"DisclosureSystem.Types": disclosureSystemTypes,
|
|
62
62
|
"DisclosureSystem.ConfigURL": disclosureSystemConfigURL,
|
|
63
63
|
"ModelXbrl.LoadComplete": modelXbrlLoadComplete,
|
|
64
|
-
"Validate.XBRL.Start": validateXbrlStart,
|
|
65
64
|
"Validate.XBRL.Finally": validateXbrlFinally,
|
|
65
|
+
"ValidateFormula.Finished": validateFinally,
|
|
66
66
|
}
|