This repository has been archived by the owner on Sep 20, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 58
/
RefManager.py
74 lines (67 loc) · 3.6 KB
/
RefManager.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# -*- coding: utf-8 -*-
"""
:mod:`EdgarRenderer.RefManager`
~~~~~~~~~~~~~~~~~~~
Edgar(tm) Renderer was created by staff of the U.S. Securities and Exchange Commission.
Data and content created by government employees within the scope of their employment
are not subject to domestic copyright protection. 17 U.S.C. 105.
"""
import os.path, lxml, time
import regex as re
import arelle.ModelDocument
from arelle.FileSource import openFileSource
taxonomyManagerFile = 'TaxonomyAddonManager.xml'
"""
The Add on manager is a hold over from RE2. The purpose is to load standard taxonomy doc and ref
files without requiring them to be in the DTS during validation. There is a configuration file that
maps schema file names to all associated documentation and reference file names. After a document
is loaded, then each schema in the dts is checked to see whether its associated doc and/or ref files
(there could be zero, one, or more of each) need to be loaded.
"""
class RefManager(object):
def __init__(self,resources):
managerPath = os.path.join(resources,taxonomyManagerFile)
self.tree = lxml.etree.parse(managerPath)
# method getUrls on CntlrAddOnManager
# returns: set of strings representing additional linkbases to be loaded.
# return the set of URLs that must be loaded due to the presence of schemas in the DTS.
def getUrls(self,modelXbrl):
urls = set()
from urllib.parse import urlparse,urljoin
namespacesInFacts = {f.qname.namespaceURI for f in modelXbrl.facts if f.qname is not None}
for fileUri,doc in modelXbrl.urlDocs.items():
if doc.targetNamespace in namespacesInFacts:
parsedUri = urlparse(fileUri)
fileBasename = os.path.basename(parsedUri.path)
if re.compile(r'.*\.xsd$').match(fileBasename): # Assume we only care about urls ending in .xsd
xp = "/TaxonomyAddonManager/TaxonomyList/TaxonomyAddon[Taxonomy[.='" + fileBasename + "']]/*/string"
moreUrls = self.tree.xpath(xp)
for u in moreUrls:
urls.add(urljoin(fileUri,u.text))
return urls
def loadAddedUrls(self,modelXbrl,controller):
validateDisclosureSystem = modelXbrl.modelManager.validateDisclosureSystem
loadedAdditionalUrls = False
_startedAt = time.time()
_numUrls = 0
try:
modelXbrl.modelManager.validateDisclosureSystem = False
for url in self.getUrls(modelXbrl):
doc = None
try: # isSupplemental is needed here to force the parsing of linkbase.
doc = arelle.ModelDocument.load(modelXbrl,url,isSupplemental=True)
loadedAdditionalUrls = True
except (arelle.ModelDocument.LoadingException):
pass
if doc is None:
#message = ErrorMgr.getError('UNABLE_TO_LOAD_ADDON_LINKBASE')
modelXbrl.info("info:unableToAddOnLinkbase",
_("Unable to load add-on linkbase %(linkbase)s."),
modelObject=modelXbrl.modelDocument, linkbase=url)
_numUrls += 1
finally:
modelXbrl.modelManager.validateDisclosureSystem = validateDisclosureSystem
if loadedAdditionalUrls:
modelXbrl.relationshipSets.clear() # relationships have to be re-cached
controller.logDebug("{} add on linkbases loaded {:.3f} secs.".format(_numUrls, time.time() - _startedAt))
return