<commit_before>"""A Future class similar to the one in PEP 3148."""

__all__ = ['Future', 'InvalidStateError', 'InvalidTimeoutError', 'sleep']

import concurrent.futures._base

from . import events

# States for Future.
_PENDING = 'PENDING'  # Next states: _CANCELLED, _RUNNING.
_CANCELLED = 'CANCELLED'  # End state.
_RUNNING = 'RUNNING'  # Next state: _FINISHED.
_FINISHED = 'FINISHED'  # End state.
_DONE_STATES = (_CANCELLED, _FINISHED)


Error = concurrent.futures._base.Error


class InvalidStateError(Error):
    """The operation is not allowed in this state."""
    # TODO: Show the future, its state, the method, and the required state.


class InvalidTimeoutError(Error):
    """Called result() or exception() with timeout != 0."""
    # TODO: Print a nice error message.


class Future:
    """This class is *almost* compatible with concurrent.futures.Future.

    Differences:

    - result() and exception() do not take a timeout argument and
      raise an exception when the future isn't done yet.

    - Callbacks registered with add_done_callback() are always called
      via the event loop's call_soon_threadsafe().

    - This class is not compatible with the wait() and as_completed()
      methods in the concurrent.futures package.

    (In Python 3.4 or later we may be able to unify the implementations.)
    """

    # TODO: PEP 3148 seems to say that cancel() does not call the
    # callbacks, but set_running_or_notify_cancel() does (if cancel()
    # was called).  Here, cancel() schedules the callbacks, and
    # set_running_or_notify_cancel() just sets the state.

    # Class variables serving to as defaults for instance variables.
    _state = _PENDING
    _result = None
    _exception = None

    def __init__(self):
        """XXX"""
        self._callbacks = []

    def __repr__(self):
        """XXX"""
        if self._callbacks:
            # TODO: Maybe limit the list of callbacks if there are many?
            return 'Future<{}, {}>'.format(self._state, self._callbacks)
        else:
            return 'Future<{}>'.format(self._state)

    def cancel(self):
        """XXX"""
        if self._state != _PENDING:
            return False
        self._state = _CANCELLED
        self._schedule_callbacks()
        return True

    def _schedule_callbacks(self):
        """XXX"""
        callbacks = self._callbacks[:]
        if not callbacks:
            return
        # Is it worth emptying the callbacks?  It may reduce the
        # usefulness of repr().
        self._callbacks[:] = []
        event_loop = events.get_event_loop()
        for callback in self._callbacks:
            event_loop.call_soon(callback, self)

    def cancelled(self):
        """XXX"""
        return self._state == _CANCELLED

    def running(self):
        """XXX"""
        return self._state == _RUNNING

    def done(self):
        """XXX"""
        return self._state in _DONE_STATES

    def result(self, timeout=0):
        """XXX"""
        if timeout != 0:
            raise InvalidTimeoutError
        if self._state == _CANCELLED:
            raise CancelledError
        if self._state != _FINISHED:
            raise InvalidStateError
        if self._exception is not None:
            raise self._exception
        return self._result

    def exception(self, timeout=0):
        """XXX"""
        if timeout != 0:
            raise InvalidTimeoutError
        if self._state == _CANCELLED:
            raise CancelledError
        if self._state != _FINISHED:
            raise InvalidStateError
        return self._exception

    def add_done_callback(self, fn):
        """XXX"""
        if self._state in _DONE_STATES:
            events.get_event_loop().call_soon(fn, self)
        else:
            self._callbacks.append(fn)

    # So-called internal methods.

    def set_running_or_notify_cancel(self):
        """XXX"""
        if self._state == _CANCELLED:
            return False
        if self._state != _PENDING:
            raise InvalidStateError
        self._state = _RUNNING
        return True

    def set_result(self, result):
        """XXX"""
        if self._state != _RUNNING:
            raise InvalidStateError
        self._result = result
        self._state = _FINISHED
        self._schedule_callbacks()

    def set_exception(self, exception):
        """XXX"""
        if self._state != _RUNNING:
            raise InvalidStateError
        self._exception = exception
        self._state = _FINISHED
        self._schedule_callbacks()

    def _copy_state(self, other):
        """Internal helper to copy state from another Future.<commit_msg>Better __repr__().<commit_after>"""A Future class similar to the one in PEP 3148."""

__all__ = ['Future', 'InvalidStateError', 'InvalidTimeoutError', 'sleep']

import concurrent.futures._base

from . import events

# States for Future.
_PENDING = 'PENDING'  # Next states: _CANCELLED, _RUNNING.
_CANCELLED = 'CANCELLED'  # End state.
_RUNNING = 'RUNNING'  # Next state: _FINISHED.
_FINISHED = 'FINISHED'  # End state.
_DONE_STATES = (_CANCELLED, _FINISHED)


Error = concurrent.futures._base.Error


class InvalidStateError(Error):
    """The operation is not allowed in this state."""
    # TODO: Show the future, its state, the method, and the required state.


class InvalidTimeoutError(Error):
    """Called result() or exception() with timeout != 0."""
    # TODO: Print a nice error message.


class Future:
    """This class is *almost* compatible with concurrent.futures.Future.

    Differences:

    - result() and exception() do not take a timeout argument and
      raise an exception when the future isn't done yet.

    - Callbacks registered with add_done_callback() are always called
      via the event loop's call_soon_threadsafe().

    - This class is not compatible with the wait() and as_completed()
      methods in the concurrent.futures package.

    (In Python 3.4 or later we may be able to unify the implementations.)
    """

    # TODO: PEP 3148 seems to say that cancel() does not call the
    # callbacks, but set_running_or_notify_cancel() does (if cancel()
    # was called).  Here, cancel() schedules the callbacks, and
    # set_running_or_notify_cancel() just sets the state.

    # Class variables serving to as defaults for instance variables.
    _state = _PENDING
    _result = None
    _exception = None

    def __init__(self):
        """XXX"""
        self._callbacks = []

    def __repr__(self):
        """XXX"""
        if self._state == _FINISHED:
            if self._exception is not None:
                return 'Future<exception={}>'.format(self._exception)
            else:
                return 'Future<result={}>'.format(self._result)
        elif self._callbacks:
            size = len(self._callbacks)
            if size > 2:
                return 'Future<{}, [{}, <{} more>, {}]>'.format(
                    self._state, self._callbacks[0],
                    size-2, self._callbacks[-1])
            else:
                return 'Future<{}, {}>'.format(self._state, self._callbacks)
        else:
            return 'Future<{}>'.format(self._state)

    def cancel(self):
        """XXX"""
        if self._state != _PENDING:
            return False
        self._state = _CANCELLED
        self._schedule_callbacks()
        return True

    def _schedule_callbacks(self):
        """XXX"""
        callbacks = self._callbacks[:]
        if not callbacks:
            return
        # Is it worth emptying the callbacks?  It may reduce the
        # usefulness of repr().
        self._callbacks[:] = []
        event_loop = events.get_event_loop()
        for callback in self._callbacks:
            event_loop.call_soon(callback, self)

    def cancelled(self):
        """XXX"""
        return self._state == _CANCELLED

    def running(self):
        """XXX"""
        return self._state == _RUNNING

    def done(self):
        """XXX"""
        return self._state in _DONE_STATES

    def result(self, timeout=0):
        """XXX"""
        if timeout != 0:
            raise InvalidTimeoutError
        if self._state == _CANCELLED:
            raise CancelledError
        if self._state != _FINISHED:
            raise InvalidStateError
        if self._exception is not None:
            raise self._exception
        return self._result

    def exception(self, timeout=0):
        """XXX"""
        if timeout != 0:
            raise InvalidTimeoutError
        if self._state == _CANCELLED:
            raise CancelledError
        if self._state != _FINISHED:
            raise InvalidStateError
        return self._exception

    def add_done_callback(self, fn):
        """XXX"""
        if self._state in _DONE_STATES:
            events.get_event_loop().call_soon(fn, self)
        else:
            self._callbacks.append(fn)

    # So-called internal methods.

    # TODO: set_running_or_notify_cancel() is not really needed since
    # we're not in a threaded environment.  Consider allowing
    # transitions directly from PENDING to FINISHED.

    def set_running_or_notify_cancel(self):
        """XXX"""
        if self._state == _CANCELLED:
            return False
        if self._state != _PENDING:
            raise InvalidStateError
        self._state = _RUNNING
        return True

    def set_result(self, result):
        """XXX"""
        if self._state != _RUNNING:
            raise InvalidStateError
        self._result = result
        self._state = _FINISHED
        self._schedule_callbacks()

    def set_exception(self, exception):
        """XXX"""
        if self._state != _RUNNING:
            raise InvalidStateError
        self._exception = exception
        self._state = _FINISHED
        self._schedule_callbacks()

    def _copy_state(self, other):
        """Internal helper to copy state from another Future.
{'fraction_non_alphanumeric': 0.09877418701246074, 'fraction_numerical': 0.0034444331881268364, 'mean_word_length': 2.273209549071618, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 12, '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': '3551825', 'n_tokens_mistral': 2853, 'n_tokens_neox': 2718, 'n_words': 855}