def generate_jwt(claims, priv_key=None,<EOL>algorithm='<STR_LIT>', lifetime=None, expires=None,<EOL>not_before=None,<EOL>jti_size=<NUM_LIT:16>, other_headers=None):
header = {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': algorithm if priv_key else '<STR_LIT:none>'<EOL>}<EOL>if other_headers is not None:<EOL><INDENT>redefined_keys = set(header.keys()) & set(other_headers.keys())<EOL>if redefined_keys:<EOL><INDENT>raise ValueError('<STR_LIT>'.format('<STR_LIT:U+002CU+0020>'.join(redefined_keys)))<EOL><DEDENT>header.update(other_headers)<EOL><DEDENT>claims = dict(claims)<EOL>now = datetime.utcnow()<EOL>if jti_size:<EOL><INDENT>claims['<STR_LIT>'] = base64url_encode(urandom(jti_size))<EOL><DEDENT>claims['<STR_LIT>'] = timegm((not_before or now).utctimetuple())<EOL>claims['<STR_LIT>'] = timegm(now.utctimetuple())<EOL>if lifetime:<EOL><INDENT>claims['<STR_LIT>'] = timegm((now + lifetime).utctimetuple())<EOL><DEDENT>elif expires:<EOL><INDENT>claims['<STR_LIT>'] = timegm(expires.utctimetuple())<EOL><DEDENT>if header['<STR_LIT>'] == '<STR_LIT:none>':<EOL><INDENT>signature = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>token = JWS(json_encode(claims))<EOL>token.add_signature(priv_key, protected=header)<EOL>signature = json_decode(token.serialize())['<STR_LIT>']<EOL><DEDENT>return u'<STR_LIT>' % (<EOL>base64url_encode(json_encode(header)),<EOL>base64url_encode(json_encode(claims)),<EOL>signature<EOL>)<EOL>
Generate a JSON Web Token.

:param claims: The claims you want included in the signature.
:type claims: dict

:param priv_key: The private key to be used to sign the token. Note: if you pass ``None`` then the token will be returned with an empty cryptographic signature and :obj:`algorithm` will be forced to the value ``none``.
:type priv_key: `jwcrypto.jwk.JWK <https://jwcrypto.readthedocs.io/en/latest/jwk.html>`_

:param algorithm: The algorithm to use for generating the signature. ``RS256``, ``RS384``, ``RS512``, ``PS256``, ``PS384``, ``PS512``, ``ES256``, ``ES384``, ``ES512``, ``HS256``, ``HS384``, ``HS512`` and ``none`` are supported.
:type algorithm: str

:param lifetime: How long the token is valid for.
:type lifetime: datetime.timedelta

:param expires: When the token expires (if :obj:`lifetime` isn't specified)
:type expires: datetime.datetime

:param not_before: When the token is valid from. Defaults to current time (if ``None`` is passed).
:type not_before: datetime.datetime

:param jti_size: Size in bytes of the unique token ID to put into the token (can be used to detect replay attacks). Defaults to 16 (128 bits). Specify 0 or ``None`` to omit the JTI from the token.
:type jti_size: int

:param other_headers: Any headers other than "typ" and "alg" may be specified, they will be included in the header.
:type other_headers: dict

:rtype: unicode
:returns: The JSON Web Token. Note this includes a header, the claims and a cryptographic signature. The following extra claims are added, per the `JWT spec <http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html>`_:

- **exp** (*IntDate*) -- The UTC expiry date and time of the token, in number of seconds from 1970-01-01T0:0:0Z UTC.
- **iat** (*IntDate*) -- The UTC date and time at which the token was generated.
- **nbf** (*IntDate*) -- The UTC valid-from date and time of the token.
- **jti** (*str*) -- A unique identifier for the token.

:raises:
    ValueError: If other_headers contains either the "typ" or "alg" header