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.
- {numbr-3.0.0 → numbr-3.2.3}/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
- {numbr-3.0.0 → numbr-3.2.3}/.github/workflows/ci.yml +1 -1
- {numbr-3.0.0 → numbr-3.2.3}/PKG-INFO +124 -34
- {numbr-3.0.0 → numbr-3.2.3}/README.md +123 -33
- {numbr-3.0.0 → numbr-3.2.3}/RELEASING.md +7 -7
- {numbr-3.0.0 → numbr-3.2.3}/pyproject.toml +1 -1
- {numbr-3.0.0 → numbr-3.2.3}/.gitattributes +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/.github/pull_request_template.md +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/.github/release.yml +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/.github/workflows/codeql.yml +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/.github/workflows/publish.yml +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/.gitignore +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/CHANGELOG.md +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/CODE_OF_CONDUCT.md +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/CONTRIBUTING.md +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/LICENSE +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/SECURITY.md +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/assets/png/numbr-lockup-endorsed-1118x344.png +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/assets/png/organization/author-lock-up.png +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/assets/png/organization/author-mark.png +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/assets/png/organization/author-wordmark.png +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/src/numbr/__init__.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/src/numbr/engine.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_cardinals.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_decimals.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_diagnostics_and_batch.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_extraction.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_notation_and_normalization.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_ordinals.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_public_api.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_roman.py +0 -0
- {numbr-3.0.0 → numbr-3.2.3}/tests/test_structured_extraction.py +0 -0
|
@@ -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.
|
|
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.
|
|
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
|
-
|
|
61
|
-
from decimal import Decimal
|
|
64
|
+
## What numbr does
|
|
62
65
|
|
|
63
|
-
|
|
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
|
|
66
|
-
# 167
|
|
76
|
+
With `numbr`, an application can:
|
|
67
77
|
|
|
68
|
-
|
|
69
|
-
|
|
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.
|
|
72
|
-
|
|
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
|
-
|
|
75
|
-
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
Install the latest release from PyPI:
|
|
76
93
|
|
|
77
|
-
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
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
|
-
|
|
146
|
+
## Choosing the right API
|
|
97
147
|
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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
|
-
|
|
33
|
-
from decimal import Decimal
|
|
36
|
+
## What numbr does
|
|
34
37
|
|
|
35
|
-
|
|
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
|
|
38
|
-
# 167
|
|
48
|
+
With `numbr`, an application can:
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
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.
|
|
44
|
-
|
|
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
|
-
|
|
47
|
-
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
Install the latest release from PyPI:
|
|
48
65
|
|
|
49
|
-
|
|
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
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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
|
-
|
|
118
|
+
## Choosing the right API
|
|
69
119
|
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
58
|
+
## Publish 3.2.3
|
|
59
59
|
|
|
60
60
|
1. On GitHub, draft a new release targeting `main`.
|
|
61
|
-
2. Create tag `v3.
|
|
62
|
-
3. Use the approved `v3.
|
|
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.
|
|
67
|
-
`numbr-3.
|
|
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.
|
|
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.
|
|
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
|
|
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
|