def my_fn_PDxEV(xc, p, contextItem, args): if len(args) != 2: raise XPathContext.FunctionNumArgs() PDseq = flattenSequence(args[0]) EVseq = flattenSequence(args[1]) dimQname = qname("{http://www.example.com/wgt-avg}ExposuresDimension") PDxEV = [] for pd in PDseq: if pd.context is not None: pdDim = pd.context.dimValue(dimQname) for ev in EVseq: if ev.context is not None: evDim = ev.context.dimValue(dimQname) if pdDim is not None and isinstance(pdDim,ModelDimensionValue): dimEqual = pdDim.isEqualTo(evDim, equalMode=XbrlUtil.S_EQUAL2) elif evDim is not None and isinstance(evDim,ModelDimensionValue): dimEqual = evDim.isEqualTo(pdDim, equalMode=XbrlUtil.S_EQUAL2) else: dimEqual = (pdDim == evDim) if dimEqual: pdX = pd.xValue evX = ev.xValue # type promotion required if isinstance(pdX,Decimal) and isinstance(evX,float): pdX = float(pdX) elif isinstance(evX,Decimal) and isinstance(pdX,float): pdX = float(evX) PDxEV.append(pdX * evX) break return PDxEV
def loadTaxonomyCompatibility(modelXbrl): _file = openFileStream(modelXbrl.modelManager.cntlr, resourcesFilePath(modelXbrl.modelManager, "taxonomy-compatibility.json"), 'rt', encoding='utf-8') compat = json.load(_file, object_pairs_hook=OrderedDict) # preserve order of keys _file.close() tc = compat["taxonomy-classes"] cc = compat["compatible-classes"] def refTx(txAbbrs): return [refTx(tc[txAbbr[1:]]) if txAbbr.startswith("@") else txAbbr for txAbbr in txAbbrs] for k in cc.keys(): cc[k] = set(flattenSequence(refTx(cc[k]))) compat["checked-taxonomies"] = set(flattenSequence([t for t in cc.items()])) return compat
def compileFormSet(forms, formSet=None, visitedClasses=None): if visitedClasses is None: visitedClasses = set() if formSet is None: formSet = set() for form in flattenSequence(forms): if form.startswith("@"): referencedClass = form[1:] if referencedClass not in fc: modelXbrl.error( "arelle:loadDeiValidations", _("Missing declaration for %(referencedClass)s."), referencedClass=form) elif form in visitedClasses: modelXbrl.error( "arelle:loadDeiValidations", _("Circular reference to %(formClass)s in %(formClasses)s." ), formClass=referencedClass, formClasses=sorted(visitedClasses)) else: visitedClasses.add(form) compileFormSet(fc[referencedClass], formSet, visitedClasses) else: formSet.add(form) return formSet
def deprecatedConceptDatesFile(modelManager, abbrNs, latestTaxonomyDoc): cntlr = modelManager.cntlr _fileName = resourcesFilePath( modelManager, abbrNs.partition("/")[0] + "-deprecated-concepts.json") _deprecatedLabelRole = latestTaxonomyDoc["deprecatedLabelRole"] _deprecatedDateMatchPattern = latestTaxonomyDoc["deprecationDatePattern"] if os.path.exists(_fileName): return _fileName # load labels and store file name modelManager.addToLog(_("loading {} deprecated concepts into {}").format( abbrNs, _fileName), messageCode="info") deprecatedConceptDates = {} from arelle import ModelXbrl for latestTaxonomyLabelFile in flattenSequence( latestTaxonomyDoc["deprecatedLabels"]): # load without SEC/EFM validation (doc file would not be acceptable) priorValidateDisclosureSystem = modelManager.validateDisclosureSystem modelManager.validateDisclosureSystem = False deprecationsInstance = ModelXbrl.load( modelManager, # "http://xbrl.fasb.org/us-gaap/2012/elts/us-gaap-doc-2012-01-31.xml", # load from zip (especially after caching) is incredibly faster openFileSource(latestTaxonomyLabelFile, cntlr), _("built deprecations table in cache")) modelManager.validateDisclosureSystem = priorValidateDisclosureSystem if deprecationsInstance is None: modelManager.addToLog(_("%(name)s documentation not loaded"), messageCode="arelle:notLoaded", messageArgs={ "modelXbrl": val, "name": _abbrNs }) else: # load deprecations for labelRel in deprecationsInstance.relationshipSet( XbrlConst.conceptLabel).modelRelationships: modelLabel = labelRel.toModelObject conceptName = labelRel.fromModelObject.name if modelLabel.role == _deprecatedLabelRole: match = _deprecatedDateMatchPattern.match(modelLabel.text) if match is not None: date = match.group(1) if date: deprecatedConceptDates[conceptName] = date jsonStr = _STR_UNICODE( json.dumps( OrderedDict( ((k, v) for k, v in sorted(deprecatedConceptDates.items()) )), # sort in json file ensure_ascii=False, indent=0)) # might not be unicode in 2.7 saveFile(cntlr, _fileName, jsonStr) # 2.7 gets unicode this way deprecationsInstance.close() del deprecationsInstance # dereference closed modelXbrl
def loadDeiValidations(modelXbrl, isInlineXbrl): _file = openFileStream(modelXbrl.modelManager.cntlr, resourcesFilePath(modelXbrl.modelManager, "dei-validations.json"), 'rt', encoding='utf-8') validations = json.load(_file) # {localName: date, ...} _file.close() #print ("original validations size {}".format(pyObjectSize(validations))) # get dei namespaceURI deiNamespaceURI = None for doc in modelXbrl.urlDocs.values(): if doc.targetNamespace and doc.targetNamespace.startswith("http://xbrl.sec.gov/dei/"): deiNamespaceURI = doc.targetNamespace break # compile form-classes fc = validations["form-classes"] def compileFormSet(forms, formSet=None, visitedClasses=None): if visitedClasses is None: visitedClasses = set() if formSet is None: formSet = set() for form in flattenSequence(forms): if form.startswith("@"): referencedClass = form[1:] if referencedClass not in fc: modelXbrl.error("arelle:loadDeiValidations", _("Missing declaration for %(referencedClass)s."), referencedClass=form) elif form in visitedClasses: modelXbrl.error("arelle:loadDeiValidations", _("Circular reference to %(formClass)s in %(formClasses)s."), formClass=referencedClass, formClasses=sorted(visitedClasses)) else: visitedClasses.add(form) compileFormSet(fc[referencedClass], formSet, visitedClasses) else: formSet.add(form) return formSet for fev in validations["form-element-validations"]: for field in ("xbrl-names", "validation", "efm", "source") : if field not in fev: modelXbrl.error("arelle:loadDeiValidations", _("Missing form-element-validation[\"%(field)s\"] from %(validation)s."), field=field, validation=fev) if "severity" in fev and not any(field.startswith("message") for field in fev): modelXbrl.error("arelle:loadDeiValidations", _("Missing form-element-validation[\"%(field)s\"] from %(validation)s."), field="message*", validation=fev) validationCode = fev.get("validation") if validationCode in ("f2", "og", "ol1", "ol2", "oph", "ar", "sr", "oth", "t", "tb", "t1") and "references" not in fev: modelXbrl.error("arelle:loadDeiValidations", _("Missing form-element-validation[\"references\"] from %(validation)s."), field=field, validation=fev) if validationCode in ("ru", "ou"): if isinstance(fev.get("value"), list): fev["value"] = set(fev["value"]) # change options list into set else: modelXbrl.error("arelle:loadDeiValidations", _("Missing form-element-validation[\"value\"] from %(validation)s, must be a list."), field=field, validation=fev) if validationCode in (): if isinstance(fev.get("reference-value"), list): fev["reference-value"] = set(fev["reference-value"]) # change options list into set else: modelXbrl.error("arelle:loadDeiValidations", _("Missing form-element-validation[\"value\"] from %(validation)s, must be a list."), field=field, validation=fev) if validationCode not in validations["validations"]: modelXbrl.error("arelle:loadDeiValidations", _("Missing validation[\"%(validationCode)s\"]."), validationCode=validationCode) axisCode = fev.get("axis") if axisCode and axisCode not in validations["axis-validations"]: modelXbrl.error("arelle:loadDeiValidations", _("Missing axis[\"%(axisCode)s\"]."), axisCode=axisCode) if "lang" in fev: fev["langPattern"] = re.compile(fev["lang"]) s = fev.get("source") if s not in ("inline", "non-inline", "both"): modelXbrl.error("arelle:loadDeiValidations", _("Invalid source [\"%(source)s\"]."), source=s) elif (isInlineXbrl and s in ("inline", "both")) or (not isInlineXbrl and s in ("non-inline", "both")): messageKey = fev.get("message") if messageKey and messageKey not in validations["messages"]: modelXbrl.error("arelle:loadDeiValidations", _("Missing message[\"%(messageKey)s\"]."), messageKey=messageKey) # only include dei names in current dei taxonomy fev["xbrl-names"] = [name for name in flattenSequence(fev.get("xbrl-names", ())) if qname(deiNamespaceURI, name) in modelXbrl.qnameConcepts] formSet = compileFormSet(fev.get("forms", (fev.get("form",()),))) if "*" in formSet: formSet = "all" # change to string for faster testing in Filing.py fev["formSet"] = formSet for axisKey, axisValidation in validations["axis-validations"].items(): messageKey = axisValidation.get("message") if messageKey and messageKey not in validations["messages"]: modelXbrl.error("arelle:loadDeiValidations", _("Missing axis \"%(axisKey)s\" message[\"%(messageKey)s\"]."), axisKey=axisKey, messageKey=messageKey) for valKey, validation in validations["validations"].items(): messageKey = validation.get("message") if messageKey and messageKey not in validations["messages"]: modelXbrl.error("arelle:loadDeiValidations", _("Missing validation \"%(valKey)s\" message[\"%(messageKey)s\"]."), valKey=valKey, messageKey=messageKey) #print ("compiled validations size {}".format(pyObjectSize(validations))) return validations
def loggingMessageParameters(messageCode, msgIn, modelObjectArgs, fmtArgs, *args, **kwargs): if messageCode and messageCode.startswith("DQC"): # change ${...} in message into %(...)s msg = altParametersPattern.sub(r"%(\1)s", msgIn) # find qnamed fact references qnamedReferences = set() paramNames = parametersPattern.findall(msg) for param in paramNames: paramParts = param.split('.') if len(paramParts) > 1 and not factNumberPattern.match( paramParts[0]): qnamedReferences.add(paramParts[0]) factsArray = [] factsByQname = defaultdict(list) # list of facts with the qname conceptsByQname = {} missingQnamedArguments = set() qnameFirstOrdinalPosition = { } # for qnamed facts multiply in sequence (to insert on 2nd occurance in ordinal position) for arg in flattenSequence(modelObjectArgs): # Pargmeter may be a ModelFact, or a name of a concept (such as a dimension) if isinstance(arg, ModelFact): _strQName = str(arg.qname) if _strQName in qnamedReferences: if _strQName not in factsByQname: # if twice in args, let one be an ordinal fact factsByQname[_strQName].append(arg) qnameFirstOrdinalPosition[_strQName] = len(factsArray) elif arg not in factsArray: # if twice in args, insert first occurence in ordinal position factsArray.insert(qnameFirstOrdinalPosition[_strQName], arg) else: factsArray.append(arg) cntx = arg.context if cntx is not None: for dim in cntx.qnameDims.values(): if str(dim.dimensionQname) in qnamedReferences: conceptsByQname[str( dim.dimensionQname)] = dim.dimension elif str(dim.dimensionQname) in qnamedReferences: conceptsByQname[str(dim.memberQname)] = dim.member def setArgForFactProperty(param, modelFact, propertyNameParts): propVal = None property = propertyNameParts[0] if property == "value": if isinstance(modelFact.xValue, Decimal): propVal = "{:,}".format(modelFact.xValue) else: propVal = modelFact.value elif property == "decimals": propVal = modelFact.decimals elif property == "label" and modelFact.concept is not None: propVal = modelFact.concept.label( labelrole, lang=lang, linkroleHint=XbrlConst.defaultLinkRole) elif property == "name": propVal = str(modelFact.qname) elif property == "localName": propVal = modelFact.qname.localName else: cntx = modelFact.context unit = modelFact.unit if cntx is not None: if property == "period": if len(propertyNameParts) == 1: if cntx.isForeverPeriod: propVal = "forever" elif cntx.isInstantPeriod: propVal = XmlUtil.dateunionValue( cntx.instantDatetime, subtractOneDay=True) else: propVal = "{} to {}".format( XmlUtil.dateunionValue(cntx.startDatetime), XmlUtil.dateunionValue( cntx.endDatetime, subtractOneDay=True)) else: dateSelection = propertyNameParts[1] if dateSelection == "startDate": propVal = XmlUtil.dateunionValue( cntx.startDatetime) elif dateSelection == "endDate": propVal = XmlUtil.dateunionValue( cntx.endDatetime, subtractOneDay=True) elif dateSelection == "instant": propVal = XmlUtil.dateunionValue( cntx.instant, subtractOneDay=True) elif dateSelection == "durationDays": propVal = str((cntx.endDatetime - cntx.startDatetime).days) elif property == "dimensions": if cntx.qnameDims: propVal = "\n".join( "{} = {}".format( d.dimensionQname, d.memberQname if d.isExplicit else XmlUtil. xmlstring(XmlUtil.child(d), stripXmlns=True, prettyPrint=True)) for d in cntx.qnameDims.values()) else: propVal = "none" if property == "unit": if unit is None: propVal = "none" else: measures = unit.measures if measures[1]: propVal = 'mul {}\ndiv {} '.format( ', '.join( measureFormat(m) for m in measures[0]), ', '.join( measureFormat(m) for m in measures[1])) else: propVal = ', '.join( measureFormat(m) for m in measures[0]) fmtArgs[param] = propVal def setArgForConceptProperty(param, modelConceptOrQname, propertyNameParts): propVal = None property = propertyNameParts[0] if property == "label": if isinstance(modelConceptOrQname, ModelConcept): propVal = modelConceptOrQname.label( labelrole, lang=lang, linkroleHint=XbrlConst.defaultLinkRole) elif isinstance(modelConceptOrQname, _STR_BASE): propVal = modelConceptOrQname elif property == "name": if isinstance(modelConceptOrQname, ModelConcept): propVal = str(modelConceptOrQname.qname) elif isinstance(modelConceptOrQname, _STR_BASE): propVal = modelConceptOrQname elif property == "localName": if isinstance(modelConcept, ModelConcept): propVal = modelConcept.qname.localName elif isinstance(modelConcept, _STR_BASE): propVal = modelConcept.rpartition(':')[2] if propVal is not None: fmtArgs[param] = propVal # parse parameter names out of msg for param in paramNames: try: paramParts = param.split('.') if len(paramParts) >= 2 and factNumberPattern.match( paramParts[0]): modelFactNum = int( factNumberPattern.match(paramParts[0]).group(1)) if 1 <= modelFactNum <= len(factsArray): modelFact = factsArray[modelFactNum - 1] setArgForFactProperty(param, modelFact, paramParts[1:]) elif len(paramParts) >= 3 and paramParts[1] == "fact": # take first matching fact ?? if paramParts[0] in factsByQname: modelFact = factsByQname[paramParts[0]][ 0] # there may be multiple facts of this QName, take first setArgForFactProperty(param, modelFact, paramParts[2:]) else: missingQnamedArguments.add(paramParts[0]) elif len(paramParts) >= 2: modelConcept = conceptsByQname.get( paramParts[0], paramParts[0]) # if no model concept pass in the qname setArgForConceptProperty(param, modelConcept, paramParts[1:]) except Exception as _ex: raise # pass if missingQnamedArguments: for arg in modelObjectArgs: # Pargmeter may be a ModelFact, or a name of a concept (such as a dimension) if isinstance(arg, ModelObject): arg.modelXbrl.error( "dqcErrorLog:unresolvedParameters", _("The error message %(messageCode)s has unresolved named parameters: %(unresolvedParameters)s" ), modelObject=modelObjectArgs, messageCode=messageCode, unresolvedParameters=', '.join( sorted(missingQnamedArguments))) break for missingArgument in missingQnamedArguments: fmtArgs[missingArgument] = "unavailable" return msg return None
def loggingMessageParameters(messageCode, msgIn, modelObjectArgs, fmtArgs): if messageCode and messageCode.startswith("DQC"): # change ${...} in message into %(...)s msg = altParametersPattern.sub(r"%(\1)s", msgIn) # find qnamed fact references qnamedReferences = set() paramNames = parametersPattern.findall(msg) for param in paramNames: paramParts = param.split('.') if len(paramParts) > 1 and not factNumberPattern.match(paramParts[0]): qnamedReferences.add(paramParts[0]) factsArray = [] factsByQname = defaultdict(list) # list of facts with the qname conceptsByQname = {} missingQnamedArguments = set() qnameFirstOrdinalPosition = {} # for qnamed facts multiply in sequence (to insert on 2nd occurance in ordinal position) for arg in flattenSequence(modelObjectArgs): # Pargmeter may be a ModelFact, or a name of a concept (such as a dimension) if isinstance(arg, ModelFact): _strQName = str(arg.qname) if _strQName in qnamedReferences: if _strQName not in factsByQname: # if twice in args, let one be an ordinal fact factsByQname[_strQName].append(arg) qnameFirstOrdinalPosition[_strQName] = len(factsArray) elif arg not in factsArray: # if twice in args, insert first occurence in ordinal position factsArray.insert(qnameFirstOrdinalPosition[_strQName], arg) else: factsArray.append(arg) cntx = arg.context if cntx is not None: for dim in cntx.qnameDims.values(): if str(dim.dimensionQname) in qnamedReferences: conceptsByQname[str(dim.dimensionQname)] = dim.dimension elif str(dim.dimensionQname) in qnamedReferences: conceptsByQname[str(dim.memberQname)] = dim.member def setArgForFactProperty(param, modelFact, propertyNameParts): propVal = None property = propertyNameParts[0] if property == "value": if isinstance(modelFact.xValue, Decimal): propVal = "{:,}".format(modelFact.xValue) else: propVal = modelFact.value elif property == "decimals": propVal = modelFact.decimals elif property == "label" and modelFact.concept is not None: propVal = modelFact.concept.label(labelrole, lang=lang, linkroleHint=XbrlConst.defaultLinkRole) elif property == "name": propVal = str(modelFact.qname) elif property == "localName": propVal = modelFact.qname.localName else: cntx = modelFact.context unit = modelFact.unit if cntx is not None: if property == "period": if len(propertyNameParts) == 1: if cntx.isForeverPeriod: propVal = "forever" elif cntx.isInstantPeriod: propVal = XmlUtil.dateunionValue(cntx.instantDatetime, subtractOneDay=True) else: propVal = "{} to {}".format(XmlUtil.dateunionValue(cntx.startDatetime), XmlUtil.dateunionValue(cntx.endDatetime, subtractOneDay=True)) else: dateSelection = propertyNameParts[1] if dateSelection == "startDate": propVal = XmlUtil.dateunionValue(cntx.startDatetime) elif dateSelection == "endDate": propVal = XmlUtil.dateunionValue(cntx.endDatetime, subtractOneDay=True) elif dateSelection == "instant": propVal = XmlUtil.dateunionValue(cntx.instant, subtractOneDay=True) elif dateSelection == "durationDays": propVal = str((cntx.endDatetime - cntx.startDatetime).days) elif property == "dimensions": if cntx.qnameDims: propVal = "\n".join("{} = {}".format(d.dimensionQname, d.memberQname if d.isExplicit else XmlUtil.xmlstring( XmlUtil.child(d), stripXmlns=True, prettyPrint=True )) for d in cntx.qnameDims.values()) else: propVal = "none" if property == "unit": if unit is None: propVal = "none" else: measures = unit.measures if measures[1]: propVal = 'mul {}\ndiv {} '.format( ', '.join(measureFormat(m) for m in measures[0]), ', '.join(measureFormat(m) for m in measures[1])) else: propVal = ', '.join(measureFormat(m) for m in measures[0]) if propVal is not None: fmtArgs[param] = propVal def setArgForConceptProperty(param, modelConceptOrQname, propertyNameParts): propVal = None property = propertyNameParts[0] if property == "label": if isinstance(modelConceptOrQname, ModelConcept): propVal = modelConceptOrQname.label(labelrole, lang=lang, linkroleHint=XbrlConst.defaultLinkRole) elif isinstance(modelConceptOrQname, _STR_BASE): propVal = modelConceptOrQname elif property == "name": if isinstance(modelConceptOrQname, ModelConcept): propVal = str(modelConceptOrQname.qname) elif isinstance(modelConceptOrQname, _STR_BASE): propVal = modelConceptOrQname elif property == "localName": if isinstance(modelConcept, ModelConcept): propVal = modelConcept.qname.localName elif isinstance(modelConcept, _STR_BASE): propVal = modelConcept.rpartition(':')[2] if propVal is not None: fmtArgs[param] = propVal # parse parameter names out of msg for param in paramNames: try: paramParts = param.split('.') if len(paramParts) >= 2 and factNumberPattern.match(paramParts[0]): modelFactNum = int(factNumberPattern.match(paramParts[0]).group(1)) if 1 <= modelFactNum <= len(factsArray): modelFact = factsArray[modelFactNum - 1] setArgForFactProperty(param, modelFact, paramParts[1:]) elif len(paramParts) >= 3 and paramParts[1] == "fact": # take first matching fact ?? if paramParts[0] in factsByQname: modelFact = factsByQname[paramParts[0]][0] # there may be multiple facts of this QName, take first setArgForFactProperty(param, modelFact, paramParts[2:]) else: missingQnamedArguments.add(paramParts[0]) elif len(paramParts) >= 2: modelConcept = conceptsByQname.get(paramParts[0], paramParts[0]) # if no model concept pass in the qname setArgForConceptProperty(param, modelConcept, paramParts[1:]) except Exception as _ex: raise # pass if missingQnamedArguments: for arg in modelObjectArgs: # Pargmeter may be a ModelFact, or a name of a concept (such as a dimension) if isinstance(arg, ModelObject): arg.modelXbrl.error("dqcErrorLog:unresolvedParameters", _("The error message %(messageCode)s has unresolved named parameters: %(unresolvedParameters)s"), modelObject=modelObjectArgs, messageCode=messageCode, unresolvedParameters=', '.join(sorted(missingQnamedArguments))) break for missingArgument in missingQnamedArguments: fmtArgs[missingArgument] = "unavailable" return msg return None
def validateXbrlStart(val, parameters=None, *args, **kwargs): val.validateEFMplugin = val.validateDisclosureSystem and getattr(val.disclosureSystem, "EFMplugin", False) if not (val.validateEFMplugin): return val.params = {} parameterNames = ("CIK", "cik", "cikList", "cikNameList", "submissionType", "exhibitType", # CIK or cik both allowed "itemsList", "accessionNumber", "entity.repFileNum", "periodOfReport", "entityRegistration.fyEnd", "submissionHeader.fyEnd", "voluntaryFilerFlag", "wellKnownSeasonedIssuerFlag", "shellCompanyFlag", "acceleratedFilerStatus", "smallBusinessFlag", "emergingGrowthCompanyFlag", "exTransitionPeriodFlag", "invCompanyType", "rptIncludeAllSeriesFlag", "rptSeriesClassInfo.seriesIds", "newClass2.seriesIds", "eligibleFundFlag", "pursuantGeneralInstructionFlag", "filerNewRegistrantFlag", "datetimeForTesting") parameterEisFileTags = { "cik":["depositorId", "cik", "filerId"], "submissionType": "submissionType", "itemsList": "item", "periodOfReport": "periodOfReport", #"headerFyEnd": ?, #"voluntaryFilerFlag": ?, "wellKnownSeasonedIssuerFlag": "wellKnownSeasonedIssuerFlag", #"shellCompanyFlag": ?, "acceleratedFilerStatus": "acceleratedFilerStatus", "smallBusinessFlag": "smallBusinessFlag", "emergingGrowthCompanyFlag": "emergingGrowthCompanyFlag", "exTransitionPeriodFlag": "exTransitionPeriodFlag", "invCompanyType": "invCompany", #"rptIncludeAllSeriesFlag": ?, #"rptSeriesClassInfo.seriesIds": ?, #"newClass2.seriesIds": ?, "filerNewRegistrantFlag": "filerNewRegistrantFlag", "pursuantGeneralInstructionFlag": "pursuantGeneralInstructionFlag", "eligibleFundFlag": "eligibleFundFlag" } # retrieve any EIS file parameters first if val.modelXbrl.fileSource and val.modelXbrl.fileSource.isEis and hasattr(val.modelXbrl.fileSource, "eisDocument"): eisDoc = val.modelXbrl.fileSource.eisDocument for paramName, eisEltNames in parameterEisFileTags.items(): paramQName = ModelValue.qname(paramName,noPrefixIsNoNamespace=True) for eisElt in eisDoc.iter(*("{*}"+e for e in flattenSequence(eisEltNames))): if paramName in ("itemsList",): parameters.setdefault(paramQName, []).append(eisElt.text) else: parameters[paramQName] = ("", "".join(eisElt.itertext()).strip()) if parameters: # parameter-provided CIKs and registrant names for paramName in parameterNames: p = parameters.get(ModelValue.qname(paramName,noPrefixIsNoNamespace=True)) if p and len(p) == 2 and p[1] not in ("null", "None", None): v = p[1] # formula dialog and cmd line formula parameters may need type conversion if isinstance(v, str): if paramName in {"voluntaryFilerFlag", "wellKnownSeasonedIssuerFlag", "shellCompanyFlag", "acceleratedFilerStatus", "smallBusinessFlag", "emergingGrowthCompanyFlag", "exTransitionPeriodFlag", "rptIncludeAllSeriesFlag", "filerNewRegistrantFlag", "pursuantGeneralInstructionFlag", "eligibleFundFlag"}: v = {"true":True, "false":False}.get(v) elif paramName in {"itemsList", "rptSeriesClassInfo.seriesIds", "newClass2.seriesIds"}: v = v.split() val.params[paramName] = v if "CIK" in val.params: # change to lower case key val.params["cik"] = val.params["CIK"] del val.params["CIK"] for paramName, p in parameters.items(): # allow ELOparams to be in any namespace (no xmlns="" required) if paramName and paramName.localName == "ELOparams" and len(p) == 2 and p[1] not in ("null", "None", None): try: for key, value in json.loads(p[1]).items(): val.params[{"CIK":"cik"}.get(key,key)] = value # change upper case CIK to lower case except (ValueError, AttributeError, TypeError): val.modelXbrl.error("arelle.testcaseVariationParameters", _("parameter ELOparams has malformed JSON %(json)s object"), modelXbrl=val.modelXbrl, json=p[1][:100]) break # parameters may also come from report entryPoint (such as exhibitType for SDR) if hasattr(val.modelXbrl.modelManager, "efmFiling"): efmFiling = val.modelXbrl.modelManager.efmFiling if efmFiling.reports: # possible that there are no reports entryPoint = efmFiling.reports[-1].entryPoint for paramName in parameterNames: # cik is lower case here if paramName in entryPoint and entryPoint[paramName] not in (None, ""): val.params[paramName] = entryPoint[paramName] # if not set uses prior value # exhibitType may be an attachmentType, if so remove ".INS" if val.params.get("exhibitType", "").endswith(".INS"): val.params["exhibitType"] = val.params["exhibitType"][:-4] if isinstance(val.params.get("cikNameList", None), str): # cik1, cik2, cik3 in cikList and name1|Edgar|name2|Edgar|name3 in cikNameList strings _filerIdentifiers = val.params["cikList"].split(",") if "cikList" in val.params else [] _filerNames = val.params["cikNameList"].split("|Edgar|") if "cikNameList" in val.params else [] if _filerIdentifiers: if len(_filerNames) not in (0, len(_filerIdentifiers)): val.modelXbrl.error(("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikList and cikNameList different list entry counts: %(cikList)s, %(cikNameList)s"), modelXbrl=val.modelXbrl, cikList=_filerIdentifiers, cikNameList=_filerNames) if _filerNames: val.params["cikNameList"]=dict((_cik,_filerNames[i] if i < len(_filerNames) else None) for i, _cik in enumerate(_filerIdentifiers)) else: val.params["cikNameList"]=dict((_cik,None) for _cik in _filerIdentifiers) del val.params["cikList"] elif _filerNames: val.modelXbrl.error(("EFM.6.05.24.parameters", "GFM.3.02.02"), _("parameters for cikNameList provided but missing corresponding cikList: %(cikNameList)s"), modelXbrl=val.modelXbrl, cikNameList=_filerNames) del val.params["cikNameList"] # can't process without cik's as keys if val.params.get("exhibitType", "") == "EX-2.01": # only applicable for edgar production and parameterized testcases val.EFM60303 = "EFM.6.23.01" else: val.EFM60303 = "EFM.6.03.03" if any((concept.qname.namespaceURI in val.disclosureSystem.standardTaxonomiesDict and concept.modelDocument.inDTS) for concept in val.modelXbrl.nameConcepts.get("UTR",())): val.validateUTR = True modelManager = val.modelXbrl.modelManager if hasattr(modelManager, "efmFiling"): efmFiling = modelManager.efmFiling efmFiling.submissionType = val.params.get("submissionType")