<commit_before># -*- coding: utf-8 -*-

from abc import ABCMeta, abstractmethod

from shapely.affinity import translate

from image import ImageWindow
from logging import Loggable, SilentLogger, Logger
from information import ChainInformation, WorkflowInformationCollection, WorkflowInformation

__author__ = "<NAME> <<EMAIL>>"
__version__ = "0.1"


class ImageProvider(Loggable):
    """An image provider is a class which generates a set of images to be processed by a workflow chein
    """
    __metaclass__ = ABCMeta

    def __init__(self, silent_fail=False, logger=SilentLogger()):
        """Constructs instances of ImageProvider

        Parameters
        ----------
        silent_fail: bool
            True for putting the image provider in silent fail mode. In this situation, when an image cannot be
            extracted, the provider simply ignore the error and skip the image. Otherwise, when set to False,
            the provider raises an error when an image extraction fails.
        logger: Logger (optional, default: SilentLogger)
            A logger object
        """
        Loggable.__init__(self, logger)
        self._silent_fail = silent_fail

    @abstractmethod
    def get_images(self):
        """
        Return the images to be processed by instances of the workflow

        Returns
        -------
        images: iterable (subtype: Image)
            An iterable of images

        Exceptions
        ----------
        ImageExtractionException:
            Raised when an image cannot be extracted. This error is never raised when the image provider is in
            silent_fail mode. In this situation, the provider fetches as many images as possible and returns only the
            successfully fetched images in the array.
        """
        pass


class WorkflowExecutor(Loggable):
    """A class for encapsulating the execution of a workflow. It provides two abstract methods to implement for
    generating the images to process and to post-process the generated data after each run of the workflow.
    The execution of the workflow executor is something like :

        .execute(image, info) :
            {get_images} -- images --> [ image --> {workflow.process} -- data --> {after} ] --> workflow_info
    """
    __metaclass__ = ABCMeta

    def __init__(self, workflow, mute_workflow=True, logger=SilentLogger()):
        """Constructs a WorkflowExecutor for the given workflow object

        Parameters
        ----------
        workflow: SLDCWorkflow
            The workflow to execute
        mute_workflow: bool
            True for disabling the workflow logging during execution on sub-images
        logger: Logger (optional, default: a SilentLogger instance)
            A logger object
        """
        Loggable.__init__(self, logger)
        self._workflow = workflow
        self._mute_workflow = mute_workflow

    def execute(self, image, workflow_info_collection):
        """Execute the workflow with the images generated by get_images

        Parameters
        ----------
        image: Image
            The base image from which must be extracted the sub images to process
        workflow_info_collection: WorkflowInformationCollection
            The information generated by the previous workflow in a workflow chain

        Returns
        -------
        workflow_information: WorkflowInformation
            The workflow information object containing the data generated by all the executions of the stored workflow
        """
        workflow_information = WorkflowInformation([], [], [], [], None)
        images = self.get_windows(image, workflow_info_collection)
        self.logger.info("WorkflowExecutor : {} image(s) to process.".format(len(images)))
        previous_verbosity = self._workflow.logger.level
        for sub_image in images:
            if self._mute_workflow:
                self._workflow.logger.level = Logger.ERROR
            returned_info = self._workflow.process(sub_image)
            if self._mute_workflow:
                self._workflow.logger.level = previous_verbosity
            self.after(sub_image, returned_info)
            workflow_information.merge(returned_info)
        return workflow_information

    @abstractmethod
    def get_windows(self, image, workflow_info_collection):
        """Given the workflow_info_collection produces by execution of sldc workflows, produces images objects for the
        next execution
<commit_msg>log progress in workflow executor<commit_after># -*- coding: utf-8 -*-

from abc import ABCMeta, abstractmethod

from shapely.affinity import translate

from image import ImageWindow
from logging import Loggable, SilentLogger, Logger
from information import ChainInformation, WorkflowInformationCollection, WorkflowInformation

__author__ = "<NAME> <<EMAIL>>"
__version__ = "0.1"


class ImageProvider(Loggable):
    """An image provider is a class which generates a set of images to be processed by a workflow chein
    """
    __metaclass__ = ABCMeta

    def __init__(self, silent_fail=False, logger=SilentLogger()):
        """Constructs instances of ImageProvider

        Parameters
        ----------
        silent_fail: bool
            True for putting the image provider in silent fail mode. In this situation, when an image cannot be
            extracted, the provider simply ignore the error and skip the image. Otherwise, when set to False,
            the provider raises an error when an image extraction fails.
        logger: Logger (optional, default: SilentLogger)
            A logger object
        """
        Loggable.__init__(self, logger)
        self._silent_fail = silent_fail

    @abstractmethod
    def get_images(self):
        """
        Return the images to be processed by instances of the workflow

        Returns
        -------
        images: iterable (subtype: Image)
            An iterable of images

        Exceptions
        ----------
        ImageExtractionException:
            Raised when an image cannot be extracted. This error is never raised when the image provider is in
            silent_fail mode. In this situation, the provider fetches as many images as possible and returns only the
            successfully fetched images in the array.
        """
        pass


class WorkflowExecutor(Loggable):
    """A class for encapsulating the execution of a workflow. It provides two abstract methods to implement for
    generating the images to process and to post-process the generated data after each run of the workflow.
    The execution of the workflow executor is something like :

        .execute(image, info) :
            {get_images} -- images --> [ image --> {workflow.process} -- data --> {after} ] --> workflow_info
    """
    __metaclass__ = ABCMeta

    def __init__(self, workflow, mute_workflow=True, logger=SilentLogger()):
        """Constructs a WorkflowExecutor for the given workflow object

        Parameters
        ----------
        workflow: SLDCWorkflow
            The workflow to execute
        mute_workflow: bool
            True for disabling the workflow logging during execution on sub-images
        logger: Logger (optional, default: a SilentLogger instance)
            A logger object
        """
        Loggable.__init__(self, logger)
        self._workflow = workflow
        self._mute_workflow = mute_workflow

    def execute(self, image, workflow_info_collection):
        """Execute the workflow with the images generated by get_images

        Parameters
        ----------
        image: Image
            The base image from which must be extracted the sub images to process
        workflow_info_collection: WorkflowInformationCollection
            The information generated by the previous workflow in a workflow chain

        Returns
        -------
        workflow_information: WorkflowInformation
            The workflow information object containing the data generated by all the executions of the stored workflow
        """
        workflow_information = WorkflowInformation([], [], [], [], None)
        images = self.get_windows(image, workflow_info_collection)
        self.logger.info("WorkflowExecutor : {} image(s) to process.".format(len(images)))
        previous_verbosity = self._workflow.logger.level
        for i, sub_image in enumerate(images):
            self.logger.info("WorkflowExecutor : process image {}/{}.".format(i + 1, len(images)))
            if self._mute_workflow:
                self._workflow.logger.level = Logger.ERROR
            returned_info = self._workflow.process(sub_image)
            if self._mute_workflow:
                self._workflow.logger.level = previous_verbosity
            self.after(sub_image, returned_info)
            workflow_information.merge(returned_info)
        return workflow_information

    @abstractmethod
    def get_windows(self, image, workflow_info_collection):
        """Given the workflow_info_collection produces by execution of sldc workflows, produces images objects for the
        next execution

{'fraction_non_alphanumeric': 0.07198765295998236, 'fraction_numerical': 0.0007716900011024143, 'mean_word_length': 2.4986502121095255, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1407834', 'n_tokens_mistral': 2212, 'n_tokens_neox': 2128, 'n_words': 829}