Spaces:
Running on Zero
Running on Zero
Download maya3/tests/test_text.py from hugging-apps/maya2-native: direct link, hf CLI and curl.
- Browser
- Download file 22.9 kB
-
https://huggingface.co/spaces/hugging-apps/maya2-native/resolve/main/maya3/tests/test_text.py
- Command line
-
hf download hf://spaces/hugging-apps/maya2-native/maya3/tests/test_text.py
-
curl -L -o test_text.py https://huggingface.co/spaces/hugging-apps/maya2-native/resolve/main/maya3/tests/test_text.py
22.9 kB
| """Bundled text normaliser (maya3.text): CPU only, standard library only. | |
| python -m pytest maya3/tests/test_text.py -q | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import re | |
| import subprocess | |
| import sys | |
| import pytest | |
| import maya3.text as T | |
| from maya3.text import normalise_text | |
| ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| def test_normalise(text, lang, want): | |
| assert normalise_text(text, lang) == want | |
| def test_caps_fold_and_acronyms(): | |
| assert normalise_text("RAHUL KUMAR paid", "en") == "Rahul Kumar paid" | |
| assert normalise_text("HDFC NEFT KYC done", "en") == "HDFC NEFT KYC done" # vowel-poor: stay acronyms | |
| assert T._caps_fold("ASHA OTP NASA KYC") == "Asha OTP Nasa KYC" # 4 letters + 2 vowels -> a name | |
| def test_tags_are_protected(): | |
| out = normalise_text("[laughs] 2 [sighs] [whispers] 3 [laughs]", "en") | |
| assert out == "[laughs] two [sighs] [whispers] three [laughs]" | |
| assert normalise_text("[laughs]", "en") == "[laughs]" | |
| def test_fallback_returns_text_unchanged(monkeypatch): | |
| def boom(s, lang): | |
| raise RuntimeError("tn failure") | |
| monkeypatch.setattr(T, "_TN", boom) | |
| assert normalise_text("I have 25 apples [laughs] 3", "en") == "I have 25 apples [laughs] 3" | |
| monkeypatch.setattr(T, "_TN", None) | |
| assert normalise_text("x 1", "fr") == "x 1" # unsupported language: unchanged | |
| def test_all_languages_run(): | |
| for lang in ("as", "bn", "en", "gu", "hi", "kn", "ml", "mr", "or", "pa", "ta", "te"): | |
| out = normalise_text("Pay ₹1,250 on 12/03/2024 at 10:30, call 9820451120 [laughs]", lang) | |
| assert out and not any(ch.isdigit() for ch in out) and out.endswith("[laughs]"), (lang, out) | |
| def test_vendored_copy_is_verbatim(): | |
| import hashlib | |
| want = { # sha256 of the vendored upstream tn files (upstream commit fe5e6ec) | |
| "assamese_numbers.py": "0f590e4132c5ee539d4fffdf098c58ae1b72ba28c9b939f78ffb78374c043d48", | |
| "identifier_rules.py": "c3021145c5020b85d8597f4e47415e0341c1baafa0fbc0a80318a8b27f523682", | |
| "indic_languages.py": "af9195e44e739bf72b2522a253d69edd0d6fc5ff1dbb7f1b5040f548cabcd800", # one comment line reworded for the public release | |
| "normalize.py": "b232015a7c02b8ab9b28f5e21571a0cd6c4ad7ee35ab9381bd5ee56a59169b8b", | |
| "script_guard.py": "5b7405de2997932ff8785da20fbd3c89e5316ce3854638194dec3f4988e019fb", | |
| "text_pipeline.py": "259b2ac510406bdef6a5f9bc14ebc2d3c28173729bdb6dff71e25ea31b44680a", | |
| "tts_chunker.py": "6ad313fa5bff97512d07db5164664802c9c9f887dd835e8ad5bc8d814657ff58", | |
| } | |
| d = os.path.join(os.path.dirname(T.__file__), "tn") | |
| got = {f: hashlib.sha256(open(os.path.join(d, f), "rb").read()).hexdigest() for f in want} | |
| assert got == want | |
| def test_imports_with_stdlib_only(): | |
| code = ("import sys; import maya3.text as t; assert t.normalise_text('25', 'hi') == 'पच्चीस'; " | |
| "print(sorted({m.split('.')[0] for m in sys.modules} & {'numpy', 'torch', 'scipy', 'aiohttp'}))") | |
| out = subprocess.run([sys.executable, "-c", code], cwd=ROOT, capture_output=True, text=True, check=True) | |
| assert out.stdout.strip() == "[]" | |
| GUARDS = os.environ.get("MAYA3_REF_GUARDS", "") # optional: reference wrapper for the parity test | |
| def test_parity_with_eval_wrapper(): | |
| """Same output as the wrapper the release evals used, on the source repo's audit cases in every language.""" | |
| import importlib.util | |
| import json | |
| spec = importlib.util.spec_from_file_location("_eval_guards", GUARDS) | |
| g = importlib.util.module_from_spec(spec) | |
| spec.loader.exec_module(g) | |
| base = os.environ.get("MAYA3_REF_NORM_CASES", "") | |
| cases = [c["input"] for c in json.load(open(base))["cases"]] if os.path.exists(base) else [] | |
| cases += ["Your OTP is 482913 [laughs]", "Visit https://www.example.com/abc", "RAHUL KUMAR paid ₹1,250"] | |
| for text in cases: | |
| for lang in ("en", "hi", "te", "ta", "bn", "kn"): | |
| t = text + " [laughs] " + text.upper() | |
| assert normalise_text(t, lang, rules=False) == g.normalise_text(t, lang), (lang, t) | |
| # --------------------------------------------------------------------------------------------------------------- | |
| # Residual-failure rules (maya3.text.rules), cases taken from eval rows that still failed with normalisation on. | |
| def test_residual_rules(text, lang, want): | |
| assert normalise_text(text, lang) == want | |
| def test_residual_rules_keep_existing(text, lang): | |
| from maya3.text.tn import normalize as tn_normalize | |
| assert normalise_text(text, lang) == tn_normalize(T._caps_fold(text), lang).strip() | |
| def test_residual_rules_negative(text, lang, want): | |
| from maya3.text.tn import normalize as tn_normalize | |
| plain = re.sub(r"\s+", " ", tn_normalize(T._caps_fold(text), lang)).strip() | |
| got = normalise_text(text, lang) | |
| if want is None: | |
| assert got == plain.replace(" dash ", " " + T._rules.DASH.get(lang, "dash") + " ") | |
| else: | |
| assert got == want | |
| assert "February" not in got and "फ़रवरी" not in got and "फरवरी" not in got | |
| def test_tag_keeps_comma(monkeypatch): | |
| # P1 is off by default (no measured gain); when switched on it keeps the comma before an inline [tag] | |
| assert normalise_text("नौ, आठ, सात, [curious] छह, पाँच", "hi") == "नौ, आठ, सात. [curious] छह, पाँच" | |
| monkeypatch.setattr(T._rules, "TAG_COMMA", True) | |
| assert normalise_text("नौ, आठ, सात, [curious] छह, पाँच", "hi") == "नौ, आठ, सात, [curious] छह, पाँच" | |
| assert normalise_text("आपका पेमेंट फेल हुआ था ना, [sighs] बारह मई को", "hi") == "आपका पेमेंट फेल हुआ था ना, [sighs] बारह मई को" | |
| assert normalise_text("ठीक है. [laughs] चलो", "hi") == "ठीक है. [laughs] चलो" | |
| def test_uri_dash_native(): | |
| assert normalise_text("kyc_update@safebank-india.com ਤੇ ਭੇਜੋ", "pa") == "ਕੇ ਵਾਈ ਸੀ ਅੰਡਰਸਕੋਰ update ਐਟ ਦ ਰੇਟ safebank ਡੈਸ਼ india ਡਾਟ com ਤੇ ਭੇਜੋ" # P3 spells kyc | |
| assert "dash" in normalise_text("mail a-b@x.com", "en") | |
| def test_rules_all_languages(): | |
| for lang in ("as", "bn", "en", "gu", "hi", "kn", "ml", "mr", "or", "pa", "ta", "te"): | |
| out = normalise_text("15-08-25, 4111 2233 4455 6677, 560038, ₹95.41, v4.5.2, 2023-24, expiry 08/27", lang) | |
| assert out and not any(ch.isdigit() for ch in out), (lang, out) | |
| assert "minus" not in out and "/" not in out, (lang, out) | |
| # --------------------------------------------------------------------------------------------------------------- | |
| # normaliser fixes from a multi-language benchmark (maya3.text.lexicon L1-L3, maya3.text.rules P3) | |
| def test_assamese_lexicon(text, want): | |
| assert normalise_text(text, "as") == want | |
| def test_assamese_no_bengali_forms(): | |
| from maya3.text import lexicon | |
| T._lexicon.install(True) | |
| assert all("র" not in w for w in lexicon.AS_ONES) and len(lexicon.AS_ONES) == 100 | |
| s = ("Pay ₹1,23,456.75 on 12/03/2024 at 5:00 PM, 1st, 3rd, 33%, 1/2, x², 5 > 3, a_b@x-y.co.in, #45, A&B, " | |
| "38°C, RS 42, 9:15 AM, 14:30, 1990 চনত, 99, 31, 38 [laughs]") | |
| out = normalise_text(s, "as") | |
| assert "র" not in out and not any(ch.isdigit() for ch in out), out # no Bengali ra (র), no digits | |
| for bn_word in ("চার", "আট", "তিন ", "নয়", "সকাল", "দুপুর", "সন্ধ্যা", "অ্যাট", "এর ", "টা বেজে"): | |
| assert bn_word not in out, (bn_word, out) | |
| def test_lexicon_off_restores_vendored_tables(): | |
| from maya3.text.tn import normalize as tn_normalize | |
| s = "12:30 PM ত ₹50 ৰ 45, 71 support@hdfcbank.com e-receipt.hdfcbank.com 40 km/h" | |
| for lang in ("as", "bn", "hi", "kn"): | |
| on = normalise_text(s, lang) | |
| off = normalise_text(s, lang, rules=False) | |
| assert off == re.sub(r"\s+", " ", tn_normalize(T._caps_fold(s), lang)).strip() | |
| assert on != off | |
| assert normalise_text(s, lang) == on # toggling back on gives the same output | |
| assert "ত্রিশ" in normalise_text("30", "as", rules=False) # vendored data untouched | |
| assert normalise_text("30", "bn") == "ত্রিশ" # Bengali keeps its own ra | |
| def test_per_units(text, lang, want): | |
| assert normalise_text(text, lang) == want | |
| def test_uri_hosts_and_acronyms(text, lang, want): | |
| assert normalise_text(text, lang) == want | |
| def test_uri_acronym_only_inside_uris(): | |
| assert normalise_text("sbi and kyc", "en") == "sbi and kyc" | |
| assert normalise_text("Contact the public office", "en") == "Contact the public office" | |
| def test_symbol_rules(text, lang, want): | |
| assert normalise_text(text, lang) == want | |