1from nameparser.config._invariants import assert_normalized
2
3#: Bound Arabic given-name prefixes that attach to the following word to
4#: form one given name (e.g. "abdul salam smith" → given name "abdul
5#: salam"). They are never standalone names. The join is a group-stage
6#: rule on the FIRST non-title piece, so it is not about roles -- it
7#: fires whatever name_order later assigns. It reserves a piece for what
8#: follows: three pieces that are neither title nor suffix in a main
9#: segment -- counting the bound word's OWN piece even where that word is
10#: also suffix vocabulary, since it is the piece the rule has claimed
11#: rather than one left to spare -- which is why two-word "abdul salam"
12#: stays given "abdul" plus
13#: family "salam"; only two after a family comma, where the family name
14#: is already fixed ("salam, abdul rahman" → given "abdul rahman").
15#: Mirrors :py:data:`~nameparser.config.particles.PARTICLES`, which
16#: chains onto the piece that follows it.
17BOUND_GIVEN_NAMES: frozenset[str] = frozenset({
18 'abdul',
19 'abdel',
20 'abdal',
21 # The bare transliteration, which abdul/abdel/abdal do not match:
22 # "abd Allah Smith" -> given "abd Allah", and "Abd al-Rahman
23 # Smith" likewise, al-Rahman being ONE token. The three-token
24 # spelling "abd al rahman smith" is still not joined -- `al` is a
25 # particle and chains forward -- and stays deferred, as it was
26 # when this word was excluded. Same word as عبد below, which has
27 # covered the Arabic-script side since #269 (shipped in 2.0).
28 #
29 # Collides with the postnominal ABD ("All But Dissertation"),
30 # which stays in SUFFIX_ACRONYMS. Position decides at the two ends
31 # -- a leading `abd` reads as a name, a trailing one as the
32 # credential -- but not everywhere: in the given slot of a
33 # family-comma name the credential still wins, so "Smith, Abd"
34 # reports suffix 'Abd' and no given name, where "Smith, Abdul"
35 # reports the given name. Recorded at decisions.md#P5.
36 'abd',
37 'abu',
38 'abou',
39 'umm',
40
41 # #269 follow-up: the Arabic-script originals of the entries above.
42 # Script writes "Abdul Rahman" as two words (عبد + الرحمن -- the
43 # article attaches to the following word), so عبد alone covers the
44 # abdul/abdel/abdal variants. Both kunya spellings ship, matching
45 # the أبو/ابو prefix pair.
46 'عبد', # "abd" (servant of) -- عبد الرحمن -> given "عبد الرحمن"
47 'أبو', # "abu" (father of), hamza spelling
48 'ابو', # "abu", hamza-less spelling
49 'أم', # "umm" (mother of), hamza spelling
50 'ام', # "umm", hamza-less spelling
51})
52
53
54assert_normalized("BOUND_GIVEN_NAMES", BOUND_GIVEN_NAMES)
55
56# Star imports read __all__ and never the module __getattr__ -- see the
57# note in prefixes.py. Without it `assert_normalized`, imported only for
58# the invariant above, is bound by a star import as though it were
59# vocabulary (#356).
60__all__ = ["BOUND_GIVEN_NAMES"]