or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-operations.mdgeographic-services.mdindex.mdshort-numbers.mdtext-processing.mdutilities.md

utilities.mddocs/

0

# Utilities

1

2

Helper functions for string processing, normalization, example number generation, and metadata access. These utilities provide advanced functionality for specialized use cases and integration with other systems.

3

4

## Capabilities

5

6

### String Processing and Normalization

7

8

Functions to clean, normalize, and process phone number strings before parsing or after formatting.

9

10

```python { .api }

11

def normalize_digits_only(number: str, keep_non_digits: bool = False) -> str:

12

"""

13

Extract and normalize only digits from string.

14

15

Parameters:

16

- number: Input string to normalize

17

- keep_non_digits: Whether to preserve non-digit characters

18

19

Returns:

20

String containing only digits (0-9) or digits plus non-digits if keep_non_digits=True

21

"""

22

23

def normalize_diallable_chars_only(number: str) -> str:

24

"""

25

Normalize string to contain only diallable characters.

26

27

Parameters:

28

- number: Input string to normalize

29

30

Returns:

31

String containing only characters that can be dialed (digits, +, *, #, etc.)

32

"""

33

34

def convert_alpha_characters_in_number(number: str) -> str:

35

"""

36

Convert alphabetic characters to digits (e.g., ABC → 222).

37

38

Parameters:

39

- number: Phone number string potentially containing letters

40

41

Returns:

42

String with letters converted to corresponding digits

43

"""

44

45

def is_alpha_number(number: str) -> bool:

46

"""

47

Check if string could be an alphanumeric phone number.

48

49

Parameters:

50

- number: String to check for alphanumeric phone number pattern

51

52

Returns:

53

True if the string appears to be an alphanumeric phone number

54

"""

55

```

56

57

**Usage Examples:**

58

59

```python

60

# Normalize digits from messy input

61

messy_input = "Call (555) 123-HELP or +1.555.987.6543 ext.123"

62

digits_only = phonenumbers.normalize_digits_only(messy_input)

63

print(digits_only) # "555123555987654312"

64

65

# Keep some non-digits for context

66

partial_normalize = phonenumbers.normalize_digits_only("555-123-HELP", keep_non_digits=True)

67

print(partial_normalize) # "555-123-"

68

69

# Normalize to diallable characters

70

diallable = phonenumbers.normalize_diallable_chars_only("Call +1 (555) 123-4567!")

71

print(diallable) # "+15551234567"

72

73

# Convert letters to numbers (phone keypad mapping)

74

alpha_number = "1-800-FLOWERS"

75

numeric = phonenumbers.convert_alpha_characters_in_number(alpha_number)

76

print(numeric) # "1-800-3569377"

77

78

# Letter conversion examples

79

conversions = [

80

"CALL-HOME", # 2255-4663

81

"555-HELP", # 555-4357

82

"1-800-GOT-JUNK", # 1-800-468-5865

83

"TEXT-TAXI" # 8398-8294

84

]

85

86

for alpha in conversions:

87

numeric = phonenumbers.convert_alpha_characters_in_number(alpha)

88

print(f"{alpha} -> {numeric}")

89

90

# Check if string is alphanumeric phone number

91

test_strings = [

92

"1-800-FLOWERS", # True

93

"555-HELP", # True

94

"CALL-ME", # True

95

"Hello World", # False

96

"123-456-7890", # False (no letters)

97

"" # False

98

]

99

100

for test_str in test_strings:

101

is_alpha = phonenumbers.is_alpha_number(test_str)

102

print(f"'{test_str}' is alphanumeric: {is_alpha}")

103

```

104

105

### Example Number Generation

106

107

Functions to generate example phone numbers for testing, documentation, and user interface mockups.

108

109

```python { .api }

110

def example_number(region_code: str) -> PhoneNumber | None:

111

"""

112

Get example phone number for region.

113

114

Parameters:

115

- region_code: Region identifier (e.g., "US", "GB")

116

117

Returns:

118

Example PhoneNumber for the region, None if no example available

119

"""

120

121

def example_number_for_type(region_code: str | None, num_type: int) -> PhoneNumber | None:

122

"""

123

Get example number of specified type for region.

124

125

Parameters:

126

- region_code: Region identifier, None for non-geographical numbers

127

- num_type: PhoneNumberType value (MOBILE, FIXED_LINE, etc.)

128

129

Returns:

130

Example PhoneNumber of the specified type, None if unavailable

131

"""

132

133

def example_number_for_non_geo_entity(country_calling_code: int) -> PhoneNumber | None:

134

"""

135

Get example number for non-geographical country code.

136

137

Parameters:

138

- country_calling_code: Non-geographical country calling code

139

140

Returns:

141

Example PhoneNumber for the non-geographical entity

142

"""

143

144

def invalid_example_number(region_code: str) -> PhoneNumber | None:

145

"""

146

Get example of invalid number for testing purposes.

147

148

Parameters:

149

- region_code: Region identifier

150

151

Returns:

152

Example invalid PhoneNumber for testing validation logic

153

"""

154

```

155

156

**Usage Examples:**

157

158

```python

159

# Generate example numbers for different regions

160

regions = ["US", "GB", "DE", "FR", "JP", "AU"]

161

162

print("Example numbers by region:")

163

for region in regions:

164

example = phonenumbers.example_number(region)

165

if example:

166

formatted = phonenumbers.format_number(example, phonenumbers.PhoneNumberFormat.INTERNATIONAL)

167

print(f"{region}: {formatted}")

168

169

# Generate examples by number type

170

types_to_test = [

171

(phonenumbers.PhoneNumberType.FIXED_LINE, "Fixed Line"),

172

(phonenumbers.PhoneNumberType.MOBILE, "Mobile"),

173

(phonenumbers.PhoneNumberType.TOLL_FREE, "Toll Free"),

174

(phonenumbers.PhoneNumberType.PREMIUM_RATE, "Premium Rate")

175

]

176

177

print("\nUS examples by type:")

178

for num_type, type_name in types_to_test:

179

example = phonenumbers.example_number_for_type("US", num_type)

180

if example:

181

formatted = phonenumbers.format_number(example, phonenumbers.PhoneNumberFormat.NATIONAL)

182

print(f"{type_name}: {formatted}")

183

184

# Non-geographical examples

185

non_geo_codes = [800, 808, 870, 878, 881, 882, 883, 888]

186

print("\nNon-geographical examples:")

187

for code in non_geo_codes:

188

example = phonenumbers.example_number_for_non_geo_entity(code)

189

if example:

190

formatted = phonenumbers.format_number(example, phonenumbers.PhoneNumberFormat.INTERNATIONAL)

191

print(f"Country code {code}: {formatted}")

192

193

# Invalid examples for testing

194

print("\nInvalid examples for testing:")

195

test_regions = ["US", "GB", "DE"]

196

for region in test_regions:

197

invalid = phonenumbers.invalid_example_number(region)

198

if invalid:

199

# These should fail validation

200

is_valid = phonenumbers.is_valid_number(invalid)

201

formatted = phonenumbers.format_number(invalid, phonenumbers.PhoneNumberFormat.E164)

202

print(f"{region} invalid: {formatted} (valid: {is_valid})")

203

204

# Generate test data for unit tests

205

def generate_test_data(region, include_invalid=True):

206

"""Generate comprehensive test data for a region."""

207

test_data = {

208

"region": region,

209

"general_example": None,

210

"by_type": {},

211

"invalid_example": None

212

}

213

214

# General example

215

general = phonenumbers.example_number(region)

216

if general:

217

test_data["general_example"] = {

218

"number": general,

219

"e164": phonenumbers.format_number(general, phonenumbers.PhoneNumberFormat.E164),

220

"national": phonenumbers.format_number(general, phonenumbers.PhoneNumberFormat.NATIONAL),

221

"international": phonenumbers.format_number(general, phonenumbers.PhoneNumberFormat.INTERNATIONAL)

222

}

223

224

# Examples by type

225

all_types = [

226

phonenumbers.PhoneNumberType.FIXED_LINE,

227

phonenumbers.PhoneNumberType.MOBILE,

228

phonenumbers.PhoneNumberType.TOLL_FREE,

229

phonenumbers.PhoneNumberType.PREMIUM_RATE,

230

phonenumbers.PhoneNumberType.SHARED_COST,

231

phonenumbers.PhoneNumberType.VOIP,

232

phonenumbers.PhoneNumberType.PERSONAL_NUMBER,

233

phonenumbers.PhoneNumberType.PAGER,

234

phonenumbers.PhoneNumberType.UAN,

235

phonenumbers.PhoneNumberType.VOICEMAIL

236

]

237

238

for num_type in all_types:

239

example = phonenumbers.example_number_for_type(region, num_type)

240

if example:

241

test_data["by_type"][num_type] = {

242

"number": example,

243

"formatted": phonenumbers.format_number(example, phonenumbers.PhoneNumberFormat.E164)

244

}

245

246

# Invalid example

247

if include_invalid:

248

invalid = phonenumbers.invalid_example_number(region)

249

if invalid:

250

test_data["invalid_example"] = {

251

"number": invalid,

252

"formatted": phonenumbers.format_number(invalid, phonenumbers.PhoneNumberFormat.E164)

253

}

254

255

return test_data

256

257

# Generate test data for US

258

us_test_data = generate_test_data("US")

259

print(f"\nGenerated test data for US:")

260

print(f"- General example: {us_test_data['general_example']['e164'] if us_test_data['general_example'] else 'None'}")

261

print(f"- Number types with examples: {len(us_test_data['by_type'])}")

262

print(f"- Has invalid example: {us_test_data['invalid_example'] is not None}")

263

```

264

265

### Metadata and Constants Access

266

267

Access to global constants and metadata about supported regions and capabilities.

268

269

```python { .api }

270

SUPPORTED_REGIONS: set[str] # Set of all supported region codes

271

272

SUPPORTED_SHORT_REGIONS: list[str] # List of regions with short number support

273

274

COUNTRY_CODE_TO_REGION_CODE: dict[int, tuple[str, ...]] # Map country codes to regions

275

276

COUNTRY_CODES_FOR_NON_GEO_REGIONS: set[int] # Non-geographical country codes

277

278

UNKNOWN_REGION: str # Constant for unknown region ("ZZ")

279

280

REGION_CODE_FOR_NON_GEO_ENTITY: str # Region code for non-geographical numbers ("001")

281

282

NON_DIGITS_PATTERN: Pattern[str] # Regex pattern matching non-digit characters

283

284

__version__: str # Package version string

285

```

286

287

**Usage Examples:**

288

289

```python

290

# Access global constants

291

print(f"Library version: {phonenumbers.__version__}")

292

print(f"Unknown region code: {phonenumbers.UNKNOWN_REGION}")

293

print(f"Non-geo region code: {phonenumbers.REGION_CODE_FOR_NON_GEO_ENTITY}")

294

295

# Supported regions information

296

all_regions = phonenumbers.SUPPORTED_REGIONS

297

print(f"Total supported regions: {len(all_regions)}")

298

print(f"Sample regions: {sorted(list(all_regions))[:10]}")

299

300

# Check if specific regions are supported

301

regions_to_check = ["US", "GB", "CA", "AU", "XX", "ZZ"]

302

for region in regions_to_check:

303

is_supported = region in phonenumbers.SUPPORTED_REGIONS

304

print(f"Region {region} supported: {is_supported}")

305

306

# Short number support

307

short_regions = phonenumbers.SUPPORTED_SHORT_REGIONS

308

print(f"\nShort numbers supported in {len(short_regions)} regions")

309

print(f"Short number regions: {short_regions[:10]}") # First 10

310

311

# Country code mappings

312

print(f"\nCountry code mappings (sample):")

313

sample_codes = [1, 44, 33, 49, 81]

314

for code in sample_codes:

315

regions = phonenumbers.COUNTRY_CODE_TO_REGION_CODE.get(code, ())

316

print(f"Country code {code}: {regions}")

317

318

# Non-geographical country codes

319

non_geo_codes = phonenumbers.COUNTRY_CODES_FOR_NON_GEO_REGIONS

320

print(f"\nNon-geographical country codes: {sorted(non_geo_codes)}")

321

322

# Pattern matching with NON_DIGITS_PATTERN

323

import re

324

test_strings = ["123-456-7890", "abc123def", "+1 (555) 123-4567", ""]

325

for test_str in test_strings:

326

non_digits = phonenumbers.NON_DIGITS_PATTERN.findall(test_str)

327

print(f"'{test_str}' non-digits: {non_digits}")

328

```

329

330

### Advanced Utility Functions

331

332

Specialized utility functions for advanced use cases and system integration.

333

334

```python { .api }

335

def supported_calling_codes() -> set[int]:

336

"""Get set of all supported country calling codes."""

337

338

def supported_types_for_region(region_code: str) -> set[int]:

339

"""Get supported phone number types for region."""

340

341

def supported_types_for_non_geo_entity(country_code: int) -> set[int]:

342

"""Get supported types for non-geographical entities."""

343

```

344

345

**Usage Examples:**

346

347

```python

348

# Get all supported calling codes

349

all_codes = phonenumbers.supported_calling_codes()

350

print(f"All supported country codes ({len(all_codes)}):")

351

print(f"Range: {min(all_codes)} to {max(all_codes)}")

352

print(f"Sample codes: {sorted(list(all_codes))[:20]}")

353

354

# Analyze regional capabilities

355

def analyze_region_capabilities(region_code):

356

"""Analyze what number types are supported in a region."""

357

if region_code not in phonenumbers.SUPPORTED_REGIONS:

358

return f"Region {region_code} is not supported"

359

360

supported_types = phonenumbers.supported_types_for_region(region_code)

361

362

type_names = {

363

phonenumbers.PhoneNumberType.FIXED_LINE: "Fixed Line",

364

phonenumbers.PhoneNumberType.MOBILE: "Mobile",

365

phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE: "Fixed Line or Mobile",

366

phonenumbers.PhoneNumberType.TOLL_FREE: "Toll Free",

367

phonenumbers.PhoneNumberType.PREMIUM_RATE: "Premium Rate",

368

phonenumbers.PhoneNumberType.SHARED_COST: "Shared Cost",

369

phonenumbers.PhoneNumberType.VOIP: "VoIP",

370

phonenumbers.PhoneNumberType.PERSONAL_NUMBER: "Personal Number",

371

phonenumbers.PhoneNumberType.PAGER: "Pager",

372

phonenumbers.PhoneNumberType.UAN: "Universal Access Number",

373

phonenumbers.PhoneNumberType.VOICEMAIL: "Voicemail"

374

}

375

376

capabilities = []

377

for type_code in supported_types:

378

type_name = type_names.get(type_code, f"Type {type_code}")

379

capabilities.append(type_name)

380

381

return {

382

"region": region_code,

383

"supported_types": sorted(capabilities),

384

"count": len(capabilities)

385

}

386

387

# Analyze several regions

388

regions_to_analyze = ["US", "GB", "DE", "JP", "IN", "BR"]

389

for region in regions_to_analyze:

390

analysis = analyze_region_capabilities(region)

391

if isinstance(analysis, dict):

392

print(f"\n{region} capabilities ({analysis['count']} types):")

393

for capability in analysis['supported_types']:

394

print(f" - {capability}")

395

396

# Non-geographical entity analysis

397

non_geo_codes = [800, 808, 870, 878, 881, 882, 883, 888]

398

print(f"\nNon-geographical entity capabilities:")

399

for code in non_geo_codes:

400

supported_types = phonenumbers.supported_types_for_non_geo_entity(code)

401

if supported_types:

402

print(f"Country code {code}: {len(supported_types)} supported types")

403

404

# Create comprehensive capability matrix

405

def create_capability_matrix(regions=None):

406

"""Create a matrix showing which capabilities are available in which regions."""

407

if regions is None:

408

regions = ["US", "GB", "DE", "FR", "JP", "AU", "CA", "IN"]

409

410

all_types = [

411

phonenumbers.PhoneNumberType.FIXED_LINE,

412

phonenumbers.PhoneNumberType.MOBILE,

413

phonenumbers.PhoneNumberType.TOLL_FREE,

414

phonenumbers.PhoneNumberType.PREMIUM_RATE,

415

phonenumbers.PhoneNumberType.SHARED_COST,

416

phonenumbers.PhoneNumberType.VOIP

417

]

418

419

type_names = ["Fixed", "Mobile", "Toll Free", "Premium", "Shared", "VoIP"]

420

421

matrix = {}

422

for region in regions:

423

if region in phonenumbers.SUPPORTED_REGIONS:

424

supported = phonenumbers.supported_types_for_region(region)

425

matrix[region] = [num_type in supported for num_type in all_types]

426

427

return matrix, type_names

428

429

capability_matrix, type_headers = create_capability_matrix()

430

431

print(f"\nCapability Matrix:")

432

print(f"{'Region':<8}", end="")

433

for header in type_headers:

434

print(f"{header:<10}", end="")

435

print()

436

437

print("-" * (8 + len(type_headers) * 10))

438

439

for region, capabilities in capability_matrix.items():

440

print(f"{region:<8}", end="")

441

for has_capability in capabilities:

442

mark = "✓" if has_capability else "✗"

443

print(f"{mark:<10}", end="")

444

print()

445

```

446

447

### System Integration Helpers

448

449

Utility functions to help integrate phonenumbers with other systems and frameworks.

450

451

**Usage Examples:**

452

453

```python

454

# Create validation helpers for web forms

455

def create_phone_validator(region_code):

456

"""Create a phone number validator function for a specific region."""

457

def validate_phone(phone_string):

458

try:

459

parsed = phonenumbers.parse(phone_string, region_code)

460

return {

461

"valid": phonenumbers.is_valid_number(parsed),

462

"possible": phonenumbers.is_possible_number(parsed),

463

"formatted": phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.E164),

464

"type": phonenumbers.number_type(parsed),

465

"region": phonenumbers.region_code_for_number(parsed)

466

}

467

except phonenumbers.NumberParseException as e:

468

return {

469

"valid": False,

470

"error": str(e),

471

"error_type": e.error_type

472

}

473

474

return validate_phone

475

476

# Create validators for different regions

477

us_validator = create_phone_validator("US")

478

uk_validator = create_phone_validator("GB")

479

480

# Test validation

481

test_numbers = [

482

"(555) 123-4567",

483

"+1 555 123 4567",

484

"020 8366 1177",

485

"+44 20 8366 1177",

486

"invalid"

487

]

488

489

for number in test_numbers:

490

us_result = us_validator(number)

491

uk_result = uk_validator(number)

492

493

print(f"\n'{number}':")

494

print(f" US context: {'Valid' if us_result.get('valid') else 'Invalid'}")

495

print(f" UK context: {'Valid' if uk_result.get('valid') else 'Invalid'}")

496

497

# Database storage helper

498

def prepare_for_storage(phone_string, region_code=None):

499

"""Prepare phone number for database storage."""

500

try:

501

parsed = phonenumbers.parse(phone_string, region_code)

502

503

if not phonenumbers.is_valid_number(parsed):

504

return None # Don't store invalid numbers

505

506

return {

507

"e164": phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.E164),

508

"national": phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.NATIONAL),

509

"international": phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.INTERNATIONAL),

510

"country_code": parsed.country_code,

511

"national_number": parsed.national_number,

512

"region": phonenumbers.region_code_for_number(parsed),

513

"type": phonenumbers.number_type(parsed),

514

"extension": parsed.extension

515

}

516

except phonenumbers.NumberParseException:

517

return None

518

519

# Test storage preparation

520

storage_tests = [

521

("(555) 123-4567", "US"),

522

("+44 20 8366 1177", None),

523

("invalid", "US")

524

]

525

526

for phone, region in storage_tests:

527

stored_data = prepare_for_storage(phone, region)

528

if stored_data:

529

print(f"\n'{phone}' -> Storage data:")

530

print(f" E164: {stored_data['e164']}")

531

print(f" Region: {stored_data['region']}")

532

print(f" Type: {stored_data['type']}")

533

else:

534

print(f"\n'{phone}' -> Not suitable for storage")

535

536

# Bulk processing helper

537

def bulk_process_numbers(phone_list, region_code=None, format_type=None):

538

"""Process a list of phone numbers efficiently."""

539

if format_type is None:

540

format_type = phonenumbers.PhoneNumberFormat.E164

541

542

results = []

543

544

for phone_string in phone_list:

545

try:

546

parsed = phonenumbers.parse(phone_string, region_code)

547

548

result = {

549

"input": phone_string,

550

"valid": phonenumbers.is_valid_number(parsed),

551

"formatted": phonenumbers.format_number(parsed, format_type),

552

"region": phonenumbers.region_code_for_number(parsed),

553

"type": phonenumbers.number_type(parsed)

554

}

555

556

results.append(result)

557

558

except phonenumbers.NumberParseException as e:

559

results.append({

560

"input": phone_string,

561

"valid": False,

562

"error": str(e),

563

"error_type": e.error_type

564

})

565

566

return results

567

568

# Test bulk processing

569

phone_batch = [

570

"(555) 123-4567",

571

"+44 20 8366 1177",

572

"1-800-555-0199",

573

"invalid-number",

574

"+33 1 42 68 53 00"

575

]

576

577

batch_results = bulk_process_numbers(phone_batch, "US", phonenumbers.PhoneNumberFormat.INTERNATIONAL)

578

579

print(f"\nBulk processing results:")

580

for result in batch_results:

581

status = "✓" if result.get("valid") else "✗"

582

formatted = result.get("formatted", "N/A")

583

print(f"{status} {result['input']} -> {formatted}")

584

```