Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/phonenumbers/asyoutypeformatter.py: 10%

302 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1"""A formatter which formats phone numbers as they are entered. 

2 

3An AsYouTypeFormatter can be created by invoking 

4AsYouTypeFormatter(region_code). After that digits can be added by invoking 

5input_digit() on the formatter instance, and the partially formatted phone 

6number will be returned each time a digit is added. clear() should be invoked 

7before a new number needs to be formatted. 

8 

9See the unit tests for more details on how the formatter is to be used. 

10""" 

11 

12# Based on original Java code: 

13# java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java 

14# Copyright (C) 2009-2011 The Libphonenumber Authors 

15# 

16# Licensed under the Apache License, Version 2.0 (the "License"); 

17# you may not use this file except in compliance with the License. 

18# You may obtain a copy of the License at 

19# 

20# http://www.apache.org/licenses/LICENSE-2.0 

21# 

22# Unless required by applicable law or agreed to in writing, software 

23# distributed under the License is distributed on an "AS IS" BASIS, 

24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

25# See the License for the specific language governing permissions and 

26# limitations under the License. 

27import re 

28 

29from .util import u, unicod, U_EMPTY_STRING, U_SPACE 

30from .unicode_util import digit as unicode_digit 

31from .re_util import fullmatch 

32from .phonemetadata import PhoneMetadata, REGION_CODE_FOR_NON_GEO_ENTITY 

33from .phonenumberutil import _VALID_PUNCTUATION 

34from .phonenumberutil import _PLUS_SIGN, _PLUS_CHARS_PATTERN 

35from .phonenumberutil import _extract_country_code, region_code_for_country_code 

36from .phonenumberutil import country_code_for_region, normalize_diallable_chars_only 

37from .phonenumberutil import _formatting_rule_has_first_group_only 

38 

39# Character used when appropriate to separate a prefix, such as a long NDD or 

40# a country calling code, from the national number. 

41_SEPARATOR_BEFORE_NATIONAL_NUMBER = U_SPACE 

42_EMPTY_METADATA = PhoneMetadata(id=unicod(""), 

43 international_prefix=unicod("NA"), 

44 register=False) 

45 

46# A set of characters that, if found in a national prefix formatting rules, are an indicator to 

47# us that we should separate the national prefix from the number when formatting. 

48_NATIONAL_PREFIX_SEPARATORS_PATTERN = re.compile("[- ]") 

49 

50# A pattern that is used to determine if a number_format under 

51# available_formats is eligible to be used by the AYTF. It is eligible when 

52# the format element under number_format contains groups of the dollar sign 

53# followed by a single digit, separated by valid phone number 

54# punctuation. This prevents invalid punctuation (such as the star sign in 

55# Israeli star numbers) getting into the output of the AYTF. We require that 

56# the first group is present in the output pattern to ensure no data is lost 

57# while formatting; when we format as you type, this should always be the case. 

58_ELIGIBLE_FORMAT_PATTERN = re.compile(unicod("[") + _VALID_PUNCTUATION + unicod("]*") + 

59 unicod("\\\\1") + unicod("[") + _VALID_PUNCTUATION + unicod("]*") + 

60 unicod("(\\\\\\d") + unicod("[") + _VALID_PUNCTUATION + unicod("]*)*")) 

61 

62# This is the minimum length of national number accrued that is required to 

63# trigger the formatter. The first element of the leading_digits_pattern of each 

64# number_format contains a regular expression that matches up to this number of 

65# digits. 

66_MIN_LEADING_DIGITS_LENGTH = 3 

67# The digits that have not been entered yet will be represented by a \u2008, 

68# the punctuation space. 

69_DIGIT_PLACEHOLDER = u("\u2008") 

70_DIGIT_PATTERN = re.compile(_DIGIT_PLACEHOLDER) 

71 

72 

73def _get_metadata_for_region(region_code): 

74 """The metadata needed by this class is the same for all regions 

75 sharing the same country calling code. Therefore, we return the 

76 metadata for "main" region for this country calling code.""" 

77 country_calling_code = country_code_for_region(region_code) 

78 main_country = region_code_for_country_code(country_calling_code) 

79 # Set to a default instance of the metadata. This allows us to 

80 # function with an incorrect region code, even if formatting only 

81 # works for numbers specified with "+". 

82 return PhoneMetadata.metadata_for_region(main_country, _EMPTY_METADATA) 

83 

84 

85class AsYouTypeFormatter(object): 

86 def __init__(self, region_code): 

87 """Gets an AsYouTypeFormatter for the specific region. 

88 

89 Arguments: 

90 region_code -- The region where the phone number is being entered 

91 

92 Return an AsYouTypeFormatter} object, which could be used to format 

93 phone numbers in the specific region "as you type" 

94 """ 

95 self._clear() 

96 self._default_country = region_code.upper() 

97 self._current_metadata = _get_metadata_for_region(self._default_country) 

98 self._default_metadata = self._current_metadata 

99 

100 def _maybe_create_new_template(self): 

101 """Returns True if a new template is created as opposed to reusing the existing template. 

102 

103 When there are multiple available formats, the formatter uses the 

104 first format where a formatting template could be created. 

105 """ 

106 ii = 0 

107 while ii < len(self._possible_formats): 

108 number_format = self._possible_formats[ii] 

109 pattern = number_format.pattern 

110 if self._current_formatting_pattern == pattern: 

111 return False 

112 if self._create_formatting_template(number_format): 

113 self._current_formatting_pattern = pattern 

114 if number_format.national_prefix_formatting_rule is None: 

115 self._should_add_space_after_national_prefix = False 

116 else: 

117 self._should_add_space_after_national_prefix = bool(_NATIONAL_PREFIX_SEPARATORS_PATTERN.search(number_format.national_prefix_formatting_rule)) 

118 # With a new formatting template, the matched position using 

119 # the old template needs to be reset. 

120 self._last_match_position = 0 

121 return True 

122 else: 

123 # Remove the current number format from _possible_formats 

124 del self._possible_formats[ii] 

125 ii -= 1 

126 ii += 1 

127 self._able_to_format = False 

128 return False 

129 

130 def _get_available_formats(self, leading_digits): 

131 # First decide whether we should use international or national number rules. 

132 is_international_number = (self._is_complete_number and len(self._extracted_national_prefix) == 0) 

133 if (is_international_number and 

134 len(self._current_metadata.intl_number_format) > 0): 

135 format_list = self._current_metadata.intl_number_format 

136 else: 

137 format_list = self._current_metadata.number_format 

138 for this_format in format_list: 

139 # Discard a few formats that we know are not relevant based on the presence of the national 

140 # prefix. 

141 if (len(self._extracted_national_prefix) > 0 and 

142 _formatting_rule_has_first_group_only(this_format.national_prefix_formatting_rule) and 

143 not this_format.national_prefix_optional_when_formatting and 

144 not (this_format.domestic_carrier_code_formatting_rule is not None)): 

145 # If it is a national number that had a national prefix, any rules that aren't valid with a 

146 # national prefix should be excluded. A rule that has a carrier-code formatting rule is 

147 # kept since the national prefix might actually be an extracted carrier code - we don't 

148 # distinguish between these when extracting it in the AYTF. 

149 continue 

150 elif (len(self._extracted_national_prefix) == 0 and 

151 not self._is_complete_number and 

152 not _formatting_rule_has_first_group_only(this_format.national_prefix_formatting_rule) and 

153 not this_format.national_prefix_optional_when_formatting): 

154 # This number was entered without a national prefix, and this formatting rule requires one, 

155 # so we discard it. 

156 continue 

157 if fullmatch(_ELIGIBLE_FORMAT_PATTERN, this_format.format): 

158 self._possible_formats.append(this_format) 

159 self._narrow_down_possible_formats(leading_digits) 

160 

161 def _narrow_down_possible_formats(self, leading_digits): 

162 index_of_leading_digits_pattern = len(leading_digits) - _MIN_LEADING_DIGITS_LENGTH 

163 ii = 0 

164 while ii < len(self._possible_formats): 

165 num_format = self._possible_formats[ii] 

166 ii += 1 

167 if len(num_format.leading_digits_pattern) == 0: 

168 # Keep everything that isn't restricted by leading digits. 

169 continue 

170 last_leading_digits_pattern = min(index_of_leading_digits_pattern, 

171 len(num_format.leading_digits_pattern) - 1) 

172 leading_digits_pattern = re.compile(num_format.leading_digits_pattern[last_leading_digits_pattern]) 

173 m = leading_digits_pattern.match(leading_digits) 

174 if not m: 

175 # remove the element we've just examined, now at (ii-1) 

176 ii -= 1 

177 self._possible_formats.pop(ii) 

178 

179 def _create_formatting_template(self, num_format): 

180 number_pattern = num_format.pattern 

181 self.formatting_template = U_EMPTY_STRING 

182 temp_template = self._get_formatting_template(number_pattern, num_format.format) 

183 if len(temp_template) > 0: 

184 self._formatting_template = temp_template 

185 return True 

186 return False 

187 

188 def _get_formatting_template(self, number_pattern, number_format): 

189 """Gets a formatting template which can be used to efficiently 

190 format a partial number where digits are added one by one.""" 

191 # Create a phone number consisting only of the digit 9 that matches the 

192 # number_pattern by applying the pattern to the longest_phone_number string. 

193 longest_phone_number = unicod("999999999999999") 

194 number_re = re.compile(number_pattern) 

195 m = number_re.search(longest_phone_number) # this will always succeed 

196 a_phone_number = m.group(0) 

197 # No formatting template can be created if the number of digits 

198 # entered so far is longer than the maximum the current formatting 

199 # rule can accommodate. 

200 if len(a_phone_number) < len(self._national_number): 

201 return U_EMPTY_STRING 

202 # Formats the number according to number_format 

203 template = re.sub(number_pattern, number_format, a_phone_number) 

204 # Replaces each digit with character _DIGIT_PLACEHOLDER 

205 template = re.sub("9", _DIGIT_PLACEHOLDER, template) 

206 return template 

207 

208 def _clear(self): 

209 """Clears the internal state of the formatter, so it can be reused.""" 

210 self._current_output = U_EMPTY_STRING 

211 self._accrued_input = U_EMPTY_STRING 

212 self._accrued_input_without_formatting = U_EMPTY_STRING 

213 self._formatting_template = U_EMPTY_STRING 

214 self._last_match_position = 0 

215 

216 # The pattern from number_format that is currently used to create 

217 # formatting_template. 

218 self._current_formatting_pattern = U_EMPTY_STRING 

219 # This contains anything that has been entered so far preceding the 

220 # national significant number, and it is formatted (e.g. with space 

221 # inserted). For example, this can contain IDD, country code, and/or 

222 # NDD, etc. 

223 self._prefix_before_national_number = U_EMPTY_STRING 

224 self._should_add_space_after_national_prefix = False 

225 # This contains the national prefix that has been extracted. It 

226 # contains only digits without formatting. 

227 self._extracted_national_prefix = U_EMPTY_STRING 

228 self._national_number = U_EMPTY_STRING 

229 # This indicates whether AsYouTypeFormatter is currently doing the 

230 # formatting. 

231 self._able_to_format = True 

232 # Set to true when users enter their own 

233 # formatting. AsYouTypeFormatter will do no formatting at all when 

234 # this is set to True. 

235 self._input_has_formatting = False 

236 # The position of a digit upon which input_digit(remember_position=True) is 

237 # most recently invoked, as found in accrued_input_without_formatting. 

238 self._position_to_remember = 0 

239 # The position of a digit upon which input_digit(remember_position=True) is 

240 # most recently invoked, as found in the original sequence of 

241 # characters the user entered. 

242 self._original_position = 0 

243 # This is set to true when we know the user is entering a full 

244 # national significant number, since we have either detected a 

245 # national prefix or an international dialing prefix. When this is 

246 # true, we will no longer use local number formatting patterns. 

247 self._is_complete_number = False 

248 self._is_expecting_country_calling_code = False 

249 self._possible_formats = [] 

250 

251 def clear(self): 

252 """Clears the internal state of the formatter, so it can be reused.""" 

253 self._clear() 

254 if self._current_metadata != self._default_metadata: 

255 self._current_metadata = _get_metadata_for_region(self._default_country) 

256 

257 def input_digit(self, next_char, remember_position=False): 

258 """Formats a phone number on-the-fly as each digit is entered. 

259 

260 If remember_position is set, remembers the position where next_char is 

261 inserted, so that it can be retrieved later by using 

262 get_remembered_position. The remembered position will be automatically 

263 adjusted if additional formatting characters are later 

264 inserted/removed in front of next_char. 

265 

266 Arguments: 

267 

268 next_char -- The most recently entered digit of a phone 

269 number. Formatting characters are allowed, but as soon as they 

270 are encountered this method formats the number as entered and 

271 not "as you type" anymore. Full width digits and Arabic-indic 

272 digits are allowed, and will be shown as they are. 

273 remember_position -- Whether to track the position where next_char is 

274 inserted. 

275 

276 Returns the partially formatted phone number. 

277 """ 

278 self._accrued_input += next_char 

279 if remember_position: 

280 self._original_position = len(self._accrued_input) 

281 # We do formatting on-the-fly only when each character entered is 

282 # either a digit, or a plus sign (accepted at the start of the number 

283 # only). 

284 if not self._is_digit_or_leading_plus_sign(next_char): 

285 self._able_to_format = False 

286 self._input_has_formatting = True 

287 else: 

288 next_char = self._normalize_and_accrue_digits_and_plus_sign(next_char, remember_position) 

289 if not self._able_to_format: 

290 # When we are unable to format because of reasons other than that 

291 # formatting chars have been entered, it can be due to really long 

292 # IDDs or NDDs. If that is the case, we might be able to do 

293 # formatting again after extracting them. 

294 if self._input_has_formatting: 

295 self._current_output = self._accrued_input 

296 return self._current_output 

297 elif self._attempt_to_extract_idd(): 

298 if self._attempt_to_extract_ccc(): 

299 self._current_output = self._attempt_to_choose_pattern_with_prefix_extracted() 

300 return self._current_output 

301 elif self._able_to_extract_longer_ndd(): 

302 # Add an additional space to separate long NDD and national 

303 # significant number for readability. We don't set 

304 # should_add_space_after_national_prefix to True, since we don't 

305 # want this to change later when we choose formatting 

306 # templates. 

307 self._prefix_before_national_number += _SEPARATOR_BEFORE_NATIONAL_NUMBER 

308 self._current_output = self._attempt_to_choose_pattern_with_prefix_extracted() 

309 return self._current_output 

310 

311 self._current_output = self._accrued_input 

312 return self._current_output 

313 

314 # We start to attempt to format only when at least 

315 # MIN_LEADING_DIGITS_LENGTH digits (the plus sign is counted as a 

316 # digit as well for this purpose) have been entered. 

317 len_input = len(self._accrued_input_without_formatting) 

318 if len_input >= 0 and len_input <= 2: 

319 self._current_output = self._accrued_input 

320 return self._current_output 

321 elif len_input == 3: 

322 if self._attempt_to_extract_idd(): 

323 self._is_expecting_country_calling_code = True 

324 else: 

325 # No IDD or plus sign is found, might be entering in national format. 

326 self._extracted_national_prefix = self._remove_national_prefix_from_national_number() 

327 self._current_output = self._attempt_to_choose_formatting_pattern() 

328 return self._current_output 

329 if self._is_expecting_country_calling_code: 

330 if self._attempt_to_extract_ccc(): 

331 self._is_expecting_country_calling_code = False 

332 self._current_output = self._prefix_before_national_number + self._national_number 

333 return self._current_output 

334 

335 if len(self._possible_formats) > 0: # The formatting patterns are already chosen. 

336 temp_national_number = self._input_digit_helper(next_char) 

337 # See if the accrued digits can be formatted properly already. If 

338 # not, use the results from input_digit_helper, which does 

339 # formatting based on the formatting pattern chosen. 

340 formatted_number = self._attempt_to_format_accrued_digits() 

341 if len(formatted_number) > 0: 

342 self._current_output = formatted_number 

343 return self._current_output 

344 self._narrow_down_possible_formats(self._national_number) 

345 if self._maybe_create_new_template(): 

346 self._current_output = self._input_accrued_national_number() 

347 return self._current_output 

348 if self._able_to_format: 

349 self._current_output = self._append_national_number(temp_national_number) 

350 return self._current_output 

351 else: 

352 self._current_output = self._accrued_input 

353 return self._current_output 

354 else: 

355 self._current_output = self._attempt_to_choose_formatting_pattern() 

356 return self._current_output 

357 

358 def _attempt_to_choose_pattern_with_prefix_extracted(self): 

359 self._able_to_format = True 

360 self._is_expecting_country_calling_code = False 

361 self._possible_formats = [] 

362 self._last_match_position = 0 

363 self._formatting_template = U_EMPTY_STRING 

364 self._current_formatting_pattern = U_EMPTY_STRING 

365 return self._attempt_to_choose_formatting_pattern() 

366 

367 # Some national prefixes are a substring of others. If extracting the 

368 # shorter NDD doesn't result in a number we can format, we try to see if 

369 # we can extract a longer version here. 

370 def _able_to_extract_longer_ndd(self): 

371 if len(self._extracted_national_prefix) > 0: 

372 # Put the extracted NDD back to the national number before 

373 # attempting to extract a new NDD. 

374 self._national_number = self._extracted_national_prefix + self._national_number 

375 # Remove the previously extracted NDD from 

376 # prefixBeforeNationalNumber. We cannot simply set it to empty 

377 # string because people sometimes incorrectly enter national 

378 # prefix after the country code, e.g. +44 (0)20-1234-5678. 

379 index_of_previous_ndd = self._prefix_before_national_number.rfind(self._extracted_national_prefix) 

380 self._prefix_before_national_number = self._prefix_before_national_number[:index_of_previous_ndd] 

381 return self._extracted_national_prefix != self._remove_national_prefix_from_national_number() 

382 

383 def _is_digit_or_leading_plus_sign(self, next_char): 

384 return (next_char.isdigit() or 

385 (len(self._accrued_input) == 1 and 

386 fullmatch(_PLUS_CHARS_PATTERN, next_char))) 

387 

388 def _attempt_to_format_accrued_digits(self): 

389 """Checks to see if there is an exact pattern match for these digits. If so, we should use this 

390 instead of any other formatting template whose leadingDigitsPattern also matches the input. 

391 """ 

392 for number_format in self._possible_formats: 

393 num_re = re.compile(number_format.pattern) 

394 if fullmatch(num_re, self._national_number): 

395 if number_format.national_prefix_formatting_rule is None: 

396 self._should_add_space_after_national_prefix = False 

397 else: 

398 self._should_add_space_after_national_prefix = bool(_NATIONAL_PREFIX_SEPARATORS_PATTERN.search(number_format.national_prefix_formatting_rule)) 

399 formatted_number = re.sub(num_re, number_format.format, self._national_number) 

400 # Check that we did not remove nor add any extra digits when we matched 

401 # this formatting pattern. This usually happens after we entered the last 

402 # digit during AYTF. Eg: In case of MX, we swallow mobile token (1) when 

403 # formatted but AYTF should retain all the number entered and not change 

404 # in order to match a format (of same leading digits and length) display 

405 # in that way. 

406 full_output = self._append_national_number(formatted_number) 

407 formatted_number_digits_only = normalize_diallable_chars_only(full_output) 

408 if formatted_number_digits_only == self._accrued_input_without_formatting: 

409 # If it's the same (i.e entered number and format is same), then it's 

410 # safe to return this in formatted number as nothing is lost / added. 

411 return full_output 

412 return U_EMPTY_STRING 

413 

414 def get_remembered_position(self): 

415 """Returns the current position in the partially formatted phone 

416 number of the character which was previously passed in as the 

417 parameter of input_digit(remember_position=True).""" 

418 if not self._able_to_format: 

419 return self._original_position 

420 accrued_input_index = 0 

421 current_output_index = 0 

422 while (accrued_input_index < self._position_to_remember and 

423 current_output_index < len(self._current_output)): 

424 if (self._accrued_input_without_formatting[accrued_input_index] == 

425 self._current_output[current_output_index]): 

426 accrued_input_index += 1 

427 current_output_index += 1 

428 return current_output_index 

429 

430 def _append_national_number(self, national_number): 

431 """Combines the national number with any prefix (IDD/+ and country 

432 code or national prefix) that was collected. A space will be inserted 

433 between them if the current formatting template indicates this to be 

434 suitable. 

435 """ 

436 prefix_before_nn_len = len(self._prefix_before_national_number) 

437 if (self._should_add_space_after_national_prefix and prefix_before_nn_len > 0 and 

438 self._prefix_before_national_number[-1] != _SEPARATOR_BEFORE_NATIONAL_NUMBER): 

439 # We want to add a space after the national prefix if the national 

440 # prefix formatting rule indicates that this would normally be 

441 # done, with the exception of the case where we already appended a 

442 # space because the NDD was surprisingly long. 

443 return self._prefix_before_national_number + _SEPARATOR_BEFORE_NATIONAL_NUMBER + national_number 

444 else: 

445 return self._prefix_before_national_number + national_number 

446 

447 def _attempt_to_choose_formatting_pattern(self): 

448 """Attempts to set the formatting template and returns a string which 

449 contains the formatted version of the digits entered so far.""" 

450 # We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits of national 

451 # number (excluding national prefix) have been entered. 

452 if len(self._national_number) >= _MIN_LEADING_DIGITS_LENGTH: 

453 self._get_available_formats(self._national_number) 

454 # See if the accrued digits can be formatted properly already. 

455 formatted_number = self._attempt_to_format_accrued_digits() 

456 if len(formatted_number) > 0: 

457 return formatted_number 

458 if self._maybe_create_new_template(): 

459 return self._input_accrued_national_number() 

460 else: 

461 return self._accrued_input 

462 else: 

463 return self._append_national_number(self._national_number) 

464 

465 def _input_accrued_national_number(self): 

466 """Invokes input_digit_helper on each digit of the national number 

467 accrued, and returns a formatted string in the end.""" 

468 length_of_national_number = len(self._national_number) 

469 if length_of_national_number > 0: 

470 temp_national_number = U_EMPTY_STRING 

471 for ii in range(length_of_national_number): 

472 temp_national_number = self._input_digit_helper(self._national_number[ii]) 

473 if self._able_to_format: 

474 return self._append_national_number(temp_national_number) 

475 else: 

476 return self._accrued_input 

477 else: 

478 return self._prefix_before_national_number 

479 

480 def _is_nanpa_number_with_national_prefix(self): 

481 """Returns true if the current country is a NANPA country and the 

482 national number begins with the national prefix. 

483 """ 

484 # For NANPA numbers beginning with 1[2-9], treat the 1 as the national 

485 # prefix. The reason is that national significant numbers in NANPA 

486 # always start with [2-9] after the national prefix. Numbers 

487 # beginning with 1[01] can only be short/emergency numbers, which 

488 # don't need the national prefix. 

489 return (self._current_metadata.country_code == 1 and self._national_number[0] == '1' and 

490 self._national_number[1] != '0' and self._national_number[1] != '1') 

491 

492 def _remove_national_prefix_from_national_number(self): 

493 start_of_national_number = 0 

494 if self._is_nanpa_number_with_national_prefix(): 

495 start_of_national_number = 1 

496 self._prefix_before_national_number += unicod("1") + _SEPARATOR_BEFORE_NATIONAL_NUMBER 

497 self._is_complete_number = True 

498 elif self._current_metadata.national_prefix_for_parsing is not None: 

499 npp_re = re.compile(self._current_metadata.national_prefix_for_parsing) 

500 m = npp_re.match(self._national_number) 

501 # Since some national prefix patterns are entirely optional, check 

502 # that a national prefix could actually be extracted. 

503 if m and m.end() > 0: 

504 # When the national prefix is detected, we use international 

505 # formatting rules instead of national ones, because national 

506 # formatting rules could contain local formatting rules for 

507 # numbers entered without area code. 

508 self._is_complete_number = True 

509 start_of_national_number = m.end() 

510 self._prefix_before_national_number += self._national_number[:start_of_national_number] 

511 national_prefix = self._national_number[:start_of_national_number] 

512 self._national_number = self._national_number[start_of_national_number:] 

513 return national_prefix 

514 

515 def _attempt_to_extract_idd(self): 

516 """Extracts IDD and plus sign to self._prefix_before_national_number 

517 when they are available, and places the remaining input into 

518 _national_number. 

519 

520 Returns True when accrued_input_without_formatting begins with the plus sign or valid IDD for 

521 default_country. 

522 """ 

523 international_prefix = re.compile(unicod("\\") + _PLUS_SIGN + unicod("|") + 

524 (self._current_metadata.international_prefix or U_EMPTY_STRING)) 

525 idd_match = international_prefix.match(self._accrued_input_without_formatting) 

526 if idd_match: 

527 self._is_complete_number = True 

528 start_of_country_calling_code = idd_match.end() 

529 self._national_number = self._accrued_input_without_formatting[start_of_country_calling_code:] 

530 self._prefix_before_national_number = self._accrued_input_without_formatting[:start_of_country_calling_code] 

531 if self._accrued_input_without_formatting[0] != _PLUS_SIGN: 

532 self._prefix_before_national_number += _SEPARATOR_BEFORE_NATIONAL_NUMBER 

533 return True 

534 return False 

535 

536 def _attempt_to_extract_ccc(self): 

537 """Extracts the country calling code from the beginning of 

538 _national_number to _prefix_before_national_number when they are 

539 available, and places the remaining input into _national_number. 

540 

541 Returns True when a valid country calling code can be found. 

542 """ 

543 if len(self._national_number) == 0: 

544 return False 

545 

546 country_code, number_without_ccc = _extract_country_code(self._national_number) 

547 if country_code == 0: 

548 return False 

549 

550 self._national_number = number_without_ccc 

551 new_region_code = region_code_for_country_code(country_code) 

552 if new_region_code == REGION_CODE_FOR_NON_GEO_ENTITY: 

553 self._current_metadata = PhoneMetadata.metadata_for_nongeo_region(country_code) 

554 elif new_region_code != self._default_country: 

555 self._current_metadata = _get_metadata_for_region(new_region_code) 

556 

557 self._prefix_before_national_number += str(country_code) 

558 self._prefix_before_national_number += _SEPARATOR_BEFORE_NATIONAL_NUMBER 

559 # When we have successfully extracted the IDD, the previously 

560 # extracted NDD should be cleared because it is no longer valid. 

561 self._extracted_national_prefix = U_EMPTY_STRING 

562 return True 

563 

564 def _normalize_and_accrue_digits_and_plus_sign(self, next_char, remember_position): 

565 """Accrues digits and the plus sign to 

566 _accrued_input_without_formatting for later use. If next_char contains 

567 a digit in non-ASCII format (e.g. the full-width version of digits), 

568 it is first normalized to the ASCII version. The return value is 

569 next_char itself, or its normalized version, if next_char is a digit 

570 in non-ASCII format. This method assumes its input is either a digit 

571 or the plus sign.""" 

572 if next_char == _PLUS_SIGN: 

573 normalized_char = next_char 

574 self._accrued_input_without_formatting += next_char 

575 else: 

576 next_digit = unicode_digit(next_char, -1) 

577 if next_digit != -1: 

578 normalized_char = unicod(next_digit) 

579 else: # pragma no cover 

580 normalized_char = next_char 

581 self._accrued_input_without_formatting += normalized_char 

582 self._national_number += normalized_char 

583 if remember_position: 

584 self._position_to_remember = len(self._accrued_input_without_formatting) 

585 return normalized_char 

586 

587 def _input_digit_helper(self, next_char): 

588 # Note that formattingTemplate is not guaranteed to have a value, it 

589 # could be empty, e.g. when the next digit is entered after extracting 

590 # an IDD or NDD. 

591 digit_match = _DIGIT_PATTERN.search(self._formatting_template, self._last_match_position) 

592 if digit_match: 

593 # Reset to search for _DIGIT_PLACEHOLDER from start of string 

594 digit_match = _DIGIT_PATTERN.search(self._formatting_template) 

595 temp_template = re.sub(_DIGIT_PATTERN, 

596 next_char, 

597 self._formatting_template, 

598 count=1) 

599 self._formatting_template = temp_template + self._formatting_template[len(temp_template):] 

600 self._last_match_position = digit_match.start() 

601 return self._formatting_template[:self._last_match_position + 1] 

602 else: 

603 if len(self._possible_formats) == 1: 

604 # More digits are entered than we could handle, and there are 

605 # no other valid patterns to try. 

606 self._able_to_format = False 

607 # else, we just reset the formatting pattern. 

608 self._current_formatting_pattern = U_EMPTY_STRING 

609 return self._accrued_input