/usr/lib/python3/dist-packages/phonenumbers/geocoder.py is in python3-phonenumbers 8.8.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | """Phone number geocoding functionality
>>> import phonenumbers
>>> from phonenumbers.geocoder import description_for_number
>>> from phonenumbers.util import u
>>> gb_number = phonenumbers.parse("+442083612345", "GB")
>>> de_number = phonenumbers.parse("0891234567", "DE")
>>> ch_number = phonenumbers.parse("0431234567", "CH")
>>> str(description_for_number(gb_number, "en"))
'London'
>>> str(description_for_number(gb_number, "fr")) # fall back to English
'London'
>>> str(description_for_number(gb_number, "en", region="GB"))
'London'
>>> str(description_for_number(gb_number, "en", region="US")) # fall back to country
'United Kingdom'
>>> str(description_for_number(de_number, "en"))
'Munich'
>>> u('M\u00fcnchen') == description_for_number(de_number, "de")
True
>>> u('Z\u00fcrich') == description_for_number(ch_number, "de")
True
>>> str(description_for_number(ch_number, "en"))
'Zurich'
>>> str(description_for_number(ch_number, "fr"))
'Zurich'
>>> str(description_for_number(ch_number, "it"))
'Zurigo'
"""
# Based very loosely on original Java code:
# java/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java
# Copyright (C) 2009-2011 The Libphonenumber Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .util import prnt, unicod, u, U_EMPTY_STRING, U_ZERO
from .phonenumberutil import region_code_for_number, PhoneNumberType, PhoneNumber
from .phonenumberutil import country_mobile_token, national_significant_number, number_type
from .phonenumberutil import region_code_for_country_code, region_codes_for_country_code
from .phonenumberutil import is_valid_number_for_region, parse, NumberParseException
from .phonenumberutil import is_number_type_geographical
from .prefix import _prefix_description_for_number
try:
from .geodata import GEOCODE_DATA, GEOCODE_LONGEST_PREFIX
from .geodata.locale import LOCALE_DATA
except ImportError: # pragma no cover
# Before the generated code exists, the geodata/ directory is empty.
# The generation process imports this module, creating a circular
# dependency. The hack below works around this.
import os
import sys
if (os.path.basename(sys.argv[0]) == "buildmetadatafromxml.py" or
os.path.basename(sys.argv[0]) == "buildprefixdata.py"):
prnt("Failed to import generated data (but OK as during autogeneration)", file=sys.stderr)
GEOCODE_DATA = {'1': {'en': u('United States')}}
GEOCODE_LONGEST_PREFIX = 1
LOCALE_DATA = {'US': {'en': u('United States')}}
else:
raise
__all__ = ['country_name_for_number', 'description_for_valid_number', 'description_for_number']
def country_name_for_number(numobj, lang, script=None, region=None):
"""Returns the customary display name in the given langauge for the given
territory the given PhoneNumber object is from. If it could be from many
territories, nothing is returned.
Arguments:
numobj -- The PhoneNumber object for which we want to get a text description.
lang -- A 2-letter lowercase ISO 639-1 language code for the language in
which the description should be returned (e.g. "en")
script -- A 4-letter titlecase (first letter uppercase, rest lowercase)
ISO script code as defined in ISO 15924, separated by an
underscore (e.g. "Hant")
region -- A 2-letter uppercase ISO 3166-1 country code (e.g. "GB")
The script and region parameters are currently ignored.
Returns a text description in the given language code, for the given phone
number's region, or an empty string if no description is available."""
region_codes = region_codes_for_country_code(numobj.country_code)
if len(region_codes) == 1:
return _region_display_name(region_codes[0], lang, script, region)
else:
region_where_number_is_valid = u("ZZ")
for region_code in region_codes:
if is_valid_number_for_region(numobj, region_code):
# If the number has already been found valid for one region,
# then we don't know which region it belongs to so we return
# nothing.
if region_where_number_is_valid != u("ZZ"):
return U_EMPTY_STRING
region_where_number_is_valid = region_code
return _region_display_name(region_where_number_is_valid, lang, script, region)
def _region_display_name(region_code, lang, script=None, region=None):
if region_code in LOCALE_DATA:
# The Locale data has a set of names for this region, in various languages.
name = LOCALE_DATA[region_code].get(lang, "")
if name.startswith('*'):
# If the location name is "*<other_lang>", this indicates that the
# name is held elsewhere, specifically in the [other_lang] entry
other_lang = name[1:]
name = LOCALE_DATA[region_code].get(other_lang, "")
return unicod(name)
return U_EMPTY_STRING
def description_for_valid_number(numobj, lang, script=None, region=None):
"""Return a text description of a PhoneNumber object, in the language
provided.
The description might consist of the name of the country where the phone
number is from and/or the name of the geographical area the phone number
is from if more detailed information is available.
If the phone number is from the same region as the user, only a
lower-level description will be returned, if one exists. Otherwise, the
phone number's region will be returned, with optionally some more detailed
information.
For example, for a user from the region "US" (United States), we would
show "Mountain View, CA" for a particular number, omitting the United
States from the description. For a user from the United Kingdom (region
"GB"), for the same number we may show "Mountain View, CA, United States"
or even just "United States".
This function assumes the validity of the number passed in has already
been checked, and that the number is suitable for geocoding. We consider
fixed-line and mobile numbers possible candidates for geocoding.
Arguments:
numobj -- A valid PhoneNumber object for which we want to get a text
description.
lang -- A 2-letter lowercase ISO 639-1 language code for the language in
which the description should be returned (e.g. "en")
script -- A 4-letter titlecase (first letter uppercase, rest lowercase)
ISO script code as defined in ISO 15924, separated by an
underscore (e.g. "Hant")
region -- The region code for a given user. This region will be omitted
from the description if the phone number comes from this
region. It should be a two-letter upper-case CLDR region
code.
Returns a text description in the given language code, for the given phone
number, or an empty string if the number could come from multiple countries,
or the country code is in fact invalid."""
number_region = region_code_for_number(numobj)
if region is None or region == number_region:
mobile_token = country_mobile_token(numobj.country_code)
national_number = national_significant_number(numobj)
if mobile_token != U_EMPTY_STRING and national_number.startswith(mobile_token):
# In some countries, eg. Argentina, mobile numbers have a mobile token
# before the national destination code, this should be removed before
# geocoding.
national_number = national_number[len(mobile_token):]
region = region_code_for_country_code(numobj.country_code)
try:
copied_numobj = parse(national_number, region)
except NumberParseException:
# If this happens, just re-use what we had.
copied_numobj = numobj
area_description = _prefix_description_for_number(GEOCODE_DATA, GEOCODE_LONGEST_PREFIX,
copied_numobj, lang, script, region)
else:
area_description = _prefix_description_for_number(GEOCODE_DATA, GEOCODE_LONGEST_PREFIX,
numobj, lang, script, region)
if area_description != "":
return area_description
else:
# Fall back to the description of the number's region
return country_name_for_number(numobj, lang, script, region)
else:
# Otherwise, we just show the region(country) name for now.
return _region_display_name(number_region, lang, script, region)
# TODO: Concatenate the lower-level and country-name information in an
# appropriate way for each language.
def description_for_number(numobj, lang, script=None, region=None):
"""Return a text description of a PhoneNumber object for the given language.
The description might consist of the name of the country where the phone
number is from and/or the name of the geographical area the phone number
is from. This function explicitly checks the validity of the number passed in
Arguments:
numobj -- The PhoneNumber object for which we want to get a text description.
lang -- A 2-letter lowercase ISO 639-1 language code for the language in
which the description should be returned (e.g. "en")
script -- A 4-letter titlecase (first letter uppercase, rest lowercase)
ISO script code as defined in ISO 15924, separated by an
underscore (e.g. "Hant")
region -- The region code for a given user. This region will be omitted
from the description if the phone number comes from this
region. It should be a two-letter upper-case CLDR region
code.
Returns a text description in the given language code, for the given phone
number, or an empty string if no description is available."""
ntype = number_type(numobj)
if ntype == PhoneNumberType.UNKNOWN:
return ""
elif not is_number_type_geographical(ntype, numobj.country_code):
return country_name_for_number(numobj, lang, script, region)
return description_for_valid_number(numobj, lang, script, region)
if __name__ == '__main__': # pragma no cover
import doctest
doctest.testmod()
|