scriptconv 0.0.3a3__tar.gz → 0.0.3a5__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 (30) hide show
  1. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/PKG-INFO +1 -1
  2. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/pyproject.toml +1 -0
  3. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv/__init__.py +9 -0
  4. scriptconv-0.0.3a5/scriptconv/cangjie.py +63 -0
  5. scriptconv-0.0.3a5/scriptconv/data/cangjie5_tc.tsv.gz +0 -0
  6. scriptconv-0.0.3a5/scriptconv/py.typed +0 -0
  7. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv/version.py +1 -1
  8. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv.egg-info/PKG-INFO +1 -1
  9. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv.egg-info/SOURCES.txt +4 -0
  10. scriptconv-0.0.3a5/tests/test_cangjie.py +58 -0
  11. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/LICENSE +0 -0
  12. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/README.md +0 -0
  13. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/requirements.txt +0 -0
  14. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv/__main__.py +0 -0
  15. /scriptconv-0.0.3a3/scriptconv/py.typed → /scriptconv-0.0.3a5/scriptconv/data/__init__.py +0 -0
  16. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv/notation.py +0 -0
  17. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv/readings.py +0 -0
  18. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv/scripts.py +0 -0
  19. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv/translit.py +0 -0
  20. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv.egg-info/dependency_links.txt +0 -0
  21. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv.egg-info/requires.txt +0 -0
  22. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/scriptconv.egg-info/top_level.txt +0 -0
  23. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/setup.cfg +0 -0
  24. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/tests/test_cli.py +0 -0
  25. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/tests/test_examples.py +0 -0
  26. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/tests/test_notation.py +0 -0
  27. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/tests/test_readings.py +0 -0
  28. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/tests/test_readings_zh.py +0 -0
  29. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/tests/test_scripts.py +0 -0
  30. {scriptconv-0.0.3a3 → scriptconv-0.0.3a5}/tests/test_translit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scriptconv
3
- Version: 0.0.3a3
3
+ Version: 0.0.3a5
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
@@ -46,6 +46,7 @@ include = ["scriptconv*"]
46
46
 
47
47
  [tool.setuptools.package-data]
48
48
  scriptconv = ["py.typed"]
49
+ "scriptconv.data" = ["*.tsv.gz"]
49
50
 
50
51
  [tool.pytest.ini_options]
51
52
  testpaths = ["tests"]
@@ -20,6 +20,8 @@ translit:
20
20
  readings:
21
21
  Dictionary-backed respelling (Japanese kanji → kana via the ``ja``
22
22
  extra; Chinese hanzi → pinyin/bopomofo via the ``zh`` extra).
23
+ cangjie:
24
+ Hanzi → Cangjie5 input codes (shape decomposition, vendored table).
23
25
 
24
26
  Zero required runtime dependencies (stdlib only); the readings module
25
27
  needs the optional ``ja``/``zh`` extras.
@@ -71,6 +73,10 @@ from scriptconv.readings import (
71
73
  to_pinyin,
72
74
  to_bopomofo,
73
75
  )
76
+ from scriptconv.cangjie import (
77
+ cangjie_code,
78
+ to_cangjie,
79
+ )
74
80
 
75
81
  __all__ = [
76
82
  # scripts
@@ -113,6 +119,9 @@ __all__ = [
113
119
  # readings (dictionary-backed, needs scriptconv[ja])
114
120
  "to_hiragana",
115
121
  "to_katakana",
122
+ # cangjie (vendored Cangjie5 table)
123
+ "cangjie_code",
124
+ "to_cangjie",
116
125
  "to_pinyin",
117
126
  "to_bopomofo",
118
127
  ]
@@ -0,0 +1,63 @@
1
+ """Hanzi → Cangjie input codes (fifth generation, traditional table).
2
+
3
+ Cangjie codes encode a glyph's SHAPE — its decomposition into geometric
4
+ radicals — not its reading: 日 is ``a`` because of what it looks like, however
5
+ it is pronounced. That makes this a deterministic, table-driven orthographic
6
+ transcode like the rest of scriptconv's core: no reading dictionary, no
7
+ ambiguity, no phonology.
8
+
9
+ The table is vendored (gzipped, loaded lazily on first use) from the Cangjie5
10
+ project — https://github.com/Jackchows/Cangjie5, MIT License — so no runtime
11
+ download or extra dependency is needed. Where the upstream table lists
12
+ alternative codes for a glyph, the primary (first) code is kept.
13
+ """
14
+ from __future__ import annotations
15
+
16
+ import gzip
17
+ from importlib.resources import files
18
+ from typing import Dict, Optional
19
+
20
+ __all__ = ["cangjie_code", "to_cangjie"]
21
+
22
+ _TABLE: Optional[Dict[str, str]] = None
23
+
24
+
25
+ def _table() -> Dict[str, str]:
26
+ global _TABLE
27
+ if _TABLE is None:
28
+ _TABLE = {}
29
+ raw = files("scriptconv.data").joinpath("cangjie5_tc.tsv.gz").read_bytes()
30
+ for line in gzip.decompress(raw).decode("utf-8").splitlines():
31
+ if line.startswith("#"):
32
+ continue
33
+ ch, _, code = line.partition("\t")
34
+ _TABLE[ch] = code
35
+ return _TABLE
36
+
37
+
38
+ def cangjie_code(char: str) -> Optional[str]:
39
+ """Return the Cangjie5 code for a single glyph, or None if unmapped."""
40
+ return _table().get(char)
41
+
42
+
43
+ def to_cangjie(text: str, sep: str = " ") -> str:
44
+ """Transcode hanzi in *text* to their Cangjie5 codes.
45
+
46
+ Mapped glyphs become their code, joined by *sep*; runs of unmapped
47
+ characters (Latin, digits, punctuation, rare glyphs) pass through
48
+ unchanged as single tokens.
49
+ """
50
+ table = _table()
51
+ tokens = []
52
+ last_raw = False
53
+ for ch in text:
54
+ code = table.get(ch)
55
+ if code is not None:
56
+ tokens.append(code)
57
+ last_raw = False
58
+ elif last_raw:
59
+ tokens[-1] += ch
60
+ else:
61
+ tokens.append(ch)
62
+ last_raw = True
63
+ return sep.join(tokens)
File without changes
@@ -2,7 +2,7 @@
2
2
  VERSION_MAJOR = 0
3
3
  VERSION_MINOR = 0
4
4
  VERSION_BUILD = 3
5
- VERSION_ALPHA = 3
5
+ VERSION_ALPHA = 5
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.3a3
3
+ Version: 0.0.3a5
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
@@ -4,6 +4,7 @@ pyproject.toml
4
4
  requirements.txt
5
5
  scriptconv/__init__.py
6
6
  scriptconv/__main__.py
7
+ scriptconv/cangjie.py
7
8
  scriptconv/notation.py
8
9
  scriptconv/py.typed
9
10
  scriptconv/readings.py
@@ -15,6 +16,9 @@ scriptconv.egg-info/SOURCES.txt
15
16
  scriptconv.egg-info/dependency_links.txt
16
17
  scriptconv.egg-info/requires.txt
17
18
  scriptconv.egg-info/top_level.txt
19
+ scriptconv/data/__init__.py
20
+ scriptconv/data/cangjie5_tc.tsv.gz
21
+ tests/test_cangjie.py
18
22
  tests/test_cli.py
19
23
  tests/test_examples.py
20
24
  tests/test_notation.py
@@ -0,0 +1,58 @@
1
+ import unittest
2
+
3
+ from scriptconv import cangjie_code, to_cangjie
4
+ from scriptconv import cangjie
5
+
6
+
7
+ class TestCangjieCode(unittest.TestCase):
8
+ def test_official_single_radical_glyphs(self):
9
+ self.assertEqual(cangjie_code("日"), "a")
10
+ self.assertEqual(cangjie_code("木"), "d")
11
+
12
+ def test_multi_radical_glyph(self):
13
+ self.assertEqual(cangjie_code("昌"), "aa")
14
+
15
+ def test_unmapped_returns_none(self):
16
+ self.assertIsNone(cangjie_code("X"))
17
+ self.assertIsNone(cangjie_code("1"))
18
+ self.assertIsNone(cangjie_code(" "))
19
+
20
+ def test_codes_are_lowercase_alpha(self):
21
+ table = cangjie._table()
22
+ self.assertGreater(len(table), 100000)
23
+ sample = list(table.values())[:5000]
24
+ self.assertTrue(all(c.isalpha() and c.islower() for c in sample))
25
+
26
+
27
+ class TestTableIsPackaged(unittest.TestCase):
28
+ def test_data_file_resolvable_via_importlib_resources(self):
29
+ from importlib.resources import files
30
+ raw = files("scriptconv.data").joinpath("cangjie5_tc.tsv.gz").read_bytes()
31
+ self.assertGreater(len(raw), 100000)
32
+
33
+
34
+ class TestToCangjie(unittest.TestCase):
35
+ def test_all_hanzi_sentence(self):
36
+ self.assertEqual(to_cangjie("倉頡"), "oiar grmbc")
37
+
38
+ def test_custom_separator(self):
39
+ self.assertEqual(to_cangjie("倉頡", sep="|"), "oiar|grmbc")
40
+
41
+ def test_unmapped_runs_stay_contiguous(self):
42
+ self.assertEqual(to_cangjie("我有ABC 123!"), "hqi kb ABC 123!")
43
+
44
+ def test_non_chinese_only_passes_through_verbatim(self):
45
+ self.assertEqual(to_cangjie("OVOS 123!"), "OVOS 123!")
46
+
47
+ def test_empty_string(self):
48
+ self.assertEqual(to_cangjie(""), "")
49
+
50
+ def test_table_loaded_once(self):
51
+ to_cangjie("日")
52
+ first = cangjie._TABLE
53
+ cangjie_code("木")
54
+ self.assertIs(cangjie._TABLE, first)
55
+
56
+
57
+ if __name__ == "__main__":
58
+ unittest.main()
File without changes
File without changes
File without changes