Skip to content

Commit d806dc0

Browse files
committed
Merge branch 'dev' into python3
Conflicts: python/phonenumbers/geocoder.py python/tests/geocodertest.py
2 parents 182b6c3 + 2ea483b commit d806dc0

3 files changed

Lines changed: 61 additions & 42 deletions

File tree

python/phonenumbers/__init__.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -120,24 +120,6 @@
120120

121121
# The geodata occupies a lot of space, so only perform the import on first use
122122
# of geocoder functionality.
123-
def area_description_for_number(*args, **kwargs):
124-
"""Return a text description of the area of a PhoneNumber for the given language.
125-
126-
Arguments:
127-
numobj -- The PhoneNumber object for which we want to get a text description.
128-
lang -- A 2-letter lowercase ISO 639-1 language code for the language in
129-
which the description should be returned (e.g. "en")
130-
script -- A 4-letter titlecase (first letter uppercase, rest lowercase)
131-
ISO script code as defined in ISO 15924, separated by an
132-
underscore (e.g. "Hant")
133-
region -- A 2-letter uppercase ISO 3166-1 country code (e.g. "GB")
134-
135-
Returns a text description in the given language code, for the given phone
136-
number's area, or an empty string if no description is available."""
137-
from .geocoder import area_description_for_number as real_fn
138-
return real_fn(*args, **kwargs)
139-
140-
141123
def country_name_for_number(*args, **kwargs):
142124
"""Return the given PhoneNumber object's country name in the given language.
143125
@@ -272,7 +254,6 @@ def description_for_valid_number(*args, **kwargs):
272254
# end of items from phonenumberutil.py
273255
'connects_to_emergency_number', 'is_emergency_number', 'ShortNumberCost',
274256
'PhoneNumberMatch', 'PhoneNumberMatcher', 'Leniency',
275-
'area_description_for_number',
276257
'country_name_for_number',
277258
'description_for_number',
278259
'description_for_valid_number',

python/phonenumbers/geocoder.py

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
"""Phone number geocoding functionality
22
33
>>> import phonenumbers
4-
>>> from phonenumbers.geocoder import area_description_for_number
4+
>>> from phonenumbers.geocoder import description_for_number
55
>>> from phonenumbers.util import u
66
>>> gb_number = phonenumbers.parse("+442083612345", "GB")
77
>>> de_number = phonenumbers.parse("0891234567", "DE")
88
>>> ch_number = phonenumbers.parse("0431234567", "CH")
9-
>>> str(area_description_for_number(gb_number, "en"))
9+
>>> str(description_for_number(gb_number, "en"))
1010
'London'
11-
>>> str(area_description_for_number(gb_number, "fr")) # fall back to English
11+
>>> str(description_for_number(gb_number, "fr")) # fall back to English
1212
'London'
13-
>>> str(area_description_for_number(gb_number, "en", region="GB"))
13+
>>> str(description_for_number(gb_number, "en", region="GB"))
1414
'London'
15-
>>> str(area_description_for_number(gb_number, "en", region="US"))
16-
'London'
17-
>>> str(area_description_for_number(de_number, "en"))
15+
>>> str(description_for_number(gb_number, "en", region="US")) # fall back to country
16+
'United Kingdom'
17+
>>> str(description_for_number(de_number, "en"))
1818
'Munich'
19-
>>> u('M\u00fcnchen') == area_description_for_number(de_number, "de")
19+
>>> u('M\u00fcnchen') == description_for_number(de_number, "de")
2020
True
21-
>>> u('Z\u00fcrich') == area_description_for_number(ch_number, "de")
21+
>>> u('Z\u00fcrich') == description_for_number(ch_number, "de")
2222
True
23-
>>> str(area_description_for_number(ch_number, "en"))
23+
>>> str(description_for_number(ch_number, "en"))
2424
'Zurich'
25-
>>> str(area_description_for_number(ch_number, "fr"))
25+
>>> str(description_for_number(ch_number, "fr"))
2626
'Zurich'
27-
>>> str(area_description_for_number(ch_number, "it"))
27+
>>> str(description_for_number(ch_number, "it"))
2828
'Zurigo'
2929
3030
"""
@@ -66,6 +66,9 @@
6666
raise
6767

6868

69+
_LOCALE_NORMALIZATION_MAP = {"zh_TW": "zh_Hant", "zh_HK": "zh_Hant", "zh_MO": "zh_Hant"}
70+
71+
6972
def _may_fall_back_to_english(lang):
7073
# Don't fall back to English if the requested language is among the following:
7174
# - Chinese
@@ -74,16 +77,38 @@ def _may_fall_back_to_english(lang):
7477
return lang != "zh" and lang != "ja" and lang != "ko"
7578

7679

80+
def _full_locale(lang, script, region):
81+
if script is not None:
82+
if region is not None:
83+
return "%s_%s_%s" % (lang, script, region)
84+
else:
85+
return "%s_%s" % (lang, script)
86+
elif region is not None:
87+
return "%s_%s" % (lang, region)
88+
else:
89+
return lang
90+
91+
7792
def _find_lang(langdict, lang, script, region):
7893
"""Return the entry in the dictionary for the given language information."""
79-
# First look for lang, script as a combination
80-
lang_script = "%s_%s" % (lang, script)
81-
if lang_script in langdict:
82-
return langdict[lang_script]
94+
# Check if we should map this to a different locale.
95+
full_locale = _full_locale(lang, script, region)
96+
if (full_locale in _LOCALE_NORMALIZATION_MAP and
97+
_LOCALE_NORMALIZATION_MAP[full_locale] in langdict):
98+
return langdict[_LOCALE_NORMALIZATION_MAP[full_locale]]
99+
# First look for the full locale
100+
if full_locale in langdict:
101+
return langdict[full_locale]
102+
# Then look for lang, script as a combination
103+
if script is not None:
104+
lang_script = "%s_%s" % (lang, script)
105+
if lang_script in langdict:
106+
return langdict[lang_script]
83107
# Next look for lang, region as a combination
84-
lang_region = "%s_%s" % (lang, region)
85-
if lang_region in langdict:
86-
return langdict[lang_region]
108+
if region is not None:
109+
lang_region = "%s_%s" % (lang, region)
110+
if lang_region in langdict:
111+
return langdict[lang_region]
87112
# Fall back to bare language code lookup
88113
if lang in langdict:
89114
return langdict[lang]
@@ -94,7 +119,7 @@ def _find_lang(langdict, lang, script, region):
94119
return None
95120

96121

97-
def area_description_for_number(numobj, lang, script=None, region=None):
122+
def _area_description_for_number(numobj, lang, script=None, region=None):
98123
"""Return a text description of the area of a PhoneNumber for the given language.
99124
100125
Arguments:
@@ -199,7 +224,7 @@ def description_for_valid_number(numobj, lang, script=None, region=None):
199224
number, or an empty string if no description is available."""
200225
number_region = region_code_for_number(numobj)
201226
if region is None or region == number_region:
202-
area_description = area_description_for_number(numobj, lang, script, region)
227+
area_description = _area_description_for_number(numobj, lang, script, region)
203228
if area_description != "":
204229
return area_description
205230
else:

python/tests/geocodertest.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
from phonenumbers import PhoneNumber, FrozenPhoneNumber
2323
from phonenumbers import geocoder
2424
from phonenumbers import description_for_number, country_name_for_number
25-
from phonenumbers import description_for_valid_number, area_description_for_number
25+
from phonenumbers import description_for_valid_number
26+
from phonenumbers.geocoder import _area_description_for_number
2627
from phonenumbers.util import u
2728

2829
# Allow override library geocoding metadata with the test metadata.
@@ -162,13 +163,14 @@ def testCoverage(self):
162163
invalid_number = PhoneNumber(country_code=210, national_number=123456)
163164
self.assertEqual("", country_name_for_number(invalid_number, "en"))
164165
# Ensure we exercise all public entrypoints directly
165-
self.assertEqual("CA", area_description_for_number(US_NUMBER1, "en"))
166+
self.assertEqual("CA", _area_description_for_number(US_NUMBER1, "en"))
166167
self.assertEqual("CA", description_for_valid_number(US_NUMBER1, "en"))
167168
self.assertEqual("", description_for_valid_number(US_INVALID_NUMBER, "en"))
168169
# Add in some script and region specific fictional names
169170
TEST_GEOCODE_DATA['1650960'] = {'en': u("Mountain View, CA"),
170171
"en_GB": u("Mountain View California"),
171172
"en_US": u("Mountain View, Sunny California"),
173+
"en_Xyzz_US": u("MTV - xyzz"),
172174
"en_Latn": u("MountainView")}
173175
# The following test might one day return "Mountain View California"
174176
self.assertEqual("United States",
@@ -179,7 +181,18 @@ def testCoverage(self):
179181
description_for_number(US_NUMBER2, _ENGLISH, script="Latn"))
180182
self.assertEqual("United States",
181183
description_for_number(US_NUMBER2, _ENGLISH, script="Latn", region="GB"))
184+
self.assertEqual("MTV - xyzz",
185+
description_for_number(US_NUMBER2, _ENGLISH, script="Xyzz", region="US"))
186+
self.assertEqual("Mountain View, Sunny California",
187+
description_for_number(US_NUMBER2, _ENGLISH, script="Zazz", region="US"))
182188
# Get a different result when there is a script-specific variant
183189
self.assertEqual("MountainView",
184190
description_for_number(US_NUMBER2, _ENGLISH, script="Latn", region="US"))
185191
TEST_GEOCODE_DATA['1650960'] = {'en': u("Mountain View, CA")}
192+
193+
# Test the locale mapping
194+
TEST_GEOCODE_DATA['8868'] = {'zh': u("Chinese"), 'zh_Hant': u("Hant-specific")}
195+
tw_number = FrozenPhoneNumber(country_code=886, national_number=810080123)
196+
self.assertEqual("Hant-specific",
197+
description_for_number(tw_number, "zh", region="TW"))
198+
del TEST_GEOCODE_DATA['8868']

0 commit comments

Comments
 (0)