arelle-release 2.37.19__py3-none-any.whl → 2.37.21__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of arelle-release might be problematic. Click here for more details.
- arelle/CntlrCmdLine.py +8 -0
- arelle/FileSource.py +2 -2
- arelle/ModelInstanceObject.py +1 -1
- arelle/ModelXbrl.py +1 -1
- arelle/RuntimeOptions.py +0 -6
- arelle/XbrlConst.py +2 -0
- arelle/_version.py +2 -2
- arelle/api/Session.py +7 -5
- arelle/formula/XPathContext.py +22 -22
- arelle/formula/XPathParser.py +2 -2
- arelle/plugin/OimTaxonomy/ModelValueMore.py +2 -2
- arelle/plugin/OimTaxonomy/ViewXbrlTxmyObj.py +2 -3
- arelle/plugin/OimTaxonomy/XbrlConcept.py +2 -1
- arelle/plugin/OimTaxonomy/XbrlCube.py +8 -8
- arelle/plugin/OimTaxonomy/XbrlDts.py +5 -5
- arelle/plugin/OimTaxonomy/XbrlImportedTaxonomy.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlNetwork.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlProperty.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlReport.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlTableTemplate.py +3 -3
- arelle/plugin/OimTaxonomy/XbrlTypes.py +1 -1
- arelle/plugin/OimTaxonomy/__init__.py +4 -5
- arelle/plugin/validate/NL/LinkbaseType.py +77 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +195 -26
- arelle/plugin/validate/NL/ValidationPluginExtension.py +1 -0
- arelle/plugin/validate/NL/__init__.py +3 -3
- arelle/plugin/validate/NL/rules/nl_kvk.py +465 -17
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/METADATA +2 -1
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/RECORD +36 -35
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +23 -17
- tests/unit_tests/arelle/test_import.py +0 -30
- tests/unit_tests/arelle/test_runtimeoptions.py +0 -13
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.19.dist-info → arelle_release-2.37.21.dist-info}/top_level.txt +0 -0
|
@@ -12,7 +12,7 @@ from arelle.XmlValidateConst import VALID
|
|
|
12
12
|
from collections.abc import Iterable
|
|
13
13
|
from typing import Any, cast, TYPE_CHECKING
|
|
14
14
|
|
|
15
|
-
from arelle import XmlUtil
|
|
15
|
+
from arelle import XmlUtil, XbrlConst
|
|
16
16
|
from arelle.ValidateXbrl import ValidateXbrl
|
|
17
17
|
from arelle.typing import TypeGetText
|
|
18
18
|
from arelle.utils.PluginHooks import ValidationHook
|
|
@@ -21,10 +21,11 @@ from arelle.utils.validate.Validation import Validation
|
|
|
21
21
|
from arelle.ValidateDuplicateFacts import getHashEquivalentFactGroups, getAspectEqualFacts
|
|
22
22
|
from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
|
|
23
23
|
from ..DisclosureSystems import DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
24
|
+
from ..LinkbaseType import LinkbaseType
|
|
24
25
|
from ..PluginValidationDataExtension import (PluginValidationDataExtension, ALLOWABLE_LANGUAGES,
|
|
25
|
-
DISALLOWED_IXT_NAMESPACES,
|
|
26
|
-
MAX_REPORT_PACKAGE_SIZE_MBS,
|
|
27
|
-
XBRLI_IDENTIFIER_SCHEMA)
|
|
26
|
+
DISALLOWED_IXT_NAMESPACES, EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES,
|
|
27
|
+
MAX_REPORT_PACKAGE_SIZE_MBS, TAXONOMY_URLS_BY_YEAR,
|
|
28
|
+
XBRLI_IDENTIFIER_PATTERN, XBRLI_IDENTIFIER_SCHEMA)
|
|
28
29
|
|
|
29
30
|
if TYPE_CHECKING:
|
|
30
31
|
from arelle.ModelXbrl import ModelXbrl
|
|
@@ -532,7 +533,7 @@ def rule_nl_kvk_3_4_1_3 (
|
|
|
532
533
|
if len(facts) > 0:
|
|
533
534
|
yield Validation.error(
|
|
534
535
|
codes='NL.NL-KVK.3.4.1.3.transformableElementIncludedInHiddenSection',
|
|
535
|
-
msg=_('The ix:hidden section should not include elements that are eligible for transformation'
|
|
536
|
+
msg=_('The ix:hidden section should not include elements that are eligible for transformation '
|
|
536
537
|
'according to the latest recommended Transformation Rules Registry.'),
|
|
537
538
|
modelObject=facts
|
|
538
539
|
)
|
|
@@ -770,7 +771,7 @@ def rule_nl_kvk_3_6_3_1(
|
|
|
770
771
|
"""
|
|
771
772
|
invalidBasenames = []
|
|
772
773
|
for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
|
|
773
|
-
filenameParts = pluginData.getFilenameParts(basename)
|
|
774
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
|
|
774
775
|
if not filenameParts:
|
|
775
776
|
continue # Filename is not formatted correctly enough to determine {base}
|
|
776
777
|
if len(filenameParts.get('base', '')) > 20:
|
|
@@ -803,7 +804,7 @@ def rule_nl_kvk_3_6_3_2(
|
|
|
803
804
|
"""
|
|
804
805
|
invalidBasenames = []
|
|
805
806
|
for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
|
|
806
|
-
filenameParts = pluginData.getFilenameParts(basename)
|
|
807
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
|
|
807
808
|
if not filenameParts:
|
|
808
809
|
invalidBasenames.append(basename)
|
|
809
810
|
if len(invalidBasenames) > 0:
|
|
@@ -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
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
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.
|
|
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
|