# 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


@click.group()
def cli():
    """Executes a data analysis pipeline given a pipeline YAML file.

    This script, when executed on the command line, accepts a single parameter, the
    path to a yaml pipeline file.  For an example of a pipeline file, see
    documentation for caput.pipeline.
    """
    pass


@cli.command("lint")
@click.argument(
    "configfile",
    nargs=-1,
    type=click.Path(exists=True, dir_okay=False, readable=True, resolve_path=True),
)
def lint_config(configfile):
    """Test a pipeline for errors without running it."""

    # nargs=-1 packs multiple arguments (or glob patterns) into tuples
    if not isinstance(configfile, tuple):
        configfile = (configfile,)
    for f in configfile:
        load_venv(f)

        try:
            Manager.from_yaml_file(f, lint=True)

# 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



@click.group()
def cli():
    """Executes a data analysis pipeline given a pipeline YAML file.

    This script, when executed on the command line, accepts a single parameter, the
    path to a yaml pipeline file.  For an example of a pipeline file, see
    documentation for caput.pipeline.
    """
    pass


@cli.command("lint")
@click.argument(
    "configfile",
    nargs=-1,
    type=click.Path(exists=True, dir_okay=False, readable=True, resolve_path=True),
)
def lint_config(configfile):
    """Test a pipeline for errors without running it."""

    # nargs=-1 packs multiple arguments (or glob patterns) into tuples
    if not isinstance(configfile, tuple):
        configfile = (configfile,)
    for f in configfile:
        load_venv(f)

        try:
            Manager.from_yaml_file(f, lint=True)

        except CaputConfigError as e: