arelle-release 2.37.5__py3-none-any.whl → 2.37.7__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 CHANGED
@@ -603,7 +603,7 @@ def filesourceEntrypointFiles(filesource, entrypointFiles=None, inlineOnly=False
603
603
  pluginXbrlMethod(filesource, reportEntries)
604
604
  ixdsDiscovered = True
605
605
  if not ixdsDiscovered and len(reportEntries) > 1:
606
- raise RuntimeError(_("Loading error. Inline document set encountered. Enable 'InlineDocumentSet' plug-in to load this filing: {0}").format(filesource.url))
606
+ raise RuntimeError(_("Loading error. Inline document set encountered. Enable 'InlineXbrlDocumentSet' plug-in to load this filing: {0}").format(filesource.url))
607
607
  entrypointFiles.extend(reportEntries)
608
608
  elif not inlineOnly:
609
609
  entrypointFiles.append({"file": report.fullPathPrimary})
arelle/ModelDocument.py CHANGED
@@ -1704,6 +1704,35 @@ def inlineIxdsDiscover(modelXbrl, modelIxdsDocument, setTargetModelXbrl=False, *
1704
1704
  for _target in sourceFactTargets:
1705
1705
  targetRoleUris[_target].add(footnoteRole)
1706
1706
 
1707
+ for htmlElement in modelXbrl.ixdsHtmlElements:
1708
+ # Discover iXBRL 1.0 footnote roles and arcroles.
1709
+ iXBRL1_0Footnotes = list(htmlElement.iterdescendants(tag=XbrlConst.qnIXbrlFootnote.clarkNotation))
1710
+ if not iXBRL1_0Footnotes:
1711
+ continue
1712
+ footnoteRefElems = (
1713
+ XbrlConst.qnIXbrlFraction.clarkNotation,
1714
+ XbrlConst.qnIXbrlNonFraction.clarkNotation,
1715
+ XbrlConst.qnIXbrlNonNumeric.clarkNotation,
1716
+ XbrlConst.qnIXbrlTuple.clarkNotation,
1717
+ )
1718
+ targetsByFootnoteId = defaultdict(set)
1719
+ for elem in htmlElement.iterdescendants(footnoteRefElems):
1720
+ if isinstance(elem, ModelObject):
1721
+ refs = elem.get("footnoteRefs")
1722
+ if refs:
1723
+ _target = elem.get("target")
1724
+ for footnoteRef in refs.split():
1725
+ targetsByFootnoteId[footnoteRef].add(_target)
1726
+ for modelInlineFootnote in iXBRL1_0Footnotes:
1727
+ arcrole = modelInlineFootnote.get("arcrole", XbrlConst.factFootnote)
1728
+ footnoteLinkRole = modelInlineFootnote.get("footnoteLinkRole", XbrlConst.defaultLinkRole)
1729
+ footnoteRole = modelInlineFootnote.get("footnoteRole")
1730
+ for _target in targetsByFootnoteId[modelInlineFootnote.footnoteID]:
1731
+ targetRoleUris[_target].add(footnoteLinkRole)
1732
+ targetArcroleUris[_target].add(arcrole)
1733
+ if footnoteRole:
1734
+ targetRoleUris[_target].add(footnoteRole)
1735
+
1707
1736
  contextRefs = factTargetContextRefs[ixdsTarget]
1708
1737
  unitRefs = factTargetUnitRefs[ixdsTarget]
1709
1738
  allContextRefs = set.union(*factTargetContextRefs.values())
arelle/Validate.py CHANGED
@@ -734,7 +734,7 @@ class Validate:
734
734
  if not isinstance(expected, list):
735
735
  expected = [expected]
736
736
  for testErr in _errors:
737
- if isinstance(testErr,str) and testErr.startswith("ESEF."): # compared as list of strings to QName localname
737
+ if isinstance(testErr, str) and testErr.startswith(("ESEF.", "NL.NL-KVK")): # compared as list of strings to QName localname
738
738
  testErr = testErr.rpartition(".")[2]
739
739
  for _exp in _expectedList:
740
740
  _expMatched = False
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.5'
21
- __version_tuple__ = version_tuple = (2, 37, 5)
20
+ __version__ = version = '2.37.7'
21
+ __version_tuple__ = version_tuple = (2, 37, 7)
arelle/oim/Load.py CHANGED
@@ -74,6 +74,7 @@ reservedLinkTypeAndGroupAliases = {
74
74
  XLINKTYPE = "{http://www.w3.org/1999/xlink}type"
75
75
  XLINKLABEL = "{http://www.w3.org/1999/xlink}label"
76
76
  XLINKARCROLE = "{http://www.w3.org/1999/xlink}arcrole"
77
+ XLINKROLE = "{http://www.w3.org/1999/xlink}role"
77
78
  XLINKFROM = "{http://www.w3.org/1999/xlink}from"
78
79
  XLINKTO = "{http://www.w3.org/1999/xlink}to"
79
80
  XLINKHREF = "{http://www.w3.org/1999/xlink}href"
@@ -2717,6 +2718,7 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
2717
2718
  footnoteLinkNotes[linkrole].add(noteId)
2718
2719
  xbrlNote = xbrlNoteTbl[noteId]
2719
2720
  attrs = {XLINKTYPE: "resource",
2721
+ XLINKROLE: XbrlConst.footnote,
2720
2722
  XLINKLABEL: footnoteToLabel,
2721
2723
  "id": idDeduped(modelXbrl, noteId),
2722
2724
  # "oimNoteId": noteId
@@ -2816,6 +2818,8 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
2816
2818
  modelObject=modelXbrl, action=currentAction, error=ex,
2817
2819
  traceback=traceback.format_tb(sys.exc_info()[2]))
2818
2820
 
2821
+ # Reset modified status of model so user is not prompted for changes triggered by this loading operation.
2822
+ _return.isModified = False
2819
2823
  return _return
2820
2824
 
2821
2825
  def _isParamRef(value):
@@ -441,7 +441,7 @@ def createTargetInstance(
441
441
  arcrole, linkrole, linkqname, arcqname = linkKey
442
442
  if (linkrole and linkqname and arcqname and # fully specified roles
443
443
  arcrole != "XBRL-footnotes" and
444
- any(lP.modelDocument.type == Type.INLINEXBRL for lP in linkPrototypes)):
444
+ any(lP.modelDocument.type in (Type.INLINEXBRL, Type.INLINEXBRLDOCUMENTSET) for lP in linkPrototypes)):
445
445
  for linkPrototype in linkPrototypes:
446
446
  if linkPrototype not in footnoteLinks[linkrole]:
447
447
  footnoteLinks[linkrole].append(linkPrototype)
@@ -59,6 +59,7 @@ from __future__ import annotations
59
59
  import csv
60
60
  import io
61
61
  import json
62
+ import operator
62
63
  import os
63
64
  import threading
64
65
  import zipfile
@@ -124,6 +125,17 @@ qnOimPeriodAspect = qname("period", noPrefixIsNoNamespace=True)
124
125
  qnOimEntityAspect = qname("entity", noPrefixIsNoNamespace=True)
125
126
  qnOimUnitAspect = qname("unit", noPrefixIsNoNamespace=True)
126
127
 
128
+ reservedUriAliases = {
129
+ nsOim: "xbrl",
130
+ XbrlConst.defaultLinkRole: "_",
131
+ XbrlConst.factExplanatoryFact: "explanatoryFact",
132
+ XbrlConst.factFootnote: "footnote",
133
+ XbrlConst.iso4217: "iso4217",
134
+ XbrlConst.utr: "utr",
135
+ XbrlConst.xbrli: "xbrli",
136
+ XbrlConst.xsd: "xs",
137
+ }
138
+
127
139
  ONE = Decimal(1)
128
140
  TEN = Decimal(10)
129
141
  NILVALUE = "nil"
@@ -142,6 +154,43 @@ csvOpenNewline = ""
142
154
  OimFact = dict[str, Any]
143
155
  OimReport = dict[str, Any]
144
156
 
157
+ class NamespacePrefixes:
158
+ def __init__(self, prefixesByNamespace: dict[str, str] | None = None) -> None:
159
+ self._prefixesByNamespace: dict[str, str] = prefixesByNamespace or {}
160
+ self._usedPrefixes: set[str] = set(self._prefixesByNamespace.values())
161
+
162
+ @property
163
+ def namespaces(self) -> dict[str, str]:
164
+ return {
165
+ prefix: namespace
166
+ for namespace, prefix in sorted(
167
+ self._prefixesByNamespace.items(),
168
+ key=operator.itemgetter(1)
169
+ )
170
+ }
171
+
172
+ def __contains__(self, namespace: str) -> bool:
173
+ return namespace in self._prefixesByNamespace
174
+
175
+ def getPrefix(self, namespace: str) -> str | None:
176
+ return self._prefixesByNamespace.get(namespace)
177
+
178
+ def addNamespace(self, namespace: str, preferredPrefix: str) -> str:
179
+ prefix = self._prefixesByNamespace.get(namespace)
180
+ if prefix is not None:
181
+ return prefix
182
+
183
+ prefix = reservedUriAliases.get(namespace)
184
+ if prefix is None:
185
+ prefix = preferredPrefix
186
+ i = 2
187
+ while prefix in self._usedPrefixes:
188
+ prefix = f"{preferredPrefix}{i}"
189
+ i += 1
190
+ self._prefixesByNamespace[namespace] = prefix
191
+ self._usedPrefixes.add(prefix)
192
+ return prefix
193
+
145
194
 
146
195
  def saveLoadableOIM(
147
196
  modelXbrl: ModelXbrl,
@@ -160,20 +209,19 @@ def saveLoadableOIM(
160
209
  isXL = oimFile.endswith(".xlsx")
161
210
  isCSVorXL = isCSV or isXL
162
211
  if not isJSON and not isCSVorXL:
163
- return
212
+ oimFile = oimFile + ".json"
213
+ isJSON = True
164
214
 
165
- namespacePrefixes = {nsOim: "xbrl"}
166
- prefixNamespaces: dict[str, str] = {}
215
+ namespacePrefixes = NamespacePrefixes({nsOim: "xbrl"})
167
216
  if extensionPrefixes:
168
217
  for extensionPrefix, extensionNamespace in extensionPrefixes.items():
169
- namespacePrefixes[extensionNamespace] = extensionPrefix
170
- prefixNamespaces[extensionPrefix] = extensionNamespace
218
+ namespacePrefixes.addNamespace(extensionNamespace, extensionPrefix)
171
219
  linkTypeAliases = {}
172
220
  groupAliases = {}
173
221
 
174
222
  def compileQname(qname: QName) -> None:
175
223
  if qname.namespaceURI is not None and qname.namespaceURI not in namespacePrefixes:
176
- namespacePrefixes[qname.namespaceURI] = qname.prefix or ""
224
+ namespacePrefixes.addNamespace(qname.namespaceURI, qname.prefix or "")
177
225
 
178
226
  aspectsDefined = {qnOimConceptAspect, qnOimEntityAspect, qnOimPeriodAspect}
179
227
 
@@ -183,12 +231,8 @@ def saveLoadableOIM(
183
231
  return " ".join([oimValue(o) for o in obj])
184
232
  if isinstance(obj, QName) and obj.namespaceURI is not None:
185
233
  if obj.namespaceURI not in namespacePrefixes:
186
- if obj.prefix:
187
- namespacePrefixes[obj.namespaceURI] = obj.prefix
188
- else:
189
- _prefix = "_{}".format(sum(1 for p in namespacePrefixes if p.startswith("_")))
190
- namespacePrefixes[obj.namespaceURI] = _prefix
191
- return f"{namespacePrefixes[obj.namespaceURI]}:{obj.localName}"
234
+ namespacePrefixes.addNamespace(obj.namespaceURI, obj.prefix or "_")
235
+ return f"{namespacePrefixes.getPrefix(obj.namespaceURI)}:{obj.localName}"
192
236
  if isinstance(obj, (float, Decimal)):
193
237
  try:
194
238
  if isinf(obj):
@@ -198,7 +242,11 @@ def saveLoadableOIM(
198
242
  elif isinstance(obj, Decimal):
199
243
  # XML canonical representation of decimal requires a decimal point.
200
244
  # https://www.w3.org/TR/xmlschema-2/#decimal-canonical-representation
201
- return f"{obj:.1f}" if obj % 1 == 0 else f"{obj}"
245
+ if obj % 1 == 0:
246
+ return f"{obj:.1f}"
247
+ intPart, fracPart = f"{obj:f}".split(".")
248
+ canonicalFracPart = fracPart.rstrip("0") or "0"
249
+ return f"{intPart}.{canonicalFracPart}"
202
250
  else:
203
251
  return f"{obj}"
204
252
  except Exception:
@@ -283,8 +331,8 @@ def saveLoadableOIM(
283
331
  _schemePrefix = "scheme"
284
332
  else:
285
333
  _schemePrefix = f"scheme{len(entitySchemePrefixes) + 1}"
286
- entitySchemePrefixes[scheme] = _schemePrefix
287
- namespacePrefixes[scheme] = _schemePrefix
334
+ namespacePrefixes.addNamespace(scheme, _schemePrefix)
335
+ entitySchemePrefixes[scheme] = namespacePrefixes.getPrefix(scheme)
288
336
  for dim in cntx.qnameDims.values():
289
337
  compileQname(dim.dimensionQname)
290
338
  aspectsDefined.add(dim.dimensionQname)
@@ -297,23 +345,17 @@ def saveLoadableOIM(
297
345
  for measure in measures:
298
346
  compileQname(measure)
299
347
 
300
- if XbrlConst.xbrli in namespacePrefixes and namespacePrefixes[XbrlConst.xbrli] != "xbrli":
301
- namespacePrefixes[XbrlConst.xbrli] = "xbrli" # normalize xbrli prefix
302
-
303
348
  if hasLang:
304
349
  aspectsDefined.add(qnOimLangAspect)
305
350
  if hasUnits:
306
351
  aspectsDefined.add(qnOimUnitAspect)
307
352
 
308
353
  for footnoteRel in footnotesRelationshipSet.modelRelationships:
309
- typePrefix = "ftTyp_" + os.path.basename(footnoteRel.arcrole)
310
- if footnoteRel.linkrole == XbrlConst.defaultLinkRole:
311
- groupPrefix = "ftGrp_default"
312
- else:
313
- groupPrefix = "ftGrp_" + os.path.basename(footnoteRel.linkrole)
314
354
  if footnoteRel.arcrole not in linkTypeAliases:
355
+ typePrefix = reservedUriAliases.get(footnoteRel.arcrole, f"ftTyp_{os.path.basename(footnoteRel.arcrole)}")
315
356
  linkTypeAliases[footnoteRel.arcrole] = typePrefix
316
- if groupPrefix not in groupAliases:
357
+ if footnoteRel.linkrole not in groupAliases:
358
+ groupPrefix = reservedUriAliases.get(footnoteRel.linkrole, f"ftGrp_{os.path.basename(footnoteRel.linkrole)}")
317
359
  groupAliases[footnoteRel.linkrole] = groupPrefix
318
360
 
319
361
  dtsReferences = set()
@@ -354,12 +396,14 @@ def saveLoadableOIM(
354
396
  _link[groupPrefix] = []
355
397
  elif isCSVorXL:
356
398
  _link[groupPrefix] = {}
399
+ tgtId = toObj.id if toObj.id else f"f{toObj.objectIndex}"
357
400
  if isJSON:
358
401
  tgtIdList = _link[groupPrefix]
402
+ tgtIdList.append(tgtId)
359
403
  elif isCSVorXL:
360
- tgtIdList = _link[groupPrefix].setdefault(srcId, [])
361
- tgtId = toObj.id if toObj.id else f"f{toObj.objectIndex}"
362
- tgtIdList.append(tgtId)
404
+ # Footnote links in xBRL-CSV include the CSV table identifier.
405
+ tgtIdList = _link[groupPrefix].setdefault(f"facts.r_{srcId}.value", [])
406
+ tgtIdList.append(f"footnotes.r_{tgtId}.footnote")
363
407
  footnote = {
364
408
  "group": footnoteRel.linkrole,
365
409
  "footnoteType": footnoteRel.arcrole,
@@ -441,19 +485,17 @@ def saveLoadableOIM(
441
485
  factFootnotes(fact, oimFact=oimFact)
442
486
  return oimFact
443
487
 
444
- namespaces = {p: ns for ns, p in sorted(namespacePrefixes.items(), key=lambda item: item[1])}
445
-
446
488
  # common metadata
447
489
  oimReport = {} # top level of oim json output
448
490
  oimReport["documentInfo"] = oimDocInfo = {}
449
491
  oimDocInfo["documentType"] = nsOim + ("/xbrl-json" if isJSON else "/xbrl-csv")
450
492
  if isJSON:
451
493
  oimDocInfo["features"] = oimFeatures = {}
452
- oimDocInfo["namespaces"] = namespaces
494
+ oimDocInfo["namespaces"] = namespacePrefixes.namespaces
453
495
  if linkTypeAliases:
454
- oimDocInfo["linkTypes"] = {a: u for u, a in sorted(linkTypeAliases.items(), key=lambda item: item[1])}
455
- if linkTypeAliases:
456
- oimDocInfo["linkGroups"] = {a: u for u, a in sorted(groupAliases.items(), key=lambda item: item[1])}
496
+ oimDocInfo["linkTypes"] = {a: u for u, a in sorted(linkTypeAliases.items(), key=operator.itemgetter(1))}
497
+ if groupAliases:
498
+ oimDocInfo["linkGroups"] = {a: u for u, a in sorted(groupAliases.items(), key=operator.itemgetter(1))}
457
499
  oimDocInfo["taxonomy"] = dtsReferences
458
500
  if isJSON:
459
501
  oimFeatures["xbrl:canonicalValues"] = True
@@ -511,6 +553,8 @@ def saveLoadableOIM(
511
553
  if outputZip:
512
554
  fh.seek(0)
513
555
  outputZip.writestr(os.path.basename(oimFile), fh.read())
556
+ if not outputZip:
557
+ modelXbrl.modelManager.cntlr.showStatus(_("Saved JSON OIM file {}").format(oimFile))
514
558
 
515
559
  elif isCSVorXL:
516
560
  # save CSV
@@ -678,21 +722,31 @@ def saveLoadableOIM(
678
722
 
679
723
  # save footnotes
680
724
  if footnotesRelationshipSet.modelRelationships:
681
- footnotes = sorted(
682
- (footnote for fact in modelXbrl.facts for footnote in factFootnotes(fact, csvLinks=csvLinks)),
683
- key=lambda footnote: footnote["id"],
684
- )
725
+ footnotesDeduplicatedById = {
726
+ footnote["id"]: footnote
727
+ for fact in modelXbrl.facts
728
+ for footnote in factFootnotes(fact, csvLinks=csvLinks)
729
+ }
730
+ footnotes = sorted(footnotesDeduplicatedById.values(), key=operator.itemgetter("id"))
685
731
  if footnotes: # text footnotes
686
- oimTables["footnotes"] = csvFtTable = {}
687
- csvFtTable["url"] = "tbd"
688
- csvFtTable["tableDimensions"] = {}
689
- csvFtTable["factColumns"] = csvFtFactColumns = {}
690
- csvFtFactColumns["footnote"] = csvFtValCol = {}
691
- csvFtValCol["id"] = "$id"
692
- csvFtValCol["noteId"] = "$id"
693
- csvFtValCol["concept"] = "xbrl:note"
694
- csvFtValCol["language"] = "$language"
695
- _open("-footnotes.csv", "footnotes", csvFtTable)
732
+ footnotesTable = {"template": "footnotes"}
733
+ oimTables["footnotes"] = footnotesTable
734
+ csvTableTemplates[footnotesTable["template"]] = {
735
+ "rowIdColumn" : "id",
736
+ "dimensions": {
737
+ "language": "$language"
738
+ },
739
+ "columns": {
740
+ "id": {},
741
+ "footnote": {
742
+ "dimensions": {
743
+ "concept": "xbrl:note",
744
+ },
745
+ },
746
+ "language": {},
747
+ }
748
+ }
749
+ _open("-footnotes.csv", "footnotes", footnotesTable)
696
750
  cols = ("id", "footnote", "language")
697
751
  _writerow(cols, header=True)
698
752
  for footnote in footnotes:
@@ -702,16 +756,17 @@ def saveLoadableOIM(
702
756
  # save metadata
703
757
  if isCSV:
704
758
  assert isinstance(_baseURL, str)
705
- with open(_baseURL + "-metadata.json", "w", encoding="utf-8") as fh:
759
+ csvMetadataFile = _baseURL + "-metadata.json"
760
+ with open(csvMetadataFile, "w", encoding="utf-8") as fh:
706
761
  fh.write(json.dumps(oimReport, ensure_ascii=False, indent=2, sort_keys=False))
762
+ modelXbrl.modelManager.cntlr.showStatus(_("Saved CSV OIM metadata file {}").format(csvMetadataFile))
707
763
  elif isXL:
708
764
  _open(None, "metadata")
709
765
  _writerow(["metadata"], header=True)
710
766
  _writerow([json.dumps(oimReport, ensure_ascii=False, indent=1, sort_keys=False)])
711
767
  _close()
712
-
713
- if isXL:
714
768
  workbook.save(oimFile)
769
+ modelXbrl.modelManager.cntlr.showStatus(_("Saved Excel file {}").format(oimFile))
715
770
 
716
771
 
717
772
  def saveLoadableOIMMenuCommand(cntlr: CntlrWinMain) -> None:
@@ -722,18 +777,23 @@ def saveLoadableOIMMenuCommand(cntlr: CntlrWinMain) -> None:
722
777
  or cntlr.modelManager.modelXbrl is None
723
778
  or cntlr.modelManager.modelXbrl.modelDocument is None
724
779
  or cntlr.modelManager.modelXbrl.modelDocument.type
725
- not in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL)
780
+ not in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INLINEXBRLDOCUMENTSET)
726
781
  ):
782
+ cntlr.addToLog(
783
+ messageCode="arelleOIMsaver",
784
+ message=_("No supported XBRL instance documents loaded that can be saved to OIM format."),
785
+ )
727
786
  return
728
787
  # get file name into which to save log file while in foreground thread
729
788
  oimFile = cntlr.uiFileDialog(
730
789
  "save",
731
790
  title=_("arelle - Save Loadable OIM file"),
732
- initialdir=cntlr.config.setdefault("loadableExcelFileDir", "."),
791
+ initialdir=cntlr.config.setdefault("loadableOIMFileDir", "."),
733
792
  filetypes=[(_("JSON file .json"), "*.json"), (_("CSV file .csv"), "*.csv"), (_("XLSX file .xlsx"), "*.xlsx")],
734
793
  defaultextension=".json",
735
794
  ) # type: ignore[no-untyped-call]
736
795
  if not isinstance(oimFile, str):
796
+ # User cancelled file dialog.
737
797
  return
738
798
 
739
799
  cntlr.config["loadableOIMFileDir"] = os.path.dirname(oimFile)
@@ -606,7 +606,7 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
606
606
  for context in contextsWithWrongInstantDate:
607
607
  modelXbrl.error("ESEF.2.1.2.inappropriateInstantDate",
608
608
  _("Instant date %(actualValue)s in context %(contextID)s shall be replaced by %(expectedValue)s to ensure a better comparability between the facts."),
609
- modelObject=contextsWithWrongInstantDate, actualValue=context.instantDate, expectedValue=context.instantDate - timedelta(days=1), contextID=context.id)
609
+ modelObject=context, actualValue=context.instantDate, expectedValue=context.instantDate - timedelta(days=1), contextID=context.id)
610
610
 
611
611
  # identify unique contexts and units
612
612
  mapContext = {}
@@ -2,4 +2,4 @@ DISCLOSURE_SYSTEM_NT16 = 'NT16'
2
2
  DISCLOSURE_SYSTEM_NT17 = 'NT17'
3
3
  DISCLOSURE_SYSTEM_NT18 = 'NT18'
4
4
  DISCLOSURE_SYSTEM_NT19 = 'NT19'
5
- DISCLOSURE_SYSTEM_INLINE_NT19 = 'INLINE-NT19'
5
+ DISCLOSURE_SYSTEM_NL_INLINE_2024 = 'NL-INLINE-2024'
@@ -9,16 +9,22 @@ import regex as re
9
9
  from collections import defaultdict
10
10
  from dataclasses import dataclass
11
11
 
12
- from arelle.ModelInstanceObject import ModelUnit, ModelContext, ModelFact
12
+ from arelle.FunctionIxt import ixtNamespaces
13
+ from arelle.ModelInstanceObject import ModelUnit, ModelContext, ModelFact, ModelInlineFootnote
13
14
  from arelle.ModelValue import QName
14
15
  from arelle.ModelXbrl import ModelXbrl
15
16
  from arelle.utils.PluginData import PluginData
16
17
  from arelle.XmlValidate import lexicalPatterns
17
18
 
18
-
19
19
  XBRLI_IDENTIFIER_PATTERN = re.compile(r"^(?!00)\d{8}$")
20
20
  XBRLI_IDENTIFIER_SCHEMA = 'http://www.kvk.nl/kvk-id'
21
21
 
22
+ DISALLOWED_IXT_NAMESPACES = frozenset((
23
+ ixtNamespaces["ixt v1"],
24
+ ixtNamespaces["ixt v2"],
25
+ ixtNamespaces["ixt v3"],
26
+ ))
27
+
22
28
  @dataclass
23
29
  class PluginValidationDataExtension(PluginData):
24
30
  chamberOfCommerceRegistrationNumberQn: QName
@@ -42,6 +48,9 @@ class PluginValidationDataExtension(PluginData):
42
48
  _contextsWithSegments: list[ModelContext | None] | None = None
43
49
  _entityIdentifiers: set[tuple[str, str]] | None = None
44
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
45
54
  _unitsByDocument: dict[str, list[ModelUnit]] | None = None
46
55
 
47
56
  def contextsByDocument(self, modelXbrl: ModelXbrl) -> dict[str, list[ModelContext]]:
@@ -80,6 +89,23 @@ class PluginValidationDataExtension(PluginData):
80
89
  self._contextsWithPeriodTimeZone = contextsWithPeriodTimeZone
81
90
  self._contextsWithSegments = contextsWithSegments
82
91
 
92
+ def checkFootnote(self, modelXbrl: ModelXbrl) -> None:
93
+ factLangs = self.factLangs(modelXbrl)
94
+ footnotesRelationshipSet = modelXbrl.relationshipSet("XBRL-footnotes")
95
+ orphanedFootnotes = set()
96
+ noMatchLangFootnotes = set()
97
+ for elts in modelXbrl.ixdsEltById.values(): # type: ignore[attr-defined]
98
+ for elt in elts:
99
+ if isinstance(elt, ModelInlineFootnote):
100
+ if elt.textValue is not None:
101
+ if not any(isinstance(rel.fromModelObject, ModelFact)
102
+ for rel in footnotesRelationshipSet.toModelObject(elt)):
103
+ orphanedFootnotes.add(elt)
104
+ if not elt.xmlLang in factLangs:
105
+ noMatchLangFootnotes.add(elt)
106
+ self._noMatchLangFootnotes = noMatchLangFootnotes
107
+ self._orphanedFootnotes = orphanedFootnotes
108
+
83
109
  def entityIdentifiersInDocument(self, modelXbrl: ModelXbrl) -> set[tuple[str, str]]:
84
110
  if self._entityIdentifiers is not None:
85
111
  return self._entityIdentifiers
@@ -95,6 +121,16 @@ class PluginValidationDataExtension(PluginData):
95
121
  self._factsByDocument = dict(factsByDocument)
96
122
  return self._factsByDocument
97
123
 
124
+ def factLangs(self, modelXbrl: ModelXbrl) -> set[str]:
125
+ if self._factLangs is not None:
126
+ return self._factLangs
127
+ factLangs = set()
128
+ for fact in modelXbrl.facts:
129
+ if fact is not None:
130
+ factLangs.add(fact.xmlLang)
131
+ self._factLangs = factLangs
132
+ return self._factLangs
133
+
98
134
  def getContextsWithImproperContent(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
99
135
  if self._contextsWithImproperContent is None:
100
136
  self.checkContexts(self.contextsByDocument(modelXbrl))
@@ -119,6 +155,18 @@ class PluginValidationDataExtension(PluginData):
119
155
  assert(self._contextsWithSegments is not None)
120
156
  return self._contextsWithSegments
121
157
 
158
+ 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
163
+
164
+ 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
169
+
122
170
  def unitsByDocument(self, modelXbrl: ModelXbrl) -> dict[str, list[ModelUnit]]:
123
171
  if self._unitsByDocument is not None:
124
172
  return self._unitsByDocument
@@ -10,7 +10,7 @@ from arelle.ModelXbrl import ModelXbrl
10
10
  from arelle.ValidateXbrl import ValidateXbrl
11
11
  from arelle.typing import TypeGetText
12
12
  from arelle.utils.validate.ValidationPlugin import ValidationPlugin
13
- from .DisclosureSystems import DISCLOSURE_SYSTEM_NT16, DISCLOSURE_SYSTEM_NT17, DISCLOSURE_SYSTEM_NT18, DISCLOSURE_SYSTEM_NT19, DISCLOSURE_SYSTEM_INLINE_NT19
13
+ from .DisclosureSystems import DISCLOSURE_SYSTEM_NT16, DISCLOSURE_SYSTEM_NT17, DISCLOSURE_SYSTEM_NT18, DISCLOSURE_SYSTEM_NT19, DISCLOSURE_SYSTEM_NL_INLINE_2024
14
14
  from .PluginValidationDataExtension import PluginValidationDataExtension
15
15
 
16
16
  _: TypeGetText
@@ -132,7 +132,7 @@ class ValidationPluginExtension(ValidationPlugin):
132
132
  'kvk-rpt-jaarverantwoording-2023-nlgaap-verzekeringsmaatschappijen.xsd',
133
133
  'kvk-rpt-jaarverantwoording-2023-nlgaap-zorginstellingen.xsd',
134
134
  ]}
135
- elif disclosureSystem == DISCLOSURE_SYSTEM_NT19 or disclosureSystem == DISCLOSURE_SYSTEM_INLINE_NT19:
135
+ elif disclosureSystem == DISCLOSURE_SYSTEM_NT19 or disclosureSystem == DISCLOSURE_SYSTEM_NL_INLINE_2024:
136
136
  jenvNamespace = 'http://www.nltaxonomie.nl/nt19/jenv/20241211/dictionary/jenv-bw2-data'
137
137
  kvkINamespace = 'http://www.nltaxonomie.nl/nt19/kvk/20241211/dictionary/kvk-data'
138
138
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt19/sbr/20240301/dictionary/nl-types'
@@ -192,7 +192,7 @@ class ValidationPluginExtension(ValidationPlugin):
192
192
  def modelXbrlLoadComplete(self, modelXbrl: ModelXbrl, *args: Any, **kwargs: Any) -> ModelDocument | LoadingException | None:
193
193
  if self.disclosureSystemFromPluginSelected(modelXbrl):
194
194
  disclosureSystem = modelXbrl.modelManager.disclosureSystem.name
195
- if disclosureSystem in (DISCLOSURE_SYSTEM_NT16, DISCLOSURE_SYSTEM_NT17, DISCLOSURE_SYSTEM_NT18, DISCLOSURE_SYSTEM_NT19, DISCLOSURE_SYSTEM_INLINE_NT19):
195
+ if disclosureSystem in (DISCLOSURE_SYSTEM_NT16, DISCLOSURE_SYSTEM_NT17, DISCLOSURE_SYSTEM_NT18, DISCLOSURE_SYSTEM_NT19, DISCLOSURE_SYSTEM_NL_INLINE_2024):
196
196
  # Dutch taxonomies prior to 2025 incorrectly used hypercube linkrole for roots instead of dimension linkrole.
197
197
  paramQName = qname('tlbDimRelsUseHcRoleForDomainRoots', noPrefixIsNoNamespace=True)
198
198
  modelXbrl.modelManager.formulaOptions.parameterValues[paramQName] = (None, "true")
@@ -14,6 +14,8 @@ from pathlib import Path
14
14
  from typing import Any
15
15
 
16
16
  from arelle.ModelDocument import LoadingException, ModelDocument
17
+ from arelle.ModelXbrl import ModelXbrl
18
+ from arelle.ValidateXbrl import ValidateXbrl
17
19
  from arelle.Version import authorLabel, copyrightLabel
18
20
  from .ValidationPluginExtension import ValidationPluginExtension
19
21
  from .rules import br_kvk, fg_nl, fr_kvk, fr_nl, nl_kvk
@@ -46,6 +48,16 @@ def validateXbrlFinally(*args: Any, **kwargs: Any) -> None:
46
48
  return validationPlugin.validateXbrlFinally(*args, **kwargs)
47
49
 
48
50
 
51
+ def modelTestcaseVariationReportPackageIxdsOptions(
52
+ val: ValidateXbrl,
53
+ rptPkgIxdsOptions: dict[str, bool],
54
+ *args: Any,
55
+ **kwargs: Any,
56
+ ) -> None:
57
+ rptPkgIxdsOptions["lookOutsideReportsDirectory"] = True
58
+ rptPkgIxdsOptions["combineIntoSingleIxds"] = True
59
+
60
+
49
61
  __pluginInfo__ = {
50
62
  "name": PLUGIN_NAME,
51
63
  "version": "0.0.1",
@@ -53,8 +65,10 @@ __pluginInfo__ = {
53
65
  "license": "Apache-2",
54
66
  "author": authorLabel,
55
67
  "copyright": copyrightLabel,
68
+ "import": ("inlineXbrlDocumentSet",), # import dependent modules
56
69
  "DisclosureSystem.Types": disclosureSystemTypes,
57
70
  "DisclosureSystem.ConfigURL": disclosureSystemConfigURL,
58
71
  "ModelXbrl.LoadComplete": modelXbrlLoadComplete,
59
72
  "Validate.XBRL.Finally": validateXbrlFinally,
73
+ "ModelTestcaseVariation.ReportPackageIxdsOptions": modelTestcaseVariationReportPackageIxdsOptions,
60
74
  }
@@ -4,8 +4,8 @@
4
4
  xsi:noNamespaceSchemaLocation="../../../../config/disclosuresystems.xsd">
5
5
  <!-- see arelle/config/disclosuresystems.xml for full comments -->
6
6
  <DisclosureSystem
7
- names="INLINE-NT19|inline-nt19|kvk-ixbrl-2024-preview"
8
- description="Checks for NT2024"
7
+ names="NL-INLINE-2024|nl-inline-2024|kvk-inline-2024-preview"
8
+ description="Checks for NL INLINE 2024"
9
9
  validationType="NL"
10
10
  />
11
11
  <DisclosureSystem
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
 
6
6
  from datetime import date, timedelta
7
7
 
8
+ from arelle.ModelInstanceObject import ModelInlineFact
8
9
  from arelle.XmlValidateConst import VALID
9
10
  from dateutil import relativedelta
10
11
  from collections.abc import Iterable
@@ -20,10 +21,8 @@ from arelle.typing import TypeGetText
20
21
  from arelle.utils.PluginHooks import ValidationHook
21
22
  from arelle.utils.validate.Decorator import validation
22
23
  from arelle.utils.validate.Validation import Validation
23
- from ..DisclosureSystems import (
24
- DISCLOSURE_SYSTEM_INLINE_NT19
25
- )
26
- from ..PluginValidationDataExtension import PluginValidationDataExtension, XBRLI_IDENTIFIER_PATTERN, XBRLI_IDENTIFIER_SCHEMA
24
+ from ..DisclosureSystems import DISCLOSURE_SYSTEM_NL_INLINE_2024
25
+ from ..PluginValidationDataExtension import PluginValidationDataExtension, XBRLI_IDENTIFIER_PATTERN, XBRLI_IDENTIFIER_SCHEMA, DISALLOWED_IXT_NAMESPACES
27
26
 
28
27
  if TYPE_CHECKING:
29
28
  from arelle.ModelXbrl import ModelXbrl
@@ -44,7 +43,7 @@ def _getReportingPeriodDateValue(modelXbrl: ModelXbrl, qname: QName) -> date | N
44
43
  @validation(
45
44
  hook=ValidationHook.XBRL_FINALLY,
46
45
  disclosureSystems=[
47
- DISCLOSURE_SYSTEM_INLINE_NT19
46
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
48
47
  ],
49
48
  )
50
49
  def rule_nl_kvk_3_1_1_1(
@@ -72,7 +71,7 @@ def rule_nl_kvk_3_1_1_1(
72
71
  @validation(
73
72
  hook=ValidationHook.XBRL_FINALLY,
74
73
  disclosureSystems=[
75
- DISCLOSURE_SYSTEM_INLINE_NT19
74
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
76
75
  ],
77
76
  )
78
77
  def rule_nl_kvk_3_1_1_2(
@@ -99,7 +98,7 @@ def rule_nl_kvk_3_1_1_2(
99
98
  @validation(
100
99
  hook=ValidationHook.XBRL_FINALLY,
101
100
  disclosureSystems=[
102
- DISCLOSURE_SYSTEM_INLINE_NT19
101
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
103
102
  ],
104
103
  )
105
104
  def rule_nl_kvk_3_1_2_1(
@@ -114,7 +113,7 @@ def rule_nl_kvk_3_1_2_1(
114
113
  contextsWithPeriodTime = pluginData.getContextsWithPeriodTime(val.modelXbrl)
115
114
  if len(contextsWithPeriodTime) !=0:
116
115
  yield Validation.error(
117
- codes='NL.NL-KVK-3.1.2.1',
116
+ codes='NL.NL-KVK-3.1.2.1.periodWithTimeContent',
118
117
  msg=_('xbrli:startDate, xbrli:endDate, xbrli:instant must be formatted as yyyy-mm-dd without time'),
119
118
  modelObject = contextsWithPeriodTime
120
119
  )
@@ -123,7 +122,7 @@ def rule_nl_kvk_3_1_2_1(
123
122
  @validation(
124
123
  hook=ValidationHook.XBRL_FINALLY,
125
124
  disclosureSystems=[
126
- DISCLOSURE_SYSTEM_INLINE_NT19
125
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
127
126
  ],
128
127
  )
129
128
  def rule_nl_kvk_3_1_2_2(
@@ -138,7 +137,7 @@ def rule_nl_kvk_3_1_2_2(
138
137
  contextsWithPeriodTimeZone = pluginData.getContextsWithPeriodTimeZone(val.modelXbrl)
139
138
  if len(contextsWithPeriodTimeZone) !=0:
140
139
  yield Validation.error(
141
- codes='NL.NL-KVK-3.1.2.2',
140
+ codes='NL.NL-KVK-3.1.2.2.periodWithTimeZone',
142
141
  msg=_('xbrli:startDate, xbrli:endDate, xbrli:instant must be formatted as yyyy-mm-dd without time zone'),
143
142
  modelObject = contextsWithPeriodTimeZone
144
143
  )
@@ -147,7 +146,7 @@ def rule_nl_kvk_3_1_2_2(
147
146
  @validation(
148
147
  hook=ValidationHook.XBRL_FINALLY,
149
148
  disclosureSystems=[
150
- DISCLOSURE_SYSTEM_INLINE_NT19
149
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
151
150
  ],
152
151
  )
153
152
  def rule_nl_kvk_3_1_3_1 (
@@ -162,7 +161,7 @@ def rule_nl_kvk_3_1_3_1 (
162
161
  contextsWithSegments = pluginData.getContextsWithSegments(val.modelXbrl)
163
162
  if len(contextsWithSegments) !=0:
164
163
  yield Validation.error(
165
- codes='NL.NL-KVK-3.1.3.1',
164
+ codes='NL.NL-KVK-3.1.3.1.segmentUsed',
166
165
  msg=_('xbrli:segment must not be used in contexts.'),
167
166
  modelObject = contextsWithSegments
168
167
  )
@@ -171,7 +170,7 @@ def rule_nl_kvk_3_1_3_1 (
171
170
  @validation(
172
171
  hook=ValidationHook.XBRL_FINALLY,
173
172
  disclosureSystems=[
174
- DISCLOSURE_SYSTEM_INLINE_NT19
173
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
175
174
  ],
176
175
  )
177
176
  def rule_nl_kvk_3_1_3_2 (
@@ -186,7 +185,7 @@ def rule_nl_kvk_3_1_3_2 (
186
185
  contextsWithImproperContent = pluginData.getContextsWithImproperContent(val.modelXbrl)
187
186
  if len(contextsWithImproperContent) !=0:
188
187
  yield Validation.error(
189
- codes='NL.NL-KVK-3.1.3.2',
188
+ codes='NL.NL-KVK-3.1.3.2.scenarioContainsNotAllowedContent',
190
189
  msg=_('xbrli:scenario must only contain content defined in XBRL Dimensions specification.'),
191
190
  modelObject = contextsWithImproperContent
192
191
  )
@@ -195,7 +194,7 @@ def rule_nl_kvk_3_1_3_2 (
195
194
  @validation(
196
195
  hook=ValidationHook.XBRL_FINALLY,
197
196
  disclosureSystems=[
198
- DISCLOSURE_SYSTEM_INLINE_NT19
197
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
199
198
  ],
200
199
  )
201
200
  def rule_nl_kvk_3_1_4_1 (
@@ -220,7 +219,7 @@ def rule_nl_kvk_3_1_4_1 (
220
219
  @validation(
221
220
  hook=ValidationHook.XBRL_FINALLY,
222
221
  disclosureSystems=[
223
- DISCLOSURE_SYSTEM_INLINE_NT19
222
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
224
223
  ],
225
224
  )
226
225
  def rule_nl_kvk_3_1_4_2 (
@@ -244,3 +243,105 @@ def rule_nl_kvk_3_1_4_2 (
244
243
  ),
245
244
  modelObject=regFact
246
245
  )
246
+
247
+
248
+ @validation(
249
+ hook=ValidationHook.XBRL_FINALLY,
250
+ disclosureSystems=[
251
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
252
+ ],
253
+ )
254
+ def rule_nl_kvk_3_2_1_1 (
255
+ pluginData: PluginValidationDataExtension,
256
+ val: ValidateXbrl,
257
+ *args: Any,
258
+ **kwargs: Any,
259
+ ) -> Iterable[Validation]:
260
+ """
261
+ NL-KVK.3.2.1.1: precision should not be used on numeric facts.
262
+ """
263
+ factsWithPrecision = []
264
+ for fact in val.modelXbrl.facts:
265
+ if fact is not None and fact.isNumeric and fact.precision:
266
+ factsWithPrecision.append(fact)
267
+ if len(factsWithPrecision) >0:
268
+ yield Validation.error(
269
+ codes='NL.NL-KVK-3.2.1.1.precisionAttributeUsed',
270
+ msg=_('Precision should not be used on numeric facts.'),
271
+ modelObject = factsWithPrecision
272
+ )
273
+
274
+
275
+ @validation(
276
+ hook=ValidationHook.XBRL_FINALLY,
277
+ disclosureSystems=[
278
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
279
+ ],
280
+ )
281
+ def rule_nl_kvk_3_2_3_1 (
282
+ pluginData: PluginValidationDataExtension,
283
+ val: ValidateXbrl,
284
+ *args: Any,
285
+ **kwargs: Any,
286
+ ) -> Iterable[Validation]:
287
+ """
288
+ NL-KVK.3.2.3.1: Transformation Registry 4 or newer are allowed. Everything else is prohibited.
289
+ """
290
+ transformRegistryErrors = []
291
+ for fact in val.modelXbrl.facts:
292
+ if isinstance(fact, ModelInlineFact):
293
+ if fact.format is not None and fact.format.namespaceURI in DISALLOWED_IXT_NAMESPACES:
294
+ transformRegistryErrors.append(fact)
295
+ if len(transformRegistryErrors) >0:
296
+ yield Validation.error(
297
+ codes='NL.NL-KVK.3.2.3.1.incorrectTransformationRuleApplied',
298
+ msg=_('Transformation Registry 4 or newer are allowed. Everything else is prohibited.'),
299
+ modelObject = transformRegistryErrors
300
+ )
301
+
302
+
303
+ @validation(
304
+ hook=ValidationHook.XBRL_FINALLY,
305
+ disclosureSystems=[
306
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
307
+ ],
308
+ )
309
+ def rule_nl_kvk_3_3_1_1 (
310
+ pluginData: PluginValidationDataExtension,
311
+ val: ValidateXbrl,
312
+ *args: Any,
313
+ **kwargs: Any,
314
+ ) -> Iterable[Validation]:
315
+ """
316
+ NL-KVK.3.3.1.1: Ensure that every nonempty <link:footnote> element is associated with at least one fact in the XBRL document.
317
+ """
318
+ orphanedFootnotes = pluginData.getOrphanedFootnotes(val.modelXbrl)
319
+ if len(orphanedFootnotes) >0:
320
+ yield Validation.error(
321
+ codes='NL.NL-KVK.3.3.1.1.unusedFootnote',
322
+ msg=_('Ensure that every nonempty <link:footnote> element is associated with at least one fact in the XBRL document.'),
323
+ modelObject = orphanedFootnotes
324
+ )
325
+
326
+ @validation(
327
+ hook=ValidationHook.XBRL_FINALLY,
328
+ disclosureSystems=[
329
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
330
+ ],
331
+ )
332
+ def rule_nl_kvk_3_3_1_2 (
333
+ pluginData: PluginValidationDataExtension,
334
+ val: ValidateXbrl,
335
+ *args: Any,
336
+ **kwargs: Any,
337
+ ) -> Iterable[Validation]:
338
+ """
339
+ NL-KVK.3.3.1.2: The xml:lang attribute of each footnote matches the language of at least one textual fact.
340
+ """
341
+ noMatchLangFootnotes = pluginData.getNoMatchLangFootnotes(val.modelXbrl)
342
+ if len(noMatchLangFootnotes) >0:
343
+ yield Validation.error(
344
+ codes='NL.NL-KVK.3.3.1.2.footnoteInLanguagesOtherThanLanguageOfContentOfAnyTextualFact',
345
+ msg=_('The xml:lang attribute of each footnote matches the language of at least one textual fact.'),
346
+ modelObject = noMatchLangFootnotes
347
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arelle-release
3
- Version: 2.37.5
3
+ Version: 2.37.7
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License: Apache-2.0
@@ -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=50acj2edwwIxVjMnQ3MdxuCq1B89g6peCogPi1Ox_OI,94190
4
+ arelle/CntlrCmdLine.py,sha256=-V3daLdYaDRqLTnJ8VYHkaYfvFEZURodCuh1kqNcPO0,94194
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
@@ -34,7 +34,7 @@ arelle/InstanceAspectsEvaluator.py,sha256=TePNIs_m0vCIbN5N4PXEyJm529T2WBFi2zmv-7
34
34
  arelle/LeiUtil.py,sha256=tSPrbQrXEeH5pXgGA_6MAdgMZp20NaW5izJglIXyEQk,5095
35
35
  arelle/LocalViewer.py,sha256=WVrfek_bLeFFxgWITi1EQb6xCQN8O9Ks-ZL16vRncSk,3080
36
36
  arelle/Locale.py,sha256=aKC1Uaen_dbPGb92kZa_yUoo7On_QtWlvr5H_F9BNXg,33008
37
- arelle/ModelDocument.py,sha256=l5HcggS5948YQpDXhvDv2NG0LnUIfTMNmdzrFlEL-bE,129222
37
+ arelle/ModelDocument.py,sha256=Sq6umEdn-aNHjxIpEsXTT7A4V25nGY0JiylSnhr9zSI,130749
38
38
  arelle/ModelDtsObject.py,sha256=JXPRiFOsbB5tZjEDc6rECuUtXMbF4oxfnwrQvKo-i5U,88656
39
39
  arelle/ModelFormulaObject.py,sha256=beUSxEFm7aoa9iimmvXLYCHdizAtOmhDqk6wmvbc9Zg,122537
40
40
  arelle/ModelInstanceObject.py,sha256=pAcwQBr85_fQCGT18JSOGGwzAZ3J-oWIU9sj9UUXLOk,73928
@@ -65,7 +65,7 @@ arelle/UITkTable.py,sha256=N83cXi5c0lLZLsDbwSKcPrlYoUoGsNavGN5YRx6d9XY,39810
65
65
  arelle/UiUtil.py,sha256=3G0xPclZI8xW_XQDbiFrmylB7Nd5muqi5n2x2oMkMZU,34218
66
66
  arelle/Updater.py,sha256=ho8Z_9GOL39H1jHL3Gaw5uc6av7J8ZBB6dR_X-nF_e0,7124
67
67
  arelle/UrlUtil.py,sha256=HrxZSG59EUMGMMGmWPuZkPi5-0BGqY3jAMkp7V4IdZo,32400
68
- arelle/Validate.py,sha256=JNjlgA8On4Ero2DjRNxCYKAs6L8DyJlmZD24Ch712bQ,55312
68
+ arelle/Validate.py,sha256=_7lDoGtUCyHgWK1Ak375D-kuPBZmDCNfSr_wsTLq10k,55328
69
69
  arelle/ValidateDuplicateFacts.py,sha256=074y-VWCOBHoi6iV6wDL_IXBtdz9oeI1uPvjEcC1oDs,21717
70
70
  arelle/ValidateFilingText.py,sha256=qBDrS3O9xtvGLn8Qfmjedg4iaClmeDA-ti7KM4JXY0A,54024
71
71
  arelle/ValidateInfoset.py,sha256=Rz_XBi5Ha43KpxXYhjLolURcWVx5qmqyjLxw48Yt9Dg,20396
@@ -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=rerVv2bkyHju_24j_qkXddEpdbpWMlSRnKzm4NdB1lc,513
126
+ arelle/_version.py,sha256=riELix1lK26X1jDSmwh4QjjGsgWelyK7-SfSm4xCIPY,513
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=2e9-rIZwGwjTlLILadXuQ1jIuPtKbXd2538owHu3-EE,181900
297
+ arelle/oim/Load.py,sha256=TX5lA0MsN1Vig0A6ozlY-eOa9z0OaAxBcsICu_jrlk0,182158
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
@@ -314,7 +314,7 @@ arelle/plugin/formulaLoader.py,sha256=_pPZQPAZeNjGj85rvH7QRl4gEjYD7Yhxl1JhuV9wOo
314
314
  arelle/plugin/formulaSaver.py,sha256=STlKyDA-pVUxZoEW57MSu74RdpyHVTxaHvOZyOt0cyg,31385
315
315
  arelle/plugin/formulaXPathChecker.py,sha256=sEEeLHx17XSj8eOgFdzYLBp9ZFk2UUYLOEKtaF_pq34,18795
316
316
  arelle/plugin/functionsMath.py,sha256=Z8N7ok3w1aOusCQA9QvqYwQ8W1j80bb-_4lVclBnNQM,9037
317
- arelle/plugin/inlineXbrlDocumentSet.py,sha256=hAIuRG6vugWEpqpWvx80ELfoKl1pinnNbpX8X4ERe-4,55226
317
+ arelle/plugin/inlineXbrlDocumentSet.py,sha256=wdlEg9OLm81E_aOINeDsPVHi03_v-dC7F9HrqmrF9e8,55256
318
318
  arelle/plugin/loadFromExcel.py,sha256=galvvaj9jTKMMRUasCSh1SQnCCBzoN_HEpYWv0fmUdM,124407
319
319
  arelle/plugin/loadFromOIM.py,sha256=dJHnX56bmuY40f6vRMsQ7pJmIWcB5N_3jmYWGGnZSdM,903
320
320
  arelle/plugin/profileCmdLine.py,sha256=uLL0fGshpiwtzyLKAtW0WuXAvcRtZgxQG6swM0e4BHA,2370
@@ -323,7 +323,7 @@ arelle/plugin/saveCHComponentFile.py,sha256=phW-n96P0BWONLqX3wBcuNcDa_IQ8QVfFWKL
323
323
  arelle/plugin/saveDTS.py,sha256=D8hfFiM9Gc9LE7ZV0-pDvOHeU7Y5ebOzZx_nXzoZrl8,3216
324
324
  arelle/plugin/saveHtmlEBAtables.py,sha256=OITN4ftI_atUO5NvrDJDKUc0CAk67GY68Jl16xDBXiI,10961
325
325
  arelle/plugin/saveLoadableExcel.py,sha256=ZPYB6injFabav0dRzgS7adCFzfHkwtftjl3PfBjijuU,20539
326
- arelle/plugin/saveLoadableOIM.py,sha256=onT61QRygFCMGS7xTZHJz9WSo1V5PyqKQRtoTBf7GDE,38180
326
+ arelle/plugin/saveLoadableOIM.py,sha256=lJ2qZ6ZMxCCAkz9wY0cucOhk8wTZulNlSlXH3qCKy2Q,40633
327
327
  arelle/plugin/saveSKOS.py,sha256=7Z1Qedf83zMo9EbigKkxNpiMjzkTYQvLEnwWMObLc1Y,12465
328
328
  arelle/plugin/saveSampleInstance.py,sha256=w66Nd4He8yIK4Il_M9qnelpeUJ_6cBBe5q01DanOxEA,23823
329
329
  arelle/plugin/streamingExtensions.py,sha256=9W4iQ1u8LFn7-ZEfbqBtuwKiZj-aq8FUXNmj5VawRXQ,47619
@@ -370,24 +370,24 @@ arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py,sha256=AGjPhegfY9hg
370
370
  arelle/plugin/validate/ESEF/ESEF_2021/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
371
371
  arelle/plugin/validate/ESEF/ESEF_Current/DTS.py,sha256=epp-PBh1NJzQqgxUE6C468HmoDc2w3j54rMwfiOAry4,29334
372
372
  arelle/plugin/validate/ESEF/ESEF_Current/Image.py,sha256=w36sCTy8QbsuKABjkK6PTWce2A4zFN_rMnEM2wi5WEc,11364
373
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py,sha256=F7UahhDQ4jieUyPKqzLCAld8e1YbSjMmZrEciAUXTH4,73130
373
+ arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py,sha256=z0ZAjDbt6jhGmcSSjfaW-MiR8jO8_ovVGXfGEk43060,73109
374
374
  arelle/plugin/validate/ESEF/ESEF_Current/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
375
375
  arelle/plugin/validate/ESEF/resources/authority-validations.json,sha256=JriLZ45KmUYlQiPbXJCAahobqdrst64Ay77bofZhB5Q,14940
376
376
  arelle/plugin/validate/ESEF/resources/config.xml,sha256=t3STU_-QYM7Ay8YwZRPapnohiWVWhjfr4L2Rjx9xN9U,3902
377
377
  arelle/plugin/validate/FERC/__init__.py,sha256=V4fXcFKBsjFFPs9_1NhvDjWpEQCoQM0tRQMS0I1Ua7U,11462
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
- arelle/plugin/validate/NL/DisclosureSystems.py,sha256=VFMcO8GJ8kIqhOV5McyEejaGJOR5JrmeF8GdFuS9IZw,174
381
- arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=WuCXeiCYlDWDrQ--lRkTVTTuD_KTemgYsiWMxs6psxM,6259
382
- arelle/plugin/validate/NL/ValidationPluginExtension.py,sha256=pRnKCXnHzwW3lDDZ_yk5d3Mia4d8a_qhqIvZK6kItTc,15216
383
- arelle/plugin/validate/NL/__init__.py,sha256=9NkkfosHnAzJhBa84KDAsoyU7vd4_DO3GYKTSvKuOk8,2554
384
- arelle/plugin/validate/NL/resources/config.xml,sha256=vu5pA-Iw6cgb5aep8LNLNPCkmG1QF6RTw3TCgEIest8,1102
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
383
+ arelle/plugin/validate/NL/__init__.py,sha256=99uMv4ESHwyJqA-Xq_hBvHygm0BQ3NxcmAJnVYUkSgg,3104
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
386
386
  arelle/plugin/validate/NL/rules/br_kvk.py,sha256=0SwKieWzTDm3YMsXPS6zTdgbk7_Z9CzqRkRmCRz1OiQ,15789
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=_eUzTAFaT_hH3EXW7MPJjM7dmBa-P14TqPMFDw4xVPc,8163
390
+ arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=OqckHX2Nxv-pvSe3ieai5P-Czb-cBOuNI04BJaCpXnQ,11822
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.5.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
710
+ arelle_release-2.37.7.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
@@ -734,9 +734,9 @@ tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Tests.cs,sha256=_0T
734
734
  tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Usings.cs,sha256=0IC7tQ27uAqlt8ZGBrJPK7BPj3kjiodPcHWB3v_JT-o,29
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
- tests/integration_tests/validation/assets.py,sha256=KLiv3HJTXn_tZW6icEaEtvcr9MrfMh-bHe27V5LLssE,6153
737
+ tests/integration_tests/validation/assets.py,sha256=Ag9qPYrodcC-Ly6aygqapV0vG2Cbn_Tigg4v4F9xX4U,8295
738
738
  tests/integration_tests/validation/conformance_suite_config.py,sha256=fLur7EOoOdu6kKlkZ3tY3Sjn9G-gpB4OGbOKZkqa-fA,10383
739
- tests/integration_tests/validation/conformance_suite_configs.py,sha256=b1-iQc0ZBzq_G6mCLIk2URYaoI5pWp6QGENavOHZNr8,7187
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
@@ -762,6 +762,7 @@ 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
766
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py,sha256=O_LFVBZPkjxmbrU7_C7VTLtrdoCUx2bYXOXw6_MlRtQ,846
766
767
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py,sha256=aTN3Ez6lPsZsuypHZP84DneOtYxUZSjUiGypHy6ofHQ,846
767
768
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py,sha256=sqHLjrHc95dTu0guTgKkphaKM1zNfKGnN4GKkZDLzeU,845
@@ -1555,8 +1556,8 @@ tests/unit_tests/arelle/oim/test_load.py,sha256=NxiUauQwJVfWAHbbpsMHGSU2d3Br8Pki
1555
1556
  tests/unit_tests/arelle/plugin/test_plugin_imports.py,sha256=bdhIs9frAnFsdGU113yBk09_jis-z43dwUItMFYuSYM,1064
1556
1557
  tests/unit_tests/arelle/plugin/validate/ESEF/ESEF_Current/test_validate_css_url.py,sha256=XHABmejQt7RlZ0udh7v42f2Xb2STGk_fSaIaJ9i2xo0,878
1557
1558
  tests/unit_tests/arelle/utils/validate/test_decorator.py,sha256=ZS8FqIY1g-2FCbjF4UYm609dwViax6qBMRJSi0vfuhY,2482
1558
- arelle_release-2.37.5.dist-info/METADATA,sha256=4Kw7oBfKyh0aON2AEk16a98SktKugAPZNfo3jey0Oww,9064
1559
- arelle_release-2.37.5.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
1560
- arelle_release-2.37.5.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1561
- arelle_release-2.37.5.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1562
- arelle_release-2.37.5.dist-info/RECORD,,
1559
+ arelle_release-2.37.7.dist-info/METADATA,sha256=jw-Xo8dgy0EDDrxqoGqtLrE4HNq2FylFDemIssw4j3g,9064
1560
+ arelle_release-2.37.7.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
1561
+ arelle_release-2.37.7.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1562
+ arelle_release-2.37.7.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1563
+ arelle_release-2.37.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.0.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -125,4 +125,47 @@ NL_PACKAGES: dict[str, list[ConformanceSuiteAssetConfig]] = {
125
125
  ),
126
126
  NL_BASE,
127
127
  ],
128
+ 'NL-INLINE-2024': [
129
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
130
+ Path('kvk-2024_taxonomie.zip'),
131
+ public_download_url='https://www.sbr-nl.nl/sites/default/files/2025-01/kvk-2024_taxonomie.zip',
132
+ ),
133
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
134
+ Path('rj-2024_taxonomie.zip'),
135
+ public_download_url='https://www.sbr-nl.nl/sites/default/files/2025-01/rj-2024_taxonomie.zip',
136
+ ),
137
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
138
+ Path('bw2-titel9_taxonomie.zip'),
139
+ public_download_url='https://www.sbr-nl.nl/sites/default/files/2025-01/bw2-titel9_taxonomie.zip',
140
+ ),
141
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
142
+ Path('ncgc-2022_taxonomie.zip'),
143
+ public_download_url='https://www.sbr-nl.nl/sites/default/files/2025-01/ncgc-2022_taxonomie.zip',
144
+ ),
145
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
146
+ Path('ifrs-2024_taxonomie.zip'),
147
+ public_download_url='https://www.sbr-nl.nl/sites/default/files/2025-01/ifrs-2024_taxonomie.zip',
148
+ ),
149
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
150
+ Path('wnt-2024_taxonomie.zip'),
151
+ public_download_url='https://www.sbr-nl.nl/sites/default/files/2025-01/wnt-2024_taxonomie.zip',
152
+ ),
153
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
154
+ Path('IFRSAT-2024-03-27_29.08.24.zip'),
155
+ public_download_url='https://www.ifrs.org/content/dam/ifrs/standards/taxonomy/ifrs-taxonomies/IFRSAT-2024-03-27_29.08.24.zip',
156
+ ),
157
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
158
+ Path('KVK_taxonomie_2024_draft.zip'),
159
+ public_download_url='',
160
+ ),
161
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
162
+ Path('JenV_taxonomie_2024_draft.zip'),
163
+ public_download_url='',
164
+ ),
165
+ ConformanceSuiteAssetConfig.public_taxonomy_package(
166
+ Path('RJ_taxonomie_2024_draft.zip'),
167
+ public_download_url='',
168
+ ),
169
+ LEI_2020_07_02,
170
+ ],
128
171
  }
@@ -24,6 +24,7 @@ from tests.integration_tests.validation.conformance_suite_configurations.nl_nt16
24
24
  from tests.integration_tests.validation.conformance_suite_configurations.nl_nt17 import config as nl_nt17
25
25
  from tests.integration_tests.validation.conformance_suite_configurations.nl_nt18 import config as nl_nt18
26
26
  from tests.integration_tests.validation.conformance_suite_configurations.nl_nt19 import config as nl_nt19
27
+ from tests.integration_tests.validation.conformance_suite_configurations.nl_inline_2024 import config as nl_inline_2024
27
28
  from tests.integration_tests.validation.conformance_suite_configurations.ros_current import config as ros_current
28
29
  from tests.integration_tests.validation.conformance_suite_configurations.xbrl_2_1 import config as xbrl_2_1
29
30
  from tests.integration_tests.validation.conformance_suite_configurations.xbrl_calculations_1_1 import config as xbrl_calculations_1_1
@@ -72,6 +73,7 @@ ALL_CONFORMANCE_SUITE_CONFIGS: tuple[ConformanceSuiteConfig, ...] = (
72
73
  nl_nt17,
73
74
  nl_nt18,
74
75
  nl_nt19,
76
+ nl_inline_2024,
75
77
  ros_current,
76
78
  xbrl_2_1,
77
79
  xbrl_calculations_1_1,
@@ -0,0 +1,116 @@
1
+ from pathlib import PurePath, Path
2
+
3
+ from tests.integration_tests.validation.assets import NL_PACKAGES
4
+ from tests.integration_tests.validation.conformance_suite_config import ConformanceSuiteConfig, ConformanceSuiteAssetConfig, AssetSource
5
+
6
+ config = ConformanceSuiteConfig(
7
+ args=[
8
+ '--disclosureSystem', 'NL-INLINE-2024',
9
+ '--baseTaxonomyValidation', 'none',
10
+ ],
11
+ assets=[
12
+ ConformanceSuiteAssetConfig.conformance_suite(
13
+ Path('conformance-suite-2024-sbr-domein-handelsregister.zip'),
14
+ entry_point=Path('conformance-suite-2024-sbr-domein-handelsregister/index.xml'),
15
+ public_download_url='https://www.sbr-nl.nl/sites/default/files/2025-04/conformance-suite-2024-sbr-domein-handelsregister.zip',
16
+ source=AssetSource.S3_PUBLIC,
17
+ ),
18
+ *NL_PACKAGES['NL-INLINE-2024'],
19
+ ],
20
+ expected_failure_ids=frozenset([
21
+ # Not Implemented
22
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-4_2/index.xml:TC4_invalid',
23
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC4_invalid',
24
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC5_invalid',
25
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC6_invalid',
26
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC7_invalid',
27
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-3-1_2/index.xml:TC3_invalid', # Expects an error code with a preceding double quote. G3-3-1_3 expects the same code without the typo.
28
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-3-1_3/index.xml:TC2_invalid',
29
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_1/index.xml:TC2_invalid',
30
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_2/index.xml:TC2_invalid',
31
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_3/index.xml:TC2_invalid',
32
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_4/index.xml:TC2_invalid',
33
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_5/index.xml:TC2_invalid',
34
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-2_1/index.xml:TC2_invalid',
35
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-2_1/index.xml:TC3_invalid',
36
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_1/index.xml:TC3_invalid',
37
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_1/index.xml:TC4_invalid',
38
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_2/index.xml:TC2_invalid',
39
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_3/index.xml:TC2_invalid',
40
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_4/index.xml:TC2_invalid',
41
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_5/index.xml:TC2_invalid',
42
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_5/index.xml:TC3_invalid',
43
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-2_1/index.xml:TC3_invalid',
44
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-2_2/index.xml:TC2_invalid',
45
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-3_1/index.xml:TC2_invalid',
46
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-4_1/index.xml:TC2_invalid',
47
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-6-2_1/index.xml:TC2_invalid',
48
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-6-3_3/index.xml:TC2_invalid',
49
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-7-1_1/index.xml:TC2_invalid',
50
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC3_invalid',
51
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC4_invalid',
52
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC5_invalid',
53
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC6_invalid',
54
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_1/index.xml:TC7_invalid',
55
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_2/index.xml:TC2_invalid',
56
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-1_2/index.xml:TC3_invalid',
57
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-2_1/index.xml:TC3_invalid',
58
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-1-2_2/index.xml:TC2_invalid',
59
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-0_1/index.xml:TC2_invalid',
60
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-0_2/index.xml:TC2_invalid',
61
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-1_1/index.xml:TC2_invalid', # Expects scenarioNotUsedInExtensionTaxonomy and segmentUsed errors. scenarioNotUsedInExtensionTaxonomy not yet implemented.
62
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-2_2/index.xml:TC2_invalid',
63
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-2-3_1/index.xml:TC2_invalid',
64
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-1_1/index.xml:TC2_invalid',
65
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-1_1/index.xml:TC3_invalid',
66
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-1_1/index.xml:TC4_invalid',
67
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-3-2_1/index.xml:TC2_invalid',
68
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-1_1/index.xml:TC2_invalid',
69
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_1/index.xml:TC2_invalid',
70
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_2/index.xml:TC2_invalid',
71
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_3/index.xml:TC2_invalid',
72
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-2_4/index.xml:TC2_invalid',
73
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-3_1/index.xml:TC2_invalid',
74
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-3_1/index.xml:TC3_invalid',
75
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-3_2/index.xml:TC2_invalid',
76
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-3_2/index.xml:TC3_invalid',
77
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-5_2/index.xml:TC2_invalid',
78
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-5_2/index.xml:TC3_invalid',
79
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_1/index.xml:TC1_valid',
80
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_1/index.xml:TC2_invalid',
81
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_2/index.xml:TC1_valid',
82
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_2/index.xml:TC2_invalid',
83
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/G6-1-1_1/index.xml:TC2_invalid',
84
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_II_Par_1/index.xml:TC3_invalid',
85
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_III_Par_1/index.xml:TC2_invalid',
86
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_III_Par_1/index.xml:TC3_invalid',
87
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_11_G4-2-2_1/index.xml:TC2_invalid',
88
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_11_G4-2-2_1/index.xml:TC3_invalid',
89
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_12_G3-2-4_1/index.xml:TC4_invalid',
90
+ '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
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_1/index.xml:TC2_invalid',
96
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_2/index.xml:TC2_invalid',
97
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_3/index.xml:TC3_invalid',
98
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_3/index.xml:TC4_invalid',
99
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_4_3/index.xml:TC5_invalid',
100
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_5/index.xml:TC2_invalid',
101
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_5/index.xml:TC3_invalid',
102
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_6/index.xml:TC3_invalid',
103
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_6/index.xml:TC4_invalid',
104
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_8_G4-4-5/index.xml:TC2_invalid',
105
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_8_G4-4-5/index.xml:TC3_invalid',
106
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_IV_Par_9_Par_10/index.xml:TC3_invalid',
107
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Art_3/index.xml:TC4_invalid',
108
+ 'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Art_6_a/index.xml:TC2_invalid',
109
+ ]),
110
+ info_url='https://www.sbr-nl.nl/sbr-domeinen/handelsregister/uitbreiding-elektronische-deponering-handelsregister',
111
+ name=PurePath(__file__).stem,
112
+ network_or_cache_required=False,
113
+ plugins=frozenset({'validate/NL'}),
114
+ shards=8,
115
+ test_case_result_options='match-all',
116
+ )