scriptconv 0.0.3a15__tar.gz → 0.0.3a17__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.
Files changed (80) hide show
  1. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/PKG-INFO +1 -1
  2. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/registry.py +44 -5
  3. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/version.py +1 -1
  4. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv.egg-info/PKG-INFO +1 -1
  5. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_phonemizers_base.py +52 -5
  6. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/LICENSE +0 -0
  7. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/README.md +0 -0
  8. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/pyproject.toml +0 -0
  9. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/requirements.txt +0 -0
  10. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/__init__.py +0 -0
  11. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/__main__.py +0 -0
  12. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/cangjie.py +0 -0
  13. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/conventions.py +0 -0
  14. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/data/__init__.py +0 -0
  15. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/data/cangjie5_tc.tsv.gz +0 -0
  16. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/graph.py +0 -0
  17. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/notation.py +0 -0
  18. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/__init__.py +0 -0
  19. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/__init__.py +0 -0
  20. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/bw2ipa.py +0 -0
  21. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/hangul2ipa.py +0 -0
  22. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/aspiration.csv +0 -0
  23. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/assimilation.csv +0 -0
  24. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/double_coda.csv +0 -0
  25. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/hanja.tsv +0 -0
  26. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/ipa.csv +0 -0
  27. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/neutralization.csv +0 -0
  28. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/tensification.csv +0 -0
  29. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/ko_tables/yale.csv +0 -0
  30. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/__init__.py +0 -0
  31. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/codeswitch.py +0 -0
  32. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/diacritize.py +0 -0
  33. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/dialectal.py +0 -0
  34. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/english_g2p.py +0 -0
  35. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/espeak.py +0 -0
  36. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/frontend.py +0 -0
  37. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/levantine_g2p.py +0 -0
  38. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/normalize.py +0 -0
  39. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/shami/phoneme_inventory.py +0 -0
  40. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/_thirdparty/zh_num.py +0 -0
  41. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/ar.py +0 -0
  42. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/base.py +0 -0
  43. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/en.py +0 -0
  44. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/enums.py +0 -0
  45. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/eu.py +0 -0
  46. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/fa.py +0 -0
  47. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/gl.py +0 -0
  48. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/he.py +0 -0
  49. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/ja.py +0 -0
  50. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/ko.py +0 -0
  51. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/mul.py +0 -0
  52. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/mwl.py +0 -0
  53. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/o2ipa.py +0 -0
  54. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/pt.py +0 -0
  55. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/shami.py +0 -0
  56. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/vi.py +0 -0
  57. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/phonemizers/zh.py +0 -0
  58. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/py.typed +0 -0
  59. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/readings.py +0 -0
  60. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/scripts.py +0 -0
  61. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv/translit.py +0 -0
  62. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv.egg-info/SOURCES.txt +0 -0
  63. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv.egg-info/dependency_links.txt +0 -0
  64. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv.egg-info/requires.txt +0 -0
  65. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/scriptconv.egg-info/top_level.txt +0 -0
  66. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/setup.cfg +0 -0
  67. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_arpa_stress.py +0 -0
  68. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_cangjie.py +0 -0
  69. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_cli.py +0 -0
  70. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_conventions.py +0 -0
  71. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_errors_policy.py +0 -0
  72. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_examples.py +0 -0
  73. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_graph.py +0 -0
  74. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_notation.py +0 -0
  75. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_phonemizers_cjk_ar.py +0 -0
  76. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_readings.py +0 -0
  77. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_readings_zh.py +0 -0
  78. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_scripts.py +0 -0
  79. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_scripts_stressonnx_compat.py +0 -0
  80. {scriptconv-0.0.3a15 → scriptconv-0.0.3a17}/tests/test_translit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scriptconv
3
- Version: 0.0.3a15
3
+ Version: 0.0.3a17
4
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
@@ -112,6 +112,14 @@ def get_phonemizer(phonemizer: Phonemizer,
112
112
  params = inspect.signature(cls.__init__).parameters
113
113
  if "alphabet" in params:
114
114
  kwargs.setdefault("alphabet", alphabet)
115
+ if model is not None:
116
+ # backends name their variant/model selector differently
117
+ # (AhoTTS: engine=, arbtok: register=, ...) — forward to whichever
118
+ # parameter the constructor declares
119
+ for name in ("model", "engine", "register"):
120
+ if name in params:
121
+ kwargs.setdefault(name, model)
122
+ break
115
123
  inst = cls(**kwargs)
116
124
  if normalizer is not None:
117
125
  inst.normalizer = normalizer
@@ -133,30 +141,61 @@ _EMITS: Dict[Phonemizer, Tuple[Alphabet, ...]] = {
133
141
  }
134
142
 
135
143
  LANG_DEFAULTS: Dict[str, Tuple[Phonemizer, ...]] = {
136
- # Arabic IPA always goes through arbtok (hard org rule)
144
+ # Arabic IPA always goes through arbtok (hard org rule — never falls
145
+ # through to orthography2ipa or espeak)
137
146
  "ar": (_P.ARBTOK,),
138
147
  "eu": (_P.EUSKAPHONE,),
139
148
  "mwl": (_P.MIRANDESE,),
140
149
  "pt": (_P.TUGAPHONE,),
141
150
  "he": (_P.PHONIKUD,),
142
- "gl": (_P.COTOVIA, _P.ESPEAK),
151
+ "gl": (_P.COTOVIA, _P.ORTHOGRAPHY2IPA, _P.ESPEAK),
143
152
  }
144
153
 
154
+ # Languages whose explicit entry is exhaustive: no generic fallback beyond it.
155
+ _NO_GENERIC_FALLBACK = {"ar"}
156
+
157
+
158
+ def _o2i_supports(lang: str) -> bool:
159
+ """True when orthography2ipa is installed and has a spec for *lang*."""
160
+ try:
161
+ from scriptconv.phonemizers.o2ipa import Orthography2IPAPhonemizer
162
+ Orthography2IPAPhonemizer.get_lang(lang)
163
+ return True
164
+ except (ImportError, ValueError):
165
+ return False
166
+
145
167
 
146
168
  def phonemizer_for_lang(lang: str, alphabet: Alphabet = Alphabet.IPA,
147
169
  override: Optional[Phonemizer] = None,
148
170
  model: Optional[str] = None, **kwargs):
149
171
  """Construct the default phonemizer for *lang* (or the override).
150
172
 
151
- Candidates from :data:`LANG_DEFAULTS` are filtered by the alphabet they
152
- can emit; espeak is the universal fallback.
173
+ Resolution order in-house engines first:
174
+
175
+ 1. ``override=`` when given;
176
+ 2. the language's explicit :data:`LANG_DEFAULTS` chain, filtered by the
177
+ alphabet each candidate can emit;
178
+ 3. :data:`~Phonemizer.ORTHOGRAPHY2IPA` when orthography2ipa supports the
179
+ language (the usual default);
180
+ 4. espeak as the last resort.
181
+
182
+ Languages in the no-fallback set (Arabic) never leave their explicit
183
+ chain — a missing arbtok raises rather than silently degrading.
153
184
  """
154
185
  if override is not None:
155
186
  return get_phonemizer(override, alphabet, model, **kwargs)
156
187
  key = lang.replace("_", "-").split("-")[0].lower()
157
- for candidate in LANG_DEFAULTS.get(key, ()):
188
+ explicit = LANG_DEFAULTS.get(key, ())
189
+ for candidate in explicit:
158
190
  if alphabet in _EMITS.get(candidate, (Alphabet.IPA,)):
159
191
  return get_phonemizer(candidate, alphabet, model, **kwargs)
192
+ if key in _NO_GENERIC_FALLBACK:
193
+ raise ValueError(
194
+ f"no eligible phonemizer for {lang!r} with alphabet "
195
+ f"{alphabet.value!r}: the explicit chain "
196
+ f"{[c.value for c in explicit]} is exhaustive for this language")
197
+ if alphabet == Alphabet.IPA and _o2i_supports(lang):
198
+ return get_phonemizer(_P.ORTHOGRAPHY2IPA, alphabet, model, **kwargs)
160
199
  return get_phonemizer(_P.ESPEAK, alphabet, model, **kwargs)
161
200
 
162
201
 
@@ -2,7 +2,7 @@
2
2
  VERSION_MAJOR = 0
3
3
  VERSION_MINOR = 0
4
4
  VERSION_BUILD = 3
5
- VERSION_ALPHA = 15
5
+ VERSION_ALPHA = 17
6
6
  # END_VERSION_BLOCK
7
7
 
8
8
  VERSION_STR = f"{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_BUILD}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scriptconv
3
- Version: 0.0.3a15
3
+ Version: 0.0.3a17
4
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
@@ -96,12 +96,34 @@ class TestLangDefaults(unittest.TestCase):
96
96
  self.assertEqual(LANG_DEFAULTS["ar"], (Phonemizer.ARBTOK,))
97
97
 
98
98
  def test_cotovia_only_for_cotovia_alphabet(self):
99
+ # requesting IPA must never yield Cotovía (it emits its own notation);
100
+ # the in-house chain falls through to orthography2ipa (or espeak)
99
101
  gl_ipa = phonemizer_for_lang("gl", alphabet=Alphabet.IPA)
100
- self.assertEqual(type(gl_ipa).__name__, "EspeakPhonemizer")
101
-
102
- def test_fallback_is_espeak(self):
103
- de = phonemizer_for_lang("de-DE")
104
- self.assertEqual(type(de).__name__, "EspeakPhonemizer")
102
+ self.assertIn(type(gl_ipa).__name__,
103
+ ("Orthography2IPAPhonemizer", "EspeakPhonemizer"))
104
+ self.assertNotEqual(type(gl_ipa).__name__, "CotoviaPhonemizer")
105
+ gl_ctv = phonemizer_for_lang("gl", alphabet=Alphabet.COTOVIA)
106
+ self.assertEqual(type(gl_ctv).__name__, "CotoviaPhonemizer")
107
+
108
+ def test_fallback_prefers_o2i_then_espeak(self):
109
+ # in-house first: orthography2ipa is the usual default when it has a
110
+ # spec for the language; espeak only as last resort
111
+ from unittest import mock
112
+ import scriptconv.phonemizers.registry as reg
113
+ with mock.patch.object(reg, "_o2i_supports", return_value=True):
114
+ with mock.patch.object(reg, "get_phonemizer") as gp:
115
+ reg.phonemizer_for_lang("de-DE")
116
+ self.assertEqual(gp.call_args[0][0], Phonemizer.ORTHOGRAPHY2IPA)
117
+ with mock.patch.object(reg, "_o2i_supports", return_value=False):
118
+ de = reg.phonemizer_for_lang("de-DE")
119
+ self.assertEqual(type(de).__name__, "EspeakPhonemizer")
120
+
121
+ def test_arabic_never_falls_through(self):
122
+ # hard org rule: Arabic IPA only via arbtok — with arbtok ineligible
123
+ # (wrong alphabet), the resolver raises instead of degrading to
124
+ # o2i/espeak
125
+ with self.assertRaises((ValueError, ImportError)):
126
+ phonemizer_for_lang("ar", alphabet=Alphabet.ARPA)
105
127
 
106
128
  def test_override_wins(self):
107
129
  g = phonemizer_for_lang("de", override=Phonemizer.GRAPHEMES)
@@ -174,3 +196,28 @@ class TestPhonikudModelResolver(unittest.TestCase):
174
196
  with self.assertRaises(ValueError):
175
197
  g.add_diacritics("שלום", "he")
176
198
  self.assertEqual(calls, [1])
199
+
200
+
201
+ class TestModelForwarding(unittest.TestCase):
202
+ def test_model_forwards_to_variant_param(self):
203
+ from unittest import mock
204
+ import scriptconv.phonemizers.registry as reg
205
+
206
+ seen = {}
207
+
208
+ class FakeEngineBackend(BasePhonemizer):
209
+ def __init__(self, engine=None, alphabet=Alphabet.IPA):
210
+ seen["engine"] = engine
211
+ super().__init__(alphabet)
212
+
213
+ def phonemize_string(self, text, lang):
214
+ return text
215
+
216
+ with mock.patch.object(reg, "get_phonemizer_class",
217
+ return_value=FakeEngineBackend):
218
+ reg.get_phonemizer(Phonemizer.AHOTTS, model="classic")
219
+ self.assertEqual(seen["engine"], "classic")
220
+
221
+ def test_model_none_forwards_nothing(self):
222
+ g = get_phonemizer(Phonemizer.GRAPHEMES, model=None)
223
+ self.assertIsInstance(g, GraphemePhonemizer)
File without changes
File without changes
File without changes