Codebase list python-humanize / 8135878
Update upstream source from tag 'upstream/4.4.0' Update to upstream version '4.4.0' with Debian dir 103707c6999ada5e09e3dc7b0d470dbc4a2c8247 Sylvestre Ledru 1 year, 7 months ago
27 changed file(s) with 676 addition(s) and 174 deletion(s). Raw diff Collapse all Expand all
+0
-1
.github/FUNDING.md less more
0 tidelift: "pypi/humanize"
0 github: hugovk
1 tidelift: "pypi/humanize"
+0
-20
.github/dependabot.yml less more
0 version: 2
1 updates:
2 - package-ecosystem: github-actions
3 directory: "/"
4 schedule:
5 interval: monthly
6 time: "03:00"
7 open-pull-requests-limit: 10
8 labels:
9 - "changelog: skip"
10 - "dependencies"
11 - package-ecosystem: pip
12 directory: "/"
13 schedule:
14 interval: monthly
15 time: "03:00"
16 open-pull-requests-limit: 10
17 labels:
18 - "changelog: skip"
19 - "dependencies"
0 {
1 "$schema": "https://docs.renovatebot.com/renovate-schema.json",
2 "extends": ["config:base"],
3 "labels": ["changelog: skip", "dependencies"],
4 "packageRules": [
5 {
6 "groupName": "github-actions",
7 "matchManagers": ["github-actions"],
8 "separateMajorMinor": "false"
9 }
10 ],
11 "schedule": ["on the first day of the month"]
12 }
99 - uses: actions/checkout@v3
1010
1111 - name: Set up Python
12 uses: actions/setup-python@v3
12 uses: actions/setup-python@v4
1313 with:
1414 python-version: "3.x"
1515 cache: pip
77
88 steps:
99 - uses: actions/checkout@v3
10 - uses: actions/setup-python@v3
11 - uses: pre-commit/action@v2.0.3
10 - uses: actions/setup-python@v4
11 with:
12 python-version: "3.x"
13 - uses: pre-commit/action@v3.0.0
88 runs-on: ubuntu-latest
99
1010 steps:
11 - uses: mheap/github-action-required-labels@v1
11 - uses: mheap/github-action-required-labels@v2
1212 with:
1313 mode: minimum
1414 count: 1
1717 - uses: actions/checkout@v3
1818
1919 - name: Set up Python ${{ matrix.python-version }}
20 uses: actions/setup-python@v3
20 uses: actions/setup-python@v4
2121 with:
2222 python-version: ${{ matrix.python-version }}
2323 cache: pip
00 repos:
11 - repo: https://github.com/asottile/pyupgrade
2 rev: v2.32.0
2 rev: v2.37.3
33 hooks:
44 - id: pyupgrade
55 args: [--py37-plus]
66
77 - repo: https://github.com/psf/black
8 rev: 22.3.0
8 rev: 22.6.0
99 hooks:
1010 - id: black
1111 args: [--target-version=py37]
3030 files: \.py$
3131
3232 - repo: https://github.com/PyCQA/flake8
33 rev: 4.0.1
33 rev: 5.0.4
3434 hooks:
3535 - id: flake8
3636 additional_dependencies: [flake8-2020, flake8-implicit-str-concat]
4141 - id: python-check-blanket-noqa
4242
4343 - repo: https://github.com/pre-commit/pre-commit-hooks
44 rev: v4.2.0
44 rev: v4.3.0
4545 hooks:
46 - id: check-json
4647 - id: check-merge-conflict
4748 - id: check-toml
4849 - id: check-yaml
5657 files: "src/"
5758
5859 - repo: https://github.com/pre-commit/mirrors-mypy
59 rev: v0.942
60 rev: v0.971
6061 hooks:
6162 - id: mypy
6263 additional_dependencies: [pytest, types-freezegun, types-setuptools]
6364 args: [--strict]
6465
6566 - repo: https://github.com/asottile/setup-cfg-fmt
66 rev: v1.20.1
67 rev: v2.0.0
6768 hooks:
6869 - id: setup-cfg-fmt
69 args: [--max-py-version=3.11]
70 args: [--max-py-version=3.11, --include-version-classifiers]
7071
7172 - repo: https://github.com/tox-dev/pyproject-fmt
72 rev: 0.3.3
73 rev: 0.3.5
7374 hooks:
7475 - id: pyproject-fmt
7576
00 Metadata-Version: 2.1
11 Name: humanize
2 Version: 4.2.3
2 Version: 4.4.0
33 Summary: Python humanize utilities
44 Home-page: https://github.com/python-humanize/humanize
55 Author: Jason Moiron
5858 - Finnish
5959 - French
6060 - German
61 - Greek
6162 - Indonesian
6263 - Italian
6364 - Japanese
8081
8182 <!-- usage-start -->
8283
84 ## Installation
85
86 ### From PyPI
87
88 ```bash
89 python3 -m pip install --upgrade humanize
90 ```
91
92 ### From source
93
94 ```bash
95 git clone https://github.com/python-humanize/humanize
96 cd humanize
97 python3 -m pip install -e .
98 ```
99
83100 ## Usage
84101
85102 ### Integer humanization
242259
243260 How to add new phrases to existing locale files:
244261
245 ```console
246 $ xgettext --from-code=UTF-8 -o humanize.pot -k'_' -k'N_' -k'P_:1c,2' -l python src/humanize/*.py # extract new phrases
247 $ msgmerge -U src/humanize/locale/ru_RU/LC_MESSAGES/humanize.po humanize.pot # add them to locale files
262 ```sh
263 xgettext --from-code=UTF-8 -o humanize.pot -k'_' -k'N_' -k'P_:1c,2' -l python src/humanize/*.py # extract new phrases
264 msgmerge -U src/humanize/locale/ru_RU/LC_MESSAGES/humanize.po humanize.pot # add them to locale files
248265 ```
249266
250267 How to add a new locale:
251268
252 ```console
253 $ msginit -i humanize.pot -o humanize/locale/<locale name>/LC_MESSAGES/humanize.po --locale <locale name>
269 ```sh
270 msginit -i humanize.pot -o humanize/locale/<locale name>/LC_MESSAGES/humanize.po --locale <locale name>
254271 ```
255272
256273 Where `<locale name>` is a locale abbreviation, eg. `en_GB`, `pt_BR` or just `ru`, `fr`
2222 - Finnish
2323 - French
2424 - German
25 - Greek
2526 - Indonesian
2627 - Italian
2728 - Japanese
4445
4546 <!-- usage-start -->
4647
48 ## Installation
49
50 ### From PyPI
51
52 ```bash
53 python3 -m pip install --upgrade humanize
54 ```
55
56 ### From source
57
58 ```bash
59 git clone https://github.com/python-humanize/humanize
60 cd humanize
61 python3 -m pip install -e .
62 ```
63
4764 ## Usage
4865
4966 ### Integer humanization
206223
207224 How to add new phrases to existing locale files:
208225
209 ```console
210 $ xgettext --from-code=UTF-8 -o humanize.pot -k'_' -k'N_' -k'P_:1c,2' -l python src/humanize/*.py # extract new phrases
211 $ msgmerge -U src/humanize/locale/ru_RU/LC_MESSAGES/humanize.po humanize.pot # add them to locale files
226 ```sh
227 xgettext --from-code=UTF-8 -o humanize.pot -k'_' -k'N_' -k'P_:1c,2' -l python src/humanize/*.py # extract new phrases
228 msgmerge -U src/humanize/locale/ru_RU/LC_MESSAGES/humanize.po humanize.pot # add them to locale files
212229 ```
213230
214231 How to add a new locale:
215232
216 ```console
217 $ msginit -i humanize.pot -o humanize/locale/<locale name>/LC_MESSAGES/humanize.po --locale <locale name>
233 ```sh
234 msginit -i humanize.pot -o humanize/locale/<locale name>/LC_MESSAGES/humanize.po --locale <locale name>
218235 ```
219236
220237 Where `<locale name>` is a locale abbreviation, eg. `en_GB`, `pt_BR` or just `ru`, `fr`
2121 pip install -U pip build keyring twine
2222 rm -rf build dist
2323 python -m build
24 twine check --strict dist/* && twine upload --repository-url https://test.pypi.org/legacy/ dist/*
24 twine check --strict dist/* && twine upload --repository testpypi dist/*
2525 ```
2626
2727 - [ ] (Optional) Check **test** installation:
4444 pip install -U pip build keyring twine
4545 rm -rf build dist
4646 python -m build
47 twine check --strict dist/* && twine upload -r pypi dist/*
47 twine check --strict dist/* && twine upload --repository pypi dist/*
4848 ```
4949
5050 * [ ] Check installation:
0 mkdocs>=1.1
0 mkdocs==1.3.1
11 mkdocs-material
2 mkdocstrings[python]>=0.18
2 mkdocstrings[python]==0.19.0
33 mkdocs-include-markdown-plugin
44 pygments
5 pymdown-extensions>=9.2
5 pymdown-extensions==9.5
00 """Main package for humanize."""
11
22 from humanize.filesize import naturalsize
3 from humanize.i18n import activate, deactivate, thousands_separator
3 from humanize.i18n import activate, deactivate, decimal_separator, thousands_separator
44 from humanize.number import (
55 apnumber,
66 clamp,
3535 "apnumber",
3636 "clamp",
3737 "deactivate",
38 "decimal_separator",
3839 "fractional",
3940 "intcomma",
4041 "intword",
5959
6060 if abs_bytes == 1 and not gnu:
6161 return "%d Byte" % bytes_
62 elif abs_bytes < base and not gnu:
62
63 if abs_bytes < base and not gnu:
6364 return "%d Bytes" % bytes_
64 elif abs_bytes < base and gnu:
65
66 if abs_bytes < base and gnu:
6567 return "%dB" % bytes_
6668
6769 for i, s in enumerate(suffix):
6870 unit = base ** (i + 2)
71
6972 if abs_bytes < unit and not gnu:
7073 return (format + " %s") % ((base * bytes_ / unit), s)
71 elif abs_bytes < unit and gnu:
74
75 if abs_bytes < unit and gnu:
7276 return (format + "%s") % ((base * bytes_ / unit), s)
77
7378 if gnu:
7479 return (format + "%s") % ((base * bytes_ / unit), s)
7580 return (format + " %s") % ((base * bytes_ / unit), s)
44 import os.path
55 from threading import local
66
7 __all__ = ["activate", "deactivate", "thousands_separator"]
7 __all__ = ["activate", "deactivate", "decimal_separator", "thousands_separator"]
88
99 _TRANSLATIONS: dict[str | None, gettext_module.NullTranslations] = {
1010 None: gettext_module.NullTranslations()
1414
1515 # Mapping of locale to thousands separator
1616 _THOUSANDS_SEPARATOR = {
17 "de_DE": ".",
1718 "fr_FR": " ",
19 }
20
21 # Mapping of locale to decimal separator
22 _DECIMAL_SEPARATOR = {
23 "de_DE": ",",
1824 }
1925
2026
171177 except (AttributeError, KeyError):
172178 sep = ","
173179 return sep
180
181
182 def decimal_separator() -> str:
183 """Return the decimal separator for a locale, default to dot.
184
185 Returns:
186 str: Decimal separator.
187 """
188 try:
189 sep = _DECIMAL_SEPARATOR[_CURRENT.locale]
190 except (AttributeError, KeyError):
191 sep = "."
192 return sep
0 # Greek translations for PACKAGE package.
1 # Copyright (C) 2022 THE PACKAGE'S COPYRIGHT HOLDER
2 # This file is distributed under the same license as the PACKAGE package.
3 # Isaak Tsalicoglou <isaak@waseigo.com>, 2022.
4 #
5 msgid ""
6 msgstr ""
7 "Project-Id-Version: humanize\n"
8 "Report-Msgid-Bugs-To: \n"
9 "POT-Creation-Date: 2022-08-05 01:06+0300\n"
10 "PO-Revision-Date: 2022-08-05 01:09+0300\n"
11 "Last-Translator: Isaak Tsalicoglou <isaak@waseigo.com>\n"
12 "Language-Team: Greek <team@lists.gnome.gr>\n"
13 "Language: el\n"
14 "MIME-Version: 1.0\n"
15 "Content-Type: text/plain; charset=utf-8\n"
16 "Content-Transfer-Encoding: 8bit\n"
17 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
18 "Generated-By: Isaak Tsalicoglou\n"
19 "X-Generator: Mousepad 0.5.9\n"
20
21 #: src/humanize/number.py:71
22 msgctxt "0 (male)"
23 msgid "ος"
24 msgstr "."
25
26 #: src/humanize/number.py:72
27 msgctxt "1 (male)"
28 msgid "ος"
29 msgstr "."
30
31 #: src/humanize/number.py:73
32 msgctxt "2 (male)"
33 msgid "ος"
34 msgstr "."
35
36 #: src/humanize/number.py:74
37 msgctxt "3 (male)"
38 msgid "ος"
39 msgstr "."
40
41 #: src/humanize/number.py:75
42 msgctxt "4 (male)"
43 msgid "ος"
44 msgstr "."
45
46 #: src/humanize/number.py:76
47 msgctxt "5 (male)"
48 msgid "ος"
49 msgstr "."
50
51 #: src/humanize/number.py:77
52 msgctxt "6 (male)"
53 msgid "ος"
54 msgstr "."
55
56 #: src/humanize/number.py:78
57 msgctxt "7 (male)"
58 msgid "ος"
59 msgstr "."
60
61 #: src/humanize/number.py:79
62 msgctxt "8 (male)"
63 msgid "ος"
64 msgstr "."
65
66 #: src/humanize/number.py:80
67 msgctxt "9 (male)"
68 msgid "ος"
69 msgstr "."
70
71 #: src/humanize/number.py:84
72 msgctxt "0 (female)"
73 msgid "η"
74 msgstr "."
75
76 #: src/humanize/number.py:85
77 msgctxt "1 (female)"
78 msgid "η"
79 msgstr "."
80
81 #: src/humanize/number.py:86
82 msgctxt "2 (female)"
83 msgid "η"
84 msgstr "."
85
86 #: src/humanize/number.py:87
87 msgctxt "3 (female)"
88 msgid "η"
89 msgstr "."
90
91 #: src/humanize/number.py:88
92 msgctxt "4 (female)"
93 msgid "η"
94 msgstr "."
95
96 #: src/humanize/number.py:89
97 msgctxt "5 (female)"
98 msgid "η"
99 msgstr "."
100
101 #: src/humanize/number.py:90
102 msgctxt "6 (female)"
103 msgid "η"
104 msgstr "."
105
106 #: src/humanize/number.py:91
107 msgctxt "7 (female)"
108 msgid "η"
109 msgstr "."
110
111 #: src/humanize/number.py:92
112 msgctxt "8 (female)"
113 msgid "η"
114 msgstr "."
115
116 #: src/humanize/number.py:93
117 msgctxt "9 (female)"
118 msgid "η"
119 msgstr "."
120
121 #: src/humanize/number.py:140
122 msgid "thousand"
123 msgid_plural "thousand"
124 msgstr[0] "χιλιάδα"
125 msgstr[1] "χιλιάδες"
126
127 #: src/humanize/number.py:141
128 msgid "million"
129 msgid_plural "million"
130 msgstr[0] "εκατομμύριο"
131 msgstr[1] "εκατομμύρια"
132
133 #: src/humanize/number.py:142
134 msgid "billion"
135 msgid_plural "billion"
136 msgstr[0] "δισεκατομμύριο"
137 msgstr[1] "δισεκατομμύρια"
138
139 #: src/humanize/number.py:143
140 msgid "trillion"
141 msgid_plural "trillion"
142 msgstr[0] "τρισεκατομμύριο"
143 msgstr[1] "τρισεκατομμύρια"
144
145 #: src/humanize/number.py:144
146 msgid "quadrillion"
147 msgid_plural "quadrillion"
148 msgstr[0] "τετράκις εκατομμύριο"
149 msgstr[1] "τετράκις εκατομμύρια"
150
151 #: src/humanize/number.py:145
152 msgid "quintillion"
153 msgid_plural "quintillion"
154 msgstr[0] "πεντάκις εκατομμύριο"
155 msgstr[1] "πεντάκις εκατομμύρια"
156
157 #: src/humanize/number.py:146
158 msgid "sextillion"
159 msgid_plural "sextillion"
160 msgstr[0] "εξάκις εκατομμύριο"
161 msgstr[1] "εξάκις εκατομμύρια"
162
163 #: src/humanize/number.py:147
164 msgid "septillion"
165 msgid_plural "septillion"
166 msgstr[0] "επτάκις εκατομμύριο"
167 msgstr[1] "επτάκις εκατομμύρια"
168
169 #: src/humanize/number.py:148
170 msgid "octillion"
171 msgid_plural "octillion"
172 msgstr[0] "οκτάκις εκατομμύριο"
173 msgstr[1] "οκτάκις εκατομμύρια"
174
175 #: src/humanize/number.py:149
176 msgid "nonillion"
177 msgid_plural "nonillion"
178 msgstr[0] "εννεάκις εκατομμύριο"
179 msgstr[1] "εννεάκις εκατομμύρια"
180
181 #: src/humanize/number.py:150
182 msgid "decillion"
183 msgid_plural "decillion"
184 msgstr[0] "δεκάκις εκατομμύριο"
185 msgstr[1] "δεκάκις εκατομμύρια"
186
187 #: src/humanize/number.py:151
188 msgid "googol"
189 msgid_plural "googol"
190 msgstr[0] "δέκα τριακονταδυάκις εκατομμύριο"
191 msgstr[1] "δέκα τριακονταδυάκις εκατομμύρια"
192
193 #: src/humanize/number.py:246
194 msgid "zero"
195 msgstr "μηδέν"
196
197 #: src/humanize/number.py:275
198 msgid "one"
199 msgstr "ένα"
200
201 #: src/humanize/number.py:276
202 msgid "two"
203 msgstr "δύο"
204
205 #: src/humanize/number.py:277
206 msgid "three"
207 msgstr "τρία"
208
209 #: src/humanize/number.py:278
210 msgid "four"
211 msgstr "τέσσερα"
212
213 #: src/humanize/number.py:279
214 msgid "five"
215 msgstr "πέντε"
216
217 #: src/humanize/number.py:280
218 msgid "six"
219 msgstr "έξι"
220
221 #: src/humanize/number.py:281
222 msgid "seven"
223 msgstr "επτά"
224
225 #: src/humanize/number.py:254
226 msgid "eight"
227 msgstr "οκτώ"
228
229 #: src/humanize/number.py:255
230 msgid "nine"
231 msgstr "εννέα"
232
233 #: src/humanize/time.py:133
234 #, fuzzy, python-format
235 msgid "%d microsecond"
236 msgid_plural "%d microseconds"
237 msgstr[0] "%d εκατομμυριοστό του δευτερολέπτου"
238 msgstr[1] "%d εκατομμυριοστά του δευτερολέπτου"
239
240 #: src/humanize/time.py:142
241 #, fuzzy, python-format
242 msgid "%d millisecond"
243 msgid_plural "%d milliseconds"
244 msgstr[0] "%d χιλιοστό του δευτερολέπτου"
245 msgstr[1] "%d χιλιοστά του δευτερολέπτου"
246
247 #: src/humanize/time.py:145 src/humanize/time.py:220
248 msgid "a moment"
249 msgstr "μια στιγμή"
250
251 #: src/humanize/time.py:147
252 msgid "a second"
253 msgstr "ένα δευτερόλεπτο"
254
255 #: src/humanize/time.py:149
256 #, python-format
257 msgid "%d second"
258 msgid_plural "%d seconds"
259 msgstr[0] "%d δευτερόλεπτο"
260 msgstr[1] "%d δευτερόλεπτα"
261
262 #: src/humanize/time.py:151
263 msgid "a minute"
264 msgstr "ένα λεπτό"
265
266 #: src/humanize/time.py:154
267 #, python-format
268 msgid "%d minute"
269 msgid_plural "%d minutes"
270 msgstr[0] "%d λεπτό"
271 msgstr[1] "%d λεπτά"
272
273 #: src/humanize/time.py:156
274 msgid "an hour"
275 msgstr "μία ώρα"
276
277 #: src/humanize/time.py:159
278 #, python-format
279 msgid "%d hour"
280 msgid_plural "%d hours"
281 msgstr[0] "%d ώρα"
282 msgstr[1] "%d ώρες"
283
284 #: src/humanize/time.py:162
285 msgid "a day"
286 msgstr "μία ημέρα"
287
288 #: src/humanize/time.py:164 src/humanize/time.py:167
289 #, python-format
290 msgid "%d day"
291 msgid_plural "%d days"
292 msgstr[0] "%d ημέρα"
293 msgstr[1] "%d ημέρες"
294
295 #: src/humanize/time.py:169
296 msgid "a month"
297 msgstr "ένα μήνα"
298
299 #: src/humanize/time.py:171
300 #, python-format
301 msgid "%d month"
302 msgid_plural "%d months"
303 msgstr[0] "%d μήνα"
304 msgstr[1] "%d μήνες"
305
306 #: src/humanize/time.py:174
307 msgid "a year"
308 msgstr "ένα έτος"
309
310 #: src/humanize/time.py:176 src/humanize/time.py:185
311 #, python-format
312 msgid "1 year, %d day"
313 msgid_plural "1 year, %d days"
314 msgstr[0] "ένα έτος και %d ημέρα"
315 msgstr[1] "ένα έτος και %d ημέρες"
316
317 #: src/humanize/time.py:179
318 msgid "1 year, 1 month"
319 msgstr "ένα έτος και ένα μήνα"
320
321 #: src/humanize/time.py:182
322 #, python-format
323 msgid "1 year, %d month"
324 msgid_plural "1 year, %d months"
325 msgstr[0] "ένα έτος και %d μήνα"
326 msgstr[1] "ένα έτος και %d μήνες"
327
328 #: src/humanize/time.py:187
329 #, python-format
330 msgid "%d year"
331 msgid_plural "%d years"
332 msgstr[0] "%d έτος"
333 msgstr[1] "%d έτη"
334
335 #: src/humanize/time.py:217
336 #, python-format
337 msgid "%s from now"
338 msgstr "σε %s από τώρα"
339
340 #: src/humanize/time.py:242
341 #, python-format
342 msgid "%s ago"
343 msgstr "πριν από %s"
344
345 #: src/humanize/time.py:246
346 msgid "now"
347 msgstr "τώρα"
348
349 #: src/humanize/time.py:269
350 msgid "today"
351 msgstr "σήμερα"
352
353 #: src/humanize/time.py:271
354 msgid "tomorrow"
355 msgstr "αύριο"
356
357 #: src/humanize/time.py:273
358 msgid "yesterday"
359 msgstr "χθες"
360
361 #: src/humanize/time.py:581
362 #, python-format
363 msgid "%s and %s"
364 msgstr "%s και %s"
22 # This file is distributed under the same license as the PACKAGE package.
33 # Bartosz Bubak <bartosz.bubak@gmail.com>, 2020.
44 # Added missing strings by Krystian Postek <krystian postek eu>, 2020.
5 # Replace short scale with long scale by Maciej J. Mikulski (mjmikulski), 2022.
56 #
67 msgid ""
78 msgstr ""
121122 #: src/humanize/number.py:140
122123 msgid "thousand"
123124 msgid_plural "thousand"
124 msgstr[0] ""
125 msgstr[1] ""
126 msgstr[2] ""
125 msgstr[0] "tysiąc"
126 msgstr[1] "tysiąc"
127 msgstr[2] "tysięcy"
127128
128129 #: src/humanize/number.py:141
129130 msgid "million"
130131 msgid_plural "million"
131132 msgstr[0] "milion"
132 msgstr[1] "milion"
133 msgstr[2] "milion"
133 msgstr[1] "miliony"
134 msgstr[2] "milionów"
134135
135136 #: src/humanize/number.py:142
136137 msgid "billion"
137138 msgid_plural "billion"
138 msgstr[0] "bilion"
139 msgstr[1] "bilion"
140 msgstr[2] "bilion"
139 msgstr[0] "miliard"
140 msgstr[1] "miliardy"
141 msgstr[2] "miliardów"
141142
142143 #: src/humanize/number.py:143
143144 msgid "trillion"
144145 msgid_plural "trillion"
145 msgstr[0] "trylion"
146 msgstr[1] "trylion"
147 msgstr[2] "trylion"
146 msgstr[0] "bilion"
147 msgstr[1] "biliony"
148 msgstr[2] "bilionów"
148149
149150 #: src/humanize/number.py:144
150151 msgid "quadrillion"
151152 msgid_plural "quadrillion"
152 msgstr[0] "kwadrylion"
153 msgstr[1] "kwadrylion"
154 msgstr[2] "kwadrylion"
153 msgstr[0] "biliard"
154 msgstr[1] "biliardy"
155 msgstr[2] "biliardów"
155156
156157 #: src/humanize/number.py:145
157158 msgid "quintillion"
158159 msgid_plural "quintillion"
159 msgstr[0] "kwintylion"
160 msgstr[1] "kwintylion"
161 msgstr[2] "kwintylion"
160 msgstr[0] "trylion"
161 msgstr[1] "tryliony"
162 msgstr[2] "trylionów"
162163
163164 #: src/humanize/number.py:146
164165 msgid "sextillion"
165166 msgid_plural "sextillion"
166 msgstr[0] "sekstylion"
167 msgstr[1] "sekstylion"
168 msgstr[2] "sekstylion"
167 msgstr[0] "tryliard"
168 msgstr[1] "tryliard"
169 msgstr[2] "tryliard"
169170
170171 #: src/humanize/number.py:147
171172 msgid "septillion"
172173 msgid_plural "septillion"
173 msgstr[0] "septylion"
174 msgstr[1] "septylion"
175 msgstr[2] "septylion"
174 msgstr[0] "kwadrylion"
175 msgstr[1] "kwadryliony"
176 msgstr[2] "kwadrylionów"
176177
177178 #: src/humanize/number.py:148
178179 msgid "octillion"
179180 msgid_plural "octillion"
180 msgstr[0] "oktylion"
181 msgstr[1] "oktylion"
182 msgstr[2] "oktylion"
181 msgstr[0] "kwadryliard"
182 msgstr[1] "kwadryliardy"
183 msgstr[2] "kwadryliardów"
183184
184185 #: src/humanize/number.py:149
185186 msgid "nonillion"
186187 msgid_plural "nonillion"
187 msgstr[0] "nonilion"
188 msgstr[1] "nonilion"
189 msgstr[2] "nonilion"
188 msgstr[0] "kwintylion"
189 msgstr[1] "kwintyliony"
190 msgstr[2] "kwintylionów"
190191
191192 #: src/humanize/number.py:150
192193 msgid "decillion"
193194 msgid_plural "decillion"
194 msgstr[0] "decylion"
195 msgstr[1] "decylion"
196 msgstr[2] "decylion"
195 msgstr[0] "kwintyliard"
196 msgstr[1] "kwintyliardy"
197 msgstr[2] "kwintyliardów"
197198
198199 #: src/humanize/number.py:151
199200 msgid "googol"
200201 msgid_plural "googol"
201202 msgstr[0] "googol"
202 msgstr[1] "googol"
203 msgstr[2] "googol"
203 msgstr[1] "googole"
204 msgstr[2] "googoli"
204205
205206 #: src/humanize/number.py:246
206207 msgid "zero"
351352 msgid "%d year"
352353 msgid_plural "%d years"
353354 msgstr[0] "%d rok"
354 msgstr[1] "%d lat"
355 msgstr[2] "%d lata"
355 msgstr[1] "%d lata"
356 msgstr[2] "%d lat"
356357
357358 #: src/humanize/time.py:217
358359 #, python-format
1212 from .i18n import _ngettext
1313 from .i18n import _ngettext_noop as NS_
1414 from .i18n import _pgettext as P_
15 from .i18n import thousands_separator
15 from .i18n import decimal_separator, thousands_separator
1616
1717 if TYPE_CHECKING:
1818 if sys.version_info >= (3, 10):
116116 '1,234.55'
117117 >>> intcomma(14308.40, 1)
118118 '14,308.4'
119 >>> intcomma("14308.40", 1)
120 '14,308.4'
119121 >>> intcomma(None)
120122 'None'
121123
127129 Returns:
128130 str: String containing commas every three digits.
129131 """
130 sep = thousands_separator()
132 thousands_sep = thousands_separator()
133 decimal_sep = decimal_separator()
131134 try:
132135 if isinstance(value, str):
133 float(value.replace(sep, ""))
136 value = value.replace(thousands_sep, "").replace(decimal_sep, ".")
137 if "." in value:
138 value = float(value)
139 else:
140 value = int(value)
134141 else:
135142 float(value)
136143 except (TypeError, ValueError):
140147 orig = "{0:.{1}f}".format(value, ndigits)
141148 else:
142149 orig = str(value)
143
144 new = re.sub(r"^(-?\d+)(\d{3})", rf"\g<1>{sep}\g<2>", orig)
145 if orig == new:
146 return new
147 else:
148 return intcomma(new)
150 orig = orig.replace(".", decimal_sep)
151 while True:
152 new = re.sub(r"^(-?\d+)(\d{3})", rf"\g<1>{thousands_sep}\g<2>", orig)
153 if orig == new:
154 return new
155 orig = new
149156
150157
151158 powers = [10**x for x in (3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 100)]
204211 except (TypeError, ValueError):
205212 return str(value)
206213
214 if value < 0:
215 value *= -1
216 negative_prefix = "-"
217 else:
218 negative_prefix = ""
219
207220 if value < powers[0]:
208 return str(value)
209 for ordinal, power in enumerate(powers[1:], 1):
221 return negative_prefix + str(value)
222
223 for ordinal_, power in enumerate(powers[1:], 1):
210224 if value < power:
211 chopped = value / float(powers[ordinal - 1])
225 chopped = value / float(powers[ordinal_ - 1])
212226 if float(format % chopped) == float(10**3):
213 chopped = value / float(powers[ordinal])
214 singular, plural = human_powers[ordinal]
227 chopped = value / float(powers[ordinal_])
228 singular, plural = human_powers[ordinal_]
215229 return (
216 " ".join([format, _ngettext(singular, plural, math.ceil(chopped))])
230 negative_prefix
231 + " ".join(
232 [format, _ngettext(singular, plural, math.ceil(chopped))]
233 )
217234 ) % chopped
218 else:
219 singular, plural = human_powers[ordinal - 1]
220 return (
221 " ".join([format, _ngettext(singular, plural, math.ceil(chopped))])
222 ) % chopped
223 return str(value)
235
236 singular, plural = human_powers[ordinal_ - 1]
237 return (
238 negative_prefix
239 + " ".join([format, _ngettext(singular, plural, math.ceil(chopped))])
240 ) % chopped
241
242 return negative_prefix + str(value)
224243
225244
226245 def apnumber(value: NumberOrString) -> str:
320339 # this means that an integer was passed in
321340 # (or variants of that integer like 1.0000)
322341 return f"{whole_number:.0f}"
323 elif not whole_number:
342
343 if not whole_number:
324344 return f"{numerator:.0f}/{denominator:.0f}"
325 else:
326 return f"{whole_number:.0f} {numerator:.0f}/{denominator:.0f}"
345
346 return f"{whole_number:.0f} {numerator:.0f}/{denominator:.0f}"
327347
328348
329349 def scientific(value: NumberOrString, precision: int = 2) -> str:
450470
451471 if isinstance(format, str):
452472 return token + format.format(value)
453 elif callable(format):
473
474 if callable(format):
454475 return token + format(value)
455 else:
456 raise ValueError(
457 "Invalid format. Must be either a valid formatting string, or a function "
458 "that accepts value and returns a string."
459 )
476
477 raise ValueError(
478 "Invalid format. Must be either a valid formatting string, or a function "
479 "that accepts value and returns a string."
480 )
460481
461482
462483 def metric(value: float, unit: str = "", precision: int = 3) -> str:
494515 Returns:
495516 str:
496517 """
497 exponent = int(math.floor(math.log10(abs(value))))
518 exponent = int(math.floor(math.log10(abs(value)))) if value != 0 else 0
498519
499520 if exponent >= 27 or exponent < -24:
500521 return scientific(value, precision - 1) + unit
501522
502523 value /= 10 ** (exponent // 3 * 3)
503524 if exponent >= 3:
504 ordinal = "kMGTPEZY"[exponent // 3 - 1]
525 ordinal_ = "kMGTPEZY"[exponent // 3 - 1]
505526 elif exponent < 0:
506 ordinal = "mμnpfazy"[(-exponent - 1) // 3]
507 else:
508 ordinal = ""
527 ordinal_ = "mμnpfazy"[(-exponent - 1) // 3]
528 else:
529 ordinal_ = ""
509530 value_ = format(value, ".%if" % (precision - (exponent % 3) - 1))
510 if not (unit or ordinal) or unit in ("°", "′", "″"):
531 if not (unit or ordinal_) or unit in ("°", "′", "″"):
511532 space = ""
512533 else:
513534 space = " "
514535
515 return f"{value_}{space}{ordinal}{unit}"
536 return f"{value_}{space}{ordinal_}{unit}"
150150 _ngettext("%d microsecond", "%d microseconds", delta.microseconds)
151151 % delta.microseconds
152152 )
153 elif min_unit == Unit.MILLISECONDS or (
153
154 if min_unit == Unit.MILLISECONDS or (
154155 min_unit == Unit.MICROSECONDS and 1000 <= delta.microseconds < 1_000_000
155156 ):
156157 milliseconds = delta.microseconds / 1000
159160 % milliseconds
160161 )
161162 return _("a moment")
162 elif seconds == 1:
163
164 if seconds == 1:
163165 return _("a second")
164 elif seconds < 60:
166
167 if seconds < 60:
165168 return _ngettext("%d second", "%d seconds", seconds) % seconds
166 elif 60 <= seconds < 120:
169
170 if 60 <= seconds < 120:
167171 return _("a minute")
168 elif 120 <= seconds < 3600:
172
173 if 120 <= seconds < 3600:
169174 minutes = seconds // 60
170175 return _ngettext("%d minute", "%d minutes", minutes) % minutes
171 elif 3600 <= seconds < 3600 * 2:
176
177 if 3600 <= seconds < 3600 * 2:
172178 return _("an hour")
173 elif 3600 < seconds:
179
180 if 3600 < seconds:
174181 hours = seconds // 3600
175182 return _ngettext("%d hour", "%d hours", hours) % hours
183
176184 elif years == 0:
177185 if days == 1:
178186 return _("a day")
187
179188 if not use_months:
180189 return _ngettext("%d day", "%d days", days) % days
181 else:
182 if not num_months:
183 return _ngettext("%d day", "%d days", days) % days
184 elif num_months == 1:
185 return _("a month")
186 else:
187 return _ngettext("%d month", "%d months", num_months) % num_months
190
191 if not num_months:
192 return _ngettext("%d day", "%d days", days) % days
193
194 if num_months == 1:
195 return _("a month")
196
197 return _ngettext("%d month", "%d months", num_months) % num_months
198
188199 elif years == 1:
189200 if not num_months and not days:
190201 return _("a year")
191 elif not num_months:
202
203 if not num_months:
192204 return _ngettext("1 year, %d day", "1 year, %d days", days) % days
193 elif use_months:
205
206 if use_months:
194207 if num_months == 1:
195208 return _("1 year, 1 month")
196 else:
197 return (
198 _ngettext("1 year, %d month", "1 year, %d months", num_months)
199 % num_months
200 )
201 else:
202 return _ngettext("1 year, %d day", "1 year, %d days", days) % days
209
210 return (
211 _ngettext("1 year, %d month", "1 year, %d months", num_months)
212 % num_months
213 )
214
215 return _ngettext("1 year, %d day", "1 year, %d days", days) % days
203216
204217 return _ngettext("%d year", "%d years", years).replace("%d", "%s") % intcomma(years)
205218
264277 # Date arguments out of range
265278 return str(value)
266279 delta = value - dt.date.today()
280
267281 if delta.days == 0:
268282 return _("today")
269 elif delta.days == 1:
283
284 if delta.days == 1:
270285 return _("tomorrow")
271 elif delta.days == -1:
286
287 if delta.days == -1:
272288 return _("yesterday")
289
273290 return value.strftime(format)
274291
275292
322339 """
323340 if unit == minimum_unit:
324341 return value / divisor, 0
325 elif unit in suppress:
342
343 if unit in suppress:
326344 return 0, value
327 else:
328 return divmod(value, divisor)
345
346 return divmod(value, divisor)
329347
330348
331349 def _carry(
360378 """
361379 if unit == min_unit:
362380 return value1 + value2 / ratio, 0
363 elif unit in suppress:
381
382 if unit in suppress:
364383 return 0, value2 + value1 * ratio
365 else:
366 return value1, value2
384
385 return value1, value2
367386
368387
369388 def _suitable_minimum_unit(min_unit: Unit, suppress: typing.Iterable[Unit]) -> Unit:
375394 >>> _suitable_minimum_unit(Unit.HOURS, []).name
376395 'HOURS'
377396
378 But if suppressed, find a unit greather than the original one that is not
397 But if suppressed, find a unit greater than the original one that is not
379398 suppressed:
380399
381400 >>> _suitable_minimum_unit(Unit.HOURS, [Unit.HOURS]).name
404423 ['MICROSECONDS', 'MILLISECONDS', 'DAYS']
405424 """
406425 suppress = set(suppress)
407 for u in Unit:
408 if u == min_unit:
426 for unit in Unit:
427 if unit == min_unit:
409428 break
410 suppress.add(u)
429 suppress.add(unit)
411430
412431 return suppress
413432
414433
415434 def precisedelta(
416 value: dt.timedelta | int,
435 value: dt.timedelta | int | None,
417436 minimum_unit: str = "seconds",
418437 suppress: typing.Iterable[str] = (),
419438 format: str = "%0.2f",
00 Metadata-Version: 2.1
11 Name: humanize
2 Version: 4.2.3
2 Version: 4.4.0
33 Summary: Python humanize utilities
44 Home-page: https://github.com/python-humanize/humanize
55 Author: Jason Moiron
5858 - Finnish
5959 - French
6060 - German
61 - Greek
6162 - Indonesian
6263 - Italian
6364 - Japanese
8081
8182 <!-- usage-start -->
8283
84 ## Installation
85
86 ### From PyPI
87
88 ```bash
89 python3 -m pip install --upgrade humanize
90 ```
91
92 ### From source
93
94 ```bash
95 git clone https://github.com/python-humanize/humanize
96 cd humanize
97 python3 -m pip install -e .
98 ```
99
83100 ## Usage
84101
85102 ### Integer humanization
242259
243260 How to add new phrases to existing locale files:
244261
245 ```console
246 $ xgettext --from-code=UTF-8 -o humanize.pot -k'_' -k'N_' -k'P_:1c,2' -l python src/humanize/*.py # extract new phrases
247 $ msgmerge -U src/humanize/locale/ru_RU/LC_MESSAGES/humanize.po humanize.pot # add them to locale files
262 ```sh
263 xgettext --from-code=UTF-8 -o humanize.pot -k'_' -k'N_' -k'P_:1c,2' -l python src/humanize/*.py # extract new phrases
264 msgmerge -U src/humanize/locale/ru_RU/LC_MESSAGES/humanize.po humanize.pot # add them to locale files
248265 ```
249266
250267 How to add a new locale:
251268
252 ```console
253 $ msginit -i humanize.pot -o humanize/locale/<locale name>/LC_MESSAGES/humanize.po --locale <locale name>
269 ```sh
270 msginit -i humanize.pot -o humanize/locale/<locale name>/LC_MESSAGES/humanize.po --locale <locale name>
254271 ```
255272
256273 Where `<locale name>` is a locale abbreviation, eg. `en_GB`, `pt_BR` or just `ru`, `fr`
1010 setup.py
1111 tox.ini
1212 .github/CONTRIBUTING.md
13 .github/FUNDING.md
13 .github/FUNDING.yml
1414 .github/ISSUE_TEMPLATE.md
1515 .github/PULL_REQUEST_TEMPLATE.md
1616 .github/SECURITY.md
17 .github/dependabot.yml
1817 .github/labels.yml
1918 .github/release-drafter.yml
19 .github/renovate.json
2020 .github/workflows/docs.yml
2121 .github/workflows/labels.yml
2222 .github/workflows/lint.yml
5454 src/humanize/locale/da_DK/LC_MESSAGES/humanize.po
5555 src/humanize/locale/de_DE/LC_MESSAGES/humanize.mo
5656 src/humanize/locale/de_DE/LC_MESSAGES/humanize.po
57 src/humanize/locale/el_GR/LC_MESSAGES/humanize.mo
58 src/humanize/locale/el_GR/LC_MESSAGES/humanize.po
5759 src/humanize/locale/es_ES/LC_MESSAGES/humanize.mo
5860 src/humanize/locale/es_ES/LC_MESSAGES/humanize.po
5961 src/humanize/locale/fa_IR/LC_MESSAGES/humanize.mo
4141 assert humanize.intcomma(number) == "10,000,000"
4242
4343 try:
44 humanize.i18n.activate("de_DE")
45 assert humanize.intcomma(number) == "10.000.000"
46 assert humanize.intcomma(1_234_567.8901) == "1.234.567,8901"
47 assert humanize.intcomma(1_234_567.89) == "1.234.567,89"
48 assert humanize.intcomma("1234567,89") == "1.234.567,89"
49 assert humanize.intcomma("1.234.567,89") == "1.234.567,89"
50 assert humanize.intcomma("1.234.567,8") == "1.234.567,8"
51
4452 humanize.i18n.activate("fr_FR")
4553 assert humanize.intcomma(number) == "10 000 000"
4654
155163 def test_default_locale_path_undefined__file__() -> None:
156164 i18n = importlib.import_module("humanize.i18n")
157165 del i18n.__file__
158 i18n._get_default_locale_path() is None
166 assert i18n._get_default_locale_path() is None
159167
160168
161169 class TestActivate:
4545 (["10311"], "10,311"),
4646 (["1000000"], "1,000,000"),
4747 (["1234567.1234567"], "1,234,567.1234567"),
48 (["1234567.1234567", 0], "1,234,567"),
49 (["1234567.1234567", 1], "1,234,567.1"),
50 (["1234567.1234567", 10], "1,234,567.1234567000"),
51 (["1234567", 1], "1,234,567.0"),
4852 ([None], "None"),
4953 ([14308.40], "14,308.4"),
5054 ([14308.40, None], "14,308.4"),
7478 @pytest.mark.parametrize(
7579 "test_args, expected",
7680 [
81 (["0"], "0"),
7782 (["100"], "100"),
83 (["-100"], "-100"),
7884 (["1000"], "1.0 thousand"),
7985 (["12400"], "12.4 thousand"),
8086 (["12490"], "12.5 thousand"),
8187 (["1000000"], "1.0 million"),
88 (["-1000000"], "-1.0 million"),
8289 (["1200000"], "1.2 million"),
8390 (["1290000"], "1.3 million"),
8491 (["999999999"], "1.0 billion"),
8592 (["1000000000"], "1.0 billion"),
93 (["-1000000000"], "-1.0 billion"),
8694 (["2000000000"], "2.0 billion"),
8795 (["999999999999"], "1.0 trillion"),
8896 (["1000000000000"], "1.0 trillion"),
8997 (["6000000000000"], "6.0 trillion"),
98 (["-6000000000000"], "-6.0 trillion"),
9099 (["999999999999999"], "1.0 quadrillion"),
91100 (["1000000000000000"], "1.0 quadrillion"),
92101 (["1300000000000000"], "1.3 quadrillion"),
102 (["-1300000000000000"], "-1.3 quadrillion"),
93103 (["3500000000000000000000"], "3.5 sextillion"),
94104 (["8100000000000000000000000000000000"], "8.1 decillion"),
105 (["-8100000000000000000000000000000000"], "-8.1 decillion"),
95106 ([None], "None"),
96107 (["1230000", "%0.2f"], "1.23 million"),
97108 ([10**101], "1" + "0" * 101),
186197 @pytest.mark.parametrize(
187198 "test_args, expected",
188199 [
200 ([0], "0.00"),
189201 ([1, "Hz"], "1.00 Hz"),
190202 ([1.0, "W"], "1.00 W"),
191203 ([3, "C"], "3.00 C"),
628628
629629
630630 def test_precisedelta_bogus_call() -> None:
631 assert humanize.precisedelta(None) == "None"
632
631633 with pytest.raises(ValueError):
632634 humanize.precisedelta(1, minimum_unit="years", suppress=["years"])
633635
639641 years, minutes = time.Unit["YEARS"], time.Unit["MINUTES"]
640642 assert minutes < years
641643 assert years > minutes
642 assert minutes == minutes
643644
644645 with pytest.raises(TypeError):
645646 _ = years < "foo"