Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple support to TypedMember #143

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 67 additions & 3 deletions xbrl/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
<xbrldi:explicitMember dimension="us-gaap:StatementBusinessSegmentsAxis">aapl:EuropeSegmentMember</xbrldi:explicitMember>
"""
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:
<xbrldi:explicitMember dimension="us-gaap:StatementBusinessSegmentsAxis">aapl:EuropeSegmentMember</xbrldi:explicitMember>
"""
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):
"""
Expand All @@ -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):
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
Loading