Changelog¶
Released and unreleased changes. The text below is CHANGELOG.md from the repository. The newest section is Unreleased.
Unreleased¶
- Add
openodia.sandhito split an Odia compound into the words sandhi joined (split) and to join those parts (join). A known lemma, or a word that does not split into two known words, is returned unchanged.splitandjoinNFC-normalize, so for a compound the splitter acceptsjoin(split(word))equals the NFC form of that word.openodia.sandhineeds a release newer than 0.1.14:import openodia.sandhifails on 0.1.14. - Add
openodia.piiandopenodia piito find or mask phone numbers, emails, URLs, Aadhaar (Verhoeff checksum), PAN and PIN codes in Odia or ASCII digits. Names, addresses, dates and amounts are not detected. Overlapping matches merge into one span, so for every detected valuemasknever leaves part of it visible (see the limits below), andmaskrepeats until stable so masking its output changes nothing (up to 10 glued values). Detection is linear in the input size. - Every CLI subcommand accepts
--jsonand prints one UTF-8 JSON document on stdout; default text output is unchanged by--json. With--json, invalid UTF-8 in stdin or in the text argument is anopenodia: error:with exit code 1;detect-language --jsonused to pass it through in 0.1.14. - Docs for AI agents:
AGENTS.md,skills/openodia/SKILL.mdandllms.txton the docs site. - Docs: generated API reference and six usage guides (text, script and names, numbers, analysis, translation, command line) on the docs site, with every guide example checked by the test suite. The
docsanddevextras now includemkdocstrings[python]; the library's runtime dependencies are unchanged. - Docs: a getting started page, guides for transliteration and PII, API pages for
pii,indic, async translation, andSTOPWORDS, plus a changelog page and a contributing page. Docs search suggests matches and highlights the terms. Getting started says।is its own token only when a space precedes it. The translation guide says a padded English phrase hits the offline dictionary only on a release newer than 0.1.14. - Behaviour change, changes default output:
ud.sentence_tokenizernow splits after।,॥,?and!, with or without a space after them; it used to split only on" ।". Each sentence is trimmed and keeps its terminator, a terminator with no words of its own joins its neighbour, and empty input gives[]. A?or!directly followed by an ASCII letter, digit or=&%#/_(a?id=5,Yahoo!Mail) is not a boundary.["ଏକ ଦୁଇ", " ତିନି ଚାରି", ""]becomes["ଏକ ଦୁଇ ।", "ତିନି ଚାରି ।"]. This changes the default text and--jsonoutput ofopenodia tokenize --sentences(no leading spaces, no empty last entry,[]for empty input; text mode prints no blank line for empty input) and ofopenodia summarizeandWordFrequency.get_summary(sentences keep their।and are joined with one space, and text containing?,!,॥or a danda without a leading space is split into different sentences, so the chosen sentences can differ). This overrides the "output is unchanged" statement in the--jsonbullet above for these two subcommands. - Async translation:
odia_to_other_lang_async,other_lang_to_odia_async,universal_translation_asyncandtranslate_batchwith bounded concurrency, optional retries andreturn_exceptions. TranslationCachecan be shared between threads (it can still be pickled and deep-copied). Concurrentget,setandclearcalls no longer raiseKeyErroror lose hit and miss counts, and agetthat reads the disk cache while asetorclearruns no longer puts the old or cleared value back in memory. A disk write or clear that raises leaves the cache usable. Pickling or copying a cache while another thread writes to it takes a consistent snapshot. Behaviour change:copy.copy(cache)now gets its own memory entries instead of sharing them with the original.openodia.cache.get_cache()builds its singleton under a lock, so threads making the first call together share one cache (before,OPENODIA_CACHE_DISKcould give each its own, losing entries and counts).- The package ships
py.typed(PEP 561) and is fully type-annotated (mypy strict), so type checkers see the narrowedremove_stopwordsreturn types. import openodiaandopenodia --helpno longer importfaker,deep_translator,requestsorbs4; they load on first use ofname.generate_namesor a Google translation (a cached result or an offline-dictionary hit loads nothing).import openodiais about 2.5x faster in this repo's measurements. The public API is unchanged.import openodiano longer configures logging. It used to calllogging.basicConfigwith a Rich handler, which attached a root handler in the host application and printed log lines (with local variables in tracebacks) to stdout. Library logs now go to theopenodialogger, which has aNullHandler; configure logging in your application to see them. TheopenodiaCLI output is unchanged.- An invalid
name_typeinname.generate_firstnameslogs an error without the meaninglessNoneType: Nonetraceback line (theValueErroris unchanged). openodia translateandother_lang_to_odiafind offline-dictionary words when the text has leading or trailing whitespace. Input from--fileor stdin ends in a newline, so it used to miss the dictionary and call Google Translate, which failed whenever Google rate limited the request.
Added¶
openodia.phonetic: Odia-adapted phonetic matching (soundex,metaphone, andsimilarity).-
openodia.indic: transliterate between Brahmic Indic scripts. A composition-excluded nukta letter is consonant + nukta when the target has those parts, except Gurmukhi flap RRA and a target LLA, SHA, or YYA, which stay one letter. Odia WA stays when the target has no WA. Bengali writes VA as BA. A Malayalam chillu expands to consonant + virama. -
openodia.roman: Odia romanisation (to_roman/from_roman) with the ISO 15919, Hunterian and ITRANS schemes. -
Hunterian
from_romandecodes no Roman spelling as anusvara, candrabindu or visarga: annorhthat is not part of a longer letter such asngorkhdecodes as the consonantନorହ. Odiaଂ,ଁandଃin the input pass through.ନ୍endings and clusters such asନ୍ସandଙ୍କround-trip; anusvara and visarga round-trip through the explicit marks of ISO 15919 and ITRANS. -
to_romanwrites a nukta after any consonant except ଡ and ଢ as·in ISO 15919 and a backtick in ITRANS, and drops it in Hunterian. ଡ଼ and ଢ଼ keep their own letters in all three schemes:ṛ/ṛhin ISO 15919,.D/.Dhin ITRANS, andr/rhin Hunterian (where plain ଡ and ଢ gived/dh).from_romanreads each scheme's mark back as the nukta, soto_roman(..., reversible=True)now quotes a literal·(ISO 15919) or backtick (ITRANS) instead of passing it through.
Behaviour note¶
- By default,
to_romanreturns non-Odia text exactly as given, so its output no longer round-trips text that mixes Odia with other text (for exampleto_roman("କi")giveskai, whichfrom_romanreads asକୈ). Callers who need an exact round trip should passreversible=True(to_roman("କi", reversible=True)giveska:{i:}). - In
ISO15919andITRANS,from_roman(to_roman(text, scheme, reversible=True), scheme)gives backtextwith each run of Odia characters (U+0B00-U+0B7F) in NFC and all other characters unchanged. NFC Odia therefore comes back with the same code points, including vowel signs, viramas and nuktas that follow no consonant or follow ZWJ/ZWNJ. - In all three schemes, each run of Odia characters (U+0B00-U+0B7F) in the
output of
from_romanis in NFC, including Odia passed through or quoted in the input, so U+0B5C gives U+0B21 U+0B3C. Non-Odia characters thatfrom_romandoes not decode are left as given, except thatISO15919applies NFC to its input outside quotes.
0.1.14 (2026-10-26)¶
python -m openodianow runs the CLI.- Add CLI
--version, UTF-8 stdin handling, and concise file/encoding errors. - File input now requires
--file; existing filenames passed without it are literal text. openodia translatereports Google rate limits, unsupported language codes and text over 5,000 characters as a singleopenodia: error:line instead of a traceback.- UTF-8 byte order marks are ignored in
--fileinput, stdin andStopwords.from_file, which now defaults toencoding="utf-8-sig"(files without a BOM read as before). - The CLI exits quietly on a closed pipe (status 141), reports closed stdin and invalid
OPENODIA_CACHE_*values as one-line errors, and names argument types plainly in error messages. - Docs:
alphabet.matras, two-decimal confidence scores and a workingud.sentence_tokenizerexample.