<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def presign_v4(method, url, access_key, secret_key, session_token=None, region=None, headers=None, expires=None, response_headers=None, request_date=None):
 """ Calculates signature version '4' for regular presigned URLs. :param method: Method to be presigned examples 'PUT', 'GET'. :param url: URL to be presigned. :param access_key: Access key id for your AWS s3 account. :param secret_key: Secret access key for your AWS s3 account. :param session_token: Session token key set only for temporary access credentials. :param region: region of the bucket, it is optional. :param headers: any additional HTTP request headers to be presigned, it is optional. :param expires: final expiration of the generated URL. Maximum is 7days. :param response_headers: Specify additional query string parameters. :param request_date: the date of the request. """


    # Validate input arguments.
    if not access_key or not secret_key:
        raise InvalidArgumentError('Invalid access_key and secret_key.')

    if region is None:
        region = 'us-east-1'

    if headers is None:
        headers = {}

    if expires is None:
        expires = '604800'

    if request_date is None:
        request_date = datetime.utcnow()

    parsed_url = urlsplit(url)
    content_hash_hex = _UNSIGNED_PAYLOAD
    host = parsed_url.netloc
    headers['Host'] = host
    iso8601Date = request_date.strftime("%Y%m%dT%H%M%SZ")

    headers_to_sign = headers
    # Construct queries.
    query = {}
    query['X-Amz-Algorithm'] = _SIGN_V4_ALGORITHM
    query['X-Amz-Credential'] = generate_credential_string(access_key,
                                                           request_date,
                                                           region)
    query['X-Amz-Date'] = iso8601Date
    query['X-Amz-Expires'] = str(expires)
    if session_token:
        query['X-Amz-Security-Token'] = session_token

    signed_headers = get_signed_headers(headers_to_sign)
    query['X-Amz-SignedHeaders'] = ';'.join(signed_headers)

    if response_headers is not None:
        query.update(response_headers)

    # URL components.
    url_components = [parsed_url.geturl()]
    if query is not None:
        ordered_query = collections.OrderedDict(sorted(query.items()))
        query_components = []
        for component_key in ordered_query:
            single_component = [component_key]
            if ordered_query[component_key] is not None:
                single_component.append('=')
                single_component.append(
                    queryencode(ordered_query[component_key])
                )
            else:
                single_component.append('=')
            query_components.append(''.join(single_component))

        query_string = '&'.join(query_components)
        if query_string:
            url_components.append('?')
            url_components.append(query_string)
    new_url = ''.join(url_components)
    # new url constructor block ends.
    new_parsed_url = urlsplit(new_url)

    canonical_request = generate_canonical_request(method,
                                                   new_parsed_url,
                                                   headers_to_sign,
                                                   signed_headers,
                                                   content_hash_hex)
    string_to_sign = generate_string_to_sign(request_date, region,
                                             canonical_request)
    signing_key = generate_signing_key(request_date, region, secret_key)
    signature = hmac.new(signing_key, string_to_sign.encode('utf-8'),
                         hashlib.sha256).hexdigest()
    new_parsed_url = urlsplit(new_url + "&X-Amz-Signature="+signature)
    return new_parsed_url.geturl()