Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

103 we should be using the logging module #224

Merged
merged 19 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2f6da74
Added baseline logging implementation, tests relying on stdout need t…
bschroeter Dec 18, 2023
59e56fe
Reorganised logger, updated most debugs to infos. Fixes #103
bschroeter Dec 20, 2023
43deac8
Added logger instantiation to CLI. Fixes #103
bschroeter Dec 20, 2023
63b41f8
Automatic application of ruff/black suggestions. Manual edits to foll…
bschroeter Dec 21, 2023
023c4d4
Manual ruff modifications. #103
bschroeter Dec 21, 2023
ff36e53
Manual black modifications. #103
bschroeter Dec 21, 2023
d26937b
Merge branch 'main' into 103-we-should-be-using-the-logging-module
bschroeter Jan 19, 2024
7686403
Refactoring of verbosity
bschroeter Jan 24, 2024
222ad43
Black reformatting. #103
bschroeter Jan 24, 2024
1ba25b0
Reverted to native logger singleton, less flexible but pickles. #103
bschroeter Feb 6, 2024
7d84532
Applied black/ruff checks, ran integration tests successfully. Fixes …
bschroeter Feb 6, 2024
f618128
Merge update from main. Fixes #103
bschroeter Feb 6, 2024
44818a4
Updated again from main - further commits coming to handle clobbered …
bschroeter Feb 12, 2024
222d16d
Ruff checks, pytest passes. #103.
bschroeter Feb 13, 2024
9b49c13
Black reapplied. #103
bschroeter Feb 13, 2024
7a3b741
Merge branch 'main' into 103-we-should-be-using-the-logging-module
abhaasgoyal Feb 14, 2024
b6bca5b
Remaining clobbered code fix. #103.
bschroeter Feb 14, 2024
3957aaf
Merge branch '103-we-should-be-using-the-logging-module' of github.co…
bschroeter Feb 14, 2024
b65ddbb
Last clobbered merge changes.
Feb 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion benchcab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@

import importlib.metadata

from benchcab.utils import get_logger

try:
__version__ = importlib.metadata.version("benchcab")
except importlib.metadata.PackageNotFoundError:
__version__ = ""
print("Warning: unable to interrogate version string from installed distribution.")
get_logger().warn(
"unable to interrogate version string from installed distribution."
)
# Note: cannot re-raise exception here as this will break pytest
# when running without first installing the package
168 changes: 87 additions & 81 deletions benchcab/benchcab.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
)
from benchcab.internal import get_met_forcing_file_names
from benchcab.model import Model
from benchcab.utils import get_logger
from benchcab.utils.fs import mkdir, next_path
from benchcab.utils.pbs import render_job_script
from benchcab.utils.repo import SVNRepo, create_repo
from benchcab.utils.repo import create_repo
from benchcab.utils.subprocess import SubprocessWrapper, SubprocessWrapperInterface
from benchcab.workdir import setup_fluxsite_directory_tree

Expand All @@ -41,13 +42,25 @@
benchcab_exe_path: Optional[Path],
validate_env: bool = True,
) -> None:
"""Constructor.

Parameters
----------
benchcab_exe_path : Optional[Path]
Path to the executable.
validate_env : bool, optional
Validate the environment, by default True

"""
self.benchcab_exe_path = benchcab_exe_path
self.validate_env = validate_env

self._config: Optional[dict] = None
self._models: list[Model] = []
self.tasks: list[Task] = [] # initialise fluxsite tasks lazily

# Get the logger object
self.logger = get_logger()
self._set_environment()

def _set_environment(self):
Expand All @@ -61,13 +74,13 @@
return

if "gadi.nci" not in internal.NODENAME:
print("Error: benchcab is currently implemented only on Gadi")
self.logger.error("benchcab is currently implemented only on Gadi")

Check warning on line 77 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L77

Added line #L77 was not covered by tests
sys.exit(1)

namelist_dir = Path(internal.CWD / internal.NAMELIST_DIR)
if not namelist_dir.exists():
print(
"Error: cannot find 'namelists' directory in current working directory"
self.logger.error(

Check warning on line 82 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L82

Added line #L82 was not covered by tests
"Cannot find 'namelists' directory in current working directory"
)
sys.exit(1)

Expand All @@ -89,16 +102,16 @@

for modname in modules:
if not self.modules_handler.module_is_avail(modname):
print(f"Error: module ({modname}) is not available.")
self.logger.error(f"Module ({modname}) is not available.")

Check warning on line 105 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L105

Added line #L105 was not covered by tests
sys.exit(1)

system_paths = os.getenv("PATH").split(":")[: len(internal.SYSTEM_PATHS)]
if set(system_paths) != set(internal.SYSTEM_PATHS):
msg = f"""Error: System paths are not prioritized over user-defined paths

Check warning on line 110 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L108-L110

Added lines #L108 - L110 were not covered by tests
Currently set as: {system_paths}
The required system paths are: {internal.SYSTEM_PATHS}
"""
raise EnvironmentError(msg)

Check warning on line 114 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L114

Added line #L114 was not covered by tests

all_site_ids = set(
internal.MEORG_EXPERIMENTS["five-site-test"]
Expand All @@ -107,14 +120,15 @@
for site_id in all_site_ids:
paths = list(internal.MET_DIR.glob(f"{site_id}*"))
if not paths:
print(
f"Error: failed to infer met file for site id '{site_id}' in "
f"{internal.MET_DIR}."
self.logger.error(

Check warning on line 123 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L123

Added line #L123 was not covered by tests
f"Failed to infer met file for site id '{site_id}' in "
)
self.logger.error(f"{internal.MET_DIR}.")

Check warning on line 126 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L126

Added line #L126 was not covered by tests

sys.exit(1)
if len(paths) > 1:
print(
f"Error: multiple paths infered for site id: '{site_id}' in {internal.MET_DIR}."
self.logger.error(

Check warning on line 130 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L130

Added line #L130 was not covered by tests
f"Multiple paths infered for site id: '{site_id}' in {internal.MET_DIR}."
)
sys.exit(1)

Expand Down Expand Up @@ -145,13 +159,11 @@
)
return self.tasks

def validate_config(self, config_path: str, verbose: bool):
def validate_config(self, config_path: str):
"""Endpoint for `benchcab validate_config`."""
_ = self._get_config(config_path)

def fluxsite_submit_job(
self, config_path: str, verbose: bool, skip: list[str]
) -> None:
def fluxsite_submit_job(self, config_path: str, skip: list[str]) -> None:
"""Submits the PBS job script step in the fluxsite test workflow."""
config = self._get_config(config_path)
self._validate_environment(project=config["project"], modules=config["modules"])
Expand All @@ -160,17 +172,18 @@
raise RuntimeError(msg)

job_script_path = Path(internal.QSUB_FNAME)
print(
"Creating PBS job script to run fluxsite tasks on compute "
f"nodes: {job_script_path}"
self.logger.info(

Check warning on line 175 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L175

Added line #L175 was not covered by tests
"Creating PBS job script to run fluxsite tasks on compute nodes"
)

self.logger.info(f"job_script_path = {job_script_path}")

Check warning on line 179 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L179

Added line #L179 was not covered by tests

with job_script_path.open("w", encoding="utf-8") as file:
contents = render_job_script(
project=config["project"],
config_path=config_path,
modules=config["modules"],
pbs_config=config["fluxsite"]["pbs"],
verbose=verbose,
skip_bitwise_cmp="fluxsite-bitwise-cmp" in skip,
benchcab_path=str(self.benchcab_exe_path),
)
Expand All @@ -180,94 +193,89 @@
proc = self.subprocess_handler.run_cmd(
f"qsub {job_script_path}",
capture_output=True,
verbose=verbose,
)
except CalledProcessError as exc:
print("Error when submitting job to NCI queue")
print(exc.output)
self.logger.error("when submitting job to NCI queue, details to follow")
self.logger.error(exc.output)

Check warning on line 199 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L198-L199

Added lines #L198 - L199 were not covered by tests
raise

print(
f"PBS job submitted: {proc.stdout.strip()}\n"
"The CABLE log file for each task is written to "
f"{internal.FLUXSITE_DIRS['LOG']}/<task_name>_log.txt\n"
"The CABLE standard output for each task is written to "
f"{internal.FLUXSITE_DIRS['TASKS']}/<task_name>/out.txt\n"
"The NetCDF output for each task is written to "
f"{internal.FLUXSITE_DIRS['OUTPUT']}/<task_name>_out.nc"
)
self.logger.info(f"PBS job submitted: {proc.stdout.strip()}")
self.logger.info("CABLE log file for each task is written to:")
self.logger.info(f"{internal.FLUXSITE_DIRS['LOG']}/<task_name>_log.txt")
self.logger.info("The CABLE standard output for each task is written to:")
self.logger.info(f"{internal.FLUXSITE_DIRS['TASKS']}/<task_name>/out.txt")
self.logger.info("The NetCDF output for each task is written to:")
self.logger.info(f"{internal.FLUXSITE_DIRS['OUTPUT']}/<task_name>_out.nc")

Check warning on line 208 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L202-L208

Added lines #L202 - L208 were not covered by tests

def checkout(self, config_path: str, verbose: bool):
def checkout(self, config_path: str):
"""Endpoint for `benchcab checkout`."""
config = self._get_config(config_path)
self._validate_environment(project=config["project"], modules=config["modules"])

mkdir(internal.SRC_DIR, exist_ok=True, verbose=True)
mkdir(internal.SRC_DIR, exist_ok=True)

Check warning on line 215 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L215

Added line #L215 was not covered by tests

print("Checking out repositories...")
self.logger.info("Checking out repositories...")

Check warning on line 217 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L217

Added line #L217 was not covered by tests
rev_number_log = ""

for model in self._get_models(config):
model.repo.checkout(verbose=verbose)
model.repo.checkout()

Check warning on line 221 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L221

Added line #L221 was not covered by tests
rev_number_log += f"{model.name}: {model.repo.get_revision()}\n"

rev_number_log_path = next_path("rev_number-*.log")
print(f"Writing revision number info to {rev_number_log_path}")
self.logger.info(f"Writing revision number info to {rev_number_log_path}")

Check warning on line 225 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L225

Added line #L225 was not covered by tests
with rev_number_log_path.open("w", encoding="utf-8") as file:
file.write(rev_number_log)

print("")

def build(self, config_path: str, verbose: bool):
def build(self, config_path: str):
"""Endpoint for `benchcab build`."""
config = self._get_config(config_path)
self._validate_environment(project=config["project"], modules=config["modules"])

for repo in self._get_models(config):
if repo.build_script:
print(
"Compiling CABLE using custom build script for "
f"realisation {repo.name}..."
)
repo.custom_build(modules=config["modules"], verbose=verbose)

self.logger.info("Compiling CABLE using custom build script for")
self.logger.info(f"realisation {repo.name}")
repo.custom_build(modules=config["modules"])

Check warning on line 239 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L237-L239

Added lines #L237 - L239 were not covered by tests

else:
build_mode = "with MPI" if internal.MPI else "serially"
print(f"Compiling CABLE {build_mode} for realisation {repo.name}...")
repo.pre_build(verbose=verbose)
repo.run_build(modules=config["modules"], verbose=verbose)
repo.post_build(verbose=verbose)
print(f"Successfully compiled CABLE for realisation {repo.name}")
print("")

def fluxsite_setup_work_directory(self, config_path: str, verbose: bool):
self.logger.info(

Check warning on line 243 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L243

Added line #L243 was not covered by tests
f"Compiling CABLE {build_mode} for realisation {repo.name}..."
)
repo.pre_build()
repo.run_build(modules=config["modules"])
repo.post_build()
self.logger.info(f"Successfully compiled CABLE for realisation {repo.name}")

Check warning on line 249 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L246-L249

Added lines #L246 - L249 were not covered by tests

def fluxsite_setup_work_directory(self, config_path: str):
"""Endpoint for `benchcab fluxsite-setup-work-dir`."""
config = self._get_config(config_path)
self._validate_environment(project=config["project"], modules=config["modules"])

tasks = self.tasks if self.tasks else self._initialise_tasks(config)
print("Setting up run directory tree for fluxsite tests...")
setup_fluxsite_directory_tree(verbose=verbose)
print("Setting up tasks...")
self.logger.info("Setting up run directory tree for fluxsite tests...")
setup_fluxsite_directory_tree()
self.logger.info("Setting up tasks...")

Check warning on line 259 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L257-L259

Added lines #L257 - L259 were not covered by tests
for task in tasks:
task.setup_task(verbose=verbose)
print("Successfully setup fluxsite tasks")
print("")
task.setup_task()
self.logger.info("Successfully setup fluxsite tasks")

Check warning on line 262 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L261-L262

Added lines #L261 - L262 were not covered by tests

def fluxsite_run_tasks(self, config_path: str, verbose: bool):
def fluxsite_run_tasks(self, config_path: str):
"""Endpoint for `benchcab fluxsite-run-tasks`."""
config = self._get_config(config_path)
self._validate_environment(project=config["project"], modules=config["modules"])

tasks = self.tasks if self.tasks else self._initialise_tasks(config)
print("Running fluxsite tasks...")
self.logger.info("Running fluxsite tasks...")

Check warning on line 270 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L270

Added line #L270 was not covered by tests
if config["fluxsite"]["multiprocess"]:
ncpus = config["fluxsite"]["pbs"]["ncpus"]
run_tasks_in_parallel(tasks, n_processes=ncpus, verbose=verbose)
run_tasks_in_parallel(tasks, n_processes=ncpus)

Check warning on line 273 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L273

Added line #L273 was not covered by tests
else:
run_tasks(tasks, verbose=verbose)
print("Successfully ran fluxsite tasks")
print("")
run_tasks(tasks)
self.logger.info("Successfully ran fluxsite tasks")

Check warning on line 276 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L275-L276

Added lines #L275 - L276 were not covered by tests

def fluxsite_bitwise_cmp(self, config_path: str, verbose: bool):
def fluxsite_bitwise_cmp(self, config_path: str):
"""Endpoint for `benchcab fluxsite-bitwise-cmp`."""
config = self._get_config(config_path)
self._validate_environment(project=config["project"], modules=config["modules"])
Expand All @@ -280,32 +288,30 @@
tasks = self.tasks if self.tasks else self._initialise_tasks(config)
comparisons = get_fluxsite_comparisons(tasks)

print("Running comparison tasks...")
self.logger.info("Running comparison tasks...")

Check warning on line 291 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L291

Added line #L291 was not covered by tests
if config["fluxsite"]["multiprocess"]:
ncpus = config["fluxsite"]["pbs"]["ncpus"]
run_comparisons_in_parallel(comparisons, n_processes=ncpus, verbose=verbose)
run_comparisons_in_parallel(comparisons, n_processes=ncpus)

Check warning on line 294 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L294

Added line #L294 was not covered by tests
else:
run_comparisons(comparisons, verbose=verbose)
print("Successfully ran comparison tasks")
run_comparisons(comparisons)
self.logger.info("Successfully ran comparison tasks")

Check warning on line 297 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L296-L297

Added lines #L296 - L297 were not covered by tests

def fluxsite(
self, config_path: str, no_submit: bool, verbose: bool, skip: list[str]
):
def fluxsite(self, config_path: str, no_submit: bool, skip: list[str]):
"""Endpoint for `benchcab fluxsite`."""
self.checkout(config_path, verbose)
self.build(config_path, verbose)
self.fluxsite_setup_work_directory(config_path, verbose)
self.checkout(config_path)
self.build(config_path)
self.fluxsite_setup_work_directory(config_path)

Check warning on line 303 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L301-L303

Added lines #L301 - L303 were not covered by tests
if no_submit:
self.fluxsite_run_tasks(config_path, verbose)
self.fluxsite_run_tasks(config_path)

Check warning on line 305 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L305

Added line #L305 was not covered by tests
if "fluxsite-bitwise-cmp" not in skip:
self.fluxsite_bitwise_cmp(config_path, verbose)
self.fluxsite_bitwise_cmp(config_path)

Check warning on line 307 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L307

Added line #L307 was not covered by tests
else:
self.fluxsite_submit_job(config_path, verbose, skip)
self.fluxsite_submit_job(config_path, skip)

Check warning on line 309 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L309

Added line #L309 was not covered by tests

def spatial(self, config_path: str, verbose: bool):
def spatial(self, config_path: str):
"""Endpoint for `benchcab spatial`."""

def run(self, config_path: str, no_submit: bool, verbose: bool, skip: list[str]):
def run(self, config_path: str, no_submit: bool, skip: list[str]):
"""Endpoint for `benchcab run`."""
self.fluxsite(config_path, no_submit, verbose, skip)
self.spatial(config_path, verbose)
self.fluxsite(config_path, no_submit, skip)
self.spatial(config_path)

Check warning on line 317 in benchcab/benchcab.py

View check run for this annotation

Codecov / codecov/patch

benchcab/benchcab.py#L316-L317

Added lines #L316 - L317 were not covered by tests
Loading
Loading