[Types-sig] Sample declarations

Paul Prescod paulp@ActiveState.com
Tue, 13 Mar 2001 05:35:06 -0800


Here are some sample declarations from an experimental typecheck module.
I'd like feedback because there are lots of subtle issues.

import types, operator

############# Basic types ##############

class _number:
    "Any kind of Number"
    def __implementedby__(self, obj):
        try:  # includes appropriate complexes, excludes strings
              # should I use isNumberType???
            complex(obj)
            return 1
        except TypeError:
            return 0

Number=_number()
Complex=_number()
Complex.__doc__="A complex number (including one with no imaginary
part)"

class _integer:
    "An integer value"
    def __implementedby__(self, obj):
        try: # includes appropriate floats and complexes
            return int(obj)==obj
        except TypeError:
            return 0

Integer=_integer()

class _float:
    "A floating point value"
    def __implementedby__(self, obj):
        try: # includes integers, appropriate complexes 
            return float(obj)==obj
        except TypeError:
            return 0

Float=_float()

class _string:
    "Any kind of string"
    def __implementedby__(self, obj):
        return obj in (types.StringType, types.UnicodeType)
String=_string()

########### Ancient Protocols #################

def findInterface(iface, obj):
    ifaces = getattr(obj, "__interfaces__", None)
    # don't make this mutually recursive on
    # Sequence.__implementedby__!
    if type(ifaces) in (types.ListType, types.TupleType): 
        return iface in ifaces # multiple interfaces case
    else:
        return iface is ifaces # single interface case

class _sequence:
    "Any kind of sequence"
    def __implementedby__(self, obj):
        if findInterface(self, obj):
            return 1
        else:
            return operator.isSequenceType(obj)
Sequence=_sequence()

class _mapping:
    "Any kind of mapping from keys to values"
    def __implementedby__(self, obj):
        if findInterface(self, obj):
            return 1
        else:
            return operator.isMappingType(obj)

Mapping=_sequence()

class _callable:
    "Any object that can be called with arguments."
    def __implementedby__(self, obj):
        return callable(obj)
Callable=_callable()


class _readstream:
    "An object that can be read from like a file."
    def __implementedby__(self, obj):
        if findInterface(self, obj):
            return 1
        else:
            attrs = dir(obj) #argh...this doesn't handle instances well!
            return ("read" in attrs and 
                    "flush" in attrs and 
                    "seek" in attrs) # ...
ReadStream= _readstream()

def experimentalAssertTypes(dict):
    # this is VERY ROUGH
    # for one thing it should use variable names from the caller,
    # not a passed in dictionary!
    for val, type in dict.items():
        if not type.__implementedby__(val):
            raise TypeError(val, type)

def _test():
    import os
    # use doctest eventually!
    experimentalAssertTypes({5:Integer})
    experimentalAssertTypes({_test:Callable})
    experimentalAssertTypes({os.popen("blah"):ReadStream})
    # experimentalAssertTypes({5:String}) # should raise assertion

if __name__=="__main__":
    _test()


-- 
Python:
    Programming the way
    Guido
    indented it.
       - (originated with Skip Montanaro?)