words2num2 0.3.0.dev1__tar.gz → 0.3.1__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 (183) hide show
  1. {words2num2-0.3.0.dev1 → words2num2-0.3.1}/PKG-INFO +86 -28
  2. words2num2-0.3.0.dev1/words2num2.egg-info/PKG-INFO → words2num2-0.3.1/README.rst +72 -44
  3. words2num2-0.3.1/pyproject.toml +94 -0
  4. words2num2-0.3.1/rust/Cargo.lock +287 -0
  5. words2num2-0.3.1/rust/Cargo.toml +16 -0
  6. words2num2-0.3.1/rust/words2num2-core/Cargo.toml +18 -0
  7. words2num2-0.3.1/rust/words2num2-core/src/lib.rs +242 -0
  8. words2num2-0.3.1/rust/words2num2-core/src/w2n_formats.rs +1056 -0
  9. words2num2-0.3.1/rust/words2num2-core/src/w2n_lang_en.rs +1011 -0
  10. words2num2-0.3.1/rust/words2num2-core/src/w2n_sentence.rs +2336 -0
  11. words2num2-0.3.1/rust/words2num2-py/Cargo.toml +14 -0
  12. words2num2-0.3.1/rust/words2num2-py/src/lib.rs +312 -0
  13. words2num2-0.3.1/words2num2/__init__.py +140 -0
  14. words2num2-0.3.1/words2num2/_version.py +5 -0
  15. words2num2-0.3.1/words2num2/base.py +19 -0
  16. words2num2-0.3.1/words2num2/converters/auto.py +43 -0
  17. words2num2-0.3.0.dev1/.flake8 +0 -11
  18. words2num2-0.3.0.dev1/.github/workflows/aur-publish.yml +0 -104
  19. words2num2-0.3.0.dev1/.github/workflows/ci.yml +0 -68
  20. words2num2-0.3.0.dev1/.github/workflows/codeql-analysis.yml +0 -38
  21. words2num2-0.3.0.dev1/.github/workflows/e2e-tests.yml +0 -73
  22. words2num2-0.3.0.dev1/.github/workflows/lint.yml +0 -47
  23. words2num2-0.3.0.dev1/.github/workflows/manual-publish.yml +0 -66
  24. words2num2-0.3.0.dev1/.github/workflows/manual-release.yml +0 -81
  25. words2num2-0.3.0.dev1/.github/workflows/pr-size.yml +0 -67
  26. words2num2-0.3.0.dev1/.github/workflows/publish-pypi.yml +0 -76
  27. words2num2-0.3.0.dev1/.github/workflows/python-publish.yml +0 -61
  28. words2num2-0.3.0.dev1/.github/workflows/release.yml +0 -166
  29. words2num2-0.3.0.dev1/.github/workflows/scheduled-test.yml +0 -44
  30. words2num2-0.3.0.dev1/.gitignore +0 -18
  31. words2num2-0.3.0.dev1/CHANGELOG.md +0 -139
  32. words2num2-0.3.0.dev1/CONTRIBUTING.md +0 -123
  33. words2num2-0.3.0.dev1/LOCAL_TESTING.md +0 -173
  34. words2num2-0.3.0.dev1/MANIFEST.in +0 -5
  35. words2num2-0.3.0.dev1/Makefile +0 -50
  36. words2num2-0.3.0.dev1/README.rst +0 -351
  37. words2num2-0.3.0.dev1/REFERENCE.md +0 -450
  38. words2num2-0.3.0.dev1/bin/words2num2 +0 -28
  39. words2num2-0.3.0.dev1/packaging/aur/python-words2num2/.SRCINFO +0 -20
  40. words2num2-0.3.0.dev1/packaging/aur/python-words2num2/PKGBUILD +0 -33
  41. words2num2-0.3.0.dev1/packaging/aur/python-words2num2/README.md +0 -88
  42. words2num2-0.3.0.dev1/pyproject.toml +0 -87
  43. words2num2-0.3.0.dev1/setup.cfg +0 -4
  44. words2num2-0.3.0.dev1/setup.py +0 -58
  45. words2num2-0.3.0.dev1/tests/__init__.py +0 -0
  46. words2num2-0.3.0.dev1/tests/test_auto_parse.py +0 -252
  47. words2num2-0.3.0.dev1/tests/test_dispatch.py +0 -28
  48. words2num2-0.3.0.dev1/tests/test_lang_EN.py +0 -113
  49. words2num2-0.3.0.dev1/tests/test_multilang.py +0 -49
  50. words2num2-0.3.0.dev1/words2num2/__init__.py +0 -360
  51. words2num2-0.3.0.dev1/words2num2/_version.py +0 -3
  52. words2num2-0.3.0.dev1/words2num2/base.py +0 -155
  53. words2num2-0.3.0.dev1/words2num2/compat.py +0 -9
  54. words2num2-0.3.0.dev1/words2num2/converters/auto.py +0 -586
  55. words2num2-0.3.0.dev1/words2num2/converters/sentence.py +0 -116
  56. words2num2-0.3.0.dev1/words2num2/formats.py +0 -212
  57. words2num2-0.3.0.dev1/words2num2/lang_AF.py +0 -15
  58. words2num2-0.3.0.dev1/words2num2/lang_AM.py +0 -15
  59. words2num2-0.3.0.dev1/words2num2/lang_AR.py +0 -15
  60. words2num2-0.3.0.dev1/words2num2/lang_AS.py +0 -15
  61. words2num2-0.3.0.dev1/words2num2/lang_AZ.py +0 -15
  62. words2num2-0.3.0.dev1/words2num2/lang_BA.py +0 -15
  63. words2num2-0.3.0.dev1/words2num2/lang_BE.py +0 -15
  64. words2num2-0.3.0.dev1/words2num2/lang_BG.py +0 -15
  65. words2num2-0.3.0.dev1/words2num2/lang_BN.py +0 -15
  66. words2num2-0.3.0.dev1/words2num2/lang_BO.py +0 -15
  67. words2num2-0.3.0.dev1/words2num2/lang_BR.py +0 -15
  68. words2num2-0.3.0.dev1/words2num2/lang_BS.py +0 -15
  69. words2num2-0.3.0.dev1/words2num2/lang_CA.py +0 -15
  70. words2num2-0.3.0.dev1/words2num2/lang_CE.py +0 -15
  71. words2num2-0.3.0.dev1/words2num2/lang_CS.py +0 -15
  72. words2num2-0.3.0.dev1/words2num2/lang_CY.py +0 -15
  73. words2num2-0.3.0.dev1/words2num2/lang_DA.py +0 -15
  74. words2num2-0.3.0.dev1/words2num2/lang_DE.py +0 -15
  75. words2num2-0.3.0.dev1/words2num2/lang_EL.py +0 -15
  76. words2num2-0.3.0.dev1/words2num2/lang_EN.py +0 -242
  77. words2num2-0.3.0.dev1/words2num2/lang_EN_IN.py +0 -15
  78. words2num2-0.3.0.dev1/words2num2/lang_EN_NG.py +0 -15
  79. words2num2-0.3.0.dev1/words2num2/lang_EO.py +0 -15
  80. words2num2-0.3.0.dev1/words2num2/lang_ES.py +0 -15
  81. words2num2-0.3.0.dev1/words2num2/lang_ES_CO.py +0 -15
  82. words2num2-0.3.0.dev1/words2num2/lang_ES_CR.py +0 -15
  83. words2num2-0.3.0.dev1/words2num2/lang_ES_GT.py +0 -15
  84. words2num2-0.3.0.dev1/words2num2/lang_ES_NI.py +0 -15
  85. words2num2-0.3.0.dev1/words2num2/lang_ES_VE.py +0 -15
  86. words2num2-0.3.0.dev1/words2num2/lang_ET.py +0 -15
  87. words2num2-0.3.0.dev1/words2num2/lang_EU.py +0 -15
  88. words2num2-0.3.0.dev1/words2num2/lang_FA.py +0 -15
  89. words2num2-0.3.0.dev1/words2num2/lang_FI.py +0 -15
  90. words2num2-0.3.0.dev1/words2num2/lang_FO.py +0 -15
  91. words2num2-0.3.0.dev1/words2num2/lang_FR.py +0 -15
  92. words2num2-0.3.0.dev1/words2num2/lang_FR_BE.py +0 -15
  93. words2num2-0.3.0.dev1/words2num2/lang_FR_CH.py +0 -15
  94. words2num2-0.3.0.dev1/words2num2/lang_FR_DZ.py +0 -15
  95. words2num2-0.3.0.dev1/words2num2/lang_GL.py +0 -15
  96. words2num2-0.3.0.dev1/words2num2/lang_GU.py +0 -15
  97. words2num2-0.3.0.dev1/words2num2/lang_HA.py +0 -15
  98. words2num2-0.3.0.dev1/words2num2/lang_HAW.py +0 -15
  99. words2num2-0.3.0.dev1/words2num2/lang_HE.py +0 -15
  100. words2num2-0.3.0.dev1/words2num2/lang_HI.py +0 -15
  101. words2num2-0.3.0.dev1/words2num2/lang_HR.py +0 -15
  102. words2num2-0.3.0.dev1/words2num2/lang_HT.py +0 -15
  103. words2num2-0.3.0.dev1/words2num2/lang_HU.py +0 -15
  104. words2num2-0.3.0.dev1/words2num2/lang_HY.py +0 -15
  105. words2num2-0.3.0.dev1/words2num2/lang_ID.py +0 -15
  106. words2num2-0.3.0.dev1/words2num2/lang_IS.py +0 -15
  107. words2num2-0.3.0.dev1/words2num2/lang_IT.py +0 -15
  108. words2num2-0.3.0.dev1/words2num2/lang_JA.py +0 -15
  109. words2num2-0.3.0.dev1/words2num2/lang_JW.py +0 -15
  110. words2num2-0.3.0.dev1/words2num2/lang_KA.py +0 -15
  111. words2num2-0.3.0.dev1/words2num2/lang_KK.py +0 -15
  112. words2num2-0.3.0.dev1/words2num2/lang_KM.py +0 -15
  113. words2num2-0.3.0.dev1/words2num2/lang_KN.py +0 -15
  114. words2num2-0.3.0.dev1/words2num2/lang_KO.py +0 -15
  115. words2num2-0.3.0.dev1/words2num2/lang_KZ.py +0 -15
  116. words2num2-0.3.0.dev1/words2num2/lang_LA.py +0 -15
  117. words2num2-0.3.0.dev1/words2num2/lang_LB.py +0 -15
  118. words2num2-0.3.0.dev1/words2num2/lang_LN.py +0 -15
  119. words2num2-0.3.0.dev1/words2num2/lang_LO.py +0 -15
  120. words2num2-0.3.0.dev1/words2num2/lang_LT.py +0 -15
  121. words2num2-0.3.0.dev1/words2num2/lang_LV.py +0 -15
  122. words2num2-0.3.0.dev1/words2num2/lang_MG.py +0 -15
  123. words2num2-0.3.0.dev1/words2num2/lang_MI.py +0 -15
  124. words2num2-0.3.0.dev1/words2num2/lang_MK.py +0 -15
  125. words2num2-0.3.0.dev1/words2num2/lang_ML.py +0 -15
  126. words2num2-0.3.0.dev1/words2num2/lang_MN.py +0 -15
  127. words2num2-0.3.0.dev1/words2num2/lang_MR.py +0 -15
  128. words2num2-0.3.0.dev1/words2num2/lang_MS.py +0 -15
  129. words2num2-0.3.0.dev1/words2num2/lang_MT.py +0 -15
  130. words2num2-0.3.0.dev1/words2num2/lang_MY.py +0 -15
  131. words2num2-0.3.0.dev1/words2num2/lang_NE.py +0 -15
  132. words2num2-0.3.0.dev1/words2num2/lang_NL.py +0 -15
  133. words2num2-0.3.0.dev1/words2num2/lang_NN.py +0 -15
  134. words2num2-0.3.0.dev1/words2num2/lang_NO.py +0 -15
  135. words2num2-0.3.0.dev1/words2num2/lang_OC.py +0 -15
  136. words2num2-0.3.0.dev1/words2num2/lang_PA.py +0 -15
  137. words2num2-0.3.0.dev1/words2num2/lang_PL.py +0 -15
  138. words2num2-0.3.0.dev1/words2num2/lang_PS.py +0 -15
  139. words2num2-0.3.0.dev1/words2num2/lang_PT.py +0 -15
  140. words2num2-0.3.0.dev1/words2num2/lang_PT_BR.py +0 -15
  141. words2num2-0.3.0.dev1/words2num2/lang_RO.py +0 -15
  142. words2num2-0.3.0.dev1/words2num2/lang_RU.py +0 -15
  143. words2num2-0.3.0.dev1/words2num2/lang_SA.py +0 -15
  144. words2num2-0.3.0.dev1/words2num2/lang_SD.py +0 -15
  145. words2num2-0.3.0.dev1/words2num2/lang_SI.py +0 -15
  146. words2num2-0.3.0.dev1/words2num2/lang_SK.py +0 -15
  147. words2num2-0.3.0.dev1/words2num2/lang_SL.py +0 -15
  148. words2num2-0.3.0.dev1/words2num2/lang_SN.py +0 -15
  149. words2num2-0.3.0.dev1/words2num2/lang_SO.py +0 -15
  150. words2num2-0.3.0.dev1/words2num2/lang_SQ.py +0 -15
  151. words2num2-0.3.0.dev1/words2num2/lang_SR.py +0 -15
  152. words2num2-0.3.0.dev1/words2num2/lang_SU.py +0 -15
  153. words2num2-0.3.0.dev1/words2num2/lang_SV.py +0 -15
  154. words2num2-0.3.0.dev1/words2num2/lang_SW.py +0 -15
  155. words2num2-0.3.0.dev1/words2num2/lang_TA.py +0 -15
  156. words2num2-0.3.0.dev1/words2num2/lang_TE.py +0 -15
  157. words2num2-0.3.0.dev1/words2num2/lang_TET.py +0 -15
  158. words2num2-0.3.0.dev1/words2num2/lang_TG.py +0 -15
  159. words2num2-0.3.0.dev1/words2num2/lang_TH.py +0 -15
  160. words2num2-0.3.0.dev1/words2num2/lang_TK.py +0 -15
  161. words2num2-0.3.0.dev1/words2num2/lang_TL.py +0 -15
  162. words2num2-0.3.0.dev1/words2num2/lang_TR.py +0 -15
  163. words2num2-0.3.0.dev1/words2num2/lang_TT.py +0 -15
  164. words2num2-0.3.0.dev1/words2num2/lang_UK.py +0 -15
  165. words2num2-0.3.0.dev1/words2num2/lang_UR.py +0 -15
  166. words2num2-0.3.0.dev1/words2num2/lang_UZ.py +0 -15
  167. words2num2-0.3.0.dev1/words2num2/lang_VI.py +0 -15
  168. words2num2-0.3.0.dev1/words2num2/lang_WO.py +0 -15
  169. words2num2-0.3.0.dev1/words2num2/lang_YI.py +0 -15
  170. words2num2-0.3.0.dev1/words2num2/lang_YO.py +0 -15
  171. words2num2-0.3.0.dev1/words2num2/lang_ZH.py +0 -15
  172. words2num2-0.3.0.dev1/words2num2/lang_ZH_CN.py +0 -15
  173. words2num2-0.3.0.dev1/words2num2/lang_ZH_HK.py +0 -15
  174. words2num2-0.3.0.dev1/words2num2/lang_ZH_TW.py +0 -15
  175. words2num2-0.3.0.dev1/words2num2/utils.py +0 -23
  176. words2num2-0.3.0.dev1/words2num2.egg-info/SOURCES.txt +0 -167
  177. words2num2-0.3.0.dev1/words2num2.egg-info/dependency_links.txt +0 -1
  178. words2num2-0.3.0.dev1/words2num2.egg-info/entry_points.txt +0 -2
  179. words2num2-0.3.0.dev1/words2num2.egg-info/requires.txt +0 -2
  180. words2num2-0.3.0.dev1/words2num2.egg-info/top_level.txt +0 -1
  181. {words2num2-0.3.0.dev1 → words2num2-0.3.1}/COPYING +0 -0
  182. {words2num2-0.3.0.dev1 → words2num2-0.3.1}/words2num2/__main__.py +0 -0
  183. {words2num2-0.3.0.dev1 → words2num2-0.3.1}/words2num2/converters/__init__.py +0 -0
@@ -1,17 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: words2num2
3
- Version: 0.3.0.dev1
4
- Summary: Inverse of num2words2: convert spoken-form numbers back to numeric values across 100+ languages.
5
- Home-page: https://github.com/jqueguiner/words2num2
6
- Author: Jean-Louis Queguiner
7
- Author-email: Jean-Louis Queguiner <jlqueguiner@gladia.io>
8
- Maintainer: Jean-Louis Queguiner
9
- Maintainer-email: Jean-Louis Queguiner <jlqueguiner@gladia.io>
10
- License: LGPL-2.1
11
- Project-URL: Homepage, https://github.com/jqueguiner/words2num2
12
- Project-URL: Repository, https://github.com/jqueguiner/words2num2.git
13
- Project-URL: Bug Tracker, https://github.com/jqueguiner/words2num2/issues
14
- Keywords: number,word,numbers,words,parse,parser,convert,conversion,i18n,localisation,localization,internationalisation,internationalization,asr,speech,llm
3
+ Version: 0.3.1
15
4
  Classifier: Development Status :: 4 - Beta
16
5
  Classifier: Intended Audience :: Developers
17
6
  Classifier: Programming Language :: Python :: 3
@@ -20,21 +9,23 @@ Classifier: Programming Language :: Python :: 3.11
20
9
  Classifier: Programming Language :: Python :: 3.12
21
10
  Classifier: Programming Language :: Python :: 3.13
22
11
  Classifier: Programming Language :: Python :: 3.14
23
- Classifier: Programming Language :: Python :: 3.15
12
+ Classifier: Programming Language :: Rust
24
13
  Classifier: Topic :: Software Development :: Internationalization
25
14
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
15
  Classifier: Topic :: Software Development :: Localization
27
16
  Classifier: Topic :: Text Processing :: Linguistic
28
- Requires-Python: >=3.10
29
- Description-Content-Type: text/x-rst
30
17
  License-File: COPYING
31
- Requires-Dist: docopt>=0.6.2
32
- Requires-Dist: num2words2>=0.1.0.dev0
33
- Dynamic: author
34
- Dynamic: home-page
35
- Dynamic: license
36
- Dynamic: license-file
37
- Dynamic: maintainer
18
+ Summary: Rust-powered inverse of num2words2: parse spoken-form numbers back to numeric values across 100+ languages, optimized for ASR/LLM/speech.
19
+ Keywords: number,word,numbers,words,parse,parser,convert,conversion,i18n,localisation,localization,internationalisation,internationalization,asr,speech,llm,rust
20
+ Author-email: Jean-Louis Queguiner <jean-louis.queguiner@gmail.com>
21
+ Maintainer-email: Jean-Louis Queguiner <jean-louis.queguiner@gmail.com>
22
+ License-Expression: LGPL-2.1-only
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/x-rst; charset=UTF-8
25
+ Project-URL: Bug Tracker, https://github.com/jqueguiner/words2num2/issues
26
+ Project-URL: Documentation, https://github.com/jqueguiner/words2num2/wiki
27
+ Project-URL: Homepage, https://github.com/jqueguiner/words2num2
28
+ Project-URL: Repository, https://github.com/jqueguiner/words2num2.git
38
29
 
39
30
  words2num2 — words to numbers
40
31
  =============================
@@ -104,9 +95,21 @@ entries**) and adds a free-text *auto-parse* mode that handles
104
95
  currencies, units, configurable thousands/decimal separators, and
105
96
  ASR/LLM-style mixed text.
106
97
 
107
- The project is hosted on GitHub_. Contributions are welcome.
98
+ It is **Rust-powered with a thin Python binder**. The whole parsing engine —
99
+ the English grammar, the generic reverse-lookup backend, the sentence walker,
100
+ number-format parsing and auto-parse — runs in a compiled Rust core
101
+ (PyO3/``abi3``); Python only shapes arguments and results. The core embeds the
102
+ num2words2 conversion engine natively, so ``words2num2`` is **self-contained
103
+ and has no runtime dependencies**, while running several times faster than the
104
+ former pure-Python implementation. Output is unchanged — validated against a
105
+ frozen corpus of ~11,000 round-trip cases.
106
+
107
+ The project is hosted on GitHub_, and the full documentation is available
108
+ in the Wiki_. Contributions are welcome.
108
109
 
109
110
  .. _GitHub: https://github.com/jqueguiner/words2num2
111
+ .. _Wiki: https://github.com/jqueguiner/words2num2/wiki
112
+ .. _GitHub Releases: https://github.com/jqueguiner/words2num2/releases
110
113
 
111
114
  Why this library
112
115
  ----------------
@@ -130,13 +133,59 @@ the forward direction. ``words2num2``:
130
133
  * Pluralizes long-form units in expand mode (``5 dollars`` /
131
134
  ``1 dollar``, ``5 feet`` / ``1 foot``, ``5 yen`` / ``1 yen``).
132
135
 
136
+ Performance
137
+ -----------
138
+
139
+ The parsing engine is compiled Rust (PyO3/``abi3``), so there is no
140
+ Python-level tokenising or table walking on the hot path. Typical native
141
+ throughput (Apple M-series, nanoseconds per call, after warmup):
142
+
143
+ .. list-table::
144
+ :header-rows: 1
145
+ :widths: 60 20
146
+
147
+ * - Operation
148
+ - ns/call
149
+ * - English cardinal (``"eight thousand seven hundred sixty-five"``)
150
+ - ~5,900
151
+ * - English ordinal (``"forty-second"``)
152
+ - ~4,100
153
+ * - French cardinal (``"trois cent quatre"``)
154
+ - ~1,900
155
+ * - Russian cardinal (``"сорок два"``)
156
+ - ~1,700
157
+ * - ``parse_number_string("1.234.567,89", lang="de")``
158
+ - ~240
159
+ * - ``auto_parse("$12,345.00")``
160
+ - ~990
161
+
162
+ For the 100+ generic locales, the first call in a given language builds the
163
+ ``{words → number}`` reverse table once (~35 ms) and caches it in the core;
164
+ every call after that is a native lookup. Output is byte-for-byte identical to
165
+ the former pure-Python implementation, validated against a frozen corpus of
166
+ ~11,000 round-trip cases and the full test suite.
167
+
133
168
  Installation
134
169
  ------------
135
170
 
136
- **pip**::
171
+ **pip** (Python 3.10+)::
137
172
 
138
173
  pip install words2num2
139
174
 
175
+ That's it — the wheel bundles the Python binder and the compiled Rust
176
+ extension, and ``words2num2`` has **no runtime dependencies** (the num2words2
177
+ conversion engine is compiled in, so you do *not* need the num2words2 package).
178
+
179
+ Prebuilt wheels are published for:
180
+
181
+ * **Linux** — x86_64 and aarch64 (manylinux2014)
182
+ * **macOS** — Apple Silicon (arm64); Intel (x86_64) from a later release
183
+ * **Windows** — x86_64
184
+
185
+ On any other platform (or an older release without a matching wheel), pip
186
+ falls back to the source distribution and builds the extension locally — this
187
+ needs a **stable Rust toolchain** (`rustup <https://rustup.rs>`_); nothing else.
188
+
140
189
  **Arch Linux / Manjaro (AUR):**
141
190
 
142
191
  .. code-block:: bash
@@ -150,14 +199,15 @@ Installation
150
199
  cd python-words2num2
151
200
  makepkg -si
152
201
 
153
- **From source**::
202
+ **From source** (needs a stable Rust toolchain and `maturin
203
+ <https://www.maturin.rs>`_)::
154
204
 
155
205
  git clone https://github.com/jqueguiner/words2num2
156
206
  cd words2num2
157
- pip install -e .
207
+ pip install -e . # builds the Rust extension via maturin
208
+ # or, to produce a wheel: maturin build --release
158
209
 
159
- ``num2words2`` is a runtime dependency for the generic multi-language
160
- backend and is installed automatically.
210
+ Wheels for every version are also attached to the `GitHub Releases`_ page.
161
211
 
162
212
  Quickstart
163
213
  ----------
@@ -303,6 +353,13 @@ entries** including:
303
353
 
304
354
  Aliases: ``jp`` → ``ja``, ``cn`` → ``zh_CN``.
305
355
 
356
+ Wiki
357
+ ----
358
+ For the full documentation, including installation, API details, CLI
359
+ usage, supported locales, sentence conversion, auto-parse behavior, and
360
+ migration guidance, please check the Wiki_. Feel free to propose wiki
361
+ enhancements.
362
+
306
363
  Conversion types
307
364
  ~~~~~~~~~~~~~~~~
308
365
 
@@ -387,3 +444,4 @@ License
387
444
  -------
388
445
 
389
446
  LGPL-2.1, mirroring ``num2words2``. See `COPYING`.
447
+
@@ -1,41 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: words2num2
3
- Version: 0.3.0.dev1
4
- Summary: Inverse of num2words2: convert spoken-form numbers back to numeric values across 100+ languages.
5
- Home-page: https://github.com/jqueguiner/words2num2
6
- Author: Jean-Louis Queguiner
7
- Author-email: Jean-Louis Queguiner <jlqueguiner@gladia.io>
8
- Maintainer: Jean-Louis Queguiner
9
- Maintainer-email: Jean-Louis Queguiner <jlqueguiner@gladia.io>
10
- License: LGPL-2.1
11
- Project-URL: Homepage, https://github.com/jqueguiner/words2num2
12
- Project-URL: Repository, https://github.com/jqueguiner/words2num2.git
13
- Project-URL: Bug Tracker, https://github.com/jqueguiner/words2num2/issues
14
- Keywords: number,word,numbers,words,parse,parser,convert,conversion,i18n,localisation,localization,internationalisation,internationalization,asr,speech,llm
15
- Classifier: Development Status :: 4 - Beta
16
- Classifier: Intended Audience :: Developers
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.10
19
- Classifier: Programming Language :: Python :: 3.11
20
- Classifier: Programming Language :: Python :: 3.12
21
- Classifier: Programming Language :: Python :: 3.13
22
- Classifier: Programming Language :: Python :: 3.14
23
- Classifier: Programming Language :: Python :: 3.15
24
- Classifier: Topic :: Software Development :: Internationalization
25
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
- Classifier: Topic :: Software Development :: Localization
27
- Classifier: Topic :: Text Processing :: Linguistic
28
- Requires-Python: >=3.10
29
- Description-Content-Type: text/x-rst
30
- License-File: COPYING
31
- Requires-Dist: docopt>=0.6.2
32
- Requires-Dist: num2words2>=0.1.0.dev0
33
- Dynamic: author
34
- Dynamic: home-page
35
- Dynamic: license
36
- Dynamic: license-file
37
- Dynamic: maintainer
38
-
39
1
  words2num2 — words to numbers
40
2
  =============================
41
3
 
@@ -104,9 +66,21 @@ entries**) and adds a free-text *auto-parse* mode that handles
104
66
  currencies, units, configurable thousands/decimal separators, and
105
67
  ASR/LLM-style mixed text.
106
68
 
107
- The project is hosted on GitHub_. Contributions are welcome.
69
+ It is **Rust-powered with a thin Python binder**. The whole parsing engine —
70
+ the English grammar, the generic reverse-lookup backend, the sentence walker,
71
+ number-format parsing and auto-parse — runs in a compiled Rust core
72
+ (PyO3/``abi3``); Python only shapes arguments and results. The core embeds the
73
+ num2words2 conversion engine natively, so ``words2num2`` is **self-contained
74
+ and has no runtime dependencies**, while running several times faster than the
75
+ former pure-Python implementation. Output is unchanged — validated against a
76
+ frozen corpus of ~11,000 round-trip cases.
77
+
78
+ The project is hosted on GitHub_, and the full documentation is available
79
+ in the Wiki_. Contributions are welcome.
108
80
 
109
81
  .. _GitHub: https://github.com/jqueguiner/words2num2
82
+ .. _Wiki: https://github.com/jqueguiner/words2num2/wiki
83
+ .. _GitHub Releases: https://github.com/jqueguiner/words2num2/releases
110
84
 
111
85
  Why this library
112
86
  ----------------
@@ -130,13 +104,59 @@ the forward direction. ``words2num2``:
130
104
  * Pluralizes long-form units in expand mode (``5 dollars`` /
131
105
  ``1 dollar``, ``5 feet`` / ``1 foot``, ``5 yen`` / ``1 yen``).
132
106
 
107
+ Performance
108
+ -----------
109
+
110
+ The parsing engine is compiled Rust (PyO3/``abi3``), so there is no
111
+ Python-level tokenising or table walking on the hot path. Typical native
112
+ throughput (Apple M-series, nanoseconds per call, after warmup):
113
+
114
+ .. list-table::
115
+ :header-rows: 1
116
+ :widths: 60 20
117
+
118
+ * - Operation
119
+ - ns/call
120
+ * - English cardinal (``"eight thousand seven hundred sixty-five"``)
121
+ - ~5,900
122
+ * - English ordinal (``"forty-second"``)
123
+ - ~4,100
124
+ * - French cardinal (``"trois cent quatre"``)
125
+ - ~1,900
126
+ * - Russian cardinal (``"сорок два"``)
127
+ - ~1,700
128
+ * - ``parse_number_string("1.234.567,89", lang="de")``
129
+ - ~240
130
+ * - ``auto_parse("$12,345.00")``
131
+ - ~990
132
+
133
+ For the 100+ generic locales, the first call in a given language builds the
134
+ ``{words → number}`` reverse table once (~35 ms) and caches it in the core;
135
+ every call after that is a native lookup. Output is byte-for-byte identical to
136
+ the former pure-Python implementation, validated against a frozen corpus of
137
+ ~11,000 round-trip cases and the full test suite.
138
+
133
139
  Installation
134
140
  ------------
135
141
 
136
- **pip**::
142
+ **pip** (Python 3.10+)::
137
143
 
138
144
  pip install words2num2
139
145
 
146
+ That's it — the wheel bundles the Python binder and the compiled Rust
147
+ extension, and ``words2num2`` has **no runtime dependencies** (the num2words2
148
+ conversion engine is compiled in, so you do *not* need the num2words2 package).
149
+
150
+ Prebuilt wheels are published for:
151
+
152
+ * **Linux** — x86_64 and aarch64 (manylinux2014)
153
+ * **macOS** — Apple Silicon (arm64); Intel (x86_64) from a later release
154
+ * **Windows** — x86_64
155
+
156
+ On any other platform (or an older release without a matching wheel), pip
157
+ falls back to the source distribution and builds the extension locally — this
158
+ needs a **stable Rust toolchain** (`rustup <https://rustup.rs>`_); nothing else.
159
+
140
160
  **Arch Linux / Manjaro (AUR):**
141
161
 
142
162
  .. code-block:: bash
@@ -150,14 +170,15 @@ Installation
150
170
  cd python-words2num2
151
171
  makepkg -si
152
172
 
153
- **From source**::
173
+ **From source** (needs a stable Rust toolchain and `maturin
174
+ <https://www.maturin.rs>`_)::
154
175
 
155
176
  git clone https://github.com/jqueguiner/words2num2
156
177
  cd words2num2
157
- pip install -e .
178
+ pip install -e . # builds the Rust extension via maturin
179
+ # or, to produce a wheel: maturin build --release
158
180
 
159
- ``num2words2`` is a runtime dependency for the generic multi-language
160
- backend and is installed automatically.
181
+ Wheels for every version are also attached to the `GitHub Releases`_ page.
161
182
 
162
183
  Quickstart
163
184
  ----------
@@ -303,6 +324,13 @@ entries** including:
303
324
 
304
325
  Aliases: ``jp`` → ``ja``, ``cn`` → ``zh_CN``.
305
326
 
327
+ Wiki
328
+ ----
329
+ For the full documentation, including installation, API details, CLI
330
+ usage, supported locales, sentence conversion, auto-parse behavior, and
331
+ migration guidance, please check the Wiki_. Feel free to propose wiki
332
+ enhancements.
333
+
306
334
  Conversion types
307
335
  ~~~~~~~~~~~~~~~~
308
336
 
@@ -0,0 +1,94 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.5,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "words2num2"
7
+ # Static base version. The release CI overrides it from the pushed git tag
8
+ # (see .github/workflows/release.yml); bump here for local source builds.
9
+ version = "0.3.1"
10
+ license = "LGPL-2.1-only"
11
+ license-files = ["COPYING"]
12
+ description = "Rust-powered inverse of num2words2: parse spoken-form numbers back to numeric values across 100+ languages, optimized for ASR/LLM/speech."
13
+ readme = "README.rst"
14
+ requires-python = ">=3.10"
15
+ # Self-contained: the num2words2 conversion engine is embedded in the compiled
16
+ # core (num2words2-core), so there is no runtime dependency on the num2words2
17
+ # package and no docopt (the CLI uses only the standard library).
18
+ dependencies = []
19
+ authors = [
20
+ {name = "Jean-Louis Queguiner", email = "jean-louis.queguiner@gmail.com"}
21
+ ]
22
+ maintainers = [
23
+ {name = "Jean-Louis Queguiner", email = "jean-louis.queguiner@gmail.com"}
24
+ ]
25
+ keywords = ["number", "word", "numbers", "words", "parse", "parser", "convert",
26
+ "conversion", "i18n", "localisation", "localization",
27
+ "internationalisation", "internationalization", "asr", "speech",
28
+ "llm", "rust"]
29
+ classifiers = [
30
+ "Development Status :: 4 - Beta",
31
+ "Intended Audience :: Developers",
32
+ "Programming Language :: Python :: 3",
33
+ "Programming Language :: Python :: 3.10",
34
+ "Programming Language :: Python :: 3.11",
35
+ "Programming Language :: Python :: 3.12",
36
+ "Programming Language :: Python :: 3.13",
37
+ "Programming Language :: Python :: 3.14",
38
+ "Programming Language :: Rust",
39
+ "Topic :: Software Development :: Internationalization",
40
+ "Topic :: Software Development :: Libraries :: Python Modules",
41
+ "Topic :: Software Development :: Localization",
42
+ "Topic :: Text Processing :: Linguistic",
43
+ ]
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/jqueguiner/words2num2"
47
+ Documentation = "https://github.com/jqueguiner/words2num2/wiki"
48
+ Repository = "https://github.com/jqueguiner/words2num2.git"
49
+ "Bug Tracker" = "https://github.com/jqueguiner/words2num2/issues"
50
+
51
+ [project.scripts]
52
+ words2num2 = "words2num2.__main__:main"
53
+
54
+ # ---- maturin: mixed Rust/Python project -------------------------------------
55
+ # The compiled engine lives in ./rust (vendored crates `words2num2-py`, lib
56
+ # `_rust`, plus its `num2words2-core` dependency); the thin Python binder is
57
+ # ./words2num2. maturin bundles both into a single per-platform wheel. The
58
+ # wheel embeds num2words2-core natively — no lingua-rs models, so it stays
59
+ # small (~4MB), and there is only one variant.
60
+ [tool.maturin]
61
+ manifest-path = "rust/words2num2-py/Cargo.toml"
62
+ python-source = "."
63
+ module-name = "words2num2._rust"
64
+ features = ["pyo3/extension-module"]
65
+ strip = true
66
+
67
+ [tool.isort]
68
+ profile = "black"
69
+ line_length = 88
70
+ skip = ["words2num2/_version.py"]
71
+ multi_line_output = 3
72
+ include_trailing_comma = true
73
+ force_grid_wrap = 0
74
+ use_parentheses = true
75
+ ensure_newline_before_comments = true
76
+
77
+ [tool.black]
78
+ line-length = 88
79
+ target-version = ['py310']
80
+ include = '\.pyi?$'
81
+ exclude = '''
82
+ /(
83
+ \.git
84
+ | \.hg
85
+ | \.mypy_cache
86
+ | \.tox
87
+ | \.venv
88
+ | _build
89
+ | buck-out
90
+ | build
91
+ | dist
92
+ | words2num2/_version.py
93
+ )/
94
+ '''