# Path: pylinac/log_analyzer.py
# def load_log(file_or_dir: str, exclude_beam_off: bool = True, recursive: bool = True) -> Union[
#              TrajectoryLog, Dynalog, MachineLogs]:
#     """Load a log file or directory of logs, either dynalogs or Trajectory logs.
# 
#     Parameters
#     ----------
#     file_or_dir : str
#         String pointing to a single log file or a directory that contains log files.
#     exclude_beam_off : bool
#         Whether to include snapshots where the beam was off.
#     recursive : bool
#         Whether to recursively search a directory. Irrelevant for single log files.
# 
#     Returns
#     -------
#     One of :class:`~pylinac.log_analyzer.Dynalog`, :class:`~pylinac.log_analyzer.TrajectoryLog`,
#         :class:`~pylinac.log_analyzer.MachineLogs`.
#     """
#     if io.is_url(file_or_dir):
#         file_or_dir = io.get_url(file_or_dir)
#     if osp.isfile(file_or_dir):
#         if io.is_zipfile(file_or_dir):
#             return MachineLogs.from_zip(file_or_dir)
#         if not is_log(file_or_dir):
#             raise NotALogError("Not a valid log")
#         elif is_tlog(file_or_dir):
#             return TrajectoryLog(file_or_dir, exclude_beam_off)
#         else:
#             return Dynalog(file_or_dir, exclude_beam_off)
#     elif osp.isdir(file_or_dir):
#         return MachineLogs(file_or_dir, recursive)
#     else:
#         raise NotALogError(f"'{file_or_dir}' did not point to a valid file, directory, or ZIP archive")
# 
# Path: pylinac/log_analyzer.py
# IMAGING = 'Imaging'  #:
# 
# Path: tests_basic/utils.py
# class DataBankMixin:
#     """Mixin class for running through a bank of images/datasets. No details are tested; only pass/fail results.
# 
#     DATA_DIR must be set and is a relative location.
#     ``file_should_be_processed()`` should be overloaded if the criteria is not an Image.
#     ``test_all()`` should be overloaded to pass an analysis function. Because of the pool executor, methods nor attrs can be passed.
#     ``executor`` can be either 'ProcessPoolExecutor' or 'ThreadPoolExecutor'.
#     ``workers`` specifies how many workers (threads or processes) will be started.
# 
#     This class walks through a directory and runs through the files, analyzing them if the file should be analyzed.
#     Note that an executor is started **per directory** rather than one executor for all the files.
#     This is on purpose.
#     Some test runs, seemingly due to the executor, bog down when running a very large number of files. By opening a new executor at
#     every directory, memory leaks are minimized.
#     """
# 
#     DATA_BANK_DIR = osp.abspath(
#         osp.join(osp.abspath(__file__), "..", "..", "..", "pylinac test files")
#     )
#     DATA_DIR = []
#     executor = "ProcessPoolExecutor"
#     workers = multiprocessing.cpu_count() - 1
#     print_success_path = False
#     write_failures_to_file = False
# 
#     @classmethod
#     def setUpClass(cls):
#         cls.DATA_DIR = osp.join(cls.DATA_BANK_DIR, *cls.DATA_DIR)
#         if not osp.isdir(cls.DATA_DIR):
#             raise NotADirectoryError("Directory {} is not valid".format(cls.DATA_DIR))
# 
#     def file_should_be_processed(self, filepath):
#         """Decision of whether file should be run. Returns boolean."""
#         try:
#             image.load(filepath)
#             return True
#         except:
#             return False
# 
#     def test_all(self, func):
#         """Test method that runs through the bank data in an executor pool.
# 
#         Parameters
#         ----------
#         func : A function that processes the filepath and determines if it passes. Must return ``Success`` if passed.
#         """
#         passes = 0
#         fails = []
#         start = time.time()
#         futures = {}
#         # open an executor
#         with getattr(concurrent.futures, self.executor)(
#             max_workers=self.workers
#         ) as exec:
#             # walk through datasets
#             for pdir, sdir, files in os.walk(self.DATA_DIR):
#                 for file in files:
#                     # if the file needs processing, submit it into the queue
#                     filepath = osp.join(pdir, file)
#                     if self.file_should_be_processed(filepath):
#                         future = exec.submit(func, filepath)
#                         futures[future] = filepath
# 
#             # return results
#             for test_num, future in enumerate(concurrent.futures.as_completed(futures)):
#                 stuff_to_print = [test_num, future.result()]
#                 if future.result() == "Success":
#                     passes += 1
#                     if self.print_success_path:
#                         stuff_to_print.append(futures[future])
#                 else:
#                     fails += [futures[future]]
#                 print(*stuff_to_print)
# 
#         end = time.time() - start
#         print(
#             "Processing of {} files took {:3.1f}s ({:3.2f}s/item). {} passed; {} failed.".format(
#                 test_num, end, end / test_num, passes, len(fails)
#             )
#         )
#         if len(fails) > 0:
#             pprint.pprint("Failures: {}".format(fails))
#             if self.write_failures_to_file:
#                 with open(
#                     "failures_{}.txt".format(osp.basename(self.DATA_DIR)), mode="w"
#                 ) as f:
#                     for file in fails:
#                         f.write(file + "\n")
#                 print("Failures written to file")


from unittest import TestCase
from pylinac import load_log
from pylinac.log_analyzer import IMAGING
from tests_basic.utils import DataBankMixin
"""Run through the Machine Log bank."""



def run_log(path):
    """Function to pass to the process pool executor to process machine logs."""
    try:
        log = load_log(path)

# Path: pylinac/log_analyzer.py
# def load_log(file_or_dir: str, exclude_beam_off: bool = True, recursive: bool = True) -> Union[
#              TrajectoryLog, Dynalog, MachineLogs]:
#     """Load a log file or directory of logs, either dynalogs or Trajectory logs.
# 
#     Parameters
#     ----------
#     file_or_dir : str
#         String pointing to a single log file or a directory that contains log files.
#     exclude_beam_off : bool
#         Whether to include snapshots where the beam was off.
#     recursive : bool
#         Whether to recursively search a directory. Irrelevant for single log files.
# 
#     Returns
#     -------
#     One of :class:`~pylinac.log_analyzer.Dynalog`, :class:`~pylinac.log_analyzer.TrajectoryLog`,
#         :class:`~pylinac.log_analyzer.MachineLogs`.
#     """
#     if io.is_url(file_or_dir):
#         file_or_dir = io.get_url(file_or_dir)
#     if osp.isfile(file_or_dir):
#         if io.is_zipfile(file_or_dir):
#             return MachineLogs.from_zip(file_or_dir)
#         if not is_log(file_or_dir):
#             raise NotALogError("Not a valid log")
#         elif is_tlog(file_or_dir):
#             return TrajectoryLog(file_or_dir, exclude_beam_off)
#         else:
#             return Dynalog(file_or_dir, exclude_beam_off)
#     elif osp.isdir(file_or_dir):
#         return MachineLogs(file_or_dir, recursive)
#     else:
#         raise NotALogError(f"'{file_or_dir}' did not point to a valid file, directory, or ZIP archive")
# 
# Path: pylinac/log_analyzer.py
# IMAGING = 'Imaging'  #:
# 
# Path: tests_basic/utils.py
# class DataBankMixin:
#     """Mixin class for running through a bank of images/datasets. No details are tested; only pass/fail results.
# 
#     DATA_DIR must be set and is a relative location.
#     ``file_should_be_processed()`` should be overloaded if the criteria is not an Image.
#     ``test_all()`` should be overloaded to pass an analysis function. Because of the pool executor, methods nor attrs can be passed.
#     ``executor`` can be either 'ProcessPoolExecutor' or 'ThreadPoolExecutor'.
#     ``workers`` specifies how many workers (threads or processes) will be started.
# 
#     This class walks through a directory and runs through the files, analyzing them if the file should be analyzed.
#     Note that an executor is started **per directory** rather than one executor for all the files.
#     This is on purpose.
#     Some test runs, seemingly due to the executor, bog down when running a very large number of files. By opening a new executor at
#     every directory, memory leaks are minimized.
#     """
# 
#     DATA_BANK_DIR = osp.abspath(
#         osp.join(osp.abspath(__file__), "..", "..", "..", "pylinac test files")
#     )
#     DATA_DIR = []
#     executor = "ProcessPoolExecutor"
#     workers = multiprocessing.cpu_count() - 1
#     print_success_path = False
#     write_failures_to_file = False
# 
#     @classmethod
#     def setUpClass(cls):
#         cls.DATA_DIR = osp.join(cls.DATA_BANK_DIR, *cls.DATA_DIR)
#         if not osp.isdir(cls.DATA_DIR):
#             raise NotADirectoryError("Directory {} is not valid".format(cls.DATA_DIR))
# 
#     def file_should_be_processed(self, filepath):
#         """Decision of whether file should be run. Returns boolean."""
#         try:
#             image.load(filepath)
#             return True
#         except:
#             return False
# 
#     def test_all(self, func):
#         """Test method that runs through the bank data in an executor pool.
# 
#         Parameters
#         ----------
#         func : A function that processes the filepath and determines if it passes. Must return ``Success`` if passed.
#         """
#         passes = 0
#         fails = []
#         start = time.time()
#         futures = {}
#         # open an executor
#         with getattr(concurrent.futures, self.executor)(
#             max_workers=self.workers
#         ) as exec:
#             # walk through datasets
#             for pdir, sdir, files in os.walk(self.DATA_DIR):
#                 for file in files:
#                     # if the file needs processing, submit it into the queue
#                     filepath = osp.join(pdir, file)
#                     if self.file_should_be_processed(filepath):
#                         future = exec.submit(func, filepath)
#                         futures[future] = filepath
# 
#             # return results
#             for test_num, future in enumerate(concurrent.futures.as_completed(futures)):
#                 stuff_to_print = [test_num, future.result()]
#                 if future.result() == "Success":
#                     passes += 1
#                     if self.print_success_path:
#                         stuff_to_print.append(futures[future])
#                 else:
#                     fails += [futures[future]]
#                 print(*stuff_to_print)
# 
#         end = time.time() - start
#         print(
#             "Processing of {} files took {:3.1f}s ({:3.2f}s/item). {} passed; {} failed.".format(
#                 test_num, end, end / test_num, passes, len(fails)
#             )
#         )
#         if len(fails) > 0:
#             pprint.pprint("Failures: {}".format(fails))
#             if self.write_failures_to_file:
#                 with open(
#                     "failures_{}.txt".format(osp.basename(self.DATA_DIR)), mode="w"
#                 ) as f:
#                     for file in fails:
#                         f.write(file + "\n")
#                 print("Failures written to file")


# Path: tests_bank/_test_bank_logs.py
from unittest import TestCase
from pylinac import load_log
from pylinac.log_analyzer import IMAGING
from tests_basic.utils import DataBankMixin

"""Run through the Machine Log bank."""



def run_log(path):
    """Function to pass to the process pool executor to process machine logs."""
    try:
        log = load_log(path)

        if not log.treatment_type == IMAGING: