arelle-release 2.37.8__py3-none-any.whl → 2.37.10__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/FileSource.py CHANGED
@@ -272,8 +272,7 @@ class FileSource:
272
272
  assert isinstance(self.basefile, str)
273
273
  file: io.BufferedReader | io.BytesIO | io.StringIO | None = open(self.basefile, 'rb')
274
274
  assert isinstance(file, (io.BufferedReader, io.BytesIO))
275
- more = True
276
- while more:
275
+ while True:
277
276
  l = file.read(8)
278
277
  if len(l) < 8:
279
278
  break
arelle/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '2.37.8'
21
- __version_tuple__ = version_tuple = (2, 37, 8)
20
+ __version__ = version = '2.37.10'
21
+ __version_tuple__ = version_tuple = (2, 37, 10)
arelle/oim/Load.py CHANGED
@@ -839,7 +839,21 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
839
839
  filepath = modelXbrl.modelManager.cntlr.webCache.getfilename(mappedUrl) # , reload=reloadCache, checkModifiedTime=kwargs.get("checkModifiedTime",False))
840
840
  if filepath:
841
841
  url = modelXbrl.modelManager.cntlr.webCache.normalizeUrl(filepath)
842
- if filepath and filepath.endswith(".csv") or ("metadata" in filepath and filepath.endswith(".json")):
842
+ if filepath is None:
843
+ if extendingFile is None:
844
+ raise OIMException(
845
+ "oime:unresolvableFile",
846
+ _("Unable to resolve file %(oimFile)s. A taxonomy package may be required to load this report."),
847
+ oimFile=oimFile,
848
+ )
849
+ else:
850
+ raise OIMException(
851
+ "xbrlce:unresolvableBaseMetadataFile",
852
+ _("Unable to resolve extended metadata file %(extendingFile)s, referenced from %(oimFile)s. A taxonomy package may be required to load this report."),
853
+ extendingFile=extendingFile,
854
+ oimFile=oimFile,
855
+ )
856
+ if filepath.endswith(".csv") or ("metadata" in filepath and filepath.endswith(".json")):
843
857
  errPrefix = "xbrlce"
844
858
  else:
845
859
  errPrefix = "xbrlje"
@@ -8,6 +8,7 @@ from typing import cast, Any
8
8
  import regex as re
9
9
  from collections import defaultdict
10
10
  from dataclasses import dataclass
11
+ from functools import lru_cache
11
12
 
12
13
  from arelle.FunctionIxt import ixtNamespaces
13
14
  from arelle.ModelInstanceObject import ModelUnit, ModelContext, ModelFact, ModelInlineFootnote
@@ -25,6 +26,18 @@ DISALLOWED_IXT_NAMESPACES = frozenset((
25
26
  ixtNamespaces["ixt v3"],
26
27
  ))
27
28
 
29
+ @dataclass(frozen=True)
30
+ class ContextData:
31
+ contextsWithImproperContent: list[ModelContext | None]
32
+ contextsWithPeriodTime: list[ModelContext | None]
33
+ contextsWithPeriodTimeZone: list[ModelContext | None]
34
+ contextsWithSegments: list[ModelContext | None]
35
+
36
+ @dataclass(frozen=True)
37
+ class FootnoteData:
38
+ noMatchLangFootnotes: set[ModelInlineFootnote]
39
+ orphanedFootnotes: set[ModelInlineFootnote]
40
+
28
41
  @dataclass
29
42
  class PluginValidationDataExtension(PluginData):
30
43
  chamberOfCommerceRegistrationNumberQn: QName
@@ -41,28 +54,21 @@ class PluginValidationDataExtension(PluginData):
41
54
  textFormattingSchemaPath: str
42
55
  textFormattingWrapper: str
43
56
 
44
- _contextsByDocument: dict[str, list[ModelContext]] | None = None
45
- _contextsWithImproperContent: list[ModelContext | None] | None = None
46
- _contextsWithPeriodTime: list[ModelContext | None] | None = None
47
- _contextsWithPeriodTimeZone: list[ModelContext | None] | None = None
48
- _contextsWithSegments: list[ModelContext | None] | None = None
49
- _entityIdentifiers: set[tuple[str, str]] | None = None
50
- _factsByDocument: dict[str, list[ModelFact]] | None = None
51
- _factLangs: set[str] | None = None
52
- _noMatchLangFootnotes: set[ModelInlineFootnote] | None = None
53
- _orphanedFootnotes: set[ModelInlineFootnote] | None = None
54
- _unitsByDocument: dict[str, list[ModelUnit]] | None = None
57
+ # Identity hash for caching.
58
+ def __hash__(self) -> int:
59
+ return id(self)
55
60
 
61
+ @lru_cache(1)
56
62
  def contextsByDocument(self, modelXbrl: ModelXbrl) -> dict[str, list[ModelContext]]:
57
- if self._contextsByDocument is not None:
58
- return self._contextsByDocument
59
63
  contextsByDocument = defaultdict(list)
60
64
  for context in modelXbrl.contexts.values():
61
65
  contextsByDocument[context.modelDocument.filepath].append(context)
62
- self._contextsByDocument = dict(contextsByDocument)
63
- return self._contextsByDocument
66
+ contextsByDocument.default_factory = None
67
+ return contextsByDocument
64
68
 
65
- def checkContexts(self, allContexts: dict[str, list[ModelContext]]) -> None:
69
+ @lru_cache(1)
70
+ def checkContexts(self, modelXbrl: ModelXbrl) -> ContextData:
71
+ allContexts = self.contextsByDocument(modelXbrl)
66
72
  contextsWithImproperContent: list[ModelContext | None] = []
67
73
  contextsWithPeriodTime: list[ModelContext | None] = []
68
74
  contextsWithPeriodTimeZone: list[ModelContext | None] = []
@@ -84,12 +90,15 @@ class PluginValidationDataExtension(PluginData):
84
90
  contextsWithSegments.append(context)
85
91
  if context.nonDimValues("scenario"): # type: ignore[no-untyped-call]
86
92
  contextsWithImproperContent.append(context)
87
- self._contextsWithImproperContent = contextsWithImproperContent
88
- self._contextsWithPeriodTime = contextsWithPeriodTime
89
- self._contextsWithPeriodTimeZone = contextsWithPeriodTimeZone
90
- self._contextsWithSegments = contextsWithSegments
91
-
92
- def checkFootnote(self, modelXbrl: ModelXbrl) -> None:
93
+ return ContextData(
94
+ contextsWithImproperContent=contextsWithImproperContent,
95
+ contextsWithPeriodTime=contextsWithPeriodTime,
96
+ contextsWithPeriodTimeZone=contextsWithPeriodTimeZone,
97
+ contextsWithSegments=contextsWithSegments,
98
+ )
99
+
100
+ @lru_cache(1)
101
+ def checkFootnotes(self, modelXbrl: ModelXbrl) -> FootnoteData:
93
102
  factLangs = self.factLangs(modelXbrl)
94
103
  footnotesRelationshipSet = modelXbrl.relationshipSet("XBRL-footnotes")
95
104
  orphanedFootnotes = set()
@@ -101,77 +110,55 @@ class PluginValidationDataExtension(PluginData):
101
110
  if not any(isinstance(rel.fromModelObject, ModelFact)
102
111
  for rel in footnotesRelationshipSet.toModelObject(elt)):
103
112
  orphanedFootnotes.add(elt)
104
- if not elt.xmlLang in factLangs:
113
+ if elt.xmlLang not in factLangs:
105
114
  noMatchLangFootnotes.add(elt)
106
- self._noMatchLangFootnotes = noMatchLangFootnotes
107
- self._orphanedFootnotes = orphanedFootnotes
115
+ return FootnoteData(
116
+ noMatchLangFootnotes=noMatchLangFootnotes,
117
+ orphanedFootnotes=orphanedFootnotes,
118
+ )
108
119
 
120
+ @lru_cache(1)
109
121
  def entityIdentifiersInDocument(self, modelXbrl: ModelXbrl) -> set[tuple[str, str]]:
110
- if self._entityIdentifiers is not None:
111
- return self._entityIdentifiers
112
- self._entityIdentifiers = {context.entityIdentifier for context in modelXbrl.contexts.values()}
113
- return self._entityIdentifiers
122
+ return {context.entityIdentifier for context in modelXbrl.contexts.values()}
114
123
 
124
+ @lru_cache(1)
115
125
  def factsByDocument(self, modelXbrl: ModelXbrl) -> dict[str, list[ModelFact]]:
116
- if self._factsByDocument is not None:
117
- return self._factsByDocument
118
126
  factsByDocument = defaultdict(list)
119
127
  for fact in modelXbrl.facts:
120
128
  factsByDocument[fact.modelDocument.filepath].append(fact)
121
- self._factsByDocument = dict(factsByDocument)
122
- return self._factsByDocument
129
+ factsByDocument.default_factory = None
130
+ return factsByDocument
123
131
 
132
+ @lru_cache(1)
124
133
  def factLangs(self, modelXbrl: ModelXbrl) -> set[str]:
125
- if self._factLangs is not None:
126
- return self._factLangs
127
134
  factLangs = set()
128
135
  for fact in modelXbrl.facts:
129
136
  if fact is not None:
130
137
  factLangs.add(fact.xmlLang)
131
- self._factLangs = factLangs
132
- return self._factLangs
138
+ return factLangs
133
139
 
134
140
  def getContextsWithImproperContent(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
135
- if self._contextsWithImproperContent is None:
136
- self.checkContexts(self.contextsByDocument(modelXbrl))
137
- assert(self._contextsWithImproperContent is not None)
138
- return self._contextsWithImproperContent
141
+ return self.checkContexts(modelXbrl).contextsWithImproperContent
139
142
 
140
143
  def getContextsWithPeriodTime(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
141
- if self._contextsWithPeriodTime is None:
142
- self.checkContexts(self.contextsByDocument(modelXbrl))
143
- assert(self._contextsWithPeriodTime is not None)
144
- return self._contextsWithPeriodTime
144
+ return self.checkContexts(modelXbrl).contextsWithPeriodTime
145
145
 
146
146
  def getContextsWithPeriodTimeZone(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
147
- if self._contextsWithPeriodTimeZone is None:
148
- self.checkContexts(self.contextsByDocument(modelXbrl))
149
- assert (self._contextsWithPeriodTimeZone is not None)
150
- return self._contextsWithPeriodTimeZone
147
+ return self.checkContexts(modelXbrl).contextsWithPeriodTimeZone
151
148
 
152
149
  def getContextsWithSegments(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
153
- if self._contextsWithSegments is None:
154
- self.checkContexts(self.contextsByDocument(modelXbrl))
155
- assert(self._contextsWithSegments is not None)
156
- return self._contextsWithSegments
150
+ return self.checkContexts(modelXbrl).contextsWithSegments
157
151
 
158
152
  def getNoMatchLangFootnotes(self, modelXbrl: ModelXbrl) -> set[ModelInlineFootnote]:
159
- if self._noMatchLangFootnotes is None:
160
- self.checkFootnote(modelXbrl)
161
- assert(self._noMatchLangFootnotes is not None)
162
- return self._noMatchLangFootnotes
153
+ return self.checkFootnotes(modelXbrl).noMatchLangFootnotes
163
154
 
164
155
  def getOrphanedFootnotes(self, modelXbrl: ModelXbrl) -> set[ModelInlineFootnote]:
165
- if self._orphanedFootnotes is None:
166
- self.checkFootnote(modelXbrl)
167
- assert(self._orphanedFootnotes is not None)
168
- return self._orphanedFootnotes
156
+ return self.checkFootnotes(modelXbrl).orphanedFootnotes
169
157
 
158
+ @lru_cache(1)
170
159
  def unitsByDocument(self, modelXbrl: ModelXbrl) -> dict[str, list[ModelUnit]]:
171
- if self._unitsByDocument is not None:
172
- return self._unitsByDocument
173
160
  unitsByDocument = defaultdict(list)
174
161
  for unit in modelXbrl.units.values():
175
162
  unitsByDocument[unit.modelDocument.filepath].append(unit)
176
- self._unitsByDocument = dict(unitsByDocument)
177
- return self._unitsByDocument
163
+ unitsByDocument.default_factory = None
164
+ return unitsByDocument
@@ -23,7 +23,6 @@ class ValidationPluginExtension(ValidationPlugin):
23
23
  jenvNamespace = 'http://www.nltaxonomie.nl/nt16/jenv/20211208/dictionary/jenv-bw2-data'
24
24
  kvkINamespace = 'http://www.nltaxonomie.nl/nt16/kvk/20211208/dictionary/kvk-data'
25
25
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt16/sbr/20210301/dictionary/nl-types'
26
- titel9Namespace = ''
27
26
  entrypointRoot = 'http://www.nltaxonomie.nl/nt16/kvk/20211208/entrypoints/'
28
27
  entrypoints = {entrypointRoot + e for e in [
29
28
  'kvk-rpt-jaarverantwoording-2021-ifrs-full.xsd',
@@ -60,7 +59,6 @@ class ValidationPluginExtension(ValidationPlugin):
60
59
  jenvNamespace = 'http://www.nltaxonomie.nl/nt17/jenv/20221214/dictionary/jenv-bw2-data'
61
60
  kvkINamespace = 'http://www.nltaxonomie.nl/nt17/kvk/20221214/dictionary/kvk-data'
62
61
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt17/sbr/20220301/dictionary/nl-types'
63
- titel9Namespace = ''
64
62
  entrypointRoot = 'http://www.nltaxonomie.nl/nt17/kvk/20221214/entrypoints/'
65
63
  entrypoints = {entrypointRoot + e for e in [
66
64
  'kvk-rpt-jaarverantwoording-2022-ifrs-full.xsd',
@@ -98,7 +96,6 @@ class ValidationPluginExtension(ValidationPlugin):
98
96
  jenvNamespace = 'http://www.nltaxonomie.nl/nt18/jenv/20231213/dictionary/jenv-bw2-data'
99
97
  kvkINamespace = 'http://www.nltaxonomie.nl/nt18/kvk/20231213/dictionary/kvk-data'
100
98
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt18/sbr/20230301/dictionary/nl-types'
101
- titel9Namespace = ''
102
99
  entrypointRoot = 'http://www.nltaxonomie.nl/nt18/kvk/20231213/entrypoints/'
103
100
  entrypoints = {entrypointRoot + e for e in [
104
101
  'kvk-rpt-jaarverantwoording-2023-ifrs-full.xsd',
@@ -132,11 +129,10 @@ class ValidationPluginExtension(ValidationPlugin):
132
129
  'kvk-rpt-jaarverantwoording-2023-nlgaap-verzekeringsmaatschappijen.xsd',
133
130
  'kvk-rpt-jaarverantwoording-2023-nlgaap-zorginstellingen.xsd',
134
131
  ]}
135
- elif disclosureSystem == DISCLOSURE_SYSTEM_NT19 or disclosureSystem == DISCLOSURE_SYSTEM_NL_INLINE_2024:
132
+ elif disclosureSystem == DISCLOSURE_SYSTEM_NT19:
136
133
  jenvNamespace = 'http://www.nltaxonomie.nl/nt19/jenv/20241211/dictionary/jenv-bw2-data'
137
134
  kvkINamespace = 'http://www.nltaxonomie.nl/nt19/kvk/20241211/dictionary/kvk-data'
138
135
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt19/sbr/20240301/dictionary/nl-types'
139
- titel9Namespace = 'https://www.nltaxonomie.nl/jenv/2024-03-31/bw2-titel9-cor'
140
136
  entrypointRoot = 'http://www.nltaxonomie.nl/nt19/kvk/20241211/entrypoints/'
141
137
  entrypoints = {entrypointRoot + e for e in [
142
138
  'kvk-rpt-jaarverantwoording-2024-ifrs-full.xsd',
@@ -170,11 +166,21 @@ class ValidationPluginExtension(ValidationPlugin):
170
166
  'kvk-rpt-jaarverantwoording-2024-nlgaap-verzekeringsmaatschappijen.xsd',
171
167
  'kvk-rpt-jaarverantwoording-2024-nlgaap-zorginstellingen.xsd',
172
168
  ]}
169
+ elif disclosureSystem == DISCLOSURE_SYSTEM_NL_INLINE_2024:
170
+ jenvNamespace = 'https://www.nltaxonomie.nl/bw2-titel9/2024-12-31/bw2-titel9-cor'
171
+ kvkINamespace = None
172
+ nlTypesNamespace = None
173
+ entrypointRoot = 'http://www.nltaxonomie.nl/kvk/2024-12-31/'
174
+ entrypoints = {entrypointRoot + e for e in [
175
+ 'kvk-annual-report-ifrs-ext.xsd',
176
+ 'kvk-annual-report-nlgaap-ext.xsd',
177
+ 'kvk-annual-report-other-gaap.xsd',
178
+ ]}
173
179
  else:
174
180
  raise ValueError(f'Invalid NL disclosure system: {disclosureSystem}')
175
181
  return PluginValidationDataExtension(
176
182
  self.name,
177
- chamberOfCommerceRegistrationNumberQn=qname(f'{{{titel9Namespace}}}ChamberOfCommerceRegistrationNumber'),
183
+ chamberOfCommerceRegistrationNumberQn=qname(f'{{{jenvNamespace}}}ChamberOfCommerceRegistrationNumber'),
178
184
  documentAdoptionDateQn=qname(f'{{{jenvNamespace}}}DocumentAdoptionDate'),
179
185
  documentAdoptionStatusQn=qname(f'{{{jenvNamespace}}}DocumentAdoptionStatus'),
180
186
  documentResubmissionUnsurmountableInaccuraciesQn=qname(f'{{{kvkINamespace}}}DocumentResubmissionDueToUnsurmountableInaccuracies'),
@@ -3,20 +3,16 @@ See COPYRIGHT.md for copyright information.
3
3
  """
4
4
  from __future__ import annotations
5
5
 
6
- from datetime import date, timedelta
6
+ from datetime import date
7
7
 
8
8
  from arelle.ModelInstanceObject import ModelInlineFact
9
+ from arelle.ValidateDuplicateFacts import getDuplicateFactSets
9
10
  from arelle.XmlValidateConst import VALID
10
- from dateutil import relativedelta
11
11
  from collections.abc import Iterable
12
- from typing import Any, cast, TYPE_CHECKING
12
+ from typing import Any, TYPE_CHECKING
13
13
 
14
- from regex import regex
15
-
16
- from arelle import XmlUtil, XbrlConst
17
- from arelle.ModelObject import ModelObject
14
+ from arelle import XmlUtil
18
15
  from arelle.ValidateXbrl import ValidateXbrl
19
- from arelle.XmlValidate import INVALID
20
16
  from arelle.typing import TypeGetText
21
17
  from arelle.utils.PluginHooks import ValidationHook
22
18
  from arelle.utils.validate.Decorator import validation
@@ -60,7 +56,7 @@ def rule_nl_kvk_3_1_1_1(
60
56
  for entityId in entityIdentifierValues:
61
57
  if not XBRLI_IDENTIFIER_PATTERN.match(entityId[1]):
62
58
  yield Validation.error(
63
- codes='NL.NL-KVK-3.1.1.1',
59
+ codes='NL.NL-KVK-RTS_Annex_IV_Par_2_G3-1-1_1.invalidIdentifierFormat',
64
60
  msg=_('xbrli:identifier content to match KVK number format that must consist of 8 consecutive digits.'
65
61
  'Additionally the first two digits must not be "00".'),
66
62
  modelObject = val.modelXbrl
@@ -87,7 +83,7 @@ def rule_nl_kvk_3_1_1_2(
87
83
  for entityId in entityIdentifierValues:
88
84
  if XBRLI_IDENTIFIER_SCHEMA != entityId[0]:
89
85
  yield Validation.error(
90
- codes='NL.NL-KVK-3.1.1.2',
86
+ codes='NL.NL-KVK-RTS_Annex_IV_Par_2_G3-1-1_2.invalidIdentifier',
91
87
  msg=_('The scheme attribute of the xbrli:identifier does not match the required content.'
92
88
  'This should be "http://www.kvk.nl/kvk-id".'),
93
89
  modelObject = val.modelXbrl
@@ -209,7 +205,7 @@ def rule_nl_kvk_3_1_4_1 (
209
205
  entityIdentifierValues = pluginData.entityIdentifiersInDocument(val.modelXbrl)
210
206
  if len(entityIdentifierValues) >1:
211
207
  yield Validation.error(
212
- codes='NL.NL-KVK-3.1.4.1',
208
+ codes='NL.NL-KVK-RTS_Annex_IV_Par_1_G3-1-4_1.multipleIdentifiers',
213
209
  msg=_('All entity identifiers and schemes must have identical content.'),
214
210
  modelObject = entityIdentifierValues
215
211
  )
@@ -236,7 +232,7 @@ def rule_nl_kvk_3_1_4_2 (
236
232
  regFact = next(iter(registrationNumberFacts))
237
233
  if regFact.xValid >= VALID and regFact.xValue != regFact.context.entityIdentifier[1]:
238
234
  yield Validation.error(
239
- codes='NL-KVK.3.1.4.2',
235
+ codes='NL.NL-KVK-RTS_Annex_IV_Par_1_G3-1-4_2.nonIdenticalIdentifier',
240
236
  msg=_("xbrli:identifier value must be identical to bw2-titel9:ChamberOfCommerceRegistrationNumber fact value.").format(
241
237
  regFact.xValue,
242
238
  regFact.context.entityIdentifier[1]
@@ -300,6 +296,66 @@ def rule_nl_kvk_3_2_3_1 (
300
296
  )
301
297
 
302
298
 
299
+ @validation(
300
+ hook=ValidationHook.XBRL_FINALLY,
301
+ disclosureSystems=[
302
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
303
+ ],
304
+ )
305
+ def rule_nl_kvk_3_2_4_1 (
306
+ pluginData: PluginValidationDataExtension,
307
+ val: ValidateXbrl,
308
+ *args: Any,
309
+ **kwargs: Any,
310
+ ) -> Iterable[Validation]:
311
+ """
312
+ NL-KVK.3.2.4.1: Inconsistent numeric facts are prohibited.
313
+ """
314
+ problematicFacts= []
315
+ numericFacts = [fact for fact in val.modelXbrl.facts if fact is not None and fact.isNumeric]
316
+ if len(numericFacts) > 0:
317
+ for duplicateFactSet in getDuplicateFactSets(numericFacts, False):
318
+ if duplicateFactSet.areAnyInconsistent:
319
+ for fact in duplicateFactSet:
320
+ problematicFacts.append(fact)
321
+ if len(problematicFacts) > 0:
322
+ yield Validation.error(
323
+ codes='NL.NL-KVK.3.2.4.1.inconsistentDuplicateNumericFactInInlineXbrlDocument',
324
+ msg=_('Inconsistent numeric facts are prohibited.'),
325
+ modelObject = problematicFacts
326
+ )
327
+
328
+
329
+ @validation(
330
+ hook=ValidationHook.XBRL_FINALLY,
331
+ disclosureSystems=[
332
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
333
+ ],
334
+ )
335
+ def rule_nl_kvk_3_2_4_2 (
336
+ pluginData: PluginValidationDataExtension,
337
+ val: ValidateXbrl,
338
+ *args: Any,
339
+ **kwargs: Any,
340
+ ) -> Iterable[Validation]:
341
+ """
342
+ NL-KVK.3.2.4.2: Inconsistent non-numeric facts are prohibited.
343
+ """
344
+ problematicFacts = []
345
+ nonNumericFacts = [fact for fact in val.modelXbrl.facts if fact is not None and not fact.isNumeric]
346
+ if len(nonNumericFacts) > 0:
347
+ for duplicateFactSet in getDuplicateFactSets(nonNumericFacts, False):
348
+ if duplicateFactSet.areAnyInconsistent:
349
+ for fact in duplicateFactSet:
350
+ problematicFacts.append(fact)
351
+ if len(problematicFacts) > 0:
352
+ yield Validation.error(
353
+ codes='NL.NL-KVK.3.2.4.2.inconsistentDuplicateNonnumericFactInInlineXbrlDocument',
354
+ msg=_('Inconsistent non-numeric facts are prohibited.'),
355
+ modelObject = problematicFacts
356
+ )
357
+
358
+
303
359
  @validation(
304
360
  hook=ValidationHook.XBRL_FINALLY,
305
361
  disclosureSystems=[
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arelle-release
3
- Version: 2.37.8
3
+ Version: 2.37.10
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License: Apache-2.0
@@ -21,7 +21,7 @@ arelle/DialogRssWatch.py,sha256=mjc4pqyFDISY4tQtME0uSRQ3NlcWnNsOsMu9Zj8tTd0,1378
21
21
  arelle/DialogURL.py,sha256=JH88OPFf588E8RW90uMaieok7A_4kOAURQ8kHWVhnao,4354
22
22
  arelle/DialogUserPassword.py,sha256=kWPlCCihhwvsykDjanME9qBDtv6cxZlsrJyoMqiRep4,13769
23
23
  arelle/DisclosureSystem.py,sha256=g3XXMjuyKJk2eoqvHGqoyIs2bMfcODwOeISDRCcY9gc,24749
24
- arelle/FileSource.py,sha256=FXqXCd7FZ7p7DH4yAYDHYYZ_43P8H3nreT8LJpoWu1M,46643
24
+ arelle/FileSource.py,sha256=prfbAyYlrVGaYp8VagT4E6rz-sE1kLvL3FnzjHUN0c0,46611
25
25
  arelle/FunctionCustom.py,sha256=d1FsBG14eykvpLpgaXpN8IdxnlG54dfGcsXPYfdpA9Q,5880
26
26
  arelle/FunctionFn.py,sha256=BcZKah1rpfquSVPwjvknM1pgFXOnK4Hr1e_ArG_mcJY,38058
27
27
  arelle/FunctionIxt.py,sha256=8JELGh1l4o8Ul4_G7JgwX8Ebch9it2DblI6OkfL33Cw,80082
@@ -123,7 +123,7 @@ 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=cAF-eK-alaFm1NSbJP5rO2cSf3Bdy0OV8kAVRdfoiWI,513
126
+ arelle/_version.py,sha256=iV7pCtMGFdowMnJ9Enx0EMr8MXyKfpbuw_YEjFfm9Rc,515
127
127
  arelle/typing.py,sha256=Ct5lrNKRow_o9CraMEXNza8nFsJ_iGIKoUeGfPs2dxI,1084
128
128
  arelle/api/Session.py,sha256=O8zpg7MJys9uxwwHf8OsSlZxpPdq7A3ONyY39Q4A3Kc,6218
129
129
  arelle/archive/CustomLogger.py,sha256=v_JXOCQLDZcfaFWzxC9FRcEf9tQi4rCI4Sx7jCuAVQI,1231
@@ -294,7 +294,7 @@ arelle/model/CommentBase.py,sha256=NtC2lFd9Mt1y7kzWwrpvexwqBdfSe1nvGFiIJeio3rU,1
294
294
  arelle/model/ElementBase.py,sha256=pZX836d4-s-OvzPMUusvEDezI9D_6YKO7_j6iDcUXm4,404
295
295
  arelle/model/PIBase.py,sha256=easZ3pKXJ5wq3NFB2pDtBeXNDcjwMAXylpXz6mnumOg,257
296
296
  arelle/model/__init__.py,sha256=RLmC1rTus3T_2Vvnu3yHtdw1r0wrZCHZoqxe8BLg_wE,595
297
- arelle/oim/Load.py,sha256=TX5lA0MsN1Vig0A6ozlY-eOa9z0OaAxBcsICu_jrlk0,182158
297
+ arelle/oim/Load.py,sha256=kqKvs3q6VE6fKxCv9X0kxnyTywKMyC_qGGAB__v51TU,182910
298
298
  arelle/oim/Validate.py,sha256=IaBClr2KYMiVC_GKYy4_A9gF7hcnm-lxXpQrDCqIWGs,9012
299
299
  arelle/oim/xml/Save.py,sha256=MdaJiGcEo4nbQCX9sRgWfVIoxp6fd2N-wuLiDAS9D-I,607
300
300
  arelle/packages/PackageConst.py,sha256=iIIF-Ic8zlMPiiCq3PcV57aWci6ispBtilSG4W7ZW4U,121
@@ -378,8 +378,8 @@ arelle/plugin/validate/FERC/__init__.py,sha256=V4fXcFKBsjFFPs9_1NhvDjWpEQCoQM0tR
378
378
  arelle/plugin/validate/FERC/config.xml,sha256=bn9b8eCqJA1J62rYq1Nz85wJrMGAahVmmnIUQZyerjo,1919
379
379
  arelle/plugin/validate/FERC/resources/ferc-utr.xml,sha256=OCRj9IUpdXATCBXKbB71apYx9kxcNtZW-Hq4s-avsRY,2663
380
380
  arelle/plugin/validate/NL/DisclosureSystems.py,sha256=kTjpxkgwn58wHCbaLRBInirOy-2cpK9MLWEFJ_193y4,180
381
- arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=3SaQ85Hd8APZM994Xcl876Wy_DgoY_y2UAm_e3JfdoY,8434
382
- arelle/plugin/validate/NL/ValidationPluginExtension.py,sha256=8QL0_FL3kT-pMYqZxRI0BTN6ToJeU-wd800y_7fY3wM,15225
381
+ arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=dJjfHb3QMK2LlGKTwSz_IxFLYXejFPgLZlVgTPxgFPI,7074
382
+ arelle/plugin/validate/NL/ValidationPluginExtension.py,sha256=2qvvOqBkgk2LwERTHDuxtrRupYz3yRyhH71XQLbl9F4,15507
383
383
  arelle/plugin/validate/NL/__init__.py,sha256=99uMv4ESHwyJqA-Xq_hBvHygm0BQ3NxcmAJnVYUkSgg,3104
384
384
  arelle/plugin/validate/NL/resources/config.xml,sha256=i_ns2wHmQYjhkRItevRR8tzfkl31ASfbWlc5t6pDB-w,1117
385
385
  arelle/plugin/validate/NL/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -387,7 +387,7 @@ arelle/plugin/validate/NL/rules/br_kvk.py,sha256=0SwKieWzTDm3YMsXPS6zTdgbk7_Z9Cz
387
387
  arelle/plugin/validate/NL/rules/fg_nl.py,sha256=4Puq5wAjtK_iNd4wisH_R0Z_EKJ7MT2OCai5g4t1MPE,10714
388
388
  arelle/plugin/validate/NL/rules/fr_kvk.py,sha256=-_BLeWGoZ_f56p5VO4X40S45Ny3Ej-WK6Srei1KVSxU,8170
389
389
  arelle/plugin/validate/NL/rules/fr_nl.py,sha256=-M1WtXp06khhtkfOVPCa-b8UbC281gk4YfDhvtAVlnI,31424
390
- arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=OqckHX2Nxv-pvSe3ieai5P-Czb-cBOuNI04BJaCpXnQ,11822
390
+ arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=OSryY5fT1UCTqahJbIv0jlsWKITPeUckEw2C44K8uRo,13974
391
391
  arelle/plugin/validate/ROS/DisclosureSystems.py,sha256=rJ81mwQDYTi6JecFZ_zhqjjz3VNQRgjHNSh0wcQWAQE,18
392
392
  arelle/plugin/validate/ROS/PluginValidationDataExtension.py,sha256=IV7ILhNvgKwQXqbpSA6HRNt9kEnejCyMADI3wyyIgk0,4036
393
393
  arelle/plugin/validate/ROS/ValidationPluginExtension.py,sha256=FBhEp8t396vGdvCbMEimfcxmGiGnhXMen-yVLWnkFaI,758
@@ -707,7 +707,7 @@ arelle/utils/validate/ValidationPlugin.py,sha256=_WeRPXZUTCcSN3FLbFwiAe_2pAUTxZZ
707
707
  arelle/utils/validate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
708
708
  arelle/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
709
709
  arelle/webserver/bottle.py,sha256=P-JECd9MCTNcxCnKoDUvGcoi03ezYVOgoWgv2_uH-6M,362
710
- arelle_release-2.37.8.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
710
+ arelle_release-2.37.10.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
711
711
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
712
712
  tests/integration_tests/download_cache.py,sha256=jVMIVICsZjcVc9DCPPu3fCjF9_cWSS3tqSynhFs3oAM,4097
713
713
  tests/integration_tests/integration_test_util.py,sha256=H7mncbv0T9ZeVyrtk9Hohe3k6jgcYykHkt-LGE-Q9aQ,10270
@@ -735,14 +735,14 @@ tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Usings.cs,sha256=0I
735
735
  tests/integration_tests/ui_tests/resources/workiva.zip,sha256=QtZzi1VcKkHhVa8J-I1wVpQFy-p6tsV95Z0HmI6XbXc,223544
736
736
  tests/integration_tests/validation/README.md,sha256=Fo3TpMmOlo4llngPKtdfnemS0TeI3ou-ceX8f4u1K-Y,2907
737
737
  tests/integration_tests/validation/assets.py,sha256=Ag9qPYrodcC-Ly6aygqapV0vG2Cbn_Tigg4v4F9xX4U,8295
738
- tests/integration_tests/validation/conformance_suite_config.py,sha256=fLur7EOoOdu6kKlkZ3tY3Sjn9G-gpB4OGbOKZkqa-fA,10383
738
+ tests/integration_tests/validation/conformance_suite_config.py,sha256=LgPO_8H_esM9kQS2o4jKd8CTNi0hiHugZ1hZn7whshI,10383
739
739
  tests/integration_tests/validation/conformance_suite_configs.py,sha256=IbrL-45QTsUSI5Usz-STqtRZsz8pLu83KXqx4aDL-1w,7327
740
740
  tests/integration_tests/validation/conftest.py,sha256=rVfmNX9y0JZ1VfoEepeYyIz-ZxzEZ1IJlmbcQSuxgUo,816
741
741
  tests/integration_tests/validation/discover_tests.py,sha256=EJ0AlxWqzFBTDfncE2dv-GsBNmO8lynNOJAn0uFgXgo,4649
742
742
  tests/integration_tests/validation/download_assets.py,sha256=muHklbrvYEbxqqAM8mU-8FpeemP0BLTWxD11xTYiCMc,7850
743
743
  tests/integration_tests/validation/run_conformance_suites.py,sha256=pDtBUEfT-pggxKEN2cg3vk0_Cko6wgV3x-6cX7y3Y3M,8206
744
744
  tests/integration_tests/validation/test_conformance_suites.py,sha256=VdwY0QtV6g00M9bv1XNs4qBTwxPxCh5-z4XoDdEhgeM,711
745
- tests/integration_tests/validation/validation_util.py,sha256=W5_NpjlqVKlmV8LGgzQLIFtmgEFPO4YgSOTymQX_rns,21541
745
+ tests/integration_tests/validation/validation_util.py,sha256=zG4ZvrEGNixQ7vpeOkXMTnmYZCXmn27rpirfk2mLzCA,21658
746
746
  tests/integration_tests/validation/conformance_suite_configurations/cipc_current.py,sha256=oLXe3xIsEZLz3cv1cDdMQIuS_NgyI9Uimc9hy0NMWqg,642
747
747
  tests/integration_tests/validation/conformance_suite_configurations/dba_current.py,sha256=j-7jCpzbGXbOzG8HGEyS0ciCYSPZzZLV44VQGhP3Hmc,875
748
748
  tests/integration_tests/validation/conformance_suite_configurations/dba_multi_current.py,sha256=ICkP18Wu7aTDfszfYlrfVnBj9oe7ppXR-8wxQqCPqW0,837
@@ -752,7 +752,7 @@ tests/integration_tests/validation/conformance_suite_configurations/efm_reg_prag
752
752
  tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2021.py,sha256=KpXpm6kMYAp94K-J7-GZS47iRVE9Kr5cfxPniFFSI3A,1146
753
753
  tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2022.py,sha256=tllelZOW7R5udOhEtjnQGAVy0MxAAM03OY_cC4pstgY,1575
754
754
  tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2023.py,sha256=Imhckmr7vui2xrWdsWaengly-5e2CUeoqh2ZDTscek8,1833
755
- tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2024.py,sha256=Eu3I5Tn1ow7fB4y9KMgSe9q4W5NBfME6pHzBBmEwgqM,1610
755
+ tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2024.py,sha256=URLv7fAGPQiNB_LiL1F5L0YKFsgqYnm-X1SxtxsOQrY,1625
756
756
  tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2021.py,sha256=535hJ9CEPJPT-ciHumkii6xlJXwsV1KfL_Q9a4fjxcc,971
757
757
  tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2022.py,sha256=fr5GIUrbKB4_f7YIkSQz9hbpqFWuQyLmo4awtvODfU4,948
758
758
  tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2023.py,sha256=hOpfcMcnu_plJB-mpqyTywAncW_iPJGlZsn5hfD9sk0,920
@@ -762,13 +762,13 @@ tests/integration_tests/validation/conformance_suite_configurations/kvk_nt16.py,
762
762
  tests/integration_tests/validation/conformance_suite_configurations/kvk_nt17.py,sha256=lmEZonthFm0YKFmp1dwXtdJ2T7txUeSpL4mbAo8fl4Y,1292
763
763
  tests/integration_tests/validation/conformance_suite_configurations/kvk_nt18.py,sha256=EG2RQVkvFENhzUF3fl3QvDnH7ZPYS1n1Fo8bhfmSczM,1205
764
764
  tests/integration_tests/validation/conformance_suite_configurations/kvk_nt19.py,sha256=FAzf9RhRmn_8yowpplJho2zEspX9FxJiVq8SjZT3Dsc,1199
765
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py,sha256=hzPHrwrbkrHCx2hkYk7z97BZHEaxgR7sSkrF46VoemI,10313
765
+ tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py,sha256=kVK0obRRXZrakg9BE4aXCtuV7C39GiKPFNWC3ywKS7k,10584
766
766
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py,sha256=O_LFVBZPkjxmbrU7_C7VTLtrdoCUx2bYXOXw6_MlRtQ,846
767
767
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py,sha256=aTN3Ez6lPsZsuypHZP84DneOtYxUZSjUiGypHy6ofHQ,846
768
768
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py,sha256=sqHLjrHc95dTu0guTgKkphaKM1zNfKGnN4GKkZDLzeU,845
769
769
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt19.py,sha256=_CiNflzz0ItJslvv22CL70yyK3P7hVGYLZ3BIb0y9Ww,844
770
770
  tests/integration_tests/validation/conformance_suite_configurations/ros_current.py,sha256=yEt0XHxX6jNpbslQaIeOce07eh3dsdGP-e7ydOiZzog,725
771
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_2_1.py,sha256=GFPkzqk2lwDgHEUIRAFS9-htMOS0THmjsXT9eJDfiSc,1494
771
+ tests/integration_tests/validation/conformance_suite_configurations/xbrl_2_1.py,sha256=M_-YpwSv66m5-4vgle0g7pLENBcuZKCRQ_2KcDxZ5PE,1509
772
772
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_calculations_1_1.py,sha256=0XV1FXxFiSk5hcsSaEsT7JVGQ3KXV8FrHNmr-tqo3Zg,816
773
773
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_dimensions_1_0.py,sha256=NtliBDgTxKvpC3j75hmJSrcIIkVlA4q_q6OEXf9b28w,1871
774
774
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_dtr_2024_01_31.py,sha256=7fKQlcQR7mldll5THMmOBNCLVAZdV_yh30rPi3GmevY,698
@@ -780,7 +780,7 @@ tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula
780
780
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_ixbrl_1_1.py,sha256=Upsc9Nx0eHJQlVL9p77GamTCUpIqjexnRShe9F0b9NM,1366
781
781
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_link_role_registry_1_0.py,sha256=NQfri9MXCDSvNy7kahf4iXZaBUPey9-FYKlchg-Uw4I,633
782
782
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_oim_1_0.py,sha256=s5tcH5fgzNwLQR1iWxCjuyij4Rxjq8XrmGDIptAbfGE,906
783
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_report_packages_1_0.py,sha256=vzVq4Y_Dg0D56BDoaNyCkyhVUUAsKh6w3cK5M45zmN8,1619
783
+ tests/integration_tests/validation/conformance_suite_configurations/xbrl_report_packages_1_0.py,sha256=roUdlY_cOYFp5gSyiDoYUP_OHRCjJyReTv-dNorI72g,1799
784
784
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_table_linkbase_1_0.py,sha256=6zWp8Bt_X4QHDKeJo4NHOgu2OwMpc8-Qb0VZULWcn6M,844
785
785
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_taxonomy_packages_1_0.py,sha256=rw1QLcQBKIlwtQ3XhNJqAXxYgmWZm_4wGbwck2UZg_8,651
786
786
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_3.py,sha256=ORho6dzIyaUOgm6v9YjViMAk3MzOK40U8AX2V0Eg5t4,591
@@ -1556,8 +1556,8 @@ tests/unit_tests/arelle/oim/test_load.py,sha256=NxiUauQwJVfWAHbbpsMHGSU2d3Br8Pki
1556
1556
  tests/unit_tests/arelle/plugin/test_plugin_imports.py,sha256=bdhIs9frAnFsdGU113yBk09_jis-z43dwUItMFYuSYM,1064
1557
1557
  tests/unit_tests/arelle/plugin/validate/ESEF/ESEF_Current/test_validate_css_url.py,sha256=XHABmejQt7RlZ0udh7v42f2Xb2STGk_fSaIaJ9i2xo0,878
1558
1558
  tests/unit_tests/arelle/utils/validate/test_decorator.py,sha256=ZS8FqIY1g-2FCbjF4UYm609dwViax6qBMRJSi0vfuhY,2482
1559
- arelle_release-2.37.8.dist-info/METADATA,sha256=vVYSyHCG28r9Y7qYSKyC9E5188Rza7T9GchVet2RJDw,9064
1560
- arelle_release-2.37.8.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
1561
- arelle_release-2.37.8.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1562
- arelle_release-2.37.8.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1563
- arelle_release-2.37.8.dist-info/RECORD,,
1559
+ arelle_release-2.37.10.dist-info/METADATA,sha256=DFJI_rtWLKg0WZcg8-DGlJjNJStGQ6md6klHzFXc3Vw,9065
1560
+ arelle_release-2.37.10.dist-info/WHEEL,sha256=A8Eltl-h0W-qZDVezsLjjslosEH_pdYC2lQ0JcbgCzs,91
1561
+ arelle_release-2.37.10.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1562
+ arelle_release-2.37.10.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1563
+ arelle_release-2.37.10.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.7.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -192,7 +192,7 @@ class ConformanceSuiteConfig:
192
192
  cache_version_id: str | None = None
193
193
  capture_warnings: bool = True
194
194
  ci_enabled: bool = True
195
- expected_additional_testcase_errors: dict[str, frozenset[str]] = field(default_factory=dict)
195
+ expected_additional_testcase_errors: dict[str, dict[str, int]] = field(default_factory=dict)
196
196
  expected_failure_ids: frozenset[str] = frozenset()
197
197
  expected_missing_testcases: frozenset[str] = frozenset()
198
198
  expected_model_errors: frozenset[str] = frozenset()
@@ -25,7 +25,9 @@ config = ConformanceSuiteConfig(
25
25
  expected_additional_testcase_errors={f"esef_conformance_suite_2024/tests/inline_xbrl/{s}": val for s, val in {
26
26
  # Typo in the test case namespace declaration: incorrectly uses the Extensible Enumeration 1 namespace with the
27
27
  # commonly used Extensible Enumeration 2 prefix: xmlns:enum2="http://xbrl.org/2014/extensible-enumerations"
28
- 'G2-4-1_1/index.xml:TC2_valid': frozenset({'differentExtensionDataType'}),
28
+ 'G2-4-1_1/index.xml:TC2_valid': {
29
+ 'differentExtensionDataType': 1,
30
+ },
29
31
  }.items()},
30
32
  info_url='https://www.esma.europa.eu/document/esef-conformance-suite-2024',
31
33
  name=PurePath(__file__).stem,
@@ -17,9 +17,24 @@ config = ConformanceSuiteConfig(
17
17
  ),
18
18
  *NL_PACKAGES['NL-INLINE-2024'],
19
19
  ],
20
+ expected_additional_testcase_errors={f"conformance-suite-2024-sbr-domein-handelsregister/tests/{s}": val for s, val in {
21
+ 'RTS_Annex_IV_Par_2_G3-1-1_2/index.xml:TC2_invalid': {
22
+ 'message:lei-identifier-format': 105,
23
+ 'message:valueKvKIdentifierScheme': 105,
24
+ },
25
+ 'RTS_Annex_IV_Par_1_G3-1-4_1/index.xml:TC2_invalid': {
26
+ 'message:valueKvKIdentifier': 13,
27
+ 'nonIdenticalIdentifier': 1,
28
+ },
29
+ 'RTS_Annex_IV_Par_1_G3-1-4_2/index.xml:TC2_invalid': {
30
+ 'message:valueKvKIdentifier': 13,
31
+ },
32
+ }.items()},
20
33
  expected_failure_ids=frozenset([
34
+ # Conformance Suite Errors
35
+ '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)
36
+
21
37
  # Not Implemented
22
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-4_2/index.xml:TC4_invalid',
23
38
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC4_invalid',
24
39
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC5_invalid',
25
40
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC6_invalid',
@@ -88,10 +103,6 @@ config = ConformanceSuiteConfig(
88
103
  'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_11_G4-2-2_1/index.xml:TC3_invalid',
89
104
  'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_12_G3-2-4_1/index.xml:TC4_invalid',
90
105
  'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_14_G3-5-1_1/index.xml:TC2_invalid',
91
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_1_G3-1-4_1/index.xml:TC2_invalid',
92
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_1_G3-1-4_2/index.xml:TC2_invalid',
93
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_2_G3-1-1_1/index.xml:TC2_invalid',
94
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_2_G3-1-1_2/index.xml:TC2_invalid',
95
106
  'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_1/index.xml:TC2_invalid',
96
107
  'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_2/index.xml:TC2_invalid',
97
108
  'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_3/index.xml:TC3_invalid',
@@ -21,7 +21,9 @@ config = ConformanceSuiteConfig(
21
21
  expected_additional_testcase_errors={f"XBRL-CONF-2024-12-17/Common/{s}": val for s, val in {
22
22
  # 202.02b in the absence of source/target constraints, an empty href doesn't pose a problem
23
23
  # 202-02b-HrefResolutionCounterExample-custom.xml Expected: valid, Actual: arelle:hrefWarning
24
- '200-linkbase/202-xlinkLocator.xml:V-02b': frozenset({'arelle:hrefWarning'}),
24
+ '200-linkbase/202-xlinkLocator.xml:V-02b': {
25
+ 'arelle:hrefWarning': 1,
26
+ },
25
27
  }.items()},
26
28
  expected_missing_testcases=frozenset([f"XBRL-CONF-2024-12-17/Common/{s}" for s in [
27
29
  "related-standards/xlink/arc-duplication/arc-duplication-testcase.xml",
@@ -17,13 +17,31 @@ config = ConformanceSuiteConfig(
17
17
  ],
18
18
  expected_additional_testcase_errors={f"report-package-conformance/index.csv:{s}": val for s, val in {
19
19
  # "Empty" iXBRL docs are missing schema required elements.
20
- "V-301-xbri-with-single-ixds": frozenset({"lxml.SCHEMAV_ELEMENT_CONTENT", "ix11.14.1.2:missingResources"}),
21
- "V-302-xbri-with-single-html": frozenset({"lxml.SCHEMAV_ELEMENT_CONTENT", "ix11.14.1.2:missingResources"}),
22
- "V-303-xbri-with-single-htm": frozenset({"lxml.SCHEMAV_ELEMENT_CONTENT", "ix11.14.1.2:missingResources"}),
20
+ "V-301-xbri-with-single-ixds": {
21
+ "lxml.SCHEMAV_ELEMENT_CONTENT": 1,
22
+ "ix11.14.1.2:missingResources": 1,
23
+ },
24
+ "V-302-xbri-with-single-html": {
25
+ "lxml.SCHEMAV_ELEMENT_CONTENT": 1,
26
+ "ix11.14.1.2:missingResources": 1,
27
+ },
28
+ "V-303-xbri-with-single-htm": {
29
+ "lxml.SCHEMAV_ELEMENT_CONTENT": 1,
30
+ "ix11.14.1.2:missingResources": 1,
31
+ },
23
32
  # Report package references a taxonomy which does not exist.
24
- "V-508-xbr-with-no-taxonomy": frozenset({"IOerror", "oime:invalidTaxonomy"}),
25
- "V-509-xbr-with-json-in-dot-xhtml-directory": frozenset({"IOerror", "oime:invalidTaxonomy"}),
26
- "V-701-zip-with-no-taxonomy": frozenset({"IOerror", "oime:invalidTaxonomy"}),
33
+ "V-508-xbr-with-no-taxonomy": {
34
+ "IOerror": 1,
35
+ "oime:invalidTaxonomy": 1,
36
+ },
37
+ "V-509-xbr-with-json-in-dot-xhtml-directory": {
38
+ "IOerror": 1,
39
+ "oime:invalidTaxonomy": 1,
40
+ },
41
+ "V-701-zip-with-no-taxonomy": {
42
+ "IOerror": 1,
43
+ "oime:invalidTaxonomy": 1,
44
+ },
27
45
  }.items()},
28
46
  info_url="https://specifications.xbrl.org/work-product-index-taxonomy-packages-report-packages-1.0.html",
29
47
  membership_url="https://www.xbrl.org/join",
@@ -247,7 +247,7 @@ def _get_elems_by_local_name(tree: etree._ElementTree, local_name: str) -> list[
247
247
 
248
248
  def get_conformance_suite_arguments(config: ConformanceSuiteConfig, filename: str,
249
249
  additional_plugins: frozenset[str], build_cache: bool, offline: bool, log_to_file: bool,
250
- expected_additional_testcase_errors: dict[str, frozenset[str]],
250
+ expected_additional_testcase_errors: dict[str, dict[str, int]],
251
251
  expected_failure_ids: frozenset[str], shard: int | None,
252
252
  testcase_filters: list[str]) -> tuple[list[Any], dict[str, Any]]:
253
253
  use_shards = shard is not None
@@ -279,7 +279,10 @@ def get_conformance_suite_arguments(config: ConformanceSuiteConfig, filename: st
279
279
  args.extend(['--internetConnectivity', 'offline'])
280
280
  for pattern in testcase_filters:
281
281
  args.extend(['--testcaseFilter', pattern])
282
- for testcase_id, errors in expected_additional_testcase_errors.items():
282
+ for testcase_id, errorCounts in expected_additional_testcase_errors.items():
283
+ errors = []
284
+ for error, count in errorCounts.items():
285
+ errors.extend([error] * count)
283
286
  args.extend(['--testcaseExpectedErrors', f'{testcase_id}|{",".join(errors)}'])
284
287
  kws = dict(
285
288
  expected_failure_ids=expected_failure_ids,