native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
Python
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378import jsonimport tempfileimport unittestfrom pathlib import Path
from localization import ( Baseline, apply_summary, apply_translations, build_settings_command, candidate_literals, debt_places, open_places, places_elsewhere, extracted_keys, extraction_issues, placeholders, prune, record_decisions, serialize, structure_issues, translation_issues, unknown_candidates,)
def unit(value, state="translated"): return {"stringUnit": {"state": state, "value": value}}
def entry(zh_hans=None, **fields): localizations = {} if zh_hans is None else {"zh-Hans": unit(zh_hans)} return {"localizations": localizations, **fields}
def catalog(strings): return {"sourceLanguage": "en", "strings": strings, "version": "1.0"}
class PlaceholderTests(unittest.TestCase): def test_reads_types_in_argument_order(self): self.assertEqual(placeholders("%@ has %lld items"), ["@", "lld"]) self.assertEqual(placeholders("%2$lld 项属于 %1$@"), ["@", "lld"])
def test_ignores_escaped_percent(self): self.assertEqual(placeholders("%lld%% done"), ["lld"])
def test_rejects_mixed_positional_and_sequential(self): self.assertIsNone(placeholders("%1$@ and %@"))
class SerializeTests(unittest.TestCase): def test_matches_the_format_that_xcode_writes(self): text = serialize(catalog({"b": entry("乙"), "A": {"shouldTranslate": False}})) self.assertTrue(text.startswith('{\n "sourceLanguage" : "en",\n "strings" : {\n "A" : {')) self.assertLess(text.index('"A"'), text.index('"b"')) self.assertIn('"value" : "乙"', text) self.assertFalse(text.endswith("\n"))
class StructureIssueTests(unittest.TestCase): """The everyday check. It must not fail because a translation is still missing."""
def test_accepts_entries_that_wait_for_the_release_sync(self): strings = { "Open": entry("打开"), "New copy": entry(), "From Xcode": {"extractionState": "stale", "localizations": {"zh-Hans": unit("旧", state="new")}}, } self.assertEqual(structure_issues(catalog(strings)), [])
def test_reports_placeholder_mismatch(self): strings = {"%@ has %lld items": entry("%@ 有 %@ 项")} self.assertEqual( structure_issues(catalog(strings)), ['"%@ has %lld items": zh-Hans placeholders [@, @] do not match source [@, lld]'], )
def test_reports_reordered_placeholders_without_positions(self): strings = {"%@ has %lld items": entry("%lld 项属于 %@")} self.assertEqual(len(structure_issues(catalog(strings))), 1)
def test_checks_every_variation(self): variations = {"variations": {"plural": {"one": unit("%lld 项"), "other": unit("很多项")}}} strings = {"%lld items": {"localizations": {"zh-Hans": variations}}} self.assertEqual( structure_issues(catalog(strings)), ['"%lld items": zh-Hans placeholders [] do not match source [lld]'], )
class TranslationIssueTests(unittest.TestCase): """The release check."""
def test_accepts_complete_catalog(self): strings = {"Open": entry("打开"), "·": {"shouldTranslate": False}} self.assertEqual(translation_issues(catalog(strings)), [])
def test_reports_missing_translation(self): strings = {"Open": entry("打开"), "Close": entry()} self.assertEqual(translation_issues(catalog(strings)), ['"Close": no zh-Hans translation'])
def test_reports_unfinished_state(self): strings = {"Open": {"localizations": {"zh-Hans": unit("打开", state="needs_review")}}} self.assertEqual(translation_issues(catalog(strings)), ['"Open": zh-Hans state is needs_review'])
def test_requires_every_language_the_catalog_uses(self): strings = { "Open": {"localizations": {"zh-Hans": unit("打开"), "ja": unit("開く")}}, "Close": entry("关闭"), } self.assertEqual(translation_issues(catalog(strings)), ['"Close": no ja translation'])
class ExtractionIssueTests(unittest.TestCase): def test_reports_key_in_code_without_entry(self): extracted = {"Open": {"supacode/A.swift:3"}, "Close": {"supacode/B.swift:9", "supacode/B.swift:4"}} issues = extraction_issues(catalog({"Open": entry("打开")}), extracted) self.assertEqual(issues.missing, {"Close": ["supacode/B.swift:4", "supacode/B.swift:9"]}) self.assertEqual(issues.unused, [])
def test_reports_entry_without_use(self): issues = extraction_issues(catalog({"Open": entry("打开"), "Close": entry("关闭")}), {"Open": {"A.swift:1"}}) self.assertEqual(issues.unused, ["Close"])
def test_keeps_manual_entry_without_use(self): strings = {"Open": entry("打开", extractionState="manual")} self.assertEqual(extraction_issues(catalog(strings), {}).unused, [])
class ExtractedKeyTests(unittest.TestCase): def test_reads_localizable_table_of_existing_sources(self): with tempfile.TemporaryDirectory() as directory: root = Path(directory) source = root / "View.swift" source.write_text("") data = { "source": str(source), "tables": { "Localizable": [{"key": "Open", "location": {"startingLine": 7}}, {"key": ""}], "Other": [{"key": "Ignored"}], }, } (root / "View.stringsdata").write_text(json.dumps(data)) removed = {"source": str(root / "Removed.swift"), "tables": {"Localizable": [{"key": "Gone"}]}} (root / "Removed.stringsdata").write_text(json.dumps(removed)) self.assertEqual(extracted_keys(root, root=root), {"Open": {"View.swift:7"}})
class ApplyTests(unittest.TestCase): def test_adds_and_updates_translations(self): data = catalog({"Open": entry("开")}) errors = apply_translations(data, {"Open": {"zh-Hans": "打开"}, "Close": {"zh-Hans": "关闭"}}) self.assertEqual(errors, []) self.assertEqual(data["strings"]["Open"]["localizations"]["zh-Hans"], unit("打开")) self.assertEqual(data["strings"]["Close"]["localizations"]["zh-Hans"], unit("关闭"))
def test_null_marks_a_key_as_not_translatable(self): data = catalog({}) self.assertEqual(apply_translations(data, {"%@:%@": None}), []) self.assertEqual(data["strings"]["%@:%@"], {"shouldTranslate": False})
def test_summarizes_what_apply_changed(self): data = catalog({"Open": entry("开")}) translations = {"Open": {"zh-Hans": "打开"}, "Close": {"zh-Hans": "关闭"}, "Title": {"manual": True}, "·": None} self.assertEqual(apply_summary(data, translations), "Added 3, updated 1 (1 manual, 1 not translatable).")
def test_marks_a_key_as_manual_without_a_new_translation(self): data = catalog({"Toggle Canvas": entry("切换画布")}) self.assertEqual(apply_translations(data, {"Toggle Canvas": {"manual": True}}), []) self.assertEqual(data["strings"]["Toggle Canvas"]["extractionState"], "manual") self.assertEqual(data["strings"]["Toggle Canvas"]["localizations"]["zh-Hans"], unit("切换画布"))
def test_marks_a_run_time_key_as_manual(self): data = catalog({}) self.assertEqual(apply_translations(data, {"Toggle Canvas": {"zh-Hans": "切换画布", "manual": True}}), []) self.assertEqual(data["strings"]["Toggle Canvas"]["extractionState"], "manual") self.assertEqual(list(data["strings"]["Toggle Canvas"]["localizations"]), ["zh-Hans"])
def test_rejects_a_translation_with_wrong_placeholders(self): data = catalog({}) errors = apply_translations(data, {"%@ items": {"zh-Hans": "很多项"}}) self.assertEqual(len(errors), 1) self.assertNotIn("%@ items", data["strings"])
class PruneTests(unittest.TestCase): def test_removes_unused_entries_and_keeps_manual_ones(self): strings = { "Open": entry("打开"), "Gone": entry("没了"), "Run time": entry("运行时", extractionState="manual"), } data = catalog(strings) self.assertEqual(prune(data, {"Open": {"A.swift:1"}}), ["Gone"]) self.assertEqual(sorted(data["strings"]), ["Open", "Run time"])
class CandidateLiteralTests(unittest.TestCase): def scan(self, path, text): return [literal for _, literal in candidate_literals(path, text)]
def test_finds_sentences_anywhere(self): text = 'let message = "Unable to create worktree"\nlet key = "defaultEditorID"\n' self.assertEqual(self.scan("supacode/Domain/Thing.swift", text), ["Unable to create worktree"])
def test_finds_single_words_only_in_view_files(self): text = 'Text(flag ? "Ready" : label)\n' self.assertEqual(self.scan("supacode/Features/X/Views/Row.swift", text), ["Ready"]) self.assertEqual(self.scan("supacode/Domain/Thing.swift", text), [])
def test_describes_interpolation_as_a_placeholder(self): text = 'return "Cannot reach \\(endpoint). Check the network."\n' self.assertEqual(self.scan("supacode/Domain/Thing.swift", text), ["Cannot reach %@. Check the network."])
def test_finds_one_word_with_a_value_anywhere(self): text = 'let label = "Automatic (\\(ref))"\nlet header = "Bearer \\(token)"\nlet key = "prefix-\\(id)"\n' self.assertEqual(self.scan("supacode/Domain/Thing.swift", text), ["Automatic (%@)", "Bearer %@"])
def test_skips_file_names_and_identifiers(self): text = 'let a = "Cargo.toml"\nlet b = "PROWL_LAUNCH_HOOK_TOKEN"\nlet c = "\\(home)/.local/bin/gh"\n' self.assertEqual(self.scan("supacode/Domain/Thing.swift", text), [])
def test_skips_comments(self): self.assertEqual(self.scan("supacode/Domain/Thing.swift", '// "Not real copy here"\n'), [])
def test_reads_past_quotes_inside_an_interpolation(self): text = 'let text = "Launching role \\(redelivery ? "again" : "now") for you"\n' self.assertEqual(self.scan("supacode/Domain/Thing.swift", text), ["Launching role %@ for you"])
def test_reads_a_multi_line_literal_as_one_string(self): text = 'let text = """\n Host is off. \\\n Start Host first.\n """\nlet next = 1\n' self.assertEqual(self.scan("supacode/Domain/Thing.swift", text), ["Host is off. Start Host first."])
def test_keeps_a_space_that_follows_a_line_continuation(self): text = 'Text(\n """\n They play sounds\\\n according to your settings.\n """\n)\n' self.assertEqual( self.scan("supacode/Domain/Thing.swift", text), ["They play sounds according to your settings."] )
def test_reports_the_line_where_the_literal_starts(self): text = 'let a = 1\nlet text = "Unable to create worktree"\n' self.assertEqual(candidate_literals("supacode/Domain/Thing.swift", text), [(2, "Unable to create worktree")])
class BaselineTests(unittest.TestCase): def baseline(self, **fields): data = {"exemptPaths": {}, "exemptLinePatterns": {}, "exemptLiterals": {}, "blocked": {}, "debt": []} data.update(fields) return Baseline(data)
def test_reports_only_candidates_that_nobody_has_triaged(self): baseline = self.baseline(exemptLiterals={"Claude Code": "product-name"}, debt=["Unable to create worktree"]) found = { "Claude Code": ["supacode/Domain/A.swift:1"], "Unable to create worktree": ["supacode/Features/B.swift:2"], "Brand new copy": ["supacode/Features/C.swift:3"], } self.assertEqual(unknown_candidates(found, baseline, extracted={}), {"Brand new copy": found["Brand new copy"]})
def test_ignores_what_the_compiler_extracted_from_the_same_file(self): found = {"Open %@": ["supacode/Features/C.swift:3"]} extracted = {"Open %lld": {"supacode/Features/C.swift:3"}} self.assertEqual(unknown_candidates(found, self.baseline(), extracted), {})
def test_reports_a_verbatim_copy_in_the_same_file(self): found = {"Listening": ["supacode/Features/Status.swift:140", "supacode/Features/Status.swift:154"]} extracted = {"Listening": {"supacode/Features/Status.swift:140"}} self.assertEqual( unknown_candidates(found, self.baseline(), extracted), {"Listening": ["supacode/Features/Status.swift:154"]}, )
def test_does_not_confuse_two_files_with_the_same_name(self): found = {"Open %@": ["supacode/Features/A/Row.swift:3"]} extracted = {"Open %@": {"supacode/Features/B/Row.swift:3"}} self.assertEqual(list(unknown_candidates(found, self.baseline(), extracted)), ["Open %@"])
def test_trusts_a_run_time_key_only_where_titles_are_looked_up(self): baseline = self.baseline(runtimeKeyPaths={"supacode/App/AppShortcuts.swift": "Binding.localizedTitle"}) found = {"Toggle Canvas": ["supacode/App/AppShortcuts.swift:3", "supacode/Features/Tooltip.swift:8"]} self.assertEqual( unknown_candidates(found, baseline, {}, runtime_keys={"Toggle Canvas"}), {"Toggle Canvas": ["supacode/Features/Tooltip.swift:8"]}, )
def test_trusts_catalog_keys_in_a_file_that_looks_titles_up_at_run_time(self): baseline = self.baseline(runtimeKeyPaths={"supacode/App/AppShortcuts.swift": "Binding.localizedTitle"}) found = { "Toggle Left Sidebar": ["supacode/App/AppShortcuts.swift:3"], "Not in the catalog": ["supacode/App/AppShortcuts.swift:4"], } unknown = unknown_candidates(found, baseline, {"Toggle Left Sidebar": {"supacode/Commands/SidebarCommands.swift:15"}}) self.assertEqual(list(unknown), ["Not in the catalog"])
def test_reports_a_literal_that_only_another_file_localizes(self): found = {"Toggle Canvas": ["supacode/App/Menu.swift:3", "supacode/Features/Palette.swift:9"]} extracted = {"Toggle Canvas": {"supacode/App/Menu.swift:3"}} self.assertEqual( unknown_candidates(found, self.baseline(), extracted), {"Toggle Canvas": ["supacode/Features/Palette.swift:9"]}, )
def test_exempts_by_path_and_by_line(self): baseline = self.baseline( exemptPaths={"supacode/CLIService/**": "protocol"}, exemptLinePatterns={r"[Ll]ogger\.": "log"}, ) self.assertTrue(baseline.exempts_path("supacode/CLIService/Handler.swift")) self.assertFalse(baseline.exempts_path("supacode/Features/View.swift")) self.assertTrue(baseline.exempts_line(' logger.info("Something happened here")'))
def test_latest_triage_decision_wins(self): baseline = self.baseline(exemptLiterals={"RUN SCRIPT": "identifier"}, debt=["Claude Code"]) record_decisions(baseline, {"exempt": {"Claude Code": "product-name"}, "debt": ["RUN SCRIPT"]}) self.assertEqual(baseline.exempt_literals, {"Claude Code": "product-name"}) self.assertEqual(baseline.debt, ["RUN SCRIPT"])
def test_blocked_copy_is_not_debt(self): baseline = self.baseline(debt=["Launching %@ failed: %@"]) record_decisions(baseline, {"blocked": {"Launching %@ failed: %@": "also in log.md"}}) self.assertEqual(baseline.debt, []) self.assertEqual(baseline.blocked, {"Launching %@ failed: %@": "also in log.md"}) self.assertTrue(baseline.knows("Launching %@ failed: %@")) record_decisions(baseline, {"debt": ["Launching %@ failed: %@"]}) self.assertEqual((baseline.debt, baseline.blocked), (["Launching %@ failed: %@"], {}))
def test_drops_a_blocked_entry_that_is_gone(self): baseline = self.baseline(blocked={"Gone copy": "reason"}) self.assertEqual(baseline.obsolete(set()), ["Gone copy"]) baseline.remove(["Gone copy"]) self.assertEqual(baseline.blocked, {})
def test_reports_entries_that_left_the_code(self): baseline = self.baseline(exemptLiterals={"Gone Product": "product-name"}, debt=["Gone copy", "Still here"]) self.assertEqual(baseline.obsolete({"Still here"}), ["Gone Product", "Gone copy"])
def test_lists_debt_in_the_files_a_release_touched(self): baseline = self.baseline(debt=["Expand All", "Cancel Run"], exemptLiterals={"Claude Code": "product-name"}) still_open = { "Expand All": ["supacode/Features/Sidebar.swift:3"], "Cancel Run": ["supacode/Features/Workflow.swift:9"], "Claude Code": ["supacode/Features/Sidebar.swift:5"], } self.assertEqual( debt_places(still_open, baseline, changed={"supacode/Features/Sidebar.swift"}), {"supacode/Features/Sidebar.swift": [(3, "Expand All")]}, ) self.assertEqual(len(debt_places(still_open, baseline, changed=None)), 2)
def test_names_the_places_of_a_literal_outside_the_changed_files(self): baseline = self.baseline(debt=["Open on %@"]) still_open = {"Open on %@": ["supacode/Commands/Menu.swift:3", "supacode/Features/Button.swift:9"]} self.assertEqual( places_elsewhere(still_open, "Open on %@", changed={"supacode/Commands/Menu.swift"}), ["supacode/Features/Button.swift:9"], )
def test_debt_is_paid_when_every_place_is_localized(self): baseline = self.baseline(debt=["Expand All", "Collapse All"]) found = {"Expand All": ["supacode/Features/Sidebar.swift:3"], "Collapse All": ["supacode/Features/Sidebar.swift:4"]} still_open = open_places(found, baseline, {"Expand All": {"supacode/Features/Sidebar.swift:3"}}) self.assertEqual(baseline.obsolete(set(still_open)), ["Expand All"])
class BuildSettingsCommandTests(unittest.TestCase): def test_uses_the_default_derived_data(self): self.assertNotIn("-derivedDataPath", build_settings_command({}))
def test_follows_the_derived_data_path_of_make_test(self): command = build_settings_command({"PROWL_DERIVED_DATA_PATH": "/tmp/dd"}) index = command.index("-derivedDataPath") self.assertEqual(command[index + 1], "/tmp/dd")
if __name__ == "__main__": unittest.main()