arelle-release 2.37.19__py3-none-any.whl → 2.37.21__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of arelle-release might be problematic. Click here for more details.

Files changed (36) hide show
  1. arelle/CntlrCmdLine.py +8 -0
  2. arelle/FileSource.py +2 -2
  3. arelle/ModelInstanceObject.py +1 -1
  4. arelle/ModelXbrl.py +1 -1
  5. arelle/RuntimeOptions.py +0 -6
  6. arelle/XbrlConst.py +2 -0
  7. arelle/_version.py +2 -2
  8. arelle/api/Session.py +7 -5
  9. arelle/formula/XPathContext.py +22 -22
  10. arelle/formula/XPathParser.py +2 -2
  11. arelle/plugin/OimTaxonomy/ModelValueMore.py +2 -2
  12. arelle/plugin/OimTaxonomy/ViewXbrlTxmyObj.py +2 -3
  13. arelle/plugin/OimTaxonomy/XbrlConcept.py +2 -1
  14. arelle/plugin/OimTaxonomy/XbrlCube.py +8 -8
  15. arelle/plugin/OimTaxonomy/XbrlDts.py +5 -5
  16. arelle/plugin/OimTaxonomy/XbrlImportedTaxonomy.py +3 -3
  17. arelle/plugin/OimTaxonomy/XbrlNetwork.py +3 -3
  18. arelle/plugin/OimTaxonomy/XbrlProperty.py +3 -3
  19. arelle/plugin/OimTaxonomy/XbrlReport.py +3 -3
  20. arelle/plugin/OimTaxonomy/XbrlTableTemplate.py +3 -3
  21. arelle/plugin/OimTaxonomy/XbrlTypes.py +1 -1
  22. arelle/plugin/OimTaxonomy/__init__.py +4 -5
  23. arelle/plugin/validate/NL/LinkbaseType.py +77 -0
  24. arelle/plugin/validate/NL/PluginValidationDataExtension.py +195 -26
  25. arelle/plugin/validate/NL/ValidationPluginExtension.py +1 -0
  26. arelle/plugin/validate/NL/__init__.py +3 -3
  27. arelle/plugin/validate/NL/rules/nl_kvk.py +465 -17
  28. {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/METADATA +2 -1
  29. {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/RECORD +36 -35
  30. tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +23 -17
  31. tests/unit_tests/arelle/test_import.py +0 -30
  32. tests/unit_tests/arelle/test_runtimeoptions.py +0 -13
  33. {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/WHEEL +0 -0
  34. {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/entry_points.txt +0 -0
  35. {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/licenses/LICENSE.md +0 -0
  36. {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/top_level.txt +0 -0
@@ -12,7 +12,7 @@ from arelle.XmlValidateConst import VALID
12
12
  from collections.abc import Iterable
13
13
  from typing import Any, cast, TYPE_CHECKING
14
14
 
15
- from arelle import XmlUtil
15
+ from arelle import XmlUtil, XbrlConst
16
16
  from arelle.ValidateXbrl import ValidateXbrl
17
17
  from arelle.typing import TypeGetText
18
18
  from arelle.utils.PluginHooks import ValidationHook
@@ -21,10 +21,11 @@ from arelle.utils.validate.Validation import Validation
21
21
  from arelle.ValidateDuplicateFacts import getHashEquivalentFactGroups, getAspectEqualFacts
22
22
  from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
23
23
  from ..DisclosureSystems import DISCLOSURE_SYSTEM_NL_INLINE_2024
24
+ from ..LinkbaseType import LinkbaseType
24
25
  from ..PluginValidationDataExtension import (PluginValidationDataExtension, ALLOWABLE_LANGUAGES,
25
- DISALLOWED_IXT_NAMESPACES, EFFECTIVE_TAXONOMY_URLS,
26
- MAX_REPORT_PACKAGE_SIZE_MBS, XBRLI_IDENTIFIER_PATTERN,
27
- XBRLI_IDENTIFIER_SCHEMA)
26
+ DISALLOWED_IXT_NAMESPACES, EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES,
27
+ MAX_REPORT_PACKAGE_SIZE_MBS, TAXONOMY_URLS_BY_YEAR,
28
+ XBRLI_IDENTIFIER_PATTERN, XBRLI_IDENTIFIER_SCHEMA)
28
29
 
29
30
  if TYPE_CHECKING:
30
31
  from arelle.ModelXbrl import ModelXbrl
@@ -532,7 +533,7 @@ def rule_nl_kvk_3_4_1_3 (
532
533
  if len(facts) > 0:
533
534
  yield Validation.error(
534
535
  codes='NL.NL-KVK.3.4.1.3.transformableElementIncludedInHiddenSection',
535
- msg=_('The ix:hidden section should not include elements that are eligible for transformation'
536
+ msg=_('The ix:hidden section should not include elements that are eligible for transformation '
536
537
  'according to the latest recommended Transformation Rules Registry.'),
537
538
  modelObject=facts
538
539
  )
@@ -770,7 +771,7 @@ def rule_nl_kvk_3_6_3_1(
770
771
  """
771
772
  invalidBasenames = []
772
773
  for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
773
- filenameParts = pluginData.getFilenameParts(basename)
774
+ filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
774
775
  if not filenameParts:
775
776
  continue # Filename is not formatted correctly enough to determine {base}
776
777
  if len(filenameParts.get('base', '')) > 20:
@@ -803,7 +804,7 @@ def rule_nl_kvk_3_6_3_2(
803
804
  """
804
805
  invalidBasenames = []
805
806
  for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
806
- filenameParts = pluginData.getFilenameParts(basename)
807
+ filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
807
808
  if not filenameParts:
808
809
  invalidBasenames.append(basename)
809
810
  if len(invalidBasenames) > 0:
@@ -847,6 +848,156 @@ def rule_nl_kvk_3_6_3_3(
847
848
  'Invalid filenames: %(invalidBasenames)s'))
848
849
 
849
850
 
851
+ @validation(
852
+ hook=ValidationHook.FINALLY,
853
+ disclosureSystems=[
854
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
855
+ ],
856
+ )
857
+ def rule_nl_kvk_3_7_1_1(
858
+ pluginData: PluginValidationDataExtension,
859
+ val: ValidateXbrl,
860
+ *args: Any,
861
+ **kwargs: Any,
862
+ ) -> Iterable[Validation]:
863
+ """
864
+ NL-KVK.3.7.1.1: The filing MUST be valid against the formula linkbase assertions with error severity.
865
+ """
866
+ modelXbrl = val.modelXbrl
867
+ sumErrMsgs = 0
868
+ for e in modelXbrl.errors:
869
+ if isinstance(e,dict):
870
+ for id, (numSat, numUnsat, numOkMsgs, numWrnMsgs, numErrMsgs) in e.items():
871
+ sumErrMsgs += numErrMsgs
872
+ if sumErrMsgs > 0:
873
+ yield Validation.error(
874
+ codes='NL.NL-KVK.3.7.1.1.targetXBRLDocumentWithFormulaErrors',
875
+ msg=_("The filing is not valid against the formula linkbase assertions with error severity. Address the %(numUnsatisfied)s unresolved formula linkbase validation errors."),
876
+ modelObject=modelXbrl,
877
+ numUnsatisfied=sumErrMsgs
878
+ )
879
+
880
+
881
+ @validation(
882
+ hook=ValidationHook.FINALLY,
883
+ disclosureSystems=[
884
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
885
+ ],
886
+ )
887
+ def rule_nl_kvk_3_7_1_2(
888
+ pluginData: PluginValidationDataExtension,
889
+ val: ValidateXbrl,
890
+ *args: Any,
891
+ **kwargs: Any,
892
+ ) -> Iterable[Validation]:
893
+ """
894
+ NL-KVK.3.7.1.2: The filing MUST be valid against the formula linkbase assertions with error warning.
895
+ """
896
+ modelXbrl = val.modelXbrl
897
+ sumWrnMsgs = 0
898
+ for e in modelXbrl.errors:
899
+ if isinstance(e,dict):
900
+ for id, (numSat, numUnsat, numOkMsgs, numWrnMsgs, numErrMsgs) in e.items():
901
+ sumWrnMsgs += numWrnMsgs
902
+ if sumWrnMsgs > 0:
903
+ yield Validation.warning(
904
+ codes='NL.NL-KVK.3.7.1.2.targetXBRLDocumentWithFormulaWarnings',
905
+ msg=_("The filing is not valid against the formula linkbase assertions with warning severity. Address the %(numUnsatisfied)s unresolved formula linkbase validation warnings."),
906
+ modelObject=modelXbrl,
907
+ numUnsatisfied=sumWrnMsgs
908
+ )
909
+
910
+
911
+ @validation(
912
+ hook=ValidationHook.XBRL_FINALLY,
913
+ disclosureSystems=[
914
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
915
+ ],
916
+ )
917
+ def rule_nl_kvk_4_1_1_1(
918
+ pluginData: PluginValidationDataExtension,
919
+ val: ValidateXbrl,
920
+ *args: Any,
921
+ **kwargs: Any,
922
+ ) -> Iterable[Validation]:
923
+ """
924
+ NL-KVK.4.1.1.1: Extension taxonomies MUST consist of at least a schema file and presentation,
925
+ calculation and definition linkbases.
926
+ A label linkbase is also required if extension elements are present.
927
+ """
928
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
929
+ linkbaseIsMissing = {
930
+ LinkbaseType.CALCULATION: True,
931
+ LinkbaseType.DEFINITION: True,
932
+ LinkbaseType.LABEL: len(extensionData.extensionConcepts) > 0,
933
+ LinkbaseType.PRESENTATION: True,
934
+ }
935
+ for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
936
+ hasArcs = False
937
+ linkbaseType = LinkbaseType.fromRefUri(extensionDocumentData.hrefXlinkRole)
938
+ for linkbaseData in extensionDocumentData.linkbases:
939
+ if linkbaseType is not None:
940
+ if linkbaseType == linkbaseData.linkbaseType:
941
+ if linkbaseData.hasArcs:
942
+ hasArcs = True
943
+ break
944
+ elif linkbaseData.hasArcs:
945
+ linkbaseType = linkbaseData.linkbaseType
946
+ hasArcs = True
947
+ break
948
+ if linkbaseType is None:
949
+ continue
950
+ if hasArcs and linkbaseIsMissing.get(linkbaseType, False):
951
+ linkbaseIsMissing[linkbaseType] = False
952
+ missingFiles = set(linkbaseType.getLowerName() for linkbaseType, isMissing in linkbaseIsMissing.items() if isMissing)
953
+ if len(missingFiles) > 0:
954
+ yield Validation.error(
955
+ codes='NL.NL-KVK.4.1.1.1.extensionTaxonomyWrongFilesStructure',
956
+ msg=_('The extension taxonomy is missing one or more required components: %(missingFiles)s '
957
+ 'Review to ensure that the schema file, presentation, calculation, '
958
+ 'and definition linkbases are included and not empty. '
959
+ 'A label linkbase is also required if extension elements are present.'),
960
+ modelObject=val.modelXbrl, missingFiles=", ".join(missingFiles)
961
+ )
962
+
963
+
964
+ @validation(
965
+ hook=ValidationHook.XBRL_FINALLY,
966
+ disclosureSystems=[
967
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
968
+ ],
969
+ )
970
+ def rule_nl_kvk_4_1_1_2(
971
+ pluginData: PluginValidationDataExtension,
972
+ val: ValidateXbrl,
973
+ *args: Any,
974
+ **kwargs: Any,
975
+ ) -> Iterable[Validation]:
976
+ """
977
+ NL-KVK.4.1.1.2: Each linkbase type MUST be provided in a separate linkbase file.
978
+ """
979
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
980
+ errors = []
981
+ for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
982
+ linkbasesFound = set(
983
+ linkbase.linkbaseType.getLowerName()
984
+ for linkbase in extensionDocumentData.linkbases
985
+ if linkbase.linkbaseType is not None
986
+ )
987
+ if len(linkbasesFound) > 1:
988
+ errors.append((modelDocument, linkbasesFound))
989
+ for modelDocument, linkbasesFound in errors:
990
+ yield Validation.error(
991
+ codes='NL.NL-KVK.4.1.1.2.linkbasesNotSeparateFiles',
992
+ msg=_('Linkbase types are not stored in separate files. '
993
+ 'Review linkbase files and ensure they are provided as individual files. '
994
+ 'Found: %(linkbasesFound)s. in %(basename)s.'),
995
+ modelObject=modelDocument.xmlRootElement,
996
+ basename=modelDocument.basename,
997
+ linkbasesFound=", ".join(sorted(linkbasesFound))
998
+ )
999
+
1000
+
850
1001
  @validation(
851
1002
  hook=ValidationHook.XBRL_FINALLY,
852
1003
  disclosureSystems=[
@@ -861,17 +1012,314 @@ def rule_nl_kvk_4_1_2_1(
861
1012
  ) -> Iterable[Validation]:
862
1013
  """
863
1014
  NL-KVK.4.1.2.1: Validate that the imported taxonomy matches the KVK-specified entry point.
864
- - https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd,
865
- - https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd.
1015
+ - https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd
1016
+ - https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd
866
1017
  """
867
- if val.modelXbrl.modelDocument is not None:
868
- pluginData.checkFilingDTS(val, val.modelXbrl.modelDocument, [])
869
- if not any(e in val.extensionImportedUrls for e in EFFECTIVE_TAXONOMY_URLS):
870
- yield Validation.error(
871
- codes='NL.NL-KVK.4.1.2.1.requiredEntryPointNotImported',
872
- msg=_('The extension taxonomy must import the entry point of the taxonomy files prepared by KVK.'),
873
- modelObject=val.modelXbrl.modelDocument
874
- )
1018
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1019
+ matches = extensionData.extensionImportedUrls & EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES
1020
+ if not matches:
1021
+ yield Validation.error(
1022
+ codes='NL.NL-KVK.4.1.2.1.requiredEntryPointNotImported',
1023
+ msg=_('The extension taxonomy must import the entry point of the taxonomy files prepared by KVK.'),
1024
+ modelObject=val.modelXbrl.modelDocument
1025
+ )
1026
+
1027
+
1028
+ @validation(
1029
+ hook=ValidationHook.XBRL_FINALLY,
1030
+ disclosureSystems=[
1031
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1032
+ ],
1033
+ )
1034
+ def rule_nl_kvk_4_1_2_2(
1035
+ pluginData: PluginValidationDataExtension,
1036
+ val: ValidateXbrl,
1037
+ *args: Any,
1038
+ **kwargs: Any,
1039
+ ) -> Iterable[Validation]:
1040
+ """
1041
+ NL-KVK.4.1.2.2: The legal entity’s extension taxonomy MUST import the applicable version of
1042
+ the taxonomy files prepared by KVK.
1043
+ """
1044
+ reportingPeriod = pluginData.getReportingPeriod(val.modelXbrl)
1045
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1046
+ matches = extensionData.extensionImportedUrls & TAXONOMY_URLS_BY_YEAR.get(reportingPeriod or '', set())
1047
+ if not reportingPeriod or not matches:
1048
+ yield Validation.error(
1049
+ codes='NL.NL-KVK.4.1.2.2.incorrectKvkTaxonomyVersionUsed',
1050
+ msg=_('The extension taxonomy MUST import the applicable version of the taxonomy files prepared by KVK '
1051
+ 'for the reported financial reporting period of %(reportingPeriod)s.'),
1052
+ modelObject=val.modelXbrl.modelDocument
1053
+ )
1054
+
1055
+
1056
+ @validation(
1057
+ hook=ValidationHook.XBRL_FINALLY,
1058
+ disclosureSystems=[
1059
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1060
+ ],
1061
+ )
1062
+ def rule_nl_kvk_4_1_5_1(
1063
+ pluginData: PluginValidationDataExtension,
1064
+ val: ValidateXbrl,
1065
+ *args: Any,
1066
+ **kwargs: Any,
1067
+ ) -> Iterable[Validation]:
1068
+ """
1069
+ NL-KVK.4.1.5.1: The `{base}` component of the extension document filename SHOULD not exceed twenty characters.
1070
+ """
1071
+ invalidBasenames = []
1072
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1073
+ for extensionDocument in extensionData.extensionDocuments.values():
1074
+ basename = extensionDocument.basename
1075
+ filenameParts = pluginData.getFilenameParts(basename, pluginData.getExtensionFilenameFormatPattern())
1076
+ if not filenameParts:
1077
+ continue # Filename is not formatted correctly enough to determine {base}
1078
+ if len(filenameParts.get('base', '')) > 20:
1079
+ invalidBasenames.append(basename)
1080
+ if len(invalidBasenames) > 0:
1081
+ yield Validation.warning(
1082
+ codes='NL.NL-KVK.4.1.5.1.baseComponentInNameOfTaxonomyFileExceedsTwentyCharacters',
1083
+ invalidBasenames=', '.join(invalidBasenames),
1084
+ msg=_('The {base} component of the extension document filename is greater than twenty characters. '
1085
+ 'The {base} component can either be the KVK number or the legal entity\'s name. '
1086
+ 'If the legal entity\'s name has been utilized, review to shorten the name to twenty characters or less. '
1087
+ 'Invalid filenames: %(invalidBasenames)s'))
1088
+
1089
+
1090
+ @validation(
1091
+ hook=ValidationHook.XBRL_FINALLY,
1092
+ disclosureSystems=[
1093
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1094
+ ],
1095
+ )
1096
+ def rule_nl_kvk_4_1_5_2(
1097
+ pluginData: PluginValidationDataExtension,
1098
+ val: ValidateXbrl,
1099
+ *args: Any,
1100
+ **kwargs: Any,
1101
+ ) -> Iterable[Validation]:
1102
+ """
1103
+ NL-KVK.4.1.5.2: Extension document filename SHOULD match the {base}-{date}_{suffix}-{lang}.{extension} pattern.
1104
+ """
1105
+ invalidBasenames = []
1106
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1107
+ for extensionDocument in extensionData.extensionDocuments.values():
1108
+ basename = extensionDocument.basename
1109
+ filenameParts = pluginData.getFilenameParts(basename, pluginData.getExtensionFilenameFormatPattern())
1110
+ if not filenameParts:
1111
+ invalidBasenames.append(basename)
1112
+ if len(invalidBasenames) > 0:
1113
+ yield Validation.warning(
1114
+ codes='NL.NL-KVK.4.1.5.2.extensionTaxonomyDocumentNameDoesNotFollowNamingConvention',
1115
+ invalidBasenames=', '.join(invalidBasenames),
1116
+ msg=_('The extension document filename does not match the naming convention outlined by the KVK. '
1117
+ 'It is recommended to be in the {base}-{date}_{suffix}-{lang}.{extension} format. '
1118
+ '{extension} must be one of the following: html, htm, xhtml. '
1119
+ 'Review formatting and update as appropriate. '
1120
+ 'Invalid filenames: %(invalidBasenames)s'))
1121
+
1122
+
1123
+ @validation(
1124
+ hook=ValidationHook.XBRL_FINALLY,
1125
+ disclosureSystems=[
1126
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1127
+ ],
1128
+ )
1129
+ def rule_nl_kvk_4_2_0_1(
1130
+ pluginData: PluginValidationDataExtension,
1131
+ val: ValidateXbrl,
1132
+ *args: Any,
1133
+ **kwargs: Any,
1134
+ ) -> Iterable[Validation]:
1135
+ """
1136
+ NL-KVK.4.2.0.1: Tuples MUST NOT be defined in extension taxonomy.
1137
+ """
1138
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1139
+ tupleConcepts = [
1140
+ concept for concept in extensionData.extensionConcepts if concept.isTuple
1141
+ ]
1142
+ if len(tupleConcepts) > 0:
1143
+ yield Validation.error(
1144
+ codes='NL.NL-KVK.4.2.0.1.tupleElementUsed',
1145
+ modelObject=tupleConcepts,
1146
+ msg=_('The extension taxonomy must not define tuple concepts.'))
1147
+
1148
+
1149
+ @validation(
1150
+ hook=ValidationHook.XBRL_FINALLY,
1151
+ disclosureSystems=[
1152
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1153
+ ],
1154
+ )
1155
+ def rule_nl_kvk_4_2_0_2(
1156
+ pluginData: PluginValidationDataExtension,
1157
+ val: ValidateXbrl,
1158
+ *args: Any,
1159
+ **kwargs: Any,
1160
+ ) -> Iterable[Validation]:
1161
+ """
1162
+ NL-KVK.4.2.0.2: Items with xbrli:fractionItemType data type MUST NOT be defined in extension taxonomy
1163
+ """
1164
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1165
+ fractionConcepts = [
1166
+ concept for concept in extensionData.extensionConcepts if concept.isFraction
1167
+ ]
1168
+ if len(fractionConcepts) > 0:
1169
+ yield Validation.error(
1170
+ codes='NL.NL-KVK.4.2.0.2.fractionElementUsed',
1171
+ modelObject=fractionConcepts,
1172
+ msg=_('The extension taxonomy must not define fraction concepts.'))
1173
+
1174
+
1175
+ @validation(
1176
+ hook=ValidationHook.XBRL_FINALLY,
1177
+ disclosureSystems=[
1178
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1179
+ ],
1180
+ )
1181
+ def rule_nl_kvk_4_2_1_1(
1182
+ pluginData: PluginValidationDataExtension,
1183
+ val: ValidateXbrl,
1184
+ *args: Any,
1185
+ **kwargs: Any,
1186
+ ) -> Iterable[Validation]:
1187
+ """
1188
+ NL-KVK.4.2.1.1: Extension taxonomy MUST set xbrli:scenario as context element on definition arcs with
1189
+ http://xbrl.org/int/dim/arcrole/all and http://xbrl.org/int/dim/arcrole/notAll arcroles.
1190
+ """
1191
+ errors = []
1192
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1193
+ for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
1194
+ for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.all, XbrlConst.notAll}):
1195
+ if arc.get(XbrlConst.qnXbrldtContextElement.clarkNotation) != "scenario":
1196
+ errors.append(arc)
1197
+ if len(errors) > 0:
1198
+ yield Validation.error(
1199
+ codes='NL.NL-KVK.4.2.1.1.scenarioNotUsedInExtensionTaxonomy',
1200
+ modelObject=errors,
1201
+ msg=_('The definition linkbase is missing xbrli:scenario in extension taxonomy. '
1202
+ 'Review definition linkbase and update as appropriate.'),
1203
+ )
1204
+
1205
+
1206
+ @validation(
1207
+ hook=ValidationHook.XBRL_FINALLY,
1208
+ disclosureSystems=[
1209
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1210
+ ],
1211
+ )
1212
+ def rule_nl_kvk_4_4_1_1(
1213
+ pluginData: PluginValidationDataExtension,
1214
+ val: ValidateXbrl,
1215
+ *args: Any,
1216
+ **kwargs: Any,
1217
+ ) -> Iterable[Validation]:
1218
+ """
1219
+ NL-KVK.4.4.1.1: Arithmetical relationships defined in the calculation linkbase of an extension taxonomy
1220
+ MUST use the https://xbrl.org/2023/arcrole/summation-item arcrole as defined in Calculation 1.1 specification.
1221
+ """
1222
+ errors = []
1223
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1224
+ for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
1225
+ for arc in extensionDocumentData.iterArcsByType(LinkbaseType.CALCULATION, excludeArcroles={XbrlConst.summationItem11}):
1226
+ errors.append(arc)
1227
+ if len(errors) > 0:
1228
+ yield Validation.error(
1229
+ codes='NL.NL-KVK.4.4.1.1.incorrectSummationItemArcroleUsed',
1230
+ modelObject=errors,
1231
+ msg=_('Calculation relationships should follow the requirements of the Calculation 1.1 specification. '
1232
+ 'Update to ensure use of summation-item arcrole in the calculation linkbase.'),
1233
+ )
1234
+
1235
+
1236
+ @validation(
1237
+ hook=ValidationHook.XBRL_FINALLY,
1238
+ disclosureSystems=[
1239
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1240
+ ],
1241
+ )
1242
+ def rule_nl_kvk_4_4_2_1(
1243
+ pluginData: PluginValidationDataExtension,
1244
+ val: ValidateXbrl,
1245
+ *args: Any,
1246
+ **kwargs: Any,
1247
+ ) -> Iterable[Validation]:
1248
+ """
1249
+ NL-KVK.4.4.2.1: Extension taxonomies MUST NOT define definition arcs
1250
+ with http://xbrl.org/int/dim/arcrole/notAll arcrole.
1251
+ """
1252
+ errors = []
1253
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1254
+ for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
1255
+ for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.notAll}):
1256
+ errors.append(arc)
1257
+ if len(errors) > 0:
1258
+ yield Validation.error(
1259
+ codes='NL.NL-KVK.4.4.2.1.notAllArcroleUsedInDefinitionLinkbase',
1260
+ modelObject=errors,
1261
+ msg=_('Incorrect hypercube settings are found. Ensure that positive hypercubes are in use.'),
1262
+ )
1263
+
1264
+
1265
+ @validation(
1266
+ hook=ValidationHook.XBRL_FINALLY,
1267
+ disclosureSystems=[
1268
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1269
+ ],
1270
+ )
1271
+ def rule_nl_kvk_4_4_2_2(
1272
+ pluginData: PluginValidationDataExtension,
1273
+ val: ValidateXbrl,
1274
+ *args: Any,
1275
+ **kwargs: Any,
1276
+ ) -> Iterable[Validation]:
1277
+ """
1278
+ NL-KVK.4.4.2.2: Hypercubes appearing as target of definition arc with
1279
+ http://xbrl.org/int/dim/arcrole/all arcrole MUST have xbrldt:closed attribute set to “true”.
1280
+ """
1281
+ errors = []
1282
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1283
+ for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
1284
+ for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.all}):
1285
+ if arc.get(XbrlConst.qnXbrldtClosed.clarkNotation, "false") != "true":
1286
+ errors.append(arc)
1287
+ if len(errors) > 0:
1288
+ yield Validation.error(
1289
+ codes='NL.NL-KVK.4.4.2.2.openPositiveHypercubeInDefinitionLinkbase',
1290
+ modelObject=errors,
1291
+ msg=_('Incorrect hypercube settings are found. Ensure that positive hypercubes are closed.'),
1292
+ )
1293
+
1294
+
1295
+ @validation(
1296
+ hook=ValidationHook.XBRL_FINALLY,
1297
+ disclosureSystems=[
1298
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
1299
+ ],
1300
+ )
1301
+ def rule_nl_kvk_4_4_2_3(
1302
+ pluginData: PluginValidationDataExtension,
1303
+ val: ValidateXbrl,
1304
+ *args: Any,
1305
+ **kwargs: Any,
1306
+ ) -> Iterable[Validation]:
1307
+ """
1308
+ NL-KVK.4.4.2.3: Hypercubes appearing as target of definition arc with
1309
+ http://xbrl.org/int/dim/arcrole/notAll arcrole MUST have xbrldt:closed attribute set to “false”.
1310
+ """
1311
+ errors = []
1312
+ extensionData = pluginData.getExtensionData(val.modelXbrl)
1313
+ for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
1314
+ for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.notAll}):
1315
+ if arc.get(XbrlConst.qnXbrldtClosed.clarkNotation, "true") != "false":
1316
+ errors.append(arc)
1317
+ if len(errors) > 0:
1318
+ yield Validation.error(
1319
+ codes='NL.NL-KVK.4.4.2.3.closedNegativeHypercubeInDefinitionLinkbase',
1320
+ modelObject=errors,
1321
+ msg=_('Incorrect hypercube settings are found. Ensure that negative hypercubes are not closed.'),
1322
+ )
875
1323
 
876
1324
 
877
1325
  @validation(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arelle-release
3
- Version: 2.37.19
3
+ Version: 2.37.21
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License: Apache-2.0
@@ -41,6 +41,7 @@ Requires-Dist: pillow<12,>=10
41
41
  Requires-Dist: pyparsing==3.*
42
42
  Requires-Dist: python-dateutil==2.*
43
43
  Requires-Dist: regex
44
+ Requires-Dist: typing-extensions==4.*
44
45
  Provides-Extra: crypto
45
46
  Requires-Dist: pycryptodome==3.*; extra == "crypto"
46
47
  Provides-Extra: db