#------------------------------------------------------------------------------
# Copyright (c) 2018-2019, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
#------------------------------------------------------------------------------
"""Test the typed dictionary.


"""
import sys
import pytest

from atom.api import Atom, Dict, Int, atomdict


@pytest.fixture
def atom_dict():
    """Atom with different Dict members.

    """
    class DictAtom(Atom):
        untyped = Dict()
        keytyped = Dict(Int())
        valuetyped = Dict(value=Int())
        fullytyped = Dict(Int(), Int())
        untyped_default = Dict(default={1: 1})
        keytyped_default = Dict(Int(), default={1: 1})
        valuetyped_default = Dict(value=Int(), default={1: 1})
        fullytyped_default = Dict(Int(), Int(), default={1: 1})

    return DictAtom()


MEMBERS = ['untyped', 'keytyped', 'valuetyped', 'fullytyped',
           'untyped_default', 'keytyped_default', 'valuetyped_default',
           'fullytyped_default']


@pytest.mark.parametrize('member', MEMBERS)
def test_instance(atom_dict, member):
    """Test the repr.

    """
    assert isinstance(getattr(atom_dict, member), atomdict)


@pytest.mark.parametrize('member', MEMBERS)
def test_repr(atom_dict, member):
    """Test the repr.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert repr(getattr(atom_dict, member)) == repr(d)


@pytest.mark.parametrize('member', MEMBERS)
def test_len(atom_dict, member):
    """Test the len.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert len(getattr(atom_dict, member)) == len(d)


@pytest.mark.parametrize('member', MEMBERS)
def test_contains(atom_dict, member):
    """Test __contains__.

    """
    d = {i: i**2 for i in range(10)}
    setattr(atom_dict, member, d)
    assert 5 in getattr(atom_dict, member)
    del getattr(atom_dict, member)[5]
    assert 5 not in getattr(atom_dict, member)

@pytest.mark.parametrize('member', MEMBERS)
def test_keys(atom_dict, member):
    """Test the keys.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert getattr(atom_dict, member).keys() == d.keys()


@pytest.mark.parametrize('member', MEMBERS)
def test_copy(atom_dict, member):
    """Test copy.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert getattr(atom_dict, member).copy() == d


def test_setitem(atom_dict):
    """Test setting items.

    """
    atom_dict.untyped[''] = 1
    assert atom_dict.untyped[''] == 1

    atom_dict.keytyped[1] = ''
    assert atom_dict.keytyped[1] == ''
    with pytest.raises(TypeError):
        atom_dict.keytyped[''] = 1

    atom_dict.valuetyped[1] = 1
    assert atom_dict.valuetyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.valuetyped[''] = ''

    atom_dict.fullytyped[1] = 1
    assert atom_dict.fullytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped[''] = 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped[1] = ''


def test_setdefault(atom_dict):
    """Test using setdefault.

    """

    assert atom_dict.untyped.setdefault('',  1) == 1
    assert atom_dict.untyped.setdefault('',  2) == 1
    assert atom_dict.untyped[''] == 1

    assert atom_dict.keytyped.setdefault(1, '') == ''
    assert atom_dict.keytyped[1] == ''
    with pytest.raises(TypeError):
        atom_dict.keytyped.setdefault('', 1)

    assert atom_dict.valuetyped.setdefault(1, 1) == 1
    assert atom_dict.valuetyped.setdefault(1, '') == 1
    assert atom_dict.valuetyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.valuetyped.setdefault(2, '')

    assert atom_dict.fullytyped.setdefault(1, 1) == 1
    assert atom_dict.fullytyped.setdefault(1, '') == 1
    assert atom_dict.fullytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped.setdefault('', 1)
    with pytest.raises(TypeError):
        atom_dict.fullytyped.setdefault(2, '')


def test_update(atom_dict):
    """Test update a dict.

    """
    atom_dict.untyped.update({'': 1})
    assert atom_dict.untyped[''] == 1
    atom_dict.untyped.update([('1', 1)])
    assert atom_dict.untyped['1'] == 1

    atom_dict.keytyped.update({1: 1})
    assert atom_dict.keytyped[1] == 1
    atom_dict.keytyped.update([(2, 1)])
    assert atom_dict.keytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.keytyped.update({'': 1})

    atom_dict.valuetyped.update({1: 1})
    assert atom_dict.valuetyped[1] == 1
    atom_dict.valuetyped.update([(2, 1)])
    assert atom_dict.valuetyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.valuetyped.update({'': ''})

    atom_dict.fullytyped.update({1: 1})
    assert atom_dict.fullytyped[1] == 1
    atom_dict.fullytyped.update([(2, 1)])
    assert atom_dict.fullytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped.update({'': 1})
    with pytest.raises(TypeError):
        atom_dict.fullytyped.update({'': ''})

[((1130, 1172), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""member"""', 'MEMBERS'], {}), "('member', MEMBERS)\n", (1153, 1172), False, 'import pytest\n'), ((1305, 1347), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""member"""', 'MEMBERS'], {}), "('member', MEMBERS)\n", (1328, 1347), False, 'import pytest\n'), ((1631, 1673), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""member"""', 'MEMBERS'], {}), "('member', MEMBERS)\n", (1654, 1673), False, 'import pytest\n'), ((1953, 1995), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""member"""', 'MEMBERS'], {}), "('member', MEMBERS)\n", (1976, 1995), False, 'import pytest\n'), ((2270, 2312), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""member"""', 'MEMBERS'], {}), "('member', MEMBERS)\n", (2293, 2312), False, 'import pytest\n'), ((2598, 2640), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""member"""', 'MEMBERS'], {}), "('member', MEMBERS)\n", (2621, 2640), False, 'import pytest\n'), ((589, 595), 'atom.api.Dict', 'Dict', ([], {}), '()\n', (593, 595), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((732, 754), 'atom.api.Dict', 'Dict', ([], {'default': '{(1): 1}'}), '(default={(1): 1})\n', (736, 754), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((3127, 3151), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (3140, 3151), False, 'import pytest\n'), ((3270, 3294), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (3283, 3294), False, 'import pytest\n'), ((3416, 3440), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (3429, 3440), False, 'import pytest\n'), ((3488, 3512), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (3501, 3512), False, 'import pytest\n'), ((3872, 3896), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (3885, 3896), False, 'import pytest\n'), ((4102, 4126), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (4115, 4126), False, 'import pytest\n'), ((4334, 4358), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (4347, 4358), False, 'import pytest\n'), ((4416, 4440), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (4429, 4440), False, 'import pytest\n'), ((4875, 4899), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (4888, 4899), False, 'import pytest\n'), ((5116, 5140), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (5129, 5140), False, 'import pytest\n'), ((5360, 5384), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (5373, 5384), False, 'import pytest\n'), ((5440, 5464), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (5453, 5464), False, 'import pytest\n'), ((620, 625), 'atom.api.Int', 'Int', ([], {}), '()\n', (623, 625), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((692, 697), 'atom.api.Int', 'Int', ([], {}), '()\n', (695, 697), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((699, 704), 'atom.api.Int', 'Int', ([], {}), '()\n', (702, 704), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((785, 790), 'atom.api.Int', 'Int', ([], {}), '()\n', (788, 790), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((905, 910), 'atom.api.Int', 'Int', ([], {}), '()\n', (908, 910), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((912, 917), 'atom.api.Int', 'Int', ([], {}), '()\n', (915, 917), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((659, 664), 'atom.api.Int', 'Int', ([], {}), '()\n', (662, 664), False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((848, 853), 'atom.api.Int', 'Int', ([], {}), '()\n', (851, 853), False, 'from atom.api import Atom, Dict, Int, atomdict\n')]