Skip to content

Plugins

The module allows for plugins to customize functionality, using the pluggy framework.

The only current plugin endpoint is to add more Formatters. A formatter takes a value from a iXBRL™ item and converts it into the appropriate python value. For example, the ixtNumWordsEn formatter would take a value like "eighty-five" and turn it into 85.

The formats used within iXBRL™ files can vary between schemas and countries. Rather than try to cover everything in this module, you can write a plugin to support the format that you need.

Creating a plugin

Create a custom format class

To create a plugin, you first need to create a new format class that subclasses ixbrlparse.ixbrlFormat. This has two key components:

  • a format_names attribute which consists of a tuple of possible names for the format. These are the values that will be checked against the iXBRL™ items. These names will override any already defined by the ixbrlparse, so it is possible to override the default implementation.
  • a parse_value function which takes the original text value and returns the processed value.

An example class might look like (in the file ixbrlparse-dateplugin/ixbrlparse_dateplugin.py):

import ixbrlparse

class ixtParseIsoDate(ixbrlparse.ixbrlFormat):
    format_names = ("isodateformat")

    def parse_value(self, value):
        return datetime.datetime.strptime(value, "%Y-%m-%d").astimezone().date()

Hook into ixbrlparse

Next you need to add a function which will hook into ixbrlparse at the right point. This function needs to be called ixbrl_add_formats, and returns a list of new format classes (added to the bottom of ixbrlparse-dateplugin/ixbrlparse_dateplugin.py):

@ixbrlparse.hookimpl
def ixbrl_add_formats():
    return [ixtParseIsoDate]

or you can specify the specname if you don't want to call the function ixbrl_add_formats

@ixbrlparse.hookimpl(specname="ixbrl_add_formats")
def add_new_ixbrl_formats():
    return [ixtParseIsoDate]

You then need to add an entrypoint to setup.py or to pyproject.toml which will be activated when your project is installed. This should look something like (using an example ixbrlparse-dateplugin/setup.py):

from setuptools import setup

setup(
    name="ixbrlparse-dateplugin",
    install_requires="ixbrlparse",
    entry_points={"ixbrlparse": ["dateplugin = ixbrlparse_dateplugin"]},
    py_modules=["ixbrlparse_dateplugin"],
)

Or to use pyproject.toml you would add

[project.entry-points.ixbrlparse]
dateplugin = "ixbrlparse_dateplugin"

Override an existing format

By default, formats from plugins are loaded after the default formats included with the module. This means it is possible to override them by subclassing the format class.

For example, if you wanted to add additional date formats to a format class:

from ixbrlparse.components.formats import ixtDateDayMonthYear

class ixtDateDayMonthYearExtended(ixtDateDayMonthYear):
    date_format = (*ixtDateDayMonthYear.date_format, "%d-%b-%Y", "%d-%b-%y")

@hookimpl
def ixbrl_add_formats(self) -> List[Type[ixbrlFormat]]:
    return [ixtDateDayMonthYearExtended]

After installation, this new format class would override the existing formats for ixtDateDayMonthYear and allow for dates like "29 aug 2022" to be parsed as well as dates like "29/08/2022".

Install the plugin

If you then install the plugin it should be picked up by ixbrlparse and will also include the additional formats when checking.

Acknowledgements

The implementation of pluggy used here draws heavily on pluggy's own tutorial and @simonw's implementation of plugins for datasette.