def create_packages():
    indent = "    "
    init_string_def = "    def __init__(self"

    # load JSON file
    file_structure = mfstructure.MFStructure(load_from_dfn_files=True)
    sim_struct = file_structure.sim_struct

    # assemble package list of buildable packages
    package_list = []
    package_list.append((
        sim_struct.name_file_struct_obj,
        PackageLevel.sim_level,
        "",
        sim_struct.name_file_struct_obj.dfn_list,
        sim_struct.name_file_struct_obj.file_type,
    ))
    for package in sim_struct.package_struct_objs.values():
        # add simulation level package to list
        package_list.append((
            package,
            PackageLevel.sim_level,
            "",
            package.dfn_list,
            package.file_type,
        ))
    for package in sim_struct.utl_struct_objs.values():
        # add utility packages to list
        package_list.append((
            package,
            PackageLevel.model_level,
            "utl",
            package.dfn_list,
            package.file_type,
        ))
    for model_key, model in sim_struct.model_struct_objs.items():
        package_list.append((
            model.name_file_struct_obj,
            PackageLevel.model_level,
            model_key,
            model.name_file_struct_obj.dfn_list,
            model.name_file_struct_obj.file_type,
        ))
        for package in model.package_struct_objs.values():
            package_list.append((
                package,
                PackageLevel.model_level,
                model_key,
                package.dfn_list,
                package.file_type,
            ))

    util_path, tail = os.path.split(os.path.realpath(__file__))
    init_file = io.open(
        os.path.join(util_path, "..", "modflow", "__init__.py"),
        "w",
        newline="\n",
    )
    init_file.write("# imports\n")
    init_file.write("from .mfsimulation import MFSimulation\n")

    nam_import_string = (
        "from .. import mfmodel\nfrom ..data.mfdatautil "
        "import ListTemplateGenerator, ArrayTemplateGenerator")

    # loop through packages list
    for package in package_list:
        data_structure_dict = {}
        package_properties = []
        init_vars = []
        init_param_list = []
        set_param_list = []
        class_vars = []
        template_gens = []
        dfn_string = build_dfn_string(package[3])
        package_abbr = clean_class_string("{}{}".format(
            clean_class_string(package[2]), package[0].file_type)).lower()
        package_name = clean_class_string("{}{}{}".format(
            clean_class_string(package[2]),
            package[0].file_prefix,
            package[0].file_type,
        )).lower()
        if package[0].description:
            doc_string = mfdatautil.MFDocString(package[0].description)
        else:
            if package[2]:
                package_container_text = " within a {} model".format(
                    package[2])
            else:
                package_container_text = ""
            ds = "Modflow{} defines a {} package" "{}.".format(
                package_name.title(),
                package[0].file_type,
                package_container_text,
            )
            if package[0].file_type == "mvr":
                # mvr package warning
                if package[2]:
                    ds = ("{} This package\n    can only be used to move "
                          "water between packages within a single model."
                          "\n    To move water between models use ModflowMvr"
                          ".".format(ds))
                else:
                    ds = ("{} This package can only be used to move\n    "
                          "water between two different models. To move "
                          "water between two packages\n    in the same "
                          'model use the "model level" mover package (ex. '
                          "ModflowGwfmvr).".format(ds))

            doc_string = mfdatautil.MFDocString(ds)

        if package[0].dfn_type == mfstructure.DfnType.exch_file:
            add_var(
                init_vars,
                None,
                init_param_list,
                package_properties,
                doc_string,
                data_structure_dict,
                None,
                "exgtype",
                "exgtype",
                build_doc_string(
                    "exgtype",
                    "<string>",
                    "is the exchange type (GWF-GWF or "
                    "GWF-GWT).",
                    indent,
                ),
                None,
                None,
                True,
            )
            add_var(
                init_vars,
                None,
                init_param_list,
                package_properties,
                doc_string,
                data_structure_dict,
                None,
                "exgmnamea",
                "exgmnamea",
                build_doc_string(
                    "exgmnamea",
                    "<string>",
                    "is the name of the first model that is "
                    "part of this exchange.",
                    indent,
                ),
                None,
                None,
                True,
            )
            add_var(
                init_vars,
                None,
                init_param_list,
                package_properties,
                doc_string,
                data_structure_dict,
                None,
                "exgmnameb",
                "exgmnameb",
                build_doc_string(
                    "exgmnameb",
                    "<string>",
                    "is the name of the second model that is "
                    "part of this exchange.",
                    indent,
                ),
                None,
                None,
                True,
            )
            init_vars.append(
                "        simulation.register_exchange_file(self)\n")

        # loop through all blocks
        for block in package[0].blocks.values():
            for data_structure in block.data_structures.values():
                # only create one property for each unique data structure name
                if data_structure.name not in data_structure_dict:
                    tg = add_var(
                        init_vars,
                        class_vars,
                        init_param_list,
                        package_properties,
                        doc_string,
                        data_structure_dict,
                        data_structure.default_value,
                        data_structure.name,
                        data_structure.python_name,
                        data_structure.get_doc_string(79, indent, indent),
                        data_structure.path,
                        data_structure.get_datatype(),
                        False,
                        data_structure.construct_package,
                        data_structure.construct_data,
                        data_structure.parameter_name,
                        set_param_list,
                    )
                    if tg is not None and tg not in template_gens:
                        template_gens.append(tg)

        import_string = "from .. import mfpackage"
        if template_gens:
            import_string = "{}\nfrom ..data.mfdatautil import" " ".format(
                import_string)
            first_string = True
            for template in template_gens:
                if first_string:
                    import_string = "{}{}".format(import_string, template)
                    first_string = False
                else:
                    import_string = "{}, {}".format(import_string, template)
        # add extra docstrings for additional variables
        doc_string.add_parameter("    filename : String\n        "
                                 "File name for this package.")
        doc_string.add_parameter("    pname : String\n        "
                                 "Package name for this package.")
        doc_string.add_parameter("    parent_file : MFPackage\n        "
                                 "Parent package file that references this "
                                 "package. Only needed for\n        utility "
                                 "packages (mfutl*). For example, mfutllaktab "
                                 "package must have \n        a mfgwflak "
                                 "package parent_file.")

        # build package builder class string
        init_vars.append("        self._init_complete = True")
        init_vars = "\n".join(init_vars)
        package_short_name = clean_class_string(package[0].file_type).lower()
        class_def_string = "class Modflow{}(mfpackage.MFPackage):\n".format(
            package_name.title())
        class_def_string = class_def_string.replace("-", "_")
        class_var_string = ('{}\n    package_abbr = "{}"\n    _package_type = '
                            '"{}"\n    dfn_file_name = "{}"'
                            "\n".format(
                                "\n".join(class_vars),
                                package_abbr,
                                package[4],
                                package[0].dfn_file_name,
                            ))
        init_string_full = init_string_def
        init_string_model = "{}, simulation".format(init_string_def)
        # add variables to init string
        doc_string.add_parameter(
            "    loading_package : bool\n        "
            "Do not set this parameter. It is intended "
            "for debugging and internal\n        "
            "processing purposes only.",
            beginning_of_list=True,
        )
        if package[1] == PackageLevel.sim_level:
            doc_string.add_parameter(
                "    simulation : MFSimulation\n        "
                "Simulation that this package is a part "
                "of. Package is automatically\n        "
                "added to simulation when it is "
                "initialized.",
                beginning_of_list=True,
            )
            init_string_full = ("{}, simulation, loading_package="
                                "False".format(init_string_full))
        else:
            doc_string.add_parameter(
                "    model : MFModel\n        "
                "Model that this package is a part of.  "
                "Package is automatically\n        added "
                "to model when it is initialized.",
                beginning_of_list=True,
            )
            init_string_full = "{}, model, loading_package=False".format(
                init_string_full)
        init_param_list.append("filename=None")
        init_param_list.append("pname=None")
        init_param_list.append("parent_file=None")
        init_string_full = build_init_string(init_string_full, init_param_list)

        # build init code
        if package[1] == PackageLevel.sim_level:
            init_var = "simulation"
        else:
            init_var = "model"
        parent_init_string = ("        super(Modflow{}, self)"
                              ".__init__(".format(package_name.title()))
        spaces = " " * len(parent_init_string)
        parent_init_string = ('{}{}, "{}", filename, pname,\n{}'
                              "loading_package, parent_file)\n\n"
                              "        # set up variables".format(
                                  parent_init_string, init_var,
                                  package_short_name, spaces))
        local_datetime = datetime.datetime.now(datetime.timezone.utc)
        comment_string = (
            "# DO NOT MODIFY THIS FILE DIRECTLY.  THIS FILE " +
            "MUST BE CREATED BY\n# mf6/utils/createpackages.py\n# FILE " +
            "created on {} UTC".format(
                local_datetime.strftime("%B %d, %Y %H:%M:%S")))
        # assemble full package string
        package_string = "{}\n{}\n\n\n{}{}\n{}\n{}\n\n{}{}\n{}\n".format(
            comment_string,
            import_string,
            class_def_string,
            doc_string.get_doc_string(),
            class_var_string,
            dfn_string,
            init_string_full,
            parent_init_string,
            init_vars,
        )

        # open new Packages file
        pb_file = io.open(
            os.path.join(util_path, "..", "modflow",
                         "mf{}.py".format(package_name)),
            "w",
            newline="\n",
        )
        pb_file.write(package_string)

        if package[2] == "utl" and package_abbr != "utltab":
            set_param_list.append("filename=filename")
            set_param_list.append("pname=pname")
            set_param_list.append("parent_file=self._cpparent")
            whsp_1 = "                   "
            whsp_2 = "                                    "

            chld_doc_string = ('    """\n    Utl{}Packages is a container '
                               "class for the ModflowUtl{} class.\n\n    "
                               "Methods\n    ----------"
                               "\n".format(package_short_name,
                                           package_short_name))

            # write out child packages class
            chld_cls = ("\n\nclass Utl{}Packages(mfpackage.MFChildPackage"
                        "s):\n".format(package_short_name))
            chld_var = '    package_abbr = "utl{}packages"\n\n'.format(
                package_short_name)
            chld_init = "    def initialize(self"
            chld_init = build_init_string(chld_init, init_param_list[:-1],
                                          whsp_1)
            init_pkg = "\n        self._init_package(new_package, filename)"
            params_init = ("        new_package = ModflowUtl{}("
                           "self._model".format(package_short_name))
            params_init = build_init_string(params_init, set_param_list,
                                            whsp_2)
            chld_doc_string = ("{}    initialize\n        Initializes a new "
                               "ModflowUtl{} package removing any sibling "
                               "child\n        packages attached to the same "
                               "parent package. See ModflowUtl{} init\n "
                               "       documentation for definition of "
                               "parameters.\n".format(chld_doc_string,
                                                      package_short_name,
                                                      package_short_name))

            chld_appn = ""
            params_appn = ""
            append_pkg = ""
            if package_abbr != "utlobs":  # Hard coded obs no multi-pkg support
                chld_appn = "\n\n    def append_package(self"
                chld_appn = build_init_string(chld_appn, init_param_list[:-1],
                                              whsp_1)
                append_pkg = ("\n        self._append_package(new_package, "
                              "filename)")
                params_appn = ("        new_package = ModflowUtl{}("
                               "self._model".format(package_short_name))
                params_appn = build_init_string(params_appn, set_param_list,
                                                whsp_2)
                chld_doc_string = ("{}    append_package\n        Adds a "
                                   "new ModflowUtl{} package to the container."
                                   " See ModflowUtl{}\n        init "
                                   "documentation for definition of "
                                   "parameters.\n".format(
                                       chld_doc_string, package_short_name,
                                       package_short_name))
            chld_doc_string = '{}    """\n'.format(chld_doc_string)
            packages_str = "{}{}{}{}{}{}{}{}{}\n".format(
                chld_cls,
                chld_doc_string,
                chld_var,
                chld_init,
                params_init[:-2],
                init_pkg,
                chld_appn,
                params_appn[:-2],
                append_pkg,
            )
            pb_file.write(packages_str)
        pb_file.close()

        init_file.write("from .mf{} import "
                        "Modflow{}\n".format(package_name,
                                             package_name.title()))

        if package[0].dfn_type == mfstructure.DfnType.model_name_file:
            # build model file
            model_param_list = init_param_list[:-3]
            init_vars = build_model_init_vars(model_param_list)

            model_param_list.insert(0, "model_rel_path='.'")
            model_param_list.insert(0, "exe_name='mf6.exe'")
            model_param_list.insert(0, "version='mf6'")
            model_param_list.insert(0, "model_nam_file=None")
            model_param_list.insert(0, "modelname='model'")
            model_param_list.append("**kwargs")
            init_string_model = build_init_string(init_string_model,
                                                  model_param_list)
            model_name = clean_class_string(package[2])
            class_def_string = "class Modflow{}(mfmodel.MFModel):\n".format(
                model_name.capitalize())
            class_def_string = class_def_string.replace("-", "_")
            doc_string.add_parameter(
                "    sim : MFSimulation\n        "
                "Simulation that this model is a part "
                "of.  Model is automatically\n        "
                "added to simulation when it is "
                "initialized.",
                beginning_of_list=True,
                model_parameter=True,
            )
            doc_string.description = "Modflow{} defines a {} model".format(
                model_name, model_name)
            class_var_string = "    model_type = '{}'\n".format(model_name)
            mparent_init_string = ("        super(Modflow{}, self)"
                                   ".__init__(".format(
                                       model_name.capitalize()))
            spaces = " " * len(mparent_init_string)
            mparent_init_string = ("{}simulation, model_type='{}6',\n{}"
                                   "modelname=modelname,\n{}"
                                   "model_nam_file=model_nam_file,\n{}"
                                   "version=version, exe_name=exe_name,\n{}"
                                   "model_rel_path=model_rel_path,\n{}"
                                   "**kwargs"
                                   ")\n".format(
                                       mparent_init_string,
                                       model_name,
                                       spaces,
                                       spaces,
                                       spaces,
                                       spaces,
                                       spaces,
                                   ))
            load_txt, doc_text = build_model_load(model_name)
            package_string = "{}\n{}\n\n\n{}{}\n{}\n{}\n{}{}\n{}\n\n{}".format(
                comment_string,
                nam_import_string,
                class_def_string,
                doc_string.get_doc_string(True),
                doc_text,
                class_var_string,
                init_string_model,
                mparent_init_string,
                init_vars,
                load_txt,
            )
            md_file = io.open(
                os.path.join(util_path, "..", "modflow",
                             "mf{}.py".format(model_name)),
                "w",
                newline="\n",
            )
            md_file.write(package_string)
            md_file.close()
            init_file.write("from .mf{} import "
                            "Modflow{}\n".format(model_name,
                                                 model_name.capitalize()))
    init_file.close()
Exemple #2
0
def create_packages():
    init_string_def = '    def __init__(self'

    # load JSON file
    file_structure = mfstructure.MFStructure()
    sim_struct = file_structure.sim_struct
    # package_plot_dictionary = file_structure.package_plot_dictionary

    # assemble package list of buildable packages
    package_list = []
    package_list.append(
        (sim_struct.name_file_struct_obj, PackageLevel.sim_level, ''))
    for key, package in sim_struct.package_struct_objs.items():
        # add simulation level package to list
        package_list.append((package, PackageLevel.sim_level, ''))
    for key, package in sim_struct.utl_struct_objs.items():
        # add utility packages to list
        package_list.append((package, PackageLevel.model_level, 'utl'))
    for model_key, model in sim_struct.model_struct_objs.items():
        package_list.append(
            (model.name_file_struct_obj, PackageLevel.model_level, model_key))
        for key, package in model.package_struct_objs.items():
            package_list.append((package, PackageLevel.model_level, model_key))

    util_path, tail = os.path.split(os.path.realpath(__file__))
    init_file = open(os.path.join(util_path, '..', 'modflow', '__init__.py'),
                     'w')
    init_file.write('# imports\n')

    # loop through packages list
    for package in package_list:
        data_structure_dict = {}
        plotters = []
        plotter_defs = []
        package_properties = []
        init_vars = []
        init_param_list = []
        class_vars = []
        package_name = clean_class_string('{}{}'.format(
            clean_class_string(package[2]), package[0].file_type)).lower()
        if package[0].description:
            doc_string = mfdatautil.MFDocString(package[0].description)
        else:
            if package[2]:
                package_container_text = ' within a {} model'.format(
                    package[2])
            else:
                package_container_text = ''
            doc_string = mfdatautil.MFDocString(
                'Modflow{} defines a {} package'
                '{}.'.format(package_name.title(), package[0].file_type,
                             package_container_text))
        import_string = 'from .. import mfpackage\nfrom ..data import mfdatautil'

        if package[0].dfn_type == mfstructure.DfnType.exch_file:
            add_var(init_vars, None, init_param_list, package_properties,
                    doc_string, data_structure_dict, 'exgtype', 'exgtype',
                    '<string>', 'is the exchange type (GWF-GWF or GWF-GWT).',
                    None, None, True)
            add_var(
                init_vars, None, init_param_list, package_properties,
                doc_string, data_structure_dict, 'exgmnamea', 'exgmnamea',
                '<string>',
                'is the name of the first model that is part of this exchange.',
                None, None, True)
            add_var(
                init_vars, None, init_param_list, package_properties,
                doc_string, data_structure_dict, 'exgmnameb', 'exgmnameb',
                '<string>',
                'is the name of the second model that is part of this exchange.',
                None, None, True)
            init_vars.append(
                '        simulation.register_exchange_file(self)\n')

        # loop through all blocks
        for bl_key, block in package[0].blocks.items():
            for ds_key, data_structure in block.data_structures.items():
                # only create one property for each unique data structure name
                if data_structure.name not in data_structure_dict:
                    add_var(init_vars, class_vars, init_param_list,
                            package_properties, doc_string,
                            data_structure_dict, data_structure.name,
                            data_structure.python_name,
                            data_structure.get_type_string(),
                            data_structure.get_description(),
                            data_structure.path, data_structure.get_datatype())

        # build package builder class string
        init_vars = '\n'.join(init_vars)
        plotters_string = ''.join(plotters)
        plotters_def_string = '\n'.join(plotter_defs)
        package_short_name = clean_class_string(package[0].file_type).lower()
        class_def_string = 'class Modflow{}(mfpackage.MFPackage):\n'.format(
            package_name.title())
        class_def_string = class_def_string.replace('-', '_')
        class_var_string = '{}\n    package_abbr = "{}"'.format(
            '\n'.join(class_vars), package_name)
        line_chars = len(init_string_def)
        init_string_full = init_string_def
        # add variables to init string
        if package[1] == PackageLevel.sim_level:
            init_string_full = '{}, simulation, add_to_package_list=True'.format(
                init_string_full)
        else:
            init_string_full = '{}, model, add_to_package_list=True'.format(
                init_string_full)
        init_param_list.append('fname=None')
        init_param_list.append('pname=None')
        init_param_list.append('parent_file=None')
        for param in init_param_list:
            line_chars += len(param) + 1
            if line_chars > 80:
                init_string_full = '{},\n                 {}'.format(
                    init_string_full, param)
                line_chars = len(param) + 1
            else:
                init_string_full = '{}, {}'.format(init_string_full, param)
        init_string_full = '{}):\n'.format(init_string_full)

        # build init code
        if package[1] == PackageLevel.sim_level:
            init_var = 'simulation'
        else:
            init_var = 'model'
        parent_init_string = '        super(Modflow{}, self).__init__({}, "{}", fname, pname, add_to_package_list,' \
                             ' parent_file)        \n\n' \
                             '        # set up variables'.format(
            package_name.title(), init_var, package_short_name)

        # assemble full package string
        package_string = '{}\n\n\n{}{}\n{}\n\n{}{}{}\n{}\n\n{}'.format(
            import_string, class_def_string, doc_string.get_doc_string(),
            class_var_string, init_string_full, parent_init_string,
            plotters_string, init_vars, plotters_def_string)

        # open new Packages file
        pb_file = open(
            os.path.join(util_path, '..', 'modflow',
                         'mf{}.py'.format(package_name)), 'w')
        pb_file.write(package_string)
        pb_file.close()

        init_file.write('from .mf{} import Modflow{}\n'.format(
            package_name, package_name.title()))
    init_file.close()
def create_packages():
    indent = '    '
    init_string_def = '    def __init__(self'

    # load JSON file
    file_structure = mfstructure.MFStructure(load_from_dfn_files=True)
    sim_struct = file_structure.sim_struct

    # assemble package list of buildable packages
    package_list = []
    package_list.append(
        (sim_struct.name_file_struct_obj, PackageLevel.sim_level, '',
         sim_struct.name_file_struct_obj.dfn_list,
         sim_struct.name_file_struct_obj.file_type))
    for package in sim_struct.package_struct_objs.values():
        # add simulation level package to list
        package_list.append((package, PackageLevel.sim_level, '',
                             package.dfn_list, package.file_type))
    for package in sim_struct.utl_struct_objs.values():
        # add utility packages to list
        package_list.append((package, PackageLevel.model_level, 'utl',
                             package.dfn_list, package.file_type))
    for model_key, model in sim_struct.model_struct_objs.items():
        package_list.append(
            (model.name_file_struct_obj, PackageLevel.model_level, model_key,
             model.name_file_struct_obj.dfn_list,
             model.name_file_struct_obj.file_type))
        for package in model.package_struct_objs.values():
            package_list.append((package, PackageLevel.model_level,
                                 model_key, package.dfn_list,
                                 package.file_type))

    util_path, tail = os.path.split(os.path.realpath(__file__))
    init_file = open(os.path.join(util_path, '..', 'modflow', '__init__.py'),
                     'w')
    init_file.write('# imports\n')
    init_file.write('from .mfsimulation import MFSimulation\n')

    nam_import_string = 'from .. import mfmodel\nfrom ..data.mfdatautil ' \
                        'import ListTemplateGenerator, ArrayTemplateGenerator'

    # loop through packages list
    for package in package_list:
        data_structure_dict = {}
        package_properties = []
        init_vars = []
        init_param_list = []
        set_param_list = []
        class_vars = []
        template_gens = []
        dfn_string = build_dfn_string(package[3])
        package_abbr = clean_class_string(
            '{}{}'.format(clean_class_string(package[2]),
                            package[0].file_type)).lower()
        package_name = clean_class_string(
            '{}{}{}'.format(clean_class_string(package[2]),
                            package[0].file_prefix,
                            package[0].file_type)).lower()
        if package[0].description:
            doc_string = mfdatautil.MFDocString(package[0].description)
        else:
            if package[2]:
                package_container_text = ' within a {} model'.format(
                    package[2])
            else:
                package_container_text = ''
            doc_string = mfdatautil.MFDocString(
                'Modflow{} defines a {} package'
                '{}.'.format(package_name.title(),
                             package[0].file_type,
                             package_container_text))

        if package[0].dfn_type == mfstructure.DfnType.exch_file:
            add_var(init_vars, None, init_param_list, package_properties,
                    doc_string, data_structure_dict, None,
                    'exgtype', 'exgtype',
                    build_doc_string('exgtype', '<string>',
                                     'is the exchange type (GWF-GWF or '
                                     'GWF-GWT).', indent), None, None, True)
            add_var(init_vars, None, init_param_list, package_properties,
                    doc_string, data_structure_dict, None,
                    'exgmnamea', 'exgmnamea',
                    build_doc_string('exgmnamea', '<string>',
                                     'is the name of the first model that is '
                                     'part of this exchange.', indent),
                    None, None, True)
            add_var(init_vars, None, init_param_list, package_properties,
                    doc_string, data_structure_dict, None,
                    'exgmnameb', 'exgmnameb',
                    build_doc_string('exgmnameb', '<string>',
                                     'is the name of the second model that is '
                                     'part of this exchange.', indent),
                    None, None, True)
            init_vars.append(
                '        simulation.register_exchange_file(self)\n')

        # loop through all blocks
        for block in package[0].blocks.values():
            for data_structure in block.data_structures.values():
                # only create one property for each unique data structure name
                if data_structure.name not in data_structure_dict:
                    tg = add_var(
                        init_vars, class_vars, init_param_list,
                        package_properties, doc_string, data_structure_dict,
                        data_structure.default_value, data_structure.name,
                        data_structure.python_name,
                        data_structure.get_doc_string(79, indent, indent),
                        data_structure.path, data_structure.get_datatype(),
                        False, data_structure.construct_package,
                        data_structure.construct_data,
                        data_structure.parameter_name, set_param_list)
                    if tg is not None and tg not in template_gens:
                        template_gens.append(tg)

        import_string = 'from .. import mfpackage'
        if template_gens:
            import_string = '{}\nfrom ..data.mfdatautil import' \
                            ' '.format(import_string)
            first_string = True
            for template in template_gens:
                if first_string:
                    import_string = '{}{}'.format(import_string, template)
                    first_string = False
                else:
                    import_string = '{}, {}'.format(import_string, template)
        # add extra docstrings for additional variables
        doc_string.add_parameter('    filename : String\n        '
                                 'File name for this package.')
        doc_string.add_parameter('    pname : String\n        '
                                 'Package name for this package.')
        doc_string.add_parameter('    parent_file : MFPackage\n        '
                                 'Parent package file that references this '
                                 'package. Only needed for\n        utility '
                                 'packages (mfutl*). For example, mfutllaktab '
                                 'package must have \n        a mfgwflak '
                                 'package parent_file.')

        # build package builder class string
        init_vars.append('        self._init_complete = True')
        init_vars = '\n'.join(init_vars)
        package_short_name = clean_class_string(package[0].file_type).lower()
        class_def_string = 'class Modflow{}(mfpackage.MFPackage):\n'.format(
            package_name.title())
        class_def_string = class_def_string.replace('-', '_')
        class_var_string = '{}\n    package_abbr = "{}"\n    _package_type = ' \
                           '"{}"\n    dfn_file_name = "{}"' \
                           '\n'.format('\n'.join(class_vars), package_abbr,
                                       package[4], package[0].dfn_file_name)
        init_string_full = init_string_def
        init_string_model = '{}, simulation'.format(init_string_def)
        # add variables to init string
        doc_string.add_parameter('    loading_package : bool\n        '
                                 'Do not set this parameter. It is intended '
                                 'for debugging and internal\n        '
                                 'processing purposes only.',
                                 beginning_of_list=True)
        if package[1] == PackageLevel.sim_level:
            doc_string.add_parameter('    simulation : MFSimulation\n        '
                                     'Simulation that this package is a part '
                                     'of. Package is automatically\n        '
                                     'added to simulation when it is '
                                     'initialized.', beginning_of_list=True)
            init_string_full = '{}, simulation, loading_package=' \
                               'False'.format(init_string_full)
        else:
            doc_string.add_parameter('    model : MFModel\n        '
                                     'Model that this package is a part of.  '
                                     'Package is automatically\n        added '
                                     'to model when it is initialized.',
                                     beginning_of_list=True)
            init_string_full = '{}, model, loading_package=False'.format(
                init_string_full)
        init_param_list.append('filename=None')
        init_param_list.append('pname=None')
        init_param_list.append('parent_file=None')
        init_string_full = build_init_string(init_string_full, init_param_list)

        # build init code
        if package[1] == PackageLevel.sim_level:
            init_var = 'simulation'
        else:
            init_var = 'model'
        parent_init_string = '        super(Modflow{}, self)' \
                             '.__init__('.format(package_name.title())
        spaces = ' ' * len(parent_init_string)
        parent_init_string = '{}{}, "{}", filename, pname,\n{}' \
                             'loading_package, parent_file)\n\n' \
                             '        # set up variables'.format(
            parent_init_string, init_var, package_short_name, spaces)
        comment_string = '# DO NOT MODIFY THIS FILE DIRECTLY.  THIS FILE ' \
                         'MUST BE CREATED BY\n# mf6/utils/createpackages.py'
        # assemble full package string
        package_string = '{}\n{}\n\n\n{}{}\n{}\n{}\n\n{}{}\n{}\n'.format(
            comment_string, import_string, class_def_string,
            doc_string.get_doc_string(), class_var_string, dfn_string,
            init_string_full, parent_init_string, init_vars)

        # open new Packages file
        pb_file = open(os.path.join(util_path, '..', 'modflow',
                                    'mf{}.py'.format(package_name)), 'w')
        pb_file.write(package_string)

        if package[2] == 'utl' and package_abbr != 'utltab':
            set_param_list.append('filename=filename')
            set_param_list.append('pname=pname')
            set_param_list.append('parent_file=self._cpparent')
            whsp_1 = '                   '
            whsp_2 = '                                    '

            chld_doc_string = '    """\n    Utl{}Packages is a container ' \
                              'class for the ModflowUtl{} class.\n\n    ' \
                              'Methods\n    ----------' \
                              '\n'.format(package_short_name,
                                          package_short_name)

            # write out child packages class
            chld_cls = '\n\nclass Utl{}Packages(mfpackage.MFChildPackage' \
                         's):\n'.format(package_short_name)
            chld_var = '    package_abbr = "utl{}packages"\n\n'.format(
                package_short_name)
            chld_init = '    def initialize(self'
            chld_init = build_init_string(chld_init, init_param_list[:-1],
                                          whsp_1)
            init_pkg = '\n        self._init_package(new_package, filename)'
            params_init = '        new_package = ModflowUtl{}(' \
                          'self._model'.format(package_short_name)
            params_init = build_init_string(params_init, set_param_list, whsp_2)
            chld_doc_string = '{}    initialize\n        Initializes a new ' \
                              'ModflowUtl{} package removing any sibling ' \
                              'child\n        packages attached to the same ' \
                              'parent package. See ModflowUtl{} init\n ' \
                              '       documentation for definition of ' \
                              'parameters.\n'.format(chld_doc_string,
                                                     package_short_name,
                                                     package_short_name)

            chld_appn = ''
            params_appn = ''
            append_pkg = ''
            if package_abbr != 'utlobs':  # Hard coded obs no multi-pkg support
                chld_appn = '\n\n    def append_package(self'
                chld_appn = build_init_string(chld_appn, init_param_list[:-1],
                                              whsp_1)
                append_pkg = '\n        self._append_package(new_package, ' \
                             'filename)'
                params_appn = '        new_package = ModflowUtl{}(' \
                              'self._model'.format(package_short_name)
                params_appn = build_init_string(params_appn, set_param_list,
                                                whsp_2)
                chld_doc_string = '{}    append_package\n        Adds a ' \
                                  'new ModflowUtl{} package to the container.' \
                                  ' See ModflowUtl{}\n        init ' \
                                  'documentation for definition of ' \
                                  'parameters.\n'.format(chld_doc_string,
                                                         package_short_name,
                                                         package_short_name)
            chld_doc_string = '{}    """\n'.format(chld_doc_string)
            packages_str = '{}{}{}{}{}{}{}{}{}\n'.format(chld_cls,
                                                         chld_doc_string,
                                                         chld_var, chld_init,
                                                         params_init[:-2],
                                                         init_pkg, chld_appn,
                                                         params_appn[:-2],
                                                         append_pkg,)
            pb_file.write(packages_str)
        pb_file.close()

        init_file.write('from .mf{} import '
                        'Modflow{}\n'.format(package_name,
                                             package_name.title()))

        if package[0].dfn_type == mfstructure.DfnType.model_name_file:
            # build model file
            model_param_list = init_param_list[:-3]
            init_vars = build_model_init_vars(model_param_list)

            model_param_list.insert(0, "model_rel_path='.'")
            model_param_list.insert(0, "exe_name='mf6.exe'")
            model_param_list.insert(0, "version='mf6'")
            model_param_list.insert(0, 'model_nam_file=None')
            model_param_list.insert(0, "modelname='model'")
            model_param_list.append("**kwargs")
            init_string_model = build_init_string(init_string_model,
                                                  model_param_list)
            model_name = clean_class_string(package[2])
            class_def_string = 'class Modflow{}(mfmodel.MFModel):\n'.format(
                model_name.capitalize())
            class_def_string = class_def_string.replace('-', '_')
            doc_string.add_parameter('    sim : MFSimulation\n        '
                                     'Simulation that this model is a part '
                                     'of.  Model is automatically\n        '
                                     'added to simulation when it is '
                                     'initialized.',
                                     beginning_of_list=True,
                                     model_parameter=True)
            doc_string.description = 'Modflow{} defines a {} model'.format(
                model_name, model_name)
            class_var_string = "    model_type = '{}'\n".format(model_name)
            mparent_init_string = '        super(Modflow{}, self)' \
                                 '.__init__('.format(model_name.capitalize())
            spaces = ' ' * len(mparent_init_string)
            mparent_init_string = "{}simulation, model_type='gwf6',\n{}" \
                                  "modelname=modelname,\n{}" \
                                  "model_nam_file=model_nam_file,\n{}" \
                                  "version=version, exe_name=exe_name,\n{}" \
                                  "model_rel_path=model_rel_path,\n{}" \
                                  "**kwargs" \
                                  ")\n".format(mparent_init_string, spaces,
                                               spaces, spaces, spaces, spaces)
            load_txt, doc_text = build_model_load('gwf')
            package_string = '{}\n{}\n\n\n{}{}\n{}\n{}\n{}{}\n{}\n\n{}'.format(
                comment_string, nam_import_string, class_def_string,
                doc_string.get_doc_string(True), doc_text, class_var_string,
                init_string_model, mparent_init_string, init_vars, load_txt)
            md_file = open(os.path.join(util_path, '..', 'modflow',
                           'mf{}.py'.format(model_name)),
                           'w')
            md_file.write(package_string)
            md_file.close()
            init_file.write('from .mf{} import '
                            'Modflow{}\n'.format(model_name,
                                                 model_name.capitalize()))
    init_file.close()
def create_packages():
    indent = '    '
    init_string_def = '    def __init__(self'

    # load JSON file
    file_structure = mfstructure.MFStructure(load_from_dfn_files=True)
    sim_struct = file_structure.sim_struct

    # assemble package list of buildable packages
    package_list = []
    package_list.append(
        (sim_struct.name_file_struct_obj, PackageLevel.sim_level, '',
         sim_struct.name_file_struct_obj.dfn_list,
         sim_struct.name_file_struct_obj.file_type))
    for key, package in sim_struct.package_struct_objs.items():
        # add simulation level package to list
        package_list.append((package, PackageLevel.sim_level, '',
                             package.dfn_list, package.file_type))
    for key, package in sim_struct.utl_struct_objs.items():
        # add utility packages to list
        package_list.append((package, PackageLevel.model_level, 'utl',
                             package.dfn_list, package.file_type))
    for model_key, model in sim_struct.model_struct_objs.items():
        package_list.append(
            (model.name_file_struct_obj, PackageLevel.model_level, model_key,
             model.name_file_struct_obj.dfn_list,
             model.name_file_struct_obj.file_type))
        for key, package in model.package_struct_objs.items():
            package_list.append((package, PackageLevel.model_level, model_key,
                                 package.dfn_list, package.file_type))

    util_path, tail = os.path.split(os.path.realpath(__file__))
    init_file = open(os.path.join(util_path, '..', 'modflow', '__init__.py'),
                     'w')
    init_file.write('# imports\n')

    # loop through packages list
    for package in package_list:
        data_structure_dict = {}
        package_properties = []
        init_vars = []
        init_param_list = []
        class_vars = []
        dfn_string = build_dfn_string(package[3])
        package_abbr = clean_class_string('{}{}'.format(
            clean_class_string(package[2]), package[0].file_type)).lower()
        package_name = clean_class_string('{}{}{}'.format(
            clean_class_string(package[2]), package[0].file_prefix,
            package[0].file_type)).lower()
        if package[0].description:
            doc_string = mfdatautil.MFDocString(package[0].description)
        else:
            if package[2]:
                package_container_text = ' within a {} model'.format(
                    package[2])
            else:
                package_container_text = ''
            doc_string = mfdatautil.MFDocString(
                'Modflow{} defines a {} package'
                '{}.'.format(package_name.title(), package[0].file_type,
                             package_container_text))
        import_string = 'from .. import mfpackage\nfrom ..data.mfdatautil ' \
                        'import ListTemplateGenerator, ArrayTemplateGenerator'

        if package[0].dfn_type == mfstructure.DfnType.exch_file:
            add_var(
                init_vars, None, init_param_list, package_properties,
                doc_string, data_structure_dict, None, 'exgtype', 'exgtype',
                build_doc_string(
                    'exgtype', '<string>', 'is the exchange type (GWF-GWF or '
                    'GWF-GWT).', indent), None, None, True)
            add_var(
                init_vars, None, init_param_list, package_properties,
                doc_string, data_structure_dict, None, 'exgmnamea',
                'exgmnamea',
                build_doc_string(
                    'exgmnamea', '<string>',
                    'is the name of the first model that is '
                    'part of this exchange.', indent), None, None, True)
            add_var(
                init_vars, None, init_param_list, package_properties,
                doc_string, data_structure_dict, None, 'exgmnameb',
                'exgmnameb',
                build_doc_string(
                    'exgmnameb', '<string>',
                    'is the name of the second model that is '
                    'part of this exchange.', indent), None, None, True)
            init_vars.append(
                '        simulation.register_exchange_file(self)\n')

        # loop through all blocks
        for bl_key, block in package[0].blocks.items():
            for ds_key, data_structure in block.data_structures.items():
                # only create one property for each unique data structure name
                if data_structure.name not in data_structure_dict:
                    add_var(init_vars, class_vars, init_param_list,
                            package_properties, doc_string,
                            data_structure_dict, data_structure.default_value,
                            data_structure.name, data_structure.python_name,
                            data_structure.get_doc_string(79, indent, indent),
                            data_structure.path, data_structure.get_datatype())

        # add extra docstrings for additional variables
        doc_string.add_parameter('    fname : String\n        '
                                 'File name for this package.')
        doc_string.add_parameter('    pname : String\n        '
                                 'Package name for this package.')
        doc_string.add_parameter('    parent_file : MFPackage\n        '
                                 'Parent package file that references this '
                                 'package. Only needed for\n        utility '
                                 'packages (mfutl*). For example, mfutllaktab '
                                 'package must have \n        a mfgwflak '
                                 'package parent_file.')

        # build package builder class string
        init_vars = '\n'.join(init_vars)
        package_short_name = clean_class_string(package[0].file_type).lower()
        class_def_string = 'class Modflow{}(mfpackage.MFPackage):\n'.format(
            package_name.title())
        class_def_string = class_def_string.replace('-', '_')
        class_var_string = '{}\n    package_abbr = "{}"\n    package_type = ' \
                           '"{}"\n    dfn_file_name = "{}"' \
                           '\n'.format('\n'.join(class_vars), package_abbr,
                                       package[4], package[0].dfn_file_name)
        init_string_full = init_string_def
        # add variables to init string
        doc_string.add_parameter(
            '    loading_package : bool\n        '
            'Do not set this parameter. It is intended '
            'for debugging and internal\n        '
            'processing purposes only.',
            beginning_of_list=True)
        if package[1] == PackageLevel.sim_level:
            doc_string.add_parameter(
                '    simulation : MFSimulation\n        '
                'Simulation that this package is a part '
                'of. Package is automatically\n        '
                'added to simulation when it is '
                'initialized.',
                beginning_of_list=True)
            init_string_full = '{}, simulation, loading_package=' \
                               'False'.format(init_string_full)
        else:
            doc_string.add_parameter(
                '    model : MFModel\n        '
                'Model that this package is a part of.  '
                'Package is automatically\n        added '
                'to model when it is initialized.',
                beginning_of_list=True)
            init_string_full = '{}, model, loading_package=False'.format(
                init_string_full)
        line_chars = len(init_string_full)
        init_param_list.append('fname=None')
        init_param_list.append('pname=None')
        init_param_list.append('parent_file=None')
        for index, param in enumerate(init_param_list):
            if index + 1 < len(init_param_list):
                line_chars += len(param) + 2
            else:
                line_chars += len(param) + 3
            if line_chars > 79:
                init_string_full = '{},\n                 {}'.format(
                    init_string_full, param)
                line_chars = len(param) + len('                 ') + 1
            else:
                init_string_full = '{}, {}'.format(init_string_full, param)
        init_string_full = '{}):\n'.format(init_string_full)

        # build init code
        if package[1] == PackageLevel.sim_level:
            init_var = 'simulation'
        else:
            init_var = 'model'
        parent_init_string = '        super(Modflow{}, self)' \
                             '.__init__('.format(package_name.title())
        spaces = ' ' * len(parent_init_string)
        parent_init_string = '{}{}, "{}", fname, pname,\n{}' \
                             'loading_package, parent_file)        \n\n' \
                             '        # set up variables'.format(
            parent_init_string, init_var, package_short_name, spaces)
        comment_string = '# DO NOT MODIFY THIS FILE DIRECTLY.  THIS FILE ' \
                         'MUST BE CREATED BY\n# mf6/utils/createpackages.py'
        # assemble full package string
        package_string = '{}\n{}\n\n\n{}{}\n{}\n{}\n\n{}{}\n{}\n'.format(
            comment_string, import_string, class_def_string,
            doc_string.get_doc_string(), class_var_string, dfn_string,
            init_string_full, parent_init_string, init_vars)

        # open new Packages file
        pb_file = open(
            os.path.join(util_path, '..', 'modflow',
                         'mf{}.py'.format(package_name)), 'w')
        pb_file.write(package_string)
        pb_file.close()

        init_file.write('from .mf{} import '
                        'Modflow{}\n'.format(package_name,
                                             package_name.title()))
    init_file.close()