import os
import shutil
import tempfile
import time
from .createpackages import create_packages
thisfilepath = os.path.dirname(os.path.abspath(__file__))
flopypth = os.path.join(thisfilepath, "..", "..")
flopypth = os.path.abspath(flopypth)
protected_dfns = ["flopy.dfn"]
[docs]def delete_files(files, pth, allow_failure=False, exclude=None):
if exclude is None:
exclude = []
else:
if not isinstance(exclude, list):
exclude = [exclude]
for fn in files:
if fn in exclude:
continue
fpth = os.path.join(pth, fn)
try:
print(f" removing...{fn}")
os.remove(fpth)
except:
print(f"could not remove...{fn}")
if not allow_failure:
return False
return True
[docs]def list_files(pth, exts=["py"]):
print(f"\nLIST OF FILES IN {pth}")
files = [
entry
for entry in os.listdir(pth)
if os.path.isfile(os.path.join(pth, entry))
]
idx = 0
for fn in files:
ext = os.path.splitext(fn)[1][1:].lower()
if ext in exts:
idx += 1
print(f" {idx:5d} - {fn}")
return
[docs]def download_dfn(branch, new_dfn_pth):
pymake = None
try:
import pymake
except:
pass
if pymake is None:
msg = (
"Error. The pymake package must be installed in order to "
"generate the MODFLOW 6 classes. pymake can be installed using "
"pip install pymake. Stopping."
)
print(msg)
return
mf6url = "https://github.com/MODFLOW-USGS/modflow6/archive/{}.zip"
mf6url = mf6url.format(branch)
print(f" Downloading MODFLOW 6 repository from {mf6url}")
with tempfile.TemporaryDirectory() as tmpdirname:
pymake.download_and_unzip(mf6url, tmpdirname)
downloaded_dfn_pth = os.path.join(tmpdirname, f"modflow6-{branch}")
downloaded_dfn_pth = os.path.join(
downloaded_dfn_pth, "doc", "mf6io", "mf6ivar", "dfn"
)
shutil.copytree(downloaded_dfn_pth, new_dfn_pth)
return
[docs]def backup_existing_dfns(flopy_dfn_path):
parent_folder = os.path.dirname(flopy_dfn_path)
timestr = time.strftime("%Y%m%d-%H%M%S")
backup_folder = os.path.join(parent_folder, "dfn_backup", timestr)
shutil.copytree(flopy_dfn_path, backup_folder)
assert os.path.isdir(
backup_folder
), f"dfn backup files not found: {backup_folder}"
return
[docs]def replace_dfn_files(new_dfn_pth, flopy_dfn_path):
# remove the old files, unless the file is protected
filenames = os.listdir(flopy_dfn_path)
delete_files(filenames, flopy_dfn_path, exclude=protected_dfns)
# copy the new ones into the folder
filenames = os.listdir(new_dfn_pth)
for filename in filenames:
filename_w_path = os.path.join(new_dfn_pth, filename)
print(f" copying..{filename}")
shutil.copy(filename_w_path, flopy_dfn_path)
[docs]def delete_mf6_classes():
pth = os.path.join(flopypth, "mf6", "modflow")
files = [
entry
for entry in os.listdir(pth)
if os.path.isfile(os.path.join(pth, entry))
]
delete_files(files, pth, exclude="mfsimulation.py")
return
[docs]def generate_classes(branch="master", dfnpath=None, backup=True):
"""
Generate the MODFLOW 6 flopy classes using definition files from the
MODFLOW 6 GitHub repository or a set of definition files in a folder
provided by the user.
Parameters
----------
branch : str
Branch name of the MODFLOW 6 repository to use to update the
definition files and generate the MODFLOW 6 classes. Default is master.
dfnpath : str
Path to a definition file folder that will be used to generate the
MODFLOW 6 classes. Default is none, which means that the branch
will be used instead. dfnpath will take precedence over branch
if dfnpath is specified.
backup : bool
Keep a backup of the definition files in dfn_backup with a date and
time stamp from when the definition files were replaced.
"""
# print header
print(2 * "\n")
print(72 * "*")
print("Updating the flopy MODFLOW 6 classes")
flopy_dfn_path = os.path.join(flopypth, "mf6", "data", "dfn")
# download the dfn files and put them in flopy.mf6.data or update using
# user provided dfnpath
if dfnpath is None:
print(f" Updating the MODFLOW 6 classes using the branch: {branch}")
timestr = time.strftime("%Y%m%d-%H%M%S")
new_dfn_pth = os.path.join(flopypth, "mf6", "data", f"dfn_{timestr}")
download_dfn(branch, new_dfn_pth)
else:
print(f" Updating the MODFLOW 6 classes using {dfnpath}")
assert os.path.isdir(dfnpath)
new_dfn_pth = dfnpath
if backup:
print(f" Backup existing definition files in: {flopy_dfn_path}")
backup_existing_dfns(flopy_dfn_path)
print(" Replacing existing definition files with new ones.")
replace_dfn_files(new_dfn_pth, flopy_dfn_path)
if dfnpath is None:
shutil.rmtree(new_dfn_pth)
print(" Deleting existing mf6 classes.")
delete_mf6_classes()
print(" Create mf6 classes using the downloaded definition files.")
create_packages()
list_files(os.path.join(flopypth, "mf6", "modflow"))
return