scriptconv 0.0.1a6__tar.gz → 0.0.2a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/PKG-INFO +10 -4
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/README.md +9 -3
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv/__init__.py +4 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv/notation.py +128 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv/version.py +2 -2
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv.egg-info/PKG-INFO +10 -4
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/tests/test_examples.py +6 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/tests/test_notation.py +52 -1
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/LICENSE +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/pyproject.toml +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/requirements.txt +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv/__main__.py +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv/py.typed +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv/scripts.py +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv/translit.py +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv.egg-info/SOURCES.txt +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv.egg-info/dependency_links.txt +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv.egg-info/requires.txt +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/scriptconv.egg-info/top_level.txt +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/setup.cfg +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/tests/test_cli.py +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/tests/test_scripts.py +0 -0
- {scriptconv-0.0.1a6 → scriptconv-0.0.2a1}/tests/test_translit.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scriptconv
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2a1
|
|
4
4
|
Summary: Shared script-conversion core — ISO-15924 detection, IPA↔ARPA/X-SAMPA/Lexique, Buckwalter, Hangul→jamo
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/TigreGotico/scriptconv
|
|
@@ -33,7 +33,7 @@ Dynamic: license-file
|
|
|
33
33
|
|
|
34
34
|
**scriptconv** is a zero-dependency Python library for written-script operations:
|
|
35
35
|
ISO-15924 script identification and metadata, character-range detection, language-to-script
|
|
36
|
-
mapping, phoneme-notation transcoding (IPA ↔ ARPABET
|
|
36
|
+
mapping, phoneme-notation transcoding (IPA ↔ ARPABET / X-SAMPA / Lexique / Kirshenbaum / Cotovía,
|
|
37
37
|
Buckwalter ↔ Arabic script), and orthographic decomposition of Hangul syllable blocks into
|
|
38
38
|
jamo letters. Every conversion is a pure data table or arithmetic operation; no linguistic
|
|
39
39
|
rules, no external files, no runtime dependencies beyond the Python standard library.
|
|
@@ -75,7 +75,7 @@ from scriptconv import (
|
|
|
75
75
|
xsampa_to_ipa, ipa_to_xsampa,
|
|
76
76
|
buckwalter_to_arabic, arabic_to_buckwalter,
|
|
77
77
|
lexique_to_ipa, ipa_to_lexique,
|
|
78
|
-
kirshenbaum_to_ipa, ipa_to_kirshenbaum, looks_like_ipa,
|
|
78
|
+
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia, looks_like_ipa,
|
|
79
79
|
decompose_hangul, hira_to_kana, kana_to_hira,
|
|
80
80
|
convert, can_convert, convert_batch, Notation, NOTATION_INFO,
|
|
81
81
|
)
|
|
@@ -107,6 +107,9 @@ ipa_to_lexique("vɛ̃") # "v5" (vin)
|
|
|
107
107
|
kirshenbaum_to_ipa("S") # "ʃ" (espeak-ng ASCII-IPA)
|
|
108
108
|
ipa_to_kirshenbaum("ŋ") # "N"
|
|
109
109
|
|
|
110
|
+
cotovia_to_ipa("karro") # "karo" (Galician Cotovía TTS notation)
|
|
111
|
+
ipa_to_cotovia("ʎ") # "L"
|
|
112
|
+
|
|
110
113
|
looks_like_ipa("pʰɑtʃ") # True (heuristic: has IPA-distinctive symbols)
|
|
111
114
|
looks_like_ipa("hello") # False
|
|
112
115
|
|
|
@@ -139,7 +142,7 @@ python -m scriptconv lang ko
|
|
|
139
142
|
| Module | Contents |
|
|
140
143
|
|--------|----------|
|
|
141
144
|
| `scriptconv.scripts` | `Script` dataclass (with `script_type`), `SCRIPT_REGISTRY` (34 scripts), `detect_script`, `char_script`, `script_distribution`, `script_runs`, `base_direction`, `lang_to_script`, `script_to_langs`, `normalize_script_tag` |
|
|
142
|
-
| `scriptconv.notation` | `Notation` enum, `NotationInfo`/`NOTATION_INFO` fidelity registry, `convert` facade, `can_convert` predicate, `convert_batch` generator, pair-wise converters (ARPABET ↔ IPA, X-SAMPA ↔ IPA, Buckwalter ↔ Arabic, Lexique ↔ IPA, Kirshenbaum ↔ IPA), `looks_like_ipa` detector |
|
|
145
|
+
| `scriptconv.notation` | `Notation` enum, `NotationInfo`/`NOTATION_INFO` fidelity registry, `convert` facade, `can_convert` predicate, `convert_batch` generator, pair-wise converters (ARPABET ↔ IPA, X-SAMPA ↔ IPA, Buckwalter ↔ Arabic, Lexique ↔ IPA, Kirshenbaum ↔ IPA, Cotovía ↔ IPA), `looks_like_ipa` detector |
|
|
143
146
|
| `scriptconv.translit` | `decompose_hangul` (Hangul blocks → jamo, compatibility or conjoining), `hira_to_kana`/`kana_to_hira` — all orthographic only |
|
|
144
147
|
|
|
145
148
|
## Documentation
|
|
@@ -168,6 +171,7 @@ Runnable scripts in [examples/](examples/):
|
|
|
168
171
|
| `12_kirshenbaum.py` | Kirshenbaum (ASCII-IPA) ↔ IPA, and ARPABET → Kirshenbaum routing |
|
|
169
172
|
| `13_script_runs.py` | Per-script segmentation of mixed-script text |
|
|
170
173
|
| `14_kana_transliteration.py` | Hiragana ↔ Katakana |
|
|
174
|
+
| `15_cotovia.py` | Cotovía (Galician TTS notation) ↔ IPA |
|
|
171
175
|
|
|
172
176
|
## Fidelity guarantees
|
|
173
177
|
|
|
@@ -182,6 +186,7 @@ round-trip is exact and what happens to a symbol the table does not know.
|
|
|
182
186
|
| **Buckwalter ↔ Arabic** | Exact (the `^` shadda alias normalises to canonical `~`; precomposed lam-alef ligatures decompose to two chars, visually identical) | Exact | Passed through unchanged |
|
|
183
187
|
| **Lexique ↔ IPA** | Exact except the `°`/`3` schwa pair (both → `ə`; reverse always → `°`) | Exact | Passed through unchanged |
|
|
184
188
|
| **Kirshenbaum ↔ IPA** | Exact | **Lossy** — restricted ASCII inventory; IPA outside it passes through | Passed through unchanged |
|
|
189
|
+
| **Cotovía ↔ IPA** | Exact except the three `L`/`Z`/`jj` symbols for `ʎ` normalise to `L` | **Lossy** — Galician/Spanish inventory; IPA outside it passes through | Passed through unchanged |
|
|
185
190
|
|
|
186
191
|
This table is also available programmatically via `NOTATION_INFO`
|
|
187
192
|
(`NotationInfo` records with `lossless_to_ipa`, `lossless_from_ipa`,
|
|
@@ -207,4 +212,5 @@ Derived tables used internally:
|
|
|
207
212
|
| Buckwalter ↔ Arabic | Tim Buckwalter's Arabic transliteration scheme | — (factual 1:1 mapping) |
|
|
208
213
|
| Lexique phoneme codes | New, B. & Pallier, C. — *Manuel de Lexique 3* v3.11, Tableau 2; [chrplr/openlexicon](https://github.com/chrplr/openlexicon) | CC BY-SA 4.0 |
|
|
209
214
|
| Kirshenbaum ↔ IPA | Kirshenbaum 1993 ASCII-IPA standard (comp.speech), cross-checked against espeak-ng | — (factual symbol mapping) |
|
|
215
|
+
| Cotovía ↔ IPA | Universidade de Vigo GTM Cotovía TTS project (`fonemas.cpp`) | — (factual symbol mapping) |
|
|
210
216
|
| Hangul jamo tables | [stannam/hangul_to_ipa](https://github.com/stannam/hangul_to_ipa) | — |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
**scriptconv** is a zero-dependency Python library for written-script operations:
|
|
8
8
|
ISO-15924 script identification and metadata, character-range detection, language-to-script
|
|
9
|
-
mapping, phoneme-notation transcoding (IPA ↔ ARPABET
|
|
9
|
+
mapping, phoneme-notation transcoding (IPA ↔ ARPABET / X-SAMPA / Lexique / Kirshenbaum / Cotovía,
|
|
10
10
|
Buckwalter ↔ Arabic script), and orthographic decomposition of Hangul syllable blocks into
|
|
11
11
|
jamo letters. Every conversion is a pure data table or arithmetic operation; no linguistic
|
|
12
12
|
rules, no external files, no runtime dependencies beyond the Python standard library.
|
|
@@ -48,7 +48,7 @@ from scriptconv import (
|
|
|
48
48
|
xsampa_to_ipa, ipa_to_xsampa,
|
|
49
49
|
buckwalter_to_arabic, arabic_to_buckwalter,
|
|
50
50
|
lexique_to_ipa, ipa_to_lexique,
|
|
51
|
-
kirshenbaum_to_ipa, ipa_to_kirshenbaum, looks_like_ipa,
|
|
51
|
+
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia, looks_like_ipa,
|
|
52
52
|
decompose_hangul, hira_to_kana, kana_to_hira,
|
|
53
53
|
convert, can_convert, convert_batch, Notation, NOTATION_INFO,
|
|
54
54
|
)
|
|
@@ -80,6 +80,9 @@ ipa_to_lexique("vɛ̃") # "v5" (vin)
|
|
|
80
80
|
kirshenbaum_to_ipa("S") # "ʃ" (espeak-ng ASCII-IPA)
|
|
81
81
|
ipa_to_kirshenbaum("ŋ") # "N"
|
|
82
82
|
|
|
83
|
+
cotovia_to_ipa("karro") # "karo" (Galician Cotovía TTS notation)
|
|
84
|
+
ipa_to_cotovia("ʎ") # "L"
|
|
85
|
+
|
|
83
86
|
looks_like_ipa("pʰɑtʃ") # True (heuristic: has IPA-distinctive symbols)
|
|
84
87
|
looks_like_ipa("hello") # False
|
|
85
88
|
|
|
@@ -112,7 +115,7 @@ python -m scriptconv lang ko
|
|
|
112
115
|
| Module | Contents |
|
|
113
116
|
|--------|----------|
|
|
114
117
|
| `scriptconv.scripts` | `Script` dataclass (with `script_type`), `SCRIPT_REGISTRY` (34 scripts), `detect_script`, `char_script`, `script_distribution`, `script_runs`, `base_direction`, `lang_to_script`, `script_to_langs`, `normalize_script_tag` |
|
|
115
|
-
| `scriptconv.notation` | `Notation` enum, `NotationInfo`/`NOTATION_INFO` fidelity registry, `convert` facade, `can_convert` predicate, `convert_batch` generator, pair-wise converters (ARPABET ↔ IPA, X-SAMPA ↔ IPA, Buckwalter ↔ Arabic, Lexique ↔ IPA, Kirshenbaum ↔ IPA), `looks_like_ipa` detector |
|
|
118
|
+
| `scriptconv.notation` | `Notation` enum, `NotationInfo`/`NOTATION_INFO` fidelity registry, `convert` facade, `can_convert` predicate, `convert_batch` generator, pair-wise converters (ARPABET ↔ IPA, X-SAMPA ↔ IPA, Buckwalter ↔ Arabic, Lexique ↔ IPA, Kirshenbaum ↔ IPA, Cotovía ↔ IPA), `looks_like_ipa` detector |
|
|
116
119
|
| `scriptconv.translit` | `decompose_hangul` (Hangul blocks → jamo, compatibility or conjoining), `hira_to_kana`/`kana_to_hira` — all orthographic only |
|
|
117
120
|
|
|
118
121
|
## Documentation
|
|
@@ -141,6 +144,7 @@ Runnable scripts in [examples/](examples/):
|
|
|
141
144
|
| `12_kirshenbaum.py` | Kirshenbaum (ASCII-IPA) ↔ IPA, and ARPABET → Kirshenbaum routing |
|
|
142
145
|
| `13_script_runs.py` | Per-script segmentation of mixed-script text |
|
|
143
146
|
| `14_kana_transliteration.py` | Hiragana ↔ Katakana |
|
|
147
|
+
| `15_cotovia.py` | Cotovía (Galician TTS notation) ↔ IPA |
|
|
144
148
|
|
|
145
149
|
## Fidelity guarantees
|
|
146
150
|
|
|
@@ -155,6 +159,7 @@ round-trip is exact and what happens to a symbol the table does not know.
|
|
|
155
159
|
| **Buckwalter ↔ Arabic** | Exact (the `^` shadda alias normalises to canonical `~`; precomposed lam-alef ligatures decompose to two chars, visually identical) | Exact | Passed through unchanged |
|
|
156
160
|
| **Lexique ↔ IPA** | Exact except the `°`/`3` schwa pair (both → `ə`; reverse always → `°`) | Exact | Passed through unchanged |
|
|
157
161
|
| **Kirshenbaum ↔ IPA** | Exact | **Lossy** — restricted ASCII inventory; IPA outside it passes through | Passed through unchanged |
|
|
162
|
+
| **Cotovía ↔ IPA** | Exact except the three `L`/`Z`/`jj` symbols for `ʎ` normalise to `L` | **Lossy** — Galician/Spanish inventory; IPA outside it passes through | Passed through unchanged |
|
|
158
163
|
|
|
159
164
|
This table is also available programmatically via `NOTATION_INFO`
|
|
160
165
|
(`NotationInfo` records with `lossless_to_ipa`, `lossless_from_ipa`,
|
|
@@ -180,4 +185,5 @@ Derived tables used internally:
|
|
|
180
185
|
| Buckwalter ↔ Arabic | Tim Buckwalter's Arabic transliteration scheme | — (factual 1:1 mapping) |
|
|
181
186
|
| Lexique phoneme codes | New, B. & Pallier, C. — *Manuel de Lexique 3* v3.11, Tableau 2; [chrplr/openlexicon](https://github.com/chrplr/openlexicon) | CC BY-SA 4.0 |
|
|
182
187
|
| Kirshenbaum ↔ IPA | Kirshenbaum 1993 ASCII-IPA standard (comp.speech), cross-checked against espeak-ng | — (factual symbol mapping) |
|
|
188
|
+
| Cotovía ↔ IPA | Universidade de Vigo GTM Cotovía TTS project (`fonemas.cpp`) | — (factual symbol mapping) |
|
|
183
189
|
| Hangul jamo tables | [stannam/hangul_to_ipa](https://github.com/stannam/hangul_to_ipa) | — |
|
|
@@ -50,6 +50,8 @@ from scriptconv.notation import (
|
|
|
50
50
|
ipa_to_lexique,
|
|
51
51
|
kirshenbaum_to_ipa,
|
|
52
52
|
ipa_to_kirshenbaum,
|
|
53
|
+
cotovia_to_ipa,
|
|
54
|
+
ipa_to_cotovia,
|
|
53
55
|
looks_like_ipa,
|
|
54
56
|
)
|
|
55
57
|
from scriptconv.translit import (
|
|
@@ -87,6 +89,8 @@ __all__ = [
|
|
|
87
89
|
"ipa_to_lexique",
|
|
88
90
|
"kirshenbaum_to_ipa",
|
|
89
91
|
"ipa_to_kirshenbaum",
|
|
92
|
+
"cotovia_to_ipa",
|
|
93
|
+
"ipa_to_cotovia",
|
|
90
94
|
"looks_like_ipa",
|
|
91
95
|
# translit
|
|
92
96
|
"decompose_hangul",
|
|
@@ -37,6 +37,8 @@ __all__ = [
|
|
|
37
37
|
"ipa_to_lexique",
|
|
38
38
|
"kirshenbaum_to_ipa",
|
|
39
39
|
"ipa_to_kirshenbaum",
|
|
40
|
+
"cotovia_to_ipa",
|
|
41
|
+
"ipa_to_cotovia",
|
|
40
42
|
"looks_like_ipa",
|
|
41
43
|
]
|
|
42
44
|
|
|
@@ -51,6 +53,7 @@ class Notation(str, Enum):
|
|
|
51
53
|
ARABIC = "arabic" # Arabic script (target/source for BW)
|
|
52
54
|
LEXIQUE = "lexique" # Lexique one-char-per-phoneme French notation
|
|
53
55
|
KIRSHENBAUM = "kirshenbaum" # ASCII-IPA (espeak-ng native notation)
|
|
56
|
+
COTOVIA = "cotovia" # Universidade de Vigo Cotovía TTS notation (gl)
|
|
54
57
|
|
|
55
58
|
def __repr__(self) -> str:
|
|
56
59
|
return f"Notation.{self.name}"
|
|
@@ -665,6 +668,124 @@ def ipa_to_kirshenbaum(ipa: str) -> str:
|
|
|
665
668
|
return "".join(_IPA_TO_KIRSHENBAUM.get(ch, ch) for ch in ipa)
|
|
666
669
|
|
|
667
670
|
|
|
671
|
+
# ---------------------------------------------------------------------------
|
|
672
|
+
# Cotovía ↔ IPA
|
|
673
|
+
#
|
|
674
|
+
# Cotovía is the internal phoneme notation of the Universidade de Vigo GTM
|
|
675
|
+
# Cotovía TTS system (Galician/Spanish). The table is the phoneme symbol map
|
|
676
|
+
# from its ``fonemas.cpp``. Symbols are matched longest-first (``tS``, ``rr``
|
|
677
|
+
# before single characters). The silence/pause marker (``#``) is a boundary
|
|
678
|
+
# token, not a phoneme, and is intentionally excluded.
|
|
679
|
+
# ---------------------------------------------------------------------------
|
|
680
|
+
|
|
681
|
+
_COTOVIA_TO_IPA: dict[str, str] = {
|
|
682
|
+
# Double-character symbols first (longest-match ordering)
|
|
683
|
+
"tS": "tʃ",
|
|
684
|
+
"rr": "r", # trill (single "r" is the tap ɾ)
|
|
685
|
+
"jj": "ʎ",
|
|
686
|
+
# Consonants
|
|
687
|
+
"B": "β",
|
|
688
|
+
"D": "ð",
|
|
689
|
+
"G": "ɣ",
|
|
690
|
+
"J": "ɲ",
|
|
691
|
+
"N": "ŋ",
|
|
692
|
+
"S": "ʃ",
|
|
693
|
+
"T": "θ",
|
|
694
|
+
"Z": "ʎ",
|
|
695
|
+
"L": "ʎ", # canonical Cotovía symbol for the palatal lateral
|
|
696
|
+
"b": "b",
|
|
697
|
+
"d": "d",
|
|
698
|
+
"f": "f",
|
|
699
|
+
"g": "ɡ",
|
|
700
|
+
"k": "k",
|
|
701
|
+
"l": "l",
|
|
702
|
+
"m": "m",
|
|
703
|
+
"n": "n",
|
|
704
|
+
"p": "p",
|
|
705
|
+
"r": "ɾ", # tap
|
|
706
|
+
"s": "s",
|
|
707
|
+
"t": "t",
|
|
708
|
+
"x": "x",
|
|
709
|
+
"X": "x",
|
|
710
|
+
# Vowels
|
|
711
|
+
"E": "ɛ",
|
|
712
|
+
"O": "ɔ",
|
|
713
|
+
"a": "a",
|
|
714
|
+
"e": "e",
|
|
715
|
+
"i": "i",
|
|
716
|
+
"o": "o",
|
|
717
|
+
"u": "u",
|
|
718
|
+
# Glides
|
|
719
|
+
"j": "j",
|
|
720
|
+
"w": "w",
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
# Reverse: IPA → Cotovía. First-wins deduplicates the symbols that share an IPA
|
|
724
|
+
# value; pin ʎ → "L" (the standard Cotovía palatal-lateral symbol) and x → "x".
|
|
725
|
+
_IPA_TO_COTOVIA: dict[str, str] = {}
|
|
726
|
+
for _cv, _ip in _COTOVIA_TO_IPA.items():
|
|
727
|
+
_IPA_TO_COTOVIA.setdefault(_ip, _cv)
|
|
728
|
+
_IPA_TO_COTOVIA["ʎ"] = "L"
|
|
729
|
+
_IPA_TO_COTOVIA["x"] = "x"
|
|
730
|
+
|
|
731
|
+
_CV_KEYS_SORTED = sorted(_COTOVIA_TO_IPA.keys(), key=len, reverse=True)
|
|
732
|
+
_CV_RE = re.compile("|".join(re.escape(s) for s in _CV_KEYS_SORTED))
|
|
733
|
+
_IPA_CV_KEYS_SORTED = sorted(_IPA_TO_COTOVIA.keys(), key=len, reverse=True)
|
|
734
|
+
_IPA_CV_RE = re.compile("|".join(re.escape(s) for s in _IPA_CV_KEYS_SORTED))
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
def cotovia_to_ipa(cotovia: str) -> str:
|
|
738
|
+
"""Convert a Cotovía phoneme string to IPA.
|
|
739
|
+
|
|
740
|
+
Multi-character symbols are matched longest-first. Characters outside the
|
|
741
|
+
table pass through unchanged.
|
|
742
|
+
|
|
743
|
+
Examples
|
|
744
|
+
--------
|
|
745
|
+
>>> cotovia_to_ipa("tS")
|
|
746
|
+
'tʃ'
|
|
747
|
+
>>> cotovia_to_ipa("karro")
|
|
748
|
+
'karo'
|
|
749
|
+
"""
|
|
750
|
+
result = []
|
|
751
|
+
pos = 0
|
|
752
|
+
while pos < len(cotovia):
|
|
753
|
+
m = _CV_RE.match(cotovia, pos)
|
|
754
|
+
if m:
|
|
755
|
+
result.append(_COTOVIA_TO_IPA[m.group(0)])
|
|
756
|
+
pos = m.end()
|
|
757
|
+
else:
|
|
758
|
+
result.append(cotovia[pos])
|
|
759
|
+
pos += 1
|
|
760
|
+
return "".join(result)
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def ipa_to_cotovia(ipa: str) -> str:
|
|
764
|
+
"""Convert an IPA string to Cotovía notation.
|
|
765
|
+
|
|
766
|
+
Multi-character IPA symbols are matched longest-first. Characters outside
|
|
767
|
+
the table pass through unchanged.
|
|
768
|
+
|
|
769
|
+
Examples
|
|
770
|
+
--------
|
|
771
|
+
>>> ipa_to_cotovia("tʃ")
|
|
772
|
+
'tS'
|
|
773
|
+
>>> ipa_to_cotovia("ʎ")
|
|
774
|
+
'L'
|
|
775
|
+
"""
|
|
776
|
+
result = []
|
|
777
|
+
pos = 0
|
|
778
|
+
while pos < len(ipa):
|
|
779
|
+
m = _IPA_CV_RE.match(ipa, pos)
|
|
780
|
+
if m:
|
|
781
|
+
result.append(_IPA_TO_COTOVIA[m.group(0)])
|
|
782
|
+
pos = m.end()
|
|
783
|
+
else:
|
|
784
|
+
result.append(ipa[pos])
|
|
785
|
+
pos += 1
|
|
786
|
+
return "".join(result)
|
|
787
|
+
|
|
788
|
+
|
|
668
789
|
# ---------------------------------------------------------------------------
|
|
669
790
|
# convert — facade routing through IPA where no direct map exists
|
|
670
791
|
# ---------------------------------------------------------------------------
|
|
@@ -735,12 +856,14 @@ _TO_IPA: dict[Notation, "callable"] = {
|
|
|
735
856
|
Notation.XSAMPA: xsampa_to_ipa,
|
|
736
857
|
Notation.LEXIQUE: lexique_to_ipa,
|
|
737
858
|
Notation.KIRSHENBAUM: kirshenbaum_to_ipa,
|
|
859
|
+
Notation.COTOVIA: cotovia_to_ipa,
|
|
738
860
|
}
|
|
739
861
|
_FROM_IPA: dict[Notation, "callable"] = {
|
|
740
862
|
Notation.ARPA: ipa_to_arpa,
|
|
741
863
|
Notation.XSAMPA: ipa_to_xsampa,
|
|
742
864
|
Notation.LEXIQUE: ipa_to_lexique,
|
|
743
865
|
Notation.KIRSHENBAUM: ipa_to_kirshenbaum,
|
|
866
|
+
Notation.COTOVIA: ipa_to_cotovia,
|
|
744
867
|
}
|
|
745
868
|
_DIRECT_PAIRS: dict[tuple[Notation, Notation], "callable"] = {
|
|
746
869
|
(Notation.BUCKWALTER, Notation.ARABIC): buckwalter_to_arabic,
|
|
@@ -846,6 +969,11 @@ NOTATION_INFO: dict[Notation, NotationInfo] = {
|
|
|
846
969
|
token_separated=False,
|
|
847
970
|
reference="Kirshenbaum 1993 ASCII-IPA standard (comp.speech)",
|
|
848
971
|
),
|
|
972
|
+
Notation.COTOVIA: NotationInfo(
|
|
973
|
+
Notation.COTOVIA, lossless_to_ipa=False, lossless_from_ipa=False,
|
|
974
|
+
token_separated=False,
|
|
975
|
+
reference="Universidade de Vigo GTM Cotovía TTS (fonemas.cpp)",
|
|
976
|
+
),
|
|
849
977
|
Notation.BUCKWALTER: NotationInfo(
|
|
850
978
|
Notation.BUCKWALTER, lossless_to_ipa=True, lossless_from_ipa=False,
|
|
851
979
|
token_separated=False,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scriptconv
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2a1
|
|
4
4
|
Summary: Shared script-conversion core — ISO-15924 detection, IPA↔ARPA/X-SAMPA/Lexique, Buckwalter, Hangul→jamo
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/TigreGotico/scriptconv
|
|
@@ -33,7 +33,7 @@ Dynamic: license-file
|
|
|
33
33
|
|
|
34
34
|
**scriptconv** is a zero-dependency Python library for written-script operations:
|
|
35
35
|
ISO-15924 script identification and metadata, character-range detection, language-to-script
|
|
36
|
-
mapping, phoneme-notation transcoding (IPA ↔ ARPABET
|
|
36
|
+
mapping, phoneme-notation transcoding (IPA ↔ ARPABET / X-SAMPA / Lexique / Kirshenbaum / Cotovía,
|
|
37
37
|
Buckwalter ↔ Arabic script), and orthographic decomposition of Hangul syllable blocks into
|
|
38
38
|
jamo letters. Every conversion is a pure data table or arithmetic operation; no linguistic
|
|
39
39
|
rules, no external files, no runtime dependencies beyond the Python standard library.
|
|
@@ -75,7 +75,7 @@ from scriptconv import (
|
|
|
75
75
|
xsampa_to_ipa, ipa_to_xsampa,
|
|
76
76
|
buckwalter_to_arabic, arabic_to_buckwalter,
|
|
77
77
|
lexique_to_ipa, ipa_to_lexique,
|
|
78
|
-
kirshenbaum_to_ipa, ipa_to_kirshenbaum, looks_like_ipa,
|
|
78
|
+
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia, looks_like_ipa,
|
|
79
79
|
decompose_hangul, hira_to_kana, kana_to_hira,
|
|
80
80
|
convert, can_convert, convert_batch, Notation, NOTATION_INFO,
|
|
81
81
|
)
|
|
@@ -107,6 +107,9 @@ ipa_to_lexique("vɛ̃") # "v5" (vin)
|
|
|
107
107
|
kirshenbaum_to_ipa("S") # "ʃ" (espeak-ng ASCII-IPA)
|
|
108
108
|
ipa_to_kirshenbaum("ŋ") # "N"
|
|
109
109
|
|
|
110
|
+
cotovia_to_ipa("karro") # "karo" (Galician Cotovía TTS notation)
|
|
111
|
+
ipa_to_cotovia("ʎ") # "L"
|
|
112
|
+
|
|
110
113
|
looks_like_ipa("pʰɑtʃ") # True (heuristic: has IPA-distinctive symbols)
|
|
111
114
|
looks_like_ipa("hello") # False
|
|
112
115
|
|
|
@@ -139,7 +142,7 @@ python -m scriptconv lang ko
|
|
|
139
142
|
| Module | Contents |
|
|
140
143
|
|--------|----------|
|
|
141
144
|
| `scriptconv.scripts` | `Script` dataclass (with `script_type`), `SCRIPT_REGISTRY` (34 scripts), `detect_script`, `char_script`, `script_distribution`, `script_runs`, `base_direction`, `lang_to_script`, `script_to_langs`, `normalize_script_tag` |
|
|
142
|
-
| `scriptconv.notation` | `Notation` enum, `NotationInfo`/`NOTATION_INFO` fidelity registry, `convert` facade, `can_convert` predicate, `convert_batch` generator, pair-wise converters (ARPABET ↔ IPA, X-SAMPA ↔ IPA, Buckwalter ↔ Arabic, Lexique ↔ IPA, Kirshenbaum ↔ IPA), `looks_like_ipa` detector |
|
|
145
|
+
| `scriptconv.notation` | `Notation` enum, `NotationInfo`/`NOTATION_INFO` fidelity registry, `convert` facade, `can_convert` predicate, `convert_batch` generator, pair-wise converters (ARPABET ↔ IPA, X-SAMPA ↔ IPA, Buckwalter ↔ Arabic, Lexique ↔ IPA, Kirshenbaum ↔ IPA, Cotovía ↔ IPA), `looks_like_ipa` detector |
|
|
143
146
|
| `scriptconv.translit` | `decompose_hangul` (Hangul blocks → jamo, compatibility or conjoining), `hira_to_kana`/`kana_to_hira` — all orthographic only |
|
|
144
147
|
|
|
145
148
|
## Documentation
|
|
@@ -168,6 +171,7 @@ Runnable scripts in [examples/](examples/):
|
|
|
168
171
|
| `12_kirshenbaum.py` | Kirshenbaum (ASCII-IPA) ↔ IPA, and ARPABET → Kirshenbaum routing |
|
|
169
172
|
| `13_script_runs.py` | Per-script segmentation of mixed-script text |
|
|
170
173
|
| `14_kana_transliteration.py` | Hiragana ↔ Katakana |
|
|
174
|
+
| `15_cotovia.py` | Cotovía (Galician TTS notation) ↔ IPA |
|
|
171
175
|
|
|
172
176
|
## Fidelity guarantees
|
|
173
177
|
|
|
@@ -182,6 +186,7 @@ round-trip is exact and what happens to a symbol the table does not know.
|
|
|
182
186
|
| **Buckwalter ↔ Arabic** | Exact (the `^` shadda alias normalises to canonical `~`; precomposed lam-alef ligatures decompose to two chars, visually identical) | Exact | Passed through unchanged |
|
|
183
187
|
| **Lexique ↔ IPA** | Exact except the `°`/`3` schwa pair (both → `ə`; reverse always → `°`) | Exact | Passed through unchanged |
|
|
184
188
|
| **Kirshenbaum ↔ IPA** | Exact | **Lossy** — restricted ASCII inventory; IPA outside it passes through | Passed through unchanged |
|
|
189
|
+
| **Cotovía ↔ IPA** | Exact except the three `L`/`Z`/`jj` symbols for `ʎ` normalise to `L` | **Lossy** — Galician/Spanish inventory; IPA outside it passes through | Passed through unchanged |
|
|
185
190
|
|
|
186
191
|
This table is also available programmatically via `NOTATION_INFO`
|
|
187
192
|
(`NotationInfo` records with `lossless_to_ipa`, `lossless_from_ipa`,
|
|
@@ -207,4 +212,5 @@ Derived tables used internally:
|
|
|
207
212
|
| Buckwalter ↔ Arabic | Tim Buckwalter's Arabic transliteration scheme | — (factual 1:1 mapping) |
|
|
208
213
|
| Lexique phoneme codes | New, B. & Pallier, C. — *Manuel de Lexique 3* v3.11, Tableau 2; [chrplr/openlexicon](https://github.com/chrplr/openlexicon) | CC BY-SA 4.0 |
|
|
209
214
|
| Kirshenbaum ↔ IPA | Kirshenbaum 1993 ASCII-IPA standard (comp.speech), cross-checked against espeak-ng | — (factual symbol mapping) |
|
|
215
|
+
| Cotovía ↔ IPA | Universidade de Vigo GTM Cotovía TTS project (`fonemas.cpp`) | — (factual symbol mapping) |
|
|
210
216
|
| Hangul jamo tables | [stannam/hangul_to_ipa](https://github.com/stannam/hangul_to_ipa) | — |
|
|
@@ -105,3 +105,9 @@ def test_14_kana_transliteration():
|
|
|
105
105
|
r = _run(EXAMPLES_DIR / "14_kana_transliteration.py")
|
|
106
106
|
assert r.returncode == 0, r.stderr
|
|
107
107
|
assert r.stdout.strip()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_15_cotovia():
|
|
111
|
+
r = _run(EXAMPLES_DIR / "15_cotovia.py")
|
|
112
|
+
assert r.returncode == 0, r.stderr
|
|
113
|
+
assert r.stdout.strip()
|
|
@@ -947,7 +947,7 @@ def test_notation_enum_values():
|
|
|
947
947
|
|
|
948
948
|
|
|
949
949
|
def test_notation_enum_count():
|
|
950
|
-
assert len(Notation) ==
|
|
950
|
+
assert len(Notation) == 8
|
|
951
951
|
|
|
952
952
|
|
|
953
953
|
def test_notation_str():
|
|
@@ -1057,3 +1057,54 @@ def test_looks_like_ipa_true(text):
|
|
|
1057
1057
|
])
|
|
1058
1058
|
def test_looks_like_ipa_false(text):
|
|
1059
1059
|
assert looks_like_ipa(text) is False
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
# ---------------------------------------------------------------------------
|
|
1063
|
+
# Cotovía ↔ IPA
|
|
1064
|
+
# ---------------------------------------------------------------------------
|
|
1065
|
+
|
|
1066
|
+
from scriptconv.notation import cotovia_to_ipa, ipa_to_cotovia # noqa: E402
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
@pytest.mark.parametrize("cv, ipa", [
|
|
1070
|
+
("tS", "tʃ"),
|
|
1071
|
+
("rr", "r"), # trill
|
|
1072
|
+
("r", "ɾ"), # tap
|
|
1073
|
+
("L", "ʎ"), ("Z", "ʎ"), ("jj", "ʎ"), # all three collapse to ʎ
|
|
1074
|
+
("B", "β"), ("D", "ð"), ("G", "ɣ"), ("J", "ɲ"), ("N", "ŋ"),
|
|
1075
|
+
("S", "ʃ"), ("T", "θ"), ("E", "ɛ"), ("O", "ɔ"), ("x", "x"), ("X", "x"),
|
|
1076
|
+
("karro", "karo"),
|
|
1077
|
+
])
|
|
1078
|
+
def test_cotovia_to_ipa(cv, ipa):
|
|
1079
|
+
assert cotovia_to_ipa(cv) == ipa
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
@pytest.mark.parametrize("ipa, cv", [
|
|
1083
|
+
("tʃ", "tS"),
|
|
1084
|
+
("r", "rr"), # trill
|
|
1085
|
+
("ɾ", "r"), # tap
|
|
1086
|
+
("ʎ", "L"), # canonical Cotovía palatal lateral
|
|
1087
|
+
("x", "x"),
|
|
1088
|
+
("β", "B"), ("ɲ", "J"), ("ɛ", "E"), ("ɔ", "O"),
|
|
1089
|
+
])
|
|
1090
|
+
def test_ipa_to_cotovia(ipa, cv):
|
|
1091
|
+
assert ipa_to_cotovia(ipa) == cv
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
def test_cotovia_tap_trill_round_trip():
|
|
1095
|
+
# The tap/trill distinction must survive a round-trip.
|
|
1096
|
+
assert ipa_to_cotovia(cotovia_to_ipa("karro")) == "karro" # trill
|
|
1097
|
+
assert ipa_to_cotovia(cotovia_to_ipa("kara")) == "kara" # tap
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
def test_convert_routes_through_cotovia():
|
|
1101
|
+
assert convert("tS", "cotovia", "x-sampa") == "tS"
|
|
1102
|
+
assert convert("CH IY1", "arpa", "cotovia") == "tSi"
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
def test_cotovia_pause_marker_not_a_phoneme():
|
|
1106
|
+
# "#" (silence marker) is excluded from the table and passes through
|
|
1107
|
+
# unchanged, rather than being emitted as a "pau" token.
|
|
1108
|
+
assert cotovia_to_ipa("#") == "#"
|
|
1109
|
+
# p/a/u are ordinary phonemes, converted independently.
|
|
1110
|
+
assert cotovia_to_ipa("pau") == "pau"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|