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
@@ -26,6 +26,8 @@
26
26
  <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/jpdei_cor_2013-08-31.xsd</Href><AttType>SCH</AttType><FileTypeName>Schema</FileTypeName><Elements>1</Elements> <Namespace>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/jpdei_cor</Namespace><Prefix>jpdei</Prefix></Loc>
27
27
  <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/jpdei_rt_2013-08-31.xsd</Href><AttType>SCH</AttType><FileTypeName>Entry Point</FileTypeName><Elements>0</Elements> <Namespace>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/jpdei_rt</Namespace><Prefix>jpdei</Prefix></Loc>
28
28
  <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/label/jpdei_2013-08-31_gla.xml</Href><AttType>LAB</AttType><FileTypeName>Labels</FileTypeName><Elements>0</Elements></Loc>
29
+ <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/label/jpdei_2013-08-31_lab-en.xml</Href><AttType>LAB</AttType><FileTypeName>Labels</FileTypeName><Elements>0</Elements></Loc>
30
+ <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/label/jpdei_2013-08-31_lab.xml</Href><AttType>LAB</AttType><FileTypeName>Labels</FileTypeName><Elements>0</Elements></Loc>
29
31
  <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/label/jpdei_2024-11-01_lab-en.xml</Href><AttType>LAB</AttType><FileTypeName>Labels</FileTypeName><Elements>0</Elements></Loc>
30
32
  <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/label/jpdei_2024-11-01_lab.xml</Href><AttType>LAB</AttType><FileTypeName>Labels</FileTypeName><Elements>0</Elements></Loc>
31
33
  <Loc><Family>FSA</Family><Version>2013</Version><Href>http://disclosure.edinet-fsa.go.jp/taxonomy/jpdei/2013-08-31/r/jpdei_000100-000_2013-08-31_def.xml</Href><AttType>DEF</AttType><FileTypeName>Definition, Dimensions</FileTypeName><Elements>0</Elements></Loc>
@@ -8,12 +8,14 @@ from itertools import chain
8
8
  from typing import Any, Iterable
9
9
 
10
10
  from arelle import XbrlConst
11
+ from arelle.LinkbaseType import LinkbaseType
11
12
  from arelle.ModelDtsObject import ModelConcept
12
13
  from arelle.ValidateXbrl import ValidateXbrl
13
14
  from arelle.typing import TypeGetText
14
15
  from arelle.utils.PluginHooks import ValidationHook
15
16
  from arelle.utils.validate.Decorator import validation
16
17
  from arelle.utils.validate.Validation import Validation
18
+ from ..Constants import FINANCIAL_STATEMENT_CONTEXT_ID_PATTERN, CONTEXT_ID_PATTERN
17
19
  from ..DisclosureSystems import (DISCLOSURE_SYSTEM_EDINET)
18
20
  from ..PluginValidationDataExtension import PluginValidationDataExtension
19
21
 
@@ -28,6 +30,64 @@ FINANCIAL_STATEMENT_ELR_PREFIXES = (
28
30
  )
29
31
 
30
32
 
33
+ @validation(
34
+ hook=ValidationHook.XBRL_FINALLY,
35
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
36
+ )
37
+ def rule_EC8011W(
38
+ pluginData: PluginValidationDataExtension,
39
+ val: ValidateXbrl,
40
+ *args: Any,
41
+ **kwargs: Any,
42
+ ) -> Iterable[Validation]:
43
+ """
44
+ EDINET.EC8011W: The context ID must conform to the naming rules.
45
+ """
46
+ for contextId, context in val.modelXbrl.contexts.items():
47
+ if not CONTEXT_ID_PATTERN.fullmatch(contextId):
48
+ yield Validation.warning(
49
+ codes='EDINET.EC8011W',
50
+ msg=_("The context ID does not conform to the naming rules. "
51
+ "Context ID: '%(contextId)s'. "
52
+ "Please correct the relevant context ID in accordance with the naming rules. "
53
+ "* No action is required for warnings caused by setting \"FutureDate\" "
54
+ "for first portion of context ID. "
55
+ "* No action is required for warnings caused by tagging for disclosure beyond "
56
+ "the period specified in the naming convention for \"total greenhouse gas emissions.\""),
57
+ contextId=contextId,
58
+ modelObject=context,
59
+ )
60
+
61
+
62
+ @validation(
63
+ hook=ValidationHook.XBRL_FINALLY,
64
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
65
+ )
66
+ def rule_EC8012W(
67
+ pluginData: PluginValidationDataExtension,
68
+ val: ValidateXbrl,
69
+ *args: Any,
70
+ **kwargs: Any,
71
+ ) -> Iterable[Validation]:
72
+ """
73
+ EDINET.EC8012W: If a main financial statement element is present, a calculation linkbase file must be present.
74
+ """
75
+ if not any(
76
+ fact.qname.namespaceURI == pluginData.jppfsNamespace
77
+ for fact in val.modelXbrl.facts
78
+ ):
79
+ return
80
+ relSet = val.modelXbrl.relationshipSet(tuple(LinkbaseType.CALCULATION.getArcroles()))
81
+ if relSet is None or len(relSet.modelRelationships) == 0:
82
+ yield Validation.warning(
83
+ codes='EDINET.EC8012W',
84
+ msg=_("If a main financial statement element is present, a calculation linkbase "
85
+ "file must be present. "
86
+ "If you wish to tag the financial statements, please submit a "
87
+ "calculation linkbase file."),
88
+ )
89
+
90
+
31
91
  @validation(
32
92
  hook=ValidationHook.XBRL_FINALLY,
33
93
  disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
@@ -75,7 +135,7 @@ def rule_EC8013W(
75
135
  continue
76
136
  if fact.contextID is None:
77
137
  continue
78
- if not pluginData.contextIdPattern.match(fact.contextID):
138
+ if not FINANCIAL_STATEMENT_CONTEXT_ID_PATTERN.fullmatch(fact.contextID):
79
139
  invalidContextIdMap[fact.contextID].append(fact)
80
140
  for contextId, facts in invalidContextIdMap.items():
81
141
  yield Validation.warning(
@@ -3,10 +3,15 @@ See COPYRIGHT.md for copyright information.
3
3
  """
4
4
  from __future__ import annotations
5
5
 
6
+ from pathlib import Path
6
7
  from typing import Any, Iterable
7
8
 
9
+ import regex
10
+ from jaconv import jaconv
11
+
8
12
  from arelle import XbrlConst, ValidateDuplicateFacts
9
13
  from arelle.LinkbaseType import LinkbaseType
14
+ from arelle.ModelValue import QName
10
15
  from arelle.ValidateDuplicateFacts import DuplicateType
11
16
  from arelle.ValidateXbrl import ValidateXbrl
12
17
  from arelle.typing import TypeGetText
@@ -14,8 +19,10 @@ from arelle.utils.PluginHooks import ValidationHook
14
19
  from arelle.utils.validate.Decorator import validation
15
20
  from arelle.utils.validate.Validation import Validation
16
21
  from ..Constants import AccountingStandard
22
+ from ..DeiRequirements import DeiItemStatus
17
23
  from ..DisclosureSystems import (DISCLOSURE_SYSTEM_EDINET)
18
24
  from ..PluginValidationDataExtension import PluginValidationDataExtension
25
+ from ..ReportFolderType import ReportFolderType
19
26
  from ..Statement import StatementType
20
27
 
21
28
  _: TypeGetText
@@ -164,14 +171,117 @@ def rule_EC5002E(
164
171
  hook=ValidationHook.XBRL_FINALLY,
165
172
  disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
166
173
  )
167
- def rule_EC5613W(
174
+ def rule_EC5602R(
175
+ pluginData: PluginValidationDataExtension,
176
+ val: ValidateXbrl,
177
+ *args: Any,
178
+ **kwargs: Any,
179
+ ) -> Iterable[Validation]:
180
+ """
181
+ EDINET.EC5602R: DEI value must match corresponding cover page value.
182
+
183
+ Applies to FilerNameInJapaneseDEI, FilerNameInEnglishDEI, FundNameInJapaneseDEI.
184
+ """
185
+ errors = []
186
+
187
+ def _normalizeValue(value: str) -> str:
188
+ value = regex.sub(r'\s+', ' ', value).strip()
189
+ return jaconv.h2z(value, kana=True, ascii=True, digit=True)
190
+
191
+ def _collectMismatchedValues(deiQName: QName, coverPageQnames: list[QName]) -> None:
192
+ deiFact = next((
193
+ fact
194
+ for fact in pluginData.iterValidNonNilFacts(val.modelXbrl, deiQName)
195
+ ), None)
196
+ if deiFact is None or deiFact.xValue is None:
197
+ return
198
+ deiValue = _normalizeValue(str(deiFact.xValue))
199
+ for coverPageQname in coverPageQnames:
200
+ for coverPageFact in pluginData.iterValidNonNilFacts(val.modelXbrl, coverPageQname):
201
+ factValue = _normalizeValue(str(coverPageFact.xValue))
202
+ if not factValue.startswith(deiValue):
203
+ errors.append((deiFact, coverPageFact))
204
+
205
+ _collectMismatchedValues(
206
+ pluginData.qname('jpdei_cor', 'FilerNameInJapaneseDEI'),
207
+ [
208
+ #【発行者名】
209
+ pluginData.qname('jpsps-esr_cor', 'IssuerNameCoverPage'),
210
+ pluginData.qname('jpsps-sbr_cor', 'IssuerNameCoverPage'),
211
+ pluginData.qname('jpsps_cor', 'IssuerNameCoverPage'),
212
+ #【会社名】
213
+ pluginData.qname('jpcrp-esr_cor', 'CompanyNameCoverPage'),
214
+ pluginData.qname('jpcrp-sbr_cor', 'CompanyNameCoverPage'),
215
+ pluginData.qname('jpcrp_cor', 'CompanyNameCoverPage'),
216
+ pluginData.qname('jpctl_cor', 'CompanyNameCoverPage'),
217
+ #【氏名又は名称】
218
+ pluginData.qname('jplvh_cor', 'NameCoverPage'),
219
+ #【届出者の名称】
220
+ pluginData.qname('jptoi_cor', 'FullNameOrNameOfFilerOfNotificationCoverPage'),
221
+ #【届出者の氏名又は名称】
222
+ pluginData.qname('jptoo-ton_cor', 'FullNameOrNameOfFilerOfNotificationCoverPage'),
223
+ pluginData.qname('jptoo-wto_cor', 'FullNameOrNameOfFilerOfNotificationCoverPage'),
224
+ #【報告者の名称】
225
+ pluginData.qname('jptoi_cor', 'NameOfFilerCoverPage'),
226
+ pluginData.qname('jptoo-pst_cor', 'NameOfFilerCoverPage'),
227
+ #【報告者の氏名又は名称】
228
+ pluginData.qname('jptoo-toa_cor', 'FullNameOrNameOfFilerCoverPage'),
229
+ pluginData.qname('jptoo-tor_cor', 'FullNameOrNameOfFilerCoverPage'),
230
+ ]
231
+ )
232
+
233
+ _collectMismatchedValues(
234
+ pluginData.qname('jpdei_cor', 'FilerNameInEnglishDEI'),
235
+ [
236
+ #【英訳名】
237
+ pluginData.qname('jpcrp-esr_cor', 'CompanyNameInEnglishCoverPage'),
238
+ pluginData.qname('jpcrp-sbr_cor', 'CompanyNameInEnglishCoverPage'),
239
+ pluginData.qname('jpcrp_cor', 'CompanyNameInEnglishCoverPage'),
240
+ pluginData.qname('jpctl_cor', 'CompanyNameInEnglishCoverPage'),
241
+ ]
242
+ )
243
+
244
+ _collectMismatchedValues(
245
+ pluginData.qname('jpdei_cor', 'FundNameInJapaneseDEI'),
246
+ [
247
+ #【ファンド名】
248
+ pluginData.qname('jpsps-esr_cor', 'FundNameCoverPage'),
249
+ pluginData.qname('jpsps_cor', 'FundNameCoverPage'),
250
+ #【届出の対象とした募集(売出)内国投資信託受益証券に係るファンドの名称】
251
+ pluginData.qname('jpsps_cor', 'NameOfFundRelatedToDomesticInvestmentTrustBeneficiaryCertificateToRegisterForOfferingOrDistributionCoverPageTextBlock'),
252
+ #【届出の対象とした募集(売出)内国投資証券に係る投資法人の名称】
253
+ pluginData.qname('jpsps_cor', 'NameOfInvestmentCorporationRelatedToDomesticInvestmentSecuritiesToRegisterForOfferingOrDistributionCoverPage'),
254
+ ]
255
+ )
256
+
257
+ for deiFact, coverPageFact in errors:
258
+ yield Validation.warning(
259
+ codes='EDINET.EC5602R',
260
+ msg=_("The DEI information \"%(deiQname)s\" (%(deiValue)s) does not match "
261
+ "\"%(coverPageQname)s\" (%(coverPageValue)s) . "
262
+ "Please check the content of the corresponding DEI (the element "
263
+ "displayed in the message) and the value in the submitted document, "
264
+ "and correct it so that they match."),
265
+ deiQname=deiFact.qname,
266
+ deiValue=deiFact.xValue,
267
+ coverPageQname=coverPageFact.qname,
268
+ coverPageValue=coverPageFact.xValue,
269
+ modelObject=[deiFact, coverPageFact],
270
+ )
271
+
272
+
273
+ @validation(
274
+ hook=ValidationHook.XBRL_FINALLY,
275
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
276
+ )
277
+ def rule_EC5613E(
168
278
  pluginData: PluginValidationDataExtension,
169
279
  val: ValidateXbrl,
170
280
  *args: Any,
171
281
  **kwargs: Any,
172
282
  ) -> Iterable[Validation]:
173
283
  """
174
- EDINET.EC5613W: Please set the DEI "Accounting Standard" value to one
284
+ EDINET.EC5613E: Please set the DEI "Accounting Standard" value to one
175
285
  of the following: "Japan GAAP", "US GAAP", "IFRS".
176
286
  """
177
287
  validAccountingStandards = {s.value for s in AccountingStandard}
@@ -180,8 +290,8 @@ def rule_EC5613W(
180
290
  if fact.xValue not in validAccountingStandards
181
291
  ]
182
292
  if len(errorFacts) > 0:
183
- yield Validation.warning(
184
- codes='EDINET.EC5613W',
293
+ yield Validation.error(
294
+ codes='EDINET.EC5613E',
185
295
  msg=_("Please set the DEI \"Accounting Standard\" value to one "
186
296
  "of the following: %(values)s."),
187
297
  values=', '.join(f'"{s.value}"' for s in AccountingStandard),
@@ -189,6 +299,170 @@ def rule_EC5613W(
189
299
  )
190
300
 
191
301
 
302
+ @validation(
303
+ hook=ValidationHook.XBRL_FINALLY,
304
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
305
+ )
306
+ def rule_EC5614E(
307
+ pluginData: PluginValidationDataExtension,
308
+ val: ValidateXbrl,
309
+ *args: Any,
310
+ **kwargs: Any,
311
+ ) -> Iterable[Validation]:
312
+ """
313
+ EDINET.EC5614E: A required DEI value is missing.
314
+ """
315
+ for coverPageDocument in pluginData.iterCoverPages(val.modelXbrl):
316
+ filingFormat = pluginData.getFilingFormat(val.modelXbrl)
317
+ if filingFormat is None:
318
+ return
319
+ deiRequirements = pluginData.getDeiRequirements(val.modelXbrl)
320
+ for qname in pluginData.deiItems:
321
+ status = deiRequirements.get(qname, filingFormat)
322
+ if (
323
+ status == DeiItemStatus.REQUIRED and
324
+ not pluginData.hasValidNonNilFact(val.modelXbrl, qname)
325
+ ):
326
+ yield Validation.error(
327
+ codes='EDINET.EC5614E',
328
+ msg=_("The value of '%(localName)s' in the DEI does not exist. "
329
+ "File name: '%(file)s'. "
330
+ "Please add the cover item %(localName)s to the relevant file."),
331
+ localName=qname.localName,
332
+ file=coverPageDocument.basename,
333
+ )
334
+
335
+
336
+ @validation(
337
+ hook=ValidationHook.XBRL_FINALLY,
338
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
339
+ )
340
+ def rule_EC5623W(
341
+ pluginData: PluginValidationDataExtension,
342
+ val: ValidateXbrl,
343
+ *args: Any,
344
+ **kwargs: Any,
345
+ ) -> Iterable[Validation]:
346
+ """
347
+ EDINET.EC5623W: Instances using IFRS taxonomies must set the DEI "Accounting Standard" value to "IFRS".
348
+ """
349
+ if pluginData.jpigpNamespace not in val.modelXbrl.prefixedNamespaces.values():
350
+ return
351
+ errorFacts = [
352
+ fact for fact in pluginData.iterValidNonNilFacts(val.modelXbrl, pluginData.accountingStandardsDeiQn)
353
+ if fact.xValue != AccountingStandard.IFRS.value
354
+ ]
355
+ if len(errorFacts) > 0:
356
+ yield Validation.warning(
357
+ codes='EDINET.EC5623W',
358
+ msg=_("Please set the DEI \"Accounting Standard\" value to \"IFRS\"."),
359
+ modelObject=errorFacts,
360
+ )
361
+
362
+
363
+ @validation(
364
+ hook=ValidationHook.XBRL_FINALLY,
365
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
366
+ )
367
+ def rule_namespace_prefixes(
368
+ pluginData: PluginValidationDataExtension,
369
+ val: ValidateXbrl,
370
+ *args: Any,
371
+ **kwargs: Any,
372
+ ) -> Iterable[Validation]:
373
+ """
374
+ EDINET.EC8003W: The namespace prefix used in the namespace declaration of the
375
+ report schema file must conform to the rules.
376
+ jp{府令略号}{様式番号}-{報告書略号}_{EDINET コード又はファンドコード}-{追番(3 桁)}
377
+ EDINET.EC8004W: The namespace prefix used in the namespace declaration of the
378
+ audit report schema file must conform to the rules.
379
+ jpaud-{監査報告書略号}-{当期又は前期の別}{連結又は個別の別}_{EDINET コード又はファンドコード}-{追番(3 桁)}
380
+ """
381
+ extensionSchemas = pluginData.getExtensionSchemas(val.modelXbrl)
382
+ for modelDocument in val.modelXbrl.urlDocs.values():
383
+ for prefix, namespace in modelDocument.xmlRootElement.nsmap.items():
384
+ if namespace not in extensionSchemas:
385
+ continue # Not an extension schema namespace
386
+ pathInfo = extensionSchemas[namespace]
387
+ assert pathInfo.reportFolderType is not None
388
+ patterns = pathInfo.reportFolderType.prefixPatterns
389
+ if len(patterns) == 0:
390
+ continue # No patterns to check against
391
+ match = any(pattern.fullmatch(prefix) for pattern in patterns)
392
+ if match:
393
+ continue # Valid namespace URI
394
+ if pathInfo.reportFolderType == ReportFolderType.AUDIT_DOC:
395
+ yield Validation.warning(
396
+ codes='EDINET.EC8004W',
397
+ msg=_("The namespace prefix used in the namespace declaration of the "
398
+ "audit report schema file does not conform to the rules. "
399
+ "File name: '%(file)s'. "
400
+ "Prefix: '%(prefix)s'."),
401
+ file=pathInfo.path.name,
402
+ prefix=prefix
403
+ )
404
+ else:
405
+ yield Validation.warning(
406
+ codes='EDINET.EC8003W',
407
+ msg=_("The namespace prefix used in the namespace declaration of the "
408
+ "report schema file does not conform to the rules. "
409
+ "File name: '%(file)s'. "
410
+ "Prefix: '%(prefix)s'."),
411
+ file=pathInfo.path.name,
412
+ prefix=prefix
413
+ )
414
+
415
+
416
+ @validation(
417
+ hook=ValidationHook.XBRL_FINALLY,
418
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
419
+ )
420
+ def rule_namespace_uris(
421
+ pluginData: PluginValidationDataExtension,
422
+ val: ValidateXbrl,
423
+ *args: Any,
424
+ **kwargs: Any,
425
+ ) -> Iterable[Validation]:
426
+ """
427
+ EDINET.EC8000W: A report's extension taxonomy namespace URI must conform to the rules.
428
+ http://disclosure.edinet-fsa.go.jp/jp{府令略号}{様式番号}/{報告書略号}/{報告書連番(3 桁)}
429
+ /{EDINET コード又はファンドコード}-{追番(3 桁)}/{報告対象期間期末日|報告義務発生日}
430
+ /{報告書提出回数(2 桁)}/{報告書提出日}
431
+ EDINET.EC8001W: An audit report's extension taxonomy namespace URI must conform to the rules.
432
+ http://disclosure.edinet-fsa.go.jp/jpaud/{監査報告書略号}/{当期又は前期の別}{連結又は個別の別}
433
+ /{報告書連番(3 桁)}/{EDINET コード又はファンドコード}-{追番(3桁)}/{報告対象期間期末日}
434
+ /{報告書提出回数(2 桁)}/{報告書提出日}
435
+ """
436
+ for targetNamespace, pathInfo in pluginData.getExtensionSchemas(val.modelXbrl).items():
437
+ assert pathInfo.reportFolderType is not None
438
+ patterns = pathInfo.reportFolderType.namespaceUriPatterns
439
+ if len(patterns) == 0:
440
+ continue # No patterns to check against
441
+ match = any(pattern.fullmatch(targetNamespace) for pattern in patterns)
442
+ if match:
443
+ continue # Valid namespace URI
444
+ if pathInfo.reportFolderType == ReportFolderType.AUDIT_DOC:
445
+ yield Validation.warning(
446
+ codes='EDINET.EC8001W',
447
+ msg=_("The namespace URI used in the namespace declaration of the "
448
+ "audit report schema file does not conform to the rules. "
449
+ "File name: '%(file)s'. "
450
+ "<<Namespace URI=%(uri)s>>."),
451
+ file=pathInfo.path.name,
452
+ uri=targetNamespace
453
+ )
454
+ else:
455
+ yield Validation.warning(
456
+ codes='EDINET.EC8000W',
457
+ msg=_("The namespace URI used in the namespace declaration of the "
458
+ "report schema file does not conform to the rules. "
459
+ "File name: '%(file)s'. "
460
+ "<<Namespace URI=%(uri)s>>."),
461
+ file=pathInfo.path.name,
462
+ uri=targetNamespace
463
+ )
464
+
465
+
192
466
  @validation(
193
467
  hook=ValidationHook.XBRL_FINALLY,
194
468
  disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
@@ -6,7 +6,7 @@ from __future__ import annotations
6
6
  from collections import defaultdict
7
7
  from typing import Any, Iterable
8
8
 
9
- from arelle import XbrlConst
9
+ from arelle import XbrlConst, ModelDocument
10
10
  from arelle.ModelDtsObject import ModelResource, ModelConcept
11
11
  from arelle.ValidateXbrl import ValidateXbrl
12
12
  from arelle.typing import TypeGetText
@@ -60,7 +60,7 @@ def rule_frta_2_1_10(
60
60
  **kwargs: Any,
61
61
  ) -> Iterable[Validation]:
62
62
  """
63
- EDINET: [FRTA.2.1.10] All extension taxonomy concepts must have a standard label.
63
+ EDINET.EC5710W: [FRTA.2.1.10] All extension taxonomy concepts must have a standard label.
64
64
  """
65
65
  errors = []
66
66
  for concept in val.modelXbrl.qnameConcepts.values():
@@ -70,7 +70,7 @@ def rule_frta_2_1_10(
70
70
  errors.append(concept)
71
71
  if len(errors) > 0:
72
72
  yield Validation.warning(
73
- codes='EDINET.FRTA.2.1.10', # Not associated with EC5710W code.
73
+ codes='EDINET.EC5710W.FRTA.2.1.10',
74
74
  msg=_("All extension taxonomy concepts must have a standard label. "
75
75
  "A standard label is not specified for a concept in an "
76
76
  "extension taxonomy. When adding a concept to an extension taxonomy, "
@@ -180,3 +180,122 @@ def rule_frta_3_1_10(
180
180
  msg=_("Role types defined in the extension taxonomy must have a definition."),
181
181
  modelObject=errors,
182
182
  )
183
+
184
+
185
+ @validation(
186
+ hook=ValidationHook.XBRL_FINALLY,
187
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
188
+ )
189
+ def rule_frta_4_2_2(
190
+ pluginData: PluginValidationDataExtension,
191
+ val: ValidateXbrl,
192
+ *args: Any,
193
+ **kwargs: Any,
194
+ ) -> Iterable[Validation]:
195
+ """
196
+ EDINET.EC5710W: [FRTA.4.2.2] Taxonomy schemas must be defined in XML documents in which the XML Schema 'schema'
197
+ element appears once only as the root element.
198
+ """
199
+ for modelDocument in val.modelXbrl.urlDocs.values():
200
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl):
201
+ continue
202
+ # check for nested Schema declarations which are not allowed.
203
+ schemaElts = {elt for elt in modelDocument.xmlRootElement.iterdescendants(XbrlConst.qnXsdSchema.clarkNotation)}
204
+ if len(schemaElts) > 0:
205
+ yield Validation.warning(
206
+ codes='EDINET.EC5710W.FRTA.4.2.2',
207
+ msg=_("The root of a taxonomy schema file MUST be the XMLSchema element."),
208
+ modelObject=modelDocument,
209
+ )
210
+
211
+
212
+ @validation(
213
+ hook=ValidationHook.XBRL_FINALLY,
214
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
215
+ )
216
+ def rule_frta_4_2_4(
217
+ pluginData: PluginValidationDataExtension,
218
+ val: ValidateXbrl,
219
+ *args: Any,
220
+ **kwargs: Any,
221
+ ) -> Iterable[Validation]:
222
+ """
223
+ EDINET.EC5710W: [FRTA.4.2.4] Taxonomy schemas must declare elementFormDefault to be 'qualified',
224
+ attributeFormDefault must have the value 'unqualified', and the 'form' attribute
225
+ must not appear on element and attribute declarations.
226
+ """
227
+ for modelDocument in val.modelXbrl.urlDocs.values():
228
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl) or not modelDocument.type == ModelDocument.Type.SCHEMA:
229
+ continue
230
+ rootElt = modelDocument.xmlRootElement
231
+ if rootElt.get('elementFormDefault') != 'qualified' or rootElt.get('attributeFormDefault') != 'unqualified':
232
+ yield Validation.warning(
233
+ codes='EDINET.EC5710W.FRTA.4.2.4',
234
+ msg=_("The XMLSchema root in taxonomy schema files must have the 'elementFormDefault' atribute set as "
235
+ "'qulaified' and the 'attributeFormDefault' attribute set as 'unqualified'"),
236
+ modelObject=modelDocument,
237
+ )
238
+ formUsages = []
239
+ for elt in rootElt.iterdescendants([XbrlConst.qnXsdElement.clarkNotation, XbrlConst.qnXsdAttribute.clarkNotation]):
240
+ if elt.get('form') is not None:
241
+ formUsages.append(elt)
242
+ if len(formUsages) > 0:
243
+ yield Validation.warning(
244
+ codes='EDINET.EC5710W.FRTA.4.2.4',
245
+ msg=_("The 'form' attribute is not allowed on 'xsd:element' or 'xsd:attribute' declarations in a schema file"),
246
+ modelObject=formUsages,
247
+ )
248
+
249
+
250
+ @validation(
251
+ hook=ValidationHook.XBRL_FINALLY,
252
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
253
+ )
254
+ def rule_frta_4_2_7(
255
+ pluginData: PluginValidationDataExtension,
256
+ val: ValidateXbrl,
257
+ *args: Any,
258
+ **kwargs: Any,
259
+ ) -> Iterable[Validation]:
260
+ """
261
+ EDINET.EC5710W: [FRTA.4.2.7] A label linkbase should only contain labels defined in a single language.
262
+ """
263
+ for modelDocument in val.modelXbrl.urlDocs.values():
264
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl) or not modelDocument.type == ModelDocument.Type.LINKBASE:
265
+ continue
266
+ usedLangs = {
267
+ elt.get(XbrlConst.qnXmlLang.clarkNotation)
268
+ for elt in modelDocument.xmlRootElement.iterdescendants(XbrlConst.qnLinkLabel.clarkNotation)
269
+ }
270
+ if len(usedLangs) > 1:
271
+ yield Validation.warning(
272
+ codes='EDINET.EC5710W.FRTA.4.2.7',
273
+ msg=_("A label linkbase should only contain labels defined in a single language. This linkbase uses the following languages: %(langs)s"),
274
+ langs=usedLangs,
275
+ modelObject=modelDocument,
276
+ )
277
+
278
+
279
+ @validation(
280
+ hook=ValidationHook.XBRL_FINALLY,
281
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
282
+ )
283
+ def rule_frta_4_2_11(
284
+ pluginData: PluginValidationDataExtension,
285
+ val: ValidateXbrl,
286
+ *args: Any,
287
+ **kwargs: Any,
288
+ ) -> Iterable[Validation]:
289
+ """
290
+ EDINET.EC5710W: [FRTA.4.2.11] Every schema in a DTS must define a non-empty targetNamespace attribute value
291
+ """
292
+ for modelDocument in val.modelXbrl.urlDocs.values():
293
+ if pluginData.isStandardTaxonomyUrl(modelDocument.uri, val.modelXbrl) or not modelDocument.type == ModelDocument.Type.SCHEMA:
294
+ continue
295
+ rootElt = modelDocument.xmlRootElement
296
+ if rootElt.get('targetNamespace') is None or rootElt.get('targetNamespace') == "":
297
+ yield Validation.warning(
298
+ codes='EDINET.EC5710W.FRTA.4.2.11',
299
+ msg=_("Every schema in a DTS must define a non-empty targetNamespace attribute value."),
300
+ modelObject=modelDocument,
301
+ )