'Creates a signed CloudFront URL based on given parameters.
:type url: str
:param url: The URL of the protected object
:type date_less_than: datetime
:param date_less_than: The URL will expire after that date and time
:type policy: str
:param policy: The custom policy, possibly built by self.build_policy()
:rtype: str
:return: The signed URL.'

def generate_presigned_url(self, url, date_less_than=None, policy=None):

    if (((date_less_than is not None) and (policy is not None)) or ((date_less_than is None) and (policy is None))):
        e = 'Need    to    provide    either    date_less_than    or    policy,    but    not    both'
        raise ValueError(e)
    if (date_less_than is not None):
        policy = self.build_policy(url, date_less_than)
    if isinstance(policy, six.text_type):
        policy = policy.encode('utf8')
    if (date_less_than is not None):
        params = [('Expires=%s' % int(datetime2timestamp(date_less_than)))]
    else:
        params = [('Policy=%s' % self._url_b64encode(policy).decode('utf8'))]
    signature = self.rsa_signer(policy)
    params.extend([('Signature=%s' % self._url_b64encode(signature).decode('utf8')), ('Key-Pair-Id=%s' % self.key_id)])
    return self._build_url(url, params)
