or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

as-you-type-formatting.mdcore-parsing-formatting.mdindex.mdnumber-validation.mdphone-number-matching.mdregion-metadata.mdshort-numbers.mdutility-functions.md

number-validation.mddocs/

0

# Number Validation

1

2

Comprehensive validation functions to check if phone numbers are valid, possible, or match specific criteria. These functions provide detailed validation information and support various validation levels.

3

4

## Capabilities

5

6

### Basic Validity Checking

7

8

Determine if phone numbers are valid according to official numbering plan rules and formatting requirements.

9

10

```python { .api }

11

def is_valid_number(numobj: PhoneNumber) -> bool:

12

"""

13

Check if a phone number is valid.

14

15

A valid number is one that is both possible (correct length) and

16

follows the numbering rules for its region and type.

17

18

Parameters:

19

- numobj: PhoneNumber object to validate

20

21

Returns:

22

True if the number is valid, False otherwise

23

"""

24

25

def is_valid_number_for_region(numobj: PhoneNumber, region_code: str) -> bool:

26

"""

27

Check if a phone number is valid for a specific region.

28

29

Parameters:

30

- numobj: PhoneNumber object to validate

31

- region_code: Two-letter region code to validate against

32

33

Returns:

34

True if valid for the specified region, False otherwise

35

"""

36

```

37

38

**Usage Examples:**

39

40

```python

41

import phonenumbers

42

43

# Parse and validate various numbers

44

numbers = [

45

"+442083661177", # Valid UK number

46

"+1234567890", # Invalid country code

47

"+44208366", # Too short

48

"+442083661177123", # Too long

49

]

50

51

for number_str in numbers:

52

try:

53

number = phonenumbers.parse(number_str)

54

is_valid = phonenumbers.is_valid_number(number)

55

print(f"{number_str}: {'Valid' if is_valid else 'Invalid'}")

56

except phonenumbers.NumberParseException:

57

print(f"{number_str}: Parse failed")

58

59

# Region-specific validation

60

number = phonenumbers.parse("+442083661177")

61

print(f"Valid for GB: {phonenumbers.is_valid_number_for_region(number, 'GB')}")

62

print(f"Valid for US: {phonenumbers.is_valid_number_for_region(number, 'US')}")

63

```

64

65

### Possibility Checking

66

67

Check if numbers have valid lengths and basic formatting, which is less strict than full validation.

68

69

```python { .api }

70

def is_possible_number(numobj: PhoneNumber) -> bool:

71

"""

72

Check if a phone number is possible (has valid length).

73

74

This is a quicker check than full validation - it only verifies

75

that the number length is appropriate for the region.

76

77

Parameters:

78

- numobj: PhoneNumber object to check

79

80

Returns:

81

True if the number could possibly be valid, False otherwise

82

"""

83

84

def is_possible_number_string(number: str, region_code: str) -> bool:

85

"""

86

Check if a number string is possible without full parsing.

87

88

Parameters:

89

- number: Phone number string to check

90

- region_code: Region code for parsing context

91

92

Returns:

93

True if the string could represent a valid number, False otherwise

94

"""

95

```

96

97

### Detailed Possibility Analysis

98

99

Get detailed information about why a number might not be possible, with specific reasons for failure.

100

101

```python { .api }

102

def is_possible_number_with_reason(numobj: PhoneNumber) -> ValidationResult:

103

"""

104

Check number possibility with detailed reason for the result.

105

106

Parameters:

107

- numobj: PhoneNumber object to analyze

108

109

Returns:

110

ValidationResult indicating specific possibility status:

111

- IS_POSSIBLE: Number has valid length

112

- IS_POSSIBLE_LOCAL_ONLY: Valid for local dialing only

113

- INVALID_COUNTRY_CODE: Country code is not recognized

114

- TOO_SHORT: Number is shorter than valid lengths

115

- TOO_LONG: Number is longer than valid lengths

116

- INVALID_LENGTH: Length doesn't match any valid pattern

117

"""

118

119

def is_possible_number_for_type(numobj: PhoneNumber,

120

phone_type: PhoneNumberType) -> bool:

121

"""

122

Check if number is possible for a specific phone number type.

123

124

Parameters:

125

- numobj: PhoneNumber object to check

126

- phone_type: Specific type to validate against (MOBILE, FIXED_LINE, etc.)

127

128

Returns:

129

True if possible for the specified type, False otherwise

130

"""

131

132

def is_possible_number_for_type_with_reason(numobj: PhoneNumber,

133

phone_type: PhoneNumberType) -> ValidationResult:

134

"""

135

Check type-specific possibility with detailed reason.

136

137

Parameters:

138

- numobj: PhoneNumber object to analyze

139

- phone_type: Phone number type to check against

140

141

Returns:

142

ValidationResult with specific reason for the validation outcome

143

"""

144

```

145

146

**Usage Examples:**

147

148

```python

149

import phonenumbers

150

from phonenumbers import PhoneNumberType, ValidationResult

151

152

number = phonenumbers.parse("+44208366", "GB") # Too short

153

154

# Basic possibility check

155

print(f"Is possible: {phonenumbers.is_possible_number(number)}")

156

157

# Detailed analysis

158

result = phonenumbers.is_possible_number_with_reason(number)

159

if result == ValidationResult.TOO_SHORT:

160

print("Number is too short")

161

elif result == ValidationResult.TOO_LONG:

162

print("Number is too long")

163

elif result == ValidationResult.IS_POSSIBLE:

164

print("Number is possible")

165

166

# Type-specific checking

167

mobile_number = phonenumbers.parse("+447700900123", "GB")

168

is_mobile_possible = phonenumbers.is_possible_number_for_type(

169

mobile_number, PhoneNumberType.MOBILE

170

)

171

print(f"Possible as mobile: {is_mobile_possible}")

172

```

173

174

### Number Type Classification

175

176

Determine what type of phone number (mobile, fixed-line, toll-free, etc.) a given number represents.

177

178

```python { .api }

179

def number_type(numobj: PhoneNumber) -> PhoneNumberType:

180

"""

181

Determine the type of a phone number.

182

183

Parameters:

184

- numobj: PhoneNumber object to classify

185

186

Returns:

187

PhoneNumberType indicating the number's classification:

188

- FIXED_LINE: Traditional landline number

189

- MOBILE: Mobile/cellular number

190

- FIXED_LINE_OR_MOBILE: Cannot distinguish (e.g., US numbers)

191

- TOLL_FREE: Free-to-caller service number

192

- PREMIUM_RATE: Premium-rate service number

193

- SHARED_COST: Shared cost between caller and receiver

194

- VOIP: Voice over IP number

195

- PERSONAL_NUMBER: Personal numbering service

196

- PAGER: Pager number

197

- UAN: Universal Access Number (company number)

198

- VOICEMAIL: Voicemail access number

199

- UNKNOWN: Cannot determine type

200

"""

201

```

202

203

### Geographic Number Analysis

204

205

Analyze whether numbers are tied to specific geographic locations.

206

207

```python { .api }

208

def is_number_geographical(numobj: PhoneNumber) -> bool:

209

"""

210

Check if a phone number is geographical (tied to a location).

211

212

Parameters:

213

- numobj: PhoneNumber object to analyze

214

215

Returns:

216

True if the number is associated with a geographic area, False otherwise

217

"""

218

219

def is_number_type_geographical(phone_type: PhoneNumberType) -> bool:

220

"""

221

Check if a phone number type is generally geographical.

222

223

Parameters:

224

- phone_type: PhoneNumberType to check

225

226

Returns:

227

True if numbers of this type are typically geographical

228

"""

229

```

230

231

### International Dialing Capability

232

233

Check if numbers can be dialed internationally from other countries.

234

235

```python { .api }

236

def can_be_internationally_dialled(numobj: PhoneNumber) -> bool:

237

"""

238

Check if a number can be dialed internationally.

239

240

Some numbers (like emergency services) cannot be reached from abroad.

241

242

Parameters:

243

- numobj: PhoneNumber object to check

244

245

Returns:

246

True if the number can be dialed from other countries, False otherwise

247

"""

248

```

249

250

### Length Truncation

251

252

Attempt to truncate overly long numbers to valid lengths.

253

254

```python { .api }

255

def truncate_too_long_number(numobj: PhoneNumber) -> PhoneNumber:

256

"""

257

Truncate a number that is too long to a valid length.

258

259

Parameters:

260

- numobj: PhoneNumber that may be too long

261

262

Returns:

263

PhoneNumber truncated to valid length, or original if already valid

264

"""

265

```

266

267

## Usage Patterns

268

269

### Comprehensive Number Validation

270

271

```python

272

import phonenumbers

273

from phonenumbers import PhoneNumberType, ValidationResult

274

275

def validate_phone_number(number_string, region=None):

276

"""Comprehensive phone number validation with detailed feedback."""

277

try:

278

# Parse the number

279

number = phonenumbers.parse(number_string, region)

280

281

# Basic validation

282

is_valid = phonenumbers.is_valid_number(number)

283

is_possible = phonenumbers.is_possible_number(number)

284

285

# Detailed possibility analysis

286

possibility_reason = phonenumbers.is_possible_number_with_reason(number)

287

288

# Number type classification

289

num_type = phonenumbers.number_type(number)

290

291

# Geographic analysis

292

is_geographic = phonenumbers.is_number_geographical(number)

293

294

# International dialing capability

295

can_dial_intl = phonenumbers.can_be_internationally_dialled(number)

296

297

return {

298

'number': number,

299

'is_valid': is_valid,

300

'is_possible': is_possible,

301

'possibility_reason': possibility_reason,

302

'type': num_type,

303

'is_geographic': is_geographic,

304

'can_dial_internationally': can_dial_intl,

305

'formatted': {

306

'e164': phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164),

307

'international': phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL),

308

'national': phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.NATIONAL)

309

}

310

}

311

312

except phonenumbers.NumberParseException as e:

313

return {

314

'error': str(e),

315

'error_type': e.error_type

316

}

317

318

# Example usage

319

result = validate_phone_number("+442083661177")

320

if 'error' not in result:

321

print(f"Valid: {result['is_valid']}")

322

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

323

print(f"Geographic: {result['is_geographic']}")

324

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

325

```

326

327

### Batch Validation

328

329

```python

330

import phonenumbers

331

332

def validate_number_list(numbers, default_region="US"):

333

"""Validate a list of phone numbers with summary statistics."""

334

results = {

335

'valid': [],

336

'invalid': [],

337

'unparseable': [],

338

'types': {}

339

}

340

341

for number_str in numbers:

342

try:

343

number = phonenumbers.parse(number_str, default_region)

344

345

if phonenumbers.is_valid_number(number):

346

results['valid'].append(number_str)

347

num_type = phonenumbers.number_type(number)

348

results['types'][num_type] = results['types'].get(num_type, 0) + 1

349

else:

350

results['invalid'].append(number_str)

351

352

except phonenumbers.NumberParseException:

353

results['unparseable'].append(number_str)

354

355

return results

356

357

# Example usage

358

test_numbers = [

359

"+1-800-555-1234", # Valid US toll-free

360

"+44 20 8366 1177", # Valid UK fixed-line

361

"+1-555-123", # Invalid (too short)

362

"not-a-number" # Unparseable

363

]

364

365

results = validate_number_list(test_numbers)

366

print(f"Valid: {len(results['valid'])}")

367

print(f"Invalid: {len(results['invalid'])}")

368

print(f"Unparseable: {len(results['unparseable'])}")

369

print(f"Types found: {results['types']}")

370

```