import typecheck
from typecheck import accepts
from typecheck import IsOneOf
from typecheck import typeclasses

#A simple test
@accepts(str)
def aStrFunction(a):
    print "aStrFunction:",a

#A simple test for specific types
@accepts(int, float, str)
def aNiftyFunction(a,b,c):
    print "aNiftyFunction:",a,b,c

#A test for more generic Type Classes
@accepts(typeclasses.String())
def aStringFunction(a):
    print "aStringFunction:",a

#A test for more generic Type Classes
@accepts(typeclasses.Number)
def aNumberFunction(a):
    print "a:",a


#A test that accepts Numbers or Strings
@accepts(IsOneOf(typeclasses.Number(),typeclasses.String()))
def aStringOrNumberFunction(a):
    print "aStringOrNumberFunction:",a

#A test of a typeclass of my own creation
#Goodtypes are Stuff or OtherStuff but not NotStuff
#Typeclass() recognizes that "doesStuff()" is the similarity between Stuff and
#OtherStuff. OneMoreStuff is an implicit goodType because it share's the same
#interface (doesStuff) as the explicit goodTypes. NotStuff does not share that
#common interface so it will not pass as a goodType.
class Stuff:
    def doesStuff():
        pass
class OtherStuff:
    def doesStuff():
        pass
class OneMoreStuff:
    def doesStuff():
        pass
class NotStuff:
    def dont_do_stuff():
        pass
goodTypes = typecheck.Typeclass(Stuff,OtherStuff)
@accepts(goodTypes)
def goodTypeFunction(a):
    print "goodTypeFunction:",a


#This works because I pass a string
aStrFunction("This is a simple string")
try:
    aStrFunction(u"This is a unicode string")
except typecheck.TypeCheckError:
    print "  aStrFunction: doesn't work with unicode strings"
#This works because I pass a string
aStringFunction("Another simple string.")
#I can even pass a unicode string.
aStringFunction(u"Another unicode string.")
#This doesn't work because it's not passing a string
try:
    var = 1.0
    aStringFunction(var)
except typecheck.TypeCheckError:
    print "  aStringFunction: %s that didn't work because it's not a string" % var

#This works when I pass a number OR a string
aStringOrNumberFunction(1.0)
aStringOrNumberFunction("Hello")
#But not anything else

#test my own class type
stuff = Stuff()
otherstuff = OtherStuff()
onemorestuff = OneMoreStuff()
notstuff = NotStuff()
goodTypeFunction(stuff)
goodTypeFunction(otherstuff)
#Test the implicit goodType
goodTypeFunction(onemorestuff)
try:
    goodTypeFunction(notstuff)
except typecheck.TypeCheckError:
    print "  goodTypeFunction: NotStuffs are not a goodType"
