I'm trying to use PyContracts within a web application, so I have lots of custom-defined classes being passed around that I simply want to type check alongside other more traditional argument types. I'd like to use contractual programming (PyContracts) to accomplish this, for the sake of cleanliness and forced documentation.
When I reference a locally visible class by name, PyContracts doesn't seem to be aware of the type. For example:
from contracts import contract
class SomeClass:
pass
@contract
def f(a):
"""
:param a: Just a parameter
:type a: SomeClass
"""
print(a)
my_a = SomeClass()
f(my_a)
Raises the following error:
ContractSyntaxError: Unknown identifier 'SomeClass'. Did you mean 'np_complex64'? (at char 0), (line:1, col:1)
I know I can use new_contract to custom-define names and bind them to classes, but that's a lot of hassle to do for every type. I want to use the docstring syntax for PyContracts if at all possible, and I definitely need to use the string-defined contract format since I'm using boolean type logic ("None|str|SomeClass"
). How do I accomplish this with local types and minimal intrusion into the rest of my codebase?
I hacked together a magic decorator that adds types before creating the contract. For anyone that's interested, it seems to work, but it's probably pretty slow if you define a large number of functions:
And some test runs: