55"""
66
77import ast
8+ import pytest
89import re
910import sys
1011import tokenize
@@ -101,10 +102,7 @@ def assert_no_for(filename, comps=True):
101102 node_count = count_nodes (filename )
102103 assert node_count ["For" ] == 0 , "For loops are not allowed"
103104 if comps :
104- assert node_count ["ListComp" ] == 0 , "List comprehensions are not allowed"
105- assert node_count ["SetComp" ] == 0 , "Set comprehensions are not allowed"
106- assert node_count ["DictComp" ] == 0 , "Dict comprehensions are not allowed"
107- assert node_count ["GeneratorExp" ] == 0 , "Generator expressions are not allowed"
105+ assert_no_functional (filename )
108106
109107
110108def assert_no_while (filename ):
@@ -127,6 +125,42 @@ def assert_no_loops(filename):
127125 assert_no_while (filename )
128126
129127
128+ def assert_no_functional (filename ):
129+ """Check that functional programming features are NOT used.
130+
131+ This includes list/set/dict comprehensions, generator expressions, and
132+ lambda expressions.
133+
134+ Args:
135+ filename (str): The source file to parse.
136+ """
137+ node_count = count_nodes (filename )
138+ assert node_count ["ListComp" ] == 0 , "List comprehensions are not allowed"
139+ assert node_count ["SetComp" ] == 0 , "Set comprehensions are not allowed"
140+ assert node_count ["DictComp" ] == 0 , "Dict comprehensions are not allowed"
141+ assert node_count ["GeneratorExp" ] == 0 , "Generator expressions are not allowed"
142+ assert node_count ["Lambda" ] == 0 , "Lambda expressions are not allowed"
143+
144+
145+ def assert_not_imported (filename , modules ):
146+ """Check that forbidden modules are not imported.
147+
148+ Args:
149+ filename (str): The source file to parse.
150+ modules (list): Names of modules that are not allowed to be imported.
151+ """
152+ source = get_source_code (filename )
153+ tree = ast .parse (source , filename )
154+ for node in ast .walk (tree ):
155+ if isinstance (node , ast .Import ):
156+ for alias in node .names :
157+ if alias .name in modules :
158+ pytest .fail (f"Importing { alias .name } is not allowed" )
159+ if isinstance (node , ast .ImportFrom ):
160+ if node .module in modules :
161+ pytest .fail (f"Importing from { node .module } is not allowed" )
162+
163+
130164def count_calls (filename , func_id ):
131165 """Count how many times a function is called.
132166
0 commit comments