AndreaCensi / contracts

PyContracts is a Python package that allows to declare constraints on function parameters and return values. Contracts can be specified using Python3 annotations, or inside a docstring. PyContracts supports a basic type system, variables binding, arithmetic constraints, and has several specialized contracts and an extension API.
http://andreacensi.github.io/contracts/
Other
398 stars 62 forks source link

Better support for generic iterators #46

Open averagehat opened 8 years ago

averagehat commented 8 years ago

write now it is possible to do

new_contract('alistofstrings', 'list(string)')

but not

new_contract('aniteratorofstrings', 'Iterator(string)')

or

new_contract('aniteratorofstrings', 'Sequence(string)')

This really stifles polymorphism. I want it to accept a tuple, or a list, etc. Maybe I'm missing something?

NB: (On a related note, I'd like something that would accept generators too, but that has it's own problems).

dvolgyes commented 6 years ago

Maybe 'Iterable'? String is also iterable, but you can define new contract to rule out strings. It is not too nice, maybe it a negation in contract would be useful, e.g. 'not str', but it works this way:

from contracts import contract, new_contract

def not_string(x):
    return not isinstance(x,str)

new_contract('notstring',not_string)

def iter(n):
    for i in range(n):
        yield i

@contract(it='Iterable, notstring')
def pr(it):
    for x in it:
        print(x)

pr(iter(5))
pr([1,2,3])
pr((1,2,3))
pr(range(5))
pr("string should fail")
AndreaCensi commented 6 years ago

You can say: seq(str), to mean any Sequence (list, tuple, etc.). Note: you cannot use it with iterators because it would consume the data.

This "genericity" part is important in PyContracts, but unfortunately I didn't have time to do it properly. If you want to contribute, you can start at the definition of "seq".