<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def parse(number, region=None, keep_raw_input=False, numobj=None, _check_region=True):
 """Parse a string and return a corresponding PhoneNumber object. The method is quite lenient and looks for a number in the input text (raw input) and does not check whether the string is definitely only a phone number. To do this, it ignores punctuation and white-space, as well as any text before the number (e.g. a leading "Tel: ") and trims the non-number bits. It will accept a number in any format (E164, national, international etc), assuming it can be interpreted with the defaultRegion supplied. It also attempts to convert any alpha characters into digits if it thinks this is a vanity number of the type "1800 MICROSOFT". This method will throw a NumberParseException if the number is not considered to be a possible number. Note that validation of whether the number is actually a valid number for a particular region is not performed. This can be done separately with is_valid_number. Note this method canonicalizes the phone number such that different representations can be easily compared, no matter what form it was originally entered in (e.g. national, international). If you want to record context about the number being parsed, such as the raw input that was entered, how the country code was derived etc. then ensure keep_raw_input is set. Note if any new field is added to this method that should always be filled in, even when keep_raw_input is False, it should also be handled in the _copy_core_fields_only() function. Arguments: number -- The number that we are attempting to parse. This can contain formatting such as +, ( and -, as well as a phone number extension. It can also be provided in RFC3966 format. region -- The region that we are expecting the number to be from. This is only used if the number being parsed is not written in international format. The country_code for the number in this case would be stored as that of the default region supplied. If the number is guaranteed to start with a '+' followed by the country calling code, then None or UNKNOWN_REGION can be supplied. keep_raw_input -- Whether to populate the raw_input field of the PhoneNumber object with number (as well as the country_code_source field). numobj -- An optional existing PhoneNumber object to receive the parsing results _check_region -- Whether to check the supplied region parameter; should always be True for external callers. Returns a PhoneNumber object filled with the parse number. Raises: NumberParseException if the string is not considered to be a viable phone number (e.g. too few or too many digits) or if no default region was supplied and the number is not in international format (does not start with +). """

    if numobj is None:
        numobj = PhoneNumber()
    if number is None:
        raise NumberParseException(NumberParseException.NOT_A_NUMBER,
                                   "The phone number supplied was None.")
    elif len(number) > _MAX_INPUT_STRING_LENGTH:
        raise NumberParseException(NumberParseException.TOO_LONG,
                                   "The string supplied was too long to parse.")

    national_number = _build_national_number_for_parsing(number)

    if not _is_viable_phone_number(national_number):
        raise NumberParseException(NumberParseException.NOT_A_NUMBER,
                                   "The string supplied did not seem to be a phone number.")

    # Check the region supplied is valid, or that the extracted number starts
    # with some sort of + sign so the number's region can be determined.
    if _check_region and not _check_region_for_parsing(national_number, region):
        raise NumberParseException(NumberParseException.INVALID_COUNTRY_CODE,
                                   "Missing or invalid default region.")
    if keep_raw_input:
        numobj.raw_input = number

    # Attempt to parse extension first, since it doesn't require
    # region-specific data and we want to have the non-normalised number here.
    extension, national_number = _maybe_strip_extension(national_number)
    if len(extension) > 0:
        numobj.extension = extension
    if region is None:
        metadata = None
    else:
        metadata = PhoneMetadata.metadata_for_region(region.upper(), None)

    country_code = 0
    try:
        country_code, normalized_national_number = _maybe_extract_country_code(national_number,
                                                                               metadata,
                                                                               keep_raw_input,
                                                                               numobj)
    except NumberParseException:
        _, e, _ = sys.exc_info()
        matchobj = _PLUS_CHARS_PATTERN.match(national_number)
        if (e.error_type == NumberParseException.INVALID_COUNTRY_CODE and
            matchobj is not None):
            # Strip the plus-char, and try again.
            country_code, normalized_national_number = _maybe_extract_country_code(national_number[matchobj.end():],
                                                                                   metadata,
                                                                                   keep_raw_input,
                                                                                   numobj)
            if country_code == 0:
                raise NumberParseException(NumberParseException.INVALID_COUNTRY_CODE,
                                           "Could not interpret numbers after plus-sign.")
        else:
            raise

    if country_code != 0:
        number_region = region_code_for_country_code(country_code)
        if number_region != region:
            # Metadata cannot be null because the country calling code is valid.
            metadata = PhoneMetadata.metadata_for_region_or_calling_code(country_code, number_region)
    else:
        # If no extracted country calling code, use the region supplied
        # instead. The national number is just the normalized version of the
        # number we were given to parse.
        normalized_national_number += _normalize(national_number)
        if region is not None:
            country_code = metadata.country_code
            numobj.country_code = country_code
        elif keep_raw_input:
            numobj.country_code_source = CountryCodeSource.UNSPECIFIED

    if len(normalized_national_number) < _MIN_LENGTH_FOR_NSN:
        raise NumberParseException(NumberParseException.TOO_SHORT_NSN,
                                   "The string supplied is too short to be a phone number.")
    if metadata is not None:
        potential_national_number = normalized_national_number
        carrier_code, potential_national_number, _ = _maybe_strip_national_prefix_carrier_code(potential_national_number,
                                                                                               metadata)
        # We require that the NSN remaining after stripping the national
        # prefix and carrier code be long enough to be a possible length for
        # the region. Otherwise, we don't do the stripping, since the original
        # number could be a valid short number.
        validation_result = _test_number_length(potential_national_number, metadata)
        if validation_result not in (ValidationResult.TOO_SHORT,
                                     ValidationResult.IS_POSSIBLE_LOCAL_ONLY,
                                     ValidationResult.INVALID_LENGTH):
            normalized_national_number = potential_national_number
            if keep_raw_input and carrier_code is not None and len(carrier_code) > 0:
                numobj.preferred_domestic_carrier_code = carrier_code
    len_national_number = len(normalized_national_number)
    if len_national_number < _MIN_LENGTH_FOR_NSN:  # pragma no cover
        # Check of _is_viable_phone_number() at the top of this function makes
        # this effectively unhittable.
        raise NumberParseException(NumberParseException.TOO_SHORT_NSN,
                                   "The string supplied is too short to be a phone number.")
    if len_national_number > _MAX_LENGTH_FOR_NSN:
        raise NumberParseException(NumberParseException.TOO_LONG,
                                   "The string supplied is too long to be a phone number.")
    _set_italian_leading_zeros_for_phone_number(normalized_national_number, numobj)
    numobj.national_number = to_long(normalized_national_number)
    return numobj