"""Tests for no-LLM structural entity extraction.""" from mempalace.entities import entities_metadata, extract_structural_entities def test_extracts_code_symbols_paths_urls(): text = ( "We patched `_extract_authored_at` in rag/convo_miner.py so MemoryStack and " "ChromaBackend agree. See module.func and pkg.Class.method, plus do_thing_now. " "Ref https://github.com/MemPalace/mempalace/pull/1890 for details." ) ents = set(extract_structural_entities(text)) assert "_extract_authored_at" in ents assert "rag/convo_miner.py" in ents assert "MemoryStack" in ents assert "ChromaBackend" in ents assert "module.func" in ents assert "pkg.Class.method" in ents assert "do_thing_now" in ents assert any(e.startswith("https://github.com/MemPalace") for e in ents) def test_excludes_prose_noise(): text = "This is a normal sentence, e.g. with i.e. abbreviations and version 1.2.3 here." ents = extract_structural_entities(text) # No plain prose words, no "e.g"/"i.e", no bare version numbers. assert ents == [] def test_ranked_by_frequency_then_order(): text = "alpha_one alpha_one alpha_one beta_two beta_two gamma_three" ents = extract_structural_entities(text) assert ents[:3] == ["alpha_one", "beta_two", "gamma_three"] def test_dedup_case_insensitive_keeps_first_form(): text = "`MemoryStack` and memorystack and MEMORYSTACK" ents = extract_structural_entities(text) assert ents.count("MemoryStack") == 1 assert ents == ["MemoryStack"] def test_respects_max_entities(): text = " ".join(f"sym_{i}_x" for i in range(50)) assert len(extract_structural_entities(text, max_entities=10)) == 10 def test_extracts_leading_underscore_snake_in_plain_text(): # Not in backticks — must still be caught by the snake-case pattern. ents = extract_structural_entities("we called _extract_authored_at and _do_thing here") assert "_extract_authored_at" in ents assert "_do_thing" in ents def test_semicolon_in_entity_does_not_corrupt_metadata(): # A backtick span containing ';' must not split the ;-joined metadata field. md = entities_metadata("see `a(); b()` and TwoThing") parts = md.split(";") # Every part is a whole entity — no fragment is a bare separator artifact. assert all(p.strip() for p in parts) assert "TwoThing" in parts def test_metadata_is_semicolon_joined(): text = "`one_thing` and TwoThing" md = entities_metadata(text) assert md == "one_thing;TwoThing" assert entities_metadata("") == "" assert entities_metadata("just plain prose with nothing structural") == ""