Skip to content

Commit 522e01b

Browse files
authored
chore: add pre-commit hook to check for absolute imports in routingpy package (#151)
* disallow absolute imports, check it in pre-commit hook * cancel running ci workflows
1 parent eb20b43 commit 522e01b

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

.github/workflows/ci-tests.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ on:
1515
- '.gitignore'
1616
- '**.md'
1717
- '**.rst'
18+
19+
# Cancel CI runs on a branch when new commits were pushed
20+
# See https://stackoverflow.com/a/72408109/2582935
21+
concurrency:
22+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
23+
cancel-in-progress: true
1824

1925
jobs:
2026
build:

.pre-commit-config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ repos:
1414
- id: isort
1515
name: isort (python)
1616
args: [--filter-files]
17+
- repo: local
18+
hooks:
19+
- id: no-absolute-imports
20+
name: Disallow absolute self-imports
21+
entry: python tests/scripts/check_imports.py routingpy routingpy
22+
language: system
23+
pass_filenames: false

tests/scripts/check_imports.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
3+
# Errors on absolute imports in any .py files found in the input paths
4+
5+
import re
6+
import sys
7+
from pathlib import Path
8+
9+
10+
def check_for_absolute_imports(library_name: str, *dirs):
11+
"""
12+
Ensures no absolute imports of the library (e.g. 'import mylib' or 'from mylib import ...')
13+
appear outside test files.
14+
"""
15+
# only matches "from/import <library_name>", while "from/import <library-name>-other" is allowed
16+
abs_import_pattern = re.compile(rf"^\s*(?:from|import)\s+{re.escape(library_name)}(?=\.|\s|$)")
17+
18+
errors = []
19+
for dir in dirs:
20+
dir_path = Path(dir)
21+
for py_file in dir_path.rglob("*.py"):
22+
with py_file.open() as f:
23+
dir_rel_path = py_file.absolute().relative_to(Path.cwd())
24+
for lineno, line in enumerate(f, 1):
25+
if not abs_import_pattern.search(line):
26+
continue
27+
errors.append(f"{dir_rel_path}:{lineno}: {line.strip()}")
28+
29+
if errors:
30+
print(f"❌ Absolute imports of {library_name} found outside tests:")
31+
print("\n".join(errors))
32+
sys.exit(1)
33+
else:
34+
print("✅ No forbidden absolute imports found.")
35+
sys.exit(0)
36+
37+
38+
if __name__ == "__main__":
39+
if len(sys.argv) < 3:
40+
print("Usage: python check_imports.py <library_name> <dirpath1> [<dirpath2>] ...")
41+
sys.exit(1)
42+
43+
check_for_absolute_imports(sys.argv[1], *sys.argv[2:])

0 commit comments

Comments
 (0)