mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-31 10:07:57 +00:00 
			
		
		
		
	 7a1b15a916
			
		
	
	7a1b15a916
	
	
	
		
			
			Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com> Change-Id: Ifdd6a566fda74c5b7d417f9d61c51d4d3da07bfd
		
			
				
	
	
		
			126 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			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
 |