arelle-release 2.37.31__py3-none-any.whl → 2.37.33__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.

arelle/CntlrCmdLine.py CHANGED
@@ -634,7 +634,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
634
634
  super().__init__(hasGui=False, uiLang=uiLang, disable_persistent_config=disable_persistent_config, logFileName=logFileName)
635
635
  self.preloadedPlugins = {}
636
636
 
637
- def run(self, options: RuntimeOptions, sourceZipStream=None, responseZipStream=None, sourceZipStreamFileName=None) -> bool:
637
+ def run(self, options: RuntimeOptions, sourceZipStream=None, responseZipStream=None) -> bool:
638
638
  """Process command line arguments or web service request, such as to load and validate an XBRL document, or start web server.
639
639
 
640
640
  When a web server has been requested, this method may be called multiple times, once for each web service (REST) request that requires processing.
@@ -998,7 +998,7 @@ class CntlrCmdLine(Cntlr.Cntlr):
998
998
  _entryPoints.append({"file":f})
999
999
  filesource = None # file source for all instances if not None
1000
1000
  if sourceZipStream:
1001
- filesource = FileSource.openFileSource(None, self, sourceZipStream=sourceZipStream, sourceZipStreamFileName=sourceZipStreamFileName)
1001
+ filesource = FileSource.openFileSource(None, self, sourceZipStream)
1002
1002
  elif len(_entryPoints) == 1 and "file" in _entryPoints[0]: # check if an archive and need to discover entry points (and not IXDS)
1003
1003
  entryPath = PackageManager.mappedUrl(_entryPoints[0]["file"])
1004
1004
  filesource = FileSource.openFileSource(entryPath, self, checkIfXmlIsEis=_checkIfXmlIsEis)
arelle/CntlrWebMain.py CHANGED
@@ -19,7 +19,7 @@ from bottle import Bottle, HTTPResponse, request, response, static_file # type:
19
19
 
20
20
  from arelle import Version
21
21
  from arelle.CntlrCmdLine import CntlrCmdLine
22
- from arelle.FileSource import FileNamedStringIO
22
+ from arelle.FileSource import FileNamedBytesIO, FileNamedStringIO
23
23
  from arelle.logging.formatters.LogFormatter import LogFormatter
24
24
  from arelle.logging.handlers.LogToBufferHandler import LogToBufferHandler
25
25
  from arelle.PluginManager import pluginClassMethods
@@ -263,19 +263,16 @@ def validation(file: str | None = None) -> str | bytes:
263
263
  isValidation = 'validation' == requestPathParts[-1] or 'validation' == requestPathParts[-2]
264
264
  view = request.query.view
265
265
  viewArcrole = request.query.viewArcrole
266
- sourceZipStreamFileName = None
267
266
  sourceZipStream = None
268
267
  if request.method == 'POST':
269
268
  mimeType = request.get_header("Content-Type")
270
269
  if mimeType and mimeType.startswith("multipart/form-data"):
271
270
  if upload := request.files.get("upload"):
272
- sourceZipStreamFileName = upload.filename
273
- sourceZipStream = upload.file
271
+ sourceZipStream = FileNamedBytesIO(upload.filename, upload.file.read())
274
272
  else:
275
273
  errors.append(_("POST 'multipart/form-data' request must include 'upload' part containing the XBRL file to process."))
276
274
  elif mimeType in ('application/zip', 'application/x-zip', 'application/x-zip-compressed', 'multipart/x-zip'):
277
- sourceZipStreamFileName = request.get_header("X-File-Name")
278
- sourceZipStream = request.body
275
+ sourceZipStream = FileNamedBytesIO(request.get_header("X-File-Name"), request.body.read())
279
276
  else:
280
277
  errors.append(_("POST request must provide an XBRL zip file to process. Content-Type '{0}' not recognized as a zip file.").format(mimeType))
281
278
  if not view and not viewArcrole:
@@ -349,14 +346,13 @@ def validation(file: str | None = None) -> str | bytes:
349
346
  viewFile = FileNamedStringIO(media)
350
347
  options.viewArcrole = viewArcrole
351
348
  options.viewFile = viewFile
352
- return runOptionsAndGetResult(options, media, viewFile, sourceZipStream, sourceZipStreamFileName)
349
+ return runOptionsAndGetResult(options, media, viewFile, sourceZipStream)
353
350
 
354
351
  def runOptionsAndGetResult(
355
352
  options: RuntimeOptions,
356
353
  media: str,
357
354
  viewFile: FileNamedStringIO | None,
358
- sourceZipStream: FileNamedStringIO | None = None,
359
- sourceZipStreamFileName: str | None = None,
355
+ sourceZipStream: FileNamedBytesIO | None = None,
360
356
  ) -> str | bytes:
361
357
  """Execute request according to options, for result in media, with *post*ed file in sourceZipStream, if any.
362
358
 
@@ -381,7 +377,7 @@ def runOptionsAndGetResult(
381
377
  else:
382
378
  responseZipStream = None
383
379
  cntlr = getCntlr()
384
- successful = cntlr.run(options, sourceZipStream, responseZipStream, sourceZipStreamFileName)
380
+ successful = cntlr.run(options, sourceZipStream, responseZipStream)
385
381
  if media == "xml":
386
382
  response.content_type = 'text/xml; charset=UTF-8'
387
383
  elif media == "csv":
arelle/FileSource.py CHANGED
@@ -13,7 +13,7 @@ import struct
13
13
  import tarfile
14
14
  import zipfile
15
15
  import zlib
16
- from typing import IO, TYPE_CHECKING, Any, Optional, TextIO, cast
16
+ from typing import IO, TYPE_CHECKING, Any, BinaryIO, Optional, TextIO, cast
17
17
 
18
18
  import regex as re
19
19
  from lxml import etree
@@ -44,15 +44,17 @@ TAXONOMY_PACKAGE_FILE_NAMES = ('.taxonomyPackage.xml', 'catalog.xml') # pre-PWD
44
44
  def openFileSource(
45
45
  filename: str | None,
46
46
  cntlr: Cntlr | None = None,
47
- sourceZipStream: str | None = None,
47
+ sourceZipStream: BinaryIO | FileNamedBytesIO | None = None,
48
48
  checkIfXmlIsEis: bool = False,
49
49
  reloadCache: bool = False,
50
50
  base: str | None = None,
51
51
  sourceFileSource: FileSource | None = None,
52
- sourceZipStreamFileName: str | None = None,
53
52
  ) -> FileSource:
54
53
  if sourceZipStream:
55
- sourceZipStreamFileName = os.sep + (sourceZipStreamFileName or "POSTupload.zip")
54
+ if isinstance(sourceZipStream, FileNamedBytesIO) and sourceZipStream.fileName:
55
+ sourceZipStreamFileName = os.sep + sourceZipStream.fileName
56
+ else:
57
+ sourceZipStreamFileName = os.sep + "POSTupload.zip"
56
58
  filesource = FileSource(sourceZipStreamFileName, cntlr)
57
59
  filesource.openZipStream(sourceZipStream)
58
60
  if filename:
@@ -390,7 +392,7 @@ class FileSource:
390
392
  assert self.taxonomyPackage is not None
391
393
  self.mappedPaths = cast('dict[str, str]', self.taxonomyPackage.get("remappings"))
392
394
 
393
- def openZipStream(self, sourceZipStream: str) -> None:
395
+ def openZipStream(self, sourceZipStream: BinaryIO) -> None:
394
396
  if not self.isOpen:
395
397
  assert isinstance(self.url, str)
396
398
  self.basefile = self.url
@@ -655,6 +657,30 @@ class FileSource:
655
657
  else:
656
658
  return openXmlFileStream(self.cntlr, filepath, stripDeclaration)
657
659
 
660
+ def getBytesSize(self) -> int | None:
661
+ """
662
+ Get the size of the zip file in bytes.
663
+ :return: Size of the zip file in bytes, or None if not applicable.
664
+ """
665
+ if isinstance(self.basefile, str) and os.path.isfile(self.basefile):
666
+ return os.path.getsize(self.basefile)
667
+ # ZipFile.fp is a private field, but is currently the simplest way for us to
668
+ # access the internal stream
669
+ if isinstance(self.fs, zipfile.ZipFile) and (fp := getattr(self.fs, 'fp')) is not None:
670
+ stream = cast(IO[Any], fp)
671
+ stream.seek(0, 2) # Move to the end of the file
672
+ return stream.tell() # Report the current position, which is the size of the file
673
+ return None
674
+
675
+ def getBytesSizeEstimate(self) -> int | None:
676
+ """
677
+ Get an estimated size of the zip file in bytes.
678
+ :return: Estimated size of the zip file in bytes, or None if not applicable.
679
+ """
680
+ if not isinstance(self.fs, zipfile.ZipFile):
681
+ return None
682
+ return sum(zi.compress_size for zi in self.fs.infolist())
683
+
658
684
  def exists(self, filepath: str) -> bool:
659
685
  archiveFileSource = self.fileSourceContainingFilepath(filepath)
660
686
  if archiveFileSource is not None:
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.31'
21
- __version_tuple__ = version_tuple = (2, 37, 31)
20
+ __version__ = version = '2.37.33'
21
+ __version_tuple__ = version_tuple = (2, 37, 33)
arelle/api/Session.py CHANGED
@@ -12,6 +12,7 @@ from typing import Any, BinaryIO
12
12
 
13
13
  from arelle import PackageManager, PluginManager
14
14
  from arelle.CntlrCmdLine import CntlrCmdLine, createCntlrAndPreloadPlugins
15
+ from arelle.FileSource import FileNamedBytesIO
15
16
  from arelle.ModelXbrl import ModelXbrl
16
17
  from arelle.RuntimeOptions import RuntimeOptions
17
18
 
@@ -102,11 +103,10 @@ class Session:
102
103
  def run(
103
104
  self,
104
105
  options: RuntimeOptions,
105
- sourceZipStream: BinaryIO | None = None,
106
+ sourceZipStream: BinaryIO | FileNamedBytesIO | None = None,
106
107
  responseZipStream: BinaryIO | None = None,
107
108
  logHandler: logging.Handler | None = None,
108
109
  logFilters: list[logging.Filter] | None = None,
109
- sourceZipStreamFileName: str | None = None,
110
110
  ) -> bool:
111
111
  """
112
112
  Perform a run using the given options.
@@ -114,13 +114,10 @@ class Session:
114
114
  :param sourceZipStream: Optional stream to read source data from.
115
115
  :param responseZipStream: Options stream to write response data to.
116
116
  :param logHandler: Optional log handler to use for logging.
117
- :param sourceZipStreamFileName: Optional file name to use for the passed zip stream.
118
117
  :return: True if the run was successful, False otherwise.
119
118
  """
120
119
  with _session_lock:
121
120
  self._check_thread()
122
- if sourceZipStreamFileName is not None and sourceZipStream is None:
123
- raise ValueError("sourceZipStreamFileName may only be provided if sourceZipStream is not None.")
124
121
  PackageManager.reset()
125
122
  PluginManager.reset()
126
123
  if self._cntlr is None:
@@ -174,5 +171,4 @@ class Session:
174
171
  options,
175
172
  sourceZipStream=sourceZipStream,
176
173
  responseZipStream=responseZipStream,
177
- sourceZipStreamFileName=sourceZipStreamFileName,
178
174
  )
arelle/oim/Load.py CHANGED
@@ -1532,7 +1532,7 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
1532
1532
  hasRowError = True
1533
1533
  elif propGrpColValue in propGrpObjects:
1534
1534
  rowPropGroups[propGrpName] = propGrpObjects[propGrpColValue]
1535
- else:
1535
+ elif propGrpColValue is not EMPTY_CELL:
1536
1536
  error("xbrlce:unknownPropertyGroup",
1537
1537
  _("Table %(table)s unknown property group row %(row)s column %(column)s group %(propertyGroup)s, url: %(url)s"),
1538
1538
  table=tableId, row=rowIndex+1, column=rowIdColName, url=tableUrl, propertyGroup=propGrpName)
@@ -1573,12 +1573,11 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
1573
1573
  if _isParamRef(val):
1574
1574
  rowPropGrpParamRefs.add(_getParamRefName(val))
1575
1575
  if factDimensions[colName] is None:
1576
- if colName in paramRefColNames:
1577
- value = _cellValue(row[colNameIndex[colName]])
1578
- if value:
1579
- paramColsWithValue.add(colName)
1580
- elif value is EMPTY_CELL or value is NONE_CELL:
1581
- emptyCols.add(colName)
1576
+ value = _cellValue(row[colNameIndex[colName]])
1577
+ if value is EMPTY_CELL or value is NONE_CELL:
1578
+ emptyCols.add(colName)
1579
+ elif colName in paramRefColNames:
1580
+ paramColsWithValue.add(colName)
1582
1581
  if not cellPropGroup:
1583
1582
  continue # not a fact column
1584
1583
  for rowPropGrpParamRef in rowPropGrpParamRefs:
@@ -238,11 +238,10 @@ def rule_EC0183E(
238
238
  """
239
239
  if not pluginData.shouldValidateUpload(val):
240
240
  return
241
- zipFile = cast(zipfile.ZipFile, val.modelXbrl.fileSource.fs)
242
- file = cast(IO[Any], zipFile.fp)
243
- file.seek(0, 2) # Move to the end of the file
244
- size = file.tell()
245
- if size > 55 * 1000 * 1000: # Interpretting MB as megabytes (1,000,000 bytes)
241
+ size = val.modelXbrl.fileSource.getBytesSize()
242
+ if size is None:
243
+ return # File size is not available, cannot validate
244
+ if size > 55_000_000: # Interpretting MB as megabytes (1,000,000 bytes)
246
245
  yield Validation.error(
247
246
  codes='EDINET.EC0183E',
248
247
  msg=_("The compressed file size exceeds 55MB. "
@@ -88,12 +88,25 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
88
88
  if reportPackageMaxMB is not None and modelXbrl.fileSource.fs: # must be a zip to be a report package
89
89
  assert isinstance(modelXbrl.fileSource.fs, zipfile.ZipFile)
90
90
  maxMB = float(reportPackageMaxMB)
91
+ _size: int | None = None
92
+ _sizeExact = True
91
93
  if val.authParam["reportPackageMeasurement"] == "unzipped":
92
94
  _size = sum(zi.file_size for zi in modelXbrl.fileSource.fs.infolist())
95
+ _sizeExact = False
93
96
  else:
94
- _size = sum(zi.compress_size for zi in modelXbrl.fileSource.fs.infolist())
95
- # not usable because zip may be posted or streamed: _size = os.path.getsize(modelXbrl.fileSource.basefile)
96
- if _size > maxMB * 1048576:
97
+ try:
98
+ _size = modelXbrl.fileSource.getBytesSize()
99
+ except Exception:
100
+ pass
101
+ if _size is None:
102
+ _size = modelXbrl.fileSource.getBytesSizeEstimate()
103
+ _sizeExact = False
104
+ modelXbrl.info("arelle.ESEF.reportPackageSize",
105
+ _("The %(estimated)s report package %(reportPackageMeasurement)s size is %(size)s bytes."),
106
+ estimated=_("exact") if _sizeExact else _("estimated"),
107
+ reportPackageMeasurement=_(val.authParam["reportPackageMeasurement"]) or _("zipped"),
108
+ size=_size)
109
+ if _size is not None and _size > maxMB * 1048576:
97
110
  modelXbrl.error("arelle.ESEF.maximumReportPackageSize",
98
111
  _("The authority %(authority)s requires a report package size under %(maxSize)s MB, size is %(size)s."),
99
112
  modelObject=modelXbrl, authority=val.authority, maxSize=reportPackageMaxMB, size=_size)
@@ -93,12 +93,25 @@ def validateXbrlFinally(val: ValidateXbrl, *args: Any, **kwargs: Any) -> None:
93
93
  assert isinstance(modelXbrl.fileSource.fs, zipfile.ZipFile)
94
94
 
95
95
  maxMB = float(reportPackageMaxMB)
96
+ _size: int | None = None
97
+ _sizeExact = True
96
98
  if val.authParam["reportPackageMeasurement"] == "unzipped":
97
99
  _size = sum(zi.file_size for zi in modelXbrl.fileSource.fs.infolist())
100
+ _sizeExact = False
98
101
  else:
99
- _size = sum(zi.compress_size for zi in modelXbrl.fileSource.fs.infolist())
100
- # not usable because zip may be posted or streamed: _size = os.path.getsize(modelXbrl.fileSource.basefile)
101
- if _size > maxMB * 1048576:
102
+ try:
103
+ _size = modelXbrl.fileSource.getBytesSize()
104
+ except Exception:
105
+ pass
106
+ if _size is None:
107
+ _size = modelXbrl.fileSource.getBytesSizeEstimate()
108
+ _sizeExact = False
109
+ modelXbrl.info("arelle.ESEF.reportPackageSize",
110
+ _("The %(estimated)s report package %(reportPackageMeasurement)s size is %(size)s bytes."),
111
+ estimated=_("exact") if _sizeExact else _("estimated"),
112
+ reportPackageMeasurement=_(val.authParam["reportPackageMeasurement"]) or _("zipped"),
113
+ size=_size)
114
+ if _size is not None and _size > maxMB * 1048576:
102
115
  modelXbrl.error("arelle.ESEF.maximumReportPackageSize",
103
116
  _("The authority %(authority)s requires a report package size under %(maxSize)s MB, size is %(size)s."),
104
117
  modelObject=modelXbrl, authority=val.authority, maxSize=reportPackageMaxMB, size=_size)
@@ -1112,18 +1125,26 @@ def validateCssUrl(cssContent:str, normalizedUri:str, modelXbrl: ModelXbrl, val:
1112
1125
  _("Fonts SHOULD be included in the XHTML document as a base64 encoded string: %(file)s."),
1113
1126
  modelObject=elt, file=css_rule.value)
1114
1127
  if isinstance(css_element, tinycss2.ast.QualifiedRule):
1115
- validateCssUrlContent(css_element.content, normalizedUri, modelXbrl, val, elt, params)
1116
-
1117
-
1118
- def validateCssUrlContent(cssRules: list[Any], normalizedUri:str, modelXbrl: ModelXbrl, val: ValidateXbrl, elt: ModelObject, params: ImageValidationParameters) -> None:
1128
+ validateCssUrlContent(css_element.content, normalizedUri, modelXbrl, val, elt, params, css_element.prelude)
1129
+
1130
+
1131
+ def validateCssUrlContent(
1132
+ cssRules: list[Any],
1133
+ normalizedUri:str,
1134
+ modelXbrl: ModelXbrl,
1135
+ val: ValidateXbrl,
1136
+ elt: ModelObject,
1137
+ params: ImageValidationParameters,
1138
+ prelude: list[Any] | None = None,
1139
+ ) -> None:
1119
1140
  for css_rule in cssRules:
1120
1141
  if isinstance(css_rule, tinycss2.ast.FunctionBlock):
1121
1142
  if css_rule.lower_name == "url":
1122
1143
  if len(css_rule.arguments):
1123
1144
  css_rule_url = css_rule.arguments[0].value # url or base64
1124
1145
  evaluatedMsg = _('On line {line}').format(line=1) #css_element.source_line)
1125
- validateImageAndLog(normalizedUri, css_rule_url, modelXbrl, val, elt, evaluatedMsg, params)
1146
+ validateImageAndLog(normalizedUri, css_rule_url, modelXbrl, val, elt, evaluatedMsg, params, prelude)
1126
1147
  elif isinstance(css_rule, tinycss2.ast.URLToken):
1127
1148
  value = css_rule.value
1128
1149
  evaluatedMsg = _('On line {line}').format(line=1) #css_element.source_line)
1129
- validateImageAndLog(normalizedUri, value, modelXbrl, val, elt, evaluatedMsg, params)
1150
+ validateImageAndLog(normalizedUri, value, modelXbrl, val, elt, evaluatedMsg, params, prelude)
@@ -226,6 +226,9 @@ class PluginValidationDataExtension(PluginData):
226
226
  financialReportingPeriodPreviousStartDateQn: QName
227
227
  financialReportingPeriodPreviousEndDateQn: QName
228
228
  formattedExplanationItemTypeQn: QName
229
+ ifrsIdentifier: str
230
+ permissibleGAAPRootAbstracts: frozenset[QName]
231
+ permissibleIFRSRootAbstracts: frozenset[QName]
229
232
  textFormattingSchemaPath: str
230
233
  textFormattingWrapper: str
231
234
 
@@ -22,9 +22,11 @@ class ValidationPluginExtension(ValidationPlugin):
22
22
  def newPluginData(self, validateXbrl: ValidateXbrl) -> PluginValidationDataExtension:
23
23
  disclosureSystem = validateXbrl.disclosureSystem.name
24
24
  if disclosureSystem == DISCLOSURE_SYSTEM_NT16:
25
+ ifrsNamespace = None
25
26
  jenvNamespace = 'http://www.nltaxonomie.nl/nt16/jenv/20211208/dictionary/jenv-bw2-data'
26
27
  kvkINamespace = 'http://www.nltaxonomie.nl/nt16/kvk/20211208/dictionary/kvk-data'
27
28
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt16/sbr/20210301/dictionary/nl-types'
29
+ rjNamespace = None
28
30
  entrypointRoot = 'http://www.nltaxonomie.nl/nt16/kvk/20211208/entrypoints/'
29
31
  entrypoints = {entrypointRoot + e for e in [
30
32
  'kvk-rpt-jaarverantwoording-2021-ifrs-full.xsd',
@@ -58,9 +60,11 @@ class ValidationPluginExtension(ValidationPlugin):
58
60
  'kvk-rpt-jaarverantwoording-2021-nlgaap-zorginstellingen.xsd',
59
61
  ]}
60
62
  elif disclosureSystem == DISCLOSURE_SYSTEM_NT17:
63
+ ifrsNamespace = None
61
64
  jenvNamespace = 'http://www.nltaxonomie.nl/nt17/jenv/20221214/dictionary/jenv-bw2-data'
62
65
  kvkINamespace = 'http://www.nltaxonomie.nl/nt17/kvk/20221214/dictionary/kvk-data'
63
66
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt17/sbr/20220301/dictionary/nl-types'
67
+ rjNamespace = None
64
68
  entrypointRoot = 'http://www.nltaxonomie.nl/nt17/kvk/20221214/entrypoints/'
65
69
  entrypoints = {entrypointRoot + e for e in [
66
70
  'kvk-rpt-jaarverantwoording-2022-ifrs-full.xsd',
@@ -95,9 +99,11 @@ class ValidationPluginExtension(ValidationPlugin):
95
99
  'kvk-rpt-jaarverantwoording-2022-nlgaap-zorginstellingen.xsd',
96
100
  ]}
97
101
  elif disclosureSystem == DISCLOSURE_SYSTEM_NT18:
102
+ ifrsNamespace = None
98
103
  jenvNamespace = 'http://www.nltaxonomie.nl/nt18/jenv/20231213/dictionary/jenv-bw2-data'
99
104
  kvkINamespace = 'http://www.nltaxonomie.nl/nt18/kvk/20231213/dictionary/kvk-data'
100
105
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt18/sbr/20230301/dictionary/nl-types'
106
+ rjNamespace = None
101
107
  entrypointRoot = 'http://www.nltaxonomie.nl/nt18/kvk/20231213/entrypoints/'
102
108
  entrypoints = {entrypointRoot + e for e in [
103
109
  'kvk-rpt-jaarverantwoording-2023-ifrs-full.xsd',
@@ -132,9 +138,11 @@ class ValidationPluginExtension(ValidationPlugin):
132
138
  'kvk-rpt-jaarverantwoording-2023-nlgaap-zorginstellingen.xsd',
133
139
  ]}
134
140
  elif disclosureSystem == DISCLOSURE_SYSTEM_NT19:
141
+ ifrsNamespace = None
135
142
  jenvNamespace = 'http://www.nltaxonomie.nl/nt19/jenv/20241211/dictionary/jenv-bw2-data'
136
143
  kvkINamespace = 'http://www.nltaxonomie.nl/nt19/kvk/20241211/dictionary/kvk-data'
137
144
  nlTypesNamespace = 'http://www.nltaxonomie.nl/nt19/sbr/20240301/dictionary/nl-types'
145
+ rjNamespace = None
138
146
  entrypointRoot = 'http://www.nltaxonomie.nl/nt19/kvk/20241211/entrypoints/'
139
147
  entrypoints = {entrypointRoot + e for e in [
140
148
  'kvk-rpt-jaarverantwoording-2024-ifrs-full.xsd',
@@ -169,18 +177,22 @@ class ValidationPluginExtension(ValidationPlugin):
169
177
  'kvk-rpt-jaarverantwoording-2024-nlgaap-zorginstellingen.xsd',
170
178
  ]}
171
179
  elif disclosureSystem == DISCLOSURE_SYSTEM_NL_INLINE_2024:
180
+ ifrsNamespace = 'https://xbrl.ifrs.org/taxonomy/2024-03-27/ifrs-full'
172
181
  jenvNamespace = 'https://www.nltaxonomie.nl/bw2-titel9/2024-12-31/bw2-titel9-cor'
173
- kvkINamespace = None
182
+ kvkINamespace = 'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-cor'
174
183
  nlTypesNamespace = None
184
+ rjNamespace = 'https://www.nltaxonomie.nl/rj/2024-12-31/rj-cor'
175
185
  entrypointRoot = 'http://www.nltaxonomie.nl/kvk/2024-12-31/'
176
186
  entrypoints = {entrypointRoot + e for e in [
177
187
  'kvk-annual-report-ifrs-ext.xsd',
178
188
  'kvk-annual-report-nlgaap-ext.xsd',
179
189
  ]}
180
190
  elif disclosureSystem == DISCLOSURE_SYSTEM_NL_INLINE_2024_GAAP_OTHER:
191
+ ifrsNamespace = 'https://xbrl.ifrs.org/taxonomy/2024-03-27/ifrs-full'
181
192
  jenvNamespace = 'https://www.nltaxonomie.nl/bw2-titel9/2024-12-31/bw2-titel9-cor'
182
- kvkINamespace = None
193
+ kvkINamespace = 'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-cor'
183
194
  nlTypesNamespace = None
195
+ rjNamespace = 'https://www.nltaxonomie.nl/rj/2024-12-31/rj-cor'
184
196
  entrypointRoot = 'http://www.nltaxonomie.nl/kvk/2024-12-31/'
185
197
  entrypoints = {entrypointRoot + e for e in [
186
198
  'kvk-annual-report-other-gaap.xsd',
@@ -201,6 +213,23 @@ class ValidationPluginExtension(ValidationPlugin):
201
213
  financialReportingPeriodPreviousStartDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodPreviousStartDate'),
202
214
  financialReportingPeriodPreviousEndDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodPreviousEndDate'),
203
215
  formattedExplanationItemTypeQn=qname(f'{{{nlTypesNamespace}}}formattedExplanationItemType'),
216
+ ifrsIdentifier = 'https://xbrl.ifrs.org',
217
+ permissibleGAAPRootAbstracts=frozenset([
218
+ qname(f'{{{jenvNamespace}}}BalanceSheetTitle'),
219
+ qname(f'{{{jenvNamespace}}}IncomeStatementTitle'),
220
+ qname(f'{{{jenvNamespace}}}StatementOfComprehensiveIncomeTitle'),
221
+ qname(f'{{{jenvNamespace}}}EquityStatementOfChangesTitle'),
222
+ qname(f'{{{kvkINamespace}}}AnnualReportFilingInformationTitle'),
223
+ qname(f'{{{rjNamespace}}}StatementOfCashFlowsTitle'),
224
+ ]),
225
+ permissibleIFRSRootAbstracts=frozenset([
226
+ qname(f'{{{ifrsNamespace}}}StatementOfFinancialPositionAbstract'),
227
+ qname(f'{{{ifrsNamespace}}}IncomeStatementAbstract'),
228
+ qname(f'{{{ifrsNamespace}}}StatementOfComprehensiveIncomeAbstract'),
229
+ qname(f'{{{ifrsNamespace}}}StatementOfCashFlowsAbstract'),
230
+ qname(f'{{{ifrsNamespace}}}StatementOfChangesInEquityAbstract'),
231
+ qname(f'{{{kvkINamespace}}}AnnualReportFilingInformationTitle'),
232
+ ]),
204
233
  textFormattingSchemaPath='sbr-text-formatting.xsd',
205
234
  textFormattingWrapper='<formattedText xmlns="http://www.nltaxonomie.nl/2017/xbrl/sbr-text-formatting">{}</formattedText>',
206
235
  )
@@ -18,7 +18,7 @@ from arelle.ModelInstanceObject import ModelInlineFact
18
18
  from arelle.ModelObject import ModelObject
19
19
  from arelle.PrototypeDtsObject import PrototypeObject
20
20
  from arelle.ValidateDuplicateFacts import getDuplicateFactSets
21
- from arelle.XbrlConst import standardLabel
21
+ from arelle.XbrlConst import parentChild, standardLabel
22
22
  from arelle.XmlValidateConst import VALID
23
23
 
24
24
  from arelle import XbrlConst, XmlUtil, ModelDocument
@@ -1785,17 +1785,50 @@ def rule_nl_kvk_6_1_1_1(
1785
1785
  """
1786
1786
  NL-KVK.6.1.1.1: The size of the report package MUST NOT exceed 100 MB.
1787
1787
  """
1788
- if val.modelXbrl.fileSource.fs and isinstance(val.modelXbrl.fileSource.fs, zipfile.ZipFile):
1789
- maxMB = float(MAX_REPORT_PACKAGE_SIZE_MBS)
1790
- # The following code computes report package size by adding the compressed file sizes within the package.
1791
- # This method of computation is over 99% accurate and gets more accurate the larger the filesize is.
1792
- _size = sum(zi.compress_size for zi in val.modelXbrl.fileSource.fs.infolist())
1793
- if _size > maxMB * 1000000:
1794
- yield Validation.error(
1795
- codes='NL.NL-KVK.6.1.1.1.reportPackageMaximumSizeExceeded',
1796
- msg=_('The size of the report package must not exceed %(maxSize)s MBs, size is %(size)s MBs.'),
1797
- modelObject=val.modelXbrl, maxSize=MAX_REPORT_PACKAGE_SIZE_MBS, size=int(_size/1000000)
1798
- )
1788
+ size = val.modelXbrl.fileSource.getBytesSize()
1789
+ if size is None:
1790
+ return # File size is not available, cannot validate
1791
+ if size > MAX_REPORT_PACKAGE_SIZE_MBS * 1_000_000: # Interpretting MB as megabytes (1,000,000 bytes)
1792
+ yield Validation.error(
1793
+ codes='NL.NL-KVK.6.1.1.1.reportPackageMaximumSizeExceeded',
1794
+ msg=_('The size of the report package must not exceed %(maxSize)s MBs, size is %(size)s MBs.'),
1795
+ modelObject=val.modelXbrl, maxSize=MAX_REPORT_PACKAGE_SIZE_MBS, size=int(size/1000000)
1796
+ )
1797
+
1798
+
1799
+ @validation(
1800
+ hook=ValidationHook.XBRL_FINALLY,
1801
+ disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
1802
+ )
1803
+ def rule_nl_kvk_RTS_Annex_II_Par_1_RTS_Annex_IV_par_7(
1804
+ pluginData: PluginValidationDataExtension,
1805
+ val: ValidateXbrl,
1806
+ *args: Any,
1807
+ **kwargs: Any,
1808
+ ) -> Iterable[Validation]:
1809
+ """
1810
+ NL-KVK.RTS_Annex_II_Par_1_RTS_Annex_IV_par_7: Legal entities should mark all amounts in a designated currency included in a. the balance sheet, income statement, cash flow statement,
1811
+ statement of comprehensive income and statement of changes in equity of the (consolidated) financial statements based on NL-GAAP; or b. the statement of financial position,
1812
+ the income statement (separately or as part of the statement of comprehensive income), the statement of comprehensive income, the statement of changes in equity and
1813
+ the statement of cash flows of the (consolidated) financial statements based on IFRS.
1814
+ """
1815
+ warnings = []
1816
+ permissibleAbstracts = pluginData.permissibleGAAPRootAbstracts
1817
+ ifrsMatch = any(k.startswith(pluginData.ifrsIdentifier) for k in val.modelXbrl.namespaceDocs.keys())
1818
+ if ifrsMatch:
1819
+ permissibleAbstracts = pluginData.permissibleIFRSRootAbstracts
1820
+ for ELR in val.modelXbrl.relationshipSet(parentChild).linkRoleUris:
1821
+ relSet = val.modelXbrl.relationshipSet(parentChild, ELR)
1822
+ for rootConcept in relSet.rootConcepts:
1823
+ if relSet.fromModelObject(rootConcept):
1824
+ if not rootConcept.qname in permissibleAbstracts:
1825
+ warnings.append(rootConcept)
1826
+ if len(warnings) > 0:
1827
+ yield Validation.warning(
1828
+ codes='NL.NL-KVK.RTS_Annex_II_Par_1_RTS_Annex_IV_par_7.missingRelevantPlaceholder',
1829
+ msg=_('A root abstract is being used that is not one of the starting abstracts defined by the regulator. Review abstracts in use and update to defined abstracts.'),
1830
+ modelObject=warnings
1831
+ )
1799
1832
 
1800
1833
 
1801
1834
  @validation(
@@ -454,7 +454,7 @@ def validateXbrlFinally(val, *args, **kwargs):
454
454
  _("Image scope must be base-64 encoded string (starting with data:image/*;base64), *=gif, jpeg or png. src disallowed: %(src)s."),
455
455
  modelObject=elt, src=attrValue[:128])
456
456
  for elt in rootElt.iterdescendants(tag="{http://www.w3.org/1999/xhtml}style"):
457
- _validateScriptElement(elt, modelXbrl)
457
+ _validateStyleElement(elt, modelXbrl)
458
458
  for elt in rootElt.xpath("//xhtml:*[@style]", namespaces={"xhtml": "http://www.w3.org/1999/xhtml"}):
459
459
  _validateStyleAttribute(elt, modelXbrl)
460
460
 
@@ -468,7 +468,7 @@ def validateXbrlFinally(val, *args, **kwargs):
468
468
  modelXbrl.modelManager.showStatus(None)
469
469
 
470
470
 
471
- def _validateScriptElement(elt, modelXbrl):
471
+ def _validateStyleElement(elt, modelXbrl):
472
472
  cssElements = tinycss2.parse_stylesheet(elt.text)
473
473
  for css_element in cssElements:
474
474
  if isinstance(css_element, tinycss2.ast.QualifiedRule):
@@ -479,9 +479,10 @@ def _validateScriptElement(elt, modelXbrl):
479
479
  elif _isExternalImageUrl(cssProperty, elem):
480
480
  modelXbrl.error(
481
481
  "HMRC.SG.3.8",
482
- _("Style element has disallowed image reference: %(styleImage)s."),
482
+ _("Style element has disallowed image reference: %(cssSelectors)s, %(styleImage)s."),
483
483
  modelObject=elt,
484
- styleImage=elem.arguments[0].value
484
+ cssSelectors=tinycss2.serialize(css_element.prelude).strip(),
485
+ styleImage=elem.arguments[0].value,
485
486
  )
486
487
  return
487
488
  elif isinstance(css_element, tinycss2.ast.ParseError):
@@ -5,22 +5,22 @@ from __future__ import annotations
5
5
 
6
6
  import binascii
7
7
  import os
8
-
8
+ from collections.abc import Iterable
9
9
  from dataclasses import dataclass
10
- from typing import cast, Iterable
10
+ from typing import Any, cast
11
11
  from urllib.parse import unquote
12
12
 
13
- from lxml.etree import XML, XMLSyntaxError
14
- from lxml.etree import _Element
13
+ import tinycss2 # type: ignore[import-untyped]
14
+ from lxml.etree import XML, XMLSyntaxError, _Element
15
15
 
16
16
  from arelle import ModelDocument
17
17
  from arelle.ModelObjectFactory import parser
18
18
  from arelle.ModelXbrl import ModelXbrl
19
+ from arelle.typing import TypeGetText
19
20
  from arelle.UrlUtil import decodeBase64DataImage, scheme
21
+ from arelle.utils.validate.Validation import Validation
20
22
  from arelle.ValidateFilingText import parseImageDataURL, validateGraphicHeaderType
21
23
  from arelle.ValidateXbrl import ValidateXbrl
22
- from arelle.typing import TypeGetText
23
- from arelle.utils.validate.Validation import Validation
24
24
 
25
25
  _: TypeGetText # Handle gettext
26
26
 
@@ -61,7 +61,9 @@ def validateImageAndLog(
61
61
  elts: _Element | list[_Element],
62
62
  evaluatedMsg: str,
63
63
  params: ImageValidationParameters,
64
+ prelude: list[Any] | None = None,
64
65
  ) -> None:
66
+ cssSelectors = None
65
67
  for validation in validateImage(
66
68
  baseUrl=baseUrl,
67
69
  image=image,
@@ -71,7 +73,14 @@ def validateImageAndLog(
71
73
  evaluatedMsg=evaluatedMsg,
72
74
  params=params,
73
75
  ):
74
- modelXbrl.log(level=validation.level.name, codes=validation.codes, msg=validation.msg, **validation.args)
76
+ if cssSelectorsArg := validation.args.get("cssSelectors"):
77
+ raise ValueError(_("The 'cssSelectors' argument is reserved to record the CSS selector. It should not be present in the validation arguments: {}").format(cssSelectorsArg))
78
+ if prelude and cssSelectors is None:
79
+ cssSelectors = tinycss2.serialize(prelude).strip()
80
+ args = validation.args.copy()
81
+ if cssSelectors:
82
+ args["cssSelectors"] = cssSelectors
83
+ modelXbrl.log(level=validation.level.name, codes=validation.codes, msg=validation.msg, **args)
75
84
 
76
85
  # check image contents against mime/file ext and for Steganography
77
86
  def validateImage(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arelle-release
3
- Version: 2.37.31
3
+ Version: 2.37.33
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License-Expression: Apache-2.0
@@ -1,11 +1,11 @@
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=uCpv_MaDGwMX1A3EZdN5h678aDaI0MTgRCQwOEKlimY,90250
4
+ arelle/CntlrCmdLine.py,sha256=tSbTlREbJkppAZ9HlB_99KpDKx3EwWBV9veWnXg6hVQ,90155
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
- arelle/CntlrWebMain.py,sha256=x5vtiopqGdp6L5s7PrUTEABXCGqtb5oy7yqWIVePtgE,50860
8
+ arelle/CntlrWebMain.py,sha256=_jhosP0Pg-erutBRzTVsL0cmWVgbc6z0WIIlNO-z1N4,50712
9
9
  arelle/CntlrWinMain.py,sha256=53lRaGTh8-4vG-hpuNVkxUhFa60u0jIHM9WvFdwdv-o,97273
10
10
  arelle/CntlrWinTooltip.py,sha256=6MzoAIfkYnNu_bl_je8n0adhwmKxAIcymkg9Tij9Z4M,7951
11
11
  arelle/DialogAbout.py,sha256=XXzMV0fO4BQ3-l1Puirzmn7EZEdmgJg7JNYdJm1FueM,1987
@@ -21,7 +21,7 @@ arelle/DialogRssWatch.py,sha256=mjc4pqyFDISY4tQtME0uSRQ3NlcWnNsOsMu9Zj8tTd0,1378
21
21
  arelle/DialogURL.py,sha256=JH88OPFf588E8RW90uMaieok7A_4kOAURQ8kHWVhnao,4354
22
22
  arelle/DialogUserPassword.py,sha256=kWPlCCihhwvsykDjanME9qBDtv6cxZlsrJyoMqiRep4,13769
23
23
  arelle/DisclosureSystem.py,sha256=g3XXMjuyKJk2eoqvHGqoyIs2bMfcODwOeISDRCcY9gc,24749
24
- arelle/FileSource.py,sha256=OHWArRo30BfqC4vmNsSsUVOjRXvhDGlW4EVmE5uG9ZM,46652
24
+ arelle/FileSource.py,sha256=S19Rll9CoRPZ2zJCAlNHv1jt2UUfiLbSgI2tDdJq5Xc,47899
25
25
  arelle/FunctionCustom.py,sha256=d1FsBG14eykvpLpgaXpN8IdxnlG54dfGcsXPYfdpA9Q,5880
26
26
  arelle/FunctionFn.py,sha256=BcZKah1rpfquSVPwjvknM1pgFXOnK4Hr1e_ArG_mcJY,38058
27
27
  arelle/FunctionIxt.py,sha256=8JELGh1l4o8Ul4_G7JgwX8Ebch9it2DblI6OkfL33Cw,80082
@@ -123,9 +123,9 @@ arelle/XmlValidateConst.py,sha256=U_wN0Q-nWKwf6dKJtcu_83FXPn9c6P8JjzGA5b0w7P0,33
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=LXwm4N6xleTL-6YANibNIENFoy1W4bsQPlh3mMEUrok,515
126
+ arelle/_version.py,sha256=RAjXCgP-9p3VBfxEV85KcfgMP1noD9OimvpQH9hUuu8,515
127
127
  arelle/typing.py,sha256=PRe-Fxwr2SBqYYUVPCJ3E7ddDX0_oOISNdT5Q97EbRM,1246
128
- arelle/api/Session.py,sha256=5KPjCIPiNuanKrz1MdFdKIx8Bg40Pk9sf2cL9OU4x-E,7770
128
+ arelle/api/Session.py,sha256=27HVuK3Bz1_21l4_RLn1IQg6v0MNsUEYrHajymyWwxI,7429
129
129
  arelle/archive/CustomLogger.py,sha256=v_JXOCQLDZcfaFWzxC9FRcEf9tQi4rCI4Sx7jCuAVQI,1231
130
130
  arelle/archive/LoadEFMvalidate.py,sha256=HR1ZJmOvWGUlWEsWd0tGCa2TTtZSNzeL6tgN1TFfrl0,986
131
131
  arelle/archive/LoadSavePreLbCsv.py,sha256=mekr1R6OE5d3xdUCZIVfSeolyet0HO8R6wsHnW4eyaA,767
@@ -294,7 +294,7 @@ arelle/model/CommentBase.py,sha256=NtC2lFd9Mt1y7kzWwrpvexwqBdfSe1nvGFiIJeio3rU,1
294
294
  arelle/model/ElementBase.py,sha256=pZX836d4-s-OvzPMUusvEDezI9D_6YKO7_j6iDcUXm4,404
295
295
  arelle/model/PIBase.py,sha256=easZ3pKXJ5wq3NFB2pDtBeXNDcjwMAXylpXz6mnumOg,257
296
296
  arelle/model/__init__.py,sha256=RLmC1rTus3T_2Vvnu3yHtdw1r0wrZCHZoqxe8BLg_wE,595
297
- arelle/oim/Load.py,sha256=kqKvs3q6VE6fKxCv9X0kxnyTywKMyC_qGGAB__v51TU,182910
297
+ arelle/oim/Load.py,sha256=jLDidnntV78Pwzw0MvOLWSHXC8QxDkHO41TrdmsQuOQ,182874
298
298
  arelle/oim/Validate.py,sha256=IaBClr2KYMiVC_GKYy4_A9gF7hcnm-lxXpQrDCqIWGs,9012
299
299
  arelle/oim/xml/Save.py,sha256=MdaJiGcEo4nbQCX9sRgWfVIoxp6fd2N-wuLiDAS9D-I,607
300
300
  arelle/packages/PackageConst.py,sha256=iIIF-Ic8zlMPiiCq3PcV57aWci6ispBtilSG4W7ZW4U,121
@@ -399,17 +399,17 @@ arelle/plugin/validate/EDINET/ValidationPluginExtension.py,sha256=HIGOpBOyuVs5SE
399
399
  arelle/plugin/validate/EDINET/__init__.py,sha256=1kJUaV2AbNZdakKSa_v3opdyCRKO3gva62RpHVOrpIE,4398
400
400
  arelle/plugin/validate/EDINET/resources/config.xml,sha256=7uxn_HZT3USgbs2GQkew-dCUzlEgUGs62PiqEfljPgk,514
401
401
  arelle/plugin/validate/EDINET/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
402
- arelle/plugin/validate/EDINET/rules/upload.py,sha256=KehSxCyqC9aujaPYucK4b5VpXmjT7L6Gz_D0u82w6GY,17096
402
+ arelle/plugin/validate/EDINET/rules/upload.py,sha256=sZFDSRWukJZEEBfg_RsG1q3Qw1IHhD0LZjl9LL1i9Ao,17048
403
403
  arelle/plugin/validate/ESEF/Const.py,sha256=JujF_XV-_TNsxjGbF-8SQS4OOZIcJ8zhCMnr-C1O5Ho,22660
404
404
  arelle/plugin/validate/ESEF/Dimensions.py,sha256=MOJM7vwNPEmV5cu-ZzPrhx3347ZvxgD6643OB2HRnIk,10597
405
405
  arelle/plugin/validate/ESEF/Util.py,sha256=QH3btcGqBpr42M7WSKZLSdNXygZaZLfEiEjlxoG21jE,7950
406
406
  arelle/plugin/validate/ESEF/__init__.py,sha256=LL7uYOcGPHgjwTlcfW2oWMqWiqrZ5yABzcKkJZFrZis,20391
407
407
  arelle/plugin/validate/ESEF/ESEF_2021/DTS.py,sha256=6Za7BANwwc_egxLCgbgWzwUGOXZv9IF1I7JCkDNt2Tw,26277
408
408
  arelle/plugin/validate/ESEF/ESEF_2021/Image.py,sha256=4bnhuy5viBU0viPjb4FhcRRjVVKlNdnKLFdSGg3sZvs,4871
409
- arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py,sha256=l4Nl-QuYJlM4WDpg87YjTwMUh05VP7tNq86gLFhWHyE,63380
409
+ arelle/plugin/validate/ESEF/ESEF_2021/ValidateXbrlFinally.py,sha256=Oh_Qy2Shug3wN1-uwct0BCnuNe36RoCQvLEJxdmE1HY,63941
410
410
  arelle/plugin/validate/ESEF/ESEF_2021/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
411
411
  arelle/plugin/validate/ESEF/ESEF_Current/DTS.py,sha256=epp-PBh1NJzQqgxUE6C468HmoDc2w3j54rMwfiOAry4,29334
412
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py,sha256=tWgBYHtnEosZTOBN3p-DguhYwCCNhf8xvk5K5qcZK_I,73637
412
+ arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py,sha256=DL6k5ebGTgIdUDWz9BtN6x9VQFzRin_xje5iMhXx3_8,74330
413
413
  arelle/plugin/validate/ESEF/ESEF_Current/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
414
414
  arelle/plugin/validate/ESEF/resources/authority-validations.json,sha256=JriLZ45KmUYlQiPbXJCAahobqdrst64Ay77bofZhB5Q,14940
415
415
  arelle/plugin/validate/ESEF/resources/config.xml,sha256=t3STU_-QYM7Ay8YwZRPapnohiWVWhjfr4L2Rjx9xN9U,3902
@@ -418,8 +418,8 @@ arelle/plugin/validate/FERC/config.xml,sha256=bn9b8eCqJA1J62rYq1Nz85wJrMGAahVmmn
418
418
  arelle/plugin/validate/FERC/resources/ferc-utr.xml,sha256=OCRj9IUpdXATCBXKbB71apYx9kxcNtZW-Hq4s-avsRY,2663
419
419
  arelle/plugin/validate/NL/DisclosureSystems.py,sha256=urRmYJ8RnGPlTgSVKW7zGN4_4CtL3OVKlcI3LwTpBz4,561
420
420
  arelle/plugin/validate/NL/LinkbaseType.py,sha256=BwRQl4XZFFCopufC2FEMLhYENNTk2JUWVQvnIUsaqtI,3108
421
- arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=en-x3J_sH9w-lIJzNwKRE6rRJ2fgovovVtq7n7QLo4E,34667
422
- arelle/plugin/validate/NL/ValidationPluginExtension.py,sha256=suCNqrtC_IMndyS_mXaeujDvjgSduTQ9KPNRc9B0F6I,16098
421
+ arelle/plugin/validate/NL/PluginValidationDataExtension.py,sha256=PQFQmJWLDqe4LXBMQ0u1VyaCejoUCaFzURrsyADZ-0Y,34793
422
+ arelle/plugin/validate/NL/ValidationPluginExtension.py,sha256=Pjg-tOTTn3qi5G-Ue1i8AmCXz5uGeFZlemdeL1O8HCA,17872
423
423
  arelle/plugin/validate/NL/__init__.py,sha256=W-SHohiAWM7Yi77gAbt-D3vvZNAB5s1j16mHCTFta6w,3158
424
424
  arelle/plugin/validate/NL/resources/config.xml,sha256=qBE6zywFSmemBSWonuTII5iuOCUlNb1nvkpMbsZb5PM,1853
425
425
  arelle/plugin/validate/NL/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -427,7 +427,7 @@ arelle/plugin/validate/NL/rules/br_kvk.py,sha256=0SwKieWzTDm3YMsXPS6zTdgbk7_Z9Cz
427
427
  arelle/plugin/validate/NL/rules/fg_nl.py,sha256=4Puq5wAjtK_iNd4wisH_R0Z_EKJ7MT2OCai5g4t1MPE,10714
428
428
  arelle/plugin/validate/NL/rules/fr_kvk.py,sha256=kYqXt45S6eM32Yg9ii7pUhOMfJaHurgYqQ73FyQALs8,8171
429
429
  arelle/plugin/validate/NL/rules/fr_nl.py,sha256=-M1WtXp06khhtkfOVPCa-b8UbC281gk4YfDhvtAVlnI,31424
430
- arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=mMPMeGhhlYEhC9LMHVaFfHzIpqJObl9ukU8cuuitaRU,88446
430
+ arelle/plugin/validate/NL/rules/nl_kvk.py,sha256=WW56HvQNSAqGOkPKTAFSuzZEXz-ECAYKvJlNKvZmsKM,90151
431
431
  arelle/plugin/validate/ROS/DisclosureSystems.py,sha256=rJ81mwQDYTi6JecFZ_zhqjjz3VNQRgjHNSh0wcQWAQE,18
432
432
  arelle/plugin/validate/ROS/PluginValidationDataExtension.py,sha256=IV7ILhNvgKwQXqbpSA6HRNt9kEnejCyMADI3wyyIgk0,4036
433
433
  arelle/plugin/validate/ROS/ValidationPluginExtension.py,sha256=FBhEp8t396vGdvCbMEimfcxmGiGnhXMen-yVLWnkFaI,758
@@ -437,7 +437,7 @@ arelle/plugin/validate/ROS/resources/config.xml,sha256=HXWume5HlrAqOx5AtiWWqgADb
437
437
  arelle/plugin/validate/ROS/rules/__init__.py,sha256=wW7BUAIb7sRkOxC1Amc_ZKrz03FM-Qh1TyZe6wxYaAU,1567
438
438
  arelle/plugin/validate/ROS/rules/ros.py,sha256=6DciQvv3H9QCEaDgINfHejZd196pEulUcQHk2qqMWhs,19921
439
439
  arelle/plugin/validate/UK/ValidateUK.py,sha256=0UhSwsY1lrY-EAEBJJR9QY38YXGBZ6PEgmuC5gQfBlI,57813
440
- arelle/plugin/validate/UK/__init__.py,sha256=WOAbzcogxP2hD3HmNnVIrvUO4w0Cv36447AoPrMa7KU,30548
440
+ arelle/plugin/validate/UK/__init__.py,sha256=KE6s_B-EvrHDCtWQz2N_wQwyx_ZbWhYNV2GfQnluxMw,30655
441
441
  arelle/plugin/validate/UK/config.xml,sha256=mUFhWDfBzGTn7v0ZSmf4HaweQTMJh_4ZcJmD9mzCHrA,1547
442
442
  arelle/plugin/validate/UK/consistencyChecksByName.json,sha256=BgB9YAWzmcsX-_rU74RBkABwEsS75vrMlwBHsYCz2R0,25247
443
443
  arelle/plugin/validate/UK/hmrc-taxonomies.xml,sha256=3lR-wb2sooAddQkVqqRzG_VqLuHq_MQ8kIaXAQs1KVk,9623
@@ -743,16 +743,16 @@ arelle/utils/PluginHooks.py,sha256=CeVxti23VjERQl4xWFucDVTW63TCG2PUdnxpjd3x_Ms,3
743
743
  arelle/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
744
744
  arelle/utils/validate/Decorator.py,sha256=8LGmA171HZgKrALtsMKyHqMNM-XCdwJOv6KpZz4pC2c,3161
745
745
  arelle/utils/validate/DetectScriptsInXhtml.py,sha256=RFBh_Z24OjR69s71qQzSzbxdU-WCTWuvYlONN-BgpZ0,2098
746
- arelle/utils/validate/ESEFImage.py,sha256=qel9_DgZGAQnCM45YQ93HLspuIK0JEUg4uotj82UarI,14907
746
+ arelle/utils/validate/ESEFImage.py,sha256=eEPoe8h6KYi_4YNjWXuvYHmoEvCT-JB7KQLJPDhpIgQ,15485
747
747
  arelle/utils/validate/Validation.py,sha256=n6Ag7VeCj_VO5nqzw_P53hOfXXeT2APK0Enb3UQqBns,832
748
748
  arelle/utils/validate/ValidationPlugin.py,sha256=_WeRPXZUTCcSN3FLbFwiAe_2pAUTxZZk1061qMoDW8w,11527
749
749
  arelle/utils/validate/ValidationUtil.py,sha256=9vmSvShn-EdQy56dfesyV8JjSRVPj7txrxRFgh8FxIs,548
750
750
  arelle/utils/validate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
751
751
  arelle/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
752
752
  arelle/webserver/bottle.py,sha256=P-JECd9MCTNcxCnKoDUvGcoi03ezYVOgoWgv2_uH-6M,362
753
- arelle_release-2.37.31.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
754
- arelle_release-2.37.31.dist-info/METADATA,sha256=bL6O3WLyWJ64s470luXZ7e5-pQIB54EbXSOpMrnsaAM,9137
755
- arelle_release-2.37.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
756
- arelle_release-2.37.31.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
757
- arelle_release-2.37.31.dist-info/top_level.txt,sha256=fwU7SYawL4_r-sUMRg7r1nYVGjFMSDvRWx8VGAXEw7w,7
758
- arelle_release-2.37.31.dist-info/RECORD,,
753
+ arelle_release-2.37.33.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
754
+ arelle_release-2.37.33.dist-info/METADATA,sha256=uXm8EVfOHE2g5IEWyUcC9UDreYR5taOMDuwboUuNANw,9137
755
+ arelle_release-2.37.33.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
756
+ arelle_release-2.37.33.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
757
+ arelle_release-2.37.33.dist-info/top_level.txt,sha256=fwU7SYawL4_r-sUMRg7r1nYVGjFMSDvRWx8VGAXEw7w,7
758
+ arelle_release-2.37.33.dist-info/RECORD,,