ixbrl-viewer 1.4.9__py3-none-any.whl → 1.4.11__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 ixbrl-viewer might be problematic. Click here for more details.
- iXBRLViewerPlugin/_version.py +2 -2
- iXBRLViewerPlugin/iXBRLViewer.py +47 -52
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js +1 -1
- iXBRLViewerPlugin/viewer/src/html/inspector.html +2 -2
- iXBRLViewerPlugin/viewer/src/i18n/en/translation.json +1 -1
- iXBRLViewerPlugin/viewer/src/i18n/es/translation.json +1 -1
- iXBRLViewerPlugin/viewer/src/js/aspect.js +1 -1
- iXBRLViewerPlugin/viewer/src/js/aspect.test.js +2 -1
- iXBRLViewerPlugin/viewer/src/js/chart.js +1 -1
- iXBRLViewerPlugin/viewer/src/js/chart.test.js +2 -2
- iXBRLViewerPlugin/viewer/src/js/concept.test.js +2 -2
- iXBRLViewerPlugin/viewer/src/js/fact.js +11 -24
- iXBRLViewerPlugin/viewer/src/js/fact.test.js +6 -11
- iXBRLViewerPlugin/viewer/src/js/factset.test.js +2 -4
- iXBRLViewerPlugin/viewer/src/js/inspector.js +3 -3
- iXBRLViewerPlugin/viewer/src/js/inspector.test.js +2 -3
- iXBRLViewerPlugin/viewer/src/js/outline.test.js +3 -3
- iXBRLViewerPlugin/viewer/src/js/report.js +7 -3
- iXBRLViewerPlugin/viewer/src/js/report.test.js +2 -1
- iXBRLViewerPlugin/viewer/src/js/reportset.test.js +3 -3
- iXBRLViewerPlugin/viewer/src/js/unit.js +15 -33
- iXBRLViewerPlugin/viewer/src/js/unit.test.js +17 -24
- iXBRLViewerPlugin/viewer/src/js/util.js +21 -0
- iXBRLViewerPlugin/viewer/src/js/viewer.js +58 -53
- {ixbrl_viewer-1.4.9.dist-info → ixbrl_viewer-1.4.11.dist-info}/METADATA +8 -4
- {ixbrl_viewer-1.4.9.dist-info → ixbrl_viewer-1.4.11.dist-info}/RECORD +32 -32
- tests/unit_tests/iXBRLViewerPlugin/test_iXBRLViewer.py +17 -12
- {ixbrl_viewer-1.4.9.dist-info → ixbrl_viewer-1.4.11.dist-info}/LICENSE +0 -0
- {ixbrl_viewer-1.4.9.dist-info → ixbrl_viewer-1.4.11.dist-info}/NOTICE +0 -0
- {ixbrl_viewer-1.4.9.dist-info → ixbrl_viewer-1.4.11.dist-info}/WHEEL +0 -0
- {ixbrl_viewer-1.4.9.dist-info → ixbrl_viewer-1.4.11.dist-info}/entry_points.txt +0 -0
- {ixbrl_viewer-1.4.9.dist-info → ixbrl_viewer-1.4.11.dist-info}/top_level.txt +0 -0
iXBRLViewerPlugin/_version.py
CHANGED
iXBRLViewerPlugin/iXBRLViewer.py
CHANGED
|
@@ -95,6 +95,7 @@ class IXBRLViewerBuilder:
|
|
|
95
95
|
"languages": {},
|
|
96
96
|
}
|
|
97
97
|
self.basenameSuffix = basenameSuffix
|
|
98
|
+
self.currentTargetReport = None
|
|
98
99
|
|
|
99
100
|
def enableFeature(self, featureName: str):
|
|
100
101
|
if featureName in self.taxonomyData["features"]:
|
|
@@ -148,21 +149,13 @@ class IXBRLViewerBuilder:
|
|
|
148
149
|
if langCode not in self.taxonomyData["languages"]:
|
|
149
150
|
self.taxonomyData["languages"][langCode] = self.makeLanguageName(langCode)
|
|
150
151
|
|
|
151
|
-
@property
|
|
152
|
-
def currentSourceReportData(self):
|
|
153
|
-
return self.taxonomyData["sourceReports"][-1]
|
|
154
|
-
|
|
155
|
-
@property
|
|
156
|
-
def currentReportData(self):
|
|
157
|
-
return self.currentSourceReportData["targetReports"][-1]
|
|
158
|
-
|
|
159
152
|
def addELR(self, report: ModelXbrl, elr):
|
|
160
153
|
prefix = self.roleMap.getPrefix(elr)
|
|
161
|
-
if self.
|
|
154
|
+
if self.currentTargetReport.setdefault("roleDefs",{}).get(prefix, None) is None:
|
|
162
155
|
rts = report.roleTypes.get(elr, [])
|
|
163
156
|
label = next((rt.definition for rt in rts if rt.definition is not None), None)
|
|
164
157
|
if label is not None:
|
|
165
|
-
self.
|
|
158
|
+
self.currentTargetReport["roleDefs"].setdefault(prefix,{})["en"] = label
|
|
166
159
|
|
|
167
160
|
def addConcept(self, report: ModelXbrl, concept, dimensionType = None):
|
|
168
161
|
if concept is None:
|
|
@@ -170,7 +163,7 @@ class IXBRLViewerBuilder:
|
|
|
170
163
|
labelsRelationshipSet = report.relationshipSet(XbrlConst.conceptLabel)
|
|
171
164
|
labels = labelsRelationshipSet.fromModelObject(concept)
|
|
172
165
|
conceptName = self.nsmap.qname(concept.qname)
|
|
173
|
-
if conceptName not in self.
|
|
166
|
+
if conceptName not in self.currentTargetReport["concepts"]:
|
|
174
167
|
conceptData = {
|
|
175
168
|
"labels": { }
|
|
176
169
|
}
|
|
@@ -205,7 +198,7 @@ class IXBRLViewerBuilder:
|
|
|
205
198
|
conceptData['td'] = typedDomainName
|
|
206
199
|
self.addConcept(report, typedDomainElement)
|
|
207
200
|
|
|
208
|
-
self.
|
|
201
|
+
self.currentTargetReport["concepts"][conceptName] = conceptData
|
|
209
202
|
|
|
210
203
|
def treeWalk(self, rels, item, indent = 0):
|
|
211
204
|
for r in rels.fromModelObject(item):
|
|
@@ -324,7 +317,7 @@ class IXBRLViewerBuilder:
|
|
|
324
317
|
if frel.toModelObject is not None:
|
|
325
318
|
factData.setdefault("fn", []).append(frel.toModelObject.id)
|
|
326
319
|
|
|
327
|
-
self.
|
|
320
|
+
self.currentTargetReport["facts"][f.id] = factData
|
|
328
321
|
self.addConcept(report, f.concept)
|
|
329
322
|
|
|
330
323
|
def oimUnitString(self, unit):
|
|
@@ -348,10 +341,11 @@ class IXBRLViewerBuilder:
|
|
|
348
341
|
return "{}/{}".format(numeratorsString, denominatorsString)
|
|
349
342
|
return numeratorsString
|
|
350
343
|
|
|
351
|
-
def
|
|
344
|
+
def addViewerData(self, viewerFile, scriptUrl):
|
|
345
|
+
viewerFile.xmlDocument = deepcopy(viewerFile.xmlDocument)
|
|
352
346
|
taxonomyDataJSON = self.escapeJSONForScriptTag(json.dumps(self.taxonomyData, indent=1, allow_nan=False))
|
|
353
347
|
|
|
354
|
-
for child in xmlDocument.getroot():
|
|
348
|
+
for child in viewerFile.xmlDocument.getroot():
|
|
355
349
|
if child.tag == '{http://www.w3.org/1999/xhtml}body':
|
|
356
350
|
for body_child in child:
|
|
357
351
|
if body_child.tag == '{http://www.w3.org/1999/xhtml}script' and body_child.get('type','') == 'application/x.ixbrl-viewer+json':
|
|
@@ -383,15 +377,18 @@ class IXBRLViewerBuilder:
|
|
|
383
377
|
with open(os.path.join(os.path.dirname(__file__),"stubviewer.html")) as fin:
|
|
384
378
|
return etree.parse(fin)
|
|
385
379
|
|
|
386
|
-
def
|
|
387
|
-
|
|
388
|
-
"
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
380
|
+
def newTargetReport(self):
|
|
381
|
+
return {
|
|
382
|
+
"concepts": {},
|
|
383
|
+
"facts": {},
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
def addSourceReport(self):
|
|
387
|
+
sourceReport = {
|
|
388
|
+
"targetReports": []
|
|
389
|
+
}
|
|
390
|
+
self.taxonomyData["sourceReports"].append(sourceReport)
|
|
391
|
+
return sourceReport
|
|
395
392
|
|
|
396
393
|
def createViewer(self, scriptUrl: str = DEFAULT_VIEWER_PATH, useStubViewer: bool = False, showValidations: bool = True, packageDownloadURL: str = None) -> Optional[iXBRLViewer]:
|
|
397
394
|
"""
|
|
@@ -411,59 +408,56 @@ class IXBRLViewerBuilder:
|
|
|
411
408
|
self.roleMap.getPrefix(XbrlConst.dimensionDefault, "d-d")
|
|
412
409
|
self.roleMap.getPrefix(WIDER_NARROWER_ARCROLE, "w-n")
|
|
413
410
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
411
|
+
sourceReportsByFiles = dict()
|
|
412
|
+
|
|
413
|
+
if useStubViewer:
|
|
414
|
+
iv.addFile(iXBRLViewerFile(DEFAULT_OUTPUT_NAME, self.getStubDocument()))
|
|
417
415
|
|
|
418
416
|
for n, report in enumerate(self.reports):
|
|
419
417
|
self.footnoteRelationshipSet = ModelRelationshipSet(report, "XBRL-footnotes")
|
|
420
|
-
self.
|
|
418
|
+
self.currentTargetReport = self.newTargetReport()
|
|
421
419
|
for f in report.facts:
|
|
422
420
|
self.addFact(report, f)
|
|
423
|
-
self.
|
|
421
|
+
self.currentTargetReport["rels"] = self.getRelationships(report)
|
|
424
422
|
|
|
425
423
|
docSetFiles = None
|
|
426
424
|
report.info("viewer:info", "Creating iXBRL viewer (%d of %d)" % (n+1, len(self.reports)))
|
|
427
425
|
if report.modelDocument.type == Type.INLINEXBRLDOCUMENTSET:
|
|
428
426
|
# Sort by object index to preserve order in which files were specified.
|
|
429
427
|
xmlDocsByFilename = {
|
|
430
|
-
os.path.basename(self.outputFilename(doc.filepath)):
|
|
428
|
+
os.path.basename(self.outputFilename(doc.filepath)): doc.xmlDocument
|
|
431
429
|
for doc in sorted(report.modelDocument.referencesDocument.keys(), key=lambda x: x.objectIndex)
|
|
432
430
|
if doc.type == Type.INLINEXBRL
|
|
433
431
|
}
|
|
434
432
|
docSetFiles = list(xmlDocsByFilename.keys())
|
|
435
433
|
|
|
436
|
-
if xmlDocument is None:
|
|
437
|
-
if useStubViewer:
|
|
438
|
-
xmlDocument = self.getStubDocument()
|
|
439
|
-
iv.addFile(iXBRLViewerFile(DEFAULT_OUTPUT_NAME, xmlDocument))
|
|
440
|
-
else:
|
|
441
|
-
xmlDocument = next(iter(xmlDocsByFilename.values()))
|
|
442
|
-
|
|
443
434
|
for filename, docSetXMLDoc in xmlDocsByFilename.items():
|
|
444
435
|
iv.addFile(iXBRLViewerFile(filename, docSetXMLDoc))
|
|
445
436
|
|
|
446
437
|
elif useStubViewer:
|
|
447
|
-
if xmlDocument is None:
|
|
448
|
-
xmlDocument = self.getStubDocument()
|
|
449
|
-
iv.addFile(iXBRLViewerFile(DEFAULT_OUTPUT_NAME, xmlDocument))
|
|
450
438
|
filename = self.outputFilename(os.path.basename(report.modelDocument.filepath))
|
|
451
439
|
docSetFiles = [ filename ]
|
|
452
440
|
iv.addFile(iXBRLViewerFile(filename, report.modelDocument.xmlDocument))
|
|
453
441
|
|
|
454
442
|
else:
|
|
443
|
+
srcFilename = self.outputFilename(os.path.basename(report.modelDocument.filepath))
|
|
444
|
+
docSetFiles = [ srcFilename ]
|
|
455
445
|
if len(self.reports) == 1:
|
|
456
446
|
# If there is only a single report, call the output file "xbrlviewer.html"
|
|
457
447
|
filename = "xbrlviewer.html"
|
|
458
448
|
else:
|
|
459
449
|
# Otherwise, preserve filenames
|
|
460
|
-
filename =
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
450
|
+
filename = srcFilename
|
|
451
|
+
iv.addFile(iXBRLViewerFile(filename, report.modelDocument.xmlDocument))
|
|
452
|
+
|
|
453
|
+
docSetKey = frozenset(docSetFiles)
|
|
454
|
+
sourceReport = sourceReportsByFiles.get(docSetKey)
|
|
455
|
+
if sourceReport is None:
|
|
456
|
+
sourceReport = self.addSourceReport()
|
|
457
|
+
sourceReportsByFiles[docSetKey] = sourceReport
|
|
458
|
+
sourceReport["docSetFiles"] = list(urllib.parse.quote(f) for f in docSetFiles)
|
|
459
|
+
|
|
460
|
+
sourceReport["targetReports"].append(self.currentTargetReport)
|
|
467
461
|
|
|
468
462
|
localDocs = defaultdict(set)
|
|
469
463
|
for path, doc in report.urlDocs.items():
|
|
@@ -482,14 +476,11 @@ class IXBRLViewerBuilder:
|
|
|
482
476
|
linkbaseIdentifed = True
|
|
483
477
|
if not linkbaseIdentifed:
|
|
484
478
|
localDocs[doc.basename].add(UNRECOGNIZED_LINKBASE_LOCAL_DOCUMENTS_TYPE)
|
|
485
|
-
self.
|
|
479
|
+
self.currentTargetReport["localDocs"] = {
|
|
486
480
|
localDoc: sorted(docTypes)
|
|
487
481
|
for localDoc, docTypes in localDocs.items()
|
|
488
482
|
}
|
|
489
483
|
|
|
490
|
-
if docSetFiles is not None:
|
|
491
|
-
self.currentSourceReportData["docSetFiles"] = list(urllib.parse.quote(f) for f in docSetFiles)
|
|
492
|
-
|
|
493
484
|
self.taxonomyData["prefixes"] = self.nsmap.prefixmap
|
|
494
485
|
self.taxonomyData["roles"] = self.roleMap.prefixmap
|
|
495
486
|
|
|
@@ -504,7 +495,7 @@ class IXBRLViewerBuilder:
|
|
|
504
495
|
iv.addFilingDoc(filingDocZipPath)
|
|
505
496
|
self.taxonomyData["filingDocuments"] = filingDocZipName
|
|
506
497
|
|
|
507
|
-
if not self.
|
|
498
|
+
if not self.addViewerData(iv.files[0], scriptUrl):
|
|
508
499
|
return None
|
|
509
500
|
|
|
510
501
|
return iv
|
|
@@ -524,9 +515,13 @@ class iXBRLViewer:
|
|
|
524
515
|
self.filingDocuments = None
|
|
525
516
|
# This is an arbitrary ModelXbrl used for logging only
|
|
526
517
|
self.logger_model = logger_model
|
|
518
|
+
self.filenames = set()
|
|
527
519
|
|
|
528
520
|
def addFile(self, ivf):
|
|
521
|
+
if ivf.filename in self.filenames:
|
|
522
|
+
return
|
|
529
523
|
self.files.append(ivf)
|
|
524
|
+
self.filenames.add(ivf.filename)
|
|
530
525
|
|
|
531
526
|
def addFilingDoc(self, filingDocuments):
|
|
532
527
|
self.filingDocuments = filingDocuments
|