From 7c1ea7f9b3badfdbb11bb040bfedb63fb413b6e4 Mon Sep 17 00:00:00 2001 From: Paulo Vitor Magacho <139177232+pvmagacho-nde@users.noreply.github.com> Date: Tue, 30 Jul 2024 21:38:12 -0300 Subject: [PATCH] Update instance.py --- xbrl/instance.py | 70 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/xbrl/instance.py b/xbrl/instance.py index 81d01df..198c0b1 100644 --- a/xbrl/instance.py +++ b/xbrl/instance.py @@ -35,22 +35,69 @@ "xbrldi": "http://xbrl.org/2006/xbrldi" } +class AbstractMember: + def __init__(self, dimension: Concept) -> None: + self.dimension = dimension + + def __str__(self) -> str: + return "Dimension {}".format(self.dimension.name) + + def to_dict(self): + return { + 'dimension': self.dimension.to_dict(), + } + + def to_json(self): + return json.dumps(self.to_dict()) + -class ExplicitMember: +class TypedMember(AbstractMember): """ Representation of an explicit member in xbrl. XML Example: aapl:EuropeSegmentMember """ + def __init__(self, dimension: Concept, domain: List[str]) -> None: + super().__init__(dimension) + self.domain = domain + + def __str__(self) -> str: + return "{} on dimension {}".format(self.domain, self.dimension.name) + + def to_dict(self): + return { + 'dimension': self.dimension.to_dict(), + 'domain': self.domain + } + + def to_json(self): + return json.dumps(self.to_dict()) + + +class ExplicitMember(AbstractMember): + """ + Representation of an explicit member in xbrl. + XML Example: + aapl:EuropeSegmentMember + """ def __init__(self, dimension: Concept, member: Concept) -> None: - self.dimension = dimension + super().__init__(dimension) self.member = member def __str__(self) -> str: return "{} on dimension {}".format(self.member.name, self.dimension.name) + def to_dict(self): + return { + 'dimension': self.dimension.to_dict(), + 'member': self.member.to_dict() + } + + def to_json(self): + return json.dumps(self.to_dict()) + class AbstractContext(abc.ABC): """ @@ -64,7 +111,7 @@ class AbstractContext(abc.ABC): def __init__(self, xml_id: str, entity: str) -> None: self.xml_id: str = xml_id self.entity: str = entity - self.segments: List[ExplicitMember] = [] + self.segments: List[AbstractMember] = [] class InstantContext(AbstractContext): @@ -201,6 +248,7 @@ def json(self, **kwargs) -> dict: if 'dimensions' not in kwargs: kwargs['dimensions'] = {} kwargs['dimensions']['concept'] = self.concept.name kwargs['dimensions']['entity'] = self.context.entity + kwargs['dimensions']['contextId'] = self.context.xml_id kwargs['dimensions']['period'] = period for segment in self.context.segments: kwargs['dimensions'][segment.dimension.name] = segment.member.name @@ -657,6 +705,22 @@ def _parse_context_elements(context_elements: List[ET.Element], ns_map: dict, ta # add the explicit member to the context context.segments.append(ExplicitMember(dimension_concept, member_concept)) + for typed_member_element in segment.findall('xbrldi:typedMember', NAME_SPACES): + _update_ns_map(ns_map, typed_member_element.attrib['ns_map']) + dimension_prefix, dimension_concept_name = typed_member_element.attrib['dimension'].strip().split(':') + # get the taxonomy where the dimension attribute is defined + dimension_tax = taxonomy.get_taxonomy(ns_map[dimension_prefix]) + # check if the taxonomy was found + if dimension_tax is None: + # try to subsequently load the taxonomy + dimension_tax = _load_common_taxonomy(cache, ns_map[dimension_prefix], taxonomy) + dimension_concept: Concept = dimension_tax.concepts[dimension_tax.name_id_map[dimension_concept_name]] + domain: List[str] = [] + for child in typed_member_element: + domain.append(child.text.strip()) + + context.segments.append(TypedMember(dimension_concept, domain)) + context_dict[context_id] = context return context_dict