#!/www/python/bin/python

"""$URL: svn+ssh://svn/repos/trunk/dulcinea/lib/test/utest_spec.py $
$Id: utest_spec.py 25402 2004-10-20 22:29:40Z dbinger $

Test for dulcinea.spec.
"""

from sancho.utest import UTest
from dulcinea.base import DulcineaPersistent
from dulcinea.spec import spec, nspec, any, get_spec_doc, get_specs, \
     get_spec_problems, match, require, format_spec, interval, \
     string, sequence, eq, anything, mapping, equal, subclass, instance, \
     all, length, no, boolean, get_spec, get_spec_report, specify


class SpecTest (UTest):

    def check_match (self):
        assert match(1, int)
        assert not match(2.5, int)
        assert match(2.5, any(int, float))
        assert not match('s', any(int, float))
        assert not match('hello', sequence(int, str))
        assert match('hello', sequence(str, str))
        assert not match('hello', sequence(str, tuple))
        assert match('hello', str)
        assert match('hello', any('yes', 'no', 'hello', int))
        assert match(3, any('yes', 'no', 'hello', int))
        mydict = {'a': 1, 'b': None}
        assert match(mydict, dict)
        assert match(mydict, { str : object })
        assert not match(mydict, { int : object })
        assert match(mydict, { str : object, int : object })
        assert match((2,3), (int, int))
        assert match((1,), tuple)
        assert match((1,), sequence(object, tuple))
        assert match((1,2,3,4), sequence(object, tuple))
        assert match((1,2,3,'ok'), sequence(object, tuple))
        assert not match((1,2,3,'ok'), sequence(int, tuple))
        assert match(mydict, mapping({ any(str, int) : object }))
        assert not match(mydict, mapping({int:object}, dict))
        assert not match(mydict, mapping({str: int}))
        assert match(True, boolean)
        assert not match(3, boolean)
        assert match([3,'ok'], [int, str])
        assert not match([3,'ok', 3], [int, str])
        assert match(3, no(None))
        assert match([3, 4], [all(int, no(None))])
        assert not match(3, any)
        assert match(3, object)
        a=[2,3]
        b=[2,3]
        assert match(a, eq(a))
        assert not match(b, eq(a))
        assert match(a, equal(b))
        assert match('a', string(1))
        assert match('a', length(1))
        assert match('a', interval('a','c'))
        assert not match('b', all(length(1), string(2)))
        assert not match('b', all(length(2)))
        assert match(10, interval(1))
        assert match(1, interval(1))
        assert not match(0, interval(1))
        assert not match(0, interval(1,4))
        assert match(4, interval(1,4))
        assert not match(5, interval(1,4))
        assert match(0, interval(anything,4))
        assert match(0, instance('int'))
        assert not match(0, no(int))

        class foo (dict, UTest):
            pass
        assert not match(0, subclass(dict))
        assert match(foo, subclass(dict))
        assert not match(0, mapping())
        assert not match(0, mapping({int:int},foo))
        sequence().get_args()
        assert not match(0, instance('foo'))
        for s in ('equal(1)',
                  'eq(1)',
                  'string(4)',
                  'sequence(2, anything)',
                  'interval(2, 4)',
                  'interval(2)',
                  'interval()',
                  'interval(anything, 3)',
                  'None',
                  '(int, str)',
                  '[int]',
                  '{int: str}',
                  "'constant'",
                  ):
            assert format_spec(eval(s)) == s
        try:
            require(1, str)
            assert 0
        except TypeError: pass
        try:
            require(1, str, 'oops')
            assert 0
        except TypeError: pass
        assert not match(1, [1])
        assert not match([1], [str])
        assert not match([1, 'hello'], [str, str])
        assert not match(1, {})
        class mytest:
            def __call__ (self, value):
                return True
        assert match(1, mytest())

    def check_specified (self):
        class A:
            flavor_is = spec(any('sweet', 'sour'), 'the flavor')
            texture_is = spec(int, 'roughness')

        class B(A):
            color_is = spec(str)
            texture_is = nspec(str)

        self.a = A()
        self.b = B()
        self.b.color = self.b.texture = 'ok'
        specify(self.b, flavor='sweet')
        assert get_spec_problems(self.b) == []
        self.b.nonsense = 34
        assert len(get_spec_problems(self.b)) == 1
        del self.b.nonsense
        assert len(get_spec_problems(self.b)) == 0
        self.b.color = 42
        assert len(get_spec_problems(self.b)) == 1
        self.b.color = 'red'
        assert len(get_spec_problems(self.b)) == 0
        assert len(get_specs(B).values()) == 3
        def is_texture(value):
            return value in (3,4)
        class C(DulcineaPersistent):
            color_is = nspec(str, 'the color')
            texture_is = is_texture
        assert get_specs(C)
        assert get_spec_doc(C)
        nspec(None)
        nspec(int)
        nspec(any(int, str))
        get_spec(C, 'texture_is')
        class D:
            color_is = nspec(str, 'the color')
            texture_is = is_texture
        get_spec(D, 'texture_is')
        get_spec_problems(D())
        class E:
            pass
        get_spec_report([D()])
        get_spec_report([E()])
        get_spec_report([])

    def check_specify (self):
        class A:
            flavor_is = spec(any('sweet', 'sour'), 'the flavor')
            texture_is = spec(int, 'roughness')

        class B(A):
            color_is = spec(str)
            texture_is = nspec(str)
        b = B()
        specify(b, texture='ok', flavor='sour')
        c = B()
        try:
            specify(c, texture=1)
            assert 0
        except TypeError:
            pass
        try:
            specify(c, boo=1)
            assert 0
        except AttributeError:
            pass

if __name__ == "__main__":
    SpecTest()
