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

@@ -428,6 +428,9 @@ class ModelFact(ModelObject):
428
428
  # non-numeric fact at this point
429
429
  if len(val) == 0: # zero length string for HMRC fixed fact
430
430
  return "(reported)"
431
+ if self.xValid >= VALID and isinstance(self.xValue, str):
432
+ # Prefer the xs:whiteSpace normalized version of strings
433
+ return self.xValue
431
434
  return val
432
435
  except Exception as ex:
433
436
  return str(ex) # could be transform value of inline fact
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.26'
21
- __version_tuple__ = version_tuple = (2, 36, 26)
20
+ __version__ = version = '2.36.28'
21
+ __version_tuple__ = version_tuple = (2, 36, 28)
arelle/oim/Load.py CHANGED
@@ -1608,6 +1608,8 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
1608
1608
  (tableDimensions, "table dimension"),
1609
1609
  (reportDimensions, "report dimension")):
1610
1610
  for dimName, dimValue in inheritedDims.items():
1611
+ if dimSource.startswith("propertyGroup"):
1612
+ factDimensionPropGrpCol[dimName] = propGroupDimSource[dimName]
1611
1613
  if dimName not in colFactDims and dimName not in noValueDimNames:
1612
1614
  dimValue = inheritedDims[dimName]
1613
1615
  dimAttr = None
@@ -1651,8 +1653,6 @@ def _loadFromOIM(cntlr, error, warning, modelXbrl, oimFile, mappedUri):
1651
1653
  noValueDimNames.add(dimName)
1652
1654
  else:
1653
1655
  colFactDims[dimName] = dimValue
1654
- if dimSource.startswith("propertyGroup"):
1655
- factDimensionPropGrpCol[dimName] = propGroupDimSource[dimName]
1656
1656
  if factDecimals.get(colName) is not None:
1657
1657
  dimValue = factDecimals[colName]
1658
1658
  dimSource = "column decimals"
@@ -1,105 +1,222 @@
1
- '''
1
+ """
2
2
  Save HTML EBA Tables is an example of a plug-in to both GUI menu and command line/web service
3
3
  that will save a directory containing HTML Tablesets with an EBA index page.
4
4
 
5
5
  See COPYRIGHT.md for copyright information.
6
- '''
7
- from arelle.Version import authorLabel, copyrightLabel
6
+ """
8
7
 
9
- def generateHtmlEbaTablesetFiles(dts, indexFile, lang="en"):
10
- try:
11
- import os, io
12
- from arelle import Version, XbrlConst, XmlUtil
13
- from arelle.ViewFileRenderedGrid import viewRenderedGrid
14
- from arelle.ModelRenderingObject import DefnMdlTable
8
+ import os
9
+ import threading
10
+ from operator import itemgetter
11
+ from optparse import OptionParser
12
+ from tkinter import Menu
13
+ from typing import Any
15
14
 
16
- numTableFiles = 0
15
+ from lxml import etree
16
+
17
+ from arelle import Version, XbrlConst, XmlUtil
18
+ from arelle.CntlrCmdLine import CntlrCmdLine
19
+ from arelle.CntlrWinMain import CntlrWinMain
20
+ from arelle.ModelDocument import Type
21
+ from arelle.ModelObjectFactory import parser
22
+ from arelle.ModelRenderingObject import DefnMdlTable
23
+ from arelle.ModelXbrl import ModelXbrl
24
+ from arelle.rendering import RenderingEvaluator
25
+ from arelle.RuntimeOptions import RuntimeOptions
26
+ from arelle.typing import TypeGetText
27
+ from arelle.utils.PluginHooks import PluginHooks
28
+ from arelle.ViewFileRenderedGrid import viewRenderedGrid
29
+
30
+ _: TypeGetText
31
+
32
+ MENU_HTML = """<!DOCTYPE html>
33
+ <html>
34
+ <head>
35
+ <style>
36
+ body {
37
+ margin: 0;
38
+ padding: 10px;
39
+ font-family: Arial, sans-serif;
40
+ color: #243e5e;
41
+ }
42
+ .nav-list-menu-ul {
43
+ list-style-type: none;
44
+ padding: 0;
45
+ margin: 0;
46
+ }
47
+ .nav-list-menu-li {
48
+ margin: 5px 0;
49
+ padding: 5px;
50
+ border-bottom: 1px solid #eee;
51
+ }
52
+ .nav-list-menu-link {
53
+ text-decoration: none;
54
+ cursor: pointer;
55
+ display: block;
56
+ background: none;
57
+ border: none;
58
+ padding: 0;
59
+ }
60
+ .nav-list-menu-link:hover {
61
+ text-decoration: underline;
62
+ }
63
+ </style>
64
+ </head>
65
+ <body>
66
+ <ul class="nav-list-menu-ul"/>
67
+ </body>
68
+ </html>
69
+ """
17
70
 
18
- file = io.StringIO('''
19
- <html xmlns="http://www.w3.org/1999/xhtml">
20
- <head id="Left">
21
- <link type="text/css" rel="stylesheet" href="http://arelle.org/files/EBA/style20121210/eba.css" />
71
+ CENTER_LANDING_HTML = """<!DOCTYPE html>
72
+ <html>
73
+ <head>
74
+ <style>
75
+ body {
76
+ margin: 0;
77
+ padding: 20px;
78
+ font-family: Arial, sans-serif;
79
+ }
80
+ #page-title {
81
+ margin-bottom: 20px;
82
+ }
83
+ #page-title h1 {
84
+ color: #243e5e;
85
+ margin-top: 0;
86
+ }
87
+ #content-center {
88
+ margin-top: 20px;
89
+ line-height: 1.5;
90
+ }
91
+ </style>
22
92
  </head>
23
- <body class="LTR IE7 ENGB">
24
- <ul class="CMSListMenuUL" id="Vertical2"/>
93
+ <body>
94
+ <div id="page-title">
95
+ <h1>Taxonomy Tables Viewer</h1>
96
+ </div>
97
+ <div id="content-center">
98
+ <p>Please select tables to view by clicking in the left column.</p>
99
+ </div>
100
+ </body>
101
+ </html>
102
+ """
103
+
104
+ TABLE_CSS_EXTRAS = """
105
+ table {background:#fff}
106
+ """
107
+
108
+
109
+ def indexFileHTML(indexBaseName: str) -> str:
110
+ return f'''<!DOCTYPE html>
111
+ <html>
112
+ <head>
113
+ <meta charset="utf-8">
114
+ <meta name="viewport" content="width=device-width, initial-scale=1">
115
+ <title>EBA - Tablesets</title>
116
+ <style>
117
+ html, body {{
118
+ margin: 0;
119
+ padding: 0;
120
+ height: 100%;
121
+ width: 100%;
122
+ font-family: Arial, sans-serif;
123
+ display: flex;
124
+ flex-direction: column;
125
+ }}
126
+ #header {{
127
+ background: rgb(36, 62, 94);
128
+ color: rgb(255, 255, 255);
129
+ height: 40px;
130
+ }}
131
+ #header h1 {{
132
+ font-size: 1.5em;
133
+ margin: 0.25em;
134
+ }}
135
+ #main-container {{
136
+ display: flex;
137
+ flex: 1;
138
+ height: calc(100vh - 40px);
139
+ }}
140
+ #menu-container {{
141
+ width: 360px;
142
+ border-right: 2px solid #243e5e;
143
+ overflow-y: auto;
144
+ box-sizing: border-box;
145
+ }}
146
+ #content-container {{
147
+ flex: 1;
148
+ overflow: auto;
149
+ box-sizing: border-box;
150
+ }}
151
+ iframe {{
152
+ border: none;
153
+ width: 100%;
154
+ height: 100%;
155
+ }}
156
+ </style>
157
+ <script>
158
+ function loadContent(url) {{
159
+ document.getElementById('content-frame').src = url;
160
+ }}
161
+ </script>
162
+ </head>
163
+ <body>
164
+ <div id="header"><h1>EBA - Tablesets</h1></div>
165
+ <div id="main-container">
166
+ <div id="menu-container">
167
+ <iframe src="{indexBaseName}FormsFrame.html" width="100%" height="100%" frameborder="0" id="menu-frame"></iframe>
168
+ </div>
169
+ <div id="content-container">
170
+ <iframe src="{indexBaseName}CenterLanding.html" width="100%" height="100%" frameborder="0" id="content-frame"></iframe>
171
+ </div>
172
+ </div>
25
173
  </body>
26
174
  </html>
27
175
  '''
28
- )
29
- from arelle.ModelObjectFactory import parser
30
- parser, parserLookupName, parserLookupClass = parser(dts,None)
31
- from lxml import etree
32
- indexDocument = etree.parse(file,parser=parser,base_url=indexFile)
33
- file.close()
34
- #xmlDocument.getroot().init(self) ## is this needed ??
35
- for listElt in indexDocument.iter(tag="{http://www.w3.org/1999/xhtml}ul"):
36
- break
37
-
38
- class nonTkBooleanVar():
39
- def __init__(self, value=True):
40
- self.value = value
41
- def set(self, value):
42
- self.value = value
43
- def get(self):
44
- return self.value
45
-
46
- class View():
47
- def __init__(self, tableOrELR, ignoreDimValidity, xAxisChildrenFirst, yAxisChildrenFirst):
48
- self.tblELR = tableOrELR
49
- # context menu boolean vars (non-tkinter boolean
50
- self.ignoreDimValidity = nonTkBooleanVar(value=ignoreDimValidity)
51
- self.xAxisChildrenFirst = nonTkBooleanVar(value=xAxisChildrenFirst)
52
- self.yAxisChildrenFirst = nonTkBooleanVar(value=yAxisChildrenFirst)
176
+
177
+
178
+ def generateHtmlEbaTablesetFiles(dts: ModelXbrl, indexFile: str, lang: str = "en") -> None:
179
+ try:
180
+ numTableFiles = 0
181
+ _parser = parser(dts, None)[0]
182
+ menuFrameDocument = etree.fromstring(MENU_HTML, parser=_parser, base_url=indexFile)
183
+ listElt = menuFrameDocument.find(".//ul")
184
+ assert listElt is not None, "No list element in index document"
53
185
 
54
186
  indexBase = indexFile.rpartition(".")[0]
55
187
  groupTableRels = dts.modelXbrl.relationshipSet(XbrlConst.euGroupTable)
56
188
  modelTables = []
57
- tblCssExtras='''
58
- body {background-image:url('http://arelle.org/files/EBA/style20121210/lhsbackground.jpg')}
59
- table {background:#fff}
60
- '''
61
- # order number is missing
62
- def viewTable(modelTable):
189
+
190
+ def viewTable(modelTable: DefnMdlTable) -> None:
63
191
  if modelTable is None:
64
192
  return
65
- if isinstance(modelTable, (DefnMdlTable)):
66
- # status
67
- dts.modelManager.cntlr.addToLog("viewing: " + modelTable.id)
68
- # for table file name, use table ELR
69
- tblFile = os.path.join(os.path.dirname(indexFile), modelTable.id + ".html")
70
- tableName = modelTable.id
193
+ tableId = modelTable.id or ""
194
+ if isinstance(modelTable, DefnMdlTable):
195
+ dts.modelManager.cntlr.addToLog("viewing: " + tableId)
196
+ tblFile = os.path.join(os.path.dirname(indexFile), tableId + ".html")
197
+ tableName = tableId
71
198
  if tableName.startswith("eba_t"):
72
199
  tableName = tableName.removeprefix("eba_t")
73
- if tableName.startswith("srb_t"):
200
+ elif tableName.startswith("srb_t"):
74
201
  tableName = tableName.removeprefix("srb_t")
75
- viewRenderedGrid(dts,
76
- tblFile,
77
- lang=lang,
78
- cssExtras=tblCssExtras,
79
- table=tableName)
80
-
81
- # generaate menu entry
82
- elt = etree.SubElement(listElt, "{http://www.w3.org/1999/xhtml}li")
83
- elt.set("class", "CMSListMenuLI")
84
- elt.set("id", modelTable.id)
85
- elt = etree.SubElement(elt, "{http://www.w3.org/1999/xhtml}a")
202
+ viewRenderedGrid(dts, tblFile, lang=lang, cssExtras=TABLE_CSS_EXTRAS, table=tableName) # type: ignore[no-untyped-call]
203
+
204
+ elt = etree.SubElement(listElt, "li")
205
+ elt.set("class", "nav-list-menu-li")
206
+ elt.set("id", tableId)
207
+ elt = etree.SubElement(elt, "button")
86
208
  elt.text = modelTable.genLabel(lang=lang, strip=True)
87
- elt.set("class", "CMSListMenuLink")
88
- elt.set("href", "javascript:void(0)")
89
- elt.set("onClick", "javascript:parent.body.location.href='{0}';".format(modelTable.id + ".html"))
209
+ elt.set("class", "nav-list-menu-link")
210
+ elt.set("onClick", f"javascript:parent.loadContent('{tableId}.html');")
90
211
  elt.text = modelTable.genLabel(lang=lang, strip=True)
91
-
92
- else: # just a header
93
- # generaate menu entry
94
- elt = etree.SubElement(listElt, "{http://www.w3.org/1999/xhtml}li")
95
- elt.set("class", "CMSListMenuLink")
96
- elt.set("id", modelTable.id)
212
+ else:
213
+ elt = etree.SubElement(listElt, "li")
214
+ elt.set("id", tableId)
97
215
  elt.text = modelTable.label(lang=lang, strip=True)
98
216
 
99
217
  for rel in groupTableRels.fromModelObject(modelTable):
100
218
  viewTable(rel.toModelObject)
101
219
 
102
-
103
220
  for rootConcept in groupTableRels.rootConcepts:
104
221
  sourceline = 0
105
222
  for rel in dts.modelXbrl.relationshipSet(XbrlConst.euGroupTable).fromModelObject(rootConcept):
@@ -107,171 +224,129 @@ table {background:#fff}
107
224
  break
108
225
  modelTables.append((rootConcept, sourceline))
109
226
 
110
- for modelTable, order in sorted(modelTables, key=lambda x: x[1]):
227
+ for modelTable, _order in sorted(modelTables, key=itemgetter(1)):
111
228
  viewTable(modelTable)
112
229
 
113
- with open(indexBase + "FormsFrame.html", "wt", encoding="utf-8") as fh:
114
- XmlUtil.writexml(fh, indexDocument, encoding="utf-8")
230
+ with open(indexBase + "FormsFrame.html", "w", encoding="utf-8") as fh:
231
+ XmlUtil.writexml(fh, menuFrameDocument, encoding="utf-8")
115
232
 
116
- with open(indexFile, "wt", encoding="utf-8") as fh:
117
- fh.write(
118
- '''
119
- <html xmlns="http://www.w3.org/1999/xhtml">
120
- <head id="Head1">
121
- <title>European Banking Authority - EBA - FINREP Taxonomy</title>
122
- <meta name="generator" content="Arelle(r) {0}" />
123
- <meta name="provider" content="Aguilonius(r)" />
124
- <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
125
- <meta http-equiv="pragma" content="no-cache" />
126
- <meta http-equiv="content-style-type" content="text/css" />
127
- <meta http-equiv="content-script-type" content="text/javascript" />
128
- <link type="text/css" rel="stylesheet" href="http://arelle.org/files/EBA/style20121210/eba.css" />
129
- </head>
130
- <frameset border="0" frameborder="0" rows="90,*">
131
- <frame name="head" src="{1}" scrolling="no" marginwidth="0" marginheight="10"/>
132
- <frameset bordercolor="#0000cc" border="10" frameborder="no" framespacing="0" cols="360, *">
133
- <frame src="{2}" name="menu" bordercolor="#0000cc"/>
134
- <frame src="{3}" name="body" bordercolor="#0000cc"/>
135
- </frameset>
136
- </frameset>
137
- '''.format(Version.version,
138
- os.path.basename(indexBase) + "TopFrame.html",
139
- os.path.basename(indexBase) + "FormsFrame.html",
140
- os.path.basename(indexBase) + "CenterLanding.html",
141
- ))
142
-
143
- with open(indexBase + "TopFrame.html", "wt", encoding="utf-8") as fh:
144
- fh.write(
145
- '''
146
- <html xmlns="http://www.w3.org/1999/xhtml">
147
- <head id="Top">
148
- <link type="text/css" rel="stylesheet" href="http://arelle.org/files/EBA/style20121210/eba.css" />
149
- </head>
150
- <body class="LTR IE7 ENGB">
151
- <div id="topsection">
152
- <div id="topsectionLeft" style="cursor:pointer;" onclick="location.href='http://www.eba.europa.eu/home.aspx';"></div>
153
- <div id="topsectionRight"></div>
154
- <div id="topnavigation">
155
- <ul id="menuElem">
156
- <li><a href="http://www.eba.europa.eu/topnav/Contacts.aspx">Contacts</a></li>
157
- <li><a href="http://www.eba.europa.eu/topnav/Links.aspx">Links</a></li>
158
- <li><a href="http://www.eba.europa.eu/topnav/Sitemap.aspx">Sitemap</a></li>
159
- <li><a href="http://www.eba.europa.eu/topnav/Legal-Notice.aspx">Legal Notice</a></li>
160
- </ul>
161
- </div>
162
- </body>
163
- </html>
164
- ''')
165
-
166
- with open(indexBase + "CenterLanding.html", "wt", encoding="utf-8") as fh:
167
- fh.write(
168
- '''
169
- <html xmlns="http://www.w3.org/1999/xhtml">
170
- <head id="Center">
171
- <link type="text/css" rel="stylesheet" href="http://http://arelle.org/files/EBA/style20121210/eba.css" />
172
- </head>
173
- <body class="LTR IE7 ENGB">
174
- <div id="plc_lt_zoneContent_usercontrol_userControlElem_ContentPanel">
175
- <div id="plc_lt_zoneContent_usercontrol_userControlElem_PanelTitle">
176
- <div id="pagetitle" style="float:left;width:500px;">
177
- <h1>Taxonomy Tables Viewer</h1>
178
- </div>
179
- </div>
180
- </div>
181
- <div style="clear:both;"></div>
182
- <div id="contentcenter">
183
- <p style="text-align: justify; margin-top: 0pt; margin-bottom: 0pt">Please select tables to view by clicking in the left column.</p>
184
- </div>
185
- </body>
186
- </html>
187
- ''')
233
+ with open(indexFile, "w", encoding="utf-8") as fh:
234
+ fh.write(indexFileHTML(os.path.basename(indexBase)))
188
235
 
189
- # to merge gif's and style sheets, use a zipfile sibling of the python plug-in file.
190
- #import zipfile
191
- #zf = zipfile.ZipFile(__file__.rpartition('.')[0] + "Files.zip", mode="r")
192
- #zf.extractall(path=os.path.dirname(indexBase))
193
- #zf.close()
236
+ with open(indexBase + "CenterLanding.html", "w", encoding="utf-8") as fh:
237
+ fh.write(CENTER_LANDING_HTML)
194
238
 
195
- dts.info("info:saveEBAtables",
196
- _("Tables index file of %(entryFile)s has %(numberTableFiles)s table files with index file %(indexFile)s."),
197
- modelObject=dts,
198
- entryFile=dts.uri, numberTableFiles=numTableFiles, indexFile=indexFile)
239
+ dts.info(
240
+ "info:saveEBAtables",
241
+ _("Tables index file of %(entryFile)s has %(numberTableFiles)s table files with index file %(indexFile)s."),
242
+ modelObject=dts,
243
+ entryFile=dts.uri,
244
+ numberTableFiles=numTableFiles,
245
+ indexFile=indexFile,
246
+ )
199
247
 
200
248
  dts.modelManager.showStatus(_("Saved EBA HTML Table Files"), 5000)
201
249
  except Exception as ex:
202
- dts.error("exception",
203
- _("HTML EBA Tableset files generation exception: %(error)s"), error=ex,
250
+ dts.error(
251
+ "exception",
252
+ _("HTML EBA Tableset files generation exception: %(error)s"),
253
+ error=ex,
204
254
  modelXbrl=dts,
205
- exc_info=True)
255
+ exc_info=True,
256
+ )
206
257
 
207
- def saveHtmlEbaTablesMenuEntender(cntlr, menu, *args, **kwargs):
208
- # Extend menu with an item for the save infoset plugin
209
- menu.add_command(label="Save HTML EBA Tables",
210
- underline=0,
211
- command=lambda: saveHtmlEbaTablesMenuCommand(cntlr) )
212
258
 
213
- def saveHtmlEbaTablesMenuCommand(cntlr):
214
- # save Infoset menu item has been invoked
215
- from arelle.ModelDocument import Type
259
+ def saveHtmlEbaTablesMenuCommand(cntlr: CntlrWinMain) -> None:
216
260
  if cntlr.modelManager is None or cntlr.modelManager.modelXbrl is None:
217
- cntlr.addToLog("No DTS loaded.")
261
+ cntlr.addToLog("No DTS loaded.") # type: ignore[no-untyped-call]
218
262
  return
219
263
 
220
- # get file name into which to save log file while in foreground thread
221
- indexFile = cntlr.uiFileDialog("save",
222
- title=_("arelle - Save HTML EBA Tables Index file"),
223
- initialdir=cntlr.config.setdefault("htmlEbaTablesFileDir","."),
224
- filetypes=[(_("HTML index file .html"), "*.html")],
225
- defaultextension=".html")
226
- if not indexFile:
227
- return False
228
- import os
264
+ assert cntlr.config is not None
265
+ indexFile = cntlr.uiFileDialog( # type: ignore[no-untyped-call]
266
+ "save",
267
+ title=_("arelle - Save HTML EBA Tables Index file"),
268
+ initialdir=cntlr.config.setdefault("htmlEbaTablesFileDir", "."),
269
+ filetypes=[(_("HTML index file .html"), "*.html")],
270
+ defaultextension=".html",
271
+ )
272
+ if not isinstance(indexFile, str):
273
+ return
229
274
  cntlr.config["htmlEbaTablesFileDir"] = os.path.dirname(indexFile)
230
275
  cntlr.saveConfig()
231
276
 
232
- import threading
233
- thread = threading.Thread(target=lambda
234
- _dts=cntlr.modelManager.modelXbrl,
235
- _indexFile=indexFile:
236
- generateHtmlEbaTablesetFiles(_dts, _indexFile))
277
+ thread = threading.Thread(
278
+ target=lambda _dts=cntlr.modelManager.modelXbrl, _indexFile=indexFile: generateHtmlEbaTablesetFiles(
279
+ _dts, _indexFile
280
+ )
281
+ )
237
282
  thread.daemon = True
238
283
  thread.start()
239
284
 
240
- def saveHtmlEbaTablesCommandLineOptionExtender(parser, *args, **kwargs):
241
- # extend command line options with a save DTS option
242
- parser.add_option("--save-EBA-tablesets",
243
- action="store",
244
- dest="ebaTablesetIndexFile",
245
- help=_("Save HTML EBA Tablesets index file, with tablest HTML files to out directory specify 'generateOutFiles'."))
246
-
247
- def saveHtmlEbaTablesCommandLineXbrlLoaded(cntlr, options, modelXbrl, *args, **kwargs):
248
- # extend XBRL-loaded run processing for this option
249
- from arelle.ModelDocument import Type
250
- if getattr(options, "ebaTablesetIndexFile", None) and options.ebaTablesetIndexFile == "generateEBAFiles" and modelXbrl.modelDocument.type in (Type.TESTCASESINDEX, Type.TESTCASE):
251
- cntlr.modelManager.generateEBAFiles = True
252
-
253
- def saveHtmlEbaTablesCommandLineXbrlRun(cntlr, options, modelXbrl, *args, **kwargs):
254
- # extend XBRL-loaded run processing for this option
255
- if getattr(options, "ebaTablesetIndexFile", None) and options.ebaTablesetIndexFile != "generateEBAFiles":
285
+
286
+ class SaveHtmlEbaTablesPlugin(PluginHooks):
287
+ @staticmethod
288
+ def cntlrWinMainMenuTools(
289
+ cntlr: CntlrWinMain,
290
+ menu: Menu,
291
+ *args: Any,
292
+ **kwargs: Any,
293
+ ) -> None:
294
+ menu.add_command(label="Save HTML EBA Tables", underline=0, command=lambda: saveHtmlEbaTablesMenuCommand(cntlr))
295
+
296
+ @staticmethod
297
+ def cntlrCmdLineOptions(
298
+ parser: OptionParser,
299
+ *args: Any,
300
+ **kwargs: Any,
301
+ ) -> None:
302
+ parser.add_option(
303
+ "--save-EBA-tablesets",
304
+ action="store",
305
+ dest="ebaTablesetIndexFile",
306
+ help=_("Save HTML EBA Tablesets index file with provided filename."),
307
+ )
308
+
309
+ @staticmethod
310
+ def cntlrCmdLineXbrlLoaded(
311
+ cntlr: CntlrCmdLine,
312
+ options: RuntimeOptions,
313
+ modelXbrl: ModelXbrl,
314
+ *args: Any,
315
+ **kwargs: Any,
316
+ ) -> None:
317
+ ebaTablesetIndexFile = getattr(options, "ebaTablesetIndexFile", None)
318
+ modelDocType = getattr(modelXbrl.modelDocument, "type", None)
319
+ if ebaTablesetIndexFile == "generateEBAFiles" and modelDocType in (Type.TESTCASESINDEX, Type.TESTCASE):
320
+ cntlr.modelManager.generateEBAFiles = True # type: ignore[attr-defined]
321
+
322
+ @staticmethod
323
+ def cntlrCmdLineXbrlRun(
324
+ cntlr: CntlrCmdLine,
325
+ options: RuntimeOptions,
326
+ modelXbrl: ModelXbrl,
327
+ *args: Any,
328
+ **kwargs: Any,
329
+ ) -> None:
330
+ ebaTablesetIndexFile = getattr(options, "ebaTablesetIndexFile", None)
331
+ if ebaTablesetIndexFile is None or ebaTablesetIndexFile == "generateEBAFiles":
332
+ return
256
333
  if cntlr.modelManager is None or cntlr.modelManager.modelXbrl is None:
257
334
  cntlr.addToLog("No taxonomy loaded.")
258
335
  return
259
-
260
- from arelle import RenderingEvaluator
261
- RenderingEvaluator.init(modelXbrl)
262
- generateHtmlEbaTablesetFiles(cntlr.modelManager.modelXbrl, options.ebaTablesetIndexFile)
336
+ RenderingEvaluator.init(modelXbrl) # type: ignore[no-untyped-call]
337
+ generateHtmlEbaTablesetFiles(cntlr.modelManager.modelXbrl, ebaTablesetIndexFile)
263
338
 
264
339
 
265
340
  __pluginInfo__ = {
266
- 'name': 'Save HTML EBA Tables',
267
- 'version': '0.9',
268
- 'description': "This plug-in adds a feature to a directory containing HTML Tablesets with an EBA index page. ",
269
- 'license': 'Apache-2',
270
- 'author': authorLabel,
271
- 'copyright': copyrightLabel,
341
+ "name": "Save HTML EBA Tables",
342
+ "version": "0.10",
343
+ "description": "This plug-in adds a feature to a directory containing HTML Tablesets with an EBA index page.",
344
+ "license": "Apache-2",
345
+ "author": Version.authorLabel,
346
+ "copyright": Version.copyrightLabel,
272
347
  # classes of mount points (required)
273
- 'CntlrWinMain.Menu.Tools': saveHtmlEbaTablesMenuEntender,
274
- 'CntlrCmdLine.Options': saveHtmlEbaTablesCommandLineOptionExtender,
275
- 'CntlrCmdLine.Xbrl.Loaded': saveHtmlEbaTablesCommandLineXbrlLoaded,
276
- 'CntlrCmdLine.Xbrl.Run': saveHtmlEbaTablesCommandLineXbrlRun,
348
+ "CntlrWinMain.Menu.Tools": SaveHtmlEbaTablesPlugin.cntlrWinMainMenuTools,
349
+ "CntlrCmdLine.Options": SaveHtmlEbaTablesPlugin.cntlrCmdLineOptions,
350
+ "CntlrCmdLine.Xbrl.Loaded": SaveHtmlEbaTablesPlugin.cntlrCmdLineXbrlLoaded,
351
+ "CntlrCmdLine.Xbrl.Run": SaveHtmlEbaTablesPlugin.cntlrCmdLineXbrlRun,
277
352
  }
@@ -168,8 +168,8 @@ def checkFilingDTS(val: ValidateXbrl, modelDocument: ModelDocument, esefNotesCon
168
168
  narrowerConcept = widerNarrowerRelSet.toModelObject(modelConcept)
169
169
 
170
170
  # Transform the qname to str for the later join()
171
- widerTypes = set(r.toModelObject.typeQname for r in widerConcept)
172
- narrowerTypes = set(r.fromModelObject.typeQname for r in narrowerConcept)
171
+ widerTypes = set(r.toModelObject.typeQname for r in widerConcept if r.toModelObject is not None)
172
+ narrowerTypes = set(r.fromModelObject.typeQname for r in narrowerConcept if r.fromModelObject is not None)
173
173
 
174
174
  if (narrowerTypes and narrowerTypes != {modelConcept.typeQname}) or (widerTypes and widerTypes != {modelConcept.typeQname}):
175
175
  widerNarrowerType = "{} {}".format(
@@ -94,6 +94,33 @@ class PluginHooks(ABC):
94
94
  """
95
95
  raise NotImplementedError
96
96
 
97
+ @staticmethod
98
+ def cntlrCmdLineXbrlLoaded(
99
+ cntlr: CntlrCmdLine,
100
+ options: RuntimeOptions,
101
+ modelXbrl: ModelXbrl,
102
+ entrypoint: dict[str, str] | None = None,
103
+ responseZipStream: BinaryIO | None = None,
104
+ *args: Any,
105
+ **kwargs: Any,
106
+ ) -> None:
107
+ """
108
+ Plugin hook: `CntlrCmdLine.Xbrl.Loaded`
109
+
110
+ This hook is triggered after loading, but prior to validation (if requested) and loading views.
111
+ It's useful if you need to perform operations with the XBRL model prior to rendering views.
112
+
113
+ :param cntlr: The [Cntlr](#arelle.Cntlr.Cntlr) being initialized.
114
+ :param options: Parsed options object.
115
+ :param modelXbrl: The loaded [ModelXbrl](#arelle.ModelXbrl.ModelXbrl).
116
+ :param entrypoint: The entrypoint that was parsed to load the model.
117
+ :param responseZipStream: The response zip stream if loaded from the webserver and the user requested a zip response.
118
+ :param args: Argument capture to ensure new parameters don't break plugin hook.
119
+ :param kwargs: Argument capture to ensure new named parameters don't break plugin hook.
120
+ :return: None
121
+ """
122
+ raise NotImplementedError
123
+
97
124
  @staticmethod
98
125
  def cntlrCmdLineXbrlRun(
99
126
  cntlr: CntlrCmdLine,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: arelle-release
3
- Version: 2.36.26
3
+ Version: 2.36.28
4
4
  Summary: An open source XBRL platform.
5
5
  Author-email: "arelle.org" <support@arelle.org>
6
6
  License: Apache-2.0