示例#1
0
def attributeDict(modelXbrl, elt, exclusions=set(), equalMode=S_EQUAL, excludeIDs=NO_IDs_EXCLUDED, ns2ns1Tbl=None, keyByTag=False, distinguishNaNs=False):
    if not hasattr(elt,"xValid"):
        XmlValidate.validate(modelXbrl, elt)
    attrs = {}
    # TBD: replace with validated attributes
    for modelAttribute in elt.xAttributes.values():
        attrTag = modelAttribute.attrTag
        ns, sep, localName = attrTag.partition('}')
        attrNsURI = ns[1:] if sep else None
        if ns2ns1Tbl and attrNsURI in ns2ns1Tbl:
            attrNsURI = ns2ns1Tbl[attrNsURI]
        if (attrTag not in exclusions and 
            (attrNsURI is None or attrNsURI not in exclusions)):
            if keyByTag:
                qname = attrTag
            elif attrNsURI is not None:
                qname = QName(None, attrNsURI, localName)
            else:
                qname = QName(None, None, attrTag)
            try:
                if excludeIDs and modelAttribute.xValid == XmlValidate.VALID_ID:
                    continue
                if modelAttribute.xValid != XmlValidate.UNKNOWN:
                    value = modelAttribute.sValue if equalMode <= S_EQUAL2 else modelAttribute.xValue
                else: # unable to validate, no schema definition, use string value of attribute
                    value = modelAttribute.text
                if distinguishNaNs and isinstance(value,float) and math.isnan(value):
                    value = (value,elt)
                attrs[qname] = value
            except KeyError:
                pass  # what should be done if attribute failed to have psvi value
    return attrs
示例#2
0
 def qname(self):
     try:
         return self._elementQname
     except AttributeError:
         self._elementQname = QName(self.prefix, self.namespaceURI,
                                    self.localName)
         return self._elementQname
示例#3
0
def _xbrlTypeMethod(node, sphinxContext, args):
    concept = conceptArg(node, sphinxContext, args, 0)
    baseTypeLocalName = concept.baseXbrliType
    if not baseTypeLocalName:
        return NONE
    return QName("{http://www.xbrl.org/2003/instance}xbrli:" +
                 baseTypeLocalName)
示例#4
0
    def _traverse(self, parent, depth=0, top_name=None):
        """Traverse a parse tree for qnames
        
        :returns: dictionary of set, keyed by qname. The set is the list of rules that use the qname
        :rtype: dict
        """
        qnames = collections.defaultdict(set)

        # When the depth is 2, we are at a top level expression (i.e. rule, constant, namespace declaration, function). Get the name of the expression.
        if depth == 2:
            top_name = "{}: {}".format(
                parent['exprName'],
                parent.get('fullName') or parent.get('constantName')
                or parent.get('functionName'))

        if isinstance(parent, dict):
            if parent.get('exprName') == 'qname':
                qnames[QName(
                    parent['prefix'] if parent['prefix'] != '*' else None,
                    parent['namespace_uri'],
                    parent['localName'])].add(top_name)
                #qnames.add(QName(parent['prefix'] if parent['prefix'] != '*' else None, parent['namespace_uri'], parent['localName']))
            else:
                for k, v in parent.items():
                    # Skip 'arcrole', 'role' and 'drsRole' in navigation if it is an unprefixed qname
                    if not (parent.get('exprName') == 'navigation'
                            and k in ('arcrole', 'role', 'drsRole')
                            and v.get('exprName') == 'qname'
                            and v.get('prefix') == '*'):
                        # Remove .networks property arguments if they are unprefixed qnames
                        if (parent.get('exprName') == 'property'
                                and parent.get('propertyName') == 'networks'
                                and k == 'propertyArgs'):
                            v = [
                                x for x in v
                                if not (x.get('exprName') == 'qname'
                                        and x.get('prefix') == '*')
                            ]

                        new_qnames = self._traverse(v, depth + 1, top_name)
                        qnames = {
                            k: qnames.get(k, set()) | new_qnames.get(k, set())
                            for k in qnames.keys() | new_qnames.keys()
                        }
                        #qnames |= self._traverse(v, depth+1, top_name)
        elif isinstance(parent, list):
            for x in parent:
                new_qnames = self._traverse(x, depth + 1, top_name)
                qnames = {
                    k: qnames.get(k, set()) | new_qnames.get(k, set())
                    for k in qnames.keys() | new_qnames.keys()
                }
                #qnames |= self._traverse(x, depth+1, top_name)

        return qnames
示例#5
0
def convert_file_data_item(item, type, xule_context):

    if type is None:
        return xv.XuleValue(xule_context, item, 'string')
    elif type == 'qname':
        if item.count(':') == 0:
            prefix = '*'  # This indicates the default namespace
            local_name = item
        elif item.count(':') == 1:
            prefix, local_name = item.split(':')
        else:
            raise XuleProcessingError(
                _("While processing a data file, QName in a file can only have one ':', found {} ':'s"
                  .format(item.count(':'))), xule_context)

        namespace = xule_context.rule_set.getNamespaceUri(prefix)

        return xv.XuleValue(
            xule_context,
            QName(prefix if prefix != '*' else None, namespace, local_name),
            'qname')
    elif type == 'int':
        try:
            return xv.XuleValue(xule_context, int(item), 'int')
        except ValueError:
            raise XuleProcessingError(
                _("While processing a data file, cannot convert '{}' to an {}."
                  .format(item, type)), xule_context)
    elif type == 'float':
        try:
            return xv.XuleValue(xule_context, float(item), 'float')
        except ValueError:
            raise XuleProcessingError(
                _("While processing a data file, cannot convert '{}' to a {}.".
                  format(item, type)), xule_context)
    elif type == 'decimal':
        try:
            return xv.XuleValue(xule_context, decimal.Decimal(item), 'decimal')
        except decimal.InvalidOperation:
            raise XuleProcessingError(
                _("While processing a data file, cannot convert '{}' to a {}.".
                  format(item, type)), xule_context)
    elif type == 'string':
        return xv.XuleValue(xule_context, item, type)
    else:
        raise XuleProcessingError(
            _("While processing a data file, {} is not implemented.".format(
                type)), xule_context)
示例#6
0
def func_qname(xule_context, *args):
    namespace_uri = args[0]
    local_name = args[1]

    if namespace_uri.type not in ('string', 'uri', 'unbound', 'none'):
        raise XuleProcessingError(
            _("Function 'qname' requires the namespace_uri argument to be a string, uri or none, found '%s'"
              % namespace_uri.type), xule_context)
    if local_name.type != 'string':
        raise XuleProcessingError(
            _("Function 'qname' requires the local_part argument to be a string, found '%s'"
              % local_name.type), xule_context)

    if namespace_uri.type == 'unbound':
        return xv.XuleValue(
            xule_context, qname(local_name.value, noPrefixIsNoNamespace=True),
            'qname')
    else:
        '''INSTEAD OF PASSING None FOR THE PREFIX, THIS SHOULD FIND THE PREFIX FOR THE NAMESPACE URI FROM THE RULE FILE. IF IT CANNOT FIND ONE, IT SHOULD CREATE ONE.'''
        return xv.XuleValue(xule_context,
                            QName(None, namespace_uri.value, local_name.value),
                            'qname')
示例#7
0
def func_qname(xule_context, *args):
    namespace_uri_arg = args[0]
    local_name_arg = args[1]

    if namespace_uri_arg.type not in ('string', 'uri', 'unbound', 'none'):
        raise XuleProcessingError(
            _("Function 'qname' requires the namespace_uri argument to be a string, uri or none, found '%s'"
              % namespace_uri_arg.type), xule_context)
    if local_name_arg.type != 'string':
        raise XuleProcessingError(
            _("Function 'qname' requires the local_part argument to be a string, found '%s'"
              % local_name_arg.type), xule_context)

    if namespace_uri_arg.type == 'unbound':
        return xv.XuleValue(
            xule_context,
            qname(local_name_arg.value, noPrefixIsNoNamespace=True), 'qname')
    else:
        # get the prefix from the rule file
        prefix = get_prefix(xule_context, namespace_uri_arg.value)
        return xv.XuleValue(
            xule_context,
            QName(prefix, namespace_uri_arg.value, local_name_arg.value),
            'qname')
def _prep_roll_forward_constants(xule_context):
    xule_context.roll_forward = dict()

    us_gaap_ns = [
        ns for ns in xule_context.model.namespaceDocs
        if re.match(r'(http://fasb.org/|http://xbrl.us/)us-gaap/', ns)
    ]
    if len(us_gaap_ns) == 0:
        raise XuleProcessingError(_("US GAAP taxonomy is not found."),
                                  xule_context)
    if len(us_gaap_ns) > 1:
        raise XuleProcessingError(
            _("Found more than one version for the US GAAP taxonomy: %s" %
              ", ".join(us_gaap_ns)), xule_context)

    xule_context.roll_forward['US_GAAP_NS'] = us_gaap_ns = us_gaap_ns[0]
    xule_context.roll_forward['INCOME_STATEMENT_LOCATION_AXIS'] = QName(
        None, xule_context.roll_forward['US_GAAP_NS'],
        'IncomeStatementLocationAxis')
    xule_context.roll_forward['ROLL_FORWARD_EXCEPTIONS'] = \
        {QName(None, xule_context.roll_forward['US_GAAP_NS'], 'ShareBasedCompensationArrangementByShareBasedPaymentAwardEquityInstrumentsOtherThanOptionsNonvestedWeightedAverageGrantDateFairValue')
           ,QName(None, xule_context.roll_forward['US_GAAP_NS'], 'ShareBasedCompensationArrangementByShareBasedPaymentAwardOptionsOutstandingWeightedAverageExercisePrice')
           ,QName(None, xule_context.roll_forward['US_GAAP_NS'], 'SharebasedCompensationArrangementBySharebasedPaymentAwardOptionsNonvestedWeightedAverageGrantDateFairValue')
           ,QName(None, xule_context.roll_forward['US_GAAP_NS'], 'PartnersCapital')
           ,QName(None, xule_context.roll_forward['US_GAAP_NS'], 'PartnersCapitalAccountUnits')}

    xule_context.roll_forward['TOTAL_LABELS'] = (
        'http://www.xbrl.org/2003/role/totalLabel',
        'http://www.xbrl.org/2009/role/negatedTotalLabel')

    xule_context.roll_forward['BASE_RF_CALCS'] = None
    xule_context.roll_forward['BASE_PERIOD_TOTALS'] = None
    xule_context.roll_forward['EXT_DEFAULTS'] = None
    xule_context.roll_forward['CALC_EXCEPTIONS'] = \
        {QName(None, xule_context.roll_forward['US_GAAP_NS'], 'AllowanceForLoanAndLeaseLossesPeriodIncreaseDecrease'):{QName(None, xule_context.roll_forward['US_GAAP_NS'], 'ProvisionForLoanAndLeaseLosses'): 1,
                                                                                                                       QName(None, xule_context.roll_forward['US_GAAP_NS'], 'AllowanceForLoanAndLeaseLossesRecoveriesOfBadDebts'):1},
         QName(None, xule_context.roll_forward['US_GAAP_NS'], 'DefinedBenefitPlanBenefitObligationPeriodIncreaseDecrease'):{QName(None, xule_context.roll_forward['US_GAAP_NS'], 'DefinedBenefitPlanForeignCurrencyExchangeRateChangesBenefitObligation'):-1,
                                                                                                                            QName(None, xule_context.roll_forward['US_GAAP_NS'], 'DefinedBenefitPlanActuarialGainLoss'):-1,
                                                                                                                            QName(None, xule_context.roll_forward['US_GAAP_NS'], 'DefinedBenefitPlanOtherChanges'):1},
         QName(None, xule_context.roll_forward['US_GAAP_NS'], 'FiniteLivedIntangibleAssetsPeriodIncreaseDecrease'):{QName(None, xule_context.roll_forward['US_GAAP_NS'], 'AmortizationOfIntangibleAssets'):-1,
                                                                                                                    QName(None, xule_context.roll_forward['US_GAAP_NS'], 'ImpairmentOfIntangibleAssetsFinitelived'):-1},
         QName(None, xule_context.roll_forward['US_GAAP_NS'], 'RestructuringReservePeriodIncreaseDecrease'):{QName(None, xule_context.roll_forward['US_GAAP_NS'], 'RestructuringReserveSettledWithCash'):-1,
                                                                                                             QName(None, xule_context.roll_forward['US_GAAP_NS'], 'RestructuringReserveSettledWithoutCash'):-1},
         QName(None, xule_context.roll_forward['US_GAAP_NS'], 'ShareBasedCompensationArrangementByShareBasedPaymentAwardOptionsOutstandingPeriodIncreaseDecrease'):{QName(None, xule_context.roll_forward['US_GAAP_NS'], 'ShareBasedCompensationArrangementByShareBasedPaymentAwardOptionsGrantsInPeriod'):1}
        }

    xule_context.roll_forward['EFFECTIVE_WEIGHTS'] = dict()
    xule_context.roll_forward['HAS_CALC'] = dict()
    xule_context.roll_forward['LINE_ITEM_CUBE'] = None
示例#9
0
    def createViewer(self, scriptUrl="js/dist/ixbrlviewer.js"):
        """
        Create an iXBRL file with XBRL data as a JSON blob, and script tags added
        """

        dts = self.dts
        iv = iXBRLViewer(dts)
        idGen = 0
        self.roleMap.getPrefix(XbrlConst.standardLabel, "std")
        self.roleMap.getPrefix(XbrlConst.documentationLabel, "doc")
        self.roleMap.getPrefix(XbrlConst.summationItem, "calc")
        self.roleMap.getPrefix(XbrlConst.parentChild, "pres")

        for f in dts.facts:
            if f.id is None:
                f.set("id", "ixv-%d" % (idGen))
            idGen += 1
            conceptName = self.nsmap.qname(f.qname)
            scheme, ident = f.context.entityIdentifier

            aspects = {
                "c":
                conceptName,
                "e":
                self.nsmap.qname(
                    QName(self.nsmap.getPrefix(scheme, "e"), scheme, ident)),
            }

            factData = {
                "v": f.value,
                "a": aspects,
            }
            if f.format is not None:
                factData["f"] = str(f.format)

            if f.isNumeric:
                if f.unit is not None:
                    # XXX does not support complex units
                    unit = self.nsmap.qname(f.unit.measures[0][0])
                    aspects["u"] = unit
                else:
                    # The presence of the unit aspect is used by the viewer to
                    # identify numeric facts.  If the fact has no unit (invalid
                    # XBRL, but we want to support it for draft documents),
                    # include the unit aspect with a null value.
                    aspects["u"] = None
                d = inferredDecimals(f)
                if d != float("INF") and not math.isnan(d):
                    factData["d"] = d

            for d, v in f.context.qnameDims.items():
                if v.memberQname is None:
                    # Typed dimension, not yet supported.
                    continue
                aspects[self.nsmap.qname(v.dimensionQname)] = self.nsmap.qname(
                    v.memberQname)
                self.addConcept(v.dimension)
                self.addConcept(v.member)

            if f.context.isForeverPeriod:
                aspects["p"] = "f"
            elif f.context.isInstantPeriod:
                aspects["p"] = self.dateFormat(
                    f.context.instantDatetime.isoformat())
            elif f.context.isStartEndPeriod:
                aspects["p"] = "%s/%s" % (
                    self.dateFormat(f.context.startDatetime.isoformat()),
                    self.dateFormat(f.context.endDatetime.isoformat()))

            self.taxonomyData["facts"][f.id] = factData
            self.addConcept(f.concept)

        self.taxonomyData["prefixes"] = self.nsmap.prefixmap
        self.taxonomyData["roles"] = self.roleMap.prefixmap
        self.taxonomyData["rels"] = self.getRelationships()

        dts.info("viewer:info", "Creating iXBRL viewer")

        if dts.modelDocument.type == Type.INLINEXBRLDOCUMENTSET:
            # Sort by object index to preserve order in which files were specified.
            docSet = sorted(dts.modelDocument.referencesDocument.keys(),
                            key=lambda x: x.objectIndex)
            docSetFiles = list(
                map(lambda x: os.path.basename(x.filepath), docSet))
            self.taxonomyData["docSetFiles"] = docSetFiles

            for n in range(0, len(docSet)):
                iv.addFile(
                    iXBRLViewerFile(docSetFiles[n], docSet[n].xmlDocument))

            xmlDocument = docSet[0].xmlDocument

        else:
            xmlDocument = dts.modelDocument.xmlDocument
            filename = os.path.basename(dts.modelDocument.filepath)
            iv.addFile(iXBRLViewerFile(filename, xmlDocument))

        taxonomyDataJSON = self.escapeJSONForScriptTag(
            json.dumps(self.taxonomyData, indent=1, allow_nan=False))

        for child in xmlDocument.getroot():
            if child.tag == '{http://www.w3.org/1999/xhtml}body':
                child.append(etree.Comment("BEGIN IXBRL VIEWER EXTENSIONS"))

                e = etree.fromstring(
                    "<script xmlns='http://www.w3.org/1999/xhtml' src='%s' type='text/javascript'  />"
                    % scriptUrl)
                # Don't self close
                e.text = ''
                child.append(e)

                # Putting this in the header can interfere with character set
                # auto detection
                e = etree.fromstring(
                    "<script xmlns='http://www.w3.org/1999/xhtml' type='application/x.ixbrl-viewer+json'></script>"
                )
                e.text = taxonomyDataJSON
                child.append(e)
                child.append(etree.Comment("END IXBRL VIEWER EXTENSIONS"))
                break

        return iv
    def createViewer(self, scriptUrl="js/dist/ixbrlviewer.js"):
        """
        Create an iXBRL file with XBRL data as a JSON blob, and script tags added
        """

        dts = self.dts
        idGen = 0
        self.roleMap.getPrefix(XbrlConst.standardLabel,"std")
        self.roleMap.getPrefix(XbrlConst.documentationLabel,"doc")
        self.roleMap.getPrefix(XbrlConst.summationItem,"calc")
        self.roleMap.getPrefix(XbrlConst.parentChild,"pres")


        for f in dts.facts:
            if f.id is None:
                f.set("id","ixv-%d" % (idGen))
            idGen += 1
            conceptName = self.nsmap.qname(f.qname)
            scheme, ident = f.context.entityIdentifier

            aspects = {
                "c": conceptName,
                "e": self.nsmap.qname(QName(self.nsmap.getPrefix(scheme,"e"), scheme, ident)),
            }

            factData = {
                "v": f.value,
                "a": aspects,
            }
            if f.format is not None:
                factData["f"] = str(f.format)

            if f.isNumeric:
                if f.unit:
                    # XXX does not support complex units
                    unit = self.nsmap.qname(f.unit.measures[0][0])
                    aspects["u"] = unit
                d = inferredDecimals(f)
                if d != float("INF") and not math.isnan(d):
                    factData["d"] = d

            for d, v in f.context.qnameDims.items():
                if v.memberQname is None:
                    # Typed dimension, not yet supported.
                    continue
                aspects[self.nsmap.qname(v.dimensionQname)] = self.nsmap.qname(v.memberQname)
                self.addConcept(v.dimension)
                self.addConcept(v.member)

            # XXX does not support forever periods
            if f.context.isInstantPeriod:
                aspects["p"] = self.dateFormat(f.context.instantDatetime.isoformat())
            elif f.context.isStartEndPeriod:
                aspects["p"] = "%s/%s" % (
                    self.dateFormat(f.context.startDatetime.isoformat()),
                    self.dateFormat(f.context.endDatetime.isoformat())
                )

            self.taxonomyData["facts"][f.id] = factData

            self.addConcept(f.concept)

        self.taxonomyData["prefixes"] = self.nsmap.prefixmap
        self.taxonomyData["roles"] = self.roleMap.prefixmap
        self.taxonomyData["rels"] = self.getRelationnShips()

        taxonomyDataJSON = self.escapeJSONForScriptTag(json.dumps(self.taxonomyData, indent=1, allow_nan=False))

        dts.info("viewer:info", "Creating iXBRL viewer")

        for child in dts.modelDocument.xmlDocument.getroot():
            if child.tag == '{http://www.w3.org/1999/xhtml}body':
                child.append(etree.Comment("BEGIN IXBRL VIEWER EXTENSIONS"))

                e = etree.fromstring("<script xmlns='http://www.w3.org/1999/xhtml' src='%s'  />" % scriptUrl)
                e.text = ''
                child.append(e)

                # Putting this in the header can interfere with character set
                # auto detection
                e = etree.fromstring("<script xmlns='http://www.w3.org/1999/xhtml' id='taxonomy-data' type='application/json'></script>")
                e.text = taxonomyDataJSON
                child.append(e)
                child.append(etree.Comment("END IXBRL VIEWER EXTENSIONS"))
                break

        return dts.modelDocument.xmlDocument
示例#11
0
    def addFact(self, f):
        if f.id is None:
            f.set("id", "ixv-%d" % (self.idGen))

        self.idGen += 1
        conceptName = self.nsmap.qname(f.qname)
        scheme, ident = f.context.entityIdentifier

        aspects = {
            "c":
            conceptName,
            "e":
            self.nsmap.qname(
                QName(self.nsmap.getPrefix(scheme, "e"), scheme, ident)),
        }

        factData = {
            "a": aspects,
        }

        if f.isNil:
            factData["v"] = None
        elif f.concept is not None and f.concept.isEnumeration:
            qnEnums = f.xValue
            if not isinstance(qnEnums, list):
                qnEnums = (qnEnums, )
            factData["v"] = " ".join(self.nsmap.qname(qn) for qn in qnEnums)
            for qn in qnEnums:
                self.addConcept(self.dts.qnameConcepts.get(qn))
        else:
            factData["v"] = f.value
            if f.value == INVALIDixVALUE:
                factData["err"] = 'INVALID_IX_VALUE'

        if f.format is not None:
            factData["f"] = str(f.format)

        if f.isNumeric:
            if f.unit is not None and len(f.unit.measures[0]):
                # XXX does not support complex units
                unit = self.nsmap.qname(f.unit.measures[0][0])
                aspects["u"] = unit
            else:
                # The presence of the unit aspect is used by the viewer to
                # identify numeric facts.  If the fact has no unit (invalid
                # XBRL, but we want to support it for draft documents),
                # include the unit aspect with a null value.
                aspects["u"] = None
            d = inferredDecimals(f)
            if d != float("INF") and not math.isnan(d):
                factData["d"] = d

        for d, v in f.context.qnameDims.items():
            if v.memberQname is not None:
                aspects[self.nsmap.qname(v.dimensionQname)] = self.nsmap.qname(
                    v.memberQname)
                self.addConcept(v.member)
                self.addConcept(v.dimension, dimensionType="e")
            elif v.typedMember is not None:
                aspects[self.nsmap.qname(
                    v.dimensionQname)] = v.typedMember.text
                self.addConcept(v.dimension, dimensionType="t")

        if f.context.isForeverPeriod:
            aspects["p"] = "f"
        elif f.context.isInstantPeriod and f.context.instantDatetime is not None:
            aspects["p"] = self.dateFormat(
                f.context.instantDatetime.isoformat())
        elif f.context.isStartEndPeriod and f.context.startDatetime is not None and f.context.endDatetime is not None:
            aspects["p"] = "%s/%s" % (
                self.dateFormat(f.context.startDatetime.isoformat()),
                self.dateFormat(f.context.endDatetime.isoformat()))

        frels = self.footnoteRelationshipSet.fromModelObject(f)
        if frels:
            for frel in frels:
                if frel.toModelObject is not None:
                    factData.setdefault("fn", []).append(frel.toModelObject.id)

        self.taxonomyData["facts"][f.id] = factData
        self.addConcept(f.concept)