PyContract check functions in an imported module
-
13-07-2021 - |
题
I am using PyContract (not PyContracts) to implement design-by-contracts for my genetic algorithms framework.
The main module is GA.py
, which calls a function from crossover.py
(let's call it foocross
). I have written precondition and postcondition expressions for foocross
.
Now, I would like those conditions to be checked when I run the main
in GA.py. I introduced a false precondition in foocross
just to test if the contracts were being checked, but it seems that they are not. How do I make sure that the contracts are being checked?
Here's a minimal section of my code:
# GA.py
def main():
# some code
crossover.foocross(params)
# some more code
if __name__ == "__main__":
main()
#crossover.py
def injectionco(p1, p2, chrom):
"""
pre:
isinstance(p1, int) # this should raise an error. p1 is never an int
isinstance(p2, list)
isinstance(chrom, int)
forall(p1, lambda elem: any(isinstance(elem, i.__class__) for i in p2))
forall(p2, lambda elem: any(isinstance(elem, i.__class__) for i in p1))
len(p1) == len(p2)
post:
p1 is __old__.p1
p2 is __old__.p2
p1 == __old__.p1
p2 == __old__.p2
isinstance(__return__, p1.__class__) # returns an individual
len(__return__) == len(p1)
id(__return__) not in [id(p1), id(p2)]
forall(__return__, lambda elem: __return__.count(elem) == 1)
"""
#code
return #something
PS: this was a pretty difficult question for me to write because I had to strip out a LOT of my code (since the framework is pretty complex) and I'm new to design-by-contract. So if I've missed out on some information that would help answer this question, please ask and I'll happily provide more info :)
解决方案
Looking at the example, seems like all you need to do would be:
# this needs to be there unconditionally.
import contract
contract.checkmod(__name__)
if __name__ == '__main__':
import doctest, GA
doctest.testmod(GA)
However, this below will NOT work (because inside import GA
, contract.checkmod()
does not happen):
if __name__ == '__main__':
import contract
contract.checkmod(__name__)
import doctest, GA
doctest.testmod(GA)
其他提示
There is another solution. For large code bases, it would be tedious to edit several files to enable/disable contract checking for each module. I was able to call all contract checks from my main module as follows:
#GA.py
import crossover # and all other required modules
import contract
for mod in [crossover]: # put all other imported modules in that list
contract.checkmod(mod)