arelle-release 2.37.11__py3-none-any.whl → 2.37.13__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 (31) hide show
  1. arelle/CntlrCmdLine.py +1 -66
  2. arelle/ModelDtsObject.py +1 -1
  3. arelle/ModelInstanceObject.py +9 -0
  4. arelle/ModelTestcaseObject.py +1 -1
  5. arelle/PackageManager.py +1 -1
  6. arelle/Validate.py +44 -21
  7. arelle/ValidateFilingText.py +3 -3
  8. arelle/XmlValidate.py +1 -1
  9. arelle/_version.py +2 -2
  10. arelle/formula/XPathParser.py +9 -3
  11. arelle/packages/report/ReportPackage.py +7 -3
  12. arelle/packages/report/ReportPackageValidator.py +4 -3
  13. arelle/plugin/inlineXbrlDocumentSet.py +1 -1
  14. arelle/plugin/validate/CIPC/__init__.py +2 -2
  15. arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py +7 -7
  16. arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +8 -9
  17. arelle/plugin/validate/NL/PluginValidationDataExtension.py +27 -26
  18. arelle/plugin/validate/NL/__init__.py +0 -11
  19. arelle/plugin/validate/NL/rules/nl_kvk.py +60 -0
  20. arelle/plugin/validate/ROS/rules/ros.py +3 -3
  21. arelle/typing.py +8 -1
  22. arelle/utils/EntryPointDetection.py +73 -0
  23. {arelle_release-2.37.11.dist-info → arelle_release-2.37.13.dist-info}/METADATA +1 -1
  24. {arelle_release-2.37.11.dist-info → arelle_release-2.37.13.dist-info}/RECORD +31 -30
  25. {arelle_release-2.37.11.dist-info → arelle_release-2.37.13.dist-info}/WHEEL +1 -1
  26. tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/ArelleGUITest.csproj +1 -1
  27. tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +4 -7
  28. tests/integration_tests/validation/conformance_suite_configurations/xbrl_report_packages_1_0.py +3 -1
  29. {arelle_release-2.37.11.dist-info → arelle_release-2.37.13.dist-info}/entry_points.txt +0 -0
  30. {arelle_release-2.37.11.dist-info → arelle_release-2.37.13.dist-info}/licenses/LICENSE.md +0 -0
  31. {arelle_release-2.37.11.dist-info → arelle_release-2.37.13.dist-info}/top_level.txt +0 -0
arelle/CntlrCmdLine.py CHANGED
@@ -56,6 +56,7 @@ from arelle.RuntimeOptions import RuntimeOptions, RuntimeOptionsException
56
56
  from arelle.SocketUtils import INTERNET_CONNECTIVITY, OFFLINE
57
57
  from arelle.SystemInfo import PlatformOS, getSystemInfo, getSystemWordSize, hasWebServer, isCGI, isGAE
58
58
  from arelle.typing import TypeGetText
59
+ from arelle.utils.EntryPointDetection import filesourceEntrypointFiles
59
60
  from arelle.UrlUtil import isHttpUrl
60
61
  from arelle.ValidateXbrlDTS import ValidateBaseTaxonomiesMode
61
62
  from arelle.WebCache import proxyTuple
@@ -585,72 +586,6 @@ def configAndRunCntlr(options, arellePluginModules):
585
586
  return cntlr
586
587
 
587
588
 
588
- def filesourceEntrypointFiles(filesource, entrypointFiles=None, inlineOnly=False):
589
- if entrypointFiles is None:
590
- entrypointFiles = []
591
- if filesource.isArchive:
592
- if filesource.isTaxonomyPackage: # if archive is also a taxonomy package, activate mappings
593
- filesource.loadTaxonomyPackageMappings()
594
- # HF note: a web api request to load a specific file from archive is ignored, is this right?
595
- del entrypointFiles[:] # clear out archive from entrypointFiles
596
- if reportPackage := filesource.reportPackage:
597
- assert isinstance(filesource.basefile, str)
598
- for report in reportPackage.reports or []:
599
- if report.isInline:
600
- reportEntries = [{"file": f} for f in report.fullPathFiles]
601
- ixdsDiscovered = False
602
- for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
603
- pluginXbrlMethod(filesource, reportEntries)
604
- ixdsDiscovered = True
605
- if not ixdsDiscovered and len(reportEntries) > 1:
606
- raise RuntimeError(_("Loading error. Inline document set encountered. Enable 'InlineXbrlDocumentSet' plug-in to load this filing: {0}").format(filesource.url))
607
- entrypointFiles.extend(reportEntries)
608
- elif not inlineOnly:
609
- entrypointFiles.append({"file": report.fullPathPrimary})
610
- else:
611
- # attempt to find inline XBRL files before instance files, .xhtml before probing others (ESMA)
612
- urlsByType = {}
613
- for _archiveFile in (filesource.dir or ()): # .dir might be none if IOerror
614
- filesource.select(_archiveFile)
615
- identifiedType = ModelDocument.Type.identify(filesource, filesource.url)
616
- if identifiedType in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL, ModelDocument.Type.HTML):
617
- urlsByType.setdefault(identifiedType, []).append(filesource.url)
618
- # use inline instances, if any, else non-inline instances
619
- for identifiedType in ((ModelDocument.Type.INLINEXBRL,) if inlineOnly else (ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INSTANCE)):
620
- for url in urlsByType.get(identifiedType, []):
621
- entrypointFiles.append({"file":url})
622
- if entrypointFiles:
623
- if identifiedType == ModelDocument.Type.INLINEXBRL:
624
- for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
625
- pluginXbrlMethod(filesource, entrypointFiles) # group into IXDS if plugin feature is available
626
- break # found inline (or non-inline) entrypoint files, don't look for any other type
627
- # for ESEF non-consolidated xhtml documents accept an xhtml entry point
628
- if not entrypointFiles and not inlineOnly:
629
- for url in urlsByType.get(ModelDocument.Type.HTML, []):
630
- entrypointFiles.append({"file":url})
631
- if not entrypointFiles and filesource.taxonomyPackage is not None:
632
- for packageEntry in filesource.taxonomyPackage.get('entryPoints', {}).values():
633
- for _resolvedUrl, remappedUrl, _closest in packageEntry:
634
- entrypointFiles.append({"file": remappedUrl})
635
-
636
-
637
- elif os.path.isdir(filesource.url):
638
- del entrypointFiles[:] # clear list
639
- hasInline = False
640
- for _file in os.listdir(filesource.url):
641
- _path = os.path.join(filesource.url, _file)
642
- if os.path.isfile(_path):
643
- identifiedType = ModelDocument.Type.identify(filesource, _path)
644
- if identifiedType == ModelDocument.Type.INLINEXBRL:
645
- hasInline = True
646
- if identifiedType in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL):
647
- entrypointFiles.append({"file":_path})
648
- if hasInline: # group into IXDS if plugin feature is available
649
- for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
650
- pluginXbrlMethod(filesource, entrypointFiles)
651
-
652
- return entrypointFiles
653
-
654
589
  class ParserForDynamicPlugins:
655
590
  def __init__(self, options):
656
591
  self._long_opt = {}
arelle/ModelDtsObject.py CHANGED
@@ -1846,7 +1846,7 @@ class ModelRelationship(ModelObject):
1846
1846
 
1847
1847
  @property
1848
1848
  def orderDecimal(self):
1849
- """(decimal) -- Value of xlink:order attribute, NaN if not convertable to float, or None if not specified"""
1849
+ """(decimal) -- Value of xlink:order attribute, NaN if not convertible to float, or None if not specified"""
1850
1850
  try:
1851
1851
  return decimal.Decimal(self.order)
1852
1852
  except decimal.InvalidOperation:
@@ -795,6 +795,15 @@ class ModelInlineFact(ModelInlineValueObject, ModelFact):
795
795
  for inline root element, the xbrli:xbrl element is substituted for by the inline root element"""
796
796
  return getattr(self, "_ixFactParent") # set by ModelDocument locateFactInTuple for the inline target's root element
797
797
 
798
+ @property
799
+ def isEscaped(self):
800
+ """(bool) -- if true, the fact is escaped"""
801
+ try:
802
+ return self._isEscaped
803
+ except AttributeError:
804
+ self._isEscaped = self.get("escape") in ("true", "1")
805
+ return self._isEscaped
806
+
798
807
  def ixIter(self, childOnly=False):
799
808
  """(ModelObject) -- child elements (tuple facts) of the inline target instance document"""
800
809
  for fact in self.modelTupleFacts:
@@ -158,7 +158,7 @@ class ModelTestcaseVariation(ModelObject):
158
158
  except AttributeError:
159
159
  self._dataUris = defaultdict(list) # may contain instances, schemas, linkbases
160
160
  for dataElement in XmlUtil.descendants(self, None, ("data", "input")):
161
- for elt in XmlUtil.descendants(dataElement, None, ("xsd", "schema", "linkbase", "instance")):
161
+ for elt in XmlUtil.descendants(dataElement, None, ("xsd", "schema", "linkbase", "instance", "taxonomyPackage")):
162
162
  self._dataUris["schema" if elt.localName == "xsd" else elt.localName].append(elt.textValue.strip())
163
163
  return self._dataUris
164
164
 
arelle/PackageManager.py CHANGED
@@ -130,7 +130,7 @@ def _parsePackageMetadata(
130
130
  try:
131
131
  metadataFileContent = filesource.file(metadataFile)[0] # URL in zip, plain file in file system or web
132
132
  tree = _parseFile(cntlr, parser, metadataFile, metadataFileContent, TP_XSD)
133
- except (etree.XMLSyntaxError, etree.DocumentInvalid) as err:
133
+ except (etree.XMLSyntaxError, etree.DocumentInvalid, etree.XMLSchemaError) as err:
134
134
  cntlr.addToLog(_("Taxonomy package file syntax error %(error)s"),
135
135
  messageArgs={"error": str(err)},
136
136
  messageCode="tpe:invalidMetaDataFile",
arelle/Validate.py CHANGED
@@ -1,6 +1,7 @@
1
1
  '''
2
2
  See COPYRIGHT.md for copyright information.
3
3
  '''
4
+ import bisect
4
5
  import fnmatch
5
6
  import os, sys, traceback, logging
6
7
  import time
@@ -25,6 +26,7 @@ from arelle.PluginManager import pluginClassMethods
25
26
  from arelle.packages.report.DetectReportPackage import isReportPackageExtension
26
27
  from arelle.packages.report.ReportPackageValidator import ReportPackageValidator
27
28
  from arelle.rendering import RenderingEvaluator
29
+ from arelle.utils.EntryPointDetection import filesourceEntrypointFiles
28
30
  from arelle.XmlUtil import collapseWhitespace, xmlstring
29
31
 
30
32
  def validate(modelXbrl):
@@ -166,7 +168,6 @@ class Validate:
166
168
  filesource = FileSource.openFileSource(rssItemUrl, self.modelXbrl.modelManager.cntlr)
167
169
  if filesource and not filesource.selection and filesource.isArchive:
168
170
  try:
169
- from arelle.CntlrCmdLine import filesourceEntrypointFiles
170
171
  entrypoints = filesourceEntrypointFiles(filesource)
171
172
  if entrypoints:
172
173
  # resolve an IXDS in entrypoints
@@ -394,13 +395,12 @@ class Validate:
394
395
  filesource.loadTaxonomyPackageMappings(errors=preLoadingErrors, expectTaxonomyPackage=expectTaxonomyPackage)
395
396
  filesource.select(None) # must select loadable reports (not the taxonomy package itself)
396
397
  elif not filesource.isReportPackage:
397
- from arelle.CntlrCmdLine import filesourceEntrypointFiles
398
398
  entrypoints = filesourceEntrypointFiles(filesource)
399
399
  if entrypoints:
400
400
  # resolve an IXDS in entrypoints
401
401
  for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ArchiveIxds"):
402
402
  pluginXbrlMethod(self, filesource,entrypoints)
403
- filesource.select(entrypoints[0].get("file", None) )
403
+ filesource.select(entrypoints[0].get("file", None))
404
404
  except Exception as err:
405
405
  self.modelXbrl.error("exception:" + type(err).__name__,
406
406
  _("Testcase variation validation exception: %(error)s, entry URL: %(instance)s"),
@@ -408,17 +408,20 @@ class Validate:
408
408
  return [] # don't try to load this entry URL
409
409
  if filesource and filesource.isReportPackage and not _rptPkgIxdsOptions:
410
410
  if not reportPackageErrors:
411
- for report in filesource.reportPackage.reports or []:
412
- assert isinstance(filesource.basefile, str)
413
- modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
414
- report.primary,
415
- _("validating"),
416
- useFileSource=filesource,
417
- base=filesource.basefile + "/",
418
- errorCaptureLevel=errorCaptureLevel,
419
- ixdsTarget=modelTestcaseVariation.ixdsTarget,
420
- errors=preLoadingErrors)
421
- loadedModels.append(modelXbrl)
411
+ assert isinstance(filesource.basefile, str)
412
+ if entrypoints := filesourceEntrypointFiles(filesource):
413
+ for pluginXbrlMethod in pluginClassMethods("ModelTestcaseVariation.ArchiveIxds"):
414
+ pluginXbrlMethod(self, filesource, entrypoints)
415
+ for entrypoint in entrypoints:
416
+ filesource.select(entrypoint.get("file", None))
417
+ modelXbrl = ModelXbrl.load(self.modelXbrl.modelManager,
418
+ filesource,
419
+ _("validating"),
420
+ base=filesource.basefile + "/",
421
+ errorCaptureLevel=errorCaptureLevel,
422
+ ixdsTarget=modelTestcaseVariation.ixdsTarget,
423
+ errors=preLoadingErrors)
424
+ loadedModels.append(modelXbrl)
422
425
  else:
423
426
  if _rptPkgIxdsOptions and filesource.isTaxonomyPackage:
424
427
  # Legacy ESEF conformance suite logic.
@@ -492,9 +495,17 @@ class Validate:
492
495
  # validate schema, linkbase, or instance
493
496
  formulaOutputInstance = None
494
497
  modelXbrl = inputDTSes[None][0]
495
- expectedDataFiles = set(modelXbrl.modelManager.cntlr.webCache.normalizeUrl(uri, baseForElement)
496
- for d in modelTestcaseVariation.dataUris.values() for uri in d
497
- if not UrlUtil.isAbsolute(uri))
498
+ expectedDataFiles = set()
499
+ expectedTaxonomyPackages = []
500
+ for localName, d in modelTestcaseVariation.dataUris.items():
501
+ for uri in d:
502
+ if not UrlUtil.isAbsolute(uri):
503
+ normalizedUri = self.modelXbrl.modelManager.cntlr.webCache.normalizeUrl(uri, baseForElement)
504
+ if localName == "taxonomyPackage":
505
+ expectedTaxonomyPackages.append(normalizedUri)
506
+ else:
507
+ expectedDataFiles.add(normalizedUri)
508
+ expectedTaxonomyPackages.sort()
498
509
  foundDataFiles = set()
499
510
  variationBase = os.path.dirname(baseForElement)
500
511
  for dtsName, inputDTS in inputDTSes.items(): # input instances are also parameters
@@ -509,16 +520,28 @@ class Validate:
509
520
  if docUrl.replace("-formula.xml", ".xf") in expectedDataFiles:
510
521
  docUrl = docUrl.replace("-formula.xml", ".xf")
511
522
  foundDataFiles.add(docUrl)
512
- if expectedDataFiles - foundDataFiles:
523
+
524
+ foundDataFilesInTaxonomyPackages = set()
525
+ foundTaxonomyPackages = set()
526
+ for f in foundDataFiles:
527
+ if i := bisect.bisect(expectedTaxonomyPackages, f):
528
+ package = expectedTaxonomyPackages[i-1]
529
+ if f.startswith(package + "/"):
530
+ foundDataFilesInTaxonomyPackages.add(f)
531
+ foundTaxonomyPackages.add(package)
532
+
533
+ expectedNotFound = expectedDataFiles.union(expectedTaxonomyPackages) - foundDataFiles - foundTaxonomyPackages
534
+ if expectedNotFound:
513
535
  modelXbrl.info("arelle:testcaseDataNotUsed",
514
536
  _("Variation %(id)s %(name)s data files not used: %(missingDataFiles)s"),
515
537
  modelObject=modelTestcaseVariation, name=modelTestcaseVariation.name, id=modelTestcaseVariation.id,
516
- missingDataFiles=", ".join(sorted(os.path.basename(f) for f in expectedDataFiles - foundDataFiles)))
517
- if foundDataFiles - expectedDataFiles:
538
+ missingDataFiles=", ".join(sorted(os.path.basename(f) for f in expectedNotFound)))
539
+ foundNotExpected = foundDataFiles - expectedDataFiles - foundDataFilesInTaxonomyPackages
540
+ if foundNotExpected:
518
541
  modelXbrl.info("arelle:testcaseDataUnexpected",
519
542
  _("Variation %(id)s %(name)s files not in variation data: %(unexpectedDataFiles)s"),
520
543
  modelObject=modelTestcaseVariation, name=modelTestcaseVariation.name, id=modelTestcaseVariation.id,
521
- unexpectedDataFiles=", ".join(sorted(os.path.basename(f) for f in foundDataFiles - expectedDataFiles)))
544
+ unexpectedDataFiles=", ".join(sorted(os.path.basename(f) for f in foundNotExpected)))
522
545
  if modelXbrl.hasTableRendering or modelTestcaseVariation.resultIsTable:
523
546
  try:
524
547
  RenderingEvaluator.init(modelXbrl)
@@ -3,7 +3,7 @@ See COPYRIGHT.md for copyright information.
3
3
  '''
4
4
  from __future__ import annotations
5
5
  #import xml.sax, xml.sax.handler
6
- from lxml.etree import XML, DTD, SubElement, _ElementTree, _Comment, _ProcessingInstruction, XMLSyntaxError, XMLParser
6
+ from lxml.etree import XML, DTD, SubElement, _ElementTree, _Comment, _ProcessingInstruction, _Entity, XMLSyntaxError, XMLParser
7
7
  from dataclasses import dataclass
8
8
  from PIL import Image as pilImage
9
9
  import os, io, base64
@@ -604,7 +604,7 @@ def validateTextBlockFacts(modelXbrl):
604
604
  eltTag = elt.tag
605
605
  if isinstance(elt, ModelObject) and elt.namespaceURI == xhtml:
606
606
  eltTag = elt.localName
607
- elif isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction)):
607
+ elif isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction, _Entity)):
608
608
  continue # comment or other non-parsed element
609
609
  else:
610
610
  eltTag = elt.tag
@@ -730,7 +730,7 @@ def validateHtmlContent(modelXbrl, referenceElt, htmlEltTree, validatedObjectLab
730
730
  for elt in htmlEltTree.iter():
731
731
  if isinstance(elt, ModelObject) and elt.namespaceURI == xhtml:
732
732
  eltTag = elt.localName
733
- elif isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction)):
733
+ elif isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction, _Entity)):
734
734
  continue # comment or other non-parsed element
735
735
  else:
736
736
  eltTag = elt.tag
arelle/XmlValidate.py CHANGED
@@ -777,7 +777,7 @@ def lxmlSchemaValidate(modelDocument: ModelDocument, extraSchema : str | None =
777
777
  file=modelDocument.basename,
778
778
  level=logging.ERROR)
779
779
  modelDocument.modelXbrl.errors.append(msgCode)
780
- except etree.XMLSyntaxError as err:
780
+ except (etree.XMLSyntaxError, etree.XMLSchemaError) as err:
781
781
  msgCode = "lxml.schemaError"
782
782
  cntlr.addToLog(_("XML file syntax error %(error)s"),
783
783
  messageArgs={"error": str(err)},
arelle/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '2.37.11'
21
- __version_tuple__ = version_tuple = (2, 37, 11)
20
+ __version__ = version = '2.37.13'
21
+ __version_tuple__ = version_tuple = (2, 37, 13)
@@ -3,6 +3,7 @@ See COPYRIGHT.md for copyright information.
3
3
  '''
4
4
  from __future__ import annotations
5
5
 
6
+ import logging
6
7
  import sys
7
8
  import time
8
9
  import traceback
@@ -906,9 +907,14 @@ def initializeParser(modelManager: ModelManager) -> bool:
906
907
  modelManager.showStatus(_("initializing formula xpath2 grammar"))
907
908
  startedAt = time.time()
908
909
  xpathExpr.parse_string("0", parseAll=True)
909
- modelManager.addToLog(format_string(modelManager.locale,
910
- _("Formula xpath2 grammar initialized in %.2f secs"),
911
- time.time() - startedAt))
910
+ modelManager.addToLog(
911
+ format_string(
912
+ modelManager.locale,
913
+ _("Formula xpath2 grammar initialized in %.2f secs"),
914
+ time.time() - startedAt
915
+ ),
916
+ level=logging.DEBUG
917
+ )
912
918
  modelManager.showStatus(None)
913
919
  isInitialized = True
914
920
  return True # was initialized on this call
@@ -7,10 +7,10 @@ from __future__ import annotations
7
7
  import json
8
8
  import os
9
9
  import zipfile
10
- from collections import defaultdict
10
+ from collections import Counter, defaultdict
11
11
  from dataclasses import dataclass
12
12
  from pathlib import Path, PurePosixPath
13
- from typing import TYPE_CHECKING, Any, Counter, cast
13
+ from typing import TYPE_CHECKING, Any, cast
14
14
 
15
15
  from arelle.packages import PackageUtils
16
16
  from arelle.packages.report import ReportPackageConst as Const
@@ -162,6 +162,10 @@ class ReportEntry:
162
162
  def isTopLevel(self) -> bool:
163
163
  return len(PurePosixPath(self.primary).parts) == 3
164
164
 
165
+ @property
166
+ def dir(self) -> str:
167
+ return PurePosixPath(self.primary).parent.name
168
+
165
169
 
166
170
  class ReportPackage:
167
171
  def __init__(
@@ -204,7 +208,7 @@ class ReportPackage:
204
208
  reports = getAllReportEntries(filesource, stld)
205
209
  if reportPackageJsonFile is None and reports is None:
206
210
  return None
207
- reportEntriesBySubDir = Counter(dir for report in reports or [] if not report.isTopLevel)
211
+ reportEntriesBySubDir = Counter(report.dir for report in reports or [] if not report.isTopLevel)
208
212
  if reports is not None and any(report.isTopLevel for report in reports):
209
213
  reports = [report for report in reports if report.isTopLevel]
210
214
  if any(subdirCount > 1 for subdirCount in reportEntriesBySubDir.values()):
@@ -4,9 +4,10 @@ See COPYRIGHT.md for copyright information.
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
+ from collections import Counter
7
8
  from collections.abc import Generator
8
9
  from pathlib import Path, PurePosixPath
9
- from typing import TYPE_CHECKING, Counter
10
+ from typing import TYPE_CHECKING
10
11
 
11
12
  from arelle.packages import PackageValidation
12
13
  from arelle.packages.PackageType import PackageType
@@ -146,8 +147,8 @@ class ReportPackageValidator:
146
147
  _("Report package must contain at least one report"),
147
148
  )
148
149
  if len(reportEntries) > 1 and not any(report.isTopLevel for report in reportEntries):
149
- byBaseDir = Counter(report.baseDir for report in reportEntries)
150
- if byBaseDir:
150
+ reportEntriesBySubDir = Counter(report.dir for report in reportEntries or [] if not report.isTopLevel)
151
+ if any(subdirCount > 1 for subdirCount in reportEntriesBySubDir.values()):
151
152
  return Validation.error(
152
153
  "rpe:multipleReportsInSubdirectory",
153
154
  _("Report package must contain only one report"),
@@ -131,7 +131,6 @@ import regex as re
131
131
  from lxml.etree import XML, XMLSyntaxError
132
132
 
133
133
  from arelle import FileSource, ModelXbrl, ValidateDuplicateFacts, ValidateXbrlDimensions, XbrlConst
134
- from arelle.CntlrCmdLine import filesourceEntrypointFiles
135
134
  from arelle.FileSource import archiveFilenameParts, archiveFilenameSuffixes
136
135
  from arelle.ModelDocument import ModelDocument, ModelDocumentReference, Type, create, inlineIxdsDiscover, load
137
136
  from arelle.ModelInstanceObject import ModelInlineFootnote
@@ -142,6 +141,7 @@ from arelle.PrototypeDtsObject import ArcPrototype, LocPrototype
142
141
  from arelle.PythonUtil import attrdict, isLegacyAbs
143
142
  from arelle.RuntimeOptions import RuntimeOptions
144
143
  from arelle.UrlUtil import isHttpUrl
144
+ from arelle.utils.EntryPointDetection import filesourceEntrypointFiles
145
145
  from arelle.ValidateDuplicateFacts import DeduplicationType
146
146
  from arelle.ValidateFilingText import CDATApattern
147
147
  from arelle.Version import authorLabel, copyrightLabel
@@ -12,7 +12,7 @@ Taxonomy packages:
12
12
  """
13
13
  import os
14
14
  import regex as re
15
- from lxml.etree import _ElementTree, _Comment, _ProcessingInstruction
15
+ from lxml.etree import _ElementTree, _Comment, _ProcessingInstruction, _Entity
16
16
  from arelle import ModelDocument, XbrlConst
17
17
  from arelle.ModelDtsObject import ModelResource
18
18
  from arelle.ModelInstanceObject import ModelFact, ModelInlineFact, ModelInlineFootnote
@@ -125,7 +125,7 @@ def validateXbrlFinally(val, *args, **kwargs):
125
125
  eltTag = elt.tag
126
126
  if isinstance(elt, ModelObject) and elt.namespaceURI == xhtml:
127
127
  eltTag = elt.localName
128
- elif isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction)):
128
+ elif isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction, _Entity)):
129
129
  continue # comment or other non-parsed element
130
130
  else:
131
131
  eltTag = elt.tag
@@ -11,7 +11,7 @@ from math import isnan
11
11
  from typing import Any, cast
12
12
 
13
13
  import regex as re
14
- from lxml.etree import EntityBase, _Comment, _ElementTree, _ProcessingInstruction
14
+ from lxml.etree import _Comment, _Element, _ElementTree, _Entity, _ProcessingInstruction
15
15
 
16
16
  from arelle import LeiUtil, ModelDocument, XbrlConst
17
17
  from arelle.ModelDtsObject import ModelConcept
@@ -188,12 +188,12 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
188
188
  _baseName, _baseExt = os.path.splitext(doc.basename)
189
189
  if _baseExt not in (".xhtml",".html"):
190
190
  if val.consolidated:
191
- XHTMLExtensionGuidance = "2.6.1"
191
+ errorCode = "ESEF.2.6.1.incorrectFileExtension"
192
192
  reportType = _("Inline XBRL document included within a ESEF report package")
193
193
  else:
194
- XHTMLExtensionGuidance = "4.1.1"
194
+ errorCode = "ESEF.4.1.1.incorrectFileExtension"
195
195
  reportType = _("Stand-alone XHTML document")
196
- modelXbrl.error(f"ESEF.{XHTMLExtensionGuidance}.incorrectFileExtension",
196
+ modelXbrl.error(errorCode,
197
197
  _("%(reportType)s MUST have a .html or .xhtml extension: %(fileName)s"),
198
198
  modelObject=doc, fileName=doc.basename, reportType=reportType)
199
199
  docinfo = doc.xmlRootElement.getroottree().docinfo
@@ -275,7 +275,7 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
275
275
  elt = cast(Any, uncast_elt)
276
276
 
277
277
  eltTag = elt.tag
278
- if isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction, EntityBase)):
278
+ if isinstance(elt, (_Comment, _ElementTree, _Entity, _ProcessingInstruction)):
279
279
  continue # comment or other non-parsed element
280
280
  else:
281
281
  eltTag = elt.tag
@@ -726,12 +726,12 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
726
726
  _("The xlink:role attribute of a link:footnote and link:footnoteLink element as well as xlink:arcrole attribute of a link:footnoteArc MUST be defined in the XBRL Specification 2.1."),
727
727
  modelObject=footnoteRoleErrors)
728
728
 
729
- nonStdFootnoteElts = list()
729
+ nonStdFootnoteElts: list[_Element] = list()
730
730
  for modelLink in modelXbrl.baseSets[("XBRL-footnotes",None,None,None)]:
731
731
  for uncast_elt in modelLink.iterchildren():
732
732
  elt = cast(Any, uncast_elt)
733
733
 
734
- if isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction)):
734
+ if isinstance(elt, (_Comment, _ElementTree, _Entity, _ProcessingInstruction)):
735
735
  continue # comment or other non-parsed element
736
736
  if elt.qname not in FOOTNOTE_LINK_CHILDREN:
737
737
  nonStdFootnoteElts.append(elt)
@@ -12,7 +12,7 @@ from typing import Any, cast
12
12
 
13
13
  import regex as re
14
14
  import tinycss2.ast # type: ignore[import-untyped]
15
- from lxml.etree import EntityBase, _Comment, _ElementTree, _ProcessingInstruction
15
+ from lxml.etree import _Comment, _Element, _ElementTree, _Entity, _ProcessingInstruction
16
16
 
17
17
  from arelle import LeiUtil, ModelDocument, XbrlConst
18
18
  from arelle.ModelDtsObject import ModelConcept
@@ -228,12 +228,12 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
228
228
  _baseName, _baseExt = os.path.splitext(doc.basename)
229
229
  if _baseExt not in (".xhtml",".html"):
230
230
  if val.consolidated:
231
- XHTMLExtensionGuidance = "2.6.1"
231
+ errorCode = "ESEF.2.6.1.incorrectFileExtension"
232
232
  reportType = _("Inline XBRL document included within a ESEF report package")
233
233
  else:
234
- XHTMLExtensionGuidance = "4.1.1"
234
+ errorCode = "ESEF.4.1.1.incorrectFileExtension"
235
235
  reportType = _("Stand-alone XHTML document")
236
- modelXbrl.error(f"ESEF.{XHTMLExtensionGuidance}.incorrectFileExtension",
236
+ modelXbrl.error(errorCode,
237
237
  _("%(reportType)s MUST have a .html or .xhtml extension: %(fileName)s"),
238
238
  modelObject=doc, fileName=doc.basename, reportType=reportType)
239
239
  docinfo = doc.xmlRootElement.getroottree().docinfo
@@ -319,7 +319,7 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
319
319
  elt = cast(Any, uncast_elt)
320
320
 
321
321
  eltTag = elt.tag
322
- if isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction, EntityBase)):
322
+ if isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction, _Entity)):
323
323
  continue # comment or other non-parsed element
324
324
  else:
325
325
  eltTag = elt.tag
@@ -664,8 +664,7 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
664
664
  if esefDisclosureSystemYear >= 2024:
665
665
  if not f.id:
666
666
  factsMissingId.append(f)
667
- escaped = f.get("escape") in ("true", "1")
668
- if f.concept is not None and escaped != f.concept.isTextBlock:
667
+ if isinstance(f, ModelInlineFact) and f.concept is not None and f.isEscaped != f.concept.isTextBlock:
669
668
  modelXbrl.error("ESEF.2.2.7.improperApplicationOfEscapeAttribute",
670
669
  _("Facts with datatype 'dtr-types:textBlockItemType' MUST use the 'escape' attribute set to 'true'. Facts with any other datatype MUST use the 'escape' attribute set to 'false' - fact %(conceptName)s"),
671
670
  modelObject=f, conceptName=f.concept.qname)
@@ -808,12 +807,12 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
808
807
  _("The xlink:role attribute of a link:footnote and link:footnoteLink element as well as xlink:arcrole attribute of a link:footnoteArc MUST be defined in the XBRL Specification 2.1."),
809
808
  modelObject=footnoteRoleErrors)
810
809
 
811
- nonStdFootnoteElts = list()
810
+ nonStdFootnoteElts: list[_Element] = list()
812
811
  for modelLink in modelXbrl.baseSets[("XBRL-footnotes",None,None,None)]:
813
812
  for uncast_elt in modelLink.iterchildren():
814
813
  elt = cast(Any, uncast_elt)
815
814
 
816
- if isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction)):
815
+ if isinstance(elt, (_Comment, _ElementTree, _Entity, _ProcessingInstruction)):
817
816
  continue # comment or other non-parsed element
818
817
  if elt.qname not in FOOTNOTE_LINK_CHILDREN:
819
818
  nonStdFootnoteElts.append(elt)
@@ -3,23 +3,24 @@ See COPYRIGHT.md for copyright information.
3
3
  """
4
4
  from __future__ import annotations
5
5
 
6
- from typing import cast, Any
7
-
8
- import regex as re
9
6
  from collections import defaultdict
10
7
  from dataclasses import dataclass
11
8
  from functools import lru_cache
9
+ from typing import Any, TYPE_CHECKING, cast
10
+
11
+ import regex as re
12
+ from lxml.etree import _Comment, _ElementTree, _Entity, _ProcessingInstruction
12
13
 
13
14
  from arelle.FunctionIxt import ixtNamespaces
14
- from arelle.ModelInstanceObject import ModelUnit, ModelContext, ModelFact, ModelInlineFootnote
15
+ from arelle.ModelInstanceObject import ModelContext, ModelFact, ModelInlineFootnote, ModelUnit
16
+ from arelle.ModelObject import ModelObject
15
17
  from arelle.ModelValue import QName
16
18
  from arelle.ModelXbrl import ModelXbrl
17
- from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
19
+ from arelle.typing import assert_type
18
20
  from arelle.utils.PluginData import PluginData
21
+ from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
19
22
  from arelle.XmlValidate import lexicalPatterns
20
23
 
21
- from lxml.etree import EntityBase, _Comment, _ElementTree, _ProcessingInstruction
22
-
23
24
  XBRLI_IDENTIFIER_PATTERN = re.compile(r"^(?!00)\d{8}$")
24
25
  XBRLI_IDENTIFIER_SCHEMA = 'http://www.kvk.nl/kvk-id'
25
26
 
@@ -38,9 +39,9 @@ class ContextData:
38
39
 
39
40
  @dataclass(frozen=True)
40
41
  class FootnoteData:
42
+ factLangFootnotes: dict[ModelObject, set[str]]
41
43
  noMatchLangFootnotes: set[ModelInlineFootnote]
42
44
  orphanedFootnotes: set[ModelInlineFootnote]
43
- factLangFootnotes: dict[ModelInlineFootnote, set[str]]
44
45
 
45
46
  @dataclass
46
47
  class PluginValidationDataExtension(PluginData):
@@ -105,9 +106,9 @@ class PluginValidationDataExtension(PluginData):
105
106
  def checkFootnotes(self, modelXbrl: ModelXbrl) -> FootnoteData:
106
107
  factLangs = self.factLangs(modelXbrl)
107
108
  footnotesRelationshipSet = modelXbrl.relationshipSet("XBRL-footnotes")
109
+ factLangFootnotes = defaultdict(set)
108
110
  orphanedFootnotes = set()
109
111
  noMatchLangFootnotes = set()
110
- factLangFootnotes = defaultdict(set)
111
112
  for elts in modelXbrl.ixdsEltById.values(): # type: ignore[attr-defined]
112
113
  for elt in elts:
113
114
  if isinstance(elt, ModelInlineFootnote):
@@ -117,14 +118,18 @@ class PluginValidationDataExtension(PluginData):
117
118
  orphanedFootnotes.add(elt)
118
119
  if elt.xmlLang not in factLangs:
119
120
  noMatchLangFootnotes.add(elt)
120
- for rel in footnotesRelationshipSet.toModelObject(elt):
121
- if rel.fromModelObject is not None:
122
- factLangFootnotes[rel.fromModelObject].add(elt.xmlLang)
121
+ if elt.xmlLang is not None:
122
+ for rel in footnotesRelationshipSet.toModelObject(elt):
123
+ if rel.fromModelObject is not None:
124
+ fromObj = cast(ModelObject, rel.fromModelObject)
125
+ lang = cast(str, elt.xmlLang)
126
+ factLangFootnotes[fromObj].add(lang)
123
127
  factLangFootnotes.default_factory = None
128
+ assert_type(factLangFootnotes, defaultdict[ModelObject, set[str]])
124
129
  return FootnoteData(
130
+ factLangFootnotes=cast(dict[ModelObject, set[str]], factLangFootnotes),
125
131
  noMatchLangFootnotes=noMatchLangFootnotes,
126
132
  orphanedFootnotes=orphanedFootnotes,
127
- factLangFootnotes=dict(factLangFootnotes),
128
133
  )
129
134
 
130
135
  @lru_cache(1)
@@ -159,32 +164,28 @@ class PluginValidationDataExtension(PluginData):
159
164
  def getContextsWithSegments(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
160
165
  return self.checkContexts(modelXbrl).contextsWithSegments
161
166
 
167
+ def getFactLangFootnotes(self, modelXbrl: ModelXbrl) -> dict[ModelObject, set[str]]:
168
+ return self.checkFootnotes(modelXbrl).factLangFootnotes
169
+
162
170
  def getNoMatchLangFootnotes(self, modelXbrl: ModelXbrl) -> set[ModelInlineFootnote]:
163
171
  return self.checkFootnotes(modelXbrl).noMatchLangFootnotes
164
172
 
165
173
  def getOrphanedFootnotes(self, modelXbrl: ModelXbrl) -> set[ModelInlineFootnote]:
166
174
  return self.checkFootnotes(modelXbrl).orphanedFootnotes
167
175
 
168
- def getFactLangFootnotes(self, modelXbrl: ModelXbrl) -> dict[ModelInlineFootnote, set[str]]:
169
- return self.checkFootnotes(modelXbrl).factLangFootnotes
170
-
171
176
  @lru_cache(1)
172
177
  def getReportXmlLang(self, modelXbrl: ModelXbrl) -> str | None:
173
- firstIxdsDoc = True
174
178
  reportXmlLang = None
175
179
  firstRootmostXmlLangDepth = 9999999
176
- for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
177
- for uncast_elt, depth in etreeIterWithDepth(ixdsHtmlRootElt):
178
- elt = cast(Any, uncast_elt)
179
- eltTag = elt.tag
180
- if isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction, EntityBase)):
180
+ if modelXbrl.ixdsHtmlElements:
181
+ ixdsHtmlRootElt = modelXbrl.ixdsHtmlElements[0]
182
+ for elt, depth in etreeIterWithDepth(ixdsHtmlRootElt):
183
+ if isinstance(elt, (_Comment, _ElementTree, _Entity, _ProcessingInstruction)):
181
184
  continue
182
- if firstIxdsDoc and (not reportXmlLang or depth < firstRootmostXmlLangDepth):
183
- xmlLang = elt.get("{http://www.w3.org/XML/1998/namespace}lang")
184
- if xmlLang:
185
+ if not reportXmlLang or depth < firstRootmostXmlLangDepth:
186
+ if xmlLang := elt.get("{http://www.w3.org/XML/1998/namespace}lang"):
185
187
  reportXmlLang = xmlLang
186
188
  firstRootmostXmlLangDepth = depth
187
- firstIxdsDoc = False
188
189
  return reportXmlLang
189
190
 
190
191
  @lru_cache(1)
@@ -48,16 +48,6 @@ def validateXbrlFinally(*args: Any, **kwargs: Any) -> None:
48
48
  return validationPlugin.validateXbrlFinally(*args, **kwargs)
49
49
 
50
50
 
51
- def modelTestcaseVariationReportPackageIxdsOptions(
52
- val: ValidateXbrl,
53
- rptPkgIxdsOptions: dict[str, bool],
54
- *args: Any,
55
- **kwargs: Any,
56
- ) -> None:
57
- rptPkgIxdsOptions["lookOutsideReportsDirectory"] = True
58
- rptPkgIxdsOptions["combineIntoSingleIxds"] = True
59
-
60
-
61
51
  __pluginInfo__ = {
62
52
  "name": PLUGIN_NAME,
63
53
  "version": "0.0.1",
@@ -70,5 +60,4 @@ __pluginInfo__ = {
70
60
  "DisclosureSystem.ConfigURL": disclosureSystemConfigURL,
71
61
  "ModelXbrl.LoadComplete": modelXbrlLoadComplete,
72
62
  "Validate.XBRL.Finally": validateXbrlFinally,
73
- "ModelTestcaseVariation.ReportPackageIxdsOptions": modelTestcaseVariationReportPackageIxdsOptions,
74
63
  }
@@ -356,6 +356,35 @@ def rule_nl_kvk_3_2_4_2 (
356
356
  )
357
357
 
358
358
 
359
+ @validation(
360
+ hook=ValidationHook.XBRL_FINALLY,
361
+ disclosureSystems=[
362
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
363
+ ],
364
+ )
365
+ def rule_nl_kvk_3_2_7_1 (
366
+ pluginData: PluginValidationDataExtension,
367
+ val: ValidateXbrl,
368
+ *args: Any,
369
+ **kwargs: Any,
370
+ ) -> Iterable[Validation]:
371
+ """
372
+ NL-KVK.3.2.7.1: Ensure that any block-tagged facts of type textBlockItemType are assigned @escape="true",
373
+ while other data types (e.g., xbrli:stringItemType) are assigned @escape="false".
374
+ """
375
+ improperlyEscapedFacts = []
376
+ for fact in val.modelXbrl.facts:
377
+ if isinstance(fact, ModelInlineFact) and fact.concept is not None and fact.isEscaped != fact.concept.isTextBlock:
378
+ improperlyEscapedFacts.append(fact)
379
+ if len(improperlyEscapedFacts) >0:
380
+ yield Validation.error(
381
+ codes='NL.NL-KVK.3.2.7.1.improperApplicationOfEscapeAttribute',
382
+ msg=_('Ensure that any block-tagged facts of type textBlockItemType are assigned @escape="true",'
383
+ 'while other data types (e.g., xbrli:stringItemType) are assigned @escape="false".'),
384
+ modelObject = improperlyEscapedFacts
385
+ )
386
+
387
+
359
388
  @validation(
360
389
  hook=ValidationHook.XBRL_FINALLY,
361
390
  disclosureSystems=[
@@ -429,6 +458,37 @@ def rule_nl_kvk_3_3_1_3 (
429
458
  )
430
459
 
431
460
 
461
+ @validation(
462
+ hook=ValidationHook.XBRL_FINALLY,
463
+ disclosureSystems=[
464
+ DISCLOSURE_SYSTEM_NL_INLINE_2024
465
+ ],
466
+ )
467
+ def rule_nl_kvk_3_5_2_1(
468
+ pluginData: PluginValidationDataExtension,
469
+ val: ValidateXbrl,
470
+ *args: Any,
471
+ **kwargs: Any,
472
+ ) -> Iterable[Validation]:
473
+ """
474
+ NL-KVK.3.5.2.1: Each tagged text fact MUST have the ‘xml:lang’ attribute assigned or inherited.
475
+ """
476
+ factsWithoutLang = []
477
+ for fact in val.modelXbrl.facts:
478
+ if (fact is not None and
479
+ fact.concept is not None and
480
+ fact.concept.type is not None and
481
+ fact.concept.type.isOimTextFactType and
482
+ not fact.xmlLang):
483
+ factsWithoutLang.append(fact)
484
+ if len(factsWithoutLang) > 0:
485
+ yield Validation.error(
486
+ codes='NL.NL-KVK.3.5.2.1.undefinedLanguageForTextFact',
487
+ msg=_('Each tagged text fact MUST have the ‘xml:lang’ attribute assigned or inherited.'),
488
+ modelObject=factsWithoutLang
489
+ )
490
+
491
+
432
492
  @validation(
433
493
  hook=ValidationHook.XBRL_FINALLY,
434
494
  disclosureSystems=[
@@ -13,7 +13,7 @@ from arelle.typing import TypeGetText
13
13
  from arelle.ValidateXbrl import ValidateXbrl
14
14
  from collections import defaultdict
15
15
  from math import isnan
16
- from lxml.etree import _ElementTree, _Comment, _ProcessingInstruction
16
+ from lxml.etree import _Comment, _ElementTree, _Entity, _ProcessingInstruction
17
17
  from arelle import ModelDocument
18
18
  from arelle.ModelInstanceObject import ModelInlineFact, ModelUnit
19
19
  from arelle.ModelValue import qname
@@ -86,12 +86,12 @@ def rule_main(
86
86
  ixTargets = set()
87
87
  for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
88
88
  for elt in ixdsHtmlRootElt.iter():
89
- if isinstance(elt, (_ElementTree, _Comment, _ProcessingInstruction)):
89
+ if isinstance(elt, (_Comment, _ElementTree, _Entity, _ProcessingInstruction)):
90
90
  continue # comment or other non-parsed element
91
91
  if isinstance(elt, ModelInlineFact):
92
92
  if elt.format is not None and elt.format.namespaceURI not in TR_NAMESPACES:
93
93
  transformRegistryErrors.add(elt)
94
- if elt.get("escape") in ("true","1"):
94
+ if elt.isEscaped:
95
95
  modelXbrl.error("ROS.escapedHTML",
96
96
  _("Escaped (x)html fact content is not supported: %(element)s"),
97
97
  modelObject=elt, element=eltTag)
arelle/typing.py CHANGED
@@ -5,7 +5,14 @@ Type hints for Arelle.
5
5
  from __future__ import annotations
6
6
 
7
7
  from collections.abc import Callable
8
- from typing import TypedDict, TypeVar # pylint: disable=no-name-in-module
8
+ from typing import Any, TypedDict, TypeVar # pylint: disable=no-name-in-module
9
+
10
+ try:
11
+ from typing import assert_type as assert_type
12
+ except ImportError:
13
+ T = TypeVar('T')
14
+ def assert_type(x: T, _: Any, /) -> T:
15
+ return x
9
16
 
10
17
  TypeGetText = Callable[[str], str]
11
18
 
@@ -0,0 +1,73 @@
1
+ import os
2
+
3
+ from arelle import (
4
+ ModelDocument,
5
+ PluginManager,
6
+ )
7
+
8
+
9
+ def filesourceEntrypointFiles(filesource, entrypointFiles=None, inlineOnly=False):
10
+ if entrypointFiles is None:
11
+ entrypointFiles = []
12
+ if filesource.isArchive:
13
+ if filesource.isTaxonomyPackage: # if archive is also a taxonomy package, activate mappings
14
+ filesource.loadTaxonomyPackageMappings()
15
+ # HF note: a web api request to load a specific file from archive is ignored, is this right?
16
+ del entrypointFiles[:] # clear out archive from entrypointFiles
17
+ if reportPackage := filesource.reportPackage:
18
+ assert isinstance(filesource.basefile, str)
19
+ for report in reportPackage.reports or []:
20
+ if report.isInline:
21
+ reportEntries = [{"file": f} for f in report.fullPathFiles]
22
+ ixdsDiscovered = False
23
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
24
+ pluginXbrlMethod(filesource, reportEntries)
25
+ ixdsDiscovered = True
26
+ if not ixdsDiscovered and len(reportEntries) > 1:
27
+ raise RuntimeError(_("Loading error. Inline document set encountered. Enable 'InlineXbrlDocumentSet' plug-in to load this filing: {0}").format(filesource.url))
28
+ entrypointFiles.extend(reportEntries)
29
+ elif not inlineOnly:
30
+ entrypointFiles.append({"file": report.fullPathPrimary})
31
+ else:
32
+ # attempt to find inline XBRL files before instance files, .xhtml before probing others (ESMA)
33
+ urlsByType = {}
34
+ for _archiveFile in (filesource.dir or ()): # .dir might be none if IOerror
35
+ filesource.select(_archiveFile)
36
+ identifiedType = ModelDocument.Type.identify(filesource, filesource.url)
37
+ if identifiedType in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL, ModelDocument.Type.HTML):
38
+ urlsByType.setdefault(identifiedType, []).append(filesource.url)
39
+ # use inline instances, if any, else non-inline instances
40
+ for identifiedType in ((ModelDocument.Type.INLINEXBRL,) if inlineOnly else (ModelDocument.Type.INLINEXBRL, ModelDocument.Type.INSTANCE)):
41
+ for url in urlsByType.get(identifiedType, []):
42
+ entrypointFiles.append({"file":url})
43
+ if entrypointFiles:
44
+ if identifiedType == ModelDocument.Type.INLINEXBRL:
45
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
46
+ pluginXbrlMethod(filesource, entrypointFiles) # group into IXDS if plugin feature is available
47
+ break # found inline (or non-inline) entrypoint files, don't look for any other type
48
+ # for ESEF non-consolidated xhtml documents accept an xhtml entry point
49
+ if not entrypointFiles and not inlineOnly:
50
+ for url in urlsByType.get(ModelDocument.Type.HTML, []):
51
+ entrypointFiles.append({"file":url})
52
+ if not entrypointFiles and filesource.taxonomyPackage is not None:
53
+ for packageEntry in filesource.taxonomyPackage.get('entryPoints', {}).values():
54
+ for _resolvedUrl, remappedUrl, _closest in packageEntry:
55
+ entrypointFiles.append({"file": remappedUrl})
56
+
57
+
58
+ elif os.path.isdir(filesource.url):
59
+ del entrypointFiles[:] # clear list
60
+ hasInline = False
61
+ for _file in os.listdir(filesource.url):
62
+ _path = os.path.join(filesource.url, _file)
63
+ if os.path.isfile(_path):
64
+ identifiedType = ModelDocument.Type.identify(filesource, _path)
65
+ if identifiedType == ModelDocument.Type.INLINEXBRL:
66
+ hasInline = True
67
+ if identifiedType in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL):
68
+ entrypointFiles.append({"file":_path})
69
+ if hasInline: # group into IXDS if plugin feature is available
70
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
71
+ pluginXbrlMethod(filesource, entrypointFiles)
72
+
73
+ return entrypointFiles
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arelle-release
3
- Version: 2.37.11
3
+ Version: 2.37.13
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License: Apache-2.0
@@ -1,7 +1,7 @@
1
1
  arelle/Aspect.py,sha256=Pn9I91D1os1RTVj6htuxTfRzVMhmVDtrbKvV_zy9xMI,5470
2
2
  arelle/BetaFeatures.py,sha256=T_tPac-FiozHyYLCemt0RoHJ1JahUE71L-0tHmIRKpE,858
3
3
  arelle/Cntlr.py,sha256=sf5Xe19t5E0wKzhdlXl1p5r6gMtCmPhYAi8RVY0jz7Y,30449
4
- arelle/CntlrCmdLine.py,sha256=-V3daLdYaDRqLTnJ8VYHkaYfvFEZURodCuh1kqNcPO0,94194
4
+ arelle/CntlrCmdLine.py,sha256=sax5n2qmqaTgucMc6TqDlSzNSWJLgzZqrh34B076faE,89969
5
5
  arelle/CntlrComServer.py,sha256=h1KPf31uMbErpxTZn_iklDqUMGFgQnjZkFkFjd8gtLQ,1888
6
6
  arelle/CntlrProfiler.py,sha256=2VQJudiUhxryVypxjODx2ccP1-n60icTiWs5lSEokhQ,972
7
7
  arelle/CntlrQuickBooks.py,sha256=BMqd5nkNQOZyNFPefkTeWUUDCYNS6BQavaG8k1Lepu4,31543
@@ -35,9 +35,9 @@ arelle/LeiUtil.py,sha256=tSPrbQrXEeH5pXgGA_6MAdgMZp20NaW5izJglIXyEQk,5095
35
35
  arelle/LocalViewer.py,sha256=WVrfek_bLeFFxgWITi1EQb6xCQN8O9Ks-ZL16vRncSk,3080
36
36
  arelle/Locale.py,sha256=aKC1Uaen_dbPGb92kZa_yUoo7On_QtWlvr5H_F9BNXg,33008
37
37
  arelle/ModelDocument.py,sha256=Sq6umEdn-aNHjxIpEsXTT7A4V25nGY0JiylSnhr9zSI,130749
38
- arelle/ModelDtsObject.py,sha256=JXPRiFOsbB5tZjEDc6rECuUtXMbF4oxfnwrQvKo-i5U,88656
38
+ arelle/ModelDtsObject.py,sha256=nvHQs4BDmPxY6mqLiBuqIGRJXyA1EqOEGB2f3S6A6w4,88656
39
39
  arelle/ModelFormulaObject.py,sha256=beUSxEFm7aoa9iimmvXLYCHdizAtOmhDqk6wmvbc9Zg,122537
40
- arelle/ModelInstanceObject.py,sha256=pAcwQBr85_fQCGT18JSOGGwzAZ3J-oWIU9sj9UUXLOk,73928
40
+ arelle/ModelInstanceObject.py,sha256=JqULoUliBscwWJa7NskIhNVxBqax2ImOSIh0tH6_7q0,74201
41
41
  arelle/ModelManager.py,sha256=QUNcD2LC_YyyGFU8bFTSuzIGI1qpOK55KBlQ697Ep1I,11075
42
42
  arelle/ModelObject.py,sha256=Rttkhv-PtfneZyDYsG5FDh98BzT97ameTmwNdqFaOv0,18657
43
43
  arelle/ModelObjectFactory.py,sha256=XuNF4Re3p00tODCdyspfar_DNCXfARqCaLEkntgAZ0g,8750
@@ -45,12 +45,12 @@ arelle/ModelRelationshipSet.py,sha256=_1T3NAS0IRgK8IWFe7nh-qxXZ7htA80i_dueyU8JYa
45
45
  arelle/ModelRenderingObject.py,sha256=iPhSUlSBG-FLzAfIdUW06UZDgTCaZJ4K2mxvAtSe2BU,76021
46
46
  arelle/ModelRssItem.py,sha256=GzFkmluOlFsVcrxn9HAyOAcuE7rcHUOGkp4Q6F2IlT8,7713
47
47
  arelle/ModelRssObject.py,sha256=xjuwyJ8pU5sQmNPJFQakDEEnujZg2bMCTaj3zVezHL8,992
48
- arelle/ModelTestcaseObject.py,sha256=qWSphg4BX8HMcmEt_IJ8pS_uU1G7XeIldTshEpAi0GY,21873
48
+ arelle/ModelTestcaseObject.py,sha256=zXaN5IbrbnGhuZOcc6JpJmJaMZlpcHYmb4yA7TTto_I,21892
49
49
  arelle/ModelValue.py,sha256=6Vko4aytXg2Ajv7rI6houQb-ZX39-tcjQ4N90ZxZvE8,39430
50
50
  arelle/ModelVersObject.py,sha256=cPD1IzhkCfuV1eMgVFWes88DH_6WkUj5kj7sgGF2M0I,26062
51
51
  arelle/ModelVersReport.py,sha256=bXEA9K3qkH57aABn5l-m3CTY0FAcF1yX6O4fo-URjl8,73326
52
52
  arelle/ModelXbrl.py,sha256=7rz4rxIGopwRDQTD12P0sdqzvPPoMhGgkg5qkMD6TDQ,72109
53
- arelle/PackageManager.py,sha256=B68B_3sUdy5rhi2HEKQwkTC1DmHAbJGEc8ewkTl4Gnw,32570
53
+ arelle/PackageManager.py,sha256=BvPExMcxh8rHMxogOag-PGbX6vXdhCiXAHcDLA6Ypsc,32592
54
54
  arelle/PluginManager.py,sha256=foSgWvRI1Ret-6KVRQMFSv4RtpEf_0UB7468N_NjPGU,42116
55
55
  arelle/PluginUtils.py,sha256=0vFQ29wVVpU0cTY3YOBL6FhNQhhCTwShBH4qTJGLnvc,2426
56
56
  arelle/PrototypeDtsObject.py,sha256=0lf60VcXR_isx57hBPrc7vEMkFpYkVuK4JVBSmopzkQ,7989
@@ -65,9 +65,9 @@ arelle/UITkTable.py,sha256=N83cXi5c0lLZLsDbwSKcPrlYoUoGsNavGN5YRx6d9XY,39810
65
65
  arelle/UiUtil.py,sha256=3G0xPclZI8xW_XQDbiFrmylB7Nd5muqi5n2x2oMkMZU,34218
66
66
  arelle/Updater.py,sha256=ho8Z_9GOL39H1jHL3Gaw5uc6av7J8ZBB6dR_X-nF_e0,7124
67
67
  arelle/UrlUtil.py,sha256=HrxZSG59EUMGMMGmWPuZkPi5-0BGqY3jAMkp7V4IdZo,32400
68
- arelle/Validate.py,sha256=_7lDoGtUCyHgWK1Ak375D-kuPBZmDCNfSr_wsTLq10k,55328
68
+ arelle/Validate.py,sha256=PWTfO6YpF2KMdImnqSLTQ1WBSMJjAonaNNM3ZdeV_Dk,56380
69
69
  arelle/ValidateDuplicateFacts.py,sha256=074y-VWCOBHoi6iV6wDL_IXBtdz9oeI1uPvjEcC1oDs,21717
70
- arelle/ValidateFilingText.py,sha256=qBDrS3O9xtvGLn8Qfmjedg4iaClmeDA-ti7KM4JXY0A,54024
70
+ arelle/ValidateFilingText.py,sha256=xnXc0xgdNiHQk0eyP7VSSpvw7qr-pRFRwqqoUb569is,54051
71
71
  arelle/ValidateInfoset.py,sha256=Rz_XBi5Ha43KpxXYhjLolURcWVx5qmqyjLxw48Yt9Dg,20396
72
72
  arelle/ValidateUtr.py,sha256=oxOPrOa1XEzBay4miXvx6eRLTnVFYUIJC9ueWUk4EkI,13633
73
73
  arelle/ValidateVersReport.py,sha256=RMe7GlcyZV0HoVFHL0qOGrKm4et-6yPq5dmikkhnvoU,43196
@@ -118,13 +118,13 @@ arelle/XbrlConst.py,sha256=YDvnf0gQ3IY5v07d8wxAHTxDmvcHIpl2mSMZeTgvKmk,56695
118
118
  arelle/XbrlUtil.py,sha256=s2Vmrh-sZI5TeuqsziKignOc3ao-uUgnCNoelP4dDj0,9212
119
119
  arelle/XhtmlValidate.py,sha256=0gtm7N-kXK0RB5o3c1AQXjfFuRp1w2fKZZAeyruNANw,5727
120
120
  arelle/XmlUtil.py,sha256=1VToOOylF8kbEorEdZLThmq35j9bmuF_DS2q9NthnHU,58774
121
- arelle/XmlValidate.py,sha256=TL72yUQA0PqdcFgw7rW8uxUWw6i1pN7q6V42Uk6gMYY,45857
121
+ arelle/XmlValidate.py,sha256=5tXC60dy3aI1sSoGp7rbB-nix_AB3q_nonbOPwMglNg,45881
122
122
  arelle/XmlValidateConst.py,sha256=U_wN0Q-nWKwf6dKJtcu_83FXPn9c6P8JjzGA5b0w7P0,338
123
123
  arelle/XmlValidateParticles.py,sha256=Mn6vhFl0ZKC_vag1mBwn1rH_x2jmlusJYqOOuxFPO2k,9231
124
124
  arelle/XmlValidateSchema.py,sha256=6frtZOc1Yrx_5yYF6V6oHbScnglWrVbWr6xW4EHtLQI,7428
125
125
  arelle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
126
- arelle/_version.py,sha256=UX5PNNTrOLUsl7iAia9CpK-Esl9BSjjx3ISlTR1ywcY,515
127
- arelle/typing.py,sha256=Ct5lrNKRow_o9CraMEXNza8nFsJ_iGIKoUeGfPs2dxI,1084
126
+ arelle/_version.py,sha256=dKIkYkYWE9hq9__IcXa7wxMMqFtErf0UfXfBI2C4PIM,515
127
+ arelle/typing.py,sha256=PRe-Fxwr2SBqYYUVPCJ3E7ddDX0_oOISNdT5Q97EbRM,1246
128
128
  arelle/api/Session.py,sha256=O8zpg7MJys9uxwwHf8OsSlZxpPdq7A3ONyY39Q4A3Kc,6218
129
129
  arelle/archive/CustomLogger.py,sha256=v_JXOCQLDZcfaFWzxC9FRcEf9tQi4rCI4Sx7jCuAVQI,1231
130
130
  arelle/archive/LoadEFMvalidate.py,sha256=HR1ZJmOvWGUlWEsWd0tGCa2TTtZSNzeL6tgN1TFfrl0,986
@@ -231,7 +231,7 @@ arelle/formula/FormulaConsisAsser.py,sha256=hO4GZwozM5cGl1xTU6OwoF3LlaMxAEB5Oy0r
231
231
  arelle/formula/FormulaEvaluator.py,sha256=WKNyJz1Os9gsKedJXLNC9y9u11Ea4_JQ-RAI7gSFmPU,82600
232
232
  arelle/formula/ValidateFormula.py,sha256=b_stG7h8RhaSsPt07_x-GRBHOl2uy-JNSMd6v-jkg_w,95942
233
233
  arelle/formula/XPathContext.py,sha256=JerF1suUL9RcKRFeF6kXZXGkuw6yaMb6gijNacrqugU,49386
234
- arelle/formula/XPathParser.py,sha256=vqG2dj0yXVPZpIBsY2rxDIAFC376GSye4CLHfjVyhyM,50321
234
+ arelle/formula/XPathParser.py,sha256=GWQuxrMzMl5uNMSZEnNHPFaynZljxkpYsJdRZiz2jB0,50381
235
235
  arelle/formula/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
236
236
  arelle/images/arelle-full-word.ico,sha256=jsAzyAJZTtVPafxhgFQtdWJj7r_r0YhX_iWvWnZ4QKg,2430
237
237
  arelle/images/arelle-mac-icon-4.gif,sha256=jTXc1dBEgZuXuZVd1XOuLuXfpjNW_pusn0mPhHhkOtk,2619
@@ -302,9 +302,9 @@ arelle/packages/PackageType.py,sha256=2s29OWZ-XpKW1bPJ1kVBcpKMDBr9gzLe25Cukg-YTE
302
302
  arelle/packages/PackageUtils.py,sha256=uraFfkyYQVlY8YdK4j-HgxhkIAOsEaU5Mk4To0ymKxE,575
303
303
  arelle/packages/PackageValidation.py,sha256=y0J6EAR5O8fF51vIrj-2Ur42TObIMvHVFtPXTR-GGOc,7408
304
304
  arelle/packages/report/DetectReportPackage.py,sha256=AemOF0eDbnCR3n6cNTWDb93FttQ18s3jsNQuA-37zM4,305
305
- arelle/packages/report/ReportPackage.py,sha256=8Bwg5scZTjv4qhI6aXCjrR-Mzg8iyAMiNoqeSZVRSAs,9836
305
+ arelle/packages/report/ReportPackage.py,sha256=_W9Z3u9WEBFJhQAgMAW4Y06bOTydk9F-Il-YNmvWBvc,9939
306
306
  arelle/packages/report/ReportPackageConst.py,sha256=nmHRfMZDc1PzxjTlOUi6SVp0QWxI62cywCY2q6CNadQ,2682
307
- arelle/packages/report/ReportPackageValidator.py,sha256=qsFLUYSMscv7w4khjGHO5n9dT3iMMM9aj2cWmANVGwA,10199
307
+ arelle/packages/report/ReportPackageValidator.py,sha256=3Ur_CXUtCPtXzUgDi9t3VI3vcew0I9pq2B-cn_rIkX4,10322
308
308
  arelle/plugin/CacheBuilder.py,sha256=-aDFD3rx83glOprQYO-8gsaIEXcdwB6PFfIq7jy20lo,4489
309
309
  arelle/plugin/EdgarRendererAllReports.py,sha256=V3AeDj29U1XbnFGUO30kAvZtWzDH5G-teyzoJE0HDU0,5031
310
310
  arelle/plugin/SECCorrespondenceLoader.py,sha256=dX3k4uI5SOKR-8zpv1Xk4X34eDQMPaWFS8R2wf8WTNs,9561
@@ -314,7 +314,7 @@ arelle/plugin/formulaLoader.py,sha256=_pPZQPAZeNjGj85rvH7QRl4gEjYD7Yhxl1JhuV9wOo
314
314
  arelle/plugin/formulaSaver.py,sha256=STlKyDA-pVUxZoEW57MSu74RdpyHVTxaHvOZyOt0cyg,31385
315
315
  arelle/plugin/formulaXPathChecker.py,sha256=sEEeLHx17XSj8eOgFdzYLBp9ZFk2UUYLOEKtaF_pq34,18795
316
316
  arelle/plugin/functionsMath.py,sha256=Z8N7ok3w1aOusCQA9QvqYwQ8W1j80bb-_4lVclBnNQM,9037
317
- arelle/plugin/inlineXbrlDocumentSet.py,sha256=wdlEg9OLm81E_aOINeDsPVHi03_v-dC7F9HrqmrF9e8,55256
317
+ arelle/plugin/inlineXbrlDocumentSet.py,sha256=mXQkqKhwizuQsXPzXsdHMxKVayQxCA86MF0gITogplI,55269
318
318
  arelle/plugin/loadFromExcel.py,sha256=galvvaj9jTKMMRUasCSh1SQnCCBzoN_HEpYWv0fmUdM,124407
319
319
  arelle/plugin/loadFromOIM.py,sha256=dJHnX56bmuY40f6vRMsQ7pJmIWcB5N_3jmYWGGnZSdM,903
320
320
  arelle/plugin/profileCmdLine.py,sha256=uLL0fGshpiwtzyLKAtW0WuXAvcRtZgxQG6swM0e4BHA,2370
@@ -345,7 +345,7 @@ arelle/plugin/security/cryptAES_CBC.py,sha256=S94AdMqu4jdLrprl0FLT2w7tG6IgxTGxRf
345
345
  arelle/plugin/security/cryptAES_EAX.py,sha256=TAL_kpu_2WMMpHOWrxA8Y7UuTAcbbTY6DK0VYQZGWF0,5952
346
346
  arelle/plugin/transforms/tester.py,sha256=57relfBci8FttRSxHtdUaxlaQPrBhJglssImDecQPow,12501
347
347
  arelle/plugin/validate/CIPC/Const.py,sha256=GSiODyiK8V9P-pV0_DPEKYAhe2wqgcYJP2Qt6xaIyA4,11425
348
- arelle/plugin/validate/CIPC/__init__.py,sha256=OMLc0DgKulsyQlVhU9Wjlt_1VMpNJiUWBH16KV6TLtA,14681
348
+ arelle/plugin/validate/CIPC/__init__.py,sha256=R6KVETICUpfW--TvVkFNDo-67Kq_KpWz3my2ECkiKxM,14699
349
349
  arelle/plugin/validate/CIPC/config.xml,sha256=4pyn40JAvQQeoRC8I046gZ4ZcmUnekX3TNfYpC5yonI,667
350
350
  arelle/plugin/validate/DBA/DisclosureSystems.py,sha256=Dp_r-Pa3tahtCfDha2Zc97N0iyrY4Zagb8w2D9ErILg,294
351
351
  arelle/plugin/validate/DBA/PluginValidationDataExtension.py,sha256=uDSu-xtKExJvlB5qNU4RXIorb4dbgh_Q8Ss_FbJ1RVg,6832
@@ -366,11 +366,11 @@ arelle/plugin/validate/ESEF/Util.py,sha256=QH3btcGqBpr42M7WSKZLSdNXygZaZLfEiEjlx
366
366
  arelle/plugin/validate/ESEF/__init__.py,sha256=LL7uYOcGPHgjwTlcfW2oWMqWiqrZ5yABzcKkJZFrZis,20391
367
367
  arelle/plugin/validate/ESEF/ESEF_2021/DTS.py,sha256=6Za7BANwwc_egxLCgbgWzwUGOXZv9IF1I7JCkDNt2Tw,26277
368
368
  arelle/plugin/validate/ESEF/ESEF_2021/Image.py,sha256=4bnhuy5viBU0viPjb4FhcRRjVVKlNdnKLFdSGg3sZvs,4871
369
- arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py,sha256=wrIjd1XsA3iAGwlULca4LxrEaeDj5vB7aldyPG9ycZE,62871
369
+ arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py,sha256=v7T51hIWHIFYHnf6RrstnZOTVUUfMaibbXUxoBJK-yc,62884
370
370
  arelle/plugin/validate/ESEF/ESEF_2021/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
371
371
  arelle/plugin/validate/ESEF/ESEF_Current/DTS.py,sha256=epp-PBh1NJzQqgxUE6C468HmoDc2w3j54rMwfiOAry4,29334
372
372
  arelle/plugin/validate/ESEF/ESEF_Current/Image.py,sha256=w36sCTy8QbsuKABjkK6PTWce2A4zFN_rMnEM2wi5WEc,11364
373
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py,sha256=aP4tVQudMAXDXLD3M121BAfQ1DtH2dox6kdBvhlyDho,73157
373
+ arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py,sha256=EJF5dKLPntwYdLUBqwKJ0-A22zhSVDKmDwYb9r8zCA4,73146
374
374
  arelle/plugin/validate/ESEF/ESEF_Current/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
375
375
  arelle/plugin/validate/ESEF/resources/authority-validations.json,sha256=JriLZ45KmUYlQiPbXJCAahobqdrst64Ay77bofZhB5Q,14940
376
376
  arelle/plugin/validate/ESEF/resources/config.xml,sha256=t3STU_-QYM7Ay8YwZRPapnohiWVWhjfr4L2Rjx9xN9U,3902
@@ -378,16 +378,16 @@ arelle/plugin/validate/FERC/__init__.py,sha256=V4fXcFKBsjFFPs9_1NhvDjWpEQCoQM0tR
378
378
  arelle/plugin/validate/FERC/config.xml,sha256=bn9b8eCqJA1J62rYq1Nz85wJrMGAahVmmnIUQZyerjo,1919
379
379
  arelle/plugin/validate/FERC/resources/ferc-utr.xml,sha256=OCRj9IUpdXATCBXKbB71apYx9kxcNtZW-Hq4s-avsRY,2663
380
380
  arelle/plugin/validate/NL/DisclosureSystems.py,sha256=kTjpxkgwn58wHCbaLRBInirOy-2cpK9MLWEFJ_193y4,180
381
- arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=0zdBf1mTfR9YCquvk1p_t67Guhjb7XgM8bwBgMpmcvs,8730
381
+ arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=G5sLghJcG43yLyZrGM4qhok3IchbeeZDKiGKjolOQGs,8952
382
382
  arelle/plugin/validate/NL/ValidationPluginExtension.py,sha256=2qvvOqBkgk2LwERTHDuxtrRupYz3yRyhH71XQLbl9F4,15507
383
- arelle/plugin/validate/NL/__init__.py,sha256=99uMv4ESHwyJqA-Xq_hBvHygm0BQ3NxcmAJnVYUkSgg,3104
383
+ arelle/plugin/validate/NL/__init__.py,sha256=GFM77Mv7OJkLKrZUEB_LmF5x3h4U5J9NsD1lven0N9o,2708
384
384
  arelle/plugin/validate/NL/resources/config.xml,sha256=i_ns2wHmQYjhkRItevRR8tzfkl31ASfbWlc5t6pDB-w,1117
385
385
  arelle/plugin/validate/NL/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
386
386
  arelle/plugin/validate/NL/rules/br_kvk.py,sha256=0SwKieWzTDm3YMsXPS6zTdgbk7_Z9CzqRkRmCRz1OiQ,15789
387
387
  arelle/plugin/validate/NL/rules/fg_nl.py,sha256=4Puq5wAjtK_iNd4wisH_R0Z_EKJ7MT2OCai5g4t1MPE,10714
388
388
  arelle/plugin/validate/NL/rules/fr_kvk.py,sha256=-_BLeWGoZ_f56p5VO4X40S45Ny3Ej-WK6Srei1KVSxU,8170
389
389
  arelle/plugin/validate/NL/rules/fr_nl.py,sha256=-M1WtXp06khhtkfOVPCa-b8UbC281gk4YfDhvtAVlnI,31424
390
- arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=gCmOZP3sYJBBzuFoZSg4T4M5bB2MnThduS1no4BWSqc,16062
390
+ arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=Q95o159XeA29g34ZeQHL113TV9KmKeVk1RzTHNsK5W8,18270
391
391
  arelle/plugin/validate/ROS/DisclosureSystems.py,sha256=rJ81mwQDYTi6JecFZ_zhqjjz3VNQRgjHNSh0wcQWAQE,18
392
392
  arelle/plugin/validate/ROS/PluginValidationDataExtension.py,sha256=IV7ILhNvgKwQXqbpSA6HRNt9kEnejCyMADI3wyyIgk0,4036
393
393
  arelle/plugin/validate/ROS/ValidationPluginExtension.py,sha256=FBhEp8t396vGdvCbMEimfcxmGiGnhXMen-yVLWnkFaI,758
@@ -395,7 +395,7 @@ arelle/plugin/validate/ROS/__init__.py,sha256=KuWg1MHVzA2S6eaHFptvP3Vu_5gQWf3OUY
395
395
  arelle/plugin/validate/ROS/config.xml,sha256=ZCpCFgr1ZAjoUuhb1eRpDnmKrae-sXA9yl6SOWnrfm8,654
396
396
  arelle/plugin/validate/ROS/resources/config.xml,sha256=HXWume5HlrAqOx5AtiWWqgADbRatA8YSfm_JvZGwdgQ,657
397
397
  arelle/plugin/validate/ROS/rules/__init__.py,sha256=wW7BUAIb7sRkOxC1Amc_ZKrz03FM-Qh1TyZe6wxYaAU,1567
398
- arelle/plugin/validate/ROS/rules/ros.py,sha256=z73XGmFHfxeD8SO4cVjuazerguaF4MBfG6Jf5TJZkKw,19923
398
+ arelle/plugin/validate/ROS/rules/ros.py,sha256=6DciQvv3H9QCEaDgINfHejZd196pEulUcQHk2qqMWhs,19921
399
399
  arelle/plugin/validate/UK/ValidateUK.py,sha256=0UhSwsY1lrY-EAEBJJR9QY38YXGBZ6PEgmuC5gQfBlI,57813
400
400
  arelle/plugin/validate/UK/__init__.py,sha256=WOAbzcogxP2hD3HmNnVIrvUO4w0Cv36447AoPrMa7KU,30548
401
401
  arelle/plugin/validate/UK/config.xml,sha256=mUFhWDfBzGTn7v0ZSmf4HaweQTMJh_4ZcJmD9mzCHrA,1547
@@ -697,6 +697,7 @@ arelle/resources/libs/Tktable2.11/win-x86_64/tkTable.tcl,sha256=JrSZRngZFHtw8Svp
697
697
  arelle/scripts-macOS/startWebServer.command,sha256=KXLSwAwchDZBlL-k9PYXdf39RNBtte4vV076_kIz2Ow,91
698
698
  arelle/scripts-unix/startWebServer.sh,sha256=_0puRzaGkdMZoFn3R7hDti9a3ryN6kTZAXwLweeZU1s,42
699
699
  arelle/scripts-windows/startWebServer.bat,sha256=qmnF1yrjNo__bi4QodONWlN0qHShVLTKptJQYyZtgcY,122
700
+ arelle/utils/EntryPointDetection.py,sha256=S85pXfCdrxLiX_L5rYVmlGwTNhwqlIE0L7c2g7UUeDc,4369
700
701
  arelle/utils/PluginData.py,sha256=GUnuZaApm1J4Xm9ZA1U2M1aask-AaNGviLtc0fgXbFg,265
701
702
  arelle/utils/PluginHooks.py,sha256=CeVxti23VjERQl4xWFucDVTW63TCG2PUdnxpjd3x_Ms,31170
702
703
  arelle/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -708,7 +709,7 @@ arelle/utils/validate/ValidationUtil.py,sha256=9vmSvShn-EdQy56dfesyV8JjSRVPj7txr
708
709
  arelle/utils/validate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
709
710
  arelle/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
710
711
  arelle/webserver/bottle.py,sha256=P-JECd9MCTNcxCnKoDUvGcoi03ezYVOgoWgv2_uH-6M,362
711
- arelle_release-2.37.11.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
712
+ arelle_release-2.37.13.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
712
713
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
713
714
  tests/integration_tests/download_cache.py,sha256=jVMIVICsZjcVc9DCPPu3fCjF9_cWSS3tqSynhFs3oAM,4097
714
715
  tests/integration_tests/integration_test_util.py,sha256=H7mncbv0T9ZeVyrtk9Hohe3k6jgcYykHkt-LGE-Q9aQ,10270
@@ -730,7 +731,7 @@ tests/integration_tests/scripts/tests/python_api_query_model.py,sha256=Ut87tvE-h
730
731
  tests/integration_tests/scripts/tests/python_api_taxonomy_service.py,sha256=C6j7BB9h7CX_dUmVFkpnqElShffRSmCI-TMJkueztGM,2711
731
732
  tests/integration_tests/scripts/tests/python_api_validate_esef.py,sha256=Qzi2RRGWjkTVhAjBB18DeJ3X_M9hJYH1TAk7j_RVv5Q,2423
732
733
  tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest.sln,sha256=uzzvHUtKpmBPpoxdfHd7cCmAkdvjs7mMehO6YHebdTY,1499
733
- tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/ArelleGUITest.csproj,sha256=_MqHWdpSGWqbmEnccKPDPCvUsB-uHH6GXkA5ZPD7gD8,1387
734
+ tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/ArelleGUITest.csproj,sha256=TW3UoKU77nleFIjyKhtXOEuhaaBjD9201ie80UIT10Y,1387
734
735
  tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Tests.cs,sha256=_0TvabpERmrfaoDSazN-xQAH0qzO3cAnuFHLGLRJnGU,20334
735
736
  tests/integration_tests/ui_tests/ArelleGUITest/ArelleGUITest/Usings.cs,sha256=0IC7tQ27uAqlt8ZGBrJPK7BPj3kjiodPcHWB3v_JT-o,29
736
737
  tests/integration_tests/ui_tests/resources/workiva.zip,sha256=QtZzi1VcKkHhVa8J-I1wVpQFy-p6tsV95Z0HmI6XbXc,223544
@@ -763,7 +764,7 @@ tests/integration_tests/validation/conformance_suite_configurations/kvk_nt16.py,
763
764
  tests/integration_tests/validation/conformance_suite_configurations/kvk_nt17.py,sha256=lmEZonthFm0YKFmp1dwXtdJ2T7txUeSpL4mbAo8fl4Y,1292
764
765
  tests/integration_tests/validation/conformance_suite_configurations/kvk_nt18.py,sha256=EG2RQVkvFENhzUF3fl3QvDnH7ZPYS1n1Fo8bhfmSczM,1205
765
766
  tests/integration_tests/validation/conformance_suite_configurations/kvk_nt19.py,sha256=FAzf9RhRmn_8yowpplJho2zEspX9FxJiVq8SjZT3Dsc,1199
766
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py,sha256=5WbjM571b4Va8JbW8nuBp_XU7K-LecvNxFfpVyKfVM0,11095
767
+ tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py,sha256=fXxnPmGE2IepTcsowV_-OxqkPwU12QDbnvaQN5aV6Qk,10601
767
768
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py,sha256=O_LFVBZPkjxmbrU7_C7VTLtrdoCUx2bYXOXw6_MlRtQ,846
768
769
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py,sha256=aTN3Ez6lPsZsuypHZP84DneOtYxUZSjUiGypHy6ofHQ,846
769
770
  tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py,sha256=sqHLjrHc95dTu0guTgKkphaKM1zNfKGnN4GKkZDLzeU,845
@@ -781,7 +782,7 @@ tests/integration_tests/validation/conformance_suite_configurations/xbrl_formula
781
782
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_ixbrl_1_1.py,sha256=Upsc9Nx0eHJQlVL9p77GamTCUpIqjexnRShe9F0b9NM,1366
782
783
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_link_role_registry_1_0.py,sha256=NQfri9MXCDSvNy7kahf4iXZaBUPey9-FYKlchg-Uw4I,633
783
784
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_oim_1_0.py,sha256=s5tcH5fgzNwLQR1iWxCjuyij4Rxjq8XrmGDIptAbfGE,906
784
- tests/integration_tests/validation/conformance_suite_configurations/xbrl_report_packages_1_0.py,sha256=roUdlY_cOYFp5gSyiDoYUP_OHRCjJyReTv-dNorI72g,1799
785
+ tests/integration_tests/validation/conformance_suite_configurations/xbrl_report_packages_1_0.py,sha256=C4-DkdYT4A4qeohf71P6of4NfLgqLQ4w04VYmWWeBTM,1954
785
786
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_table_linkbase_1_0.py,sha256=6zWp8Bt_X4QHDKeJo4NHOgu2OwMpc8-Qb0VZULWcn6M,844
786
787
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_taxonomy_packages_1_0.py,sha256=rw1QLcQBKIlwtQ3XhNJqAXxYgmWZm_4wGbwck2UZg_8,651
787
788
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_transformation_registry_3.py,sha256=ORho6dzIyaUOgm6v9YjViMAk3MzOK40U8AX2V0Eg5t4,591
@@ -1557,8 +1558,8 @@ tests/unit_tests/arelle/oim/test_load.py,sha256=NxiUauQwJVfWAHbbpsMHGSU2d3Br8Pki
1557
1558
  tests/unit_tests/arelle/plugin/test_plugin_imports.py,sha256=bdhIs9frAnFsdGU113yBk09_jis-z43dwUItMFYuSYM,1064
1558
1559
  tests/unit_tests/arelle/plugin/validate/ESEF/ESEF_Current/test_validate_css_url.py,sha256=XHABmejQt7RlZ0udh7v42f2Xb2STGk_fSaIaJ9i2xo0,878
1559
1560
  tests/unit_tests/arelle/utils/validate/test_decorator.py,sha256=ZS8FqIY1g-2FCbjF4UYm609dwViax6qBMRJSi0vfuhY,2482
1560
- arelle_release-2.37.11.dist-info/METADATA,sha256=Oo7fwuP5YONoSo93bQ9Kv9yPSXy-9PSG1SxlzYVk_D8,9065
1561
- arelle_release-2.37.11.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
1562
- arelle_release-2.37.11.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1563
- arelle_release-2.37.11.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1564
- arelle_release-2.37.11.dist-info/RECORD,,
1561
+ arelle_release-2.37.13.dist-info/METADATA,sha256=Ol2iYu-MT8cf22xuvNMIWt8qxYNedUq6E8sdaeEdGKU,9065
1562
+ arelle_release-2.37.13.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
1563
+ arelle_release-2.37.13.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1564
+ arelle_release-2.37.13.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1565
+ arelle_release-2.37.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.7.1)
2
+ Generator: setuptools (80.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -16,7 +16,7 @@
16
16
  <PackageReference Include="JUnitTestLogger" Version="1.1.0" />
17
17
  <PackageReference Include="JunitXml.TestLogger" Version="6.1.0" />
18
18
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
19
- <PackageReference Include="Microsoft.Windows.Compatibility" Version="9.0.4" />
19
+ <PackageReference Include="Microsoft.Windows.Compatibility" Version="9.0.5" />
20
20
  <PackageReference Include="NUnit" Version="4.3.2" />
21
21
  <PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
22
22
  <PackageReference Include="NUnit.Analyzers" Version="4.7.0">
@@ -22,12 +22,15 @@ config = ConformanceSuiteConfig(
22
22
  'taggedTextFactOnlyInLanguagesOtherThanLanguageOfAReport': 1,
23
23
  },
24
24
  'G4-1-2_1/index.xml:TC2_valid': {
25
+ 'undefinedLanguageForTextFact': 1,
25
26
  'taggedTextFactOnlyInLanguagesOtherThanLanguageOfAReport': 1,
26
27
  },
27
28
  'RTS_Annex_II_Par_1_RTS_Annex_IV_par_7/index.xml:TC2_valid': {
29
+ 'undefinedLanguageForTextFact': 1,
28
30
  'taggedTextFactOnlyInLanguagesOtherThanLanguageOfAReport': 1,
29
31
  },
30
32
  'RTS_Annex_II_Par_1_RTS_Annex_IV_par_7/index.xml:TC4_invalid': {
33
+ 'undefinedLanguageForTextFact': 1,
31
34
  'taggedTextFactOnlyInLanguagesOtherThanLanguageOfAReport': 1,
32
35
  },
33
36
  'RTS_Annex_IV_Par_1_G3-1-4_1/index.xml:TC2_invalid': {
@@ -42,6 +45,7 @@ config = ConformanceSuiteConfig(
42
45
  'message:valueKvKIdentifierScheme': 105,
43
46
  },
44
47
  'RTS_Annex_IV_Par_6/index.xml:TC2_valid': {
48
+ 'undefinedLanguageForTextFact': 1,
45
49
  'taggedTextFactOnlyInLanguagesOtherThanLanguageOfAReport': 1,
46
50
  },
47
51
  }.items()},
@@ -52,10 +56,6 @@ config = ConformanceSuiteConfig(
52
56
 
53
57
 
54
58
  # Not Implemented
55
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC4_invalid',
56
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC5_invalid',
57
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC6_invalid',
58
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-2-7_1/index.xml:TC7_invalid',
59
59
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_1/index.xml:TC2_invalid',
60
60
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_2/index.xml:TC2_invalid',
61
61
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-4-1_3/index.xml:TC2_invalid',
@@ -70,7 +70,6 @@ config = ConformanceSuiteConfig(
70
70
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_4/index.xml:TC2_invalid',
71
71
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_5/index.xml:TC2_invalid',
72
72
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-1_5/index.xml:TC3_invalid',
73
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-2_1/index.xml:TC3_invalid',
74
73
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-3_1/index.xml:TC2_invalid',
75
74
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-5-4_1/index.xml:TC2_invalid',
76
75
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G3-6-2_1/index.xml:TC2_invalid',
@@ -105,9 +104,7 @@ config = ConformanceSuiteConfig(
105
104
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-3_2/index.xml:TC3_invalid',
106
105
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-5_2/index.xml:TC2_invalid',
107
106
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G4-4-5_2/index.xml:TC3_invalid',
108
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_1/index.xml:TC1_valid',
109
107
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_1/index.xml:TC2_invalid',
110
- 'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_2/index.xml:TC1_valid',
111
108
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G5-1-3_2/index.xml:TC2_invalid',
112
109
  'conformance-suite-2024-sbr-domein-handelsregister/tests/G6-1-1_1/index.xml:TC2_invalid',
113
110
  'conformance-suite-2024-sbr-domein-handelsregister/tests/RTS_Annex_II_Par_1/index.xml:TC3_invalid',
@@ -18,7 +18,9 @@ config = ConformanceSuiteConfig(
18
18
  expected_additional_testcase_errors={f"report-package-conformance/index.csv:{s}": val for s, val in {
19
19
  # "Empty" iXBRL docs are missing schema required elements.
20
20
  "V-301-xbri-with-single-ixds": {
21
- "lxml.SCHEMAV_ELEMENT_CONTENT": 1,
21
+ # There are two documents in the package, empty1.xhtml and empty2.xhtml,
22
+ # each missing a title, so we must see two schema errors.
23
+ "lxml.SCHEMAV_ELEMENT_CONTENT": 2,
22
24
  "ix11.14.1.2:missingResources": 1,
23
25
  },
24
26
  "V-302-xbri-with-single-html": {