1+ # -*- coding: utf-8 -*-
12"""Python phone number parsing and formatting library
23
34If you use this library, and want to be notified about important changes,
45please sign up to the libphonenumber mailing list at
56http://groups.google.com/group/libphonenumber-discuss/about.
67
78NOTE: A lot of methods in this module require Region Code strings. These must
8- be provided using ISO 3166-1 two-letter country -code format. These should be
9- in upper-case. The list of the codes can be found here:
9+ be provided using CLDR two-letter region -code format. These should be in
10+ upper-case. The list of the codes can be found here:
1011http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm
1112
1213author: Shaopeng Jia (original Java version)
@@ -462,6 +463,9 @@ class ValidationResult(object):
462463 # The number is longer than the shortest valid numbers for this region,
463464 # shorter than the longest valid numbers for this region, and does not
464465 # itself have a number length that matches valid numbers for this region.
466+ # This can also be returned in the case where
467+ # is_possible_number_for_type_with_reason was called, and there are no
468+ # numbers of this type at all for this region.
465469 INVALID_LENGTH = 5
466470 # The number is longer than all valid numbers for this region.
467471 TOO_LONG = 3
@@ -801,6 +805,76 @@ def _normalize_helper(number, replacements, remove_non_matches):
801805 return U_EMPTY_STRING .join (normalized_number )
802806
803807
808+ def _desc_has_possible_number_data (desc ):
809+ """Returns true if there is any possible number data set for a particular PhoneNumberDesc."""
810+ # If this is empty, it means numbers of this type inherit from the "general desc" -> the value
811+ # "-1" means that no numbers exist for this type.
812+ if desc is None :
813+ return False
814+ return len (desc .possible_length ) != 1 or desc .possible_length [0 ] != - 1
815+
816+
817+ # Note: desc_has_data must account for any of MetadataFilter's excludableChildFields potentially
818+ # being absent from the metadata. It must check them all. For any changes in descHasData, ensure
819+ # that all the excludableChildFields are still being checked. If your change is safe simply
820+ # mention why during a review without needing to change MetadataFilter.
821+ def _desc_has_data (desc ):
822+ """Returns true if there is any data set for a particular PhoneNumberDesc."""
823+ if desc is None :
824+ return False
825+ # Checking most properties since we don't know what's present, since a custom build may have
826+ # stripped just one of them (e.g. liteBuild strips exampleNumber). We don't bother checking the
827+ # possibleLengthsLocalOnly, since if this is the only thing that's present we don't really
828+ # support the type at all: no type-specific methods will work with only this data.
829+ return ((desc .example_number is not None ) or
830+ _desc_has_possible_number_data (desc ) or
831+ ((desc .national_number_pattern is not None ) and (desc .national_number_pattern != "NA" )))
832+
833+
834+ def _supported_types_for_metadata (metadata ):
835+ """Returns the types we have metadata for based on the PhoneMetadata object passed in, which must be non-None."""
836+ numtypes = set ()
837+ for numtype in PhoneNumberType .values ():
838+ if numtype in (PhoneNumberType .FIXED_LINE_OR_MOBILE , PhoneNumberType .UNKNOWN ):
839+ # Never return FIXED_LINE_OR_MOBILE (it is a convenience type, and represents that a
840+ # particular number type can't be determined) or UNKNOWN (the non-type).
841+ continue
842+ if _desc_has_data (_number_desc_by_type (metadata , numtype )):
843+ numtypes .add (numtype )
844+ return numtypes
845+
846+
847+ def supported_types_for_region (region_code ):
848+ """Returns the types for a given region which the library has metadata for.
849+
850+ Will not include FIXED_LINE_OR_MOBILE (if numbers in this region could
851+ be classified as FIXED_LINE_OR_MOBILE, both FIXED_LINE and MOBILE would
852+ be present) and UNKNOWN.
853+
854+ No types will be returned for invalid or unknown region codes.
855+ """
856+ if not _is_valid_region_code (region_code ):
857+ return set ()
858+ metadata = PhoneMetadata .metadata_for_region (region_code .upper ())
859+ return _supported_types_for_metadata (metadata )
860+
861+
862+ def supported_types_for_non_geo_entity (country_code ):
863+ """Returns the types for a country-code belonging to a non-geographical entity
864+ which the library has metadata for. Will not include FIXED_LINE_OR_MOBILE
865+ (if numbers for this non-geographical entity could be classified as
866+ FIXED_LINE_OR_MOBILE, both FIXED_LINE and MOBILE would be present) and
867+ UNKNOWN.
868+
869+ No types will be returned for country calling codes that do not map to a
870+ known non-geographical entity.
871+ """
872+ metadata = PhoneMetadata .metadata_for_nongeo_region (country_code , None )
873+ if metadata is None :
874+ return set ()
875+ return _supported_types_for_metadata (metadata )
876+
877+
804878def _formatting_rule_has_first_group_only (national_prefix_formatting_rule ):
805879 """Helper function to check if the national prefix formatting rule has the
806880 first group only, i.e., does not start with the national prefix.
@@ -1115,7 +1189,7 @@ def format_number_for_mobile_dialing(numobj, region_calling_from, with_formattin
11151189 metadata = PhoneMetadata .metadata_for_region (region_calling_from )
11161190 if (_can_be_internationally_dialled (numobj_no_ext ) and
11171191 _test_number_length (national_significant_number (numobj_no_ext ),
1118- metadata . general_desc ) != ValidationResult .TOO_SHORT ):
1192+ metadata ) != ValidationResult .TOO_SHORT ):
11191193 formatted_number = format_number (numobj_no_ext , PhoneNumberFormat .INTERNATIONAL )
11201194 else :
11211195 formatted_number = format_number (numobj_no_ext , PhoneNumberFormat .NATIONAL )
@@ -2132,21 +2206,79 @@ def is_possible_number(numobj):
21322206 return is_possible_number_with_reason (numobj ) == ValidationResult .IS_POSSIBLE
21332207
21342208
2135- def _test_number_length (national_number , number_desc ):
2209+ def is_possible_number_for_type (numobj , numtype ):
2210+ """Convenience wrapper around is_possible_number_for_type_with_reason.
2211+
2212+ Instead of returning the reason for failure, this method returns a boolean value.
2213+
2214+ Arguments:
2215+ numobj -- the number object that needs to be checked
2216+ numtype -- the type we are interested in
2217+
2218+ Returns True if the number is possible
2219+ """
2220+ return is_possible_number_for_type_with_reason (numobj , numtype ) == ValidationResult .IS_POSSIBLE
2221+
2222+
2223+ def _test_number_length (national_number , metadata , numtype = PhoneNumberType .UNKNOWN ):
21362224 """Helper method to check a number against possible lengths for this number,
21372225 and determine whether it matches, or is too short or too long. Currently,
21382226 if a number pattern suggests that numbers of length 7 and 10 are possible,
21392227 and a number in between these possible lengths is entered, such as of
21402228 length 8, this will return TOO_LONG.
21412229 """
2142- possible_lengths = number_desc .possible_length
2143- local_lengths = number_desc .possible_length_local_only
2230+ desc_for_type = _number_desc_by_type (metadata , numtype )
2231+ if desc_for_type is None :
2232+ possible_lengths = metadata .general_desc .possible_length
2233+ local_lengths = ()
2234+ else :
2235+ # There should always be "possibleLengths" set for every element. This is declared in the XML
2236+ # schema which is verified by PhoneNumberMetadataSchemaTest.
2237+ # For size efficiency, where a sub-description (e.g. fixed-line) has the same possibleLengths
2238+ # as the parent, this is missing, so we fall back to the general desc (where no numbers of the
2239+ # type exist at all, there is one possible length (-1) which is guaranteed not to match the
2240+ # length of any real phone number).
2241+ possible_lengths = desc_for_type .possible_length
2242+ if len (possible_lengths ) == 0 :
2243+ possible_lengths = metadata .general_desc .possible_length
2244+ local_lengths = desc_for_type .possible_length_local_only
2245+
2246+ if numtype == PhoneNumberType .FIXED_LINE_OR_MOBILE :
2247+ if not _desc_has_possible_number_data (_number_desc_by_type (metadata , PhoneNumberType .FIXED_LINE )):
2248+ # The rare case has been encountered where no fixedLine data is available (true for some
2249+ # non-geographical entities), so we just check mobile.
2250+ return _test_number_length (national_number , metadata , PhoneNumberType .MOBILE )
2251+ else :
2252+ mobile_desc = _number_desc_by_type (metadata , PhoneNumberType .MOBILE )
2253+ if _desc_has_possible_number_data (mobile_desc ):
2254+ # Merge the mobile data in if there was any. We have to make a copy to do this.
2255+ possible_lengths = list (possible_lengths )
2256+ # Note that when adding the possible lengths from mobile, we have to again check they
2257+ # aren't empty since if they are this indicates they are the same as the general desc and
2258+ # should be obtained from there.
2259+ if len (mobile_desc .possible_length ) == 0 :
2260+ possible_lengths += metadata .general_desc .possible_length
2261+ else :
2262+ possible_lengths += mobile_desc .possible_length
2263+ # The current list is sorted; we need to merge in the new list and re-sort (duplicates
2264+ # are okay). Sorting isn't so expensive because the lists are very small.
2265+ list .sort (possible_lengths )
2266+
2267+ if len (local_lengths ) == 0 :
2268+ local_lengths = mobile_desc .possible_length_local_only
2269+ else :
2270+ local_lengths = list (local_lengths )
2271+ local_lengths += mobile_desc .possible_length_local_only
2272+ list .sort (local_lengths )
2273+
2274+ # If the type is not supported at all (indicated by a missing PhoneNumberDesc) we return invalid length.
2275+ if desc_for_type is None :
2276+ return ValidationResult .INVALID_LENGTH
2277+
21442278 actual_length = len (national_number )
21452279 if actual_length in local_lengths :
21462280 return ValidationResult .IS_POSSIBLE
2147- # There should always be "possible_lengths" set for every element. This
2148- # will be a build-time check once ShortNumberMetadata.xml is migrated to
2149- # contain this information as well.
2281+
21502282 minimum_length = possible_lengths [0 ]
21512283 if minimum_length == actual_length :
21522284 return ValidationResult .IS_POSSIBLE
@@ -2167,18 +2299,23 @@ def _test_number_length(national_number, number_desc):
21672299
21682300
21692301def is_possible_number_with_reason (numobj ):
2170- """Check whether a phone number is a possible number.
2302+ return is_possible_number_for_type_with_reason (numobj , PhoneNumberType .UNKNOWN )
2303+
2304+
2305+ def is_possible_number_for_type_with_reason (numobj , numtype ):
2306+ """Check whether a phone number is a possible number of a particular type.
21712307
2172- It provides a more lenient check than is_valid_number() in the following
2173- sense:
2308+ For types that don't exist in a particular region, this will return a result
2309+ that isn't so useful; it is recommended that you use
2310+ supported_types_for_region or supported_types_for_non_geo_entity
2311+ respectively before calling this method to determine whether you should call
2312+ it for this number at all.
2313+
2314+ This provides a more lenient check than is_valid_number in the following sense:
21742315
21752316 - It only checks the length of phone numbers. In particular, it doesn't
21762317 check starting digits of the number.
21772318
2178- - It doesn't attempt to figure out the type of the number, but uses
2179- general rules which applies to all types of phone numbers in a
2180- region. Therefore, it is much faster than is_valid_number.
2181-
21822319 - For fixed line numbers, many regions have the concept of area code,
21832320 which together with subscriber number constitute the national
21842321 significant number. It is sometimes okay to dial the subscriber number
@@ -2191,23 +2328,27 @@ def is_possible_number_with_reason(numobj):
21912328
21922329 Arguments:
21932330 numobj -- The number object that needs to be checked
2331+ numtype -- The type we are interested in
21942332
21952333 Returns a value from ValidationResult which indicates whether the number
21962334 is possible
21972335 """
21982336 national_number = national_significant_number (numobj )
21992337 country_code = numobj .country_code
2200- # Note: For Russian Fed and NANPA numbers, we just use the rules from the
2201- # default region (US or Russia) since the region_code_for_number() will
2202- # not work if the number is possible but not valid. This would need to be
2203- # revisited if the possible number pattern ever differed between various
2204- # regions within those plans.
2338+ # Note: For regions that share a country calling code, like NANPA numbers,
2339+ # we just use the rules from the default region (US in this case) since the
2340+ # region_code_for_number will not work if the number is possible but not
2341+ # valid. There is in fact one country calling code (290) where the possible
2342+ # number pattern differs between various regions (Saint Helena and Tristan
2343+ # da Cuñha), but this is handled by putting all possible lengths for any
2344+ # country with this country calling code in the metadata for the default
2345+ # region in this case.
22052346 if not _has_valid_country_calling_code (country_code ):
22062347 return ValidationResult .INVALID_COUNTRY_CODE
22072348 region_code = region_code_for_country_code (country_code )
22082349 # Metadata cannot be None because the country calling code is valid.
22092350 metadata = PhoneMetadata .metadata_for_region_or_calling_code (country_code , region_code )
2210- return _test_number_length (national_number , metadata . general_desc )
2351+ return _test_number_length (national_number , metadata , numtype )
22112352
22122353
22132354def is_possible_number_string (number , region_dialing_from ):
@@ -2384,7 +2525,7 @@ def _maybe_extract_country_code(number, metadata, keep_raw_input, numobj):
23842525 # instead.
23852526 if ((fullmatch (valid_pattern , full_number ) is None and
23862527 fullmatch (valid_pattern , potential_national_number )) or
2387- (_test_number_length (full_number , general_desc ) == ValidationResult .TOO_LONG )):
2528+ (_test_number_length (full_number , metadata ) == ValidationResult .TOO_LONG )):
23882529 if keep_raw_input :
23892530 numobj .country_code_source = CountryCodeSource .FROM_NUMBER_WITHOUT_PLUS_SIGN
23902531 numobj .country_code = default_country_code
@@ -2714,7 +2855,7 @@ def parse(number, region=None, keep_raw_input=False,
27142855 # prefix and carrier code be long enough to be a possible length for
27152856 # the region. Otherwise, we don't do the stripping, since the original
27162857 # number could be a valid short number.
2717- if _test_number_length (potential_national_number , metadata . general_desc ) != ValidationResult .TOO_SHORT :
2858+ if _test_number_length (potential_national_number , metadata ) != ValidationResult .TOO_SHORT :
27182859 normalized_national_number = potential_national_number
27192860 if keep_raw_input and carrier_code is not None and len (carrier_code ) > 0 :
27202861 numobj .preferred_domestic_carrier_code = carrier_code
0 commit comments