# names


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

Readers search for names and terms in whatever spelling they know, and
translations write them in yet another. This module closes the gap in
three ways: one key for every spelling of a name, a table of epithets,
and a table of English glosses for technical terms.

## One key per name

A reader may write Krishna, Kṛṣṇa, krsna or कृष्ण; Bheeshma or Bhīṣma;
Venkateshwara or Veṅkaṭeśvara.
[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key)
gives every spelling of a name one key. It applies
[`fold_token`](https://vedicreader.github.io/ganapati/sanskrit.html#fold_token)
and then the habits of Indian-English spelling: ṛ is read as `ri`, `sh`
as `s`, `w` as `v`, `ee` and `oo` as `i` and `u`, the h of an aspirate
is dropped, and doubled letters become single. Bhīṣma, Bheeshma and भीष्म
all give `bisma`. The key is for matching only, not a spelling to show
anyone.

[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key)
differs from
[`roman_fold`](https://vedicreader.github.io/ganapati/sanskrit.html#roman_fold)
in `ganapati.sanskrit` mainly in its treatment of ṛ.
[`roman_fold`](https://vedicreader.github.io/ganapati/sanskrit.html#roman_fold)
reads Krishna as `krsna`, matching a transliteration, while
[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key)
reads Kṛṣṇa as `krisna`, matching the way the name is usually spelled in
English.

------------------------------------------------------------------------

<a
href="https://github.com/vedicreader/ganapati/blob/main/ganapati/names.py#L17"
target="_blank" style="float:right; font-size:smaller">source</a>

### name_key

``` python
def name_key(
    s:str
)->str:
```

*Return one key for every spelling of a Sanskrit name in IAST, plain
roman, Indian English or Devanagari: Bhīṣma, Bheeshma and भीष्म all give
`bisma`.*

``` python
assert name_key('Bhīṣma') == name_key('Bheeshma') == name_key('bhishma') == name_key('भीष्म') == 'bisma'
assert name_key('Kṛṣṇa') == name_key('Krishna') == name_key('कृष्ण') == 'krisna'
assert name_key('Veṅkaṭeśvara') == name_key('Venkateshwara') == name_key('Venkateswara')
assert name_key('Yudhiṣṭhira') == name_key('Yudhishthira') == 'yudistira'
assert name_key('Lakṣmaṇa') == name_key('Lakshmana') and name_key('Kārttikeya') == name_key('Kartikeya')
assert name_key('Bhīma') != name_key('Bhīṣma')
assert name_key('') == ''
```

## Spellings with one vowel more or less

Some spellings still differ after
[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key).
Plain roman drops the vowel that IAST writes as ṛ (`krsna` for kṛṣṇa),
Indian English adds one (`krishna`), and Indian English often drops a
final a (`arjun`).
[`name_variants`](https://vedicreader.github.io/ganapati/names.html#name_variants)
looks in a pool of keys, such as the vocabulary of an index, and returns
the ones that differ from a given key by a single vowel added or
removed, with the same first letter. It never adds or removes a
consonant, because Bhīma (`bima`) and Bhīṣma (`bisma`) are different
people. A key shorter than `min_len`, five letters by default, matches
only itself, since one vowel more on a short name often makes another
name.

------------------------------------------------------------------------

<a
href="https://github.com/vedicreader/ganapati/blob/main/ganapati/names.py#L32"
target="_blank" style="float:right; font-size:smaller">source</a>

### name_variants

``` python
def name_variants(
    key:str, # a `name_key`, or any key in the same form as the pool's
    pool, # the keys to look in: a set, a dict's keys, an index vocabulary
    min_len:int=5, # keys shorter than this match only themselves, since one vowel more on a short name often makes another name
)->set:
```

*Return the keys in `pool` that spell the same name as `key`: the key
itself and, from `min_len` letters on, keys one vowel longer or shorter
with the same first letter.*

``` python
pool = {'krsna', 'krisna', 'bima', 'bisma', 'arjuna', 'rama'}
assert name_variants('krsna', pool) == {'krsna', 'krisna'}
assert name_variants('krisna', pool) == {'krsna', 'krisna'}
assert name_variants('bisma', pool) == {'bisma'}           # not bima: a dropped consonant is another name
assert name_variants('arjun', pool) == {'arjuna'}          # Indian-English drops the final a
assert name_variants('ram', pool) == set()                 # under min_len: rama is not tried
assert name_variants('karisana', {'krsna'}) == set()       # three vowels
```

## Epithets

An epithet is a descriptive name for a deity or a hero: Pārtha, son of
Pṛthā, for Arjuna, or Raṅganātha, lord of Raṅga, for Viṣṇu. A reader may
search for the epithet when the translation writes only the main name.
`EPITHETS` holds one group per line: first the canonical names that
translations use, then `|`, then the epithets.

The mapping goes one way. Raṅganātha leads to Viṣṇu, Nārāyaṇa and Hari,
but Viṣṇu does not lead to every epithet, so a search for Rāma is not
widened to every Rāghava. An epithet that two figures share is in both
groups, as Acyuta and Mādhava are. A name that more often means
something else is left out: Śrī; Ramā (Lakṣmī), whose key `rama` is
Rāma’s; Kṛṣṇā (Draupadī), whose key is Kṛṣṇa’s; Guha, which is Skanda
but also the boatman of the Rāmāyaṇa; and Kaunteya, which is any son of
Kuntī. Spellings that
[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key)
cannot bring together are listed beside the IAST, such as Subramanya,
Murugan and Bajrangbali. The names are common knowledge from the epics,
the Purāṇas and temple usage, written in IAST.

[`canonical`](https://vedicreader.github.io/ganapati/names.html#canonical)
is the function to call. It takes a name in any spelling and returns the
canonical names it leads to: an epithet’s group, a canonical name’s own
group, or `()` if the table does not have it. It also accepts a leading
Śrī, Śrīmat or Bhagavān, ṛ typed as a plain `r`, an English plural, and,
for names of five letters or more, a dropped final a, as in Ganesh for
Gaṇeśa.
[`epithets`](https://vedicreader.github.io/ganapati/names.html#epithets)
returns the whole map from epithet keys to canonical names.

------------------------------------------------------------------------

<a
href="https://github.com/vedicreader/ganapati/blob/main/ganapati/names.py#L95"
target="_blank" style="float:right; font-size:smaller">source</a>

### canonical

``` python
def canonical(
    name:str
)->tuple:
```

*Return the canonical names that `name`, in any spelling, leads to, or
`()` if the table does not have it.*

------------------------------------------------------------------------

<a
href="https://github.com/vedicreader/ganapati/blob/main/ganapati/names.py#L87"
target="_blank" style="float:right; font-size:smaller">source</a>

### epithets

``` python
def epithets()->dict:
```

*Return the map from each epithet’s
[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key)
to the canonical names a translation writes, such as `ranganata` to
Viṣṇu, Nārāyaṇa and Hari.*

``` python
assert canonical('Raṅganātha') == ('viṣṇu', 'nārāyaṇa', 'hari') == canonical('Sri Ranganatha') == canonical('Srinivasa')
assert canonical('Venkateshwara') == canonical('Balaji') == canonical('perumal') == ('viṣṇu', 'nārāyaṇa', 'hari')
assert canonical('Nārāyaṇa') == ('viṣṇu', 'nārāyaṇa', 'hari')              # a canonical name gives its group
assert canonical('Dāśarathi') == canonical('Raghava') == canonical('dasarathi') == ('rāma',)
assert canonical('Partha') == canonical('Dhananjaya') == canonical('धनञ्जय') == ('arjuna',)
assert canonical('Jānakī') == canonical('Vaidehi') == ('sītā',) and canonical('Maruti') == canonical('Anjaneya') == ('hanumān', 'hanumat')
assert canonical('Murugan') == canonical('Subramanya') == ('skanda', 'kārttikeya', 'subrahmaṇya')
assert canonical('Vinayaka') == canonical('Ganesh') == ('gaṇeśa', 'gaṇapati')    # Ganesh: the final a dropped
assert canonical('Shankar') == canonical('Mahadeva') == ('śiva',) and canonical('Ambika') == ('pārvatī', 'umā', 'gaurī')
assert set(canonical('Acyuta')) == {'viṣṇu', 'nārāyaṇa', 'hari', 'kṛṣṇa'}       # an epithet two groups share
assert canonical('Keśava') == canonical('Kesava') == ('kṛṣṇa',) and canonical('Krishna') == canonical('krsna') == ('kṛṣṇa',)   # krsna: ṛ typed as r
assert canonical('Gangeya') == ('bhīṣma',) and canonical('Vrkodara') == ('bhīma',)
assert canonical('hrsikesa') == canonical('Hrishikesha') == canonical('krsna') == ('kṛṣṇa',)
assert canonical('dharma') == canonical('karma') == canonical('') == ()
assert canonical('part') == canonical('anal') == canonical('rudhira') == canonical('ram') == ()   # English words and short stems stay out
```

The table is checked for one mistake: an epithet whose key is also the
canonical name of a different group, which would widen every search for
that name.

``` python
e = epithets()
assert e['ranganata'] == ('viṣṇu', 'nārāyaṇa', 'hari') and 'visnu' not in e   # one way: canonical names are not keys
assert not [k for k, cs in e.items() if k in _CAN and not set(cs) & set(_CAN[k])]
assert len(e) > 150 and len(_CAN) > 30
```

## Technical terms

`TERMS` gives the English that translations use for the technical terms
of the śāstras: the means of knowledge (pramāṇas) and the categories of
Nyāya, the padārthas of Vaiśeṣika, Sāṃkhya and Yoga, Vedānta and the
Gītā, and the calendar (pañcāṅga) and the horoscope. Each term has a few
English glosses, the most usual first.
[`term_gloss`](https://vedicreader.github.io/ganapati/names.html#term_gloss)
looks a term up by
[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key),
so anumāna, anumana and अनुमान are one term, and an English plural such
as `gunas` works too. Śraddhā (faith) is left out because its key is the
same as that of śrāddha, the rite for the ancestors.

A term not in the table falls back to Monier-Williams
([`mw_lexicon`](https://vedicreader.github.io/ganapati/lemma.html#mw_lexicon)
in `ganapati.lemma`) when you pass it as `mw` or it has already been
downloaded;
[`term_gloss`](https://vedicreader.github.io/ganapati/names.html#term_gloss)
never downloads anything. The fallback looks the term up by its SLP1
form, so it works for IAST and Devanagari but not for informal
spellings, and it returns at most three glosses.
[`terms`](https://vedicreader.github.io/ganapati/names.html#terms)
returns the whole table by key.

------------------------------------------------------------------------

<a
href="https://github.com/vedicreader/ganapati/blob/main/ganapati/names.py#L244"
target="_blank" style="float:right; font-size:smaller">source</a>

### term_gloss

``` python
def term_gloss(
    term:str, # IAST, plain roman or Devanagari
    mw:dict=None, # a `mw_lexicon()`; None uses the downloaded copy if there is one
)->tuple:
```

*Return short English glosses for a Sanskrit technical term from
`TERMS`, else from Monier-Williams, or `()` if neither knows it.*

------------------------------------------------------------------------

<a
href="https://github.com/vedicreader/ganapati/blob/main/ganapati/names.py#L235"
target="_blank" style="float:right; font-size:smaller">source</a>

### terms

``` python
def terms()->dict:
```

*Return every term in `TERMS` by
[`name_key`](https://vedicreader.github.io/ganapati/names.html#name_key),
mapped to its English glosses.*

``` python
assert term_gloss('anumāna') == term_gloss('anumana') == term_gloss('अनुमान') == ('inference',)
assert term_gloss('pratyaksha') == ('perception',) and term_gloss('upamana') == ('comparison', 'analogy')
assert term_gloss('saṃśaya') == term_gloss('samshaya') == ('doubt',) and term_gloss('dravya') == ('substance',)
assert term_gloss('sthitaprajña') == ('steady wisdom',) and term_gloss('moksha') == ('liberation', 'release')
assert term_gloss('nakshatra') == ('lunar mansion', 'asterism') and term_gloss('lagna') == ('ascendant',)
assert term_gloss('padarthas') == ('category',) and term_gloss('gunas') == ('quality',) and term_gloss('tamas') == ('darkness', 'inertia')
assert term_gloss('anumāna', mw={}) == ('inference',) and term_gloss('shraddha', mw={}) == ()  # the table needs no MW; śrāddha is no term
assert term_gloss('gaja', mw={'gaja': 'an elephant; the number 8'}) == ('an elephant', 'the number 8')
assert term_gloss('xyz', mw={}) == () and term_gloss('', mw={}) == ()
assert len(_TERMS) == len(TERMS.strip().splitlines()) > 120                           # no two terms share a key
```

The two tables do not overlap: no technical term has the same key as a
name.

``` python
assert not set(_TERMS) & (set(_EPI) | set(_CAN))
```
