Plugin Guide#

pyH2A follows the open-closed principle, meaning that new plugins can be interfaced with pyH2A without modification of the source code. To work with pyH2A, plugins should follow certain design principles.

Structure#

Plugins are single .py files, which contain a class with the same name as the filename (this shared name should include the term Plugin). This class is instantiated during pyH2A runtime. Instantiation requires two arguments: dcf, which is discounted cash flow object (generated during pyH2A runtime) and print_info, which is a flag to control printing of additional runtime information (this flag is passed to insert()) The file may also contain other classes and functions, which serve the central class.

The overall idea is that during instantiation, the class reads information from dcf.inp (the dictionary generated from the input file), processes the information and inserts new information into dcf.inp. dcf.inp is the medium of information exchange between plugins and by inserting information there, the results of the plugin affect the outcome of the discounted cashflow analysis.

Example#

from pyH2A.Utilities.input_modification import insert, process_table

class Example_Plugin:
        '''Docstring header.

        Parameters
        ----------
        Table > Row > Value : float
                Example input read from input file by plugin.

        Returns
        -------
        Other Table > Row > Value : float
                Output generated by plugin which is stored in dcf.inp.
        '''

        def __init__(self, dcf, print_info):
                process_table(dcf.inp, 'Table', 'Value') # 'Value' column of 'Table' is processed

                self.method(dcf)

                insert(dcf, 'Other Table', 'Row', 'Value', self.attribute,
                                __name__, print_info = print_info)

        def method(self, dcf):
                '''Calculation performed by plugin. In this case the input information is only
                read and stored in an attribute.
                '''

                self.attribute = dcf.inp['Table']['Row']['Value']

In this example, the plugin reads information from Table > Row > Value, processes it by applying the process_table() function (which ensures that references are resolved) and it runs self.method(dcf), during which it stores the input information in an attribute self.attribute. Finally, self.attribute is inserted into dcf.inp in a new location: Other Table > Row > Value.

With this pattern, plugins can process information from other plugins which ran before it in the Workflow (determined by the Workflow position) and plugins running after it can use the information inserted in to dcf.inp.

It is important to include the numpydoc formatted docstring, since it is used to generate the the input file template.