Source code for odatse._main

# SPDX-License-Identifier: MPL-2.0
#
# ODAT-SE -- an open framework for data analysis
# Copyright (C) 2020- The University of Tokyo
#
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

from typing import Optional, Sequence

import sys
import odatse
from . import exception


[docs] def choose_solver(info): """ Select the solver class for the given info. Parameters ---------- info : odatse.Info Information object containing the solver configuration. Returns ------- type The solver class. Raises ------ odatse.exception.InputError If the solver name is not recognised. """ solvername = info.solver["name"] if solvername == "analytical": from .solver.analytical import Solver return Solver raise exception.InputError(f"Unknown solver ({solvername})")
[docs] def main(argv: Optional[Sequence[str]] = None) -> dict: """ Run an analysis specified by command-line style arguments. Parses the arguments, loads the input file, selects the algorithm and solver, executes the analysis, and returns the result of ``Algorithm.main()`` so that programmatic callers can use it as ``result = odatse.main(argv)``. This is the top-level boundary: user-facing errors (``odatse.exception.Error``) are reported and converted to a non-zero exit status via ``sys.exit(1)``. To handle these as exceptions instead, compose the lower-level API (``odatse.initialize`` / ``odatse.algorithm.choose_algorithm`` / ``Algorithm``) directly. Note: do not use this function as a console-script entry point; use ``cli()``, which converts the result to an exit status. """ try: info, run_mode = odatse.initialize(argv) alg_module = odatse.algorithm.choose_algorithm(info.algorithm["name"]) Solver = choose_solver(info) solver = Solver(info) runner = odatse.Runner(solver, info) alg = alg_module.Algorithm(info, runner, run_mode=run_mode) return alg.main() except exception.Error as e: # rank-local errors (see exception.Error.rank_local) exist only on the # rank that failed, so gating on rank 0 would silence them entirely if e.rank_local: prefix = f"[rank {odatse.mpi.rank()}] " if odatse.mpi.size() > 1 else "" print(f"{prefix}ERROR: {e}", file=sys.stderr) elif odatse.mpi.rank() == 0: print(f"ERROR: {e}", file=sys.stderr) sys.exit(1)
[docs] def cli(argv: Optional[Sequence[str]] = None) -> int: """ Console-script entry point for the ``odatse`` command. Runs :func:`main` and returns exit status 0 on success, discarding the result object (``sys.exit()`` would interpret a non-integer return value as a failure). Errors are reported inside :func:`main` and terminate the process with exit status 1. """ main(argv) return 0