示例#1
0
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
示例#2
0
文件: Util.py 项目: kalituma/Arelle
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
示例#3
0
 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
示例#4
0
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
示例#5
0
文件: Util.py 项目: sclive/Arelle
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
示例#6
0
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
示例#7
0
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       
示例#8
0
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")