"""Nox configuration for CleverErnie project.""" import sys import nox # Global configuration DEFAULT_PYTHON = "3.13" SUPPORTED_PYTHONS = ["3.13"] nox.options.reuse_existing_virtualenvs = True nox.options.error_on_external_run = True # ============================================================================= # QUICK DEVELOPMENT SESSIONS (Fast - Run daily) # ============================================================================= @nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv") def lint(session): """Check code formatting and linting.""" session.install("ruff") session.run("ruff", "check", "src/", "scripts/", "examples/") @nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv") def format(session): """Format code with ruff.""" session.install("ruff") session.run("ruff", "format", ".") # session.run("ruff", "check", "--fix", ".") @nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv") def typecheck(session): """Check types with pyright.""" session.install("pyright") session.install("-e", ".") # Install project with all dependencies session.run("pyright", stderr=sys.stdout) @nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv") def unit_tests(session): """Run BDD tests with Behave across Python versions.""" session.install("-e", ".[tests]") session.run("behave", "-q", *session.posargs) @nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv") def docs(session): """Build documentation with MkDocs.""" session.install("-e", ".[docs]") session.run("mkdocs", "build") @nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv") def serve_docs(session): """Serve docs locally for development.""" session.install("-e", ".[docs]") session.run("mkdocs", "serve", "--dev-addr", "0.0.0.0:8000") @nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv") def build(session): """Build the wheel distribution.""" session.install("build") session.run("python", "-m", "build", "--wheel") @nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv") def integration_tests(session): """Run Robot Framework integration tests.""" session.install("-e", ".[tests]") # If posargs provided, run only those specific files/suites if session.posargs: session.run( "robot", "--outputdir", "build/reports/robot", "--loglevel", "INFO", "--report", "report.html", "--log", "log.html", "--xunit", "xunit.xml", "--exclude", "slow", "--exitonfailure", # Exit immediately on test failure *session.posargs, external=False, # Ensure exit code is checked success_codes=[0], # Only code 0 is success ) else: # Default: run all tests in robot/ directory session.run( "robot", "--outputdir", "build/reports/robot", "--loglevel", "INFO", "--report", "report.html", "--log", "log.html", "--xunit", "xunit.xml", "--exclude", "slow", "--exitonfailure", # Exit immediately on test failure "robot/", external=False, # Ensure exit code is checked success_codes=[0], # Only code 0 is success ) @nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv") def slow_integration_tests(session): """Run Robot Framework integration tests.""" session.install("-e", ".[tests]") session.run( "robot", "--outputdir", "build/reports/robot", "--loglevel", "INFO", "--report", "report.html", "--log", "log.html", "--xunit", "xunit.xml", "robot/", *session.posargs, ) @nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv") def coverage_report(session): """Generate coverage report from Behave tests.""" session.install("-e", ".[tests]") # Clean up any existing coverage data session.run("coverage", "erase") # Run Behave tests with coverage - allow test failures but continue coverage generation try: session.run( "coverage", "run", "--source=src", "-m", "behave", "features/", "-q" ) except Exception as e: session.warn(f"Some tests failed: {e}") session.warn("Continuing with coverage report generation...") # Combine parallel coverage data (required when parallel=true in config) try: session.run("coverage", "combine") except Exception: # No parallel data to combine pass # Generate and display coverage reports session.run("coverage", "report", "--show-missing") session.run("coverage", "html") session.run("coverage", "xml") @nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv") def benchmark(session): """Run Airspeed Velocity benchmarks and publish results.""" session.install("-e", ".[tests]") config_path = "asv.conf.json" session.run("asv", "run", "--show-stderr", "--verbose", f"--config={config_path}") session.run("asv", "publish", f"--config={config_path}") # Sessions to run by default when running `nox` without arguments nox.options.sessions = [ "lint", # ~5-10 seconds "format", # ~5-10 seconds (auto-fixes issues) "typecheck", # ~10-20 seconds "unit_tests", # ~30-60 seconds (without ML deps) "integration_tests", "docs", # ~10-30 seconds "build", # ~5-10 seconds "benchmark", # ASV benchmarks for performance tracking "coverage_report", # ~30-60 seconds (without ML deps) ]