0
# Units and Utilities
1
2
Unit formatting for measurements, utility functions for text processing and pattern matching, and support classes for translation management. This module provides additional functionality that complements Babel's core internationalization features.
3
4
## Capabilities
5
6
### Unit Formatting
7
8
Format measurement values with units according to locale conventions.
9
10
```python { .api }
11
def format_unit(value, measurement_unit, length='long', format=None,
12
locale=default_locale(), numbering_system="latn"):
13
"""
14
Format a value with unit according to locale conventions.
15
16
Args:
17
value (int|float|Decimal): Numeric value to format
18
measurement_unit (str): Unit identifier (e.g., 'meter', 'kilogram', 'second')
19
length (str): Format length ('long', 'short', 'narrow')
20
format (str, optional): Number format pattern
21
locale (Locale|str): Target locale
22
numbering_system (str): Numbering system
23
24
Returns:
25
str: Formatted value with unit
26
27
Raises:
28
UnknownUnitError: If unit is not recognized
29
"""
30
31
def format_compound_unit(numerator_value, numerator_unit, denominator_value,
32
denominator_unit, length='long', format=None,
33
locale=default_locale(), numbering_system="latn"):
34
"""
35
Format compound unit (e.g., "kilometers per hour").
36
37
Args:
38
numerator_value (int|float|Decimal): Numerator value
39
numerator_unit (str): Numerator unit identifier
40
denominator_value (int|float|Decimal): Denominator value
41
denominator_unit (str): Denominator unit identifier
42
length (str): Format length ('long', 'short', 'narrow')
43
format (str, optional): Number format pattern
44
locale (Locale|str): Target locale
45
numbering_system (str): Numbering system
46
47
Returns:
48
str: Formatted compound unit
49
"""
50
51
def get_unit_name(measurement_unit, length='long', locale=default_locale()):
52
"""
53
Get display name for a measurement unit.
54
55
Args:
56
measurement_unit (str): Unit identifier
57
length (str): Format length ('long', 'short', 'narrow')
58
locale (Locale|str): Target locale
59
60
Returns:
61
str|None: Unit display name or None if not found
62
"""
63
```
64
65
Usage example:
66
67
```python
68
from babel.units import format_unit, format_compound_unit, get_unit_name
69
70
# Basic unit formatting
71
print(format_unit(5, 'meter', locale='en_US')) # "5 meters"
72
print(format_unit(5, 'meter', locale='fr_FR')) # "5 mètres"
73
print(format_unit(1, 'meter', locale='en_US')) # "1 meter"
74
75
# Different lengths
76
print(format_unit(10, 'kilogram', length='long', locale='en_US')) # "10 kilograms"
77
print(format_unit(10, 'kilogram', length='short', locale='en_US')) # "10 kg"
78
print(format_unit(10, 'kilogram', length='narrow', locale='en_US')) # "10kg"
79
80
# Compound units
81
print(format_compound_unit(60, 'kilometer', 1, 'hour', locale='en_US')) # "60 kilometers per hour"
82
print(format_compound_unit(60, 'kilometer', 1, 'hour', length='short', locale='en_US')) # "60 km/h"
83
84
# Unit names
85
print(get_unit_name('meter', locale='en_US')) # "meter"
86
print(get_unit_name('meter', locale='fr_FR')) # "mètre"
87
```
88
89
### Format Helper Class
90
91
Convenience class that provides locale-bound formatting methods.
92
93
```python { .api }
94
class Format:
95
"""
96
Wrapper providing date/number formatting bound to a specific locale.
97
"""
98
def __init__(self, locale, tzinfo=None, numbering_system="latn"):
99
"""
100
Initialize formatter for specific locale.
101
102
Args:
103
locale (Locale|str): Target locale
104
tzinfo (datetime.tzinfo, optional): Default timezone
105
numbering_system (str): Default numbering system
106
"""
107
108
def date(self, date=None, format='medium'):
109
"""
110
Format a date using this formatter's locale.
111
112
Args:
113
date (datetime.date, optional): Date to format (default: today)
114
format (str): Format style
115
116
Returns:
117
str: Formatted date
118
"""
119
120
def datetime(self, datetime=None, format='medium'):
121
"""
122
Format a datetime using this formatter's locale.
123
124
Args:
125
datetime (datetime.datetime, optional): Datetime to format (default: now)
126
format (str): Format style
127
128
Returns:
129
str: Formatted datetime
130
"""
131
132
def time(self, time=None, format='medium'):
133
"""
134
Format a time using this formatter's locale.
135
136
Args:
137
time (datetime.time, optional): Time to format (default: now)
138
format (str): Format style
139
140
Returns:
141
str: Formatted time
142
"""
143
144
def timedelta(self, delta, granularity="second", threshold=0.85,
145
format="long", add_direction=False):
146
"""
147
Format a timedelta using this formatter's locale.
148
149
Args:
150
delta (datetime.timedelta): Time difference to format
151
granularity (str): Smallest unit to display
152
threshold (float): Threshold for larger units
153
format (str): Format style
154
add_direction (bool): Whether to add directional words
155
156
Returns:
157
str: Formatted timedelta
158
"""
159
160
def number(self, number):
161
"""
162
Format a number using this formatter's locale.
163
164
Args:
165
number (int|float|Decimal): Number to format
166
167
Returns:
168
str: Formatted number
169
"""
170
171
def decimal(self, number, format=None):
172
"""
173
Format a decimal using this formatter's locale.
174
175
Args:
176
number (int|float|Decimal): Number to format
177
format (str, optional): Number format pattern
178
179
Returns:
180
str: Formatted decimal
181
"""
182
183
def compact_decimal(self, number, format_type='short', fraction_digits=0):
184
"""
185
Format a decimal in compact notation.
186
187
Args:
188
number (int|float|Decimal): Number to format
189
format_type (str): Format type ('short', 'long')
190
fraction_digits (int): Number of fraction digits
191
192
Returns:
193
str: Compact formatted decimal
194
"""
195
196
def currency(self, number, currency):
197
"""
198
Format a currency amount using this formatter's locale.
199
200
Args:
201
number (int|float|Decimal): Amount to format
202
currency (str): Currency code
203
204
Returns:
205
str: Formatted currency
206
"""
207
208
def compact_currency(self, number, currency, format_type='short', fraction_digits=0):
209
"""
210
Format a currency amount in compact notation.
211
212
Args:
213
number (int|float|Decimal): Amount to format
214
currency (str): Currency code
215
format_type (str): Format type ('short', 'long')
216
fraction_digits (int): Number of fraction digits
217
218
Returns:
219
str: Compact formatted currency
220
"""
221
222
def percent(self, number, format=None):
223
"""
224
Format a percentage using this formatter's locale.
225
226
Args:
227
number (int|float|Decimal): Number to format as percentage
228
format (str, optional): Percent format pattern
229
230
Returns:
231
str: Formatted percentage
232
"""
233
234
def scientific(self, number):
235
"""
236
Format a number in scientific notation.
237
238
Args:
239
number (int|float|Decimal): Number to format
240
241
Returns:
242
str: Number in scientific notation
243
"""
244
```
245
246
Usage example:
247
248
```python
249
from babel.support import Format
250
from babel import Locale
251
import datetime
252
253
# Create formatter for specific locale
254
formatter = Format(Locale('fr_FR'))
255
256
# Use formatter methods
257
now = datetime.datetime.now()
258
print(formatter.date(now.date())) # French date format
259
print(formatter.currency(1234.56, 'EUR')) # "1 234,56 €"
260
print(formatter.percent(0.1234)) # "12 %"
261
```
262
263
### Lazy Evaluation Proxy
264
265
Proxy object that delays evaluation of expensive operations until actually needed.
266
267
```python { .api }
268
class LazyProxy:
269
"""
270
Proxy object that delays evaluation until the value is actually used.
271
"""
272
def __init__(self, func, *args, enable_cache=True, **kwargs):
273
"""
274
Initialize lazy proxy.
275
276
Args:
277
func (callable): Function to call for evaluation
278
*args: Arguments to pass to function
279
enable_cache (bool): Whether to cache the result
280
**kwargs: Keyword arguments to pass to function
281
"""
282
```
283
284
Usage example:
285
286
```python
287
from babel.support import LazyProxy
288
289
def expensive_operation():
290
print("Computing expensive result...")
291
return "Result"
292
293
# Create lazy proxy
294
lazy_result = LazyProxy(expensive_operation)
295
296
# Function not called yet
297
print("Proxy created")
298
299
# Function called on first access
300
print(lazy_result) # "Computing expensive result..." then "Result"
301
print(lazy_result) # Just "Result" (cached)
302
```
303
304
### Translation Classes
305
306
Extended translation classes with additional functionality.
307
308
```python { .api }
309
class NullTranslations:
310
"""
311
Base translation class without catalog (fallback behavior).
312
313
Inherits from gettext.NullTranslations with Babel extensions.
314
"""
315
def dgettext(self, domain, message):
316
"""Get translation for message in domain."""
317
318
def pgettext(self, context, message):
319
"""Get translation for message with context."""
320
321
def dpgettext(self, domain, context, message):
322
"""Get translation for message with domain and context."""
323
324
class Translations(NullTranslations):
325
"""
326
Extended translation catalog class with Babel features.
327
328
Inherits from both NullTranslations and gettext.GNUTranslations.
329
"""
330
@classmethod
331
def load(cls, dirname=None, locales=None, domain=None):
332
"""
333
Load translations from directory structure.
334
335
Args:
336
dirname (str, optional): Directory containing translations
337
locales (list, optional): List of locale identifiers to load
338
domain (str, optional): Message domain to load
339
340
Returns:
341
Translations: Loaded translation object
342
"""
343
344
def add(self, translations, merge=True):
345
"""
346
Add translations from another catalog.
347
348
Args:
349
translations (Translations): Translation catalog to add
350
merge (bool): Whether to merge conflicting entries
351
"""
352
353
def merge(self, translations):
354
"""
355
Merge translations from another catalog.
356
357
Args:
358
translations (Translations): Translation catalog to merge
359
"""
360
```
361
362
### Utility Functions
363
364
General utility functions for text processing and file handling.
365
366
```python { .api }
367
def distinct(iterable):
368
"""
369
Yield distinct items from iterable, preserving order.
370
371
Args:
372
iterable: Input sequence
373
374
Returns:
375
Generator: Distinct items in original order
376
"""
377
378
def parse_encoding(fp):
379
"""
380
Parse character encoding from Python file magic comment.
381
382
Args:
383
fp (IO[bytes]): File object to read from
384
385
Returns:
386
str|None: Detected encoding or None
387
"""
388
389
def parse_future_flags(fp, encoding='utf-8'):
390
"""
391
Parse __future__ import flags from Python code.
392
393
Args:
394
fp (IO[bytes]): File object to read from
395
encoding (str): Character encoding
396
397
Returns:
398
int: Combined future flags
399
"""
400
401
def pathmatch(pattern, filename):
402
"""
403
Extended pathname pattern matching with ** support.
404
405
Args:
406
pattern (str): Pattern with wildcards (* and **)
407
filename (str): Filename to match against pattern
408
409
Returns:
410
bool: True if filename matches pattern
411
"""
412
```
413
414
Usage example:
415
416
```python
417
from babel.util import distinct, pathmatch
418
419
# Remove duplicates while preserving order
420
items = [1, 2, 2, 3, 1, 4]
421
unique_items = list(distinct(items)) # [1, 2, 3, 4]
422
423
# Pattern matching
424
print(pathmatch('src/**/*.py', 'src/module/file.py')) # True
425
print(pathmatch('*.txt', 'document.txt')) # True
426
print(pathmatch('test_*.py', 'test_parser.py')) # True
427
```
428
429
### Text Wrapping Utilities
430
431
Enhanced text wrapping that handles special cases.
432
433
```python { .api }
434
class TextWrapper:
435
"""
436
Enhanced text wrapper that handles filenames with spaces.
437
438
Inherits from textwrap.TextWrapper with improvements.
439
"""
440
441
def wraptext(text, width=70, initial_indent='', subsequent_indent=''):
442
"""
443
Wrap text preserving filenames with spaces (deprecated).
444
445
Args:
446
text (str): Text to wrap
447
width (int): Maximum line width
448
initial_indent (str): Initial line indent
449
subsequent_indent (str): Subsequent line indent
450
451
Returns:
452
list[str]: List of wrapped lines
453
"""
454
```
455
456
### Timezone Utilities
457
458
Fixed-offset timezone implementation and timezone constants.
459
460
```python { .api }
461
class FixedOffsetTimezone:
462
"""
463
Timezone with fixed offset from UTC.
464
465
Inherits from datetime.tzinfo.
466
"""
467
def __init__(self, offset, name=None):
468
"""
469
Initialize fixed offset timezone.
470
471
Args:
472
offset (datetime.timedelta): UTC offset
473
name (str, optional): Timezone name
474
"""
475
476
# Timezone constants
477
UTC: datetime.tzinfo
478
"""UTC timezone object (re-exported from babel.dates)"""
479
480
LOCALTZ: datetime.tzinfo
481
"""Local timezone object (re-exported from babel.dates)"""
482
```
483
484
Usage example:
485
486
```python
487
from babel.util import FixedOffsetTimezone, UTC
488
import datetime
489
490
# Create fixed offset timezone
491
est = FixedOffsetTimezone(datetime.timedelta(hours=-5), 'EST')
492
493
# Use with datetime
494
dt = datetime.datetime(2023, 12, 25, 12, 0, tzinfo=est)
495
utc_dt = dt.astimezone(UTC)
496
```
497
498
## Exception Classes
499
500
```python { .api }
501
class UnknownUnitError(Exception):
502
"""Raised when an unknown unit identifier is used."""
503
```
504
505
## Constants
506
507
Various constants used throughout Babel utilities are re-exported here for convenience, including timezone objects and default values.