from numpy.testing import assert_equal
import pytest

from statsmodels.tools.decorators import cache_readonly, deprecated_alias


def test_cache_readonly():

    class Example:
        def __init__(self):
            self._cache = {}
            self.a = 0

        @cache_readonly
        def b(self):
            return 1

    ex = Example()

    # Try accessing/setting a readonly attribute
    assert_equal(ex.__dict__, dict(a=0, _cache={}))

    b = ex.b
    assert_equal(b, 1)
    assert_equal(ex.__dict__, dict(a=0, _cache=dict(b=1,)))
    # assert_equal(ex.__dict__, dict(a=0, b=1, _cache=dict(b=1)))

    with pytest.raises(AttributeError):
        ex.b = -1

    assert_equal(ex._cache, dict(b=1,))


def dummy_factory(msg, remove_version, warning):
    class Dummy:
        y = deprecated_alias("y", "x",
                             remove_version=remove_version,
                             msg=msg,
                             warning=warning)

        def __init__(self, y):
            self.x = y

    return Dummy(1)


@pytest.mark.parametrize("warning", [FutureWarning, UserWarning])
@pytest.mark.parametrize("remove_version", [None, "0.11"])
@pytest.mark.parametrize("msg", ["test message", None])
def test_deprecated_alias(msg, remove_version, warning):
    dummy_set = dummy_factory(msg, remove_version, warning)
    with pytest.warns(warning) as w:
        dummy_set.y = 2
    assert dummy_set.x == 2

    assert warning.__class__ is w[0].category.__class__

    dummy_get = dummy_factory(msg, remove_version, warning)
    with pytest.warns(warning) as w:
        x = dummy_get.y
    assert x == 1

    assert warning.__class__ is w[0].category.__class__
    message = str(w[0].message)
    if not msg:
        if remove_version:
            assert "will be removed" in message
        else:
            assert "will be removed" not in message
    else:
        assert msg in message
