import unittest from tests.fakes import config, pr_ref from werkrevisor.review import ModelRun, coverage_reasons, files_in_prompt, pr_agent_settings, unreadable_files from werkrevisor.rules import ChangedFile try: from pr_agent.config_loader import get_settings from pr_agent.algo.language_handler import is_valid_file HAVE_PR_AGENT = True except ImportError: HAVE_PR_AGENT = False @unittest.skipUnless(HAVE_PR_AGENT, "runs inside the PR-Agent image") class PrAgentSettingsTest(unittest.TestCase): def test_every_forced_setting_exists_in_pr_agent(self): values = pr_agent_settings(config(), pr_ref(), "t" * 20, "k" * 20, "extra") settings = get_settings() # num_retries is only commented out in configuration.toml but read via get(); the keys are secrets. not_in_defaults = {"config.num_retries", "openrouter.key", "gitea.personal_access_token"} for key in values: if key in not_in_defaults: continue with self.subTest(key=key): section, name = key.split(".", 1) self.assertIn(name, settings.get(section), f"{key} is not a PR-Agent 0.47.0 setting") def test_settings_reach_pr_agent(self): from werkrevisor.review import apply_settings settings = get_settings() apply_settings(settings, pr_agent_settings(config(), pr_ref(), "t" * 20, "k" * 20, "extra")) self.assertEqual(settings.get("GITEA.URL"), "https://git.example.org") self.assertEqual(settings.get("GITEA.PERSONAL_ACCESS_TOKEN"), "t" * 20) self.assertEqual(settings.get("OPENROUTER.KEY"), "k" * 20) self.assertEqual(settings.config.fallback_models, []) self.assertFalse(settings.config.publish_output) self.assertEqual(settings.pr_reviewer.extra_instructions, "extra") self.assertEqual(settings.config.model, config().model.id) def test_token_limits_reach_the_litellm_handler(self): from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.token_budget import get_max_tokens from werkrevisor.review import apply_settings cfg = config() apply_settings(get_settings(), pr_agent_settings(cfg, pr_ref(), "t" * 20, "k" * 20, "")) handler = LiteLLMAIHandler() self.assertEqual(handler.get_output_token_limit(cfg.model.id), cfg.model.max_output_tokens) self.assertEqual(get_max_tokens(cfg.model.id), cfg.model.max_input_tokens + cfg.model.max_output_tokens) def test_reviewer_exposes_the_attributes_we_read(self): from pr_agent.algo import pr_processing from pr_agent.tools.pr_reviewer import PRReviewer self.assertTrue(callable(pr_processing.pr_generate_compressed_diff)) self.assertTrue(callable(PRReviewer._load_review_yaml)) self.assertIsNone(PRReviewer.prediction_data) def test_binary_files_are_not_reviewable(self): self.assertFalse(is_valid_file("doc/img.png")) self.assertTrue(is_valid_file("src/main/java/A.java")) class PromptCoverageTest(unittest.TestCase): DIFF = ("\n\n## File: 'src/a.py'\n\n__new hunk__\n1 +x\n" "\n\n## File 'old.py' was deleted\n" "\n\n## File: 'bad.py'\n\n> **This file could not be read.** PR-Agent failed\n") def test_files_in_prompt(self): self.assertEqual(files_in_prompt(self.DIFF), {"src/a.py", "old.py", "bad.py"}) self.assertEqual(unreadable_files(self.DIFF), ["bad.py"]) def test_coverage(self): run = ModelRun(data={}, details={"completion_tokens": 10}, prompt_files={"a.py"}) files = [ChangedFile("a.py", "modified", 1), ChangedFile("b.py", "modified", 2), ChangedFile("c.png", "modified", 0), ChangedFile("d.py", "renamed", 0)] codes = [r.code for r in coverage_reasons(files, run, lambda p: not p.endswith(".png"), 4000)] self.assertEqual(codes, ["skipped_files", "unreviewable_files", "no_text_diff"]) if __name__ == "__main__": unittest.main()