scriptconv 0.0.2a1__tar.gz → 0.0.3a1__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.2a1 → scriptconv-0.0.3a1}/PKG-INFO +27 -11
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/README.md +24 -8
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/pyproject.toml +6 -2
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv/__init__.py +4 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv/notation.py +130 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv/version.py +1 -1
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv.egg-info/PKG-INFO +27 -11
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/tests/test_examples.py +6 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/tests/test_notation.py +41 -1
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/LICENSE +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/requirements.txt +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv/__main__.py +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv/py.typed +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv/scripts.py +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv/translit.py +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv.egg-info/SOURCES.txt +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv.egg-info/dependency_links.txt +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv.egg-info/requires.txt +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/scriptconv.egg-info/top_level.txt +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/setup.cfg +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/tests/test_cli.py +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/tests/test_scripts.py +0 -0
- {scriptconv-0.0.2a1 → scriptconv-0.0.3a1}/tests/test_translit.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scriptconv
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.0.3a1
|
|
4
|
+
Summary: Zero-dependency script & phoneme-notation core — ISO-15924 detection & metadata, IPA↔ARPABET/X-SAMPA/Lexique/Kirshenbaum/Cotovía/RFE, Buckwalter↔Arabic, Hangul→jamo, kana
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/TigreGotico/scriptconv
|
|
7
7
|
Project-URL: Issues, https://github.com/TigreGotico/scriptconv/issues
|
|
8
|
-
Keywords: ipa,arpabet,x-sampa,lexique,buckwalter,hangul,script,iso15924,tts,g2p
|
|
8
|
+
Keywords: ipa,arpabet,x-sampa,kirshenbaum,cotovia,rfe,lexique,buckwalter,hangul,jamo,kana,transliteration,notation,phoneme,phonetic-alphabet,script,iso15924,unicode,tts,g2p
|
|
9
9
|
Classifier: Development Status :: 3 - Alpha
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -31,12 +31,21 @@ Dynamic: license-file
|
|
|
31
31
|
[](https://github.com/TigreGotico/scriptconv/actions/workflows/build-tests.yml)
|
|
32
32
|
[](https://pypi.org/project/scriptconv/)
|
|
33
33
|
|
|
34
|
-
**scriptconv** is a zero-dependency Python library for written-script
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
**scriptconv** is a zero-dependency Python library for written-script and
|
|
35
|
+
phoneme-notation operations:
|
|
36
|
+
|
|
37
|
+
- **Script identification & metadata** — ISO-15924 detection, character-range
|
|
38
|
+
lookup, typological `script_type`, base direction, mixed-script segmentation
|
|
39
|
+
(`script_runs`), and language ↔ script mapping.
|
|
40
|
+
- **Phoneme-notation transcoding** — IPA ↔ ARPABET, X-SAMPA, Lexique,
|
|
41
|
+
Kirshenbaum, Cotovía and RFE, routed through IPA, with queryable per-notation
|
|
42
|
+
fidelity metadata (`NOTATION_INFO`) and a `looks_like_ipa` detector.
|
|
43
|
+
- **Script transliteration & decomposition** — Buckwalter ↔ Arabic script,
|
|
44
|
+
Hangul → jamo (compatibility or conjoining), Hiragana ↔ Katakana.
|
|
45
|
+
|
|
46
|
+
Every conversion is a pure data table or arithmetic operation — **no
|
|
47
|
+
phonemization**, no linguistic rules, no external files, and no runtime
|
|
48
|
+
dependencies beyond the Python standard library.
|
|
40
49
|
|
|
41
50
|
Transcoding is reversible where the target inventory permits — see
|
|
42
51
|
[Fidelity guarantees](#fidelity-guarantees) for the exact per-notation guarantees.
|
|
@@ -75,7 +84,8 @@ from scriptconv import (
|
|
|
75
84
|
xsampa_to_ipa, ipa_to_xsampa,
|
|
76
85
|
buckwalter_to_arabic, arabic_to_buckwalter,
|
|
77
86
|
lexique_to_ipa, ipa_to_lexique,
|
|
78
|
-
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia,
|
|
87
|
+
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia,
|
|
88
|
+
rfe_to_ipa, ipa_to_rfe, looks_like_ipa,
|
|
79
89
|
decompose_hangul, hira_to_kana, kana_to_hira,
|
|
80
90
|
convert, can_convert, convert_batch, Notation, NOTATION_INFO,
|
|
81
91
|
)
|
|
@@ -110,6 +120,9 @@ ipa_to_kirshenbaum("ŋ") # "N"
|
|
|
110
120
|
cotovia_to_ipa("karro") # "karo" (Galician Cotovía TTS notation)
|
|
111
121
|
ipa_to_cotovia("ʎ") # "L"
|
|
112
122
|
|
|
123
|
+
rfe_to_ipa("kaša") # "kaʃa" (Spanish/Romance RFE alphabet)
|
|
124
|
+
ipa_to_rfe("ɲ") # "ñ"
|
|
125
|
+
|
|
113
126
|
looks_like_ipa("pʰɑtʃ") # True (heuristic: has IPA-distinctive symbols)
|
|
114
127
|
looks_like_ipa("hello") # False
|
|
115
128
|
|
|
@@ -142,7 +155,7 @@ python -m scriptconv lang ko
|
|
|
142
155
|
| Module | Contents |
|
|
143
156
|
|--------|----------|
|
|
144
157
|
| `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` |
|
|
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 |
|
|
158
|
+
| `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, RFE ↔ IPA), `looks_like_ipa` detector |
|
|
146
159
|
| `scriptconv.translit` | `decompose_hangul` (Hangul blocks → jamo, compatibility or conjoining), `hira_to_kana`/`kana_to_hira` — all orthographic only |
|
|
147
160
|
|
|
148
161
|
## Documentation
|
|
@@ -172,6 +185,7 @@ Runnable scripts in [examples/](examples/):
|
|
|
172
185
|
| `13_script_runs.py` | Per-script segmentation of mixed-script text |
|
|
173
186
|
| `14_kana_transliteration.py` | Hiragana ↔ Katakana |
|
|
174
187
|
| `15_cotovia.py` | Cotovía (Galician TTS notation) ↔ IPA |
|
|
188
|
+
| `16_rfe.py` | RFE (Spanish/Romance philology alphabet) ↔ IPA |
|
|
175
189
|
|
|
176
190
|
## Fidelity guarantees
|
|
177
191
|
|
|
@@ -187,6 +201,7 @@ round-trip is exact and what happens to a symbol the table does not know.
|
|
|
187
201
|
| **Lexique ↔ IPA** | Exact except the `°`/`3` schwa pair (both → `ə`; reverse always → `°`) | Exact | Passed through unchanged |
|
|
188
202
|
| **Kirshenbaum ↔ IPA** | Exact | **Lossy** — restricted ASCII inventory; IPA outside it passes through | Passed through unchanged |
|
|
189
203
|
| **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 |
|
|
204
|
+
| **RFE ↔ IPA** | Exact except `ñ`/`n̮` for `ɲ` normalise to `ñ` | **Lossy** — core Spanish/Romance inventory; IPA outside it passes through | Passed through unchanged |
|
|
190
205
|
|
|
191
206
|
This table is also available programmatically via `NOTATION_INFO`
|
|
192
207
|
(`NotationInfo` records with `lossless_to_ipa`, `lossless_from_ipa`,
|
|
@@ -213,4 +228,5 @@ Derived tables used internally:
|
|
|
213
228
|
| 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 |
|
|
214
229
|
| Kirshenbaum ↔ IPA | Kirshenbaum 1993 ASCII-IPA standard (comp.speech), cross-checked against espeak-ng | — (factual symbol mapping) |
|
|
215
230
|
| Cotovía ↔ IPA | Universidade de Vigo GTM Cotovía TTS project (`fonemas.cpp`) | — (factual symbol mapping) |
|
|
231
|
+
| RFE ↔ IPA | RFE phonetic alphabet (Revista de Filología Española, 1915) | — (factual symbol mapping) |
|
|
216
232
|
| Hangul jamo tables | [stannam/hangul_to_ipa](https://github.com/stannam/hangul_to_ipa) | — |
|
|
@@ -4,12 +4,21 @@
|
|
|
4
4
|
[](https://github.com/TigreGotico/scriptconv/actions/workflows/build-tests.yml)
|
|
5
5
|
[](https://pypi.org/project/scriptconv/)
|
|
6
6
|
|
|
7
|
-
**scriptconv** is a zero-dependency Python library for written-script
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
**scriptconv** is a zero-dependency Python library for written-script and
|
|
8
|
+
phoneme-notation operations:
|
|
9
|
+
|
|
10
|
+
- **Script identification & metadata** — ISO-15924 detection, character-range
|
|
11
|
+
lookup, typological `script_type`, base direction, mixed-script segmentation
|
|
12
|
+
(`script_runs`), and language ↔ script mapping.
|
|
13
|
+
- **Phoneme-notation transcoding** — IPA ↔ ARPABET, X-SAMPA, Lexique,
|
|
14
|
+
Kirshenbaum, Cotovía and RFE, routed through IPA, with queryable per-notation
|
|
15
|
+
fidelity metadata (`NOTATION_INFO`) and a `looks_like_ipa` detector.
|
|
16
|
+
- **Script transliteration & decomposition** — Buckwalter ↔ Arabic script,
|
|
17
|
+
Hangul → jamo (compatibility or conjoining), Hiragana ↔ Katakana.
|
|
18
|
+
|
|
19
|
+
Every conversion is a pure data table or arithmetic operation — **no
|
|
20
|
+
phonemization**, no linguistic rules, no external files, and no runtime
|
|
21
|
+
dependencies beyond the Python standard library.
|
|
13
22
|
|
|
14
23
|
Transcoding is reversible where the target inventory permits — see
|
|
15
24
|
[Fidelity guarantees](#fidelity-guarantees) for the exact per-notation guarantees.
|
|
@@ -48,7 +57,8 @@ from scriptconv import (
|
|
|
48
57
|
xsampa_to_ipa, ipa_to_xsampa,
|
|
49
58
|
buckwalter_to_arabic, arabic_to_buckwalter,
|
|
50
59
|
lexique_to_ipa, ipa_to_lexique,
|
|
51
|
-
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia,
|
|
60
|
+
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia,
|
|
61
|
+
rfe_to_ipa, ipa_to_rfe, looks_like_ipa,
|
|
52
62
|
decompose_hangul, hira_to_kana, kana_to_hira,
|
|
53
63
|
convert, can_convert, convert_batch, Notation, NOTATION_INFO,
|
|
54
64
|
)
|
|
@@ -83,6 +93,9 @@ ipa_to_kirshenbaum("ŋ") # "N"
|
|
|
83
93
|
cotovia_to_ipa("karro") # "karo" (Galician Cotovía TTS notation)
|
|
84
94
|
ipa_to_cotovia("ʎ") # "L"
|
|
85
95
|
|
|
96
|
+
rfe_to_ipa("kaša") # "kaʃa" (Spanish/Romance RFE alphabet)
|
|
97
|
+
ipa_to_rfe("ɲ") # "ñ"
|
|
98
|
+
|
|
86
99
|
looks_like_ipa("pʰɑtʃ") # True (heuristic: has IPA-distinctive symbols)
|
|
87
100
|
looks_like_ipa("hello") # False
|
|
88
101
|
|
|
@@ -115,7 +128,7 @@ python -m scriptconv lang ko
|
|
|
115
128
|
| Module | Contents |
|
|
116
129
|
|--------|----------|
|
|
117
130
|
| `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` |
|
|
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 |
|
|
131
|
+
| `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, RFE ↔ IPA), `looks_like_ipa` detector |
|
|
119
132
|
| `scriptconv.translit` | `decompose_hangul` (Hangul blocks → jamo, compatibility or conjoining), `hira_to_kana`/`kana_to_hira` — all orthographic only |
|
|
120
133
|
|
|
121
134
|
## Documentation
|
|
@@ -145,6 +158,7 @@ Runnable scripts in [examples/](examples/):
|
|
|
145
158
|
| `13_script_runs.py` | Per-script segmentation of mixed-script text |
|
|
146
159
|
| `14_kana_transliteration.py` | Hiragana ↔ Katakana |
|
|
147
160
|
| `15_cotovia.py` | Cotovía (Galician TTS notation) ↔ IPA |
|
|
161
|
+
| `16_rfe.py` | RFE (Spanish/Romance philology alphabet) ↔ IPA |
|
|
148
162
|
|
|
149
163
|
## Fidelity guarantees
|
|
150
164
|
|
|
@@ -160,6 +174,7 @@ round-trip is exact and what happens to a symbol the table does not know.
|
|
|
160
174
|
| **Lexique ↔ IPA** | Exact except the `°`/`3` schwa pair (both → `ə`; reverse always → `°`) | Exact | Passed through unchanged |
|
|
161
175
|
| **Kirshenbaum ↔ IPA** | Exact | **Lossy** — restricted ASCII inventory; IPA outside it passes through | Passed through unchanged |
|
|
162
176
|
| **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 |
|
|
177
|
+
| **RFE ↔ IPA** | Exact except `ñ`/`n̮` for `ɲ` normalise to `ñ` | **Lossy** — core Spanish/Romance inventory; IPA outside it passes through | Passed through unchanged |
|
|
163
178
|
|
|
164
179
|
This table is also available programmatically via `NOTATION_INFO`
|
|
165
180
|
(`NotationInfo` records with `lossless_to_ipa`, `lossless_from_ipa`,
|
|
@@ -186,4 +201,5 @@ Derived tables used internally:
|
|
|
186
201
|
| 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 |
|
|
187
202
|
| Kirshenbaum ↔ IPA | Kirshenbaum 1993 ASCII-IPA standard (comp.speech), cross-checked against espeak-ng | — (factual symbol mapping) |
|
|
188
203
|
| Cotovía ↔ IPA | Universidade de Vigo GTM Cotovía TTS project (`fonemas.cpp`) | — (factual symbol mapping) |
|
|
204
|
+
| RFE ↔ IPA | RFE phonetic alphabet (Revista de Filología Española, 1915) | — (factual symbol mapping) |
|
|
189
205
|
| Hangul jamo tables | [stannam/hangul_to_ipa](https://github.com/stannam/hangul_to_ipa) | — |
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scriptconv"
|
|
7
7
|
dynamic = ["version", "dependencies"]
|
|
8
|
-
description = "
|
|
8
|
+
description = "Zero-dependency script & phoneme-notation core — ISO-15924 detection & metadata, IPA↔ARPABET/X-SAMPA/Lexique/Kirshenbaum/Cotovía/RFE, Buckwalter↔Arabic, Hangul→jamo, kana"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -22,7 +22,11 @@ classifiers = [
|
|
|
22
22
|
"License :: OSI Approved :: Apache Software License",
|
|
23
23
|
"Operating System :: OS Independent",
|
|
24
24
|
]
|
|
25
|
-
keywords = [
|
|
25
|
+
keywords = [
|
|
26
|
+
"ipa", "arpabet", "x-sampa", "kirshenbaum", "cotovia", "rfe", "lexique",
|
|
27
|
+
"buckwalter", "hangul", "jamo", "kana", "transliteration", "notation",
|
|
28
|
+
"phoneme", "phonetic-alphabet", "script", "iso15924", "unicode", "tts", "g2p",
|
|
29
|
+
]
|
|
26
30
|
|
|
27
31
|
[tool.setuptools.dynamic]
|
|
28
32
|
version = {attr = "scriptconv.version.VERSION_STR"}
|
|
@@ -52,6 +52,8 @@ from scriptconv.notation import (
|
|
|
52
52
|
ipa_to_kirshenbaum,
|
|
53
53
|
cotovia_to_ipa,
|
|
54
54
|
ipa_to_cotovia,
|
|
55
|
+
rfe_to_ipa,
|
|
56
|
+
ipa_to_rfe,
|
|
55
57
|
looks_like_ipa,
|
|
56
58
|
)
|
|
57
59
|
from scriptconv.translit import (
|
|
@@ -91,6 +93,8 @@ __all__ = [
|
|
|
91
93
|
"ipa_to_kirshenbaum",
|
|
92
94
|
"cotovia_to_ipa",
|
|
93
95
|
"ipa_to_cotovia",
|
|
96
|
+
"rfe_to_ipa",
|
|
97
|
+
"ipa_to_rfe",
|
|
94
98
|
"looks_like_ipa",
|
|
95
99
|
# translit
|
|
96
100
|
"decompose_hangul",
|
|
@@ -39,6 +39,8 @@ __all__ = [
|
|
|
39
39
|
"ipa_to_kirshenbaum",
|
|
40
40
|
"cotovia_to_ipa",
|
|
41
41
|
"ipa_to_cotovia",
|
|
42
|
+
"rfe_to_ipa",
|
|
43
|
+
"ipa_to_rfe",
|
|
42
44
|
"looks_like_ipa",
|
|
43
45
|
]
|
|
44
46
|
|
|
@@ -54,6 +56,7 @@ class Notation(str, Enum):
|
|
|
54
56
|
LEXIQUE = "lexique" # Lexique one-char-per-phoneme French notation
|
|
55
57
|
KIRSHENBAUM = "kirshenbaum" # ASCII-IPA (espeak-ng native notation)
|
|
56
58
|
COTOVIA = "cotovia" # Universidade de Vigo Cotovía TTS notation (gl)
|
|
59
|
+
RFE = "rfe" # Revista de Filología Española phonetic alphabet
|
|
57
60
|
|
|
58
61
|
def __repr__(self) -> str:
|
|
59
62
|
return f"Notation.{self.name}"
|
|
@@ -786,6 +789,126 @@ def ipa_to_cotovia(ipa: str) -> str:
|
|
|
786
789
|
return "".join(result)
|
|
787
790
|
|
|
788
791
|
|
|
792
|
+
# ---------------------------------------------------------------------------
|
|
793
|
+
# RFE (Revista de Filología Española) ↔ IPA
|
|
794
|
+
#
|
|
795
|
+
# The RFE phonetic alphabet (Navarro Tomás, Revista de Filología Española,
|
|
796
|
+
# 1915) is the traditional transcription system of Spanish and Romance
|
|
797
|
+
# philology. This is its core, well-attested inventory; rare interdental and
|
|
798
|
+
# variant diacritic symbols from the full standard are omitted. Symbols are
|
|
799
|
+
# matched longest-first (combining-mark symbols before their base letters).
|
|
800
|
+
# Reference: RFE Phonetic Alphabet
|
|
801
|
+
# (https://en.wikipedia.org/wiki/RFE_Phonetic_Alphabet).
|
|
802
|
+
# ---------------------------------------------------------------------------
|
|
803
|
+
|
|
804
|
+
_RFE_TO_IPA: dict[str, str] = {
|
|
805
|
+
# Combining-mark symbols (longest-match first)
|
|
806
|
+
"r̄": "r", # r + macron = alveolar trill (plain r = tap ɾ)
|
|
807
|
+
"n̮": "ɲ", # n + breve below = palatal nasal ɲ
|
|
808
|
+
"l̮": "ʎ", # l + breve below = palatal lateral ʎ
|
|
809
|
+
# Palatal / postalveolar
|
|
810
|
+
"ĉ": "tʃ", # ĉ = tʃ
|
|
811
|
+
"š": "ʃ", # š = ʃ
|
|
812
|
+
"ž": "ʒ", # ž = ʒ
|
|
813
|
+
"ŷ": "ɟʝ", # ŷ = ɟʝ (voiced palatal affricate)
|
|
814
|
+
"ñ": "ɲ", # ñ = ɲ
|
|
815
|
+
"y": "ʝ", # y = ʝ
|
|
816
|
+
"j": "j", # j = j
|
|
817
|
+
# Spanish approximant/fricative allophones
|
|
818
|
+
"ƀ": "β", # ƀ = β
|
|
819
|
+
"đ": "ð", # đ = ð
|
|
820
|
+
"ǥ": "ɣ", # ǥ = ɣ
|
|
821
|
+
# Other consonants
|
|
822
|
+
"θ": "θ", # θ = θ
|
|
823
|
+
"x": "x",
|
|
824
|
+
"ł": "ɫ", # ł = ɫ (velarized l)
|
|
825
|
+
"ŋ": "ŋ", # ŋ = ŋ
|
|
826
|
+
"w": "w",
|
|
827
|
+
"h": "h",
|
|
828
|
+
"b": "b",
|
|
829
|
+
"p": "p",
|
|
830
|
+
"t": "t",
|
|
831
|
+
"d": "d",
|
|
832
|
+
"k": "k",
|
|
833
|
+
"g": "ɡ", # g = ɡ (script g, matching the other tables)
|
|
834
|
+
"f": "f",
|
|
835
|
+
"v": "v",
|
|
836
|
+
"s": "s",
|
|
837
|
+
"z": "z",
|
|
838
|
+
"m": "m",
|
|
839
|
+
"n": "n",
|
|
840
|
+
"l": "l",
|
|
841
|
+
"r": "ɾ", # r = tap ɾ
|
|
842
|
+
# Vowels
|
|
843
|
+
"a": "a", "e": "e", "i": "i", "o": "o", "u": "u",
|
|
844
|
+
"ə": "ə", # ə = ə
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
# Reverse: IPA → RFE. First-wins deduplicates; pin the canonical RFE spellings
|
|
848
|
+
# for the palatal nasal (ñ) and the trill/tap pair.
|
|
849
|
+
_IPA_TO_RFE: dict[str, str] = {}
|
|
850
|
+
for _rfe, _ip in _RFE_TO_IPA.items():
|
|
851
|
+
_IPA_TO_RFE.setdefault(_ip, _rfe)
|
|
852
|
+
_IPA_TO_RFE["ɲ"] = "ñ" # ɲ → ñ (canonical, not the n̮ variant)
|
|
853
|
+
|
|
854
|
+
_RFE_KEYS_SORTED = sorted(_RFE_TO_IPA.keys(), key=len, reverse=True)
|
|
855
|
+
_RFE_RE = re.compile("|".join(re.escape(x) for x in _RFE_KEYS_SORTED))
|
|
856
|
+
_IPA_RFE_KEYS_SORTED = sorted(_IPA_TO_RFE.keys(), key=len, reverse=True)
|
|
857
|
+
_IPA_RFE_RE = re.compile("|".join(re.escape(x) for x in _IPA_RFE_KEYS_SORTED))
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
def rfe_to_ipa(rfe: str) -> str:
|
|
861
|
+
"""Convert an RFE (Revista de Filología Española) string to IPA.
|
|
862
|
+
|
|
863
|
+
Multi-character symbols are matched longest-first. Characters outside the
|
|
864
|
+
table pass through unchanged.
|
|
865
|
+
|
|
866
|
+
Examples
|
|
867
|
+
--------
|
|
868
|
+
>>> rfe_to_ipa("š")
|
|
869
|
+
'ʃ'
|
|
870
|
+
>>> rfe_to_ipa("kaša")
|
|
871
|
+
'kaʃa'
|
|
872
|
+
"""
|
|
873
|
+
result = []
|
|
874
|
+
pos = 0
|
|
875
|
+
while pos < len(rfe):
|
|
876
|
+
m = _RFE_RE.match(rfe, pos)
|
|
877
|
+
if m:
|
|
878
|
+
result.append(_RFE_TO_IPA[m.group(0)])
|
|
879
|
+
pos = m.end()
|
|
880
|
+
else:
|
|
881
|
+
result.append(rfe[pos])
|
|
882
|
+
pos += 1
|
|
883
|
+
return "".join(result)
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
def ipa_to_rfe(ipa: str) -> str:
|
|
887
|
+
"""Convert an IPA string to RFE (Revista de Filología Española) notation.
|
|
888
|
+
|
|
889
|
+
Multi-character IPA symbols are matched longest-first. Characters outside
|
|
890
|
+
the table pass through unchanged.
|
|
891
|
+
|
|
892
|
+
Examples
|
|
893
|
+
--------
|
|
894
|
+
>>> ipa_to_rfe("ʃ")
|
|
895
|
+
'š'
|
|
896
|
+
>>> ipa_to_rfe("ɲ")
|
|
897
|
+
'ñ'
|
|
898
|
+
"""
|
|
899
|
+
result = []
|
|
900
|
+
pos = 0
|
|
901
|
+
while pos < len(ipa):
|
|
902
|
+
m = _IPA_RFE_RE.match(ipa, pos)
|
|
903
|
+
if m:
|
|
904
|
+
result.append(_IPA_TO_RFE[m.group(0)])
|
|
905
|
+
pos = m.end()
|
|
906
|
+
else:
|
|
907
|
+
result.append(ipa[pos])
|
|
908
|
+
pos += 1
|
|
909
|
+
return "".join(result)
|
|
910
|
+
|
|
911
|
+
|
|
789
912
|
# ---------------------------------------------------------------------------
|
|
790
913
|
# convert — facade routing through IPA where no direct map exists
|
|
791
914
|
# ---------------------------------------------------------------------------
|
|
@@ -857,6 +980,7 @@ _TO_IPA: dict[Notation, "callable"] = {
|
|
|
857
980
|
Notation.LEXIQUE: lexique_to_ipa,
|
|
858
981
|
Notation.KIRSHENBAUM: kirshenbaum_to_ipa,
|
|
859
982
|
Notation.COTOVIA: cotovia_to_ipa,
|
|
983
|
+
Notation.RFE: rfe_to_ipa,
|
|
860
984
|
}
|
|
861
985
|
_FROM_IPA: dict[Notation, "callable"] = {
|
|
862
986
|
Notation.ARPA: ipa_to_arpa,
|
|
@@ -864,6 +988,7 @@ _FROM_IPA: dict[Notation, "callable"] = {
|
|
|
864
988
|
Notation.LEXIQUE: ipa_to_lexique,
|
|
865
989
|
Notation.KIRSHENBAUM: ipa_to_kirshenbaum,
|
|
866
990
|
Notation.COTOVIA: ipa_to_cotovia,
|
|
991
|
+
Notation.RFE: ipa_to_rfe,
|
|
867
992
|
}
|
|
868
993
|
_DIRECT_PAIRS: dict[tuple[Notation, Notation], "callable"] = {
|
|
869
994
|
(Notation.BUCKWALTER, Notation.ARABIC): buckwalter_to_arabic,
|
|
@@ -974,6 +1099,11 @@ NOTATION_INFO: dict[Notation, NotationInfo] = {
|
|
|
974
1099
|
token_separated=False,
|
|
975
1100
|
reference="Universidade de Vigo GTM Cotovía TTS (fonemas.cpp)",
|
|
976
1101
|
),
|
|
1102
|
+
Notation.RFE: NotationInfo(
|
|
1103
|
+
Notation.RFE, lossless_to_ipa=False, lossless_from_ipa=False,
|
|
1104
|
+
token_separated=False,
|
|
1105
|
+
reference="RFE phonetic alphabet (Revista de Filología Española, 1915)",
|
|
1106
|
+
),
|
|
977
1107
|
Notation.BUCKWALTER: NotationInfo(
|
|
978
1108
|
Notation.BUCKWALTER, lossless_to_ipa=True, lossless_from_ipa=False,
|
|
979
1109
|
token_separated=False,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scriptconv
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.0.3a1
|
|
4
|
+
Summary: Zero-dependency script & phoneme-notation core — ISO-15924 detection & metadata, IPA↔ARPABET/X-SAMPA/Lexique/Kirshenbaum/Cotovía/RFE, Buckwalter↔Arabic, Hangul→jamo, kana
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/TigreGotico/scriptconv
|
|
7
7
|
Project-URL: Issues, https://github.com/TigreGotico/scriptconv/issues
|
|
8
|
-
Keywords: ipa,arpabet,x-sampa,lexique,buckwalter,hangul,script,iso15924,tts,g2p
|
|
8
|
+
Keywords: ipa,arpabet,x-sampa,kirshenbaum,cotovia,rfe,lexique,buckwalter,hangul,jamo,kana,transliteration,notation,phoneme,phonetic-alphabet,script,iso15924,unicode,tts,g2p
|
|
9
9
|
Classifier: Development Status :: 3 - Alpha
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -31,12 +31,21 @@ Dynamic: license-file
|
|
|
31
31
|
[](https://github.com/TigreGotico/scriptconv/actions/workflows/build-tests.yml)
|
|
32
32
|
[](https://pypi.org/project/scriptconv/)
|
|
33
33
|
|
|
34
|
-
**scriptconv** is a zero-dependency Python library for written-script
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
**scriptconv** is a zero-dependency Python library for written-script and
|
|
35
|
+
phoneme-notation operations:
|
|
36
|
+
|
|
37
|
+
- **Script identification & metadata** — ISO-15924 detection, character-range
|
|
38
|
+
lookup, typological `script_type`, base direction, mixed-script segmentation
|
|
39
|
+
(`script_runs`), and language ↔ script mapping.
|
|
40
|
+
- **Phoneme-notation transcoding** — IPA ↔ ARPABET, X-SAMPA, Lexique,
|
|
41
|
+
Kirshenbaum, Cotovía and RFE, routed through IPA, with queryable per-notation
|
|
42
|
+
fidelity metadata (`NOTATION_INFO`) and a `looks_like_ipa` detector.
|
|
43
|
+
- **Script transliteration & decomposition** — Buckwalter ↔ Arabic script,
|
|
44
|
+
Hangul → jamo (compatibility or conjoining), Hiragana ↔ Katakana.
|
|
45
|
+
|
|
46
|
+
Every conversion is a pure data table or arithmetic operation — **no
|
|
47
|
+
phonemization**, no linguistic rules, no external files, and no runtime
|
|
48
|
+
dependencies beyond the Python standard library.
|
|
40
49
|
|
|
41
50
|
Transcoding is reversible where the target inventory permits — see
|
|
42
51
|
[Fidelity guarantees](#fidelity-guarantees) for the exact per-notation guarantees.
|
|
@@ -75,7 +84,8 @@ from scriptconv import (
|
|
|
75
84
|
xsampa_to_ipa, ipa_to_xsampa,
|
|
76
85
|
buckwalter_to_arabic, arabic_to_buckwalter,
|
|
77
86
|
lexique_to_ipa, ipa_to_lexique,
|
|
78
|
-
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia,
|
|
87
|
+
kirshenbaum_to_ipa, ipa_to_kirshenbaum, cotovia_to_ipa, ipa_to_cotovia,
|
|
88
|
+
rfe_to_ipa, ipa_to_rfe, looks_like_ipa,
|
|
79
89
|
decompose_hangul, hira_to_kana, kana_to_hira,
|
|
80
90
|
convert, can_convert, convert_batch, Notation, NOTATION_INFO,
|
|
81
91
|
)
|
|
@@ -110,6 +120,9 @@ ipa_to_kirshenbaum("ŋ") # "N"
|
|
|
110
120
|
cotovia_to_ipa("karro") # "karo" (Galician Cotovía TTS notation)
|
|
111
121
|
ipa_to_cotovia("ʎ") # "L"
|
|
112
122
|
|
|
123
|
+
rfe_to_ipa("kaša") # "kaʃa" (Spanish/Romance RFE alphabet)
|
|
124
|
+
ipa_to_rfe("ɲ") # "ñ"
|
|
125
|
+
|
|
113
126
|
looks_like_ipa("pʰɑtʃ") # True (heuristic: has IPA-distinctive symbols)
|
|
114
127
|
looks_like_ipa("hello") # False
|
|
115
128
|
|
|
@@ -142,7 +155,7 @@ python -m scriptconv lang ko
|
|
|
142
155
|
| Module | Contents |
|
|
143
156
|
|--------|----------|
|
|
144
157
|
| `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` |
|
|
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 |
|
|
158
|
+
| `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, RFE ↔ IPA), `looks_like_ipa` detector |
|
|
146
159
|
| `scriptconv.translit` | `decompose_hangul` (Hangul blocks → jamo, compatibility or conjoining), `hira_to_kana`/`kana_to_hira` — all orthographic only |
|
|
147
160
|
|
|
148
161
|
## Documentation
|
|
@@ -172,6 +185,7 @@ Runnable scripts in [examples/](examples/):
|
|
|
172
185
|
| `13_script_runs.py` | Per-script segmentation of mixed-script text |
|
|
173
186
|
| `14_kana_transliteration.py` | Hiragana ↔ Katakana |
|
|
174
187
|
| `15_cotovia.py` | Cotovía (Galician TTS notation) ↔ IPA |
|
|
188
|
+
| `16_rfe.py` | RFE (Spanish/Romance philology alphabet) ↔ IPA |
|
|
175
189
|
|
|
176
190
|
## Fidelity guarantees
|
|
177
191
|
|
|
@@ -187,6 +201,7 @@ round-trip is exact and what happens to a symbol the table does not know.
|
|
|
187
201
|
| **Lexique ↔ IPA** | Exact except the `°`/`3` schwa pair (both → `ə`; reverse always → `°`) | Exact | Passed through unchanged |
|
|
188
202
|
| **Kirshenbaum ↔ IPA** | Exact | **Lossy** — restricted ASCII inventory; IPA outside it passes through | Passed through unchanged |
|
|
189
203
|
| **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 |
|
|
204
|
+
| **RFE ↔ IPA** | Exact except `ñ`/`n̮` for `ɲ` normalise to `ñ` | **Lossy** — core Spanish/Romance inventory; IPA outside it passes through | Passed through unchanged |
|
|
190
205
|
|
|
191
206
|
This table is also available programmatically via `NOTATION_INFO`
|
|
192
207
|
(`NotationInfo` records with `lossless_to_ipa`, `lossless_from_ipa`,
|
|
@@ -213,4 +228,5 @@ Derived tables used internally:
|
|
|
213
228
|
| 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 |
|
|
214
229
|
| Kirshenbaum ↔ IPA | Kirshenbaum 1993 ASCII-IPA standard (comp.speech), cross-checked against espeak-ng | — (factual symbol mapping) |
|
|
215
230
|
| Cotovía ↔ IPA | Universidade de Vigo GTM Cotovía TTS project (`fonemas.cpp`) | — (factual symbol mapping) |
|
|
231
|
+
| RFE ↔ IPA | RFE phonetic alphabet (Revista de Filología Española, 1915) | — (factual symbol mapping) |
|
|
216
232
|
| Hangul jamo tables | [stannam/hangul_to_ipa](https://github.com/stannam/hangul_to_ipa) | — |
|
|
@@ -111,3 +111,9 @@ def test_15_cotovia():
|
|
|
111
111
|
r = _run(EXAMPLES_DIR / "15_cotovia.py")
|
|
112
112
|
assert r.returncode == 0, r.stderr
|
|
113
113
|
assert r.stdout.strip()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_16_rfe():
|
|
117
|
+
r = _run(EXAMPLES_DIR / "16_rfe.py")
|
|
118
|
+
assert r.returncode == 0, r.stderr
|
|
119
|
+
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) == 9
|
|
951
951
|
|
|
952
952
|
|
|
953
953
|
def test_notation_str():
|
|
@@ -1108,3 +1108,43 @@ def test_cotovia_pause_marker_not_a_phoneme():
|
|
|
1108
1108
|
assert cotovia_to_ipa("#") == "#"
|
|
1109
1109
|
# p/a/u are ordinary phonemes, converted independently.
|
|
1110
1110
|
assert cotovia_to_ipa("pau") == "pau"
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
# ---------------------------------------------------------------------------
|
|
1114
|
+
# RFE (Revista de Filología Española) ↔ IPA
|
|
1115
|
+
# ---------------------------------------------------------------------------
|
|
1116
|
+
|
|
1117
|
+
from scriptconv.notation import rfe_to_ipa, ipa_to_rfe # noqa: E402
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
@pytest.mark.parametrize("rfe, ipa", [
|
|
1121
|
+
("š", "ʃ"), ("ž", "ʒ"), ("ĉ", "tʃ"), ("y", "ʝ"), ("ŷ", "ɟʝ"),
|
|
1122
|
+
("ñ", "ɲ"), ("n̮", "ɲ"), ("l̮", "ʎ"),
|
|
1123
|
+
("ƀ", "β"), ("đ", "ð"), ("ǥ", "ɣ"), ("θ", "θ"), ("ł", "ɫ"),
|
|
1124
|
+
("r", "ɾ"), ("r̄", "r"),
|
|
1125
|
+
("g", "ɡ"),
|
|
1126
|
+
("kaša", "kaʃa"),
|
|
1127
|
+
])
|
|
1128
|
+
def test_rfe_to_ipa(rfe, ipa):
|
|
1129
|
+
assert rfe_to_ipa(rfe) == ipa
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
@pytest.mark.parametrize("ipa, rfe", [
|
|
1133
|
+
("ʃ", "š"), ("ʒ", "ž"), ("tʃ", "ĉ"), ("ʝ", "y"),
|
|
1134
|
+
("ɲ", "ñ"), # canonical, not the n̮ variant
|
|
1135
|
+
("ʎ", "l̮"),
|
|
1136
|
+
("β", "ƀ"), ("ð", "đ"), ("ɣ", "ǥ"),
|
|
1137
|
+
("ɾ", "r"), ("r", "r̄"),
|
|
1138
|
+
])
|
|
1139
|
+
def test_ipa_to_rfe(ipa, rfe):
|
|
1140
|
+
assert ipa_to_rfe(ipa) == rfe
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
def test_rfe_tap_trill_round_trip():
|
|
1144
|
+
assert ipa_to_rfe(rfe_to_ipa("far̄a")) == "far̄a" # trill
|
|
1145
|
+
assert ipa_to_rfe(rfe_to_ipa("kara")) == "kara" # tap
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
def test_convert_routes_through_rfe():
|
|
1149
|
+
assert convert("š", "rfe", "x-sampa") == "S"
|
|
1150
|
+
assert convert("ʃ", "ipa", "rfe") == "š"
|
|
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
|