# Path: caput/config.py
# class CaputConfigError(Exception):
#     """
#     There was an error in the configuration.
# 
#     Parameters
#     ==========
#     message : str
#         Message / description of error
#     file_ : str
#         Configuration file name (optional)
#     location : dict
#         If using :class:`SafeLineLoader` is used, a dict created by that can be
#         passed in here to report the line number where the error occurred.
#     """
# 
#     def __init__(self, message, file_=None, location=None):
#         self.message = message
#         self.file = file_
#         if isinstance(location, _line_dict):
#             self.line = location.__line__
#         else:
#             self.line = None
#         super().__init__(message)
# 
#     def __str__(self):
#         location = ""
#         if self.line is not None:
#             location = "\nError in block starting at L{}".format(self.line)
#             if self.file is not None:
#                 location = "{} ({})".format(location, self.file)
#         return "{}{}".format(self.message, location)
# 
# Path: caput/profile.py
# class Profiler:
#     """A context manager to profile a block of code using various profilers.
# 
#     Parameters
#     ----------
#     profile
#         Whether to run the profiler or not.
#     profiler
#         Which profiler to run. Currently `cProfile` and `pyinstrument` are supported.
#     comm
#         An optional MPI communicator. This is only used for labelling the output files.
#     path
#         The optional path under which to write the profiles.  If not set use the
#         current directory.
#     """
# 
#     profilers = ["cprofile", "pyinstrument"]
# 
#     def __init__(
#         self,
#         profile: bool = True,
#         profiler: str = "cprofile",
#         comm: Optional["mpiutil.MPI.IntraComm"] = None,
#         path: Optional[os.PathLike] = None,
#     ):
#         self.profile = profile
# 
#         if profiler not in self.profilers:
#             raise ValueError(f"Unsupported profiler: {profiler}")
# 
#         self.profiler = profiler
#         self.comm = comm
#         self._pr = None
# 
#         if path is None:
#             self.path = Path.cwd()
#         else:
#             self.path = Path(path)
# 
#     def __enter__(self):
# 
#         if not self.profile:
#             return
# 
#         if self.profiler == "cprofile":
#             import cProfile
# 
#             self._pr = cProfile.Profile()
#             self._pr.enable()
# 
#         elif self.profiler == "pyinstrument":
#             import pyinstrument
# 
#             self._pr = pyinstrument.Profiler()
#             self._pr.start()
# 
#     def __exit__(self, *args, **kwargs):
# 
#         if not self.profile:
#             return
# 
#         if self.comm is None:
#             rank = mpiutil.rank
#             size = mpiutil.size
#         else:
#             rank = self.comm.rank
#             size = self.comm.size
# 
#         rank_length = int(math.log10(size)) + 1
# 
#         if self.profiler == "cprofile":
#             self._pr.disable()
#             self._pr.dump_stats(f"profile_{rank:0{rank_length}}.prof")
# 
#         elif self.profiler == "pyinstrument":
#             self._pr.stop()
#             with open(f"profile_{rank:0{rank_length}}.txt", "w") as fh:
#                 fh.write(self._pr.output_text(unicode=True))


import itertools
import os
import sys
import tempfile
import click
    import site
    import yaml
    import warnings
    import shutil
    import yaml
from pathlib import Path
from caput.config import CaputConfigError
from caput.profile import Profiler
    from caput.pipeline import Manager
    from caput.pipeline import Manager
        from caput import mpiutil
    from caput.pipeline import Manager
        from caput.pipeline import Manager
    help=(
        "Enable an MPI aware exception handler such that all ranks will exit when any "
        "one throws an exception."
    ),
)
@click.option(
    "--psutil",
    is_flag=True,
    default=False,
    help=(
        "Run the job with a psutil profiler for each task. The output "
        "can be found in the caput logs, at the INFO level."
    ),
)
def run(configfile, loglevel, profile, profiler, mpi_abort, psutil):
    """Run a pipeline immediately from the given CONFIGFILE."""


    if loglevel != "CONFIG":
        warnings.warn(
            "--loglevel is deprecated, use the config file instead", DeprecationWarning
        )

    if mpi_abort:

        mpiutil.enable_mpi_exception_handler()

    with Profiler(profile, profiler=profiler.lower()):
        try:
            P = Manager.from_yaml_file(configfile, psutil_profiling=psutil)

# Path: caput/config.py
# class CaputConfigError(Exception):
#     """
#     There was an error in the configuration.
# 
#     Parameters
#     ==========
#     message : str
#         Message / description of error
#     file_ : str
#         Configuration file name (optional)
#     location : dict
#         If using :class:`SafeLineLoader` is used, a dict created by that can be
#         passed in here to report the line number where the error occurred.
#     """
# 
#     def __init__(self, message, file_=None, location=None):
#         self.message = message
#         self.file = file_
#         if isinstance(location, _line_dict):
#             self.line = location.__line__
#         else:
#             self.line = None
#         super().__init__(message)
# 
#     def __str__(self):
#         location = ""
#         if self.line is not None:
#             location = "\nError in block starting at L{}".format(self.line)
#             if self.file is not None:
#                 location = "{} ({})".format(location, self.file)
#         return "{}{}".format(self.message, location)
# 
# Path: caput/profile.py
# class Profiler:
#     """A context manager to profile a block of code using various profilers.
# 
#     Parameters
#     ----------
#     profile
#         Whether to run the profiler or not.
#     profiler
#         Which profiler to run. Currently `cProfile` and `pyinstrument` are supported.
#     comm
#         An optional MPI communicator. This is only used for labelling the output files.
#     path
#         The optional path under which to write the profiles.  If not set use the
#         current directory.
#     """
# 
#     profilers = ["cprofile", "pyinstrument"]
# 
#     def __init__(
#         self,
#         profile: bool = True,
#         profiler: str = "cprofile",
#         comm: Optional["mpiutil.MPI.IntraComm"] = None,
#         path: Optional[os.PathLike] = None,
#     ):
#         self.profile = profile
# 
#         if profiler not in self.profilers:
#             raise ValueError(f"Unsupported profiler: {profiler}")
# 
#         self.profiler = profiler
#         self.comm = comm
#         self._pr = None
# 
#         if path is None:
#             self.path = Path.cwd()
#         else:
#             self.path = Path(path)
# 
#     def __enter__(self):
# 
#         if not self.profile:
#             return
# 
#         if self.profiler == "cprofile":
#             import cProfile
# 
#             self._pr = cProfile.Profile()
#             self._pr.enable()
# 
#         elif self.profiler == "pyinstrument":
#             import pyinstrument
# 
#             self._pr = pyinstrument.Profiler()
#             self._pr.start()
# 
#     def __exit__(self, *args, **kwargs):
# 
#         if not self.profile:
#             return
# 
#         if self.comm is None:
#             rank = mpiutil.rank
#             size = mpiutil.size
#         else:
#             rank = self.comm.rank
#             size = self.comm.size
# 
#         rank_length = int(math.log10(size)) + 1
# 
#         if self.profiler == "cprofile":
#             self._pr.disable()
#             self._pr.dump_stats(f"profile_{rank:0{rank_length}}.prof")
# 
#         elif self.profiler == "pyinstrument":
#             self._pr.stop()
#             with open(f"profile_{rank:0{rank_length}}.txt", "w") as fh:
#                 fh.write(self._pr.output_text(unicode=True))


# Path: caput/scripts/runner.py
import itertools
import os
import sys
import tempfile
import click
    import site
    import yaml
    import warnings
    import shutil
    import yaml
from pathlib import Path
from caput.config import CaputConfigError
from caput.profile import Profiler
    from caput.pipeline import Manager
    from caput.pipeline import Manager
        from caput import mpiutil
    from caput.pipeline import Manager
        from caput.pipeline import Manager

    help=(
        "Enable an MPI aware exception handler such that all ranks will exit when any "
        "one throws an exception."
    ),
)
@click.option(
    "--psutil",
    is_flag=True,
    default=False,
    help=(
        "Run the job with a psutil profiler for each task. The output "
        "can be found in the caput logs, at the INFO level."
    ),
)
def run(configfile, loglevel, profile, profiler, mpi_abort, psutil):
    """Run a pipeline immediately from the given CONFIGFILE."""


    if loglevel != "CONFIG":
        warnings.warn(
            "--loglevel is deprecated, use the config file instead", DeprecationWarning
        )

    if mpi_abort:

        mpiutil.enable_mpi_exception_handler()

    with Profiler(profile, profiler=profiler.lower()):
        try:
            P = Manager.from_yaml_file(configfile, psutil_profiling=psutil)

        except CaputConfigError as e: