Skip to content

Commit d8ad0af

Browse files
committed
Add assert_no_functional and assert_not_imported
1 parent ca416e3 commit d8ad0af

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
### Added
1212

1313
- `redirect_stdin` class in common.py (#10)
14+
- `assert_no_functional` function in audit.py
15+
- `assert_not_imported` function in audit.py
1416
- `remove_docstrings` function in audit.py
1517

1618
### Fixed

jmu_pytest_utils/audit.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""
66

77
import ast
8+
import pytest
89
import re
910
import sys
1011
import 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

110108
def 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+
130164
def count_calls(filename, func_id):
131165
"""Count how many times a function is called.
132166

0 commit comments

Comments
 (0)