# Mutations the check tests must catch. One row each: file | exact text | replacement | why
# `python3 .github/scripts/run_tests.py --mutants --only check` applies each row to a scratch copy
# of check/ and fails when the tests still pass. The text must occur exactly once in the file.
gwt_check/links.py | if len(w) >= MIN_WORD] | if len(w) >= 0] | words of fewer than 3 letters never count as a name
gwt_check/links.py | if len([1 for h in ch.get("parent_family_list") or [] if h in O["families"]]) > 1: | if False: | a child with several parental families gets one row per family and a flag
gwt_check/links.py | if x.get("ref") in E and kind(x.get("role")) == "primary"] | if x.get("ref") in E] | an event where the child is only a godparent is not the child's record
gwt_check/links.py | if any(x not in BIOLOGICAL for x in rel): | if any(x and x != "birth" for x in rel): | an Unknown relation counts as by birth, as in the other checks
gwt_check/links.py | return [C[h] for h in handles or [] if h in C and not C[h].get("private")] | return [C[h] for h in handles or [] if h in C] | a private citation is not read
gwt_check/links.py | if n in N and not N[n].get("private")] | if n in N] | a private note is not read
gwt_check/links.py | (w & given and w & FILIATION) | (w & given) | one given name of several counts only beside a filiation word
gwt_check/links.py | if _public_cits(tree, r.get("citation_list")): | if False: | a citation on the link itself is the top level
gwt_check/links.py | flags = [f"the link is marked {mark}"] if mark in FLAG_MARKS else [] | flags = [] | an open [probable] or [wrong link] mark is flagged
gwt_check/links.py | rows = [r for r in rep["rows"] if only is None or r["level"] == only or (only == "flagged" and r["flags"])] | rows = rep["rows"] | --level prints only the rows of that level
gwt_check/links.py | for r in rows[:limit]: | for r in rows: | --limit caps the printed rows
gwt_check/act.py | elif len(rows) > 1: | elif False: | an act whose subject fits several people is never matched to one
gwt_check/act.py | if registered: | if False: | a tree date that is the registration day is reported as such, not as a plain difference
gwt_check/act.py | if r.get("role") == "Primary" and r.get("ref") in E | if r.get("ref") in E | a godparent's or witness's ref to an event is never read as the person's own event
gwt_check/act.py | if p.get("private"):  # counted | if False:  # counted | a person marked private is counted but nothing of them is shown
gwt_check/act.py | if not c or c.get("private"): | if not c: | a private citation is never searched for the act's reference
gwt_check/act.py | and all(isinstance(who.get(k) or "", str) for k in ("given", "surname"))) | and True) | a name given as a list or a number is refused as bad input, not a crash
gwt_check/act.py | cands = wed or cands | cands = cands | a marriage act counts only the namesakes who have a family with the named spouse
gwt_check/act.py | p.get("gramps_id") == person] | True] | --person picks exactly the named person
gwt_check/act.py | if want == names[0]: | if want in names: | a place that only encloses the tree's place is not reported as the same place
gwt_check/act.py | r"(?<!\w)" + re.escape(want) | re.escape(want) | a reference is not found inside a longer number ("1" in "folio 21")
gwt_check/act.py | x in P and x != p["handle"] and _fits | x in P and _fits | a spouse name that fits the subject is never the subject himself
gwt_check/cites.py | if want and acts and want not in acts: | if want and acts: | a citation whose page names the event's own kind of act is not other-act
gwt_check/cites.py | (?:s|es)?(?!\w)", f) | ", f) | an act word matches whole, never inside a longer word such as birthplace
gwt_check/cites.py | "boda", | "bodx", | a marriage cited by a «Bodas» page is not another kind of act
gwt_check/cites.py | if want in ("death", "marriage") and any(m in _fold(page) for m in MARGINAL): | if False: | a death or marriage cited by a marginal mention is flagged
gwt_check/fill.py | (flagged if prob else parts).extend(text) | parts.extend(text) | fill-places does not propose a place that only a flagged citation names
gwt_check/fill.py | if only: | if False: | a place only a flagged citation names is listed under held_back
gwt_check/cites.py | if want and acts and want not in acts: | if acts and want not in acts: | an event of no act kind (a residence) is never another act
gwt_check/cites.py | "baptism": "birth", | "baptismx": "birth", | a baptism is read as a birth act
gwt_check/cites.py | "burial": "death", | "burialx": "death", | a burial is read as a death act
gwt_check/cites.py | rf"(?<!\w){w} | rf"{w} | an act word inside a longer word (renacimiento) is not that act
gwt_check/cites.py | if want in ("death", "marriage") and any | if any | a birth cited by a marginal mention is not flagged
gwt_check/cites.py | prob = citation_problem(e, c) if c else None | prob = citation_problem(e, c) | a citation missing from the dump is skipped
gwt_check/cli.py | raise BadInput(f"{tree.source}: a .gramps backup has no citation pages; use a dump") | pass | cites refuses a .gramps backup
gwt_check/fill.py | if rep.get("held_back"): | if False: | the text output counts the held-back events
gwt_check/client.py | got += pool.map(first_page, TYPES[1:]) | got += [first_page(t) for t in TYPES[1:]] | the first pages of the types are read together, not one type after another
gwt_check/checks.py | if len(group) > 1 and any(in_scope("media", h) for h, _ in group): | if len(group) > 1: | dup-media reports a group only when one member is in scope
gwt_check/checks.py | if o.get("checksum"): | if True: | a media object with no checksum is never a duplicate
gwt_check/checks.py | if any(not NOTE_DISCARDED_AFTER.match(text, m.end()) | if any(True | a hypothesis discarded right after it is not reported
gwt_check/checks.py | and not NOTE_DISCARDED_BEFORE.search(text[:m.start()]) for | and True for | a hypothesis discarded right before it is not reported
gwt_check/checks.py | _GAP = rf"(?:(?!(?:no|ni|sin|nada)\b)\w+{_SEP}){{0,3}}" | _GAP = rf"(?:\w+{_SEP}){{0,3}}" | a «no» between the marker and the discard word keeps the hypothesis open
gwt_check/checks.py | for m in word.finditer(text)): | for m in list(word.finditer(text))[:1]): | one discarded hypothesis does not hide another still open in the same note
gwt_check/checks.py | _SEP = r"[^\w.;:!?]+" | _SEP = r"\W+" | a discard word in another sentence does not discard the hypothesis
gwt_check/checks.py | if not wanted: | if False: | a tree with no such tag is never blamed for missing it
gwt_check/checks.py | if not in_scope("notes", n["handle"]) or wanted & set(n.get("tag_list") or []): | if wanted & set(n.get("tag_list") or []): | a note out of scope is not reported
gwt_check/checks.py | NOTE_DISCARDED_BEFORE = re.compile(rf"\b{_DISCARD}{_SEP}{_GAP}$") | NOTE_DISCARDED_BEFORE = re.compile(rf"\b{_DISCARD}{_SEP}{_GAP}") | a discard word before the marker counts only when it is within three words of it
gwt_check/checks.py | _GAP = rf"(?:(?!(?:no|ni|sin|nada)\b)\w+{_SEP}){{0,3}}" | _GAP = rf"(?:(?!(?:no|ni|sin|nada)\b)\w+{_SEP}){{0,30}}" | a discard word more than three words from the marker does not discard it
gwt_check/checks.py | _DISCARD = r"(?:descartad|refutad|superad|sustituid|desmentid)[oa]s?" | _DISCARD = r"(?:descartad|refutad|superad|sustituid)[oa]s?" | «desmentida» discards a hypothesis like «descartada»
gwt_check/checks.py | if len(n) >= 4: | if len(n) >= 0: | place names under four letters are skipped
gwt_check/checks.py | if any(f" {n} " in padded for n in own): | if False: | a description that names the event's own place is quiet
gwt_check/checks.py | todo += [r.get("ref") for r in pl.get("placeref_list") or []] | todo += [] | a description naming a place that encloses the event's place is quiet
gwt_check/checks.py | if h not in T["places"] or not desc or not in_scope("events", e["handle"]): | if h not in T["places"] or not desc: | place-vs-description reports only events in the run scope
gwt_check/checks.py | hits = {oh: n for oh, n in hits.items() if not any(f" {n} " in f" {m} " and n != m for m in hits.values())} | hits = hits | place-vs-description names a place once, by its longest match
gwt_check/checks.py | if n not in own and n not in people and | if n not in own and | place-vs-description skips a given name or surname of someone on the event
gwt_check/checks.py | on_event[r.get("ref")] += [T["people"][x] for x in | on_event[r.get("ref")] += [] and [T["people"][x] for x in | both spouses of a family are on the family's event
gwt_check/checks.py | for part in [n.get("first_name") or ""] + [ | for part in [ | a given name of someone on the event is not a place
gwt_check/checks.py | (residence or not origin(raw, words[j][1])) | (residence or True) | a place named as where someone is from or lives is not the event's place
gwt_check/checks.py | return ((k == 0 and before[0] in ("de", "del", "d") and | return ((False and | a clause that opens with «de» («Juan, de Otropueblo») names an origin
gwt_check/checks.py | if t in ("'", "’"): | if False: | an elided «d'» before a place still reads as «de»
gwt_check/checks.py | if k == len(before): | if False: | a place right after punctuation, or with no filler word before it, is not an origin
gwt_check/checks.py | and (stop is None or stop in ORIGIN_CLAUSE_BREAK)) | and True) | a «de» after an abbreviation dot («parr. de X») does not open a clause
gwt_check/checks.py | (stop is None or stop in ORIGIN_CLAUSE_BREAK) | (stop in ORIGIN_CLAUSE_BREAK) | a description that opens with «De X» names an origin
gwt_check/checks.py | residence = e.get("type") == "Residence" | residence = False | on a residence, where someone lives is the event's own place
gwt_check/checks.py | "vezina", "residente", | "vezina", | «residente en» names where someone lives
gwt_check/checks.py | "vecina", "vezino", "vezina", | "vecina", | the old spelling «vezino» names where someone lives
gwt_check/checks.py | "vecino", "vecina", "vezino", | "vecin", "vezino", | «en la vecindad de X» is not where someone lives
gwt_check/checks.py | "domicilie", "domiciliad", | "domicili", | «en su domicilio de X» is not where someone lives
gwt_check/checks.py | "vecino", "vecina", | "vecino", | «vecina de X» names where someone lives
gwt_check/checks.py | "vezino", "vezina", | "vezino", | the old spelling «vezina» names where someone lives
gwt_check/checks.py | "domicilie", "domiciliad", | "domicilie", | «domiciliado en X» names where someone lives
gwt_check/checks.py | {",", ";", ":", | {",", ":", | a «de» after a semicolon opens a clause
gwt_check/checks.py | ";", ":", "(", | ";", "(", | a «de» after a colon opens a clause
gwt_check/checks.py | [w for w, _ in words[j:j + len(ns)]] == ns | words[j][0] == ns[0] | a place of several words matches only as a whole
