Files
oopt-gnpy/tests/test_opensource_compliancy.py
EstherLerouzic 7a1b15a916 chore: make sure all python files have the correct header
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ifdd6a566fda74c5b7d417f9d61c51d4d3da07bfd
2025-06-11 15:05:51 +02:00

126 lines
3.9 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: BSD-3-Clause
# testing commits compliancy
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
# see AUTHORS.rst for a list of contributors
"""
checks compliance to opensource rules:
- list of authors
- presence of headers
"""
import subprocess
import re
from pathlib import Path
SRC_DIR = Path(__file__).parent.parent
def get_author_emails_from_file():
# Read AUTHOR.rst content
with open(SRC_DIR / 'AUTHORS.rst', 'r', encoding='utf-8') as f:
author_rst = f.read()
# Extract all author emails from AUTHOR.rst
return set(re.findall(r'<([^>]+)>', author_rst))
def get_commit_author_emails(since_days=None):
# Get list of commit authors, optionally limited to recent commits
cmd = ['git', 'log', '--pretty=format:%aE']
if since_days:
cmd.append(f'--since={since_days} days ago')
result = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
# Return unique emails from git log
return set(result.stdout.splitlines())
def test_commit_authors_in_author_rst():
author_emails = get_author_emails_from_file()
commit_emails = get_commit_author_emails(since_days=365)
allowed_missing = {'andrea.damico@polito.it'
}
# Check that each commit author email is listed in AUTHOR.rst
missing_emails = commit_emails - author_emails - allowed_missing
assert not missing_emails, f"The following commit author emails are missing in AUTHOR.rst: {missing_emails}"
def get_python_files(root_dir):
"""Get all Python files in the project."""
return list(root_dir.glob('**/*.py'))
def check_header(file_path):
"""Check if a file has the correct header."""
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read(500) # Read just the beginning of the file
# Check for shebang
has_shebang = content.startswith('#!/usr/bin/env python')
# Check for encoding
has_encoding = '# -*- coding: utf-8 -*-' in content[:100]
# Check for SPDX license
has_license = 'SPDX-License-Identifier: BSD-3-Clause' in content
# Check for copyright
has_copyright = re.search(r'Copyright \(C\) .*Telecom Infra Project', content) is not None
# Check for AUTHORS reference
has_authors_ref = 'see AUTHORS.rst' in content
return {
'file': file_path,
'has_shebang': has_shebang,
'has_encoding': has_encoding,
'has_license': has_license,
'has_copyright': has_copyright,
'has_authors_ref': has_authors_ref,
'is_compliant': has_shebang and has_encoding and has_license and has_copyright and has_authors_ref
}
def test_file_headers():
"""Test that all Python files have the correct header."""
# Get all Python files
python_files = get_python_files(SRC_DIR / 'gnpy') + get_python_files(SRC_DIR / 'tests')
# Files that can be excluded from header checks (e.g., third-party code, generated files)
excluded_files = [
SRC_DIR / 'gnpy' / 'topology' / '__init__.py',
SRC_DIR / 'gnpy' / 'tools' / '__init__.py',
SRC_DIR / 'gnpy' / 'core' / '__init__.py',
SRC_DIR / 'gnpy' / '__init__.py',
SRC_DIR / 'tests' / '__init__.py'
]
# Filter out excluded files
python_files = [f for f in python_files if f not in excluded_files]
# Check headers
results = [check_header(f) for f in python_files]
non_compliant = [r for r in results if not r['is_compliant']]
# Generate detailed error message
error_msg = ""
if non_compliant:
error_msg = "The following files have non-compliant headers:\n"
for result in non_compliant:
file_path = result['file'].relative_to(SRC_DIR)
error_msg += f"\n{file_path}:\n"
print(non_compliant)
assert len(non_compliant) == 0, error_msg