arelle-release 2.37.71__py3-none-any.whl → 2.38.0__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.
- arelle/BetaFeatures.py +0 -21
- arelle/Cntlr.py +7 -1
- arelle/CntlrCmdLine.py +95 -19
- arelle/CntlrWinMain.py +4 -1
- arelle/DialogFind.py +1 -1
- arelle/ModelDtsObject.py +2 -0
- arelle/ModelObject.py +16 -18
- arelle/ModelObjectFactory.py +17 -15
- arelle/ModelXbrl.py +7 -1
- arelle/PluginManager.py +1 -5
- arelle/RuntimeOptions.py +1 -0
- arelle/UrlUtil.py +11 -0
- arelle/Validate.py +3 -3
- arelle/ValidateXbrl.py +2 -1
- arelle/ValidateXbrlCalcs.py +210 -186
- arelle/WebCache.py +2 -8
- arelle/XbrlConst.py +2 -0
- arelle/XmlUtil.py +16 -21
- arelle/XmlValidate.py +4 -6
- arelle/_version.py +2 -2
- arelle/config/rosettaEntitlements.plist +8 -0
- arelle/conformance/CSVTestcaseLoader.py +1 -1
- arelle/formula/XPathContext.py +3 -3
- arelle/logging/formatters/LogFormatter.py +3 -1
- arelle/packages/report/ReportPackage.py +9 -1
- arelle/plugin/inlineXbrlDocumentSet.py +1 -3
- arelle/plugin/validate/DBA/DisclosureSystems.py +19 -1
- arelle/plugin/validate/DBA/resources/config.xml +5 -0
- arelle/plugin/validate/DBA/rules/fr.py +19 -2
- arelle/plugin/validate/DBA/rules/tc.py +2 -0
- arelle/plugin/validate/DBA/rules/th.py +6 -0
- arelle/plugin/validate/DBA/rules/tm.py +18 -5
- arelle/plugin/validate/DBA/rules/tr.py +11 -5
- arelle/plugin/validate/EDINET/ControllerPluginData.py +2 -1
- arelle/plugin/validate/EDINET/NamespaceConfig.py +50 -0
- arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +33 -78
- arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +153 -51
- arelle/plugin/validate/EDINET/rules/contexts.py +1 -1
- arelle/plugin/validate/EDINET/rules/edinet.py +163 -20
- arelle/plugin/validate/EDINET/rules/gfm.py +88 -1
- arelle/plugin/validate/EDINET/rules/upload.py +1 -1
- arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +3 -3
- arelle/plugin/validate/ESEF/ESEF_Current/DTS.py +42 -14
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +14 -3
- arelle/plugin/validate/ESEF/__init__.py +10 -5
- arelle/plugin/validate/ESEF/resources/authority-validations.json +10 -5
- arelle/plugin/validate/NL/DisclosureSystems.py +22 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +20 -0
- arelle/plugin/validate/NL/ValidationPluginExtension.py +48 -3
- arelle/plugin/validate/NL/resources/config.xml +18 -0
- arelle/plugin/validate/NL/rules/br_kvk.py +9 -54
- arelle/plugin/validate/NL/rules/fg_nl.py +7 -38
- arelle/plugin/validate/NL/rules/fr_kvk.py +7 -42
- arelle/plugin/validate/NL/rules/fr_nl.py +25 -140
- arelle/plugin/validate/NL/rules/nl_kvk.py +125 -12
- arelle/plugin/validate/ROS/rules/ros.py +3 -1
- arelle/plugin/validate/UK/__init__.py +70 -14
- arelle/utils/EntryPointDetection.py +17 -11
- arelle/utils/validate/ESEFImage.py +3 -3
- arelle/utils/validate/Validation.py +9 -0
- arelle/utils/validate/ValidationPlugin.py +14 -12
- {arelle_release-2.37.71.dist-info → arelle_release-2.38.0.dist-info}/METADATA +10 -5
- {arelle_release-2.37.71.dist-info → arelle_release-2.38.0.dist-info}/RECORD +67 -69
- {arelle_release-2.37.71.dist-info → arelle_release-2.38.0.dist-info}/licenses/LICENSE.md +0 -3
- arelle/model/CommentBase.py +0 -9
- arelle/model/ElementBase.py +0 -11
- arelle/model/PIBase.py +0 -10
- arelle/model/__init__.py +0 -15
- {arelle_release-2.37.71.dist-info → arelle_release-2.38.0.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.71.dist-info → arelle_release-2.38.0.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.71.dist-info → arelle_release-2.38.0.dist-info}/top_level.txt +0 -0
|
@@ -19,13 +19,15 @@ from arelle.XmlValidateConst import VALID
|
|
|
19
19
|
from . import lookup_namespaced_facts, errorOnForbiddenImage
|
|
20
20
|
from ..PluginValidationDataExtension import PluginValidationDataExtension
|
|
21
21
|
from ..ValidationPluginExtension import NAMESPACE_GSD
|
|
22
|
-
from ..DisclosureSystems import
|
|
22
|
+
from ..DisclosureSystems import (ARL_MULTI_TARGET_DISCLOSURE_SYSTEMS, STAND_ALONE_DISCLOSURE_SYSTEMS,
|
|
23
|
+
ALL_DISCLOSURE_SYSTEMS, ARL_DISCLOSURE_SYSTEMS)
|
|
23
24
|
|
|
24
25
|
_: TypeGetText
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
@validation(
|
|
28
29
|
hook=ValidationHook.XBRL_FINALLY,
|
|
30
|
+
disclosureSystems=ARL_DISCLOSURE_SYSTEMS
|
|
29
31
|
)
|
|
30
32
|
def rule_tr01(
|
|
31
33
|
pluginData: PluginValidationDataExtension,
|
|
@@ -178,6 +180,7 @@ def rule_tr06(
|
|
|
178
180
|
|
|
179
181
|
@validation(
|
|
180
182
|
hook=ValidationHook.XBRL_FINALLY,
|
|
183
|
+
disclosureSystems=ARL_DISCLOSURE_SYSTEMS
|
|
181
184
|
)
|
|
182
185
|
def rule_tr09(
|
|
183
186
|
pluginData: PluginValidationDataExtension,
|
|
@@ -197,7 +200,8 @@ def rule_tr09(
|
|
|
197
200
|
|
|
198
201
|
|
|
199
202
|
@validation(
|
|
200
|
-
hook=ValidationHook.XBRL_FINALLY
|
|
203
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
204
|
+
disclosureSystems=ALL_DISCLOSURE_SYSTEMS
|
|
201
205
|
)
|
|
202
206
|
def rule_tr12(
|
|
203
207
|
pluginData: PluginValidationDataExtension,
|
|
@@ -223,6 +227,7 @@ def rule_tr12(
|
|
|
223
227
|
|
|
224
228
|
@validation(
|
|
225
229
|
hook=ValidationHook.XBRL_FINALLY,
|
|
230
|
+
disclosureSystems=ARL_DISCLOSURE_SYSTEMS
|
|
226
231
|
)
|
|
227
232
|
def rule_tr11(
|
|
228
233
|
pluginData: PluginValidationDataExtension,
|
|
@@ -252,7 +257,7 @@ def rule_tr11(
|
|
|
252
257
|
|
|
253
258
|
@validation(
|
|
254
259
|
hook=ValidationHook.XBRL_FINALLY,
|
|
255
|
-
disclosureSystems=
|
|
260
|
+
disclosureSystems=ARL_MULTI_TARGET_DISCLOSURE_SYSTEMS,
|
|
256
261
|
)
|
|
257
262
|
def rule_tr15(
|
|
258
263
|
pluginData: PluginValidationDataExtension,
|
|
@@ -276,7 +281,7 @@ def rule_tr15(
|
|
|
276
281
|
|
|
277
282
|
@validation(
|
|
278
283
|
hook=ValidationHook.XBRL_FINALLY,
|
|
279
|
-
disclosureSystems=
|
|
284
|
+
disclosureSystems=ARL_MULTI_TARGET_DISCLOSURE_SYSTEMS,
|
|
280
285
|
)
|
|
281
286
|
def rule_tr16(
|
|
282
287
|
pluginData: PluginValidationDataExtension,
|
|
@@ -301,7 +306,7 @@ def rule_tr16(
|
|
|
301
306
|
|
|
302
307
|
@validation(
|
|
303
308
|
hook=ValidationHook.XBRL_FINALLY,
|
|
304
|
-
disclosureSystems=
|
|
309
|
+
disclosureSystems=ARL_MULTI_TARGET_DISCLOSURE_SYSTEMS,
|
|
305
310
|
)
|
|
306
311
|
def rule_tr17(
|
|
307
312
|
pluginData: PluginValidationDataExtension,
|
|
@@ -342,6 +347,7 @@ def rule_tr17(
|
|
|
342
347
|
|
|
343
348
|
@validation(
|
|
344
349
|
hook=ValidationHook.XBRL_FINALLY,
|
|
350
|
+
disclosureSystems=ARL_DISCLOSURE_SYSTEMS
|
|
345
351
|
)
|
|
346
352
|
def rule_tr19(
|
|
347
353
|
pluginData: PluginValidationDataExtension,
|
|
@@ -21,6 +21,7 @@ from . import Constants
|
|
|
21
21
|
from .CoverItemRequirements import CoverItemRequirements
|
|
22
22
|
from .DeiRequirements import DeiRequirements, DEI_LOCAL_NAMES
|
|
23
23
|
from .FilingFormat import DocumentType, FilingFormat
|
|
24
|
+
from .NamespaceConfig import NamespaceConfig
|
|
24
25
|
from .ReportFolderType import ReportFolderType
|
|
25
26
|
from .TableOfContentsBuilder import TableOfContentsBuilder
|
|
26
27
|
from .UploadContents import UploadContents, UploadPathInfo
|
|
@@ -42,13 +43,13 @@ class ControllerPluginData(PluginData):
|
|
|
42
43
|
|
|
43
44
|
def __init__(self, name: str):
|
|
44
45
|
super().__init__(name)
|
|
46
|
+
self.namespaces = NamespaceConfig()
|
|
45
47
|
self._deiValues = {}
|
|
46
48
|
self._loadedModelXbrls = []
|
|
47
49
|
self._manifestInstancesById = {}
|
|
48
50
|
self._tocBuilder = TableOfContentsBuilder()
|
|
49
51
|
self._usedFilepaths = set()
|
|
50
52
|
self._uploadContents = None
|
|
51
|
-
self.jpcrpNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp/2024-11-01/jpcrp_cor'
|
|
52
53
|
|
|
53
54
|
def __hash__(self) -> int:
|
|
54
55
|
return id(self)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
See COPYRIGHT.md for copyright information.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NamespaceConfig:
|
|
9
|
+
def __init__(self) -> None:
|
|
10
|
+
self.jpcrpEsr = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp-esr/2024-11-01/jpcrp-esr_cor"
|
|
11
|
+
self.jpcrp = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp/2024-11-01/jpcrp_cor"
|
|
12
|
+
self.jpcrpSbr = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp-sbr/2024-11-01/jpcrp-sbr_cor"
|
|
13
|
+
self.jpctl = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpctl/2024-11-01/jpctl_cor"
|
|
14
|
+
self.jpdei = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/jpdei_cor"
|
|
15
|
+
self.jpigp = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpigp/2024-11-01/jpigp_cor"
|
|
16
|
+
self.jplvh = "http://disclosure.edinet-fsa.go.jp/taxonomy/jplvh/2024-11-01/jplvh_cor"
|
|
17
|
+
self.jppfs = "http://disclosure.edinet-fsa.go.jp/taxonomy/jppfs/2024-11-01/jppfs_cor"
|
|
18
|
+
self.jpspsEsr = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpsps-esr/2024-11-01/jpsps-esr_cor"
|
|
19
|
+
self.jpspsSbr = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpsps-sbr/2024-11-01/jpsps-sbr_cor"
|
|
20
|
+
self.jpsps = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpsps/2024-11-01/jpsps_cor"
|
|
21
|
+
self.jptoi = "http://disclosure.edinet-fsa.go.jp/taxonomy/jptoi/2024-11-01/jptoi_cor"
|
|
22
|
+
self.jptooPst = "http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-pst/2024-11-01/jptoo-pst_cor"
|
|
23
|
+
self.jptooToa = "http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-toa/2024-11-01/jptoo-toa_cor"
|
|
24
|
+
self.jptooTon = "http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-ton/2024-11-01/jptoo-ton_cor"
|
|
25
|
+
self.jptooTor = "http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-tor/2024-11-01/jptoo-tor_cor"
|
|
26
|
+
self.jptooWto = "http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-wto/2024-11-01/jptoo-wto_cor"
|
|
27
|
+
|
|
28
|
+
self._namespaceMap = {
|
|
29
|
+
"jpcrp-esr_cor": self.jpcrpEsr,
|
|
30
|
+
"jpcrp-sbr_cor": self.jpcrpSbr,
|
|
31
|
+
"jpcrp_cor": self.jpcrp,
|
|
32
|
+
"jpctl_cor": self.jpctl,
|
|
33
|
+
"jpdei_cor": self.jpdei,
|
|
34
|
+
"jpigp_cor": self.jpigp,
|
|
35
|
+
"jplvh_cor": self.jplvh,
|
|
36
|
+
"jppfs_cor": self.jppfs,
|
|
37
|
+
"jpsps_cor": self.jpsps,
|
|
38
|
+
"jpsps-esr_cor": self.jpspsEsr,
|
|
39
|
+
"jpsps-sbr_cor": self.jpspsSbr,
|
|
40
|
+
"jptoi_cor": self.jptoi,
|
|
41
|
+
"jptoo-pst_cor": self.jptooPst,
|
|
42
|
+
"jptoo-toa_cor": self.jptooToa,
|
|
43
|
+
"jptoo-ton_cor": self.jptooTon,
|
|
44
|
+
"jptoo-tor_cor": self.jptooTor,
|
|
45
|
+
"jptoo-wto_cor": self.jptooWto,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
def get(self, prefix: str) -> str | None:
|
|
49
|
+
"""get namespace URI for prefix"""
|
|
50
|
+
return self._namespaceMap.get(prefix)
|
|
@@ -4,6 +4,7 @@ See COPYRIGHT.md for copyright information.
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
from collections import defaultdict
|
|
7
|
+
from collections.abc import Callable, Hashable, Iterable
|
|
7
8
|
from dataclasses import dataclass
|
|
8
9
|
from decimal import Decimal
|
|
9
10
|
from functools import lru_cache
|
|
@@ -11,10 +12,9 @@ from pathlib import Path
|
|
|
11
12
|
|
|
12
13
|
from lxml.etree import DTD, XML
|
|
13
14
|
from operator import attrgetter
|
|
14
|
-
from typing import
|
|
15
|
+
from typing import cast
|
|
15
16
|
|
|
16
17
|
import os
|
|
17
|
-
import regex
|
|
18
18
|
|
|
19
19
|
from arelle import XbrlConst
|
|
20
20
|
from arelle.LinkbaseType import LinkbaseType
|
|
@@ -33,11 +33,11 @@ from arelle.typing import TypeGetText
|
|
|
33
33
|
from arelle.utils.PluginData import PluginData
|
|
34
34
|
from .Constants import xhtmlDtdExtension, PROHIBITED_HTML_TAGS, PROHIBITED_HTML_ATTRIBUTES
|
|
35
35
|
from .ControllerPluginData import ControllerPluginData
|
|
36
|
-
from .CoverItemRequirements import CoverItemRequirements
|
|
37
36
|
from .DeiRequirements import DeiRequirements, DEI_LOCAL_NAMES
|
|
38
37
|
from .FilingFormat import FilingFormat, FILING_FORMATS, DocumentType, Ordinance
|
|
39
38
|
from .FormType import FormType
|
|
40
39
|
from .ManifestInstance import ManifestInstance
|
|
40
|
+
from .NamespaceConfig import NamespaceConfig
|
|
41
41
|
from .ReportFolderType import HTML_EXTENSIONS
|
|
42
42
|
from .Statement import Statement, STATEMENTS, BalanceSheet, StatementInstance, StatementType
|
|
43
43
|
from .UploadContents import UploadContents, UploadPathInfo
|
|
@@ -71,34 +71,21 @@ class UriReference:
|
|
|
71
71
|
|
|
72
72
|
@dataclass
|
|
73
73
|
class PluginValidationDataExtension(PluginData):
|
|
74
|
-
|
|
75
|
-
jpcrpEsrNamespace: str
|
|
76
|
-
jpcrpNamespace: str
|
|
77
|
-
jpctlNamespace: str
|
|
78
|
-
jpcrpSbrNamespace: str
|
|
79
|
-
jpdeiNamespace: str
|
|
80
|
-
jpigpNamespace: str
|
|
81
|
-
jplvhNamespace: str
|
|
82
|
-
jppfsNamespace: str
|
|
83
|
-
jpspsEsrNamespace: str
|
|
84
|
-
jpspsSbrNamespace: str
|
|
85
|
-
jpspsNamespace: str
|
|
86
|
-
jptoiNamespace: str
|
|
87
|
-
jptooPstNamespace: str
|
|
88
|
-
jptooToaNamespace: str
|
|
89
|
-
jptooTonNamespace: str
|
|
90
|
-
jptooTorNamespace: str
|
|
91
|
-
jptooWtoNamespace: str
|
|
74
|
+
namespaces: NamespaceConfig
|
|
92
75
|
|
|
93
76
|
accountingStandardsDeiQn: QName
|
|
94
77
|
assetsIfrsQn: QName
|
|
95
78
|
categoriesOfDirectorsAndOtherOfficersAxisQn: QName
|
|
96
79
|
consolidatedOrNonConsolidatedAxisQn: QName
|
|
80
|
+
corporateGovernanceCompanyWithAuditAndSupervisoryCommitteeTextBlockQn: QName
|
|
81
|
+
corporateGovernanceCompanyWithCorporateAuditorsTextBlockQn: QName
|
|
82
|
+
corporateGovernanceCompanyWithNominatingAndOtherCommitteesTextBlockQn: QName
|
|
97
83
|
documentTypeDeiQn: QName
|
|
98
84
|
executiveOfficersMemberQn: QName
|
|
99
85
|
jpcrpEsrFilingDateCoverPageQn: QName
|
|
100
86
|
jpcrpFilingDateCoverPageQn: QName
|
|
101
87
|
jpspsFilingDateCoverPageQn: QName
|
|
88
|
+
issuedSharesTotalNumberOfSharesEtcQn: QName
|
|
102
89
|
nonConsolidatedMemberQn: QName
|
|
103
90
|
ratioOfFemaleDirectorsAndOtherOfficersQn: QName
|
|
104
91
|
|
|
@@ -107,73 +94,39 @@ class PluginValidationDataExtension(PluginData):
|
|
|
107
94
|
deiItems: tuple[QName, ...]
|
|
108
95
|
deiRequirementsPath: Path
|
|
109
96
|
|
|
110
|
-
_namespaceMap: dict[str, str]
|
|
111
97
|
_uriReferences: list[UriReference]
|
|
112
98
|
|
|
113
99
|
def __init__(self, name: str, validateXbrl: ValidateXbrl):
|
|
114
100
|
super().__init__(name)
|
|
115
101
|
|
|
116
|
-
|
|
117
|
-
self.jpcrpEsrNamespace = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp-esr/2024-11-01/jpcrp-esr_cor"
|
|
118
|
-
self.jpcrpNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp/2024-11-01/jpcrp_cor'
|
|
119
|
-
self.jpcrpSbrNamespace = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpcrp-sbr/2024-11-01/jpcrp-sbr_cor"
|
|
120
|
-
self.jpctlNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jpctl/2024-11-01/jpctl_cor'
|
|
121
|
-
self.jpdeiNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/jpdei_cor'
|
|
122
|
-
self.jpigpNamespace = "http://disclosure.edinet-fsa.go.jp/taxonomy/jpigp/2024-11-01/jpigp_cor"
|
|
123
|
-
self.jplvhNamespace = "http://disclosure.edinet-fsa.go.jp/taxonomy/jplvh/2024-11-01/jplvh_cor"
|
|
124
|
-
self.jppfsNamespace = "http://disclosure.edinet-fsa.go.jp/taxonomy/jppfs/2024-11-01/jppfs_cor"
|
|
125
|
-
self.jpspsEsrNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jpsps-esr/2024-11-01/jpsps-esr_cor'
|
|
126
|
-
self.jpspsSbrNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jpsps-sbr/2024-11-01/jpsps-sbr_cor'
|
|
127
|
-
self.jpspsNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jpsps/2024-11-01/jpsps_cor'
|
|
128
|
-
self.jptoiNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jptoi/2024-11-01/jptoi_cor'
|
|
129
|
-
self.jptooPstNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-pst/2024-11-01/jptoo-pst_cor'
|
|
130
|
-
self.jptooToaNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-toa/2024-11-01/jptoo-toa_cor'
|
|
131
|
-
self.jptooTonNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-ton/2024-11-01/jptoo-ton_cor'
|
|
132
|
-
self.jptooTorNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-tor/2024-11-01/jptoo-tor_cor'
|
|
133
|
-
self.jptooWtoNamespace = 'http://disclosure.edinet-fsa.go.jp/taxonomy/jptoo-wto/2024-11-01/jptoo-wto_cor'
|
|
134
|
-
self._namespaceMap = {
|
|
135
|
-
"jpcrp-esr_cor": self.jpcrpEsrNamespace,
|
|
136
|
-
"jpcrp-sbr_cor": self.jpcrpSbrNamespace,
|
|
137
|
-
"jpcrp_cor": self.jpcrpNamespace,
|
|
138
|
-
"jpctl_cor": self.jpctlNamespace,
|
|
139
|
-
"jpdei_cor": self.jpdeiNamespace,
|
|
140
|
-
"jpigp_cor": self.jpigpNamespace,
|
|
141
|
-
"jplvh_cor": self.jplvhNamespace,
|
|
142
|
-
"jppfs_cor": self.jppfsNamespace,
|
|
143
|
-
"jpsps_cor": self.jpspsNamespace,
|
|
144
|
-
"jpsps-esr_cor": self.jpspsEsrNamespace,
|
|
145
|
-
"jpsps-sbr_cor": self.jpspsSbrNamespace,
|
|
146
|
-
"jptoi_cor": self.jptoiNamespace,
|
|
147
|
-
"jptoo-pst_cor": self.jptooPstNamespace,
|
|
148
|
-
"jptoo-toa_cor": self.jptooToaNamespace,
|
|
149
|
-
"jptoo-ton_cor": self.jptooTonNamespace,
|
|
150
|
-
"jptoo-tor_cor": self.jptooPstNamespace,
|
|
151
|
-
"jptoo-wto_cor": self.jptooWtoNamespace,
|
|
152
|
-
}
|
|
102
|
+
self.namespaces = NamespaceConfig()
|
|
153
103
|
|
|
154
104
|
# QNames
|
|
155
|
-
self.accountingStandardsDeiQn = qname(self.
|
|
156
|
-
self.assetsIfrsQn = qname(self.
|
|
157
|
-
self.
|
|
158
|
-
self.
|
|
159
|
-
self.
|
|
160
|
-
self.
|
|
161
|
-
self.
|
|
162
|
-
self.
|
|
163
|
-
self.
|
|
164
|
-
self.
|
|
165
|
-
self.
|
|
166
|
-
self.
|
|
105
|
+
self.accountingStandardsDeiQn = qname(self.namespaces.jpdei, 'AccountingStandardsDEI')
|
|
106
|
+
self.assetsIfrsQn = qname(self.namespaces.jpigp, 'AssetsIFRS')
|
|
107
|
+
self.categoriesOfDirectorsAndOtherOfficersAxisQn = qname(self.namespaces.jpcrp, 'CategoriesOfDirectorsAndOtherOfficersAxis')
|
|
108
|
+
self.consolidatedOrNonConsolidatedAxisQn = qname(self.namespaces.jppfs, 'ConsolidatedOrNonConsolidatedAxis')
|
|
109
|
+
self.corporateGovernanceCompanyWithAuditAndSupervisoryCommitteeTextBlockQn = qname(self.namespaces.jpcrp, 'CorporateGovernanceCompanyWithAuditAndSupervisoryCommitteeTextBlock')
|
|
110
|
+
self.corporateGovernanceCompanyWithCorporateAuditorsTextBlockQn = qname(self.namespaces.jpcrp, 'CorporateGovernanceCompanyWithCorporateAuditorsTextBlock')
|
|
111
|
+
self.corporateGovernanceCompanyWithNominatingAndOtherCommitteesTextBlockQn = qname(self.namespaces.jpcrp, 'CorporateGovernanceCompanyWithNominatingAndOtherCommitteesTextBlock')
|
|
112
|
+
self.documentTypeDeiQn = qname(self.namespaces.jpdei, 'DocumentTypeDEI')
|
|
113
|
+
self.executiveOfficersMemberQn = qname(self.namespaces.jpcrp, 'ExecutiveOfficersMember')
|
|
114
|
+
self.issuedSharesTotalNumberOfSharesEtcQn = qname(self.namespaces.jpcrp, 'IssuedSharesTotalNumberOfSharesEtcTextBlock')
|
|
115
|
+
self.jpcrpEsrFilingDateCoverPageQn = qname(self.namespaces.jpcrpEsr, 'FilingDateCoverPage')
|
|
116
|
+
self.jpcrpFilingDateCoverPageQn = qname(self.namespaces.jpcrp, 'FilingDateCoverPage')
|
|
117
|
+
self.jpspsFilingDateCoverPageQn = qname(self.namespaces.jpsps, 'FilingDateCoverPage')
|
|
118
|
+
self.nonConsolidatedMemberQn = qname(self.namespaces.jppfs, "NonConsolidatedMember")
|
|
119
|
+
self.ratioOfFemaleDirectorsAndOtherOfficersQn = qname(self.namespaces.jpcrp, "RatioOfFemaleDirectorsAndOtherOfficers")
|
|
167
120
|
|
|
168
121
|
self.coverItemRequirementsPath = Path(__file__).parent / "resources" / "cover-item-requirements.json"
|
|
169
122
|
self.coverPageTitleQns = (
|
|
170
|
-
qname(self.
|
|
171
|
-
qname(self.
|
|
172
|
-
qname(self.
|
|
173
|
-
qname(self.
|
|
123
|
+
qname(self.namespaces.jpsps, "DocumentTitleAnnualSecuritiesReportCoverPage"),
|
|
124
|
+
qname(self.namespaces.jpcrp, "DocumentTitleCoverPage"),
|
|
125
|
+
qname(self.namespaces.jpcrpEsr, "DocumentTitleCoverPage"),
|
|
126
|
+
qname(self.namespaces.jpsps, "DocumentTitleCoverPage"),
|
|
174
127
|
)
|
|
175
128
|
self.deiItems = tuple(
|
|
176
|
-
qname(self.
|
|
129
|
+
qname(self.namespaces.jpdei, localName)
|
|
177
130
|
for localName in DEI_LOCAL_NAMES
|
|
178
131
|
)
|
|
179
132
|
self.deiRequirementsPath = Path(__file__).parent / "resources" / "dei-requirements.csv"
|
|
@@ -255,7 +208,9 @@ class PluginValidationDataExtension(PluginData):
|
|
|
255
208
|
tocBuilder.addDocument(modelDocument)
|
|
256
209
|
|
|
257
210
|
def qname(self, prefix: str, localName: str) -> QName:
|
|
258
|
-
|
|
211
|
+
ns = self.namespaces.get(prefix)
|
|
212
|
+
assert ns is not None, f"Unknown namespace prefix: {prefix}"
|
|
213
|
+
return qname(ns, localName)
|
|
259
214
|
|
|
260
215
|
@lru_cache(1)
|
|
261
216
|
def isCorporateForm(self, modelXbrl: ModelXbrl) -> bool:
|
|
@@ -265,7 +220,7 @@ class PluginValidationDataExtension(PluginData):
|
|
|
265
220
|
return formType.isCorporateForm
|
|
266
221
|
|
|
267
222
|
def isCorporateReport(self, modelXbrl: ModelXbrl) -> bool:
|
|
268
|
-
return self.
|
|
223
|
+
return self.namespaces.jpcrp in modelXbrl.namespaceDocs
|
|
269
224
|
|
|
270
225
|
def isExtensionUri(self, uri: str, modelXbrl: ModelXbrl) -> bool:
|
|
271
226
|
if uri.startswith(modelXbrl.uriDir):
|
|
@@ -7,7 +7,9 @@ from typing import Iterable
|
|
|
7
7
|
|
|
8
8
|
from collections import defaultdict
|
|
9
9
|
from jaconv import jaconv
|
|
10
|
+
from lxml.etree import _Element
|
|
10
11
|
|
|
12
|
+
from arelle import XbrlConst
|
|
11
13
|
from arelle.ModelDocument import ModelDocument
|
|
12
14
|
from arelle.ModelObject import ModelObject
|
|
13
15
|
from arelle.typing import TypeGetText
|
|
@@ -97,6 +99,13 @@ TOC_NUMBER_SETS = {
|
|
|
97
99
|
SHALLOWEST_LEVEL = min(TOC_NUMBER_SETS.keys())
|
|
98
100
|
DEEPEST_LEVEL = max(TOC_NUMBER_SETS.keys())
|
|
99
101
|
|
|
102
|
+
PROHIBITED_BETWEEN_TAGS = frozenset({
|
|
103
|
+
XbrlConst.qnXhtmlDel.localName,
|
|
104
|
+
XbrlConst.qnXhtmlImg.localName,
|
|
105
|
+
XbrlConst.qnXhtmlDel.clarkNotation,
|
|
106
|
+
XbrlConst.qnXhtmlImg.clarkNotation,
|
|
107
|
+
})
|
|
108
|
+
|
|
100
109
|
|
|
101
110
|
class TableOfContentsBuilder:
|
|
102
111
|
_currentDocument: ModelDocument | None
|
|
@@ -230,44 +239,151 @@ class TableOfContentsBuilder:
|
|
|
230
239
|
# First or new document, open document.
|
|
231
240
|
if self._currentDocument is None:
|
|
232
241
|
self._openDocument(elt.document)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
242
|
+
|
|
243
|
+
number, label, tail, eltsInLabel, eltsBetweenNumAndLabel = self._getTextParts(elt)
|
|
244
|
+
|
|
245
|
+
textValue = ''.join(elt.textNodes())
|
|
246
|
+
if (
|
|
247
|
+
(label is None and ('【' in textValue or '】' in textValue)) or
|
|
248
|
+
(tail is not None and ('【' in tail or '】' in tail))
|
|
249
|
+
):
|
|
250
|
+
self._validations.append(Validation.error(
|
|
251
|
+
codes='EDINET.EC2011E',
|
|
252
|
+
msg=_("\"【\" or \"】\" is used in the text. "
|
|
253
|
+
"File name: '%(path)s' (line %(line)s). "
|
|
254
|
+
"Corner brackets (【】) cannot be used in the main text "
|
|
255
|
+
"except for the table of contents. Please delete the "
|
|
256
|
+
"corner brackets (【】) in the relevant file."),
|
|
257
|
+
path=elt.document.basename,
|
|
258
|
+
line=elt.sourceline,
|
|
259
|
+
modelObject=elt,
|
|
260
|
+
))
|
|
261
|
+
|
|
262
|
+
if label is None:
|
|
263
|
+
return
|
|
264
|
+
|
|
265
|
+
if len(eltsInLabel) > 0:
|
|
266
|
+
self._validations.append(Validation.error(
|
|
267
|
+
codes='EDINET.EC2008E',
|
|
268
|
+
msg=_("The table of contents label contains HTML tags. "
|
|
269
|
+
"File name: '%(path)s' (line %(line)s). "
|
|
270
|
+
"HTML tags are not allowed in table of contents labels. "
|
|
271
|
+
"Please remove the HTML tags from the relevant file."),
|
|
272
|
+
path=elt.document.basename,
|
|
273
|
+
line=elt.sourceline,
|
|
274
|
+
modelObject=elt,
|
|
275
|
+
))
|
|
276
|
+
|
|
277
|
+
if any(
|
|
278
|
+
e.tag in PROHIBITED_BETWEEN_TAGS
|
|
279
|
+
for e in eltsBetweenNumAndLabel
|
|
280
|
+
):
|
|
281
|
+
self._validations.append(Validation.error(
|
|
282
|
+
codes='EDINET.EC2009E',
|
|
283
|
+
msg=_("An invalid tag is used between the table of contents number "
|
|
284
|
+
"and the table of contents item. "
|
|
285
|
+
"File name: '%(path)s' (line %(line)s). "
|
|
286
|
+
"Please delete the tag (\"del\" or \"img\") used between the "
|
|
287
|
+
"table of contents number and the table of contents item of "
|
|
288
|
+
"the relevant file."),
|
|
289
|
+
path=elt.document.basename,
|
|
290
|
+
line=elt.sourceline,
|
|
291
|
+
modelObject=elt,
|
|
292
|
+
))
|
|
293
|
+
|
|
294
|
+
if '【' in label[1:]:
|
|
295
|
+
self._validations.append(Validation.error(
|
|
296
|
+
codes='EDINET.EC2004E',
|
|
297
|
+
msg=_("The opening bracket (【) is repeated. "
|
|
298
|
+
"File name: '%(path)s' (line %(line)s). "
|
|
299
|
+
"When viewed in a browser, it is not possible to display "
|
|
300
|
+
"more than one table of contents item on one line. Please "
|
|
301
|
+
"delete the brackets (【) in the relevant file."),
|
|
302
|
+
path=elt.document.basename,
|
|
303
|
+
line=elt.sourceline,
|
|
304
|
+
modelObject=elt,
|
|
305
|
+
))
|
|
306
|
+
|
|
307
|
+
if '】' not in label:
|
|
308
|
+
# EDINET.EC2007E: The table of contents entries must be enclosed in square brackets (】).
|
|
309
|
+
self._validations.append(Validation.error(
|
|
310
|
+
codes='EDINET.EC2007E',
|
|
311
|
+
msg=_("The table of contents entry is not closed with '】'. "
|
|
312
|
+
"File name: '%(path)s' (line %(line)s). "
|
|
313
|
+
"Add a closing bracket (】) to match the open bracket (【) "
|
|
314
|
+
"in the table of contents entry for the file in question."),
|
|
315
|
+
path=elt.document.basename,
|
|
316
|
+
line=elt.sourceline,
|
|
317
|
+
modelObject=elt,
|
|
318
|
+
))
|
|
319
|
+
|
|
320
|
+
self._tocSequence.append((number, label, elt))
|
|
321
|
+
self._tocEntryCount += 1
|
|
322
|
+
|
|
323
|
+
def _getTextParts(
|
|
324
|
+
self,
|
|
325
|
+
elt: ModelObject
|
|
326
|
+
) -> tuple[str, str | None, str | None, list[ModelObject], list[ModelObject]]:
|
|
327
|
+
"""
|
|
328
|
+
Determines the TOC number, label, and tail of a given element (if set correctly)
|
|
329
|
+
based on the text nodes directly beneath the element.
|
|
330
|
+
Also captures misplaced elements in provided lists for error handling.
|
|
331
|
+
"""
|
|
332
|
+
eltsInLabel = []
|
|
333
|
+
eltsBetweenNumAndLabel = []
|
|
334
|
+
textParts = [(None, elt.text)] + [
|
|
335
|
+
(child, child.tail)
|
|
336
|
+
for child in elt.iterchildren()
|
|
337
|
+
]
|
|
338
|
+
|
|
339
|
+
number = ''
|
|
340
|
+
label = None
|
|
341
|
+
tail = None
|
|
342
|
+
while len(textParts) > 0:
|
|
343
|
+
textElt, text = textParts.pop(0)
|
|
344
|
+
|
|
345
|
+
# If we're iterating over an element, check if it's misplaced
|
|
346
|
+
if textElt is not None:
|
|
347
|
+
if number and label is None:
|
|
348
|
+
eltsBetweenNumAndLabel.append(textElt)
|
|
349
|
+
if label is not None and '】' not in label and tail is None:
|
|
350
|
+
eltsInLabel.append(textElt)
|
|
351
|
+
|
|
352
|
+
# If no text, move on
|
|
353
|
+
if not text:
|
|
354
|
+
continue
|
|
355
|
+
|
|
356
|
+
if label is None:
|
|
357
|
+
# We're building the number
|
|
358
|
+
start, sep, end = text.partition('【')
|
|
359
|
+
if sep:
|
|
360
|
+
number += start
|
|
361
|
+
label = sep # Start the label
|
|
362
|
+
# Process the remainder of this text node next
|
|
363
|
+
textParts.insert(0, (None, end))
|
|
364
|
+
else:
|
|
365
|
+
number += start
|
|
366
|
+
elif tail is None:
|
|
367
|
+
# We're building the label
|
|
368
|
+
start, sep, end = text.partition('】')
|
|
369
|
+
if sep:
|
|
370
|
+
label += start + sep
|
|
371
|
+
tail = '' # Start the tail
|
|
372
|
+
# Process the remainder of this text node next
|
|
373
|
+
textParts.insert(0, (None, end))
|
|
374
|
+
else:
|
|
375
|
+
label += start
|
|
259
376
|
else:
|
|
260
|
-
#
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
))
|
|
377
|
+
# We're building the tail
|
|
378
|
+
tail += text
|
|
379
|
+
|
|
380
|
+
return (
|
|
381
|
+
number.strip(),
|
|
382
|
+
label.strip() if label else label,
|
|
383
|
+
tail.strip() if tail else tail,
|
|
384
|
+
eltsInLabel,
|
|
385
|
+
eltsBetweenNumAndLabel,
|
|
386
|
+
)
|
|
271
387
|
|
|
272
388
|
def _isFloating(self) -> bool:
|
|
273
389
|
return self._floatingLevel is not None or self._currentLevel >= DEEPEST_LEVEL
|
|
@@ -459,7 +575,6 @@ class TableOfContentsBuilder:
|
|
|
459
575
|
if not self._isFloating():
|
|
460
576
|
# EDINET.EC2003E: The table of contents must be no longer than 384 bytes
|
|
461
577
|
# (equivalent to 128 full-width characters).
|
|
462
|
-
b = label.encode('utf-8')
|
|
463
578
|
if len(label.encode('utf-8')) > 384:
|
|
464
579
|
yield Validation.error(
|
|
465
580
|
codes='EDINET.EC2003E',
|
|
@@ -473,19 +588,6 @@ class TableOfContentsBuilder:
|
|
|
473
588
|
modelObject=elt,
|
|
474
589
|
)
|
|
475
590
|
|
|
476
|
-
# EDINET.EC2008E: Table of contents entries must not contain HTML tags.
|
|
477
|
-
if len(elt) > 0:
|
|
478
|
-
yield Validation.error(
|
|
479
|
-
codes='EDINET.EC2008E',
|
|
480
|
-
msg=_("The table of contents contains HTML tags. "
|
|
481
|
-
"File name: '%(path)s' (line %(line)s). "
|
|
482
|
-
"HTML tags are not allowed in table of contents entries. "
|
|
483
|
-
"Please remove the HTML tags from the relevant file."),
|
|
484
|
-
path=elt.document.basename,
|
|
485
|
-
line=elt.sourceline,
|
|
486
|
-
modelObject=elt,
|
|
487
|
-
)
|
|
488
|
-
|
|
489
591
|
# Uncomment for debugging output of TOC structure.
|
|
490
592
|
# print(
|
|
491
593
|
# f'{" " if self._floatingLevel is not None else "|"}\t' * (self._currentLevel - 1) +
|
|
@@ -84,7 +84,7 @@ def rule_EC8012W(
|
|
|
84
84
|
EDINET.EC8012W: If a main financial statement element is present, a calculation linkbase file must be present.
|
|
85
85
|
"""
|
|
86
86
|
if not any(
|
|
87
|
-
fact.qname.namespaceURI == pluginData.
|
|
87
|
+
fact.qname.namespaceURI == pluginData.namespaces.jppfs
|
|
88
88
|
for fact in val.modelXbrl.facts
|
|
89
89
|
):
|
|
90
90
|
return
|