# UserString is a wrapper around the native builtin string type.
# UserString instances should behave similar to builtin string objects.

import string
from test import test_support, string_tests
from UserString import UserString, MutableString
import warnings

class UserStringTest(
    string_tests.CommonTest,
    string_tests.MixinStrUnicodeUserStringTest,
    string_tests.MixinStrStringUserStringTest,
    string_tests.MixinStrUserStringTest
    ):

    type2test = UserString

    # Overwrite the three testing methods, because UserString
    # can't cope with arguments propagated to UserString
    # (and we don't test with subclasses)
    def checkequal(self, result, object, methodname, *args):
        result = self.fixtype(result)
        object = self.fixtype(object)
        # we don't fix the arguments, because UserString can't cope with it
        realresult = getattr(object, methodname)(*args)
        self.assertEqual(
            result,
            realresult
        )

    def checkraises(self, exc, obj, methodname, *args):
        obj = self.fixtype(obj)
        # we don't fix the arguments, because UserString can't cope with it
        with self.assertRaises(exc) as cm:
            getattr(obj, methodname)(*args)
        self.assertNotEqual(cm.exception.args[0], '')

    def checkcall(self, object, methodname, *args):
        object = self.fixtype(object)
        # we don't fix the arguments, because UserString can't cope with it
        getattr(object, methodname)(*args)

class MutableStringTest(UserStringTest):
    type2test = MutableString

    # MutableStrings can be hashed => deactivate test
    def test_hash(self):
        pass

    def test_setitem(self):
        s = self.type2test("foo")
        self.assertRaises(IndexError, s.__setitem__, -4, "bar")
        self.assertRaises(IndexError, s.__setitem__, 3, "bar")
        s[-1] = "bar"
        self.assertEqual(s, "fobar")
        s[0] = "bar"
        self.assertEqual(s, "barobar")

    def test_delitem(self):
        s = self.type2test("foo")
        self.assertRaises(IndexError, s.__delitem__, -4)
        self.assertRaises(IndexError, s.__delitem__, 3)
        del s[-1]
        self.assertEqual(s, "fo")
        del s[0]
        self.assertEqual(s, "o")
        del s[0]
        self.assertEqual(s, "")

    def test_setslice(self):
        s = self.type2test("foo")
        s[:] = "bar"
        self.assertEqual(s, "bar")
        s[1:2] = "foo"
        self.assertEqual(s, "bfoor")
        s[1:-1] = UserString("a")
        self.assertEqual(s, "bar")
        s[0:10] = 42
        self.assertEqual(s, "42")

    def test_delslice(self):
        s = self.type2test("foobar")
        del s[3:10]
        self.assertEqual(s, "foo")
        del s[-1:10]
        self.assertEqual(s, "fo")

    def test_extended_set_del_slice(self):
        indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
        orig = string.ascii_letters + string.digits
        for start in indices:
            for stop in indices:
                # Use indices[1:] when MutableString can handle real
                # extended slices
                for step in (None, 1, -1):
                    s = self.type2test(orig)
                    L = list(orig)
                    # Make sure we have a slice of exactly the right length,
                    # but with (hopefully) different data.
                    data = L[start:stop:step]
                    data.reverse()
                    L[start:stop:step] = data
                    s[start:stop:step] = "".join(data)
                    self.assertEqual(s, "".join(L))

                    del L[start:stop:step]
                    del s[start:stop:step]
                    self.assertEqual(s, "".join(L))

    def test_immutable(self):
        s = self.type2test("foobar")
        s2 = s.immutable()
        self.assertEqual(s, s2)
        self.assertIsInstance(s2, UserString)

    def test_iadd(self):
        s = self.type2test("foo")
        s += "bar"
        self.assertEqual(s, "foobar")
        s += UserString("baz")
        self.assertEqual(s, "foobarbaz")
        s += 42
        self.assertEqual(s, "foobarbaz42")

    def test_imul(self):
        s = self.type2test("foo")
        s *= 1
        self.assertEqual(s, "foo")
        s *= 2
        self.assertEqual(s, "foofoo")
        s *= -1
        self.assertEqual(s, "")

def test_main():
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore", ".*MutableString has been removed",
                                DeprecationWarning)
        warnings.filterwarnings("ignore",
                                ".*__(get|set|del)slice__ has been removed",
                                DeprecationWarning)
        test_support.run_unittest(UserStringTest, MutableStringTest)

if __name__ == "__main__":
    test_main()
