<commit_before>import contextlib, threading, time
from . runner import Runner, STATE
from .. util import deprecated, log
from .. util.threads.animation_threading import AnimationThreading
from .. project import attributes, fields


class Animation(object):
    free_run = False
    pre_recursion = fields.default_converter
    FAIL_ON_EXCEPTION = False

    @classmethod
    def construct(cls, project, *, run=None, name=None, data=None, **desc):
        """
        Construct an animation, set the runner, and add in the two
        "reserved fields" `name` and `data`.
        """
        try:
            a = cls(project.layout, **desc)
            a._set_runner(run or {})
        except Exception as e:
            if cls.FAIL_ON_EXCEPTION:
                raise
            from . failed import Failed
            a = Failed(project.layout, desc, e)

        a.name = name
        a.data = data
        return a

    def __init__(self, layout, *, preclear=True, **kwds):
        attributes.set_reserved(self, 'animation', **kwds)
        self.layout = layout
        self.internal_delay = None
        self.on_completion = None
        self.state = STATE.ready
        self.preclear = preclear

    @property
    def _led(self):
        """Many BiblioPixelAnimations use the "protected" variable _led."""
        return self.layout

    @_led.setter
    def _led(self, layout):
        self.layout = layout

    @property
    def color_list(self):
        return self.layout.color_list

    @color_list.setter
    def color_list(self, cl):
        self.layout.color_list[:] = cl

    @property
    def completed(self):
        """Many BiblioPixelAnimations use the old `completed` variable."""
        return self.state == STATE.complete

    @completed.setter
    def completed(self, state):
        self.state = STATE.complete if state else STATE.running

    def pre_run(self):
        pass

    @property
    def title(self):
        return self.__class__.__name__

    def step(self, amt=1):
        pass

    def cleanup(self, clean_layout=True):
        self.threading.cleanup()
        # Some cases we may not want to clear the screen
        # Like with the remote, it would flash between anims
        if clean_layout:
            self.layout.cleanup()

    def preframe_callback(self):
        """
        preframe_callback is called right before the start of a frame rendering
        pass.

        The ``Project`` writes over this method, for the top-level animation
        only, in order to drain its event_queue at a moment where no rendering
        is happening to avoid race conditions.
        """
        pass

    def start(self):
        self.threading.start()

    def run_all_frames(self):
        for i in self.generate_frames():
            pass

    def generate_frames(self, clean_layout=True):
        with self._run_context(clean_layout):
            while self.state == STATE.running:
                self._run_one_frame()
                yield

    def run(self, **kwds):
        deprecated.deprecated('BaseAnimation.run')
        self._set_runner(kwds)
        self.start()

    def _check_delay(self):
        if self.free_run:<commit_msg>Add BaseAnimation.stop<commit_after>import contextlib, threading, time
from . runner import Runner, STATE
from .. util import deprecated, log
from .. util.threads.animation_threading import AnimationThreading
from .. project import attributes, fields


class Animation(object):
    free_run = False
    pre_recursion = fields.default_converter
    FAIL_ON_EXCEPTION = False

    @classmethod
    def construct(cls, project, *, run=None, name=None, data=None, **desc):
        """
        Construct an animation, set the runner, and add in the two
        "reserved fields" `name` and `data`.
        """
        try:
            a = cls(project.layout, **desc)
            a._set_runner(run or {})
        except Exception as e:
            if cls.FAIL_ON_EXCEPTION:
                raise
            from . failed import Failed
            a = Failed(project.layout, desc, e)

        a.name = name
        a.data = data
        return a

    def __init__(self, layout, *, preclear=True, **kwds):
        attributes.set_reserved(self, 'animation', **kwds)
        self.layout = layout
        self.internal_delay = None
        self.on_completion = None
        self.state = STATE.ready
        self.preclear = preclear

    @property
    def _led(self):
        """Many BiblioPixelAnimations use the "protected" variable _led."""
        return self.layout

    @_led.setter
    def _led(self, layout):
        self.layout = layout

    @property
    def color_list(self):
        return self.layout.color_list

    @color_list.setter
    def color_list(self, cl):
        self.layout.color_list[:] = cl

    @property
    def completed(self):
        """Many BiblioPixelAnimations use the old `completed` variable."""
        return self.state == STATE.complete

    @completed.setter
    def completed(self, state):
        self.state = STATE.complete if state else STATE.running

    def pre_run(self):
        pass

    @property
    def title(self):
        return self.__class__.__name__

    def step(self, amt=1):
        pass

    def cleanup(self, clean_layout=True):
        self.threading.cleanup()
        # Some cases we may not want to clear the screen
        # Like with the remote, it would flash between anims
        if clean_layout:
            self.layout.cleanup()

    def preframe_callback(self):
        """
        preframe_callback is called right before the start of a frame rendering
        pass.

        The ``Project`` writes over this method, for the top-level animation
        only, in order to drain its event_queue at a moment where no rendering
        is happening to avoid race conditions.
        """
        pass

    def start(self):
        self.threading.start()

    def stop(self):
        self.threading.stop_event.set()

    def run_all_frames(self):
        for i in self.generate_frames():
            pass

    def generate_frames(self, clean_layout=True):
        with self._run_context(clean_layout):
            while self.state == STATE.running:
                self._run_one_frame()
                yield

    def run(self, **kwds):
        deprecated.deprecated('BaseAnimation.run')
        self._set_runner(kwds)
        self.start()

    def _check_delay(self):
        if self.free_run:
{'fraction_non_alphanumeric': 0.08939676616915423, 'fraction_numerical': 0.0003109452736318408, 'mean_word_length': 2.1878097125867195, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '2995299', 'n_tokens_mistral': 1834, 'n_tokens_neox': 1750, 'n_words': 531}