Skip to content

Commit

Permalink
refactor(distscripts): use pathlib
Browse files Browse the repository at this point in the history
* use pathlib for path manipulations
* construct paths relative to script locn instead of cwd (allows running from project root)
  • Loading branch information
wpbonelli committed Oct 31, 2022
1 parent 5869d4a commit a591a0e
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 174 deletions.
65 changes: 31 additions & 34 deletions distribution/build_makefiles.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import sys
from contextlib import contextmanager
from pathlib import Path

import pymake

Expand All @@ -16,28 +17,31 @@
fc = sys.argv[idx + 1]

# if compiler not set by command line argument
# use environmental variable or set to default compiler (gfortran)
# use environment variable or set to default compiler (gfortran)
if fc is None:
if "FC" in os.environ:
fc = os.getenv("FC")
else:
fc = "gfortran"

# assumes this file is in <project root>/distribution
root_path = Path(__file__).parent.parent


@contextmanager
def cwd(path):
oldpwd = os.getcwd()
prev = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(oldpwd)
os.chdir(prev)


def run_makefile(target):
assert os.path.isfile(
assert Path(
"makefile"
), f"makefile does not exist in {os.getcwd()}"
).is_file(), f"makefile does not exist in {os.getcwd()}"

base_target = os.path.basename(target)
base_message = (
Expand All @@ -64,15 +68,13 @@ def run_makefile(target):
print(f"clean {base_target} with makefile")
os.system("make clean")

return


def build_mf6_makefile():
with cwd(os.path.join("..", "make")):
with cwd(root_path / "make"):
pm = pymake.Pymake()
pm.target = "mf6"
pm.srcdir = os.path.join("..", "src")
pm.appdir = os.path.join("..", "bin")
pm.srcdir = str(root_path / "src")
pm.appdir = str(root_path / "bin")
pm.include_subdirs = True
pm.inplace = True
pm.dryrun = True
Expand All @@ -85,16 +87,15 @@ def build_mf6_makefile():
msg = f"could not create makefile for '{pm.target}'."
assert pm.returncode == 0, msg

return


def build_zbud6_makefile():
with cwd(os.path.join("..", "utils", "zonebudget", "make")):
util_path = root_path / "utils" / "zonebudget"
with cwd(util_path / "make"):
pm = pymake.Pymake()
pm.target = "zbud6"
pm.srcdir = os.path.join("..", "src")
pm.appdir = os.path.join("..", "..", "..", "bin")
pm.extrafiles = os.path.join("..", "pymake", "extrafiles.txt")
pm.srcdir = str(util_path / "src")
pm.appdir = str(root_path / "bin")
pm.extrafiles = str(util_path / "pymake" / "extrafiles.txt")
pm.inplace = True
pm.makeclean = True
pm.dryrun = True
Expand All @@ -107,14 +108,13 @@ def build_zbud6_makefile():
msg = f"could not create makefile for '{pm.target}'."
assert pm.returncode == 0, msg

return


def build_mf5to6_makefile():
with cwd(os.path.join("..", "utils", "mf5to6", "make")):
srcdir = os.path.join("..", "src")
target = os.path.join("..", "..", "..", "bin", "mf5to6")
extrafiles = os.path.join("..", "pymake", "extrafiles.txt")
util_path = root_path / "utils" / "mf5to6"
with cwd(util_path / "make"):
srcdir = str(util_path / "src")
target = str(root_path / "bin" / "mf5to6")
extrafiles = str(util_path / "pymake" / "extrafiles.txt")

# build modflow 5 to 6 converter
returncode = pymake.main(
Expand All @@ -129,34 +129,31 @@ def build_mf5to6_makefile():
fflags="-fall-intrinsics",
)

msg = f"could not create makefile for '{os.path.basename(target)}'."
msg = f"could not create makefile for '{target}'."
assert returncode == 0, msg

return


def test_build_mf6_wmake():
target = os.path.join("..", "bin", f"mf6{ext}")
with cwd(os.path.join("..", "make")):
target = str(root_path / "bin" / f"mf6{ext}")
with cwd(root_path / "make"):
run_makefile(target)


def test_build_zbud6_wmake():
target = os.path.join("..", "..", "..", "bin", f"zbud6{ext}")
with cwd(os.path.join("..", "utils", "zonebudget", "make")):
target = str(root_path / "bin" / f"zbud6{ext}")
util_path = root_path / "utils" / "zonebudget"
with cwd(util_path / "make"):
run_makefile(target)


def test_build_mf5to6_wmake():
target = os.path.join("..", "..", "..", "bin", f"mf5to6{ext}")
with cwd(os.path.join("..", "utils", "mf5to6", "make")):
target = str(root_path / "bin" / f"mf5to6{ext}")
util_path = root_path / "utils" / "mf5to6"
with cwd(util_path / "make"):
run_makefile(target)


if __name__ == "__main__":
build_mf6_makefile()
build_zbud6_makefile()
build_mf5to6_makefile()
# test_build_mf6_wmake()
# test_build_zbud6_wmake()
# test_build_mf5to6_wmake()
119 changes: 52 additions & 67 deletions distribution/build_nightly.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import os
import pathlib
from os import PathLike, chdir, X_OK
from pathlib import Path
import platform
import shutil
from shutil import which
import subprocess
import sys

import flopy
import pymake

# add path to build script in autotest directory and reuse mf6 build scripts
sys.path.append(os.path.join("..", "autotest"))
from build_exes import meson_build
from make_release import update_version
from mkdist import update_mf6io_tex_files

# make sure exe extension is used on windows
eext = ""
Expand All @@ -18,10 +18,6 @@
eext = ".exe"
soext = ".dll"

bin_path = os.path.abspath(os.path.join("..", "bin"))
example_path = os.path.abspath(os.path.join("temp"))
zip_path = os.path.abspath(os.path.join("temp_zip"))


def get_zipname():
zipname = sys.platform.lower()
Expand All @@ -35,78 +31,58 @@ def get_zipname():
return zipname


def relpath_fallback(pth):
try:
# throws ValueError on Windows if pth is on a different drive
return os.path.relpath(pth)
except ValueError:
return os.path.abspath(pth)


def create_dir(pth):
# remove pth directory if it exists
if os.path.exists(pth):
print(f"removing... {os.path.abspath(pth)}")
shutil.rmtree(pth)

# create pth directory
print(f"creating... {os.path.abspath(pth)}")
os.makedirs(pth)

msg = f"could not create... {os.path.abspath(pth)}"
assert os.path.exists(pth), msg


def test_update_version():
from make_release import update_version

update_version()


def test_create_dirs():
for pth in (
bin_path,
zip_path,
):
create_dir(pth)
def create_nightly_build(workspace_path: PathLike, zip_path: PathLike):
chdir(Path(workspace_path))

# build release source files with Meson
cmd = (
f"meson setup builddir "
+ f"--bindir=bin "
+ f"--libdir=bin "
+ f"--prefix={('%CD%' if platform.system() == 'Windows' else '$(pwd)')}"
+ (" --wipe" if Path("builddir").is_dir() else "")
)
print(f"Running meson setup command: {cmd}")
subprocess.run(cmd, shell=True, check=True)

def test_nightly_build():
meson_build()
cmd = "meson install -C builddir"
print(f"Running meson install command: {cmd}")
subprocess.run(cmd, shell=True, check=True)

# test if there are any executable files to zip
binpth_files = [
os.path.join(bin_path, f)
for f in os.listdir(bin_path)
if os.path.isfile(os.path.join(bin_path, f))
and shutil.which(os.path.join(bin_path, f), mode=os.X_OK)
and pathlib.Path(os.path.join(bin_path, f)).suffix
not in (".a", ".lib", ".pdb")
str(bin_path / f)
for f in bin_path.glob('*')
if (bin_path / f).is_file()
and which(bin_path / f, mode=X_OK)
and (bin_path / f).suffix not in (".a", ".lib", ".pdb")
]
if len(binpth_files) < 1:
raise FileNotFoundError(
f"No executable files present in {os.path.abspath(bin_path)}.\n"
+ f"Available files:\n [{', '.join(os.listdir(bin_path))}]"
f"No executable files present in {bin_path.absolute()}.\n"
+ f"Available files:\n [{', '.join([str(p) for p in bin_path.glob('*')])}]"
)
else:
print(f"Files to zip:\n [{', '.join(binpth_files)}]")

zip_pth = os.path.abspath(os.path.join(zip_path, get_zipname() + ".zip"))
print(f"Zipping files to '{zip_pth}'")
success = pymake.zip_all(zip_pth, file_pths=binpth_files)
assert success, f"Could not create '{zip_pth}'"
zip_path = (Path(zip_path) / (get_zipname() + ".zip")).absolute()
print(f"Zipping files to '{zip_path}'")
success = pymake.zip_all(str(zip_path), file_pths=binpth_files)
assert success, f"Could not create '{zip_path}'"


def test_update_mf6io():
from mkdist import update_mf6io_tex_files
def update_mf6io(bin_path: PathLike, example_path: PathLike):
bin_path = Path(bin_path)
example_path = Path(example_path)

# build simple model
name = "mymodel"
ws = os.path.join(example_path, name)
ws = str(example_path / name)
exe_name = "mf6"
if sys.platform.lower() == "win32":
exe_name += ".exe"
exe_name = os.path.join(bin_path, exe_name)
exe_name = str(bin_path / exe_name)

# build simple model
sim = flopy.mf6.MFSimulation(sim_name=name, sim_ws=ws, exe_name=exe_name)
tdis = flopy.mf6.ModflowTdis(sim)
ims = flopy.mf6.ModflowIms(sim)
Expand All @@ -125,7 +101,16 @@ def test_update_mf6io():


if __name__ == "__main__":
test_update_version()
test_create_dirs()
test_nightly_build()
test_update_mf6io()
build_path = Path(__file__).parent.parent
bin_path = build_path / "bin"
example_path = build_path / "temp"
zip_path = build_path / "distribution" / "temp_zip"

print(f"Building nightly MODFLOW 6 release")
bin_path.mkdir(exist_ok=True, parents=True)
example_path.mkdir(exist_ok=True, parents=True)
zip_path.mkdir(exist_ok=True, parents=True)

update_version()
create_nightly_build(build_path, zip_path)
update_mf6io(bin_path, example_path)
Loading

0 comments on commit a591a0e

Please sign in to comment.