Skip to content

Commit 4fb12ca

Browse files
committed
Merge upstream r231 (except geocoding functionality)
1 parent 8a8feab commit 4fb12ca

8 files changed

Lines changed: 277 additions & 112 deletions

File tree

python/HISTORY

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11

2+
=====================
3+
What's new in 3.6b1
4+
=====================
5+
6+
Merge up to upstream Subversion revision 231 (but
7+
geocoding functionality not yet ported).
8+
Require Python 2.5, to allow import unicodedata.
9+
10+
11+
=====================
12+
What's new in 3.5b2
13+
=====================
14+
15+
Fix GH-3: crash in parse() for number with blank metadata
16+
217
=====================
318
What's new in 3.5b1
419
=====================

python/phonenumbers/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@
2626
>>> print formatter.input_digit("5")
2727
65
2828
>>> print formatter.input_digit("0")
29-
(650
29+
650
3030
>>> print formatter.input_digit("2")
31-
(650) 2
31+
650-2
3232
>>> print formatter.input_digit("5")
33-
(650) 25
33+
650-25
3434
>>> print formatter.input_digit("3")
35-
(650) 253
35+
650-253
3636
>>> print formatter.input_digit("2")
3737
650-2532
3838
>>> print formatter.input_digit("2")
@@ -74,7 +74,7 @@
7474

7575
# Version number is taken from the upstream libphonenumber version
7676
# together with an indication of the version of the Python-specific code.
77-
__version__ = "3.5b2"
77+
__version__ = "3.6b1"
7878

7979
# Data class definitions
8080
from phonenumber import PhoneNumber, CountryCodeSource

python/phonenumbers/asyoutypeformatter.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@
2525
# See the License for the specific language governing permissions and
2626
# limitations under the License.
2727
import re
28-
from re_util import fullmatch
2928

29+
import unicode_util
30+
from re_util import fullmatch
3031
from phonemetadata import PhoneMetadata
3132
from phonenumberutil import _VALID_START_CHAR_PATTERN, _VALID_PUNCTUATION
32-
from phonenumberutil import _DIGIT_MAPPINGS, _PLUS_SIGN
33+
from phonenumberutil import _PLUS_SIGN
3334
from phonenumberutil import _extract_country_code, region_code_for_country_code
3435

3536
_EMPTY_METADATA = PhoneMetadata(id=u"", international_prefix=u"NA", register=False)
@@ -90,13 +91,20 @@ def _maybe_create_new_template(self):
9091
When there are multiple available formats, the formatter uses the
9192
first format where a formatting template could be created.
9293
"""
93-
for number_format in self._possible_formats:
94+
ii = 0
95+
while ii < len(self._possible_formats):
96+
number_format = self._possible_formats[ii]
9497
pattern = number_format.pattern
9598
if self._current_formatting_pattern == pattern:
9699
return False
97100
if self._create_formatting_template(number_format):
98101
self._current_formatting_pattern = pattern
99102
return True
103+
else:
104+
# Remove the current number format from _possible_formats
105+
del self._possible_formats[ii]
106+
ii -= 1
107+
ii += 1
100108
self._able_to_format = False
101109
return False
102110

@@ -147,7 +155,7 @@ def _create_formatting_template(self, num_format):
147155
number_pattern = re.sub(_STANDALONE_DIGIT_PATTERN, "\\\\d", number_pattern)
148156
self.formatting_template = ""
149157
temp_template = self._get_formatting_template(number_pattern, num_format.format)
150-
if len(temp_template) > len(self._national_number):
158+
if len(temp_template) > 0:
151159
self._formatting_template = temp_template
152160
return True
153161
return False
@@ -161,7 +169,11 @@ def _get_formatting_template(self, number_pattern, number_format):
161169
number_re = re.compile(number_pattern)
162170
m = number_re.search(longest_phone_number) # this will always succeed
163171
a_phone_number = m.group(0)
164-
172+
# No formatting template can be created if the number of digits
173+
# entered so far is longer than the maximum the current formatting
174+
# rule can accommodate.
175+
if len(a_phone_number) < len(self._national_number):
176+
return u""
165177
# Formats the number according to number_format
166178
template = re.sub(number_pattern, number_format, a_phone_number)
167179
# Replaces each digit with character _DIGIT_PLACEHOLDER
@@ -410,16 +422,19 @@ def _normalize_and_accrue_digits_and_plus_sign(self, next_char, remember_positio
410422
in non-ASCII format. This method assumes its input is either a digit
411423
or the plus sign."""
412424
if next_char == _PLUS_SIGN:
425+
normalized_char = next_char
413426
self._accrued_input_without_formatting += next_char
414427
else:
415-
next_char = _DIGIT_MAPPINGS[next_char]
416-
self._accrued_input_without_formatting += next_char
417-
self._national_number += next_char
418-
428+
next_digit = unicode_util.digit(next_char, -1)
429+
if next_digit != -1:
430+
normalized_char = unicode(next_digit)
431+
else: # pragma no cover
432+
normalized_char = next_char
433+
self._accrued_input_without_formatting += normalized_char
434+
self._national_number += normalized_char
419435
if remember_position:
420436
self._position_to_remember = len(self._accrued_input_without_formatting)
421-
422-
return next_char
437+
return normalized_char
423438

424439
def _input_digit_helper(self, next_char):
425440
digit_match = _DIGIT_PATTERN.search(self._formatting_template, self._last_match_position)

python/phonenumbers/phonenumbermatcher.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
# Extra regexp function; see README
2323
from re_util import fullmatch
24+
import unicode_util
2425
import phonenumberutil
2526

2627

@@ -64,7 +65,7 @@ def _limit(lower, upper):
6465
_DIGIT_BLOCK_LIMIT = (phonenumberutil._MAX_LENGTH_FOR_NSN +
6566
phonenumberutil._MAX_LENGTH_COUNTRY_CODE)
6667
# Limit on the number of blocks separated by punctuation. Use _DIGIT_BLOCK_LIMIT
67-
# since in some formats use spaces to separate each digit.
68+
# since some formats use spaces to separate each digit.
6869
_BLOCK_LIMIT = _limit(0, _DIGIT_BLOCK_LIMIT)
6970

7071
# A punctuation sequence allowing white space.
@@ -73,6 +74,7 @@ def _limit(lower, upper):
7374
_DIGIT_SEQUENCE = u"(?u)\\d" + _limit(1, _DIGIT_BLOCK_LIMIT)
7475
# Punctuation that may be at the start of a phone number - brackets and plus signs.
7576
_LEAD_CLASS = u"[" + _OPENING_PARENS + phonenumberutil._PLUS_CHARS + u"]"
77+
_LEAD_PATTERN = re.compile(_LEAD_CLASS)
7678

7779
# Phone number pattern allowing optional punctuation.
7880
# This is the phone number pattern used by _find(), similar to
@@ -244,6 +246,23 @@ def _trim_after_first_match(self, pattern, candidate):
244246
candidate = candidate[:trailing_chars_match.start()]
245247
return candidate
246248

249+
@classmethod
250+
def _is_latin_letter(self, letter):
251+
"""Helper method to determine if a character is a Latin-script letter
252+
or not. For our purposes, combining marks should also return true
253+
since we assume they have been added to a preceding Latin character."""
254+
# Combining marks are a subset of non-spacing-mark
255+
if (not unicode_util.is_letter(letter) and
256+
unicode_util.Category.get(letter) != unicode_util.Category.NON_SPACING_MARK):
257+
return False
258+
block = unicode_util.Block.get(letter)
259+
return (block == unicode_util.Block.BASIC_LATIN or
260+
block == unicode_util.Block.LATIN_1_SUPPLEMENT or
261+
block == unicode_util.Block.LATIN_EXTENDED_A or
262+
block == unicode_util.Block.LATIN_EXTENDED_ADDITIONAL or
263+
block == unicode_util.Block.LATIN_EXTENDED_B or
264+
block == unicode_util.Block.COMBINING_DIACRITICAL_MARKS)
265+
247266
def _extract_match(self, candidate, offset):
248267
"""Attempts to extract a match from a candidate string.
249268
@@ -258,6 +277,22 @@ def _extract_match(self, candidate, offset):
258277
_SLASH_SEPARATED_DATES.search(candidate)):
259278
return None
260279

280+
# If leniency is set to VALID only, we also want to skip numbers that
281+
# are surrounded by Latin alphabetic characters, to skip cases like
282+
# abc8005001234 or 8005001234def.
283+
if self.leniency == Leniency.VALID:
284+
# If the candidate is not at the start of the text, and does not
285+
# start with punctuation and the previous character is not a Latin
286+
# letter, return None.
287+
if (offset > 0 and
288+
not _LEAD_PATTERN.match(candidate) and
289+
self._is_latin_letter(self.text[offset - 1])):
290+
return None
291+
last_char_index = offset + len(candidate)
292+
if (last_char_index < len(self.text) and
293+
self._is_latin_letter(self.text[last_char_index])):
294+
return None
295+
261296
# Try to come up with a valid match given the entire candidate.
262297
match = self._parse_and_verify(candidate, offset)
263298
if match is not None:
@@ -278,7 +313,7 @@ def _extract_inner_match(self, candidate, offset):
278313
"""
279314
# Try removing either the first or last "group" in the number and see
280315
# if this gives a result. We consider white space to be a possible
281-
# indications of the start or end of the phone number.
316+
# indication of the start or end of the phone number.
282317
group_match = _GROUP_SEPARATOR.search(candidate)
283318
if group_match:
284319
group_start_index = group_match.end()

0 commit comments

Comments
 (0)