numbr 3.0.0__tar.gz → 3.2.3__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 (34) hide show
  1. {numbr-3.0.0 → numbr-3.2.3}/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
  2. {numbr-3.0.0 → numbr-3.2.3}/.github/workflows/ci.yml +1 -1
  3. {numbr-3.0.0 → numbr-3.2.3}/PKG-INFO +124 -34
  4. {numbr-3.0.0 → numbr-3.2.3}/README.md +123 -33
  5. {numbr-3.0.0 → numbr-3.2.3}/RELEASING.md +7 -7
  6. {numbr-3.0.0 → numbr-3.2.3}/pyproject.toml +1 -1
  7. {numbr-3.0.0 → numbr-3.2.3}/.gitattributes +0 -0
  8. {numbr-3.0.0 → numbr-3.2.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  9. {numbr-3.0.0 → numbr-3.2.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  10. {numbr-3.0.0 → numbr-3.2.3}/.github/pull_request_template.md +0 -0
  11. {numbr-3.0.0 → numbr-3.2.3}/.github/release.yml +0 -0
  12. {numbr-3.0.0 → numbr-3.2.3}/.github/workflows/codeql.yml +0 -0
  13. {numbr-3.0.0 → numbr-3.2.3}/.github/workflows/publish.yml +0 -0
  14. {numbr-3.0.0 → numbr-3.2.3}/.gitignore +0 -0
  15. {numbr-3.0.0 → numbr-3.2.3}/CHANGELOG.md +0 -0
  16. {numbr-3.0.0 → numbr-3.2.3}/CODE_OF_CONDUCT.md +0 -0
  17. {numbr-3.0.0 → numbr-3.2.3}/CONTRIBUTING.md +0 -0
  18. {numbr-3.0.0 → numbr-3.2.3}/LICENSE +0 -0
  19. {numbr-3.0.0 → numbr-3.2.3}/SECURITY.md +0 -0
  20. {numbr-3.0.0 → numbr-3.2.3}/assets/png/numbr-lockup-endorsed-1118x344.png +0 -0
  21. {numbr-3.0.0 → numbr-3.2.3}/assets/png/organization/author-lock-up.png +0 -0
  22. {numbr-3.0.0 → numbr-3.2.3}/assets/png/organization/author-mark.png +0 -0
  23. {numbr-3.0.0 → numbr-3.2.3}/assets/png/organization/author-wordmark.png +0 -0
  24. {numbr-3.0.0 → numbr-3.2.3}/src/numbr/__init__.py +0 -0
  25. {numbr-3.0.0 → numbr-3.2.3}/src/numbr/engine.py +0 -0
  26. {numbr-3.0.0 → numbr-3.2.3}/tests/test_cardinals.py +0 -0
  27. {numbr-3.0.0 → numbr-3.2.3}/tests/test_decimals.py +0 -0
  28. {numbr-3.0.0 → numbr-3.2.3}/tests/test_diagnostics_and_batch.py +0 -0
  29. {numbr-3.0.0 → numbr-3.2.3}/tests/test_extraction.py +0 -0
  30. {numbr-3.0.0 → numbr-3.2.3}/tests/test_notation_and_normalization.py +0 -0
  31. {numbr-3.0.0 → numbr-3.2.3}/tests/test_ordinals.py +0 -0
  32. {numbr-3.0.0 → numbr-3.2.3}/tests/test_public_api.py +0 -0
  33. {numbr-3.0.0 → numbr-3.2.3}/tests/test_roman.py +0 -0
  34. {numbr-3.0.0 → numbr-3.2.3}/tests/test_structured_extraction.py +0 -0
@@ -10,7 +10,7 @@ body:
10
10
  id: version
11
11
  attributes:
12
12
  label: numbr version
13
- placeholder: 3.0.0
13
+ placeholder: 3.2.3
14
14
  validations:
15
15
  required: true
16
16
  - type: input
@@ -55,7 +55,7 @@ jobs:
55
55
  run: |
56
56
  python -m pip install --force-reinstall dist/*.whl
57
57
  cd /tmp
58
- python -I -c "import numbr; assert numbr.__version__ == '3.0.0'; assert numbr.Cast('Ⅳ', 'Ordinal Word') == 'fourth'"
58
+ python -I -c "import numbr; assert numbr.__version__ == '3.2.3'; assert numbr.Cast('Ⅳ', 'Ordinal Word') == 'fourth'"
59
59
  - name: Upload distributions
60
60
  uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
61
61
  with:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: numbr
3
- Version: 3.0.0
3
+ Version: 3.2.3
4
4
  Summary: Parse, diagnose, batch-convert, extract, and normalize English numbers, exact decimals, scientific and accounting notation, and Roman numerals.
5
5
  Project-URL: Homepage, https://github.com/doydl-technologies/numbr
6
6
  Project-URL: Documentation, https://github.com/doydl-technologies/numbr#readme
@@ -44,7 +44,11 @@ Description-Content-Type: text/markdown
44
44
 
45
45
  ## Table of contents
46
46
 
47
+ - [What numbr does](#what-numbr-does)
47
48
  - [Installation](#installation)
49
+ - [Quick start](#quick-start)
50
+ - [Choosing the right API](#choosing-the-right-api)
51
+ - [Exact decimal values](#exact-decimal-values)
48
52
  - [Representations](#representations)
49
53
  - [Public API](#public-api)
50
54
  - [General conversion](#general-conversion)
@@ -57,73 +61,159 @@ Description-Content-Type: text/markdown
57
61
  - [Development](#development)
58
62
  - [License](#license)
59
63
 
60
- ```python
61
- from decimal import Decimal
64
+ ## What numbr does
62
65
 
63
- import numbr
66
+ `numbr` gives Python applications one consistent way to understand numbers
67
+ written in different forms. It can recognize that `"forty-two"`, `"42"`, and
68
+ `"XLII"` represent the same value, then convert them to the representation an
69
+ application needs.
70
+
71
+ The package is useful when numeric data arrives as human-written text rather
72
+ than a clean integer or decimal. Common examples include form responses,
73
+ documents, transcripts, scraped text, NLP pipelines, and imported business
74
+ data.
64
75
 
65
- numbr.wordsToInt("one hundred sixty-seven")
66
- # 167
76
+ With `numbr`, an application can:
67
77
 
68
- numbr.Cast("forty-ninth", "Ordinal Number")
69
- # "49th"
78
+ - identify the representation of one numeric value;
79
+ - convert between digits, English number words, ordinals, and Roman numerals;
80
+ - parse exact decimals, scientific notation, and accounting notation;
81
+ - find every numeric expression in a larger passage of text;
82
+ - replace numeric expressions while leaving the surrounding text intact;
83
+ - receive structured explanations for invalid input; and
84
+ - apply the same conversion or diagnostic operation to an iterable of values.
70
85
 
71
- numbr.Cast("Ⅳ", "Ordinal Word")
72
- # "fourth"
86
+ `numbr` is deterministic and rule-based. It does not use a language model,
87
+ network service, locale database, or heuristic confidence score. The same
88
+ supported input produces the same result on every platform.
73
89
 
74
- numbr.Cast("one point zero five", "Decimal Number")
75
- # Decimal("1.05")
90
+ ## Installation
91
+
92
+ Install the latest release from PyPI:
76
93
 
77
- numbr.Cast(Decimal("1.050"), "Cardinal Word")
94
+ ```bash
95
+ python -m pip install numbr
96
+ ```
97
+
98
+ Or install the current development version from GitHub:
99
+
100
+ ```bash
101
+ python -m pip install 'numbr @ git+ssh://git@github.com/doydl-technologies/numbr.git'
102
+ ```
103
+
104
+ Python 3.13 is required. The package has no runtime dependencies.
105
+
106
+ ## Quick start
107
+
108
+ Import `numbr`, then choose an operation based on whether the input is one
109
+ value, a passage of text, or a collection of values.
110
+
111
+ ```python
112
+ import numbr
113
+
114
+ # Identify how one value is written.
115
+ numbr.Type("forty-second")
116
+ # "Ordinal Word"
117
+
118
+ # Convert one value to a requested representation.
119
+ numbr.Cast("forty-second", "Cardinal Number")
120
+ # 42
121
+
122
+ numbr.Cast("1.050", "Cardinal Word")
78
123
  # "one point zero five zero"
79
124
 
80
- numbr.extractNumericValue("He scored twenty-one of 34 attempts")
81
- # [21, 34]
125
+ # Collect normalized values from a larger passage.
126
+ numbr.extractNumericValue("She placed 2nd with 1.05 points")
127
+ # [2, Decimal("1.05")]
82
128
 
129
+ # Collect values together with their original text and source positions.
83
130
  numbr.extractNumericEntities("She placed 2nd with 1.05 points")
84
131
  # [NumericMatch(text='2nd', value=2, representation='Ordinal Number', ...),
85
132
  # NumericMatch(text='1.05', value=Decimal('1.05'), representation='Decimal Number', ...)]
86
133
 
134
+ # Rewrite recognized expressions without changing the surrounding sentence.
87
135
  numbr.normalizeNumericText("She placed forty-second with 1.20e3 points")
88
136
  # "She placed 42nd with 1200 points"
89
137
 
138
+ # Apply one conversion to several values.
90
139
  numbr.batchCast(["one", "2", "III"], "Cardinal Number")
91
140
  # [1, 2, 3]
92
141
  ```
93
142
 
94
- ## Installation
143
+ The `Decimal(...)` text shown above is Python's representation of the returned
144
+ value; the quick-start example does not need to import `Decimal`.
95
145
 
96
- Install the latest release from PyPI:
146
+ ## Choosing the right API
97
147
 
98
- ```bash
99
- python -m pip install numbr
100
- ```
148
+ | Goal | API | Result |
149
+ |---|---|---|
150
+ | Identify how one value is written | `Type(value)` | A representation name such as `"Ordinal Word"`, or `None` |
151
+ | Convert one value | `Cast(value, target)` | The value in the requested representation |
152
+ | Collect only values from text | `extractNumericValue(text)` | A list of normalized `int` or `Decimal` values |
153
+ | Collect values and source details | `extractNumericEntities(text)` | A list of `NumericMatch` records with text, type, value, and position |
154
+ | Rewrite numbers inside text | `normalizeNumericText(text)` | A new string with recognized expressions normalized |
155
+ | Explain why parsing failed | `diagnoseNumeric(value)` | A `ParseResult` containing either a value or structured diagnostics |
156
+ | Convert many inputs | `batchCast(values, target)` | A list of converted values using the selected error policy |
157
+ | Diagnose many inputs | `batchDiagnose(values, target)` | One index-stable `ParseResult` per input |
101
158
 
102
- Or install the current development version from GitHub:
159
+ Conversion operates on one numeric value. Extraction searches a larger string
160
+ and returns the numbers it contains. Normalization also searches a larger
161
+ string, but returns rewritten text instead of match records.
103
162
 
104
- ```bash
105
- python -m pip install 'numbr @ git+ssh://git@github.com/doydl-technologies/numbr.git'
163
+ ## Exact decimal values
164
+
165
+ Decimal parsing returns [`decimal.Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal)
166
+ instead of `float`. `Decimal` is part of Python's standard library; it is not an
167
+ additional dependency. This avoids binary floating-point rounding and preserves
168
+ meaningful fractional zeros such as the final zero in `"1.050"`.
169
+
170
+ No `Decimal` import is required when the input is a string:
171
+
172
+ ```python
173
+ import numbr
174
+
175
+ value = numbr.Cast("1.050", "Decimal Number")
176
+
177
+ value
178
+ # Decimal("1.050")
179
+
180
+ numbr.Cast(value, "Cardinal Word")
181
+ # "one point zero five zero"
106
182
  ```
107
183
 
108
- Python 3.13 is required. The package has no runtime dependencies.
184
+ Import `Decimal` only when application code needs to construct a decimal value
185
+ directly or perform decimal arithmetic:
186
+
187
+ ```python
188
+ from decimal import Decimal
189
+
190
+ import numbr
191
+
192
+ numbr.decimalToAccounting(Decimal("-1234.50"), currency="$")
193
+ # "($1,234.50)"
194
+ ```
109
195
 
110
196
  ## Representations
111
197
 
112
- | Representation | Examples | `Type` result |
113
- |---|---|---|
114
- | Cardinal number | `42`, `"-42"` | `"Cardinal Number"` |
115
- | Decimal number | `"1.05"`, `Decimal("1.050")` | `"Decimal Number"` |
116
- | Scientific number | `"1.20e3"`, `"-4E-2"` | `"Scientific Number"` |
117
- | Accounting number | `"(1,234.50)"`, `"($50.00)"` | `"Accounting Number"` |
118
- | Cardinal word | `"forty-two"` | `"Cardinal Word"` |
119
- | Ordinal number | `"42nd"` | `"Ordinal Number"` |
120
- | Ordinal word | `"forty-second"` | `"Ordinal Word"` |
121
- | Roman numeral | `"XLII"`, `"Ⅳ"` | `"Roman Numeral"` |
198
+ | Representation | Meaning | Examples | `Type` result |
199
+ |---|---|---|---|
200
+ | Cardinal number | A whole-number quantity written with digits | `42`, `"-42"` | `"Cardinal Number"` |
201
+ | Decimal number | A fixed-point value with a fractional part | `"1.05"`, `Decimal("1.050")` | `"Decimal Number"` |
202
+ | Scientific number | A coefficient multiplied by a power of ten | `"1.20e3"`, `"-4E-2"` | `"Scientific Number"` |
203
+ | Accounting number | A formatted business value whose parentheses indicate a negative amount | `"(1,234.50)"`, `"($50.00)"` | `"Accounting Number"` |
204
+ | Cardinal word | A quantity written with English words | `"forty-two"` | `"Cardinal Word"` |
205
+ | Ordinal number | A position or rank written with digits and a suffix | `"42nd"` | `"Ordinal Number"` |
206
+ | Ordinal word | A position or rank written with English words | `"forty-second"` | `"Ordinal Word"` |
207
+ | Roman numeral | A value written with Roman symbols | `"XLII"`, `"Ⅳ"` | `"Roman Numeral"` |
122
208
 
123
209
  Decimal phrases such as `"one point zero five"` are cardinal-word forms. Digits
124
210
  following `point` are interpreted individually so precision and trailing zeros
125
211
  are preserved.
126
212
 
213
+ English-word parsing is intended for numeric expressions, not unrestricted
214
+ natural-language interpretation. Surrounding prose should be passed to an
215
+ extraction or normalization API rather than directly to `Type` or `Cast`.
216
+
127
217
  `Cast` accepts the display names and common aliases such as `int`, `decimal`,
128
218
  `scientific`, `accounting`, `cardword`, `ordnum`, and `roman`.
129
219
 
@@ -16,7 +16,11 @@
16
16
 
17
17
  ## Table of contents
18
18
 
19
+ - [What numbr does](#what-numbr-does)
19
20
  - [Installation](#installation)
21
+ - [Quick start](#quick-start)
22
+ - [Choosing the right API](#choosing-the-right-api)
23
+ - [Exact decimal values](#exact-decimal-values)
20
24
  - [Representations](#representations)
21
25
  - [Public API](#public-api)
22
26
  - [General conversion](#general-conversion)
@@ -29,73 +33,159 @@
29
33
  - [Development](#development)
30
34
  - [License](#license)
31
35
 
32
- ```python
33
- from decimal import Decimal
36
+ ## What numbr does
34
37
 
35
- import numbr
38
+ `numbr` gives Python applications one consistent way to understand numbers
39
+ written in different forms. It can recognize that `"forty-two"`, `"42"`, and
40
+ `"XLII"` represent the same value, then convert them to the representation an
41
+ application needs.
42
+
43
+ The package is useful when numeric data arrives as human-written text rather
44
+ than a clean integer or decimal. Common examples include form responses,
45
+ documents, transcripts, scraped text, NLP pipelines, and imported business
46
+ data.
36
47
 
37
- numbr.wordsToInt("one hundred sixty-seven")
38
- # 167
48
+ With `numbr`, an application can:
39
49
 
40
- numbr.Cast("forty-ninth", "Ordinal Number")
41
- # "49th"
50
+ - identify the representation of one numeric value;
51
+ - convert between digits, English number words, ordinals, and Roman numerals;
52
+ - parse exact decimals, scientific notation, and accounting notation;
53
+ - find every numeric expression in a larger passage of text;
54
+ - replace numeric expressions while leaving the surrounding text intact;
55
+ - receive structured explanations for invalid input; and
56
+ - apply the same conversion or diagnostic operation to an iterable of values.
42
57
 
43
- numbr.Cast("Ⅳ", "Ordinal Word")
44
- # "fourth"
58
+ `numbr` is deterministic and rule-based. It does not use a language model,
59
+ network service, locale database, or heuristic confidence score. The same
60
+ supported input produces the same result on every platform.
45
61
 
46
- numbr.Cast("one point zero five", "Decimal Number")
47
- # Decimal("1.05")
62
+ ## Installation
63
+
64
+ Install the latest release from PyPI:
48
65
 
49
- numbr.Cast(Decimal("1.050"), "Cardinal Word")
66
+ ```bash
67
+ python -m pip install numbr
68
+ ```
69
+
70
+ Or install the current development version from GitHub:
71
+
72
+ ```bash
73
+ python -m pip install 'numbr @ git+ssh://git@github.com/doydl-technologies/numbr.git'
74
+ ```
75
+
76
+ Python 3.13 is required. The package has no runtime dependencies.
77
+
78
+ ## Quick start
79
+
80
+ Import `numbr`, then choose an operation based on whether the input is one
81
+ value, a passage of text, or a collection of values.
82
+
83
+ ```python
84
+ import numbr
85
+
86
+ # Identify how one value is written.
87
+ numbr.Type("forty-second")
88
+ # "Ordinal Word"
89
+
90
+ # Convert one value to a requested representation.
91
+ numbr.Cast("forty-second", "Cardinal Number")
92
+ # 42
93
+
94
+ numbr.Cast("1.050", "Cardinal Word")
50
95
  # "one point zero five zero"
51
96
 
52
- numbr.extractNumericValue("He scored twenty-one of 34 attempts")
53
- # [21, 34]
97
+ # Collect normalized values from a larger passage.
98
+ numbr.extractNumericValue("She placed 2nd with 1.05 points")
99
+ # [2, Decimal("1.05")]
54
100
 
101
+ # Collect values together with their original text and source positions.
55
102
  numbr.extractNumericEntities("She placed 2nd with 1.05 points")
56
103
  # [NumericMatch(text='2nd', value=2, representation='Ordinal Number', ...),
57
104
  # NumericMatch(text='1.05', value=Decimal('1.05'), representation='Decimal Number', ...)]
58
105
 
106
+ # Rewrite recognized expressions without changing the surrounding sentence.
59
107
  numbr.normalizeNumericText("She placed forty-second with 1.20e3 points")
60
108
  # "She placed 42nd with 1200 points"
61
109
 
110
+ # Apply one conversion to several values.
62
111
  numbr.batchCast(["one", "2", "III"], "Cardinal Number")
63
112
  # [1, 2, 3]
64
113
  ```
65
114
 
66
- ## Installation
115
+ The `Decimal(...)` text shown above is Python's representation of the returned
116
+ value; the quick-start example does not need to import `Decimal`.
67
117
 
68
- Install the latest release from PyPI:
118
+ ## Choosing the right API
69
119
 
70
- ```bash
71
- python -m pip install numbr
72
- ```
120
+ | Goal | API | Result |
121
+ |---|---|---|
122
+ | Identify how one value is written | `Type(value)` | A representation name such as `"Ordinal Word"`, or `None` |
123
+ | Convert one value | `Cast(value, target)` | The value in the requested representation |
124
+ | Collect only values from text | `extractNumericValue(text)` | A list of normalized `int` or `Decimal` values |
125
+ | Collect values and source details | `extractNumericEntities(text)` | A list of `NumericMatch` records with text, type, value, and position |
126
+ | Rewrite numbers inside text | `normalizeNumericText(text)` | A new string with recognized expressions normalized |
127
+ | Explain why parsing failed | `diagnoseNumeric(value)` | A `ParseResult` containing either a value or structured diagnostics |
128
+ | Convert many inputs | `batchCast(values, target)` | A list of converted values using the selected error policy |
129
+ | Diagnose many inputs | `batchDiagnose(values, target)` | One index-stable `ParseResult` per input |
73
130
 
74
- Or install the current development version from GitHub:
131
+ Conversion operates on one numeric value. Extraction searches a larger string
132
+ and returns the numbers it contains. Normalization also searches a larger
133
+ string, but returns rewritten text instead of match records.
75
134
 
76
- ```bash
77
- python -m pip install 'numbr @ git+ssh://git@github.com/doydl-technologies/numbr.git'
135
+ ## Exact decimal values
136
+
137
+ Decimal parsing returns [`decimal.Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal)
138
+ instead of `float`. `Decimal` is part of Python's standard library; it is not an
139
+ additional dependency. This avoids binary floating-point rounding and preserves
140
+ meaningful fractional zeros such as the final zero in `"1.050"`.
141
+
142
+ No `Decimal` import is required when the input is a string:
143
+
144
+ ```python
145
+ import numbr
146
+
147
+ value = numbr.Cast("1.050", "Decimal Number")
148
+
149
+ value
150
+ # Decimal("1.050")
151
+
152
+ numbr.Cast(value, "Cardinal Word")
153
+ # "one point zero five zero"
78
154
  ```
79
155
 
80
- Python 3.13 is required. The package has no runtime dependencies.
156
+ Import `Decimal` only when application code needs to construct a decimal value
157
+ directly or perform decimal arithmetic:
158
+
159
+ ```python
160
+ from decimal import Decimal
161
+
162
+ import numbr
163
+
164
+ numbr.decimalToAccounting(Decimal("-1234.50"), currency="$")
165
+ # "($1,234.50)"
166
+ ```
81
167
 
82
168
  ## Representations
83
169
 
84
- | Representation | Examples | `Type` result |
85
- |---|---|---|
86
- | Cardinal number | `42`, `"-42"` | `"Cardinal Number"` |
87
- | Decimal number | `"1.05"`, `Decimal("1.050")` | `"Decimal Number"` |
88
- | Scientific number | `"1.20e3"`, `"-4E-2"` | `"Scientific Number"` |
89
- | Accounting number | `"(1,234.50)"`, `"($50.00)"` | `"Accounting Number"` |
90
- | Cardinal word | `"forty-two"` | `"Cardinal Word"` |
91
- | Ordinal number | `"42nd"` | `"Ordinal Number"` |
92
- | Ordinal word | `"forty-second"` | `"Ordinal Word"` |
93
- | Roman numeral | `"XLII"`, `"Ⅳ"` | `"Roman Numeral"` |
170
+ | Representation | Meaning | Examples | `Type` result |
171
+ |---|---|---|---|
172
+ | Cardinal number | A whole-number quantity written with digits | `42`, `"-42"` | `"Cardinal Number"` |
173
+ | Decimal number | A fixed-point value with a fractional part | `"1.05"`, `Decimal("1.050")` | `"Decimal Number"` |
174
+ | Scientific number | A coefficient multiplied by a power of ten | `"1.20e3"`, `"-4E-2"` | `"Scientific Number"` |
175
+ | Accounting number | A formatted business value whose parentheses indicate a negative amount | `"(1,234.50)"`, `"($50.00)"` | `"Accounting Number"` |
176
+ | Cardinal word | A quantity written with English words | `"forty-two"` | `"Cardinal Word"` |
177
+ | Ordinal number | A position or rank written with digits and a suffix | `"42nd"` | `"Ordinal Number"` |
178
+ | Ordinal word | A position or rank written with English words | `"forty-second"` | `"Ordinal Word"` |
179
+ | Roman numeral | A value written with Roman symbols | `"XLII"`, `"Ⅳ"` | `"Roman Numeral"` |
94
180
 
95
181
  Decimal phrases such as `"one point zero five"` are cardinal-word forms. Digits
96
182
  following `point` are interpreted individually so precision and trailing zeros
97
183
  are preserved.
98
184
 
185
+ English-word parsing is intended for numeric expressions, not unrestricted
186
+ natural-language interpretation. Surrounding prose should be passed to an
187
+ extraction or normalization API rather than directly to `Type` or `Cast`.
188
+
99
189
  `Cast` accepts the display names and common aliases such as `int`, `decimal`,
100
190
  `scientific`, `accounting`, `cardword`, `ordnum`, and `roman`.
101
191
 
@@ -49,27 +49,27 @@ a long-lived PyPI API token to the repository.
49
49
  source .release-venv/Scripts/activate
50
50
  python -m pip install dist/*.whl
51
51
  cd /tmp
52
- python -I -c "import numbr; assert numbr.__version__ == '3.0.0'; assert numbr.Cast('Ⅳ', 'Ordinal Word') == 'fourth'"
52
+ python -I -c "import numbr; assert numbr.__version__ == '3.2.3'; assert numbr.Cast('Ⅳ', 'Ordinal Word') == 'fourth'"
53
53
  ```
54
54
 
55
55
  6. Review the wheel and source archive contents. Commit the release changes and
56
56
  merge them into `main` only after all required checks pass.
57
57
 
58
- ## Publish 3.0.0
58
+ ## Publish 3.2.3
59
59
 
60
60
  1. On GitHub, draft a new release targeting `main`.
61
- 2. Create tag `v3.0.0` and use release title `v3.0.0`.
62
- 3. Use the approved `v3.0.0` release notes and reconcile them with the canonical
61
+ 2. Create tag `v3.2.3` and use release title `v3.2.3`.
62
+ 3. Use the approved `v3.2.3` release notes and reconcile them with the canonical
63
63
  changelog.
64
64
  4. Save a draft if more review is needed. Publishing the release is the point
65
65
  of no return: it triggers `.github/workflows/publish.yml`.
66
- 5. Confirm that the workflow built both `numbr-3.0.0.tar.gz` and
67
- `numbr-3.0.0-py3-none-any.whl`, validated the tag/version match, and published
66
+ 5. Confirm that the workflow built both `numbr-3.2.3.tar.gz` and
67
+ `numbr-3.2.3-py3-none-any.whl`, validated the tag/version match, and published
68
68
  through the `pypi` environment.
69
69
  6. Confirm the new release on PyPI and install it in a fresh environment:
70
70
 
71
71
  ```bash
72
- python -m pip install --no-cache-dir numbr==3.0.0
72
+ python -m pip install --no-cache-dir numbr==3.2.3
73
73
  python -c "import numbr; print(numbr.__version__)"
74
74
  ```
75
75
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "numbr"
7
- version = "3.0.0"
7
+ version = "3.2.3"
8
8
  description = "Parse, diagnose, batch-convert, extract, and normalize English numbers, exact decimals, scientific and accounting notation, and Roman numerals."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13,<3.14"
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
File without changes