#!/usr/bin/env python3 """ Test flake8 compliance for deb-bootc-image-builder. This module tests code style compliance using flake8, including: - PEP 8 compliance - Code style validation - Debian-specific style standards """ import pytest import os import tempfile import shutil import subprocess import logging # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class TestFlake8Compliance: """Test cases for flake8 compliance.""" def test_flake8_installation(self, work_dir): """Test that flake8 is available.""" try: result = subprocess.run( ["flake8", "--version"], capture_output=True, text=True, timeout=10 ) assert result.returncode == 0, "flake8 is not properly installed" logger.info("flake8 is available") except FileNotFoundError: pytest.skip("flake8 not installed") def test_flake8_basic_usage(self, work_dir): """Test basic flake8 functionality.""" # Create a simple test file test_file = os.path.join(work_dir, "test_flake8.py") with open(test_file, 'w') as f: f.write('''#!/usr/bin/env python3 """ Test file for flake8 validation. """ def test_function(): """Test function for flake8.""" return "test" if __name__ == "__main__": print(test_function()) ''') # Run flake8 on the test file try: result = subprocess.run( ["flake8", test_file], capture_output=True, text=True, timeout=30 ) # flake8 should run without errors assert result.returncode == 0, f"flake8 found issues: {result.stdout}" logger.info("flake8 basic functionality test passed") except subprocess.TimeoutExpired: pytest.fail("flake8 test timed out") except Exception as e: pytest.fail(f"flake8 test failed: {e}") def test_pep8_compliance(self, work_dir): """Test PEP 8 compliance.""" # Create a test file with various PEP 8 issues test_file = os.path.join(work_dir, "pep8_test.py") with open(test_file, 'w') as f: f.write('''#!/usr/bin/env python3 """ Test file for PEP 8 compliance. """ import os import sys # This line is too long and should trigger E501 very_long_line_that_exceeds_the_maximum_line_length_and_should_trigger_a_flake8_error = "test" def test_function_with_bad_spacing( x,y ): """Function with bad spacing.""" if x==y: return True else: return False class BadClass: def __init__(self): pass def method_with_bad_indentation(self): return "bad indentation" # Missing blank line at end of file ''') # Run flake8 and check for expected errors try: result = subprocess.run( ["flake8", test_file], capture_output=True, text=True, timeout=30 ) # Should find PEP 8 violations assert result.returncode != 0, "flake8 should find PEP 8 violations" output = result.stdout + result.stderr # Check for specific error codes expected_errors = ["E501", "E201", "E202", "E225", "E111", "W292"] found_errors = [] for error_code in expected_errors: if error_code in output: found_errors.append(error_code) assert len(found_errors) > 0, f"No expected PEP 8 errors found. Output: {output}" logger.info(f"Found PEP 8 violations: {found_errors}") except subprocess.TimeoutExpired: pytest.fail("flake8 PEP 8 test timed out") except Exception as e: pytest.fail(f"flake8 PEP 8 test failed: {e}") def test_debian_specific_style_standards(self, work_dir): """Test Debian-specific style standards.""" # Create a test file following Debian style standards test_file = os.path.join(work_dir, "debian_style_test.py") with open(test_file, 'w') as f: f.write('''#!/usr/bin/env python3 """ Debian-specific test file for flake8 validation. """ import os import subprocess import logging from typing import Dict, List, Any, Optional # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class DebianBootcBuilder: """Debian bootc image builder class.""" def __init__(self, work_dir: str): """Initialize the builder.""" self.work_dir = work_dir self.packages: List[str] = [] self.release = "trixie" self.arch = "amd64" def add_package(self, package: str) -> None: """Add a package to the installation list.""" if package not in self.packages: self.packages.append(package) logger.info(f"Added package: {package}") def set_release(self, release: str) -> None: """Set the Debian release.""" valid_releases = ["trixie", "bookworm", "bullseye"] if release in valid_releases: self.release = release logger.info(f"Set release to: {release}") else: raise ValueError(f"Invalid release: {release}") def build_image(self) -> Dict[str, Any]: """Build the Debian image.""" logger.info("Starting Debian image build") # Validate configuration if not self.packages: raise ValueError("No packages specified") # Build process would go here result = { "status": "success", "packages": self.packages, "release": self.release, "arch": self.arch } logger.info("Debian image build completed") return result def main() -> None: """Main function.""" builder = DebianBootcBuilder("/tmp/test") builder.add_package("linux-image-amd64") builder.add_package("systemd") builder.set_release("trixie") try: result = builder.build_image() print(f"Build result: {result}") except Exception as e: logger.error(f"Build failed: {e}") if __name__ == "__main__": main() ''') # Run flake8 on the Debian style file try: result = subprocess.run( ["flake8", test_file], capture_output=True, text=True, timeout=30 ) # Should pass flake8 validation assert result.returncode == 0, f"flake8 found issues in Debian style file: {result.stdout}" logger.info("Debian-specific style standards test passed") except subprocess.TimeoutExpired: pytest.fail("flake8 Debian style test timed out") except Exception as e: pytest.fail(f"flake8 Debian style test failed: {e}") def test_flake8_configuration(self, work_dir): """Test flake8 configuration and custom rules.""" # Create a flake8 configuration file setup_cfg = os.path.join(work_dir, "setup.cfg") with open(setup_cfg, 'w') as f: f.write('''[flake8] # Maximum line length max-line-length = 120 # Ignore specific error codes ignore = E203, W503 # Exclude directories exclude = .git,__pycache__,.venv # Maximum complexity max-complexity = 10 ''') # Create a test file that would normally trigger ignored errors test_file = os.path.join(work_dir, "config_test.py") with open(test_file, 'w') as f: f.write('''#!/usr/bin/env python3 """ Test file for flake8 configuration. """ def test_function(): """Test function for flake8 config.""" # This line is long but should be allowed by config very_long_line_that_exceeds_normal_pep8_but_is_allowed_by_our_config = "test" return very_long_line_that_exceeds_normal_pep8_but_is_allowed_by_our_config if __name__ == "__main__": print(test_function()) ''') # Run flake8 with custom configuration try: result = subprocess.run( ["flake8", "--config", setup_cfg, test_file], capture_output=True, text=True, timeout=30 ) # Should pass with custom configuration assert result.returncode == 0, f"flake8 with custom config failed: {result.stdout}" logger.info("flake8 configuration test passed") except subprocess.TimeoutExpired: pytest.fail("flake8 configuration test timed out") except Exception as e: pytest.fail(f"flake8 configuration test failed: {e}") def test_flake8_error_codes(self, work_dir): """Test specific flake8 error codes.""" # Create a test file with specific error types test_file = os.path.join(work_dir, "error_codes_test.py") with open(test_file, 'w') as f: f.write('''#!/usr/bin/env python3 """ Test file for specific flake8 error codes. """ # E501: Line too long very_long_line_that_exceeds_the_maximum_line_length_and_should_trigger_a_flake8_error = "test" # E201: Whitespace after '(' def function_with_bad_spacing( x ): return x # E202: Whitespace before ')' def another_bad_function( y ): return y # E225: Missing whitespace around operator x=1 y=2 z=x+y # E111: Bad indentation def bad_indentation(): return "bad" # W292: No newline at end of file result = "no newline" ''') # Run flake8 and check for specific error codes try: result = subprocess.run( ["flake8", test_file], capture_output=True, text=True, timeout=30 ) # Should find errors assert result.returncode != 0, "flake8 should find style errors" output = result.stdout + result.stderr # Check for specific error codes expected_errors = ["E501", "E201", "E202", "E225", "E111", "W292"] found_errors = [] for error_code in expected_errors: if error_code in output: found_errors.append(error_code) # Should find at least some of the expected errors assert len(found_errors) >= 3, f"Expected more error codes. Found: {found_errors}" logger.info(f"Found flake8 error codes: {found_errors}") except subprocess.TimeoutExpired: pytest.fail("flake8 error codes test timed out") except Exception as e: pytest.fail(f"flake8 error codes test failed: {e}") if __name__ == "__main__": pytest.main([__file__])