arelle-release 2.37.61__py3-none-any.whl → 2.37.63__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 (38) hide show
  1. arelle/DisclosureSystem.py +5 -0
  2. arelle/FileSource.py +4 -1
  3. arelle/HtmlUtil.py +5 -4
  4. arelle/ValidateDuplicateFacts.py +2 -0
  5. arelle/ValidateXbrl.py +3 -1
  6. arelle/ValidateXbrlDTS.py +1 -1
  7. arelle/XbrlConst.py +18 -0
  8. arelle/_version.py +2 -2
  9. arelle/api/Session.py +6 -0
  10. arelle/config/disclosuresystems.xsd +1 -0
  11. arelle/plugin/validate/EDINET/Constants.py +95 -0
  12. arelle/plugin/validate/EDINET/ControllerPluginData.py +14 -3
  13. arelle/plugin/validate/EDINET/CoverItemRequirements.py +42 -0
  14. arelle/plugin/validate/EDINET/{CoverPageRequirements.py → DeiRequirements.py} +24 -24
  15. arelle/plugin/validate/EDINET/PluginValidationDataExtension.py +209 -43
  16. arelle/plugin/validate/EDINET/ReportFolderType.py +61 -0
  17. arelle/plugin/validate/EDINET/TableOfContentsBuilder.py +493 -0
  18. arelle/plugin/validate/EDINET/__init__.py +13 -2
  19. arelle/plugin/validate/EDINET/resources/config.xml +6 -0
  20. arelle/plugin/validate/EDINET/resources/cover-item-requirements.json +793 -0
  21. arelle/plugin/validate/EDINET/resources/edinet-taxonomies.xml +2 -0
  22. arelle/plugin/validate/EDINET/rules/contexts.py +61 -1
  23. arelle/plugin/validate/EDINET/rules/edinet.py +278 -4
  24. arelle/plugin/validate/EDINET/rules/frta.py +122 -3
  25. arelle/plugin/validate/EDINET/rules/gfm.py +681 -5
  26. arelle/plugin/validate/EDINET/rules/upload.py +231 -192
  27. arelle/plugin/validate/NL/PluginValidationDataExtension.py +6 -8
  28. arelle/plugin/validate/NL/ValidationPluginExtension.py +0 -3
  29. arelle/plugin/validate/NL/rules/nl_kvk.py +1 -2
  30. arelle/utils/validate/ValidationPlugin.py +1 -1
  31. arelle/utils/validate/ValidationUtil.py +1 -2
  32. {arelle_release-2.37.61.dist-info → arelle_release-2.37.63.dist-info}/METADATA +2 -1
  33. {arelle_release-2.37.61.dist-info → arelle_release-2.37.63.dist-info}/RECORD +38 -35
  34. /arelle/plugin/validate/EDINET/resources/{cover-page-requirements.csv → dei-requirements.csv} +0 -0
  35. {arelle_release-2.37.61.dist-info → arelle_release-2.37.63.dist-info}/WHEEL +0 -0
  36. {arelle_release-2.37.61.dist-info → arelle_release-2.37.63.dist-info}/entry_points.txt +0 -0
  37. {arelle_release-2.37.61.dist-info → arelle_release-2.37.63.dist-info}/licenses/LICENSE.md +0 -0
  38. {arelle_release-2.37.61.dist-info → arelle_release-2.37.63.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,493 @@
1
+ """
2
+ See COPYRIGHT.md for copyright information.
3
+ """
4
+ from __future__ import annotations
5
+
6
+ from typing import Iterable
7
+
8
+ from collections import defaultdict
9
+ from jaconv import jaconv
10
+
11
+ from arelle.ModelDocument import ModelDocument
12
+ from arelle.ModelObject import ModelObject
13
+ from arelle.typing import TypeGetText
14
+ from arelle.utils.validate.Validation import Validation
15
+
16
+ _: TypeGetText
17
+
18
+ # Table of content number sets per EDINET documentation:
19
+ # Figure "3-4-5 設定可能な目次番号の一覧" in "File Specification for EDINET Filing"
20
+ # https://disclosure2dl.edinet-fsa.go.jp/guide/static/disclosure/download/ESE140104.pdf
21
+ TOC_DIGITS = [
22
+ '一',
23
+ '二',
24
+ '三',
25
+ '四',
26
+ '五',
27
+ '六',
28
+ '七',
29
+ '八',
30
+ '九',
31
+ '十',
32
+ ]
33
+ FULL_WIDTH_DIGIT_MAP = {
34
+ str(d): jaconv.h2z(str(d), kana=True, ascii=True, digit=True)
35
+ for d in range(0, 10)
36
+ }
37
+ KATAKANA_GOJUON_SEQUENCE = [
38
+ # a-column
39
+ 'ア', 'イ', 'ウ', 'エ', 'オ',
40
+ # k-column
41
+ 'カ', 'キ', 'ク', 'ケ', 'コ',
42
+ # s-column
43
+ 'サ', 'シ', 'ス', 'セ', 'ソ',
44
+ # t-column
45
+ 'タ', 'チ', 'ツ', 'テ', 'ト',
46
+ # n-column
47
+ 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ',
48
+ # h-column
49
+ 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
50
+ # m-column
51
+ 'マ', 'ミ', 'ム', 'メ', 'モ',
52
+ # y-column
53
+ 'ヤ', 'ユ', 'ヨ',
54
+ # r-column
55
+ 'ラ', 'リ', 'ル', 'レ', 'ロ',
56
+ # w-column
57
+ 'ワ', 'ヲ',
58
+ # n-row
59
+ 'ン'
60
+ ]
61
+ TOC_NUMBER_SETS = {
62
+ 1: {
63
+ '第一部': [f'第{d}部' for d in TOC_DIGITS] + [f'第十{d}部' for d in TOC_DIGITS[:-1]] + ['第二十部']
64
+ },
65
+ 2: {
66
+ '第1': [
67
+ '第' + ''.join(FULL_WIDTH_DIGIT_MAP[ddd] for ddd in dd)
68
+ for dd in [
69
+ str(d) for d in range(1, 61)
70
+ ]
71
+ ],
72
+ },
73
+ 3: {
74
+ '1': [
75
+ ''.join(FULL_WIDTH_DIGIT_MAP[ddd] for ddd in dd)
76
+ for dd in [
77
+ str(d) for d in range(1, 61)
78
+ ]
79
+ ],
80
+ },
81
+ 4: {
82
+ '(1)': [
83
+ '(' + ''.join(FULL_WIDTH_DIGIT_MAP[ddd] for ddd in dd) + ')'
84
+ for dd in [
85
+ str(d) for d in range(1, 61)
86
+ ]
87
+ ],
88
+ },
89
+ 5: {
90
+ '①': [chr(ord('①') + d) for d in range(0, 20)],
91
+ f'({KATAKANA_GOJUON_SEQUENCE[0]})': [f'({d})' for d in KATAKANA_GOJUON_SEQUENCE],
92
+ KATAKANA_GOJUON_SEQUENCE[0]: KATAKANA_GOJUON_SEQUENCE,
93
+ '(a)': ['(' + chr(ord('a') + d) + ')' for d in range(0, 26)],
94
+ 'a': [chr(ord('a') + d) for d in range(0, 26)],
95
+ },
96
+ }
97
+ SHALLOWEST_LEVEL = min(TOC_NUMBER_SETS.keys())
98
+ DEEPEST_LEVEL = max(TOC_NUMBER_SETS.keys())
99
+
100
+
101
+ class TableOfContentsBuilder:
102
+ _currentDocument: ModelDocument | None
103
+ _currentLevel: int
104
+ _documents: list[ModelDocument]
105
+ _floatingLevel: int | None
106
+ _levelLabels: dict[int, set[str]]
107
+ _levelPositions: dict[int, int]
108
+ _levelSequences: dict[int, list[str] | None]
109
+ _tocEntryCount: int
110
+ _tocSequence: list[tuple[str, str, ModelObject]]
111
+ _validations: list[Validation]
112
+
113
+ def __init__(self) -> None:
114
+ self._currentDocument = None
115
+ self._currentLevel = SHALLOWEST_LEVEL
116
+ self._floatingLevel = None
117
+ self._levelLabels = defaultdict(set)
118
+ self._levelPositions = defaultdict(int)
119
+ self._levelSequences = {}
120
+ self._documents = []
121
+ self._tocEntryCount = 0
122
+ self._tocSequence = []
123
+ self._validations = []
124
+
125
+ def _build(self) -> None:
126
+ documents = sorted(self._documents, key=lambda doc: doc.basename)
127
+ for document in documents:
128
+ rootElt = document.xmlRootElement
129
+ for elt in rootElt.iterdescendants():
130
+ if not isinstance(elt, ModelObject):
131
+ continue
132
+ if elt.elementQname.localName == 'title':
133
+ continue
134
+ if elt.text is not None:
135
+ self._element(elt)
136
+
137
+ def _checkCurrentLevelNext(self, number: str, nextPosition: int, currentSequence: list[str] | None) -> bool:
138
+
139
+ # NEXT IN SEQUENCE
140
+ # We can only move ahead in the sequence if it has been established AND
141
+ # we have not reached the end of the allowed numbers in the sequence.
142
+ if currentSequence is None:
143
+ # No sequence established at this level.
144
+ return False
145
+ if nextPosition >= len(currentSequence):
146
+ # We have reached the end of the sequence at this level.
147
+ return False
148
+ nextNumberInSequence = currentSequence[nextPosition]
149
+ if number == nextNumberInSequence:
150
+ # Increment the position at the current level.
151
+ self._levelPositions[self._currentLevel] = self._levelPositions[self._currentLevel] + 1
152
+ # Reset the floating status.
153
+ self._floatingLevel = None
154
+ return True
155
+ return False
156
+
157
+ def _checkDeepLevel(self, number: str) -> bool:
158
+ # STARTING DEEPER SEQUENCE
159
+ # We can move deeper one or more levels.
160
+ if self._floatingLevel is not None:
161
+ # We don't move deeper if we are floating.
162
+ return False
163
+ deeperStartingNumbers = {
164
+ startingNumber: level
165
+ for level in range(min(self._currentLevel + 1, DEEPEST_LEVEL), DEEPEST_LEVEL + 1)
166
+ for startingNumber in TOC_NUMBER_SETS[level]
167
+ }
168
+ if number not in deeperStartingNumbers:
169
+ # The number is not the first entry in a deeper level sequence.
170
+ return False
171
+ # Set the level to the deeper level.
172
+ self._currentLevel = deeperStartingNumbers[number]
173
+ # Establish the sequence at the deeper level.
174
+ self._levelSequences[self._currentLevel] = TOC_NUMBER_SETS[self._currentLevel][number]
175
+ # Reset the duplicates at the deeper level.
176
+ self._levelLabels[self._currentLevel].clear()
177
+ # Reset the position at the deeper level.
178
+ self._levelPositions[self._currentLevel] = 1
179
+ return True
180
+
181
+ def _checkShallowLevel(self, number: str) -> bool:
182
+ # RESUMING SHALLOWER SEQUENCE
183
+ # We may be moving back up one or more levels.
184
+ nextLevel = None
185
+ for shallowLevel in reversed(range(SHALLOWEST_LEVEL, self._currentLevel)):
186
+ shallowSequence = self._levelSequences.get(shallowLevel)
187
+ # For each level, should we be checking earlier and later numbers in the sequence
188
+ # to fire EC3002E or EC3003E?
189
+ if shallowSequence is not None and number == shallowSequence[self._levelPositions[shallowLevel]]:
190
+ # This is the next number in the upper sequence.
191
+ # Move up one level.
192
+ nextLevel = shallowLevel
193
+ break
194
+ shallowLevel -= 1
195
+ if nextLevel is None:
196
+ return False
197
+ # For each level shallower than the new level down to the current level...
198
+ for i in range(nextLevel + 1, self._currentLevel + 1):
199
+ # Reset the position.
200
+ self._levelPositions[i] = 0
201
+ # Reset the duplicates.
202
+ self._levelLabels[i].clear()
203
+ # Reset the sequence.
204
+ self._levelSequences[i] = None
205
+ # Set the level to the shallower level.
206
+ self._currentLevel = nextLevel
207
+ # Increment the position at the shallower level.
208
+ self._levelPositions[self._currentLevel] = self._levelPositions[self._currentLevel] + 1
209
+ # Reset the floating status.
210
+ self._floatingLevel = None
211
+ return True
212
+
213
+ def _closeDocument(self) -> None:
214
+ assert self._currentDocument is not None, "No document is currently open."
215
+ # EDINET.EC2001E: There must be at least one table of contents entry in each file.
216
+ if self._tocEntryCount == 0:
217
+ self._validations.append(Validation.error(
218
+ codes='EDINET.EC2001E',
219
+ msg=_("The table of contents is not listed at the beginning. "
220
+ "File name: '%(path)s'. "
221
+ "Please provide the table of contents entry for the file."),
222
+ path=self._currentDocument.basename,
223
+ ))
224
+ self._currentDocument = None
225
+
226
+ def _element(self, elt: ModelObject) -> None:
227
+ # New document, close previous.
228
+ if self._currentDocument is not None and self._currentDocument != elt.document:
229
+ self._closeDocument()
230
+ # First or new document, open document.
231
+ if self._currentDocument is None:
232
+ self._openDocument(elt.document)
233
+ text = elt.text or ""
234
+ openIndex = -1
235
+ closeIndex = -1
236
+ if "【" in text:
237
+ openIndex = text.index("【") + 1
238
+ # EDINET.EC2004E: Corner brackets (【) must not overlap.
239
+ if "【" in text[openIndex:]:
240
+ self._validations.append(Validation.error(
241
+ codes='EDINET.EC2004E',
242
+ msg=_("The opening bracket (【) is repeated. "
243
+ "File name: '%(path)s' (line %(line)s). "
244
+ "When viewed in a browser, it is not possible to display "
245
+ "more than one table of contents item on one line. Please "
246
+ "delete the brackets (【) in the relevant file."),
247
+ path=elt.document.basename,
248
+ line=elt.sourceline,
249
+ modelObject=elt,
250
+ ))
251
+ if "】" in text:
252
+ closeIndex = text.index("】") - 1
253
+ if openIndex >= 0:
254
+ if closeIndex > openIndex:
255
+ number = text[:openIndex - 1].strip()
256
+ label = text[openIndex:closeIndex + 1]
257
+ self._tocSequence.append((number, label, elt))
258
+ self._tocEntryCount += 1
259
+ else:
260
+ # EDINET.EC2007E: The table of contents entries must be enclosed in square brackets (】).
261
+ self._validations.append(Validation.error(
262
+ codes='EDINET.EC2007E',
263
+ msg=_("The table of contents entry is not closed with '】'. "
264
+ "File name: '%(path)s' (line %(line)s). "
265
+ "Add a closing bracket (】) to match the open bracket (【) "
266
+ "in the table of contents entry for the file in question."),
267
+ path=elt.document.basename,
268
+ line=elt.sourceline,
269
+ modelObject=elt,
270
+ ))
271
+
272
+ def _isFloating(self) -> bool:
273
+ return self._floatingLevel is not None or self._currentLevel >= DEEPEST_LEVEL
274
+
275
+ def _normalizeNumber(self, number: str) -> str:
276
+ # EDINET does not support:
277
+ # - Mixture of half-width and full-width digits within a number.
278
+ # - Mixture of half-width and full-width parentheses within a number.
279
+ # EDINET does support:
280
+ # - Mixture of half-width digits with full-width parentheses, and vice versa.
281
+ # We will normalize to full-width parantheses and digits for number validation.
282
+ if "(" in number and ")" in number: # Half-width (, full-width )
283
+ return number
284
+ if "(" in number and ")" in number: # Full-width (, half-width )
285
+ return number
286
+ paranthesesFullWidth: bool | None = None
287
+ numbersFullWidth: bool | None = None
288
+ for c in number:
289
+ if c in ("(", ")"):
290
+ if paranthesesFullWidth == True:
291
+ return number # Mix of half/full-width parantheses
292
+ paranthesesFullWidth = False
293
+ elif c in ("(", " )"):
294
+ if paranthesesFullWidth == False:
295
+ return number # Mix of half/full-width parantheses
296
+ paranthesesFullWidth = True
297
+ elif c in FULL_WIDTH_DIGIT_MAP:
298
+ if numbersFullWidth == True:
299
+ return number # Mix of half/full-width digits
300
+ numbersFullWidth = False
301
+ elif c in FULL_WIDTH_DIGIT_MAP.values():
302
+ if numbersFullWidth == False:
303
+ return number # Mix of half/full-width digits
304
+ numbersFullWidth = True
305
+ return jaconv.h2z(number, kana=True, ascii=True, digit=True)
306
+
307
+ def _openDocument(self, modelDocument: ModelDocument) -> None:
308
+ assert self._currentDocument is None, "Close current document before opening another."
309
+ self._tocEntryCount = 0
310
+ self._currentDocument = modelDocument
311
+
312
+ def _validateItem(self, number: str, label: str, elt: ModelObject) -> Iterable[Validation]:
313
+ # Convert to full-width, ONLY if fully half-width.
314
+ # EDINET does not support a mixture of half-width and full-width digits in TOC numbers.
315
+ number = self._normalizeNumber(number)
316
+ nextPosition = self._levelPositions[self._currentLevel]
317
+ currentSequence = self._levelSequences.get(self._currentLevel)
318
+
319
+ # UN-NUMBERED (FLOATING) ITEM
320
+ # Floating items trigger special behavior for following items
321
+ # until the current or shallower level is resumed.
322
+ if number == "":
323
+ # Only trigger floating/warning if we are not already floating, and we
324
+ # aren't already at the deepest level.
325
+ if not self._isFloating():
326
+ # EDINET.EC2002W: The table of contents number must be present.
327
+ # Note from documentation: Even if the data content is normal, it may be identified as an
328
+ # exception and a warning may be displayed.
329
+ yield Validation.warning(
330
+ codes='EDINET.EC2002W',
331
+ msg=_("The table of contents number is not listed. "
332
+ "File name: '%(path)s' (line %(line)s). "
333
+ "Please include the table of contents number of the relevant file."),
334
+ path=elt.document.basename,
335
+ line=elt.sourceline,
336
+ modelObject=elt,
337
+ )
338
+ self._floatingLevel = self._currentLevel
339
+ return
340
+
341
+ if self._checkCurrentLevelNext(number, nextPosition, currentSequence):
342
+ return
343
+ if self._checkDeepLevel(number):
344
+ return
345
+ if self._checkShallowLevel(number):
346
+ return
347
+
348
+ # OTHER NUMBER IN CURRENT SEQUENCE
349
+ if currentSequence is not None and number in currentSequence:
350
+ numberIndex = currentSequence.index(number)
351
+ assert numberIndex != nextPosition
352
+ # Is it repeating a previous number?
353
+ if numberIndex < nextPosition:
354
+ # EDINET.EC3002E: Table of contents numbers for table of contents entries
355
+ # must not be repeated within the same hierarchy.
356
+ yield Validation.error(
357
+ codes='EDINET.EC3002E',
358
+ msg=_("The table of contents number of the table of contents "
359
+ "item is duplicated in the same hierarchy. "
360
+ "File name: '%(path)s' (line %(line)s). "
361
+ "Please correct the table of contents number in the "
362
+ "table of contents entry of the relevant file."),
363
+ path=elt.document.basename,
364
+ line=elt.sourceline,
365
+ modelObject=elt,
366
+ )
367
+ return
368
+ # Is it skipping ahead?
369
+ if numberIndex > nextPosition:
370
+ # EDINET.EC3003E: There must be no gaps in the table of contents numbers
371
+ # within the same hierarchy.
372
+ yield Validation.error(
373
+ codes='EDINET.EC3003E',
374
+ msg=_("There is a gap in the table of contents number "
375
+ "within the same hierarchy. "
376
+ "File name: '%(path)s' (line %(line)s). "
377
+ "Please enter the missing table of contents number "
378
+ "in the appropriate file."),
379
+ number=number,
380
+ label=label,
381
+ path=elt.document.basename,
382
+ line=elt.sourceline,
383
+ modelObject=elt,
384
+ )
385
+ # Jump ahead to minimize further errors.
386
+ # Increment the position at the current level.
387
+ self._levelPositions[self._currentLevel] = numberIndex + 1
388
+ # Reset the floating status.
389
+ self._floatingLevel = None
390
+ return
391
+
392
+ # INVALID NUMBER
393
+ # Not un-numbered (floating), not next in sequence, not starting deeper sequence,
394
+ # not resuming shallower sequence.
395
+ if self._floatingLevel is None:
396
+ # The difference between EC3004W and EC3005E is unclear based on documentation.
397
+ # We will implement the higher level severity version of the two.
398
+ # EDINET.EC3004W: The table of contents number of the table of contents
399
+ # item must be set.
400
+ # EDINET.EC3005E: The table of contents numbers for the table of contents
401
+ # entries must be as specified in the format.
402
+ yield Validation.error(
403
+ codes='EDINET.EC3005E',
404
+ msg=_("The table of contents number for item '%(number)s %(label)s' is incorrect. "
405
+ "File name: '%(path)s' (line %(line)s). "
406
+ "Please correct the table of contents number of the "
407
+ "table of contents item of the corresponding file."),
408
+ number=number,
409
+ label=label,
410
+ path=elt.document.basename,
411
+ line=elt.sourceline,
412
+ modelObject=elt,
413
+ )
414
+
415
+ def addDocument(self, modelDocument: ModelDocument) -> None:
416
+ self._documents.append(modelDocument)
417
+
418
+ def validate(self) -> Iterable[Validation]:
419
+ self._build()
420
+ if self._currentDocument is not None:
421
+ self._closeDocument()
422
+ # Yield errors encountered during loading/build.
423
+ yield from self._validations
424
+
425
+ # Tracks the current level.
426
+ self._currentLevel = SHALLOWEST_LEVEL
427
+ # Tracks the current position in the sequence at each level.
428
+ self._levelPositions: dict[int, int] = defaultdict(int)
429
+ # Tracks the active number set at each level.
430
+ self._levelSequences: dict[int, list[str] | None] = {
431
+ self._currentLevel: next(iter(TOC_NUMBER_SETS[self._currentLevel].values()))
432
+ }
433
+ # Tracks unique labels within a sequence.
434
+ self._levelLabels = defaultdict(set)
435
+ # Tracks floating status.
436
+ self._floatingLevel = None
437
+ for number, label, elt in self._tocSequence:
438
+ yield from self._validateItem(number, label, elt)
439
+
440
+ # We are only concerned about duplicates if we are not floating.
441
+ if not self._isFloating():
442
+ if label in self._levelLabels[self._currentLevel]:
443
+ # EDINET.EC2005E: Table of contents entries must not be duplicated.
444
+ # Note: Sample filings suggest this applies to entries that are
445
+ # siblings within the hierarchy.
446
+ yield Validation.error(
447
+ codes='EDINET.EC2005E',
448
+ msg=_("The table of contents item ('%(label)s') is duplicated. "
449
+ "File name: '%(path)s' (line %(line)s). "
450
+ "Please remove the duplicate table of contents in the appropriate file."),
451
+ label=label,
452
+ path=elt.document.basename,
453
+ line=elt.sourceline,
454
+ modelObject=elt,
455
+ )
456
+ else:
457
+ self._levelLabels[self._currentLevel].add(label)
458
+
459
+ if not self._isFloating():
460
+ # EDINET.EC2003E: The table of contents must be no longer than 384 bytes
461
+ # (equivalent to 128 full-width characters).
462
+ b = label.encode('utf-8')
463
+ if len(label.encode('utf-8')) > 384:
464
+ yield Validation.error(
465
+ codes='EDINET.EC2003E',
466
+ msg=_("The table of contents entry exceeds 384 bytes. "
467
+ "File name: '%(path)s' (line %(line)s). "
468
+ "Please modify the table of contents of the relevant "
469
+ "file so that it is within 384B (bytes) (equivalent to "
470
+ "128 full-width characters)."),
471
+ path=elt.document.basename,
472
+ line=elt.sourceline,
473
+ modelObject=elt,
474
+ )
475
+
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
+ # Uncomment for debugging output of TOC structure.
490
+ # print(
491
+ # f'{" " if self._floatingLevel is not None else "|"}\t' * (self._currentLevel - 1) +
492
+ # f"{number} [{label}] \t{elt.document.basename}"
493
+ # )
@@ -18,12 +18,16 @@ PLUGIN_NAME = "Validate EDINET"
18
18
  DISCLOSURE_SYSTEM_VALIDATION_TYPE = "EDINET"
19
19
  RELEVELER_MAP: dict[str, dict[str, tuple[str, str | None]]] = {
20
20
  "ERROR": {
21
+ # Re-code to EDINET version
22
+ "GFM.1.1.3": ("ERROR", "EDINET.EC5700W.GFM.1.1.3"),
21
23
  # Silence, duplicated by EDINET.EC5002E
22
24
  "xbrl.4.8.2:sharesFactUnit-notSharesMeasure": ("ERROR", None),
23
25
  # Silence, duplicated by EDINET.EC5002E
24
26
  "xbrl.4.8.2:sharesFactUnit-notSingleMeasure": ("ERROR", None),
25
27
  # Silence, duplicated by EDINET.EC5700W.GFM.1.7.2
26
28
  "xbrl.5.2.5.2.1:zeroWeight": ("ERROR", None),
29
+ # Silence, Duplicated by EDINET.EC5710W.FRTA.4.2.11
30
+ "xbrl.5.1:emptyTargetNamespace": ("ERROR", None),
27
31
  },
28
32
  }
29
33
 
@@ -56,8 +60,15 @@ def fileSourceEntrypointFiles(*args: Any, **kwargs: Any) -> list[dict[str, Any]]
56
60
 
57
61
 
58
62
  def loggingSeverityReleveler(modelXbrl: ModelXbrl, level: str, messageCode: str, args: Any, **kwargs: Any) -> tuple[str | None, str | None]:
59
- if level in RELEVELER_MAP:
60
- return RELEVELER_MAP[level].get(messageCode, (level, messageCode))
63
+ if level not in RELEVELER_MAP:
64
+ return level, messageCode
65
+ messageCodes = list(args.get('messageCodes') or [])
66
+ if messageCode is not None:
67
+ messageCodes.append(messageCode)
68
+ for code in messageCodes:
69
+ result = RELEVELER_MAP[level].get(code)
70
+ if result is not None:
71
+ return result
61
72
  return level, messageCode
62
73
 
63
74
 
@@ -6,6 +6,12 @@
6
6
  <DisclosureSystem
7
7
  names="EDINET|edinet"
8
8
  description="Checks for EDINET."
9
+ arcroleCyclesAllowed='{
10
+ "http://xbrl.org/int/dim/arcrole/dimension-domain": ["none", "EDINET.EC5700W.GFM.1.8.4"],
11
+ "http://xbrl.org/int/dim/arcrole/domain-member": ["none", "EDINET.EC5700W.GFM.1.8.4"],
12
+ "http://www.xbrl.org/2003/arcrole/summation-item": ["none", "EDINET.EC5700W.GFM.1.7.4"],
13
+ "https://xbrl.org/2023/arcrole/summation-item": ["none", "EDINET.EC5700W.GFM.1.7.4"]
14
+ }'
9
15
  defaultXmlLang="ja"
10
16
  blockDisallowedReferences="true"
11
17
  validationType="EDINET"