Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/nameparser/config/_invariants.py: 100%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

6 statements  

1"""Import-time hygiene checks shared by the vocabulary data modules. 

2 

3Every constant here is looked up in normalized form, so a stray capital 

4or a surrounding space makes an entry unreachable by a direct membership 

5test -- ``'actor ' in TITLES`` is False -- even though the parser's own 

6ingest (:func:`nameparser._lexicon._normalize`) normalizes it away and 

7papers over the typo. Checking at import turns a silently-inert entry 

8into an immediate failure. 

9 

10Deliberately a weaker fold than ``_normalize``, which also 

11NFC-composes and strips edge full stops: entries like ``'esq.'`` are 

12legitimate data here, and this module cannot import ``_lexicon`` 

13anyway (``_lexicon`` imports these constants). The relationship checks 

14between constants stay in the modules that own them -- those encode 

15facts about the data, not hygiene. 

16 

17Interior whitespace is checked but not forbidden. A PHRASE entry is 

18legitimate in the two fields ``_lexicon._PHRASE_FIELDS`` names, and 

19``MAIDEN_MARKERS``'s ``'z domu'`` is the first one shipped; what this 

20asserts of one is that it is stored as the single-spaced, lowercase, 

21edge-clean form, so ``'z domu'`` and ``'Z domu '`` fail here rather 

22than becoming entries nothing can match. The remaining half of a 

23phrase's storage rule -- that each WORD is separately stripped of its 

24periods, so ``'z. domu'`` is stored ``'z domu'`` -- is 

25``_lexicon._title_key``'s and is deliberately NOT checked here. The 

26reason is altitude, not layering: importing ``_lexicon`` from here 

27would in fact work (its config imports are all inside 

28``_default_lexicon()``, nothing at module scope), but a data module 

29asserting things with the parser's own fold makes the constant's 

30hygiene depend on the parser, and the question worth asking is not 

31"is this entry pre-folded" but "does ``Lexicon`` store it unchanged". 

32That is one assertion over ``_PHRASE_FIELDS`` in 

33``tests/v2/test_ledger_guards.py``, the suite that already imports the 

34parser's fold for exactly this purpose, and it is where an entry 

35written ``'z. domu'`` is caught. 

36""" 

37from __future__ import annotations 

38 

39from collections.abc import Iterable 

40 

41 

42def assert_normalized(name: str, entries: Iterable[str]) -> None: 

43 """Assert every entry is stored lowercase, edge-clean, and -- where 

44 it is a phrase -- single-spaced.""" 

45 # " ".join(w.split()) rather than w.strip(): it subsumes the strip 

46 # and additionally collapses interior runs, which is what a phrase 

47 # entry made worth checking. For a single word the two are 

48 # identical, so no existing constant's verdict changes. 

49 offenders = sorted(w for w in entries if w != " ".join(w.lower().split())) 

50 assert not offenders, ( 

51 f"{name} entries must be stored lowercase, without edge " 

52 f"whitespace, and single-spaced if a phrase; " 

53 f"offending: {offenders}" 

54 )