Python library for parsing, formatting, storing and validating international phone numbers with reduced memory footprint
—
Support for emergency numbers, short codes, and special service numbers with cost information and regional validation. Short numbers are typically 3-6 digit numbers used for emergency services, directory assistance, and other special services.
Validate whether short numbers are valid for emergency services, directory assistance, and other special services.
def is_valid_short_number(numobj: PhoneNumber) -> bool:
"""
Check if a short number is valid.
A valid short number is one that is recognized as providing
a specific service in at least one region.
Parameters:
- numobj: PhoneNumber object containing the short number
Returns:
True if the short number is valid, False otherwise
"""
def is_valid_short_number_for_region(short_numobj: PhoneNumber,
region_dialing_from: str) -> bool:
"""
Check if a short number is valid for a specific region.
Parameters:
- short_numobj: PhoneNumber object containing the short number
- region_dialing_from: Two-letter region code where number would be dialed
Returns:
True if valid for the specified region, False otherwise
"""Check if short numbers are possible (have valid lengths) without full validation.
def is_possible_short_number(numobj: PhoneNumber) -> bool:
"""
Check if a short number is possible.
This is a quicker check than full validation - verifies that
the short number length is appropriate for some region.
Parameters:
- numobj: PhoneNumber object containing the short number
Returns:
True if the short number could possibly be valid, False otherwise
"""
def is_possible_short_number_for_region(short_numobj: PhoneNumber,
region_dialing_from: str) -> bool:
"""
Check if a short number is possible for a specific region.
Parameters:
- short_numobj: PhoneNumber object containing the short number
- region_dialing_from: Region from which the number would be dialed
Returns:
True if possible for the specified region, False otherwise
"""Identify and validate emergency service numbers.
def is_emergency_number(number: str, region_code: str) -> bool:
"""
Check if a number string is an emergency number for a region.
Parameters:
- number: Phone number string to check
- region_code: Two-letter region code for validation context
Returns:
True if the number connects to emergency services, False otherwise
"""
def connects_to_emergency_number(number: str, region_code: str) -> bool:
"""
Check if dialing a number connects to emergency services.
This may return True for numbers that are not emergency numbers
themselves but would route to emergency services when dialed.
Parameters:
- number: Phone number string to check
- region_code: Region code for dialing context
Returns:
True if dialing this number connects to emergency services
"""Determine the cost associated with calling short numbers.
class ShortNumberCost:
"""Cost categories for short numbers."""
TOLL_FREE = 0
"""Short number is free to call."""
STANDARD_RATE = 1
"""Short number is charged at standard rate."""
PREMIUM_RATE = 2
"""Short number is charged at premium rate."""
UNKNOWN_COST = 3
"""Cost of short number is unknown."""
def expected_cost(numobj: PhoneNumber) -> ShortNumberCost:
"""
Get the expected cost of calling a short number.
Parameters:
- numobj: PhoneNumber object containing the short number
Returns:
ShortNumberCost indicating the expected charge category
"""
def expected_cost_for_region(numobj: PhoneNumber,
region_dialing_from: str) -> ShortNumberCost:
"""
Get expected cost of calling a short number from a specific region.
Parameters:
- numobj: PhoneNumber object containing the short number
- region_dialing_from: Region from which the call would be made
Returns:
ShortNumberCost for the specific region context
"""Check if short numbers are specific to particular carriers.
def is_carrier_specific(numobj: PhoneNumber) -> bool:
"""
Check if a short number is carrier-specific.
Carrier-specific numbers only work when dialed from phones
on specific mobile networks or carriers.
Parameters:
- numobj: PhoneNumber object containing the short number
Returns:
True if the number is carrier-specific, False otherwise
"""
def is_carrier_specific_for_region(numobj: PhoneNumber,
region_dialing_from: str) -> bool:
"""
Check if a short number is carrier-specific for a region.
Parameters:
- numobj: PhoneNumber object containing the short number
- region_dialing_from: Region to check carrier specificity for
Returns:
True if carrier-specific in the region, False otherwise
"""Check if short numbers provide SMS services.
def is_sms_service_for_region(numobj: PhoneNumber, region_dialing_from: str) -> bool:
"""
Check if a short number provides SMS services for a region.
Parameters:
- numobj: PhoneNumber object containing the short number
- region_dialing_from: Region to check SMS service availability
Returns:
True if the number provides SMS services, False otherwise
"""Access information about regions that support short number services.
SUPPORTED_SHORT_REGIONS: list
"""
List of region codes that have short number support.
These are regions for which the library has metadata
about emergency numbers, directory services, and other
short number services.
"""import phonenumbers
def check_emergency_numbers():
"""Check emergency numbers for various regions."""
emergency_tests = [
("911", "US"), # US emergency
("999", "GB"), # UK emergency
("112", "DE"), # EU emergency
("000", "AU"), # Australian emergency
("110", "JP"), # Japanese police
("119", "JP"), # Japanese fire/ambulance
]
print("Emergency Number Validation:")
for number, region in emergency_tests:
is_emergency = phonenumbers.is_emergency_number(number, region)
connects_emergency = phonenumbers.connects_to_emergency_number(number, region)
print(f" {number} in {region}:")
print(f" Is emergency number: {is_emergency}")
print(f" Connects to emergency: {connects_emergency}")
# Example usage
check_emergency_numbers()import phonenumbers
from phonenumbers import ShortNumberCost
def analyze_short_number(number_str, region):
"""Comprehensive analysis of a short number."""
try:
# Parse as short number (no country code)
number = phonenumbers.parse(number_str, region)
# Basic validation
is_valid = phonenumbers.is_valid_short_number_for_region(number, region)
is_possible = phonenumbers.is_possible_short_number_for_region(number, region)
# Emergency services
is_emergency = phonenumbers.is_emergency_number(number_str, region)
connects_emergency = phonenumbers.connects_to_emergency_number(number_str, region)
# Cost information
cost = phonenumbers.expected_cost_for_region(number, region)
cost_names = {
ShortNumberCost.TOLL_FREE: "Toll Free",
ShortNumberCost.STANDARD_RATE: "Standard Rate",
ShortNumberCost.PREMIUM_RATE: "Premium Rate",
ShortNumberCost.UNKNOWN_COST: "Unknown Cost"
}
# Carrier and SMS info
is_carrier_specific = phonenumbers.is_carrier_specific_for_region(number, region)
provides_sms = phonenumbers.is_sms_service_for_region(number, region)
return {
'number': number_str,
'region': region,
'is_valid': is_valid,
'is_possible': is_possible,
'is_emergency': is_emergency,
'connects_to_emergency': connects_emergency,
'cost': cost_names.get(cost, "Unknown"),
'is_carrier_specific': is_carrier_specific,
'provides_sms': provides_sms
}
except phonenumbers.NumberParseException as e:
return {
'number': number_str,
'region': region,
'error': str(e)
}
# Example usage
short_numbers = [
("911", "US"), # US emergency
("411", "US"), # US directory assistance
("611", "US"), # US customer service
("999", "GB"), # UK emergency
("100", "GB"), # UK operator
("112", "DE"), # EU-wide emergency
]
print("Short Number Analysis:")
for number, region in short_numbers:
analysis = analyze_short_number(number, region)
if 'error' in analysis:
print(f"\n{number} ({region}): Parse Error - {analysis['error']}")
continue
print(f"\n{number} ({region}):")
print(f" Valid: {analysis['is_valid']}")
print(f" Possible: {analysis['is_possible']}")
print(f" Emergency: {analysis['is_emergency']}")
print(f" Cost: {analysis['cost']}")
print(f" Carrier Specific: {analysis['is_carrier_specific']}")
print(f" SMS Service: {analysis['provides_sms']}")import phonenumbers
class EmergencyServiceDirectory:
"""Directory of emergency services by region."""
def __init__(self):
self.known_emergency_patterns = {
# Common emergency numbers to test
"US": ["911", "112"],
"GB": ["999", "112"],
"DE": ["110", "112", "116117"],
"FR": ["15", "17", "18", "112"],
"AU": ["000", "112"],
"JP": ["110", "119"],
"CN": ["110", "119", "120"],
"IN": ["100", "101", "102", "108", "112"],
"BR": ["190", "193", "199"],
"CA": ["911", "112"]
}
def get_emergency_numbers(self, region_code):
"""Get confirmed emergency numbers for a region."""
emergency_numbers = []
if region_code not in phonenumbers.SUPPORTED_SHORT_REGIONS:
return {"error": f"Short numbers not supported for region {region_code}"}
# Test known patterns
test_numbers = self.known_emergency_patterns.get(region_code, [])
for number in test_numbers:
if phonenumbers.is_emergency_number(number, region_code):
emergency_numbers.append({
'number': number,
'connects_to_emergency': phonenumbers.connects_to_emergency_number(number, region_code)
})
return {
'region': region_code,
'emergency_numbers': emergency_numbers
}
def generate_emergency_guide(self, regions):
"""Generate emergency number guide for multiple regions."""
guide = {}
for region in regions:
info = self.get_emergency_numbers(region)
if 'error' not in info:
guide[region] = info['emergency_numbers']
return guide
def format_emergency_guide(self, guide):
"""Format emergency guide as readable text."""
output = ["EMERGENCY NUMBERS BY REGION", "=" * 30]
for region, numbers in guide.items():
output.append(f"\n{region}:")
if numbers:
for num_info in numbers:
status = "✓" if num_info['connects_to_emergency'] else "?"
output.append(f" {status} {num_info['number']}")
else:
output.append(" No emergency numbers found")
return "\n".join(output)
# Example usage
directory = EmergencyServiceDirectory()
# Get emergency numbers for specific regions
regions_to_check = ["US", "GB", "DE", "JP", "AU"]
emergency_guide = directory.generate_emergency_guide(regions_to_check)
print("Emergency Services Directory:")
print(directory.format_emergency_guide(emergency_guide))
# Detailed analysis for US
print("\n" + "=" * 50)
print("Detailed US Emergency Number Analysis:")
us_info = directory.get_emergency_numbers("US")
for num_info in us_info['emergency_numbers']:
number = num_info['number']
analysis = analyze_short_number(number, "US")
print(f"\n{number}:")
for key, value in analysis.items():
if key not in ['number', 'region']:
print(f" {key}: {value}")import phonenumbers
class SMSShortCodeValidator:
"""Validator for SMS short codes and services."""
def __init__(self):
self.common_sms_patterns = {
"US": ["22", "737", "4INFO", "GOOGLE", "40404"], # Common US SMS codes
"GB": ["61998", "88088"], # Common UK SMS codes
"DE": ["1212", "8888"], # Common German SMS codes
}
def validate_sms_code(self, code, region):
"""Validate if a code provides SMS services."""
try:
# Try to parse as short number
number = phonenumbers.parse(code, region)
# Check if it's a valid short number
is_valid = phonenumbers.is_valid_short_number_for_region(number, region)
if not is_valid:
return {
'code': code,
'region': region,
'is_valid': False,
'reason': 'Not a valid short number'
}
# Check SMS capability
provides_sms = phonenumbers.is_sms_service_for_region(number, region)
cost = phonenumbers.expected_cost_for_region(number, region)
is_carrier_specific = phonenumbers.is_carrier_specific_for_region(number, region)
return {
'code': code,
'region': region,
'is_valid': True,
'provides_sms': provides_sms,
'cost': cost,
'is_carrier_specific': is_carrier_specific
}
except phonenumbers.NumberParseException:
return {
'code': code,
'region': region,
'is_valid': False,
'reason': 'Parse error'
}
def scan_region_sms_codes(self, region):
"""Scan common SMS codes for a region."""
if region not in self.common_sms_patterns:
return {'error': f'No SMS patterns defined for {region}'}
results = []
for code in self.common_sms_patterns[region]:
validation = self.validate_sms_code(code, region)
results.append(validation)
return {
'region': region,
'codes_tested': len(self.common_sms_patterns[region]),
'results': results
}
# Example usage
validator = SMSShortCodeValidator()
print("SMS Short Code Validation:")
for region in ["US", "GB", "DE"]:
print(f"\n{region} SMS Codes:")
scan_result = validator.scan_region_sms_codes(region)
if 'error' in scan_result:
print(f" {scan_result['error']}")
continue
for result in scan_result['results']:
if result['is_valid']:
sms_status = "✓" if result.get('provides_sms') else "✗"
carrier_status = "(carrier-specific)" if result.get('is_carrier_specific') else ""
print(f" {result['code']}: Valid, SMS {sms_status}, Cost: {result.get('cost')} {carrier_status}")
else:
print(f" {result['code']}: Invalid - {result.get('reason', 'Unknown')}")import phonenumbers
def analyze_short_number_support():
"""Analyze which regions support short number functionality."""
all_regions = phonenumbers.supported_regions()
short_regions = set(phonenumbers.SUPPORTED_SHORT_REGIONS)
print(f"Total regions supported: {len(all_regions)}")
print(f"Regions with short number support: {len(short_regions)}")
print(f"Coverage: {len(short_regions)/len(all_regions)*100:.1f}%")
# Show some regions with short number support
print(f"\nRegions with short number support (first 20):")
for region in sorted(list(short_regions))[:20]:
print(f" {region}")
# Show regions without short number support
no_short_support = all_regions - short_regions
print(f"\nRegions without short number support (first 10):")
for region in sorted(list(no_short_support))[:10]:
print(f" {region}")
def test_emergency_coverage():
"""Test emergency number coverage across regions."""
emergency_coverage = {}
test_numbers = ["911", "999", "112", "000", "110", "119"]
for region in phonenumbers.SUPPORTED_SHORT_REGIONS[:10]: # Test first 10
emergency_coverage[region] = []
for number in test_numbers:
if phonenumbers.is_emergency_number(number, region):
emergency_coverage[region].append(number)
print("\nEmergency Number Coverage (first 10 regions):")
for region, numbers in emergency_coverage.items():
if numbers:
print(f" {region}: {', '.join(numbers)}")
else:
print(f" {region}: No common emergency numbers found")
# Example usage
print("=== Short Number Support Analysis ===")
analyze_short_number_support()
print("\n=== Emergency Number Coverage ===")
test_emergency_coverage()Short numbers vary significantly by region:
Always check cost before directing users to dial short numbers:
Some short numbers only work with specific carriers or in specific circumstances. Always validate carrier-specific restrictions before implementing automated dialing of short numbers.
Install with Tessl CLI
npx tessl i tessl/pypi-phonenumberslite