Skip to main content

Ethiopian/Eritrean name intelligence: parsing, transliteration, spelling variants, and patronymic-aware fuzzy matching.

Project description

habesha-names

Ethiopian/Eritrean name intelligence for Python: fidel script handling, transliteration, spelling-variant generation, name parsing, and patronymic-aware fuzzy matching.

Alpha status

Current release: 0.1.0a1 (alpha). The practical transliteration defaults and the bundled name lexicon are agent-seeded and pending native-speaker verification — every linguistic default ships flagged "verified": false (see Data verification). Concretely, that means match scores and variant outputs may change in 0.1.0 final as defaults are reviewed, and the API is not yet frozen. Suitable for evaluation and integration prototyping; pin the exact version if you depend on today's scores.

  • Zero runtime dependencies — stdlib only
  • Deterministic and explainable — no ML at runtime, no network calls; every match score ships an explanation object. Built for KYC/AML, remittance, HR, and entity-resolution pipelines.
  • Fully typed (py.typed, mypy strict)

Why

Habesha names break global identity systems:

  1. No family names. A full name is given name + father's given name (+ grandfather's). "First/Last name" fields are semantically wrong.
  2. No standard romanization. ጸሐይ → Tsehay / Tsehai / Sehay / Tzehay — same person, four database records.
  3. Compound given names. "Haile Mariam" can be ONE given name (Hailemariam) or given + patronym.
  4. Abbreviation conventions. Gebremedhin → G/Medhin, G.Medhin, Gebre Medhin — all common in official documents.
  5. Fidel homophones. ሀ/ሐ/ኀ, ሰ/ሠ, ጸ/ፀ, አ/ዐ are pronounced identically; spelling varies by writer.

Install

pip install --pre habesha-names

(Only alpha releases exist so far, so pip needs --pre; plain pip install habesha-names will work once 0.1.0 final is out. From a checkout: pip install -e .)

Quick tour

Every snippet below is a doctest and runs in CI.

Parse — name structure, not first/last fields

>>> from habesha_names import parse
>>> p = parse("ወይዘሮ ጸሐይ ገብረመድህን")
>>> (p.title, p.given, p.patronym)
('Woizero', 'ጸሀይ', 'ገብረመድህን')
>>> p.script
'ethiopic'
>>> parse("Hailemariam Desalegn").given_is_compound
True
>>> parse("G/Medhin Tesfaye").given      # slash abbreviation expanded
'Gebremedhin'
>>> parse("Bikila, Abebe").given         # comma inversion handled
'Abebe'

Variants — the spellings your database actually contains

>>> from habesha_names import variants
>>> variants("ጸሐይ", n=6)
['Tsehay', 'Sehay', 'Tsehai', 'Tzehay', 'Tsehaye', 'Sehai']
>>> variants("Gebremedhin", n=5)
['Gebremedhin', 'Gebre Medhin', 'Gebre-Medhin', 'G/Medhin', 'G.Medhin']

Match — patronymic-aware fuzzy matching

>>> from habesha_names import match
>>> match("Ato Abebe Bikila", "abebe bikila") >= 0.85
True
>>> round(float(match("Tesfay Mohamed", "Tesfaye Muhammed")), 2)
0.94
>>> match("Abebe Bikila", "Bikila Abebe").swapped   # field swap tolerated
True
>>> match("Abebe Bikila", "Almaz Tesfahun") <= 0.6
True

Explainability — every score can be justified

>>> result = match("ወይዘሮ ጸሐይ ገብረመድህን", "Tsehay G/Medhin")
>>> result.score
1.0
>>> [(pair.token_a, pair.token_b, pair.method) for pair in result.pairs]
[('ጸሀይ', 'Tsehay', 'exact'), ('ገብረመድህን', 'Gebremedhin', 'exact')]
>>> for note in result.notes:
...     print(note)
a: patronym 'ገብረመድህን' is a joined compound (Gebre + Medhin)
b: abbreviation 'G/Medhin' expanded with top candidate 'Gebre' (candidates: Gebre (0.8), Girma (0.2))

Normalize — fidel homophones collapse before comparison

>>> from habesha_names import normalize
>>> normalize("ፀሐይ")                    # ፀ→ጸ, ሐ→ሀ
'ጸሀይ'
>>> normalize("ፀሐይ") == normalize("ጸሀይ")
True

Transliterate — practical romanization, no diacritics

>>> from habesha_names import transliterate
>>> transliterate("ተስፋዬ")
'Tesfaye'
>>> transliterate("ገብረመድህን")
'Gebremedhin'
>>> transliterate("ፀሐይ") == transliterate("ጸሀይ") == "Tsehay"
True

Building blocks

>>> from habesha_names import is_ethiopic, phonetic_key
>>> is_ethiopic("ተስፋዬ")
True
>>> phonetic_key("Tsehay") == phonetic_key("Sehai")   # HabeshaKey
True

Public API

from habesha_names import (
    parse, match, variants, transliterate,
    normalize, phonetic_key, is_ethiopic,
)

Everything else is internal. Reverse transliteration (to_fidel) and gender inference (guess_gender) are planned for v0.2.

Data verification

All bundled linguistic data (lexicons, transliteration tables, variant rules, golden test pairs) was seeded programmatically or by a non-native speaker and ships flagged "verified": false until it passes native-speaker review. Match scores are deterministic and explainable, but treat linguistic defaults as provisional until 0.1.0 final.

Development

python -m venv .venv
.venv\Scripts\activate.bat
pip install -e .[dev]
check.bat        # pytest -q && ruff check . && mypy src --strict

See ARCHITECTURE.md for the design and CHANGELOG.md for release history.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

habesha_names-0.1.0a1.tar.gz (77.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

habesha_names-0.1.0a1-py3-none-any.whl (50.8 kB view details)

Uploaded Python 3

File details

Details for the file habesha_names-0.1.0a1.tar.gz.

File metadata

  • Download URL: habesha_names-0.1.0a1.tar.gz
  • Upload date:
  • Size: 77.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for habesha_names-0.1.0a1.tar.gz
Algorithm Hash digest
SHA256 aedda0f0a35805270be80449c3a2b58a1e8ba6c587818314fbed14becf9298f3
MD5 de8d6b0b46bb1247b7d1397f1cba0f27
BLAKE2b-256 9da392257f5a27f00c2e85a52b11c989b9c63dcf0e5ccea00fe99d77fe31dd86

See more details on using hashes here.

Provenance

The following attestation bundles were made for habesha_names-0.1.0a1.tar.gz:

Publisher: release.yml on Robel231/habesha-names

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file habesha_names-0.1.0a1-py3-none-any.whl.

File metadata

  • Download URL: habesha_names-0.1.0a1-py3-none-any.whl
  • Upload date:
  • Size: 50.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for habesha_names-0.1.0a1-py3-none-any.whl
Algorithm Hash digest
SHA256 063ab7ba879845056398ef712a953db172ce45730aa34133155d616af5a98369
MD5 09b7f4304f76c5b41e393c757951f05a
BLAKE2b-256 5e15829d23a5c49a63d3410455abcfdb0261d3b7ae1b4e176048dfe8ec705f6f

See more details on using hashes here.

Provenance

The following attestation bundles were made for habesha_names-0.1.0a1-py3-none-any.whl:

Publisher: release.yml on Robel231/habesha-names

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page