arelle-release 2.37.34__py3-none-any.whl → 2.37.36__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/FileSource.py CHANGED
@@ -119,7 +119,8 @@ class FileNamedStringIO(io.StringIO): # provide string IO in memory but behave
119
119
  self.fileName = fileName
120
120
 
121
121
  def close(self) -> None:
122
- del self.fileName
122
+ if hasattr(self, 'fileName'):
123
+ del self.fileName
123
124
  super().close()
124
125
 
125
126
  def __str__(self) -> str:
@@ -139,7 +140,8 @@ class FileNamedBytesIO(io.BytesIO): # provide Bytes IO in memory but behave as
139
140
  self.fileName = fileName
140
141
 
141
142
  def close(self) -> None:
142
- del self.fileName
143
+ if hasattr(self, 'fileName'):
144
+ del self.fileName
143
145
  super().close()
144
146
 
145
147
  def __str__(self) -> str:
arelle/ModelValue.py CHANGED
@@ -35,11 +35,11 @@ def qname(value: ModelObject | str | QName, name: str | ModelObject | None = Non
35
35
  def qname(value: ModelObject, name: QName, noPrefixIsNoNamespace: bool) -> QName: ...
36
36
 
37
37
  @overload
38
- def qname(value: ModelObject | str | QName | Any | None, name: str | ModelObject | dict[str, str] | None) -> QName | None : ...
38
+ def qname(value: ModelObject | str | QName | Any | None, name: str | ModelObject | dict[str, str] | dict[str | None, str] | None) -> QName | None : ...
39
39
 
40
40
  def qname(
41
41
  value: ModelObject | str | QName | Any | None,
42
- name: str | QName | ModelObject | dict[str, str] | None = None,
42
+ name: str | QName | ModelObject | dict[str, str] | dict[str | None, str] | None = None,
43
43
  noPrefixIsNoNamespace: bool = False,
44
44
  castException: Exception | None = None,
45
45
  prefixException: Exception | None = None,
@@ -66,6 +66,7 @@ def qname(
66
66
  elif not isinstance(value, str):
67
67
  if castException: raise castException
68
68
  return None
69
+ namespaceDict: dict[str | None, str] | None
69
70
  if value and value[0] == '{': # clark notation (with optional prefix)
70
71
  namespaceURI,sep,prefixedLocalName = value[1:].rpartition('}')
71
72
  prefix: str | None
@@ -85,7 +86,7 @@ def qname(
85
86
  else:
86
87
  if isinstance(name, dict):
87
88
  namespaceURI = None
88
- namespaceDict = name # note that default prefix must be None, not '', in dict
89
+ namespaceDict = cast(dict[str | None, str], name) # note that default prefix must be None, not '', in dict
89
90
  elif name is not None:
90
91
  if name: # len > 0
91
92
  namespaceURI = value
arelle/Validate.py CHANGED
@@ -764,7 +764,7 @@ class Validate:
764
764
  status = "pass" if numErrors == 0 else "fail"
765
765
  elif expected == "invalid":
766
766
  status = "fail" if numErrors == 0 else "pass"
767
- elif expected in (None, []) and numErrors == 0:
767
+ elif expected in (None, []) and numErrors == 0 and not expectedWarnings:
768
768
  status = "pass"
769
769
  elif isinstance(expected, (QName, str, dict, list)) or expectedWarnings:
770
770
  status = "fail"
arelle/XbrlConst.py CHANGED
@@ -55,6 +55,9 @@ qnXbrliDenominator = qname("{http://www.xbrl.org/2003/instance}xbrli:denominator
55
55
  qnXbrliTuple = qname("{http://www.xbrl.org/2003/instance}xbrli:tuple")
56
56
  qnXbrliContext = qname("{http://www.xbrl.org/2003/instance}xbrli:context")
57
57
  qnXbrliPeriod = qname("{http://www.xbrl.org/2003/instance}xbrli:period")
58
+ qnXbrliStartDate = qname("{http://www.xbrl.org/2003/instance}xbrli:startDate")
59
+ qnXbrliEndDate = qname("{http://www.xbrl.org/2003/instance}xbrli:endDate")
60
+ qnXbrliInstant = qname("{http://www.xbrl.org/2003/instance}xbrli:instant")
58
61
  qnXbrliIdentifier = qname("{http://www.xbrl.org/2003/instance}xbrli:identifier")
59
62
  qnXbrliUnit = qname("{http://www.xbrl.org/2003/instance}xbrli:unit")
60
63
  qnXbrliStringItemType = qname("{http://www.xbrl.org/2003/instance}xbrli:stringItemType")
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.34'
21
- __version_tuple__ = version_tuple = (2, 37, 34)
20
+ __version__ = version = '2.37.36'
21
+ __version_tuple__ = version_tuple = (2, 37, 36)
@@ -0,0 +1,12 @@
1
+ """
2
+ See COPYRIGHT.md for copyright information.
3
+ """
4
+ from arelle.ModelValue import qname
5
+
6
+ qnEdinetManifestInsert = qname("{http://disclosure.edinet-fsa.go.jp/2013/manifest}insert")
7
+ qnEdinetManifestInstance = qname("{http://disclosure.edinet-fsa.go.jp/2013/manifest}instance")
8
+ qnEdinetManifestItem = qname("{http://disclosure.edinet-fsa.go.jp/2013/manifest}item")
9
+ qnEdinetManifestIxbrl = qname("{http://disclosure.edinet-fsa.go.jp/2013/manifest}ixbrl")
10
+ qnEdinetManifestList = qname("{http://disclosure.edinet-fsa.go.jp/2013/manifest}list")
11
+ qnEdinetManifestTitle = qname("{http://disclosure.edinet-fsa.go.jp/2013/manifest}title")
12
+ qnEdinetManifestTocComposition = qname("{http://disclosure.edinet-fsa.go.jp/2013/manifest}tocComposition")
@@ -0,0 +1,124 @@
1
+ """
2
+ See COPYRIGHT.md for copyright information.
3
+ """
4
+ from __future__ import annotations
5
+
6
+ import zipfile
7
+ from dataclasses import dataclass
8
+ from functools import lru_cache
9
+ from pathlib import Path
10
+
11
+ from lxml import etree
12
+ from lxml.etree import _Element
13
+
14
+ from arelle import XbrlConst
15
+ from arelle.FileSource import FileSource
16
+ from arelle.ModelValue import QName, qname
17
+ from . import Constants
18
+
19
+
20
+ @dataclass(frozen=True)
21
+ class Manifest:
22
+ instances: list[ManifestInstance]
23
+ path: Path
24
+ titlesByLang: dict[str, str]
25
+ tocItems: list[ManifestTocItem]
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class ManifestTocItem:
30
+ extrole: str
31
+ childItems: list[ManifestTocItem]
32
+ itemIn: str
33
+ parent: QName | None
34
+ ref: str
35
+ start: QName | None
36
+
37
+
38
+ @dataclass(frozen=True)
39
+ class ManifestInstance:
40
+ id: str
41
+ ixbrlFiles: list[Path]
42
+ preferredFilename: str
43
+ type: str
44
+
45
+
46
+ def _parseManifestTocItems(parentElt: _Element, parentQName: QName | None) -> list[ManifestTocItem]:
47
+ tocItems = []
48
+ for itemElt in parentElt.iterchildren(tag=Constants.qnEdinetManifestItem.clarkNotation):
49
+ childTocItems = []
50
+ for insertElt in itemElt.iterchildren(tag=Constants.qnEdinetManifestInsert.clarkNotation):
51
+ childParentQName = qname(insertElt.attrib.get("parent"), insertElt.nsmap) if insertElt.attrib.get("parent") else None
52
+ childTocItems.extend(_parseManifestTocItems(insertElt, childParentQName))
53
+ tocItems.append(ManifestTocItem(
54
+ extrole=itemElt.attrib.get("extrole", ""),
55
+ childItems=childTocItems,
56
+ parent=parentQName,
57
+ itemIn=itemElt.attrib.get("in", ""),
58
+ ref=itemElt.attrib.get("ref", ""),
59
+ start=qname(itemElt.attrib.get("start"), itemElt.nsmap) if itemElt.attrib.get("start") else None,
60
+ ))
61
+ return tocItems
62
+
63
+
64
+ def _parseManifestDoc(xmlRootElement: _Element, path: Path) -> Manifest:
65
+ instances = []
66
+ titlesByLang = {}
67
+ base = path.parent
68
+ tocElts = list(xmlRootElement.iterchildren(tag=Constants.qnEdinetManifestTocComposition.clarkNotation))
69
+ assert len(tocElts) == 1, 'There should be exactly one tocComposition element in the manifest.'
70
+ for titleElt in tocElts[0].iterchildren(tag=Constants.qnEdinetManifestTitle.clarkNotation):
71
+ lang = titleElt.attrib.get(XbrlConst.qnXmlLang.clarkNotation, "")
72
+ titlesByLang[lang] = titleElt.text.strip() if titleElt.text else ""
73
+ tocItems = _parseManifestTocItems(tocElts[0], None)
74
+ listElts = list(xmlRootElement.iterchildren(tag=Constants.qnEdinetManifestList.clarkNotation))
75
+ assert len(listElts) == 1, 'There should be exactly one list element in the manifest.'
76
+ for instanceElt in listElts[0].iterchildren(tag=Constants.qnEdinetManifestInstance.clarkNotation):
77
+ instanceId = str(instanceElt.attrib.get("id", ""))
78
+ instanceType = str(instanceElt.attrib.get("type", ""))
79
+ preferredFilename = str(instanceElt.attrib.get("preferredFilename", ""))
80
+ ixbrlFiles = []
81
+ for ixbrlElt in instanceElt.iterchildren(tag=Constants.qnEdinetManifestIxbrl.clarkNotation):
82
+ uri = ixbrlElt.text.strip() if ixbrlElt.text is not None else None
83
+ if uri is not None and len(uri) > 0:
84
+ ixbrlFiles.append(base / uri)
85
+ instances.append(ManifestInstance(
86
+ id=instanceId,
87
+ ixbrlFiles=ixbrlFiles,
88
+ preferredFilename=preferredFilename,
89
+ type=instanceType,
90
+ ))
91
+ return Manifest(
92
+ instances=instances,
93
+ path=path,
94
+ titlesByLang=titlesByLang,
95
+ tocItems=tocItems,
96
+ )
97
+
98
+
99
+ @lru_cache(1)
100
+ def parseManifests(filesource: FileSource) -> list[Manifest]:
101
+ manifests: list[Manifest] = []
102
+ if filesource.isArchive:
103
+ if filesource.isTaxonomyPackage:
104
+ return manifests
105
+ if filesource.reportPackage is not None:
106
+ return manifests
107
+ for _archiveFile in (filesource.dir or ()):
108
+ if not Path(_archiveFile).stem.startswith('manifest'):
109
+ continue
110
+ assert isinstance(filesource.fs, zipfile.ZipFile), \
111
+ "The EDINET plugin only supports archives in .zip format."
112
+ with filesource.fs.open(_archiveFile) as manifestDoc:
113
+ xmlRootElement = etree.fromstring(manifestDoc.read())
114
+ manifests.append(_parseManifestDoc(xmlRootElement, Path(_archiveFile)))
115
+ elif (dirpath := Path(str(filesource.url))).is_dir():
116
+ for file in dirpath.rglob("*"):
117
+ if not file.is_file():
118
+ continue
119
+ if not file.stem.startswith('manifest'):
120
+ continue
121
+ with open(file, 'rb') as manifestDoc:
122
+ xmlRootElement = etree.fromstring(manifestDoc.read())
123
+ manifests.append(_parseManifestDoc(xmlRootElement, file))
124
+ return manifests
@@ -9,7 +9,10 @@ from dataclasses import dataclass
9
9
  from functools import lru_cache
10
10
  from pathlib import Path
11
11
 
12
+ from arelle.ModelDocument import Type as ModelDocumentType
13
+ from arelle.ModelObject import ModelObject
12
14
  from arelle.ModelXbrl import ModelXbrl
15
+ from arelle.PrototypeDtsObject import LinkPrototype
13
16
  from arelle.ValidateXbrl import ValidateXbrl
14
17
  from arelle.typing import TypeGetText
15
18
  from arelle.utils.PluginData import PluginData
@@ -60,6 +63,29 @@ class PluginValidationDataExtension(PluginData):
60
63
  return False # Not a zipfile
61
64
  return True
62
65
 
66
+ @lru_cache(1)
67
+ def getFootnoteLinkElements(self, modelXbrl: ModelXbrl) -> list[ModelObject | LinkPrototype]:
68
+ # TODO: Consolidate with similar implementations in EDGAR and FERC
69
+ doc = modelXbrl.modelDocument
70
+ if doc is None:
71
+ return []
72
+ if doc.type in (ModelDocumentType.INLINEXBRL, ModelDocumentType.INLINEXBRLDOCUMENTSET):
73
+ elts = (linkPrototype
74
+ for linkKey, links in modelXbrl.baseSets.items()
75
+ for linkPrototype in links
76
+ if linkPrototype.modelDocument.type in (ModelDocumentType.INLINEXBRL, ModelDocumentType.INLINEXBRLDOCUMENTSET)
77
+ and linkKey[1] and linkKey[2] and linkKey[3] # fully specified roles
78
+ and linkKey[0] != "XBRL-footnotes")
79
+ else:
80
+ rootElt = doc.xmlDocument.getroot()
81
+ elts = rootElt.iterdescendants(tag="{http://www.xbrl.org/2003/linkbase}footnoteLink")
82
+ return [
83
+ elt
84
+ for elt in elts
85
+ if isinstance(elt, (ModelObject, LinkPrototype))
86
+ ]
87
+
88
+
63
89
  def getUploadFileSizes(self, modelXbrl: ModelXbrl) -> dict[Path, int]:
64
90
  """
65
91
  Get the sizes of files in the upload directory.
@@ -5,17 +5,15 @@ See COPYRIGHT.md for copyright information.
5
5
  """
6
6
  from __future__ import annotations
7
7
 
8
- import zipfile
9
8
  from collections import defaultdict
10
9
  from pathlib import Path
11
10
  from typing import Any
12
11
 
13
- from lxml import etree
14
- from lxml.etree import _Element
15
-
16
12
  from arelle.FileSource import FileSource
17
13
  from arelle.ModelXbrl import ModelXbrl
18
14
  from arelle.Version import authorLabel, copyrightLabel
15
+ from . import Constants
16
+ from .Manifest import Manifest, ManifestInstance, parseManifests
19
17
  from .ValidationPluginExtension import ValidationPluginExtension
20
18
  from .rules import edinet, frta, gfm, upload
21
19
 
@@ -52,53 +50,18 @@ def disclosureSystemConfigURL(*args: Any, **kwargs: Any) -> str:
52
50
  return validationPlugin.disclosureSystemConfigURL
53
51
 
54
52
 
55
- def _parseManifestDoc(xmlRootElement: _Element, base: Path) -> dict[str, list[Path]]:
56
- sets = defaultdict(list)
57
- for instanceElt in xmlRootElement.iter(tag="{http://disclosure.edinet-fsa.go.jp/2013/manifest}instance"):
58
- instanceId = str(instanceElt.attrib["id"])
59
- for ixbrlElt in instanceElt.iter(tag="{http://disclosure.edinet-fsa.go.jp/2013/manifest}ixbrl"):
60
- uri = ixbrlElt.text.strip() if ixbrlElt.text is not None else None
61
- if uri:
62
- sets[instanceId].append(base / uri)
63
- return sets
64
-
65
-
66
53
  def fileSourceEntrypointFiles(filesource: FileSource, inlineOnly: bool, *args: Any, **kwargs: Any) -> list[dict[str, Any]] | None:
67
- manifests = {}
68
- if filesource.isArchive:
69
- if filesource.isTaxonomyPackage:
70
- return None
71
- if filesource.reportPackage is not None:
72
- return None
73
- for _archiveFile in (filesource.dir or ()):
74
- if not Path(_archiveFile).stem.startswith('manifest'):
75
- continue
76
- assert isinstance(filesource.fs, zipfile.ZipFile), \
77
- "The EDINET plugin only supports archives in .zip format."
78
- with filesource.fs.open(_archiveFile) as manifestDoc:
79
- base = Path(_archiveFile).parent
80
- xmlRootElement = etree.fromstring(manifestDoc.read())
81
- manifests.update(_parseManifestDoc(xmlRootElement, base))
82
- elif (dirpath := Path(str(filesource.url))).is_dir():
83
- for file in dirpath.rglob("*"):
84
- if not file.is_file():
85
- continue
86
- if not file.stem.startswith('manifest'):
87
- continue
88
- with open(file, 'rb') as manifestDoc:
89
- base = file.parent
90
- xmlRootElement = etree.fromstring(manifestDoc.read())
91
- manifests.update(_parseManifestDoc(xmlRootElement, base))
54
+ manifests = parseManifests(filesource)
92
55
  if len(manifests) == 0:
93
56
  return None
94
-
95
57
  entrypointFiles = []
96
- for instanceId, uris in manifests.items():
97
- entrypoints = []
98
- for uri in uris:
99
- filesource.select(str(uri))
100
- entrypoints.append({"file": filesource.url})
101
- entrypointFiles.append({'ixds': entrypoints})
58
+ for manifest in manifests:
59
+ for instance in manifest.instances:
60
+ entrypoints = []
61
+ for ixbrlFile in instance.ixbrlFiles:
62
+ filesource.select(str(ixbrlFile))
63
+ entrypoints.append({"file": filesource.url})
64
+ entrypointFiles.append({'ixds': entrypoints})
102
65
  return entrypointFiles
103
66
 
104
67
 
@@ -3,21 +3,30 @@ See COPYRIGHT.md for copyright information.
3
3
  """
4
4
  from __future__ import annotations
5
5
 
6
- from collections.abc import Iterable
7
- from typing import Any
6
+ from typing import Any, cast, Iterable
7
+
8
+ import regex
8
9
 
9
10
  from arelle import XbrlConst, XmlUtil
11
+ from arelle.ModelObject import ModelObject
12
+ from arelle.PrototypeDtsObject import LocPrototype, ArcPrototype
10
13
  from arelle.UrlUtil import isHttpUrl, splitDecodeFragment
11
14
  from arelle.ValidateXbrl import ValidateXbrl
15
+ from arelle.ValidateXbrlCalcs import insignificantDigits
16
+ from arelle.XbrlConst import xhtmlBaseIdentifier, xmlBaseIdentifier
17
+ from arelle.XmlValidate import VALID
12
18
  from arelle.typing import TypeGetText
13
19
  from arelle.utils.PluginHooks import ValidationHook
14
20
  from arelle.utils.validate.Decorator import validation
15
21
  from arelle.utils.validate.Validation import Validation
22
+ from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
16
23
  from ..DisclosureSystems import (DISCLOSURE_SYSTEM_EDINET)
17
24
  from ..PluginValidationDataExtension import PluginValidationDataExtension
18
25
 
19
26
  _: TypeGetText
20
27
 
28
+ GFM_CONTEXT_DATE_PATTERN = regex.compile(r"^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$")
29
+
21
30
 
22
31
  @validation(
23
32
  hook=ValidationHook.XBRL_FINALLY,
@@ -64,7 +73,7 @@ def rule_gfm_1_1_3(
64
73
  continue # Valid external URL
65
74
  if not any(scheme == "element" for scheme, __ in XmlUtil.xpointerSchemes(hrefId)):
66
75
  continue # Valid shorthand xpointer
67
- yield Validation.error(
76
+ yield Validation.warning(
68
77
  codes='EDINET.EC5700W.GFM.1.1.3',
69
78
  msg=_("The URI content of the xlink:href attribute, the xsi:schemaLocation "
70
79
  "attribute and the schemaLocation attribute must be relative and "
@@ -74,3 +83,188 @@ def rule_gfm_1_1_3(
74
83
  uri=uri,
75
84
  modelObject=elt,
76
85
  )
86
+
87
+
88
+ @validation(
89
+ hook=ValidationHook.XBRL_FINALLY,
90
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
91
+ )
92
+ def rule_gfm_1_1_7(
93
+ pluginData: PluginValidationDataExtension,
94
+ val: ValidateXbrl,
95
+ *args: Any,
96
+ **kwargs: Any,
97
+ ) -> Iterable[Validation]:
98
+ """
99
+ EDINET.EC5700W: [GFM 1.1.7] Attribute xml:base must not appear in any filing document.
100
+ This check has been updated to check for the xhtml:base attribute in order to account for iXBRL filings.
101
+
102
+ Original GFM text: Attribute xml:base must not appear in any filing document.
103
+ """
104
+ baseElements = []
105
+ for rootElt in val.modelXbrl.ixdsHtmlElements:
106
+ for uncast_elt, depth in etreeIterWithDepth(rootElt):
107
+ elt = cast(Any, uncast_elt)
108
+ if elt.get(xmlBaseIdentifier) is not None:
109
+ baseElements.append(elt)
110
+ if elt.tag == xhtmlBaseIdentifier:
111
+ baseElements.append(elt)
112
+ if len(baseElements) > 0:
113
+ yield Validation.warning(
114
+ codes='EDINET.EC5700W.GFM.1.1.7',
115
+ msg=_("Attribute xml:base must not appear in any filing document."),
116
+ modelObject=baseElements,
117
+ )
118
+
119
+
120
+ @validation(
121
+ hook=ValidationHook.XBRL_FINALLY,
122
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
123
+ )
124
+ def rule_gfm_1_2_16(
125
+ pluginData: PluginValidationDataExtension,
126
+ val: ValidateXbrl,
127
+ *args: Any,
128
+ **kwargs: Any,
129
+ ) -> Iterable[Validation]:
130
+ """
131
+ EDINET.EC5700W: [GFM 1.2.16] Use the decimals attribute instead of the precision attribute.
132
+
133
+ Original GFM text: The xbrli:xbrl element must not have any facts with the precision attribute.
134
+ """
135
+ errors = []
136
+ for fact in val.modelXbrl.facts:
137
+ concept = fact.concept
138
+ if concept is None:
139
+ continue
140
+ if not concept.isNumeric:
141
+ continue
142
+ if fact.precision is not None:
143
+ errors.append(fact)
144
+ if len(errors) > 0:
145
+ yield Validation.warning(
146
+ codes='EDINET.EC5700W.GFM.1.2.16',
147
+ msg=_("Use the decimals attribute instead of the precision attribute."),
148
+ modelObject=errors,
149
+ )
150
+
151
+
152
+ @validation(
153
+ hook=ValidationHook.XBRL_FINALLY,
154
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
155
+ )
156
+ def rule_gfm_1_2_22(
157
+ pluginData: PluginValidationDataExtension,
158
+ val: ValidateXbrl,
159
+ *args: Any,
160
+ **kwargs: Any,
161
+ ) -> Iterable[Validation]:
162
+ """
163
+ EDINET.EC5700W: [GFM 1.2.22] In your taxonomy, do not expand the
164
+ xlink:arcrole attribute of the link:footnoteArc element. Modify the value
165
+ of the xlink:arcrole attribute to "http://www.xbrl.org/2003/arcrole/fact-footnote".
166
+
167
+ Original GFM text: The xlink:arcrole attribute of a link:footnoteArc element must
168
+ be defined in the XBRL Specification 2.1 or declared in a standard taxonomy schema.
169
+ """
170
+ errors = []
171
+ for elt in pluginData.getFootnoteLinkElements(val.modelXbrl):
172
+ for child in elt:
173
+ if not isinstance(child, (ModelObject, LocPrototype, ArcPrototype)):
174
+ continue
175
+ xlinkType = child.get(XbrlConst.qnXlinkType.clarkNotation)
176
+ if xlinkType == "arc":
177
+ arcrole = child.get(XbrlConst.qnXlinkArcRole.clarkNotation)
178
+ if arcrole != XbrlConst.factFootnote:
179
+ errors.append(child)
180
+ if len(errors) > 0:
181
+ yield Validation.warning(
182
+ codes='EDINET.EC5700W.GFM.1.2.22',
183
+ msg=_("Do not use extension arcroles for the link:footnoteArc element. "
184
+ "Use the standard 'http://www.xbrl.org/2003/arcrole/fact-footnote' arcrole instead."),
185
+ modelObject=errors,
186
+ )
187
+
188
+
189
+ @validation(
190
+ hook=ValidationHook.XBRL_FINALLY,
191
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
192
+ )
193
+ def rule_gfm_1_2_25(
194
+ pluginData: PluginValidationDataExtension,
195
+ val: ValidateXbrl,
196
+ *args: Any,
197
+ **kwargs: Any,
198
+ ) -> Iterable[Validation]:
199
+ """
200
+ EDINET.EC5700W: [GFM 1.2.25] Set the date in the period element in the
201
+ following format: YYYY-MM-DD.
202
+
203
+ Original GFM text: Dates in period element of the context must comply with
204
+ yyyy-mm-dd format. No time is allowed in the value for dates.
205
+ """
206
+ errors = []
207
+ for context in val.modelXbrl.contexts.values():
208
+ for elt in context.iterdescendants(
209
+ XbrlConst.qnXbrliStartDate.clarkNotation,
210
+ XbrlConst.qnXbrliEndDate.clarkNotation,
211
+ XbrlConst.qnXbrliInstant.clarkNotation
212
+ ):
213
+ dateText = XmlUtil.text(elt)
214
+ if not GFM_CONTEXT_DATE_PATTERN.match(dateText):
215
+ errors.append(elt)
216
+ if len(errors) > 0:
217
+ yield Validation.warning(
218
+ codes='EDINET.EC5700W.GFM.1.2.25',
219
+ msg=_("Set the date in the period element in the following "
220
+ "format: YYYY-MM-DD."),
221
+ modelObject=errors,
222
+ )
223
+
224
+
225
+ @validation(
226
+ hook=ValidationHook.XBRL_FINALLY,
227
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
228
+ )
229
+ def rule_gfm_1_2_26(
230
+ pluginData: PluginValidationDataExtension,
231
+ val: ValidateXbrl,
232
+ *args: Any,
233
+ **kwargs: Any,
234
+ ) -> Iterable[Validation]:
235
+ """
236
+ EDINET.EC5700W: [GFM 1.2.26] The decimals attribute value must not cause truncation of
237
+ non-zero digits in the fact value. Update the fact value to match the precision of
238
+ the decimals attribute, or update the decimals attribute.
239
+
240
+ Original GFM text: The decimals attribute value must not cause non-zero digits in
241
+ the fact value to be changed to zero.
242
+ """
243
+ errors = []
244
+ for fact in val.modelXbrl.facts:
245
+ if (
246
+ fact.context is None or
247
+ fact.concept is None or
248
+ fact.concept.type is None or
249
+ getattr(fact,"xValid", 0) < VALID or
250
+ fact.isNil or
251
+ not fact.isNumeric or
252
+ not fact.decimals or
253
+ fact.decimals == "INF"
254
+ ):
255
+ continue
256
+ try:
257
+ insignificance = insignificantDigits(fact.xValue, decimals=fact.decimals)
258
+ if insignificance is not None:
259
+ errors.append(fact)
260
+ except (ValueError,TypeError):
261
+ errors.append(fact)
262
+ if len(errors) > 0:
263
+ yield Validation.warning(
264
+ codes='EDINET.EC5700W.GFM.1.2.26',
265
+ msg=_("The decimals attribute value must not cause truncation of "
266
+ "non-zero digits in the fact value. Update the fact value to "
267
+ "match the precision of the decimals attribute, or update the"
268
+ "decimals attribute."),
269
+ modelObject=errors,
270
+ )
@@ -4,11 +4,10 @@ See COPYRIGHT.md for copyright information.
4
4
  from __future__ import annotations
5
5
 
6
6
  import re
7
- import zipfile
8
7
  from collections import defaultdict
9
8
  from collections.abc import Iterable
10
9
  from pathlib import Path
11
- from typing import Any, cast, IO
10
+ from typing import Any
12
11
 
13
12
  from arelle.ValidateXbrl import ValidateXbrl
14
13
  from arelle.typing import TypeGetText
@@ -17,6 +16,7 @@ from arelle.utils.validate.Decorator import validation
17
16
  from arelle.utils.validate.Validation import Validation
18
17
  from ..DisclosureSystems import (DISCLOSURE_SYSTEM_EDINET)
19
18
  from ..FormType import FormType, HTML_EXTENSIONS, IMAGE_EXTENSIONS
19
+ from ..Manifest import parseManifests
20
20
  from ..PluginValidationDataExtension import PluginValidationDataExtension
21
21
 
22
22
  _: TypeGetText
@@ -452,3 +452,73 @@ def rule_EC1020E(
452
452
  path=str(path),
453
453
  file=str(path),
454
454
  )
455
+
456
+
457
+ @validation(
458
+ hook=ValidationHook.XBRL_FINALLY,
459
+ disclosureSystems=[DISCLOSURE_SYSTEM_EDINET],
460
+ )
461
+ def rule_manifest_preferredFilename(
462
+ pluginData: PluginValidationDataExtension,
463
+ val: ValidateXbrl,
464
+ *args: Any,
465
+ **kwargs: Any,
466
+ ) -> Iterable[Validation]:
467
+ """
468
+ EDINET.EC5804E: The preferredFilename attribute must be set on the instance
469
+ element in the manifest file.
470
+
471
+ EDINET.EC5805E: The instance file extension is not ".xbrl". File name: xxx
472
+ Please change the extension of the instance name set in the preferredFilename
473
+ attribute value of the instance element in the manifest file to ".xbrl".
474
+
475
+ EDINET.EC5806E: The same instance file name is set multiple times. File name: xxx
476
+ The preferredFilename attribute value of the instance element in the manifest
477
+ file must be unique within the same file.
478
+ """
479
+ if not pluginData.shouldValidateUpload(val):
480
+ return
481
+ manifests = parseManifests(val.modelXbrl.fileSource)
482
+ for manifest in manifests:
483
+ preferredFilenames = set()
484
+ duplicateFilenames = set()
485
+ for instance in manifest.instances:
486
+ if len(instance.preferredFilename) == 0:
487
+ yield Validation.error(
488
+ codes='EDINET.EC5804E',
489
+ msg=_("The instance file name is not set. "
490
+ "Set the instance name as the preferredFilename attribute value "
491
+ "of the instance element in the manifest file. (manifest: '%(manifest)s', id: %(id)s)"),
492
+ manifest=str(manifest.path),
493
+ id=instance.id,
494
+ )
495
+ continue
496
+ preferredFilename = Path(instance.preferredFilename)
497
+ if preferredFilename.suffix != '.xbrl':
498
+ yield Validation.error(
499
+ codes='EDINET.EC5805E',
500
+ msg=_("The instance file extension is not '.xbrl'. "
501
+ "File name: '%(preferredFilename)s'. "
502
+ "Please change the extension of the instance name set in the "
503
+ "preferredFilename attribute value of the instance element in "
504
+ "the manifest file to '.xbrl'. (manifest: '%(manifest)s', id: %(id)s)"),
505
+ preferredFilename=instance.preferredFilename,
506
+ manifest=str(manifest.path),
507
+ id=instance.id,
508
+ )
509
+ continue
510
+ if instance.preferredFilename in preferredFilenames:
511
+ duplicateFilenames.add(instance.preferredFilename)
512
+ continue
513
+ preferredFilenames.add(instance.preferredFilename)
514
+ for duplicateFilename in duplicateFilenames:
515
+ yield Validation.error(
516
+ codes='EDINET.EC5806E',
517
+ msg=_("The same instance file name is set multiple times. "
518
+ "File name: '%(preferredFilename)s'. "
519
+ "The preferredFilename attribute value of the instance "
520
+ "element in the manifest file must be unique within the "
521
+ "same file. (manifest: '%(manifest)s')"),
522
+ manifest=str(manifest.path),
523
+ preferredFilename=duplicateFilename,
524
+ )
@@ -296,67 +296,21 @@ def rule_main(
296
296
  @validation(
297
297
  hook=ValidationHook.XBRL_FINALLY,
298
298
  )
299
- def rule_ros6(
299
+ def rule_ros20(
300
300
  pluginData: PluginValidationDataExtension,
301
301
  val: ValidateXbrl,
302
302
  *args: Any,
303
303
  **kwargs: Any,
304
304
  ) -> Iterable[Validation]:
305
305
  """
306
- ROS: Rule 6: ProfitLossOnOrdinaryActivitiesBeforeTax OR ProfitLossBeforeTax must exist in the document and be non-nil.
307
- """
308
- non_nil_profit_loss_fact_exists = any(
309
- not fact.isNil for fact in val.modelXbrl.factsByLocalName.get(IE_PROFIT_LOSS, set())
310
- )
311
- non_nil_profit_loss_ordinary_fact_exists = any(
312
- not fact.isNil for fact in val.modelXbrl.factsByLocalName.get(IE_PROFIT_LOSS_ORDINARY, set())
313
- )
314
- if not non_nil_profit_loss_fact_exists and not non_nil_profit_loss_ordinary_fact_exists:
315
- yield Validation.error(
316
- codes='ROS.6',
317
- msg=_("Profit or Loss Before Tax (uk gaap:ProfitLossOnOrdinaryActivitiesBeforeTax) is missing."),
318
- modelObject=val.modelXbrl
319
- )
320
-
321
-
322
- @validation(
323
- hook=ValidationHook.XBRL_FINALLY,
324
- )
325
- def rule_ros18(
326
- pluginData: PluginValidationDataExtension,
327
- val: ValidateXbrl,
328
- *args: Any,
329
- **kwargs: Any,
330
- ) -> Iterable[Validation]:
331
- """
332
- ROS: Rule 18: DPLTurnoverRevenue cannot be a negative value.
333
- """
334
- return errorOnNegativeFact(
335
- val.modelXbrl,
336
- conceptLn=TURNOVER_REVENUE,
337
- code='ROS.18',
338
- message=_("Turnover / Revenue cannot be a negative value.")
339
- )
340
-
341
-
342
- @validation(
343
- hook=ValidationHook.XBRL_FINALLY,
344
- )
345
- def rule_ros19(
346
- pluginData: PluginValidationDataExtension,
347
- val: ValidateXbrl,
348
- *args: Any,
349
- **kwargs: Any,
350
- ) -> Iterable[Validation]:
351
- """
352
- ROS: Rule 19:PrincipalCurrencyUsedInBusinessReport must exist and its value must match the unit
306
+ ROS: Rule 20:PrincipalCurrencyUsedInBusinessReport must exist and its value must match the unit
353
307
  used for the majority of monetary facts.
354
308
  """
355
309
  principal_currency_facts = val.modelXbrl.factsByLocalName.get(PRINCIPAL_CURRENCY, set())
356
310
  principal_currency_values = set(fact.text for fact in principal_currency_facts)
357
311
  if len(principal_currency_values) != 1:
358
312
  yield Validation.error(
359
- "ROS.19",
313
+ "ROS.20",
360
314
  _("'PrincipalCurrencyUsedInBusinessReport' must exist and have a single value. Values found: %(principal_currency_values)s."),
361
315
  modelObject=principal_currency_facts,
362
316
  principal_currency_values=principal_currency_values,
@@ -370,7 +324,7 @@ def rule_ros19(
370
324
  for unit, count in unit_counts.items():
371
325
  if count > principal_currency_value_count:
372
326
  yield Validation.warning(
373
- "ROS.19",
327
+ "ROS.20",
374
328
  _("'PrincipalCurrencyUsedInBusinessReport' has a value of %(principal_currency_value)s, "
375
329
  "which must match the functional(majority) unit of the financial statement."),
376
330
  modelObject=principal_currency_facts,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arelle-release
3
- Version: 2.37.34
3
+ Version: 2.37.36
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License-Expression: Apache-2.0
@@ -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=mQlz8eezPpJuG6gHBV-x4-5Hne3LVh8TQf-Qm9jiFxI,24757
24
- arelle/FileSource.py,sha256=S19Rll9CoRPZ2zJCAlNHv1jt2UUfiLbSgI2tDdJq5Xc,47899
24
+ arelle/FileSource.py,sha256=asaX2wM47T7S6kELwmXm-YjGIoV6poWz_YdYThY0lpk,47983
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
@@ -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=dnCxatJcFPlu5BgTuToqgrQowYNx4YtA5KrmW4vHko4,22432
49
- arelle/ModelValue.py,sha256=t0mVl3-EcE4MaXdRL9F94XaBwBfu1xG2DmFuHOczrEk,39447
49
+ arelle/ModelValue.py,sha256=0sr7njFjGI2W3Bct2dxf2LoG_fLerHQouQtM0v0ZY2E,39573
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=bj-_enkb2AV2KVCRrRf2YPGxOoO9cdqKnVqfy3bGFZk,72125
@@ -65,7 +65,7 @@ arelle/UITkTable.py,sha256=N83cXi5c0lLZLsDbwSKcPrlYoUoGsNavGN5YRx6d9XY,39810
65
65
  arelle/UiUtil.py,sha256=3G0xPclZI8xW_XQDbiFrmylB7Nd5muqi5n2x2oMkMZU,34218
66
66
  arelle/Updater.py,sha256=IZ8cq44Rq88WbQcB1VOpMA6bxdfZxfYQ8rgu9Ehpbes,7448
67
67
  arelle/UrlUtil.py,sha256=HrxZSG59EUMGMMGmWPuZkPi5-0BGqY3jAMkp7V4IdZo,32400
68
- arelle/Validate.py,sha256=SxdFqjqNy3Dp2dFZV2YXn61uygZsf2UtSE5gmdqiZY8,58024
68
+ arelle/Validate.py,sha256=YQUr2t2lyuQJD4ygfKgbj7grON-Od5pYfkjFVS5XuDM,58049
69
69
  arelle/ValidateDuplicateFacts.py,sha256=L556J1Dhz4ZmsMlRNoDCMpFgDQYiryd9vuBYDvE0Aq8,21769
70
70
  arelle/ValidateFilingText.py,sha256=xnXc0xgdNiHQk0eyP7VSSpvw7qr-pRFRwqqoUb569is,54051
71
71
  arelle/ValidateInfoset.py,sha256=Rz_XBi5Ha43KpxXYhjLolURcWVx5qmqyjLxw48Yt9Dg,20396
@@ -114,7 +114,7 @@ arelle/ViewWinVersReport.py,sha256=aYfsOgynVZpMzl6f2EzQCBLzdihYGycwb5SiTghkgMQ,9
114
114
  arelle/ViewWinXml.py,sha256=4ZGKtjaoCwU9etKYm9ZAS7jSmUxba1rqNEdv0OIyjTY,1250
115
115
  arelle/WatchRss.py,sha256=5Ih4igH2MM4hpOuAXy9eO0QAyZ7jZR3S5bPzo2sdFpw,14097
116
116
  arelle/WebCache.py,sha256=HlF4vfjxO0bSFHqMPfjnmkrzc7RK9XT714a7g3XFTDY,45192
117
- arelle/XbrlConst.py,sha256=k-cingAiunkqPd7YkFMgF6y5syj9GRWP84DTK2aDrCY,57935
117
+ arelle/XbrlConst.py,sha256=T8Cvogf1j2I5aws7ZDwLmCj6zcYwxUZIk9ZXDYwHfxU,58164
118
118
  arelle/XbrlUtil.py,sha256=s2Vmrh-sZI5TeuqsziKignOc3ao-uUgnCNoelP4dDj0,9212
119
119
  arelle/XhtmlValidate.py,sha256=0gtm7N-kXK0RB5o3c1AQXjfFuRp1w2fKZZAeyruNANw,5727
120
120
  arelle/XmlUtil.py,sha256=1VToOOylF8kbEorEdZLThmq35j9bmuF_DS2q9NthnHU,58774
@@ -123,7 +123,7 @@ 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=UdKRHaB3pyxyxupZQ1MDG4KdlqxGBWeWxgwroLH2N_g,515
126
+ arelle/_version.py,sha256=qE1JoU23iZVZMuNLXnlDRaP4Udr6pvevq0c9sMilUZ4,515
127
127
  arelle/typing.py,sha256=PRe-Fxwr2SBqYYUVPCJ3E7ddDX0_oOISNdT5Q97EbRM,1246
128
128
  arelle/api/Session.py,sha256=27HVuK3Bz1_21l4_RLn1IQg6v0MNsUEYrHajymyWwxI,7429
129
129
  arelle/archive/CustomLogger.py,sha256=v_JXOCQLDZcfaFWzxC9FRcEf9tQi4rCI4Sx7jCuAVQI,1231
@@ -392,18 +392,20 @@ arelle/plugin/validate/DBA/rules/tm.py,sha256=ui9oKBqlAForwkQ9kk9KBiUogTJE5pv1Rb
392
392
  arelle/plugin/validate/DBA/rules/tr.py,sha256=zdi3kQ82whmweVWRLbMvcNpM8sqtUliPsGfd81rgZws,14671
393
393
  arelle/plugin/validate/EBA/__init__.py,sha256=1kW-04W32sStSAL8wvW1ZpXnjlFv6KLbfE4aifYUB2A,46000
394
394
  arelle/plugin/validate/EBA/config.xml,sha256=37wMVUAObK-XEqakqD8zPNog20emYt4a_yfL1AKubF8,2022
395
+ arelle/plugin/validate/EDINET/Constants.py,sha256=QG69rWdpIrpQzZQkRcDWk2i3rlBVohr4VtSdW-IS5_w,734
395
396
  arelle/plugin/validate/EDINET/DisclosureSystems.py,sha256=3rKG42Eg-17Xx_KXU_V5yHW6I3LTwQunvf4a44C9k_4,36
396
397
  arelle/plugin/validate/EDINET/FormType.py,sha256=pJfKjdjqFcRLFgH6xbEixvpwatZBBHI8uI3xjjhaPI0,3175
397
- arelle/plugin/validate/EDINET/PluginValidationDataExtension.py,sha256=VSSffANEC5kuvLC54pWYQ7w8fuSKo5LGdiuZ3NwWktg,5061
398
+ arelle/plugin/validate/EDINET/Manifest.py,sha256=VWenzA1ndOp802zpTELSLREbCrzrA-nM1UCRpRf1Q3M,4849
399
+ arelle/plugin/validate/EDINET/PluginValidationDataExtension.py,sha256=vJPs5GgNJbRUBTKP0ULMb4UqvDoGATPC9dTFsKG4HyI,6347
398
400
  arelle/plugin/validate/EDINET/ValidationPluginExtension.py,sha256=HIGOpBOyuVs5SEh573M3IzdouRdEuNIBkdumieZi8r0,959
399
- arelle/plugin/validate/EDINET/__init__.py,sha256=7Z3IdTdx0OdSm65jYYeRx_0B_zSvUKQubgXpa76OlvA,5164
401
+ arelle/plugin/validate/EDINET/__init__.py,sha256=ew9Rc2qJe5d3XvOOFzhX6MfzxNUtxIYfxRGX-wkfR1c,3555
400
402
  arelle/plugin/validate/EDINET/resources/config.xml,sha256=GmLcW7UIj5koXJkN19P6Nq5EZJcs6gKQLQ5f2V6u78w,614
401
403
  arelle/plugin/validate/EDINET/resources/edinet-taxonomies.xml,sha256=997I3RGTLg5OY3vn5hQxVFAAxOmDSOYpuyQe6VnWSY0,16285
402
404
  arelle/plugin/validate/EDINET/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
403
405
  arelle/plugin/validate/EDINET/rules/edinet.py,sha256=hm5T8PiQbOKP58BiSV9UFvKQX10uNBpxUZ06ORSU1cE,2117
404
406
  arelle/plugin/validate/EDINET/rules/frta.py,sha256=l7BQHOenDjYrpCX6bsXyUHgyvkjbfvJWfbpBthCHmBI,1713
405
- arelle/plugin/validate/EDINET/rules/gfm.py,sha256=rj1ylvRIoauyzlEW1z1UxOkgO6fzvoMl5myRKkEZzY4,3295
406
- arelle/plugin/validate/EDINET/rules/upload.py,sha256=sZFDSRWukJZEEBfg_RsG1q3Qw1IHhD0LZjl9LL1i9Ao,17048
407
+ arelle/plugin/validate/EDINET/rules/gfm.py,sha256=EYOPRzJrjp9taPFm53vn7e4CEq0rgIps4_bEslSZJWo,10392
408
+ arelle/plugin/validate/EDINET/rules/upload.py,sha256=HZ-9Gk6WtIichTGcSsSGIrMXNgsgJYQYwfUKeLs1XWU,20369
407
409
  arelle/plugin/validate/ESEF/Const.py,sha256=JujF_XV-_TNsxjGbF-8SQS4OOZIcJ8zhCMnr-C1O5Ho,22660
408
410
  arelle/plugin/validate/ESEF/Dimensions.py,sha256=MOJM7vwNPEmV5cu-ZzPrhx3347ZvxgD6643OB2HRnIk,10597
409
411
  arelle/plugin/validate/ESEF/Util.py,sha256=QH3btcGqBpr42M7WSKZLSdNXygZaZLfEiEjlxoG21jE,7950
@@ -439,7 +441,7 @@ arelle/plugin/validate/ROS/__init__.py,sha256=KuWg1MHVzA2S6eaHFptvP3Vu_5gQWf3OUY
439
441
  arelle/plugin/validate/ROS/config.xml,sha256=ZCpCFgr1ZAjoUuhb1eRpDnmKrae-sXA9yl6SOWnrfm8,654
440
442
  arelle/plugin/validate/ROS/resources/config.xml,sha256=HXWume5HlrAqOx5AtiWWqgADbRatA8YSfm_JvZGwdgQ,657
441
443
  arelle/plugin/validate/ROS/rules/__init__.py,sha256=wW7BUAIb7sRkOxC1Amc_ZKrz03FM-Qh1TyZe6wxYaAU,1567
442
- arelle/plugin/validate/ROS/rules/ros.py,sha256=6DciQvv3H9QCEaDgINfHejZd196pEulUcQHk2qqMWhs,19921
444
+ arelle/plugin/validate/ROS/rules/ros.py,sha256=Vv7qKMmhBEuPu7y_g0sjiDLnm5VXXz6EVdzonJbCUtg,18436
443
445
  arelle/plugin/validate/UK/ValidateUK.py,sha256=0UhSwsY1lrY-EAEBJJR9QY38YXGBZ6PEgmuC5gQfBlI,57813
444
446
  arelle/plugin/validate/UK/__init__.py,sha256=KE6s_B-EvrHDCtWQz2N_wQwyx_ZbWhYNV2GfQnluxMw,30655
445
447
  arelle/plugin/validate/UK/config.xml,sha256=mUFhWDfBzGTn7v0ZSmf4HaweQTMJh_4ZcJmD9mzCHrA,1547
@@ -754,9 +756,9 @@ arelle/utils/validate/ValidationUtil.py,sha256=9vmSvShn-EdQy56dfesyV8JjSRVPj7txr
754
756
  arelle/utils/validate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
755
757
  arelle/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
756
758
  arelle/webserver/bottle.py,sha256=P-JECd9MCTNcxCnKoDUvGcoi03ezYVOgoWgv2_uH-6M,362
757
- arelle_release-2.37.34.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
758
- arelle_release-2.37.34.dist-info/METADATA,sha256=580O6L8VeM_RIhUWVmkF7s_ifRMpg3mYX3e_8G3u33I,9137
759
- arelle_release-2.37.34.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
760
- arelle_release-2.37.34.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
761
- arelle_release-2.37.34.dist-info/top_level.txt,sha256=fwU7SYawL4_r-sUMRg7r1nYVGjFMSDvRWx8VGAXEw7w,7
762
- arelle_release-2.37.34.dist-info/RECORD,,
759
+ arelle_release-2.37.36.dist-info/licenses/LICENSE.md,sha256=Q0tn6q0VUbr-NM8916513NCIG8MNzo24Ev-sxMUBRZc,3959
760
+ arelle_release-2.37.36.dist-info/METADATA,sha256=O21K0JV03vScH1fAs0RomXYXTEyz-r135EHcUNJbaI8,9137
761
+ arelle_release-2.37.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
762
+ arelle_release-2.37.36.dist-info/entry_points.txt,sha256=Uj5niwfwVsx3vaQ3fYj8hrZ1xpfCJyTUA09tYKWbzpo,111
763
+ arelle_release-2.37.36.dist-info/top_level.txt,sha256=fwU7SYawL4_r-sUMRg7r1nYVGjFMSDvRWx8VGAXEw7w,7
764
+ arelle_release-2.37.36.dist-info/RECORD,,