Skip to content

load_budget should not modify class

Currently in the code for load_budget, the yaml file is loaded and the class is modified!

    Budget = getattr(mod, bname)
    ifopath = os.path.join(modpath, 'ifo.yaml')
    if not ifo and os.path.exists(ifopath):
        ifo = Struct.from_file(ifopath)
    Budget.ifo = ifo

This means a single class cannot reasonably be loaded from multiple yaml files without being confusing. It is already a bit confusing as a user needs to know to create instances before modifying the B.ifo parameter, or all future instances will be modified.

Two options to remedy:

use the type(name, bases, dict) metaclass/metafunction to dynamically subclass from the desired Budget class, the loaded ifo can be passed as an attribute during the dynamic subclass creation. This looks like

    Budget = getattr(mod, bname)
    ifopath = os.path.join(modpath, 'ifo.yaml')
    if not ifo and os.path.exists(ifopath):
        ifo = Struct.from_file(ifopath)
    Budget2 = type(name_or_path, (Budget,), {"ifo" : ifo})
    return Budget2

Or (my preference)

since load_budget is acting as an object factory, I don't see why it shouldn't also take the *args, **kwargs and return the instance directly. Is there anything useful that comes from returning the Budget class as an intermediary?

    Budget = getattr(mod, bname)
    ifopath = os.path.join(modpath, 'ifo.yaml')
    b = Budget(*args, **kwargs)
    b.ifo = Struct.from_file(ifopath)
    return b