# Path: mapchete/errors.py
# class JobCancelledError(Exception):
#     """Raised when Job gets cancelled."""
# 
# Path: mapchete/log.py
# def set_log_level(loglevel):
#     stream_handler.setLevel(loglevel)
#     for i in all_mapchete_packages:
#         logging.getLogger(i).setLevel(loglevel)
# 
# Path: mapchete/_timer.py
# class Timer:
#     """
#     Context manager to facilitate timing code.
# 
#     Examples
#     --------
#     >>> with Timer() as t:
#             ...  # some longer running code
#     >>> print(t)  # prints elapsed time
# 
#     based on http://preshing.com/20110924/timing-your-code-using-pythons-with-statement/
#     """
# 
#     def __init__(self, elapsed=0.0, str_round=3):
#         self._elapsed = elapsed
#         self._str_round = str_round
#         self.start = None
#         self.end = None
# 
#     def __enter__(self):
#         self.start = time.time()
#         return self
# 
#     def __exit__(self, *args):
#         self.end = time.time()
#         self._elapsed = self.end - self.start
# 
#     def __lt__(self, other):
#         return self._elapsed < other._elapsed
# 
#     def __le__(self, other):
#         return self._elapsed <= other._elapsed
# 
#     def __eq__(self, other):
#         return self._elapsed == other._elapsed
# 
#     def __ne__(self, other):
#         return self._elapsed != other._elapsed
# 
#     def __ge__(self, other):
#         return self._elapsed >= other._elapsed
# 
#     def __gt__(self, other):
#         return self._elapsed > other._elapsed
# 
#     def __add__(self, other):
#         return Timer(elapsed=self._elapsed + other._elapsed)
# 
#     def __sub__(self, other):
#         return Timer(elapsed=self._elapsed - other._elapsed)
# 
#     def __repr__(self):
#         return "Timer(start=%s, end=%s, elapsed=%s)" % (
#             self.start,
#             self.end,
#             self.__str__(),
#         )
# 
#     def __str__(self):
#         minutes, seconds = divmod(self.elapsed, 60)
#         hours, minutes = divmod(minutes, 60)
#         if hours:
#             return "%sh %sm %ss" % (int(hours), int(minutes), int(seconds))
#         elif minutes:
#             return "%sm %ss" % (int(minutes), int(seconds))
#         else:
#             return "%ss" % round(seconds, self._str_round)
# 
#     @property
#     def elapsed(self):
#         return (
#             time.time() - self.start if self.start and not self.end else self._elapsed
#         )


import concurrent.futures
import logging
import multiprocessing
import os
import sys
import warnings
from concurrent.futures._base import CancelledError
from functools import partial
from cached_property import cached_property
from mapchete.errors import JobCancelledError
from mapchete.log import set_log_level
from mapchete._timer import Timer
        from dask.distributed import as_completed, Client, LocalCluster
        from dask.distributed import wait
        from dask.distributed import TimeoutError
        from dask.distributed import TimeoutError
        from distributed.comm.core import CommClosedError
                # (1) chunksize is reached, or
                # (2) remaining free task spots are less than tasks in chunk
                remaining_spots = max_submitted_tasks - self._submitted
                if len(chunk) % chunksize == 0 or remaining_spots == len(chunk):
                    logger.debug("submitted futures: %s", self._submitted)
                    logger.debug("remaining spots for futures: %s", remaining_spots)
                    logger.debug("current chunk size: %s", len(chunk))
                    self._submit_chunk(
                        chunk=chunk,
                        func=func,
                        fargs=fargs,
                        fkwargs=fkwargs,
                    )
                    chunk = []

                # yield finished tasks, if
                # (1) there are finished tasks available, or
                # (2) maximum allowed number of running tasks is reached
                max_submitted_tasks_reached = self._submitted >= max_submitted_tasks
                if self._ac_iterator.has_ready() or max_submitted_tasks_reached:
                    # yield batch of finished futures
                    # if maximum submitted tasks limit is reached, block call and wait for finished futures
                    logger.debug(
                        "wait for finished tasks: %s", max_submitted_tasks_reached
                    )
                    batch = self._ac_iterator.next_batch(
                        block=max_submitted_tasks_reached
                    )
                    try:
                        yield from self._yield_from_batch(batch)

# Path: mapchete/errors.py
# class JobCancelledError(Exception):
#     """Raised when Job gets cancelled."""
# 
# Path: mapchete/log.py
# def set_log_level(loglevel):
#     stream_handler.setLevel(loglevel)
#     for i in all_mapchete_packages:
#         logging.getLogger(i).setLevel(loglevel)
# 
# Path: mapchete/_timer.py
# class Timer:
#     """
#     Context manager to facilitate timing code.
# 
#     Examples
#     --------
#     >>> with Timer() as t:
#             ...  # some longer running code
#     >>> print(t)  # prints elapsed time
# 
#     based on http://preshing.com/20110924/timing-your-code-using-pythons-with-statement/
#     """
# 
#     def __init__(self, elapsed=0.0, str_round=3):
#         self._elapsed = elapsed
#         self._str_round = str_round
#         self.start = None
#         self.end = None
# 
#     def __enter__(self):
#         self.start = time.time()
#         return self
# 
#     def __exit__(self, *args):
#         self.end = time.time()
#         self._elapsed = self.end - self.start
# 
#     def __lt__(self, other):
#         return self._elapsed < other._elapsed
# 
#     def __le__(self, other):
#         return self._elapsed <= other._elapsed
# 
#     def __eq__(self, other):
#         return self._elapsed == other._elapsed
# 
#     def __ne__(self, other):
#         return self._elapsed != other._elapsed
# 
#     def __ge__(self, other):
#         return self._elapsed >= other._elapsed
# 
#     def __gt__(self, other):
#         return self._elapsed > other._elapsed
# 
#     def __add__(self, other):
#         return Timer(elapsed=self._elapsed + other._elapsed)
# 
#     def __sub__(self, other):
#         return Timer(elapsed=self._elapsed - other._elapsed)
# 
#     def __repr__(self):
#         return "Timer(start=%s, end=%s, elapsed=%s)" % (
#             self.start,
#             self.end,
#             self.__str__(),
#         )
# 
#     def __str__(self):
#         minutes, seconds = divmod(self.elapsed, 60)
#         hours, minutes = divmod(minutes, 60)
#         if hours:
#             return "%sh %sm %ss" % (int(hours), int(minutes), int(seconds))
#         elif minutes:
#             return "%sm %ss" % (int(minutes), int(seconds))
#         else:
#             return "%ss" % round(seconds, self._str_round)
# 
#     @property
#     def elapsed(self):
#         return (
#             time.time() - self.start if self.start and not self.end else self._elapsed
#         )


# Path: mapchete/_executor.py
import concurrent.futures
import logging
import multiprocessing
import os
import sys
import warnings
from concurrent.futures._base import CancelledError
from functools import partial
from cached_property import cached_property
from mapchete.errors import JobCancelledError
from mapchete.log import set_log_level
from mapchete._timer import Timer
        from dask.distributed import as_completed, Client, LocalCluster
        from dask.distributed import wait
        from dask.distributed import TimeoutError
        from dask.distributed import TimeoutError
        from distributed.comm.core import CommClosedError

                # (1) chunksize is reached, or
                # (2) remaining free task spots are less than tasks in chunk
                remaining_spots = max_submitted_tasks - self._submitted
                if len(chunk) % chunksize == 0 or remaining_spots == len(chunk):
                    logger.debug("submitted futures: %s", self._submitted)
                    logger.debug("remaining spots for futures: %s", remaining_spots)
                    logger.debug("current chunk size: %s", len(chunk))
                    self._submit_chunk(
                        chunk=chunk,
                        func=func,
                        fargs=fargs,
                        fkwargs=fkwargs,
                    )
                    chunk = []

                # yield finished tasks, if
                # (1) there are finished tasks available, or
                # (2) maximum allowed number of running tasks is reached
                max_submitted_tasks_reached = self._submitted >= max_submitted_tasks
                if self._ac_iterator.has_ready() or max_submitted_tasks_reached:
                    # yield batch of finished futures
                    # if maximum submitted tasks limit is reached, block call and wait for finished futures
                    logger.debug(
                        "wait for finished tasks: %s", max_submitted_tasks_reached
                    )
                    batch = self._ac_iterator.next_batch(
                        block=max_submitted_tasks_reached
                    )
                    try:
                        yield from self._yield_from_batch(batch)

                    except JobCancelledError:  # pragma: no cover