<commit_before>import sys
import traceback

import pytest

from pykka import Future, Timeout, get_all

from tests import has_gevent


@pytest.fixture
def future_class(runtime):
    return runtime.future_class


@pytest.fixture
def future(runtime):
    return runtime.future_class()


@pytest.fixture
def futures(runtime):
    return [runtime.future_class() for _ in range(3)]


def test_base_future_get_is_not_implemented():
    future = Future()

    with pytest.raises(NotImplementedError):
        future.get()


def test_base_future_set_is_not_implemented():
    future = Future()

    with pytest.raises(NotImplementedError):
        future.set(None)


def test_base_future_set_exception_is_not_implemented():
    future = Future()

    with pytest.raises(NotImplementedError):
        future.set_exception(None)


def test_set_multiple_times_fails(future):
    future.set(0)

    with pytest.raises(Exception):
        future.set(0)


def test_get_all_blocks_until_all_futures_are_available(futures):
    futures[0].set(0)
    futures[1].set(1)
    futures[2].set(2)

    result = get_all(futures)

    assert result == [0, 1, 2]


def test_get_all_raises_timeout_if_not_all_futures_are_available(futures):
    futures[0].set(0)
    futures[1].set(1)
    # futures[2] is unset

    with pytest.raises(Timeout):
        get_all(futures, timeout=0)


def test_get_all_can_be_called_multiple_times(futures):
    futures[0].set(0)
    futures[1].set(1)
    futures[2].set(2)

    result1 = get_all(futures)
    result2 = get_all(futures)

    assert result1 == result2


def test_future_in_future_works(future_class):
    inner_future = future_class()
    inner_future.set('foo')

    outer_future = future_class()
    outer_future.set(inner_future)

    assert outer_future.get().get() == 'foo'


def test_get_raises_exception_with_full_traceback(runtime, future_class):
    exc_class_get = None
    exc_class_set = None
    exc_instance_get = None
    exc_instance_set = None
    exc_traceback_get = None
    exc_traceback_set = None
    future = future_class()

    try:
        raise NameError('foo')
    except NameError:
        exc_class_set, exc_instance_set, exc_traceback_set = sys.exc_info()
        future.set_exception()

    # We could move to another thread at this point

    try:
        future.get()
    except NameError:
        exc_class_get, exc_instance_get, exc_traceback_get = sys.exc_info()

    assert exc_class_set == exc_class_get
    assert exc_instance_set == exc_instance_get

    exc_traceback_list_set = list(
        reversed(traceback.extract_tb(exc_traceback_set))
    )
    exc_traceback_list_get = list(
        reversed(traceback.extract_tb(exc_traceback_get))
    )

    if runtime.name == 'gevent':
        # gevent prints the first half of the traceback instead of
        # passing it through to the other side of the AsyncResult.<commit_msg>futures: Eliminate one test fixture<commit_after>import sys
import traceback

import pytest

from pykka import Future, Timeout, get_all

from tests import has_gevent


@pytest.fixture
def future(runtime):
    return runtime.future_class()


@pytest.fixture
def futures(runtime):
    return [runtime.future_class() for _ in range(3)]


def test_base_future_get_is_not_implemented():
    future = Future()

    with pytest.raises(NotImplementedError):
        future.get()


def test_base_future_set_is_not_implemented():
    future = Future()

    with pytest.raises(NotImplementedError):
        future.set(None)


def test_base_future_set_exception_is_not_implemented():
    future = Future()

    with pytest.raises(NotImplementedError):
        future.set_exception(None)


def test_set_multiple_times_fails(future):
    future.set(0)

    with pytest.raises(Exception):
        future.set(0)


def test_get_all_blocks_until_all_futures_are_available(futures):
    futures[0].set(0)
    futures[1].set(1)
    futures[2].set(2)

    result = get_all(futures)

    assert result == [0, 1, 2]


def test_get_all_raises_timeout_if_not_all_futures_are_available(futures):
    futures[0].set(0)
    futures[1].set(1)
    # futures[2] is unset

    with pytest.raises(Timeout):
        get_all(futures, timeout=0)


def test_get_all_can_be_called_multiple_times(futures):
    futures[0].set(0)
    futures[1].set(1)
    futures[2].set(2)

    result1 = get_all(futures)
    result2 = get_all(futures)

    assert result1 == result2


def test_future_in_future_works(runtime):
    inner_future = runtime.future_class()
    inner_future.set('foo')

    outer_future = runtime.future_class()
    outer_future.set(inner_future)

    assert outer_future.get().get() == 'foo'


def test_get_raises_exception_with_full_traceback(runtime):
    exc_class_get = None
    exc_class_set = None
    exc_instance_get = None
    exc_instance_set = None
    exc_traceback_get = None
    exc_traceback_set = None
    future = runtime.future_class()

    try:
        raise NameError('foo')
    except NameError:
        exc_class_set, exc_instance_set, exc_traceback_set = sys.exc_info()
        future.set_exception()

    # We could move to another thread at this point

    try:
        future.get()
    except NameError:
        exc_class_get, exc_instance_get, exc_traceback_get = sys.exc_info()

    assert exc_class_set == exc_class_get
    assert exc_instance_set == exc_instance_get

    exc_traceback_list_set = list(
        reversed(traceback.extract_tb(exc_traceback_set))
    )
    exc_traceback_list_get = list(
        reversed(traceback.extract_tb(exc_traceback_get))
    )

    if runtime.name == 'gevent':
        # gevent prints the first half of the traceback instead of
        # passing it through to the other side of the AsyncResult.
{'fraction_non_alphanumeric': 0.08892382948986723, 'fraction_numerical': 0.009783368273934312, 'mean_word_length': 3.7235973597359737, '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': '5246782', 'n_tokens_mistral': 2002, 'n_tokens_neox': 1971, 'n_words': 369}