arelle-release 2.36.30__py3-none-any.whl → 2.36.31__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 (40) hide show
  1. arelle/CntlrCmdLine.py +88 -50
  2. arelle/CntlrWinMain.py +18 -0
  3. arelle/ModelManager.py +2 -0
  4. arelle/ModelValue.py +5 -4
  5. arelle/RuntimeOptions.py +1 -0
  6. arelle/ValidateXbrlDTS.py +83 -27
  7. arelle/ViewFileRenderedGrid.py +1 -1
  8. arelle/ViewFileRenderedLayout.py +0 -1
  9. arelle/ViewWinRenderedGrid.py +1 -1
  10. arelle/XmlUtil.py +1 -1
  11. arelle/_version.py +2 -2
  12. arelle/plugin/saveLoadableOIM.py +38 -5
  13. arelle/rendering/RenderingResolution.py +2 -2
  14. {arelle_release-2.36.30.dist-info → arelle_release-2.36.31.dist-info}/METADATA +1 -1
  15. {arelle_release-2.36.30.dist-info → arelle_release-2.36.31.dist-info}/RECORD +40 -40
  16. tests/integration_tests/validation/conformance_suite_configurations/cipc_current.py +1 -0
  17. tests/integration_tests/validation/conformance_suite_configurations/dba_current.py +1 -0
  18. tests/integration_tests/validation/conformance_suite_configurations/dba_multi_current.py +1 -0
  19. tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2021.py +1 -0
  20. tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2022.py +1 -0
  21. tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2023.py +1 -0
  22. tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2024.py +1 -0
  23. tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2021.py +1 -0
  24. tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2022.py +1 -0
  25. tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2023.py +1 -0
  26. tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2024.py +1 -0
  27. tests/integration_tests/validation/conformance_suite_configurations/hmrc_current.py +1 -0
  28. tests/integration_tests/validation/conformance_suite_configurations/kvk_nt16.py +1 -0
  29. tests/integration_tests/validation/conformance_suite_configurations/kvk_nt17.py +1 -0
  30. tests/integration_tests/validation/conformance_suite_configurations/kvk_nt18.py +1 -0
  31. tests/integration_tests/validation/conformance_suite_configurations/kvk_nt19.py +1 -0
  32. tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py +1 -0
  33. tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py +1 -0
  34. tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py +1 -0
  35. tests/integration_tests/validation/conformance_suite_configurations/nl_nt19.py +1 -0
  36. tests/integration_tests/validation/conformance_suite_configurations/ros_current.py +1 -0
  37. {arelle_release-2.36.30.dist-info → arelle_release-2.36.31.dist-info}/LICENSE.md +0 -0
  38. {arelle_release-2.36.30.dist-info → arelle_release-2.36.31.dist-info}/WHEEL +0 -0
  39. {arelle_release-2.36.30.dist-info → arelle_release-2.36.31.dist-info}/entry_points.txt +0 -0
  40. {arelle_release-2.36.30.dist-info → arelle_release-2.36.31.dist-info}/top_level.txt +0 -0
arelle/CntlrCmdLine.py CHANGED
@@ -6,33 +6,59 @@ This module is Arelle's controller in command line non-interactive mode
6
6
  See COPYRIGHT.md for copyright information.
7
7
  '''
8
8
  from __future__ import annotations
9
- from arelle import PackageManager, ValidateDuplicateFacts
10
- import gettext, time, datetime, os, shlex, sys, traceback, fnmatch, threading, json, logging, platform
11
- from optparse import OptionGroup, OptionParser, SUPPRESS_HELP, Option
9
+
10
+ import datetime
11
+ import fnmatch
12
+ import gettext
13
+ import glob
14
+ import json
15
+ import logging
16
+ import os
17
+ import platform
18
+ import shlex
19
+ import sys
20
+ import threading
21
+ import time
22
+ import traceback
23
+ from optparse import SUPPRESS_HELP, Option, OptionGroup, OptionParser
24
+ from pprint import pprint
25
+
12
26
  import regex as re
13
- from arelle import (Cntlr, FileSource, ModelDocument, XmlUtil, XbrlConst, Version,
14
- ViewFileDTS, ViewFileFactList, ViewFileFactTable, ViewFileConcepts,
15
- ViewFileFormulae, ViewFileRelationshipSet, ViewFileTests, ViewFileRssFeed,
16
- ViewFileRoleTypes)
17
- from arelle.oim.xml.Save import saveOimReportToXmlInstance
18
- from arelle.rendering import RenderingEvaluator
19
- from arelle.RuntimeOptions import RuntimeOptions, RuntimeOptionsException
27
+ from lxml import etree
28
+
29
+ from arelle import (
30
+ Cntlr,
31
+ FileSource,
32
+ ModelDocument,
33
+ PackageManager,
34
+ PluginManager,
35
+ ValidateDuplicateFacts,
36
+ Version,
37
+ ViewFileConcepts,
38
+ ViewFileDTS,
39
+ ViewFileFactList,
40
+ ViewFileFactTable,
41
+ ViewFileFormulae,
42
+ ViewFileRelationshipSet,
43
+ ViewFileRoleTypes,
44
+ ViewFileRssFeed,
45
+ ViewFileTests,
46
+ XbrlConst,
47
+ XmlUtil,
48
+ )
20
49
  from arelle.BetaFeatures import BETA_FEATURES_AND_DESCRIPTIONS
21
- from arelle.ModelValue import qname
22
50
  from arelle.Locale import format_string, setApplicationLocale, setDisableRTL
23
51
  from arelle.ModelFormulaObject import FormulaOptions
24
- from arelle import PluginManager
25
- from arelle.PluginManager import pluginClassMethods
52
+ from arelle.ModelValue import qname
53
+ from arelle.oim.xml.Save import saveOimReportToXmlInstance
54
+ from arelle.rendering import RenderingEvaluator
55
+ from arelle.RuntimeOptions import RuntimeOptions, RuntimeOptionsException
26
56
  from arelle.SocketUtils import INTERNET_CONNECTIVITY, OFFLINE
57
+ from arelle.SystemInfo import PlatformOS, getSystemInfo, getSystemWordSize, hasWebServer, isCGI, isGAE
27
58
  from arelle.typing import TypeGetText
28
59
  from arelle.UrlUtil import isHttpUrl
29
- from arelle.Version import copyrightLabel
60
+ from arelle.ValidateXbrlDTS import ValidateBaseTaxonomiesMode
30
61
  from arelle.WebCache import proxyTuple
31
- from arelle.SystemInfo import getSystemInfo, getSystemWordSize, hasWebServer, isCGI, isGAE, PlatformOS
32
- from pprint import pprint
33
- import logging
34
- from lxml import etree
35
- import glob
36
62
 
37
63
  win32file = win32api = win32process = pywintypes = None
38
64
  STILL_ACTIVE = 259 # MS Windows process status constants
@@ -51,10 +77,7 @@ def main():
51
77
  :type message: [str]
52
78
  """
53
79
  envArgs = os.getenv("ARELLE_ARGS")
54
- if envArgs:
55
- args = shlex.split(envArgs)
56
- else:
57
- args = sys.argv[1:]
80
+ args = shlex.split(envArgs) if envArgs else sys.argv[1:]
58
81
  setApplicationLocale()
59
82
  gettext.install("arelle")
60
83
  parseAndRun(args)
@@ -96,7 +119,7 @@ def parseArgs(args):
96
119
  cntlr = CntlrCmdLine(uiLang=uiLang, disable_persistent_config=disable_persistent_config) # This Cntlr is needed for translations and to enable the web cache. The cntlr is not used outside the parse function
97
120
  usage = "usage: %prog [options]"
98
121
  parser = OptionParser(usage,
99
- version="Arelle(r) {0} ({1}bit)".format(Version.__version__, getSystemWordSize()),
122
+ version=f"Arelle(r) {Version.__version__} ({getSystemWordSize()}bit)",
100
123
  conflict_handler="resolve") # allow reloading plug-in options without errors
101
124
  parser.add_option("-f", "--file", dest="entrypointFile",
102
125
  help=_("FILENAME is an entry point, which may be "
@@ -137,6 +160,15 @@ def parseArgs(args):
137
160
  choices=[a.value for a in ValidateDuplicateFacts.DUPLICATE_TYPE_ARG_MAP],
138
161
  dest="validateDuplicateFacts",
139
162
  help=_("Select which types of duplicates should trigger warnings."))
163
+ parser.add_option("--baseTaxonomyValidation", "--basetaxonomyvalidation",
164
+ choices=("disclosureSystem", "none", "all"),
165
+ dest="baseTaxonomyValidationMode",
166
+ default="disclosureSystem",
167
+ help=_("""Specify if base taxonomies should be validated.
168
+ Skipping validation of base taxonomy files which are known to be valid can significantly reduce validation time.
169
+ disclosureSystem - (default) skip validation of base taxonomy files which are known to be valid by the disclosure system
170
+ none - skip validation of all base taxonomies
171
+ all - validate all base taxonomies"""))
140
172
  parser.add_option("--saveOIMToXMLReport", "--saveoimtoxmlreport", "--saveOIMinstance", "--saveoiminstance",
141
173
  action="store",
142
174
  dest="saveOIMToXMLReport",
@@ -397,7 +429,7 @@ def parseArgs(args):
397
429
  PluginManager.reset()
398
430
  break
399
431
  # add plug-in options
400
- for optionsExtender in pluginClassMethods("CntlrCmdLine.Options"):
432
+ for optionsExtender in PluginManager.pluginClassMethods("CntlrCmdLine.Options"):
401
433
  optionsExtender(parser)
402
434
  pluginLastOptionIndex = len(parser.option_list)
403
435
  pluginLastOptionsGroupIndex = len(parser.option_groups)
@@ -459,7 +491,7 @@ def parseArgs(args):
459
491
  version=Version.__version__,
460
492
  wordSize=getSystemWordSize(),
461
493
  platform=platform.machine(),
462
- copyrightLabel=copyrightLabel,
494
+ copyrightLabel=Version.copyrightLabel,
463
495
  pythonVersion=f'{sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}',
464
496
  lxmlVersion=f'{etree.LXML_VERSION[0]}.{etree.LXML_VERSION[1]}.{etree.LXML_VERSION[2]}',
465
497
  bottleCopyright="\n Bottle (c) 2011-2013 Marcel Hellkamp" if hasWebServer() else ""
@@ -568,7 +600,7 @@ def filesourceEntrypointFiles(filesource, entrypointFiles=None, inlineOnly=False
568
600
  if report.isInline:
569
601
  reportEntries = [{"file": f} for f in report.fullPathFiles]
570
602
  ixdsDiscovered = False
571
- for pluginXbrlMethod in pluginClassMethods("InlineDocumentSet.Discovery"):
603
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
572
604
  pluginXbrlMethod(filesource, reportEntries)
573
605
  ixdsDiscovered = True
574
606
  if not ixdsDiscovered and len(reportEntries) > 1:
@@ -590,13 +622,17 @@ def filesourceEntrypointFiles(filesource, entrypointFiles=None, inlineOnly=False
590
622
  entrypointFiles.append({"file":url})
591
623
  if entrypointFiles:
592
624
  if identifiedType == ModelDocument.Type.INLINEXBRL:
593
- for pluginXbrlMethod in pluginClassMethods("InlineDocumentSet.Discovery"):
625
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
594
626
  pluginXbrlMethod(filesource, entrypointFiles) # group into IXDS if plugin feature is available
595
627
  break # found inline (or non-inline) entrypoint files, don't look for any other type
596
628
  # for ESEF non-consolidated xhtml documents accept an xhtml entry point
597
629
  if not entrypointFiles and not inlineOnly:
598
630
  for url in urlsByType.get(ModelDocument.Type.HTML, []):
599
631
  entrypointFiles.append({"file":url})
632
+ if not entrypointFiles and filesource.taxonomyPackage is not None:
633
+ for packageEntry in filesource.taxonomyPackage.get('entryPoints', {}).values():
634
+ for _resolvedUrl, remappedUrl, _closest in packageEntry:
635
+ entrypointFiles.append({"file": remappedUrl})
600
636
 
601
637
 
602
638
  elif os.path.isdir(filesource.url):
@@ -611,7 +647,7 @@ def filesourceEntrypointFiles(filesource, entrypointFiles=None, inlineOnly=False
611
647
  if identifiedType in (ModelDocument.Type.INSTANCE, ModelDocument.Type.INLINEXBRL):
612
648
  entrypointFiles.append({"file":_path})
613
649
  if hasInline: # group into IXDS if plugin feature is available
614
- for pluginXbrlMethod in pluginClassMethods("InlineDocumentSet.Discovery"):
650
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("InlineDocumentSet.Discovery"):
615
651
  pluginXbrlMethod(filesource, entrypointFiles)
616
652
 
617
653
  return entrypointFiles
@@ -652,7 +688,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
652
688
  """
653
689
 
654
690
  def __init__(self, logFileName=None, uiLang=None, disable_persistent_config=False):
655
- super(CntlrCmdLine, self).__init__(hasGui=False, uiLang=uiLang, disable_persistent_config=disable_persistent_config)
691
+ super().__init__(hasGui=False, uiLang=uiLang, disable_persistent_config=disable_persistent_config)
656
692
  self.preloadedPlugins = {}
657
693
 
658
694
  def run(self, options: RuntimeOptions, sourceZipStream=None, responseZipStream=None, sourceZipStreamFileName=None) -> bool:
@@ -664,24 +700,24 @@ class CntlrCmdLine(Cntlr.Cntlr):
664
700
  :param options: OptionParser options from parse_args of main argv arguments (when called from command line) or corresponding arguments from web service (REST) request.
665
701
  :type options: optparse.Values
666
702
  """
667
- for b in BETA_FEATURES_AND_DESCRIPTIONS.keys():
703
+ for b in BETA_FEATURES_AND_DESCRIPTIONS:
668
704
  self.betaFeatures[b] = getattr(options, b)
669
705
  if options.statusPipe or options.monitorParentProcess:
670
706
  try:
671
707
  global win32file, win32api, win32process, pywintypes
672
708
  import win32file, win32api, win32process, pywintypes
673
709
  except ImportError: # win32 not installed
674
- self.addToLog("--statusPipe {} cannot be installed, packages for win32 missing".format(options.statusPipe))
710
+ self.addToLog(f"--statusPipe {options.statusPipe} cannot be installed, packages for win32 missing")
675
711
  options.statusPipe = options.monitorParentProcess = None
676
712
  if options.statusPipe:
677
713
  try:
678
- self.statusPipe = win32file.CreateFile("\\\\.\\pipe\\{}".format(options.statusPipe),
714
+ self.statusPipe = win32file.CreateFile(f"\\\\.\\pipe\\{options.statusPipe}",
679
715
  win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None, win32file.OPEN_EXISTING, win32file.FILE_FLAG_NO_BUFFERING, None)
680
716
  self.showStatus = self.showStatusOnPipe
681
717
  self.lastStatusTime = 0.0
682
718
  self.parentProcessHandle = None
683
719
  except pywintypes.error: # named pipe doesn't exist
684
- self.addToLog("--statusPipe {} has not been created by calling program".format(options.statusPipe))
720
+ self.addToLog(f"--statusPipe {options.statusPipe} has not been created by calling program")
685
721
  if options.monitorParentProcess:
686
722
  try:
687
723
  self.parentProcessHandle = win32api.OpenProcess(PROCESS_QUERY_INFORMATION, False, int(options.monitorParentProcess))
@@ -693,14 +729,14 @@ class CntlrCmdLine(Cntlr.Cntlr):
693
729
  _t.start()
694
730
  monitorParentProcess()
695
731
  except ImportError: # win32 not installed
696
- self.addToLog("--monitorParentProcess {} cannot be installed, packages for win32api and win32process missing".format(options.monitorParentProcess))
732
+ self.addToLog(f"--monitorParentProcess {options.monitorParentProcess} cannot be installed, packages for win32api and win32process missing")
697
733
  except (ValueError, pywintypes.error): # parent process doesn't exist
698
- self.addToLog("--monitorParentProcess Process {} Id is invalid".format(options.monitorParentProcess))
734
+ self.addToLog(f"--monitorParentProcess Process {options.monitorParentProcess} Id is invalid")
699
735
  sys.exit()
700
736
  if options.showOptions: # debug options
701
737
  for optName, optValue in sorted(options.__dict__.items(), key=lambda optItem: optItem[0]):
702
- self.addToLog("Option {0}={1}".format(optName, optValue), messageCode="info")
703
- self.addToLog("sys.argv {0}".format(sys.argv), messageCode="info")
738
+ self.addToLog(f"Option {optName}={optValue}", messageCode="info")
739
+ self.addToLog(f"sys.argv {sys.argv}", messageCode="info")
704
740
 
705
741
  setDisableRTL(options.disableRtl) # not saved to config
706
742
 
@@ -730,7 +766,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
730
766
  ":****" if password else "",
731
767
  "@" if (user or password) else "",
732
768
  urlAddr,
733
- ":{0}".format(urlPort) if urlPort else ""), messageCode="info")
769
+ f":{urlPort}" if urlPort else ""), messageCode="info")
734
770
  else:
735
771
  self.addToLog(_("Proxy is disabled."), messageCode="info")
736
772
  if options.noCertificateCheck:
@@ -801,7 +837,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
801
837
  if loadPluginOptions:
802
838
  _optionsParser = ParserForDynamicPlugins(options)
803
839
  # add plug-in options
804
- for optionsExtender in pluginClassMethods("CntlrCmdLine.Options"):
840
+ for optionsExtender in PluginManager.pluginClassMethods("CntlrCmdLine.Options"):
805
841
  optionsExtender(_optionsParser)
806
842
 
807
843
  if showPluginModules:
@@ -844,6 +880,8 @@ class CntlrCmdLine(Cntlr.Cntlr):
844
880
  else:
845
881
  self.modelManager.disclosureSystem.select(None) # just load ordinary mappings
846
882
  self.modelManager.validateDisclosureSystem = False
883
+ if options.baseTaxonomyValidationMode is not None:
884
+ self.modelManager.baseTaxonomyValidationMode = ValidateBaseTaxonomiesMode.fromName(options.baseTaxonomyValidationMode)
847
885
  self.modelManager.validateXmlOim = bool(options.validateXmlOim)
848
886
  if options.validateDuplicateFacts:
849
887
  duplicateTypeArg = ValidateDuplicateFacts.DuplicateTypeArg(options.validateDuplicateFacts)
@@ -981,7 +1019,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
981
1019
 
982
1020
  # run utility command line options that don't depend on entrypoint Files
983
1021
  hasUtilityPlugin = False
984
- for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Utility.Run"):
1022
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("CntlrCmdLine.Utility.Run"):
985
1023
  hasUtilityPlugin = True
986
1024
  try:
987
1025
  pluginXbrlMethod(self, options, sourceZipStream=sourceZipStream, responseZipStream=responseZipStream)
@@ -1006,7 +1044,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
1006
1044
  except ValueError as e:
1007
1045
  # is it malformed json?
1008
1046
  if _f.startswith("[{") or _f.endswith("]}") or '"file:"' in _f:
1009
- self.addToLog(_("File name parameter appears to be malformed JSON: {0}\n{1}".format(e, _f)),
1047
+ self.addToLog(_("File name parameter appears to be malformed JSON: {}\n{}").format(e, _f),
1010
1048
  messageCode="FileNameFormatError",
1011
1049
  level=logging.ERROR)
1012
1050
  success = False
@@ -1029,7 +1067,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
1029
1067
  self.addToLog(str(err), messageCode="error", level=logging.ERROR)
1030
1068
  return False
1031
1069
 
1032
- for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Filing.Start"):
1070
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("CntlrCmdLine.Filing.Start"):
1033
1071
  pluginXbrlMethod(self, options, filesource, _entrypointFiles, sourceZipStream=sourceZipStream, responseZipStream=responseZipStream)
1034
1072
  if len(_entrypointFiles) == 0:
1035
1073
  if options.entrypointFile:
@@ -1090,10 +1128,10 @@ class CntlrCmdLine(Cntlr.Cntlr):
1090
1128
  if modelXbrl.errors:
1091
1129
  success = False # loading errors, don't attempt to utilize loaded DTS
1092
1130
  if modelXbrl.modelDocument.type in ModelDocument.Type.TESTCASETYPES:
1093
- for pluginXbrlMethod in pluginClassMethods("Testcases.Start"):
1131
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("Testcases.Start"):
1094
1132
  pluginXbrlMethod(self, options, modelXbrl)
1095
1133
  else: # not a test case, probably instance or DTS
1096
- for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Xbrl.Loaded"):
1134
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("CntlrCmdLine.Xbrl.Loaded"):
1097
1135
  pluginXbrlMethod(self, options, modelXbrl, _entrypoint, responseZipStream=responseZipStream)
1098
1136
  if options.saveOIMToXMLReport:
1099
1137
  if modelXbrl.loadedFromOIM and modelXbrl.modelDocument is not None:
@@ -1142,7 +1180,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
1142
1180
  for modelXbrl in [self.modelManager.modelXbrl] + getattr(self.modelManager.modelXbrl, "supplementalModelXbrls", []):
1143
1181
  hasFormulae = modelXbrl.hasFormulae
1144
1182
  isAlreadyValidated = False
1145
- for pluginXbrlMethod in pluginClassMethods("ModelDocument.IsValidated"):
1183
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("ModelDocument.IsValidated"):
1146
1184
  if pluginXbrlMethod(modelXbrl): # e.g., streaming extensions already has validated
1147
1185
  isAlreadyValidated = True
1148
1186
  if options.validate and not isAlreadyValidated:
@@ -1208,10 +1246,10 @@ class CntlrCmdLine(Cntlr.Cntlr):
1208
1246
  if options.arcroleTypesFile:
1209
1247
  ViewFileRoleTypes.viewRoleTypes(modelXbrl, options.arcroleTypesFile, "Arcrole Types", isArcrole=True, lang=options.labelLang)
1210
1248
 
1211
- for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Xbrl.Run"):
1249
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("CntlrCmdLine.Xbrl.Run"):
1212
1250
  pluginXbrlMethod(self, options, modelXbrl, _entrypoint, sourceZipStream=sourceZipStream, responseZipStream=responseZipStream)
1213
1251
 
1214
- except (IOError, EnvironmentError) as err:
1252
+ except OSError as err:
1215
1253
  self.addToLog(_("[IOError] Failed to save output:\n {0}").format(err),
1216
1254
  messageCode="IOError",
1217
1255
  file=options.entrypointFile,
@@ -1264,9 +1302,9 @@ class CntlrCmdLine(Cntlr.Cntlr):
1264
1302
 
1265
1303
  if success:
1266
1304
  if options.validate:
1267
- for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Filing.Validate"):
1305
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("CntlrCmdLine.Filing.Validate"):
1268
1306
  pluginXbrlMethod(self, options, filesource, _entrypointFiles, sourceZipStream=sourceZipStream, responseZipStream=responseZipStream)
1269
- for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Filing.End"):
1307
+ for pluginXbrlMethod in PluginManager.pluginClassMethods("CntlrCmdLine.Filing.End"):
1270
1308
  pluginXbrlMethod(self, options, filesource, _entrypointFiles, sourceZipStream=sourceZipStream, responseZipStream=responseZipStream)
1271
1309
  self.username = self.password = None #dereference password
1272
1310
  self._clearPluginData()
arelle/CntlrWinMain.py CHANGED
@@ -34,6 +34,7 @@ from arelle import XbrlConst
34
34
  from arelle.PluginManager import pluginClassMethods
35
35
  from arelle.UrlUtil import isHttpUrl
36
36
  from arelle.ValidateXbrlCalcs import ValidateCalcsMode as CalcsMode
37
+ from arelle.ValidateXbrlDTS import ValidateBaseTaxonomiesMode
37
38
  from arelle.Version import copyrightLabel
38
39
  from arelle.oim.xml.Save import saveOimReportToXmlInstance
39
40
  import logging
@@ -164,6 +165,16 @@ class CntlrWinMain (Cntlr.Cntlr):
164
165
  for calcChoiceMenuLabel, calcChoiceEnumValue in CalcsMode.menu().items():
165
166
  calcMenu.add_radiobutton(label=calcChoiceMenuLabel, underline=0, var=self.calcChoiceEnumVar, value=calcChoiceEnumValue)
166
167
  toolsMenu.add_cascade(label=_("Calc linkbase"), menu=calcMenu, underline=0)
168
+
169
+ baseValidateModeMenu = Menu(self.menubar, tearoff=0)
170
+ baseValidationModeName = self.config.setdefault("baseTaxonomyValidationMode", ValidateBaseTaxonomiesMode.DISCLOSURE_SYSTEM.value)
171
+ self.modelManager.baseTaxonomyValidationMode = ValidateBaseTaxonomiesMode.fromName(baseValidationModeName)
172
+ self.baseTaxonomyValidationModeEnumVar = StringVar(self.parent, value=baseValidationModeName)
173
+ self.baseTaxonomyValidationModeEnumVar.trace("w", self.setBaseTaxonomyValidationModeEnumVar)
174
+ for modeLabel, modeValue in ValidateBaseTaxonomiesMode.menu().items():
175
+ baseValidateModeMenu.add_radiobutton(label=modeLabel, underline=0, var=self.baseTaxonomyValidationModeEnumVar, value=modeValue)
176
+ validateMenu.add_cascade(label=_("Base taxonomy validation"), menu=baseValidateModeMenu, underline=0)
177
+
167
178
  self.modelManager.validateUtr = self.config.setdefault("validateUtr",True)
168
179
  self.validateUtr = BooleanVar(value=self.modelManager.validateUtr)
169
180
  self.validateUtr.trace("w", self.setValidateUtr)
@@ -1401,6 +1412,13 @@ class CntlrWinMain (Cntlr.Cntlr):
1401
1412
  self.saveConfig()
1402
1413
  self.setValidateTooltipText()
1403
1414
 
1415
+ def setBaseTaxonomyValidationModeEnumVar(self, *args):
1416
+ modeName = self.baseTaxonomyValidationModeEnumVar.get()
1417
+ self.modelManager.baseTaxonomyValidationMode = ValidateBaseTaxonomiesMode.fromName(modeName)
1418
+ self.config["baseTaxonomyValidationMode"] = modeName
1419
+ self.saveConfig()
1420
+ self.setValidateTooltipText()
1421
+
1404
1422
  def setValidateUtr(self, *args):
1405
1423
  self.modelManager.validateUtr = self.validateUtr.get()
1406
1424
  self.config["validateUtr"] = self.modelManager.validateUtr
arelle/ModelManager.py CHANGED
@@ -9,6 +9,7 @@ import gc, sys, traceback, logging
9
9
  from arelle import ModelXbrl, Validate, DisclosureSystem, PackageManager, ValidateXbrlCalcs, ValidateDuplicateFacts
10
10
  from arelle.ModelFormulaObject import FormulaOptions
11
11
  from arelle.PluginManager import pluginClassMethods
12
+ from arelle.ValidateXbrlDTS import ValidateBaseTaxonomiesMode
12
13
  from arelle.typing import LocaleDict
13
14
 
14
15
  if TYPE_CHECKING:
@@ -67,6 +68,7 @@ class ModelManager:
67
68
  self.loadedModelXbrls = []
68
69
  self.customTransforms: dict[QName, Callable[[str], str]] | None = None
69
70
  self.isLocaleSet = False
71
+ self.baseTaxonomyValidationMode = ValidateBaseTaxonomiesMode.DISCLOSURE_SYSTEM
70
72
  self.validateAllFilesAsReportPackages = False
71
73
  self.validateDuplicateFacts = ValidateDuplicateFacts.DuplicateType.NONE
72
74
  self.validateXmlOim = False
arelle/ModelValue.py CHANGED
@@ -277,10 +277,11 @@ def tzinfo(tz: str | None) -> datetime.timezone | None:
277
277
  else:
278
278
  return datetime.timezone(datetime.timedelta(hours=int(tz[0:3]), minutes=int(tz[0]+tz[4:6])))
279
279
 
280
- def tzinfoStr(dt: datetime.datetime) -> str:
281
- tz = str(dt.tzinfo or "")
282
- if tz.startswith("UTC"):
283
- return tz[3:] or "Z"
280
+ def tzinfoStr(dt: datetime.datetime | datetime.date) -> str:
281
+ if isinstance(dt, datetime.datetime):
282
+ tz = str(dt.tzinfo or "")
283
+ if tz.startswith("UTC"):
284
+ return tz[3:] or "Z"
284
285
  return ""
285
286
 
286
287
  def dateTime(
arelle/RuntimeOptions.py CHANGED
@@ -33,6 +33,7 @@ class RuntimeOptions:
33
33
  about: Optional[str] = None
34
34
  anchFile: Optional[str] = None
35
35
  arcroleTypesFile: Optional[str] = None
36
+ baseTaxonomyValidationMode: Optional[str] = None
36
37
  betaObjectModel: Optional[bool] = False
37
38
  cacheDirectory: Optional[str] = None
38
39
  calFile: Optional[str] = None
arelle/ValidateXbrlDTS.py CHANGED
@@ -2,6 +2,7 @@
2
2
  See COPYRIGHT.md for copyright information.
3
3
  '''
4
4
  from __future__ import annotations
5
+ from enum import Enum, auto
5
6
  from typing import TYPE_CHECKING
6
7
  from arelle import (ModelDocument, ModelDtsObject, HtmlUtil, UrlUtil, XmlUtil, XbrlUtil, XbrlConst,
7
8
  XmlValidate)
@@ -49,6 +50,37 @@ inlineDisplayNonePattern = re.compile(r"display\s*:\s*none")
49
50
  # lookbehind below is to ignore even numbers of \ before illegal escape character
50
51
  illegalXsdPatternEscapeChar = re.compile(r"(?:(?:^|[^\\])(?:\\\\)*)(\\[^nrt\\|.^?*+{}()[\]pPsSiIcCdDwW-])")
51
52
 
53
+ class ValidateBaseTaxonomiesMode(Enum):
54
+ DISCLOSURE_SYSTEM = "disclosureSystem"
55
+ NONE = "none"
56
+ ALL = "all"
57
+
58
+ @staticmethod
59
+ def fromName(modeName: str) -> ValidateBaseTaxonomiesMode:
60
+ for mode in ValidateBaseTaxonomiesMode:
61
+ if mode.value == modeName:
62
+ return mode
63
+ raise ValueError(f"Unknown ValidateBaseTaxonomiesMode: {modeName}")
64
+
65
+ @staticmethod
66
+ def tooltip(enum: ValidateBaseTaxonomiesMode):
67
+ if enum == ValidateBaseTaxonomiesMode.DISCLOSURE_SYSTEM:
68
+ return _("Skip validation of base taxonomy files which are known to be valid by the disclosure system")
69
+ if enum == ValidateBaseTaxonomiesMode.NONE:
70
+ return _("Skip validation of all base taxonomy files")
71
+ if enum == ValidateBaseTaxonomiesMode.ALL:
72
+ return _("Validate all base taxonomy files")
73
+ raise ValueError(f"Unknown ValidateBaseTaxonomiesMode: {enum}")
74
+
75
+ @staticmethod
76
+ def menu():
77
+ return {
78
+ _("Use disclosure system settings"): ValidateBaseTaxonomiesMode.DISCLOSURE_SYSTEM.value,
79
+ _("Don't validate any base files"): ValidateBaseTaxonomiesMode.NONE.value,
80
+ _("Validate all base files"): ValidateBaseTaxonomiesMode.ALL.value,
81
+ }
82
+
83
+
52
84
  def arcFromConceptQname(arcElement):
53
85
  modelRelationship = baseSetRelationship(arcElement)
54
86
  if modelRelationship is None:
@@ -261,36 +293,42 @@ def checkDTS(val: ValidateXbrl, modelDocument: ModelDocument.ModelDocument, chec
261
293
  # XML validation checks (remove if using validating XML)
262
294
  val.extendedElementName = None
263
295
  isFilingDocument = False
264
- # validate contents of entry point document or its sibling/descendant documents or in report package of entry point
265
- if ((modelDocument.uri.startswith(val.modelXbrl.uriDir) or # document uri in same subtree as entry doocument
266
- (val.modelXbrl.fileSource.isOpen and modelDocument.filepath.startswith(val.modelXbrl.fileSource.baseurl))) and # document in entry submission's package
267
- modelDocument.targetNamespace not in val.disclosureSystem.baseTaxonomyNamespaces and
268
- modelDocument.xmlDocument):
269
- isFilingDocument = True
270
- val.valUsedPrefixes = set()
271
- val.schemaRoleTypes = {}
272
- val.schemaArcroleTypes = {}
273
- val.referencedNamespaces = set()
274
296
 
275
- val.containsRelationship = False
297
+ if modelDocument.xmlDocument is not None:
298
+ isExtensionTaxonomyDoc = _isExtensionTaxonomyDocument(val, modelDocument)
299
+ if isExtensionTaxonomyDoc or _shouldValidateBaseTaxonomyDoc(val, modelDocument):
300
+ isFilingDocument = True
301
+ val.valUsedPrefixes = set()
302
+ val.schemaRoleTypes = {}
303
+ val.schemaArcroleTypes = {}
304
+ val.referencedNamespaces = set()
276
305
 
277
- checkElements(val, modelDocument, modelDocument.xmlDocument)
306
+ val.containsRelationship = False
278
307
 
279
- if (modelDocument.type == ModelDocument.Type.INLINEXBRL and
280
- val.validateGFM and
281
- (val.documentTypeEncoding.lower() != 'utf-8' or val.metaContentTypeEncoding.lower() != 'utf-8')):
282
- val.modelXbrl.error("GFM.1.10.4",
283
- _("XML declaration encoding %(encoding)s and meta content type encoding %(metaContentTypeEncoding)s must both be utf-8"),
284
- modelXbrl=modelDocument, encoding=val.documentTypeEncoding,
285
- metaContentTypeEncoding=val.metaContentTypeEncoding)
286
- if val.validateSBRNL:
287
- for pluginXbrlMethod in pluginClassMethods("Validate.SBRNL.DTS.document"):
288
- pluginXbrlMethod(val, modelDocument)
289
- del val.valUsedPrefixes
290
- del val.schemaRoleTypes
291
- del val.schemaArcroleTypes
292
- for pluginXbrlMethod in pluginClassMethods("Validate.XBRL.DTS.document"):
293
- pluginXbrlMethod(val, modelDocument, isFilingDocument)
308
+ checkElements(val, modelDocument, modelDocument.xmlDocument)
309
+
310
+ if (modelDocument.type == ModelDocument.Type.INLINEXBRL and
311
+ val.validateGFM and
312
+ (val.documentTypeEncoding.lower() != 'utf-8' or val.metaContentTypeEncoding.lower() != 'utf-8')):
313
+ val.modelXbrl.error("GFM.1.10.4",
314
+ _("XML declaration encoding %(encoding)s and meta content type encoding %(metaContentTypeEncoding)s must both be utf-8"),
315
+ modelXbrl=modelDocument, encoding=val.documentTypeEncoding,
316
+ metaContentTypeEncoding=val.metaContentTypeEncoding)
317
+ if val.validateSBRNL:
318
+ for pluginXbrlMethod in pluginClassMethods("Validate.SBRNL.DTS.document"):
319
+ pluginXbrlMethod(val, modelDocument)
320
+ del val.valUsedPrefixes
321
+ del val.schemaRoleTypes
322
+ del val.schemaArcroleTypes
323
+
324
+ if isExtensionTaxonomyDoc:
325
+ # While not captured in the hook name, the Validate.XBRL.DTS.document hook has been historically used by
326
+ # plugins (see EDGAR plugin) to validate extension taxonomies. This worked because Arelle didn't fully
327
+ # validate base taxonomy documents. Although Arelle now validates all documents, it retains this logic for
328
+ # the plugin hook to prevent running validation rules intended solely for extension taxonomy documents
329
+ # against base taxonomy documents.
330
+ for pluginXbrlMethod in pluginClassMethods("Validate.XBRL.DTS.document"):
331
+ pluginXbrlMethod(val, modelDocument, isFilingDocument)
294
332
 
295
333
  val.roleRefURIs = None
296
334
  val.arcroleRefURIs = None
@@ -1388,3 +1426,21 @@ def checkIxContinuationChain(val, elt, chain=None):
1388
1426
  if contAt is not None:
1389
1427
  chain.append(elt)
1390
1428
  checkIxContinuationChain(val, contAt, chain)
1429
+
1430
+ def _isExtensionTaxonomyDocument(val: ValidateXbrl, modelDocument: ModelDocument.ModelDocument) -> bool:
1431
+ if modelDocument.uri.startswith(val.modelXbrl.uriDir):
1432
+ # document uri in same subtree as entry doocument.
1433
+ return True
1434
+
1435
+ # check if document in entry submission's package.
1436
+ return val.modelXbrl.fileSource.isOpen and modelDocument.filepath.startswith(val.modelXbrl.fileSource.baseurl)
1437
+
1438
+ def _shouldValidateBaseTaxonomyDoc(val: ValidateXbrl, modelDocument: ModelDocument.ModelDocument) -> bool:
1439
+ baseTaxonomyValidationMode = val.modelXbrl.modelManager.baseTaxonomyValidationMode
1440
+ if baseTaxonomyValidationMode == ValidateBaseTaxonomiesMode.NONE:
1441
+ return False
1442
+ if baseTaxonomyValidationMode == ValidateBaseTaxonomiesMode.ALL:
1443
+ return True
1444
+ if baseTaxonomyValidationMode == ValidateBaseTaxonomiesMode.DISCLOSURE_SYSTEM:
1445
+ return modelDocument.uri not in getattr(val.disclosureSystem, "standardTaxonomiesDict", {})
1446
+ raise ValueError(f"Invalid base taxonomy validation mode: {baseTaxonomyValidationMode}")
@@ -16,7 +16,7 @@ from arelle.ModelRenderingObject import (StrctMdlBreakdown, StrctMdlStructuralNo
16
16
  OPEN_ASPECT_ENTRY_SURROGATE, ROLLUP_SPECIFIES_MEMBER, ROLLUP_FOR_DIMENSION_RELATIONSHIP_NODE,
17
17
  aspectStrctNodes)
18
18
  from arelle.rendering.RenderingLayout import layoutTable
19
- from arelle.rendering.RenderingResolution import resolveTableStructure, RENDER_UNITS_PER_CHAR
19
+ from arelle.rendering.RenderingResolution import RENDER_UNITS_PER_CHAR
20
20
  from arelle.ModelValue import QName
21
21
  from arelle.ModelXbrl import DEFAULT
22
22
  from arelle.ViewFile import HTML, XML
@@ -10,7 +10,6 @@ from arelle import ViewFile
10
10
  from arelle.FunctionXs import xsString
11
11
  from arelle.ModelObject import ModelObject
12
12
  from arelle.Aspect import Aspect, aspectModels, aspectRuleAspects, aspectModelAspect, aspectStr
13
- from arelle.rendering.RenderingResolution import resolveTableStructure
14
13
  from arelle.rendering.RenderingLayout import layoutTable
15
14
  from arelle import XbrlConst
16
15
  from arelle.XmlUtil import elementFragmentIdentifier, addQnameValue
@@ -8,7 +8,7 @@ from arelle import (ViewWinTkTable, ModelDocument, ModelDtsObject, ModelInstance
8
8
  ModelXbrl, Locale, FunctionXfi,
9
9
  ValidateXbrlDimensions, ViewFileRenderedGrid, ViewFileRenderedLayout, ViewFileRenderedStructure)
10
10
  from arelle.ModelValue import qname, QName
11
- from arelle.rendering.RenderingResolution import resolveTableStructure, RENDER_UNITS_PER_CHAR
11
+ from arelle.rendering.RenderingResolution import RENDER_UNITS_PER_CHAR
12
12
  from arelle.rendering.RenderingLayout import layoutTable
13
13
  from arelle.ModelInstanceObject import ModelDimensionValue
14
14
  from arelle.ModelRenderingObject import (StrctMdlBreakdown, DefnMdlDefinitionNode,
arelle/XmlUtil.py CHANGED
@@ -1035,7 +1035,7 @@ def dateunionValue(
1035
1035
  ) -> str:
1036
1036
  if not isinstance(datetimeValue, (datetime.datetime, datetime.date)):
1037
1037
  return "INVALID"
1038
- tz = tzinfoStr(datetimeValue) # type: ignore[arg-type] # ModelValue type hints
1038
+ tz = tzinfoStr(datetimeValue)
1039
1039
  isDate = getattr(
1040
1040
  datetimeValue, 'dateOnly', False) or not hasattr(datetimeValue, 'hour')
1041
1041
  if isDate or (
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.36.30'
21
- __version_tuple__ = version_tuple = (2, 36, 30)
20
+ __version__ = version = '2.36.31'
21
+ __version_tuple__ = version_tuple = (2, 36, 31)
@@ -30,6 +30,17 @@ allowing for efficient data handling in Arelle.
30
30
  python arelleCmdLine.py --plugins saveLoadableOIM --file filing-documents.zip --saveTestcaseOimFileSuffix -savedOim.csv
31
31
  ```
32
32
 
33
+ - **Deduplicate facts**
34
+ To save an OIM instance with duplicate fact removed use the `--deduplicateOimFacts` argument with either `complete`,
35
+ `consistent-pairs`, or `consistent-sets` as the value.
36
+ For details on what eaxctly consitutes a duplicate fact and why there are multiple options read the
37
+ [Fact Deduplication][fact-deduplication] documentation.
38
+ ```bash
39
+ python arelleCmdLine.py --plugins saveLoadableOIM --file filing-documents.zip --saveLoadableOIM example.json --deduplicateOimFacts complete
40
+ ```
41
+
42
+ [fact-deduplication]: project:/user_guides/fact_deduplication.md
43
+
33
44
  ### GUI Usage
34
45
 
35
46
  - **Save Re-Loadable Output**:
@@ -51,6 +62,7 @@ import json
51
62
  import os
52
63
  import threading
53
64
  import zipfile
65
+ from collections.abc import Iterable
54
66
  from dataclasses import dataclass
55
67
  from datetime import datetime
56
68
  from decimal import Decimal
@@ -58,7 +70,7 @@ from math import isinf, isnan
58
70
  from numbers import Number
59
71
  from optparse import OptionParser
60
72
  from pathlib import Path
61
- from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Iterable, Optional, cast
73
+ from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Optional, cast
62
74
 
63
75
  import regex as re
64
76
  from openpyxl import Workbook
@@ -66,7 +78,7 @@ from openpyxl.cell.cell import WriteOnlyCell
66
78
  from openpyxl.styles import Alignment, Color, PatternFill, fills
67
79
  from openpyxl.worksheet.dimensions import ColumnDimension
68
80
 
69
- from arelle import ModelDocument, XbrlConst
81
+ from arelle import ModelDocument, ValidateDuplicateFacts, XbrlConst
70
82
  from arelle.ModelInstanceObject import ModelContext, ModelFact
71
83
  from arelle.ModelRelationshipSet import ModelRelationshipSet
72
84
  from arelle.ModelValue import (
@@ -446,6 +458,16 @@ def saveLoadableOIM(
446
458
  if isJSON:
447
459
  oimFeatures["xbrl:canonicalValues"] = True
448
460
 
461
+ factsToSave = modelXbrl.facts
462
+ pluginData = modelXbrl.modelManager.cntlr.getPluginData(PLUGIN_NAME)
463
+ if isinstance(pluginData, SaveLoadableOIMPluginData) and pluginData.deduplicateFactsType is not None:
464
+ deduplicatedFacts = frozenset(ValidateDuplicateFacts.getDeduplicatedFacts(modelXbrl, pluginData.deduplicateFactsType))
465
+ duplicateFacts = frozenset(f for f in modelXbrl.facts if f not in deduplicatedFacts)
466
+ if duplicateFacts:
467
+ for fact in duplicateFacts:
468
+ ValidateDuplicateFacts.logDeduplicatedFact(modelXbrl, fact)
469
+ factsToSave = [f for f in factsToSave if f not in duplicateFacts]
470
+
449
471
  if isJSON:
450
472
  # save JSON
451
473
  oimReport["facts"] = oimFacts = {}
@@ -465,7 +487,7 @@ def saveLoadableOIM(
465
487
  if fact.modelTupleFacts:
466
488
  saveJsonFacts(fact.modelTupleFacts, oimFacts)
467
489
 
468
- saveJsonFacts(modelXbrl.facts, oimFacts)
490
+ saveJsonFacts(factsToSave, oimFacts)
469
491
 
470
492
  # add footnotes as pseudo facts
471
493
  for ftObj in footnoteFacts:
@@ -651,7 +673,7 @@ def saveLoadableOIM(
651
673
  _writerow(aspectCols(fact))
652
674
  saveCSVfacts(fact.modelTupleFacts)
653
675
 
654
- saveCSVfacts(modelXbrl.facts)
676
+ saveCSVfacts(factsToSave)
655
677
  _close()
656
678
 
657
679
  # save footnotes
@@ -747,6 +769,7 @@ def saveOimFiles(
747
769
 
748
770
  @dataclass
749
771
  class SaveLoadableOIMPluginData(PluginData):
772
+ deduplicateFactsType: ValidateDuplicateFacts.DeduplicationType | None
750
773
  saveTestcaseOimFileSuffix: str | None
751
774
 
752
775
 
@@ -775,6 +798,12 @@ class SaveLoadableOIMPlugin(PluginHooks):
775
798
  dest="saveTestcaseOimFileSuffix",
776
799
  help=_("Save Testcase Variation OIM file (argument file suffix and type, such as -savedOim.csv"),
777
800
  )
801
+ parser.add_option(
802
+ "--deduplicateOimFacts",
803
+ action="store",
804
+ choices=[a.value for a in ValidateDuplicateFacts.DeduplicationType],
805
+ dest="deduplicateOimFacts",
806
+ help=_("Remove duplicate facts when saving the OIM instance"))
778
807
 
779
808
  @staticmethod
780
809
  def cntlrCmdLineUtilityRun(
@@ -783,8 +812,12 @@ class SaveLoadableOIMPlugin(PluginHooks):
783
812
  *args: Any,
784
813
  **kwargs: Any,
785
814
  ) -> None:
815
+ deduplicateOimFacts = cast(Optional[str], getattr(options, "deduplicateOimFacts", None))
786
816
  saveTestcaseOimFileSuffix = cast(Optional[str], getattr(options, "saveTestcaseOimFileSuffix", None))
787
- pluginData = SaveLoadableOIMPluginData(PLUGIN_NAME, saveTestcaseOimFileSuffix)
817
+ deduplicateFactsType = None
818
+ if deduplicateOimFacts is not None:
819
+ deduplicateFactsType = ValidateDuplicateFacts.DeduplicationType(deduplicateOimFacts)
820
+ pluginData = SaveLoadableOIMPluginData(PLUGIN_NAME, deduplicateFactsType, saveTestcaseOimFileSuffix)
788
821
  cntlr.setPluginData(pluginData)
789
822
 
790
823
  @staticmethod
@@ -44,11 +44,11 @@ def resolveTableStructure(view, viewTblELR):
44
44
 
45
45
  # find an ELR for this table object
46
46
  defnMdlTable = viewTblELR
47
- strctMdlTable = StrctMdlTable(defnMdlTable)
47
+ strctMdlTableSet = StrctMdlTableSet(defnMdlTable)
48
48
  for rel in view.modelXbrl.relationshipSet((XbrlConst.tableBreakdown, XbrlConst.tableBreakdownMMDD)).fromModelObject(defnMdlTable):
49
49
  # find relationships in table's linkrole
50
50
  view.defnSubtreeRelSet = view.modelXbrl.relationshipSet((XbrlConst.tableBreakdownTree, XbrlConst.tableBreakdownTreeMMDD), rel.linkrole)
51
- return resolveTableAxesStructure(view, strctMdlTable,
51
+ return resolveTableAxesStructure(view, strctMdlTableSet,
52
52
  view.modelXbrl.relationshipSet((XbrlConst.tableBreakdown, XbrlConst.tableBreakdownMMDD), rel.linkrole))
53
53
  # no relationships from table found
54
54
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: arelle-release
3
- Version: 2.36.30
3
+ Version: 2.36.31
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License: Apache-2.0
@@ -1,12 +1,12 @@
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=7ZgI4x4g2dTET6Er2xIWowrSzaQHSOo5IQ8xwyR5BQQ,92901
4
+ arelle/CntlrCmdLine.py,sha256=XsSQBeqxlV9bODedGkmUz4nHbPHAAaxo42KdpmpsBj0,94214
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
8
8
  arelle/CntlrWebMain.py,sha256=eOzqrp0XA3TrOu7m6Arcvnmdxt7-7zQ8xyaLs-dpDHg,51028
9
- arelle/CntlrWinMain.py,sha256=GuzXetvtwkz8Ly47hRiqd3d6jlgYth7YvyqvSuotego,94914
9
+ arelle/CntlrWinMain.py,sha256=0Ctbf7Tk0Y0pjJhLlZecwL46FUmdjw3d1joto21DwOA,96174
10
10
  arelle/CntlrWinTooltip.py,sha256=6MzoAIfkYnNu_bl_je8n0adhwmKxAIcymkg9Tij9Z4M,7951
11
11
  arelle/DialogAbout.py,sha256=XXzMV0fO4BQ3-l1Puirzmn7EZEdmgJg7JNYdJm1FueM,1987
12
12
  arelle/DialogArcroleGroup.py,sha256=r81OT3LFmMkoROpFenk97oVEyQhibKZ1QgDHvMsyCl0,7547
@@ -38,7 +38,7 @@ arelle/ModelDocument.py,sha256=bP8WbSmBlk3ZxgrQxIfXMfU3Xjo7kgTtWZzxnCZvI88,12921
38
38
  arelle/ModelDtsObject.py,sha256=JXPRiFOsbB5tZjEDc6rECuUtXMbF4oxfnwrQvKo-i5U,88656
39
39
  arelle/ModelFormulaObject.py,sha256=beUSxEFm7aoa9iimmvXLYCHdizAtOmhDqk6wmvbc9Zg,122537
40
40
  arelle/ModelInstanceObject.py,sha256=pAcwQBr85_fQCGT18JSOGGwzAZ3J-oWIU9sj9UUXLOk,73928
41
- arelle/ModelManager.py,sha256=1TflmGhni3ox_yTmZl5JKU_hGlVXmN-2q_Ncgh4h9A4,10926
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
44
44
  arelle/ModelRelationshipSet.py,sha256=_1T3NAS0IRgK8IWFe7nh-qxXZ7htA80i_dueyU8JYaU,24654
@@ -46,7 +46,7 @@ arelle/ModelRenderingObject.py,sha256=iPhSUlSBG-FLzAfIdUW06UZDgTCaZJ4K2mxvAtSe2B
46
46
  arelle/ModelRssItem.py,sha256=GzFkmluOlFsVcrxn9HAyOAcuE7rcHUOGkp4Q6F2IlT8,7713
47
47
  arelle/ModelRssObject.py,sha256=xjuwyJ8pU5sQmNPJFQakDEEnujZg2bMCTaj3zVezHL8,992
48
48
  arelle/ModelTestcaseObject.py,sha256=qWSphg4BX8HMcmEt_IJ8pS_uU1G7XeIldTshEpAi0GY,21873
49
- arelle/ModelValue.py,sha256=DWKeqz558-IDcFJ6fR0s9yiGo8kEkintYQ67_3rlU_g,39360
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
@@ -56,7 +56,7 @@ arelle/PluginUtils.py,sha256=0vFQ29wVVpU0cTY3YOBL6FhNQhhCTwShBH4qTJGLnvc,2426
56
56
  arelle/PrototypeDtsObject.py,sha256=0lf60VcXR_isx57hBPrc7vEMkFpYkVuK4JVBSmopzkQ,7989
57
57
  arelle/PrototypeInstanceObject.py,sha256=CXUoDllhDqpMvSQjqIYi1Ywp-J8fLhQRV9wVD2YXgVo,13204
58
58
  arelle/PythonUtil.py,sha256=pP59gx2-z3dKLesUqiDVZmbhCOS1kpQzowsQ9ShJi-0,7947
59
- arelle/RuntimeOptions.py,sha256=luxDPPvfVkPc_3sQuCOiCq7huJopabOS6Ibr0HhiKiw,8665
59
+ arelle/RuntimeOptions.py,sha256=89pSw3zFhjHzn75RaHAl4-iPXL8awTZny-frozn9EHQ,8718
60
60
  arelle/SocketUtils.py,sha256=1wa2sA_QhM8F1klHFq90V1AgO1-hY9pJm0554FiF7Lc,677
61
61
  arelle/SystemInfo.py,sha256=6330pNedRkAPlEKl-ZdaZHiGuucEGZMI-Jrdy7B1rrU,2454
62
62
  arelle/TableStructure.py,sha256=PABOHJiTa56cHyF9qRLD7TohmCHyDTrGEltW8toP_rk,29409
@@ -73,7 +73,7 @@ arelle/ValidateUtr.py,sha256=oxOPrOa1XEzBay4miXvx6eRLTnVFYUIJC9ueWUk4EkI,13633
73
73
  arelle/ValidateVersReport.py,sha256=RMe7GlcyZV0HoVFHL0qOGrKm4et-6yPq5dmikkhnvoU,43196
74
74
  arelle/ValidateXbrl.py,sha256=kBiY_q9QmORwC8VxGpRq9mfufknt08nEAeSgNh1ov-M,78005
75
75
  arelle/ValidateXbrlCalcs.py,sha256=vx1LYbu2l6wY88O9vyaThK5gOG59R9ggHX3FapbN3XA,44308
76
- arelle/ValidateXbrlDTS.py,sha256=8WYc6ig8IUgwp9ZRlh55mMGlQkcv43TXajVi9lmlZtg,101297
76
+ arelle/ValidateXbrlDTS.py,sha256=yxvpTpImEbrQuLJ2aJf38FjA-OEznpWWdsDK0GtLXIU,104003
77
77
  arelle/ValidateXbrlDimensions.py,sha256=Qv7_CI65SiUcpgsnEc86XuMjKz81-170wE5dmZqnvHc,38373
78
78
  arelle/Version.py,sha256=Cdl7IhBHOIdfgWtBVAkeG4cXby84g21NOjkECsgaflM,1067
79
79
  arelle/ViewFile.py,sha256=Bvh50RAHDEauAmF0KPHWAZocMyA0UCduJ46e0wbSnPE,19286
@@ -83,8 +83,8 @@ arelle/ViewFileFactList.py,sha256=AVYoDJnhUoIkX7fT2D-bOrKP5g1JAwVnmSr4FYhT4iI,71
83
83
  arelle/ViewFileFactTable.py,sha256=I3U6XomCHE5bnbUN_WMq80LyYnPz0GRgYdRDm8Pu3tg,17013
84
84
  arelle/ViewFileFormulae.py,sha256=753p3pAZsoxx6-3b_xR_CDFReeMBgBZOCV_TIO0FuJE,4740
85
85
  arelle/ViewFileRelationshipSet.py,sha256=ZNxRQc57FMM1erJk-VcuVMeScMxr7zev17Rb3ng0JK0,16764
86
- arelle/ViewFileRenderedGrid.py,sha256=if0Ch7FBPG6cVylEnk3meFgi6UHmzTP03v239Eg3-pY,14135
87
- arelle/ViewFileRenderedLayout.py,sha256=k0sEd0zBAiFlRTeStJRhTkLt5EF_XuFXf7xVD2NvVsc,12241
86
+ arelle/ViewFileRenderedGrid.py,sha256=I0Q6tyhbu1vcZvWiigAGrPK2bHv_ixsZvLr3merYPJo,14112
87
+ arelle/ViewFileRenderedLayout.py,sha256=aCTpOMBUIKYE4Xu1OFPoo_NTqp1NqefpXze6qWcDKw8,12170
88
88
  arelle/ViewFileRenderedStructure.py,sha256=VemGa9HlVHvazPD3-yOrtDWTggNBkHkNtzXHtLUqngA,6192
89
89
  arelle/ViewFileRoleTypes.py,sha256=4rk7D0sd5TP6o_WNm2wkBxB2OeltUrk6InfJHPLwLDQ,2024
90
90
  arelle/ViewFileRssFeed.py,sha256=7ATWTC42QrCPTZxTK8-MH0-mDOGg0GUms7AWdzJfPKc,2726
@@ -103,7 +103,7 @@ arelle/ViewWinList.py,sha256=dz7qip9DpvVi96j71MZQoQpaVguO4FRka-_TOnsJtaE,4318
103
103
  arelle/ViewWinPane.py,sha256=ZTz1fL3-QXZLAIMjqAjGoe9IEMVG7s9AzFYamV2PTco,2783
104
104
  arelle/ViewWinProperties.py,sha256=FutWixP6g-_riNsnCxef6dej_kNqH_E2F3anse60aV4,2403
105
105
  arelle/ViewWinRelationshipSet.py,sha256=7XAmQ0o9orMDFB0Ew_Ph6FYHtsvss2c6drIQajsOnXk,25577
106
- arelle/ViewWinRenderedGrid.py,sha256=C0bD27zKb_DpO3N4_UCeVkYlt1rP1kKEy1kp8-l1riU,84648
106
+ arelle/ViewWinRenderedGrid.py,sha256=OFFypVdoPke6FVa0fPC0TaFAC2nBOIsJOFF62xNsTnQ,84625
107
107
  arelle/ViewWinRoleTypes.py,sha256=hc1pM5Q_LYOxDxMJTvG1O4_pQ0Uni9kpZ6hPuxKNs9w,4794
108
108
  arelle/ViewWinRssFeed.py,sha256=htgZKAxA3ivuE6p-jvtU2HIx78LAtfAkO2Q-KtGYHIk,6057
109
109
  arelle/ViewWinTests.py,sha256=1RNerlovLzyvemNPFjraEVmpVWcWiw_DQ5LxVZm0R4M,9414
@@ -117,13 +117,13 @@ arelle/WebCache.py,sha256=_GDLhkEf1fxe0nTdO5eCKdNcB1f3Dfv2E6H5PPjNeX8,44733
117
117
  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
- arelle/XmlUtil.py,sha256=vDk9HbQJWi3E0GLf-kvlvUfn_gnWjkHt7uVaZe6Mu08,58825
120
+ arelle/XmlUtil.py,sha256=1VToOOylF8kbEorEdZLThmq35j9bmuF_DS2q9NthnHU,58774
121
121
  arelle/XmlValidate.py,sha256=TL72yUQA0PqdcFgw7rW8uxUWw6i1pN7q6V42Uk6gMYY,45857
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=7USuSTEr7meBCL_d0f4pHt3zWfhoYI7F4kw9wVttOEo,515
126
+ arelle/_version.py,sha256=nyprLxQLl4J8OXRCVQ_v7F0qoM1HHVnAlbQEmqspAag,515
127
127
  arelle/typing.py,sha256=Ct5lrNKRow_o9CraMEXNza8nFsJ_iGIKoUeGfPs2dxI,1084
128
128
  arelle/api/Session.py,sha256=Vd09RAutWX7mxHSsrW7Bl8CsE1UzXpQpAJsZb55mqng,6188
129
129
  arelle/archive/CustomLogger.py,sha256=v_JXOCQLDZcfaFWzxC9FRcEf9tQi4rCI4Sx7jCuAVQI,1231
@@ -323,7 +323,7 @@ arelle/plugin/saveCHComponentFile.py,sha256=phW-n96P0BWONLqX3wBcuNcDa_IQ8QVfFWKL
323
323
  arelle/plugin/saveDTS.py,sha256=D8hfFiM9Gc9LE7ZV0-pDvOHeU7Y5ebOzZx_nXzoZrl8,3216
324
324
  arelle/plugin/saveHtmlEBAtables.py,sha256=OITN4ftI_atUO5NvrDJDKUc0CAk67GY68Jl16xDBXiI,10961
325
325
  arelle/plugin/saveLoadableExcel.py,sha256=ZPYB6injFabav0dRzgS7adCFzfHkwtftjl3PfBjijuU,20539
326
- arelle/plugin/saveLoadableOIM.py,sha256=19R5mZzIDkPohEdabs22nOhIZoEPe8vR0HczqN3oSI0,36239
326
+ arelle/plugin/saveLoadableOIM.py,sha256=onT61QRygFCMGS7xTZHJz9WSo1V5PyqKQRtoTBf7GDE,38180
327
327
  arelle/plugin/saveSKOS.py,sha256=7Z1Qedf83zMo9EbigKkxNpiMjzkTYQvLEnwWMObLc1Y,12465
328
328
  arelle/plugin/saveSampleInstance.py,sha256=w66Nd4He8yIK4Il_M9qnelpeUJ_6cBBe5q01DanOxEA,23823
329
329
  arelle/plugin/streamingExtensions.py,sha256=gDt3TfkHcDHqnP8jnBWmC3j5i0u53lgUOSKxHJU8HnI,47646
@@ -431,7 +431,7 @@ arelle/plugin/xbrlDB/sql/semantic/xbrlSemanticPostgresDB.ddl,sha256=DYBE4m2gSp-2
431
431
  arelle/plugin/xbrlDB/sql/semantic/xbrlSemanticSQLiteDB.ddl,sha256=TRb4zLoXUGKkBU1ZR5KCpMLBpujtNiL_WDdnv4DfBL0,726301
432
432
  arelle/rendering/RenderingEvaluator.py,sha256=suQhQsx5KD1QJMGxIiPXGbUOKQMTwg1oSSJlgl8J8kk,17781
433
433
  arelle/rendering/RenderingLayout.py,sha256=dIpR0hGyIvYR-Qj61wSb0YkgJdHbtqtlAtFGEbb65JY,31082
434
- arelle/rendering/RenderingResolution.py,sha256=Prpaaz5B4EfK9ak8cb7kgIL0DHB4hSizreAsXkI4r8Y,54544
434
+ arelle/rendering/RenderingResolution.py,sha256=W21PdF7UTmL546Hbtycaf2semGWOPNrpETDeQR9elnA,54553
435
435
  arelle/resources/cache/http/www.eurofiling.info/eu/fr/xbrl/ext/filing-indicators.xsd,sha256=BfDzYGRz5zofzjnvVP_ZdTVtddxKdsrYfjZ3dK_hJIQ,1243
436
436
  arelle/resources/cache/http/www.w3.org/2001/XMLSchema.xsd,sha256=52ehWcF5vW5NwrrCpjpi9Qy9An7BnWtcyescLzPgyy4,87677
437
437
  arelle/resources/cache/http/www.w3.org/2001/xml.xsd,sha256=YZYPsxMeOAIsqtU2Di8zozgleKs8gM1YvXQyDt5hsgw,8836
@@ -741,30 +741,30 @@ tests/integration_tests/validation/download_assets.py,sha256=muHklbrvYEbxqqAM8mU
741
741
  tests/integration_tests/validation/run_conformance_suites.py,sha256=pDtBUEfT-pggxKEN2cg3vk0_Cko6wgV3x-6cX7y3Y3M,8206
742
742
  tests/integration_tests/validation/test_conformance_suites.py,sha256=VdwY0QtV6g00M9bv1XNs4qBTwxPxCh5-z4XoDdEhgeM,711
743
743
  tests/integration_tests/validation/validation_util.py,sha256=W5_NpjlqVKlmV8LGgzQLIFtmgEFPO4YgSOTymQX_rns,21541
744
- tests/integration_tests/validation/conformance_suite_configurations/cipc_current.py,sha256=qiCU5T4xf9nI0eB9UUOya8z4UF7DEcdmJO9mSJOhIY0,598
745
- tests/integration_tests/validation/conformance_suite_configurations/dba_current.py,sha256=etV7p8ulvZVzgPeCakfgU8sJkkqBemqv8fr7Yy3JvfE,831
746
- tests/integration_tests/validation/conformance_suite_configurations/dba_multi_current.py,sha256=HgedW76v8bsCIuiUJP0j41p5meYnHxClqh1-DQ_1q2w,793
744
+ tests/integration_tests/validation/conformance_suite_configurations/cipc_current.py,sha256=oLXe3xIsEZLz3cv1cDdMQIuS_NgyI9Uimc9hy0NMWqg,642
745
+ tests/integration_tests/validation/conformance_suite_configurations/dba_current.py,sha256=j-7jCpzbGXbOzG8HGEyS0ciCYSPZzZLV44VQGhP3Hmc,875
746
+ tests/integration_tests/validation/conformance_suite_configurations/dba_multi_current.py,sha256=ICkP18Wu7aTDfszfYlrfVnBj9oe7ppXR-8wxQqCPqW0,837
747
747
  tests/integration_tests/validation/conformance_suite_configurations/efm_current.py,sha256=LoAuqV3uMiQSfgQ34c_T70ph3YT7py5nu10podbIFRM,1322
748
748
  tests/integration_tests/validation/conformance_suite_configurations/efm_reg_dqc.py,sha256=HiT8OcRAOVKLsl95Y91L66FeOsIMMMAQCs-DLMG-Lb0,739
749
749
  tests/integration_tests/validation/conformance_suite_configurations/efm_reg_pragmatic.py,sha256=U6dew0sIibjZe4r6na912qyIVAjxljh2HDix-8AwvhM,727
750
- tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2021.py,sha256=e7GZE8CWPRsD_pSfOJoKa77M_XA6QmqIm2rY3S6P4tM,1102
751
- tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2022.py,sha256=daTAIihbg1HHDnr-agqds_MDcIEDC5oNQPi0ZQYnypQ,1531
752
- tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2023.py,sha256=V4e8Zh-qYtdj6HHiJOacJsld3SoMKMJYjwfXitKGNQc,1789
753
- tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2024.py,sha256=2jRCKR0vI6SK3NEioQGCl10Iq49NGQ2-hWtXFY-uKPA,1566
754
- tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2021.py,sha256=ythem-_IxhDa_QW8mQy-uh2xZaOiB6omM8OpzLO8-Ig,927
755
- tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2022.py,sha256=SHTxy0mIz0NjI6isXpaNyVWdl4I1XAl8Zdu3AtQK6hg,904
756
- tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2023.py,sha256=YmmpKVvqrZ8EpdwHA4IDNzTe7zM0BFcgfTUl8-_VrGY,876
757
- tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2024.py,sha256=dyX5nzfzCA69DKlSSx7ciUyz4nvPHOOGqj5qDR4iHXI,922
758
- tests/integration_tests/validation/conformance_suite_configurations/hmrc_current.py,sha256=fTX6o2zEZjo_Ay42vbedDf1632d-Zc4uiouq-7wjm0o,1852
759
- tests/integration_tests/validation/conformance_suite_configurations/kvk_nt16.py,sha256=rSdOZHqVawB_brFp_5moXH_NHE1NQDQWLs6-2EkzKDo,1481
760
- tests/integration_tests/validation/conformance_suite_configurations/kvk_nt17.py,sha256=xCw0SCw35O992C3yUaC5DuGr2_jvxE33HA-LdefASHY,1248
761
- tests/integration_tests/validation/conformance_suite_configurations/kvk_nt18.py,sha256=at-cyJSYcUht-mmBNkQMXxNG0EHoKU2iBqhnMLzW0Yo,1161
762
- tests/integration_tests/validation/conformance_suite_configurations/kvk_nt19.py,sha256=uCB7uy-K0lmc7QgQqEAg2cRtQYPJBHQzEkWfiCmP-sM,1155
763
- tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py,sha256=3guWPl8aqsREYk_L31fcd6I2l3GEGYHh_1xhmR0g4tE,802
764
- tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py,sha256=Gqzu2HlT3L27HsRMJb37GWSXepjscH0ika0AwzoCwbs,802
765
- tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py,sha256=D1ZZYKcs-GUi_gsXdhclECsA1wfPQ6J8v3U8oosMOQY,801
766
- tests/integration_tests/validation/conformance_suite_configurations/nl_nt19.py,sha256=11THlh3bB2ck0KVTH7RMkkTvMY0Q6ydDSEw_U-y7qp4,800
767
- tests/integration_tests/validation/conformance_suite_configurations/ros_current.py,sha256=4WhI0TbE52rcgoJfopSkht1vIcB07Fjl00zq0QAUir0,681
750
+ tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2021.py,sha256=KpXpm6kMYAp94K-J7-GZS47iRVE9Kr5cfxPniFFSI3A,1146
751
+ tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2022.py,sha256=tllelZOW7R5udOhEtjnQGAVy0MxAAM03OY_cC4pstgY,1575
752
+ tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2023.py,sha256=Imhckmr7vui2xrWdsWaengly-5e2CUeoqh2ZDTscek8,1833
753
+ tests/integration_tests/validation/conformance_suite_configurations/esef_ixbrl_2024.py,sha256=Eu3I5Tn1ow7fB4y9KMgSe9q4W5NBfME6pHzBBmEwgqM,1610
754
+ tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2021.py,sha256=535hJ9CEPJPT-ciHumkii6xlJXwsV1KfL_Q9a4fjxcc,971
755
+ tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2022.py,sha256=fr5GIUrbKB4_f7YIkSQz9hbpqFWuQyLmo4awtvODfU4,948
756
+ tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2023.py,sha256=hOpfcMcnu_plJB-mpqyTywAncW_iPJGlZsn5hfD9sk0,920
757
+ tests/integration_tests/validation/conformance_suite_configurations/esef_xhtml_2024.py,sha256=4x8r-B6f4W2J_KFGKi2Q923TxdJxKv6_YxQS8I6Uo1k,966
758
+ tests/integration_tests/validation/conformance_suite_configurations/hmrc_current.py,sha256=0a-RIuA4xoLXyxenXt740wzhV-0JX2aOrlSPF9qQgE0,1896
759
+ tests/integration_tests/validation/conformance_suite_configurations/kvk_nt16.py,sha256=fIGmQ_7yJAnFvA-Si6dGOpdUlJbi8FQ-ODWoAC09SgI,1525
760
+ tests/integration_tests/validation/conformance_suite_configurations/kvk_nt17.py,sha256=lmEZonthFm0YKFmp1dwXtdJ2T7txUeSpL4mbAo8fl4Y,1292
761
+ tests/integration_tests/validation/conformance_suite_configurations/kvk_nt18.py,sha256=EG2RQVkvFENhzUF3fl3QvDnH7ZPYS1n1Fo8bhfmSczM,1205
762
+ tests/integration_tests/validation/conformance_suite_configurations/kvk_nt19.py,sha256=FAzf9RhRmn_8yowpplJho2zEspX9FxJiVq8SjZT3Dsc,1199
763
+ tests/integration_tests/validation/conformance_suite_configurations/nl_nt16.py,sha256=O_LFVBZPkjxmbrU7_C7VTLtrdoCUx2bYXOXw6_MlRtQ,846
764
+ tests/integration_tests/validation/conformance_suite_configurations/nl_nt17.py,sha256=aTN3Ez6lPsZsuypHZP84DneOtYxUZSjUiGypHy6ofHQ,846
765
+ tests/integration_tests/validation/conformance_suite_configurations/nl_nt18.py,sha256=sqHLjrHc95dTu0guTgKkphaKM1zNfKGnN4GKkZDLzeU,845
766
+ tests/integration_tests/validation/conformance_suite_configurations/nl_nt19.py,sha256=_CiNflzz0ItJslvv22CL70yyK3P7hVGYLZ3BIb0y9Ww,844
767
+ tests/integration_tests/validation/conformance_suite_configurations/ros_current.py,sha256=yEt0XHxX6jNpbslQaIeOce07eh3dsdGP-e7ydOiZzog,725
768
768
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_2_1.py,sha256=GFPkzqk2lwDgHEUIRAFS9-htMOS0THmjsXT9eJDfiSc,1494
769
769
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_calculations_1_1.py,sha256=0XV1FXxFiSk5hcsSaEsT7JVGQ3KXV8FrHNmr-tqo3Zg,816
770
770
  tests/integration_tests/validation/conformance_suite_configurations/xbrl_dimensions_1_0.py,sha256=NtliBDgTxKvpC3j75hmJSrcIIkVlA4q_q6OEXf9b28w,1871
@@ -1553,9 +1553,9 @@ tests/unit_tests/arelle/oim/test_load.py,sha256=NxiUauQwJVfWAHbbpsMHGSU2d3Br8Pki
1553
1553
  tests/unit_tests/arelle/plugin/test_plugin_imports.py,sha256=bdhIs9frAnFsdGU113yBk09_jis-z43dwUItMFYuSYM,1064
1554
1554
  tests/unit_tests/arelle/plugin/validate/ESEF/ESEF_Current/test_validate_css_url.py,sha256=XHABmejQt7RlZ0udh7v42f2Xb2STGk_fSaIaJ9i2xo0,878
1555
1555
  tests/unit_tests/arelle/utils/validate/test_decorator.py,sha256=ZS8FqIY1g-2FCbjF4UYm609dwViax6qBMRJSi0vfuhY,2482
1556
- arelle_release-2.36.30.dist-info/LICENSE.md,sha256=rMbWwFLGzPgLoEjEu8LCmkpWDTqsvfOI-wzLSfeJsis,4107
1557
- arelle_release-2.36.30.dist-info/METADATA,sha256=jHU6UnsmJtN_xVSKcvoAFupvFebLftPn3xPYcAVVIAU,9010
1558
- arelle_release-2.36.30.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
1559
- arelle_release-2.36.30.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1560
- arelle_release-2.36.30.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1561
- arelle_release-2.36.30.dist-info/RECORD,,
1556
+ arelle_release-2.36.31.dist-info/LICENSE.md,sha256=rMbWwFLGzPgLoEjEu8LCmkpWDTqsvfOI-wzLSfeJsis,4107
1557
+ arelle_release-2.36.31.dist-info/METADATA,sha256=dpGpu4tPQ9S6bIglo-0xhUDBAFh5hhNGL6A-MbpERRo,9010
1558
+ arelle_release-2.36.31.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
1559
+ arelle_release-2.36.31.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
1560
+ arelle_release-2.36.31.dist-info/top_level.txt,sha256=ZYmYGmhW5Jvo3vJ4iXBZPUI29LvYhntom04w90esJvU,13
1561
+ arelle_release-2.36.31.dist-info/RECORD,,
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'cipc',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'arl-2022-preview',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'arl-2024-multi-target-preview',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -8,6 +8,7 @@ from tests.integration_tests.validation.conformance_suite_config import (
8
8
  config = ConformanceSuiteConfig(
9
9
  args=[
10
10
  '--disclosureSystem', 'esef-2021',
11
+ '--baseTaxonomyValidation', 'none',
11
12
  ],
12
13
  assets=[
13
14
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -7,6 +7,7 @@ from tests.integration_tests.validation.conformance_suite_config import (
7
7
  config = ConformanceSuiteConfig(
8
8
  args=[
9
9
  '--disclosureSystem', 'esef-2022',
10
+ '--baseTaxonomyValidation', 'none',
10
11
  ],
11
12
  assets=[
12
13
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -7,6 +7,7 @@ from tests.integration_tests.validation.conformance_suite_config import (
7
7
  config = ConformanceSuiteConfig(
8
8
  args=[
9
9
  '--disclosureSystem', 'esef-2023',
10
+ '--baseTaxonomyValidation', 'none',
10
11
  ],
11
12
  assets=[
12
13
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -10,6 +10,7 @@ from tests.integration_tests.validation.conformance_suite_config import (
10
10
  config = ConformanceSuiteConfig(
11
11
  args=[
12
12
  '--disclosureSystem', 'esef-2024',
13
+ '--baseTaxonomyValidation', 'none',
13
14
  ],
14
15
  assets=[
15
16
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'esef-unconsolidated-2021',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'esef-unconsolidated-2022',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'esef-unconsolidated-2023',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -9,6 +9,7 @@ from tests.integration_tests.validation.conformance_suite_config import (
9
9
  config = ConformanceSuiteConfig(
10
10
  args=[
11
11
  '--disclosureSystem', 'esef-unconsolidated-2024',
12
+ '--baseTaxonomyValidation', 'none',
12
13
  ],
13
14
  assets=[
14
15
  ConformanceSuiteAssetConfig.conformance_suite(
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'hmrc',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -9,6 +9,7 @@ EXTRACTED_PATH = Path(ZIP_PATH.stem)
9
9
  config = ConformanceSuiteConfig(
10
10
  args=[
11
11
  '--disclosureSystem', 'NT16',
12
+ '--baseTaxonomyValidation', 'none',
12
13
  ],
13
14
  assets=[
14
15
  ConformanceSuiteAssetConfig.nested_conformance_suite(
@@ -9,6 +9,7 @@ EXTRACTED_PATH = Path(ZIP_PATH.stem)
9
9
  config = ConformanceSuiteConfig(
10
10
  args=[
11
11
  '--disclosureSystem', 'NT17',
12
+ '--baseTaxonomyValidation', 'none',
12
13
  ],
13
14
  assets=[
14
15
  ConformanceSuiteAssetConfig.nested_conformance_suite(
@@ -8,6 +8,7 @@ EXTRACTED_PATH = Path(ZIP_PATH.stem)
8
8
  config = ConformanceSuiteConfig(
9
9
  args=[
10
10
  '--disclosureSystem', 'NT18',
11
+ '--baseTaxonomyValidation', 'none',
11
12
  ],
12
13
  assets=[
13
14
  ConformanceSuiteAssetConfig.nested_conformance_suite(
@@ -8,6 +8,7 @@ EXTRACTED_PATH = Path(ZIP_PATH.stem)
8
8
  config = ConformanceSuiteConfig(
9
9
  args=[
10
10
  '--disclosureSystem', 'NT19',
11
+ '--baseTaxonomyValidation', 'none',
11
12
  ],
12
13
  assets=[
13
14
  ConformanceSuiteAssetConfig.nested_conformance_suite(
@@ -6,6 +6,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
6
6
  config = ConformanceSuiteConfig(
7
7
  args=[
8
8
  '--disclosureSystem', 'NT16',
9
+ '--baseTaxonomyValidation', 'none',
9
10
  ],
10
11
  assets=[
11
12
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -6,6 +6,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
6
6
  config = ConformanceSuiteConfig(
7
7
  args=[
8
8
  '--disclosureSystem', 'NT17',
9
+ '--baseTaxonomyValidation', 'none',
9
10
  ],
10
11
  assets=[
11
12
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -6,6 +6,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
6
6
  config = ConformanceSuiteConfig(
7
7
  args=[
8
8
  '--disclosureSystem', 'NT18',
9
+ '--baseTaxonomyValidation', 'none',
9
10
  ],
10
11
  assets=[
11
12
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -6,6 +6,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
6
6
  config = ConformanceSuiteConfig(
7
7
  args=[
8
8
  '--disclosureSystem', 'NT19',
9
+ '--baseTaxonomyValidation', 'none',
9
10
  ],
10
11
  assets=[
11
12
  ConformanceSuiteAssetConfig.local_conformance_suite(
@@ -4,6 +4,7 @@ from tests.integration_tests.validation.conformance_suite_config import Conforma
4
4
  config = ConformanceSuiteConfig(
5
5
  args=[
6
6
  '--disclosureSystem', 'ros',
7
+ '--baseTaxonomyValidation', 'none',
7
8
  ],
8
9
  assets=[
9
10
  ConformanceSuiteAssetConfig.local_conformance_suite(