Skip to content

Commit

Permalink
Merge branch 'main' of github.com:manusimidt/py-xbrl
Browse files Browse the repository at this point in the history
  • Loading branch information
manusimidt committed Nov 13, 2024
2 parents 658f225 + 6c04dbf commit 16c555c
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# These are supported funding model platforms
buy_me_a_coffee: manusimidt
14 changes: 14 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**XBRL document**
Please provide a link to the XBRL document(s) with which you have encountered the issue

**Describe the bug**
A clear and concise description of what the bug is.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

.idea/
.notes.md

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
setuptools==65.5.1
requests~=2.31.0
urllib3~=1.26.11
setuptools==70.2.0
requests~=2.32.3
urllib3~=2.2.2
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def read(filename):

setup(
name="py-xbrl",
version="2.2.10",
version="2.2.12",
url="https://github.com/manusimidt/xbrl_parser",
license='GNU General Public License v3 (GPLv3)',
author="Manuel Schmidt",
Expand Down
6 changes: 3 additions & 3 deletions tests/test_local_taxonomy.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ def test_parse_taxonomy(self):
cache_dir: str = './cache/'
cache: HttpCache = HttpCache(cache_dir)
print(f"Saving to {cache_dir}")
imported_schema_uris = set()

extension_schema_path: str = './tests/data/example.xsd'
# extension_schema_path: str = './data/example.xsd'
tax: TaxonomySchema = parse_taxonomy(extension_schema_path, cache, imported_schema_uris = set())
tax: TaxonomySchema = parse_taxonomy(extension_schema_path, cache)
print(tax)
srt_tax: TaxonomySchema = tax.get_taxonomy('http://fasb.org/srt/2020-01-31')
self.assertTrue(srt_tax)
Expand All @@ -32,4 +32,4 @@ def test_parse_taxonomy(self):


if __name__ == '__main__':
unittest.main()
unittest.main()
2 changes: 1 addition & 1 deletion xbrl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class ContextParseException(InstanceParseException):
pass


__version__ = '2.2.10'
__version__ = '2.2.12'
__author__ = 'Manuel Schmidt <[email protected]>'
__all__ = [
XbrlParseException,
Expand Down
78 changes: 73 additions & 5 deletions xbrl/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,71 @@
}


class ExplicitMember:
class AbstractMember(abc.ABC):
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 TypedMember(AbstractMember):
"""
Representation of a typed member in xbrl.
XML Example:
<xbrldi:typedMember dimension="us-gaap:RevenueRemainingPerformanceObligationExpectedTimingOfSatisfactionStartDateAxis">
<us-gaap:RevenueRemainingPerformanceObligationExpectedTimingOfSatisfactionStartDateAxis.domain>2024-06-30</us-gaap:RevenueRemainingPerformanceObligationExpectedTimingOfSatisfactionStartDateAxis.domain>
</xbrldi:typedMember>
"""
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 +114,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,9 +251,11 @@ 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
if isinstance(segment, ExplicitMember):
kwargs['dimensions'][segment.dimension.name] = segment.member.name
return kwargs


Expand Down Expand Up @@ -657,6 +709,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
5 changes: 4 additions & 1 deletion xbrl/taxonomy.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
"http://fasb.org/srt/2021-01-31": "http://xbrl.fasb.org/srt/2021/elts/srt-2021-01-31.xsd",
"http://fasb.org/srt/2022": "https://xbrl.fasb.org/srt/2022/elts/srt-2022.xsd",
"http://fasb.org/srt/2023": "https://xbrl.fasb.org/srt/2023/elts/srt-2023.xsd",
"http://fasb.org/srt/2024": "https://xbrl.fasb.org/srt/2024/elts/srt-2024.xsd",
"http://fasb.org/srt-roles/2018-01-31": "http://xbrl.fasb.org/srt/2018/elts/srt-roles-2018-01-31.xsd",
"http://fasb.org/srt-roles/2019-01-31": "http://xbrl.fasb.org/srt/2019/elts/srt-roles-2019-01-31.xsd",
"http://fasb.org/srt-roles/2020-01-31": "http://xbrl.fasb.org/srt/2020/elts/srt-roles-2020-01-31.xsd",
Expand All @@ -190,6 +191,7 @@
"http://fasb.org/us-gaap/2022-01-31": "https://xbrl.fasb.org/us-gaap/2022/elts/us-gaap-2022.xsd",
"http://fasb.org/us-gaap/2022": "https://xbrl.fasb.org/us-gaap/2022/elts/us-gaap-2022.xsd",
"http://fasb.org/us-gaap/2023": "https://xbrl.fasb.org/us-gaap/2023/elts/us-gaap-2023.xsd",
"http://fasb.org/us-gaap/2024": "https://xbrl.fasb.org/us-gaap/2024/elts/us-gaap-2024.xsd",
"http://fasb.org/us-roles/2011-01-31": "http://xbrl.fasb.org/us-gaap/2011/elts/us-roles-2011-01-31.xsd",
"http://fasb.org/us-roles/2012-01-31": "http://xbrl.fasb.org/us-gaap/2012/elts/us-roles-2012-01-31.xsd",
"http://fasb.org/us-roles/2013-01-31": "http://xbrl.fasb.org/us-gaap/2013/elts/us-roles-2013-01-31.xsd",
Expand Down Expand Up @@ -281,6 +283,7 @@
"http://xbrl.sec.gov/dei/2021": "https://xbrl.sec.gov/dei/2021/dei-2021.xsd",
"http://xbrl.sec.gov/dei/2022": "https://xbrl.sec.gov/dei/2022/dei-2022.xsd",
"http://xbrl.sec.gov/dei/2023": "https://xbrl.sec.gov/dei/2023/dei-2023.xsd",
"http://xbrl.sec.gov/dei/2024": "https://xbrl.sec.gov/dei/2024/dei-2024.xsd",
"http://xbrl.sec.gov/dei/2021q4": "https://xbrl.sec.gov/dei/2021q4/dei-2021q4.xsd",
"http://xbrl.sec.gov/dei-def/2021": "https://xbrl.sec.gov/dei/2021/dei-2021_def.xsd",
"http://xbrl.sec.gov/dei-entire/2021": "https://xbrl.sec.gov/dei/2021/dei-entire-2021.xsd",
Expand Down Expand Up @@ -603,7 +606,7 @@ def parse_taxonomy_url(schema_url: str, cache: HttpCache, imported_schema_uris:
return parse_taxonomy(schema_path, cache, imported_schema_uris, schema_url)


def parse_taxonomy(schema_path: str, cache: HttpCache, imported_schema_uris : set, schema_url: str or None = None) -> TaxonomySchema:
def parse_taxonomy(schema_path: str, cache: HttpCache, imported_schema_uris : set = set(), schema_url: str or None = None) -> TaxonomySchema:
"""
Parses a taxonomy schema file.
Expand Down
2 changes: 1 addition & 1 deletion xbrl/transformations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ def durWordSen(arg: str) -> str:


def numWordSen(arg: str) -> str:
if arg == 'no' or arg == 'none':
if arg == 'no' or arg == 'none' or arg == 'nil':
return '0'
else:
arg = arg.replace(' and ', ' ')
Expand Down

0 comments on commit 16c555c

Please sign in to comment.