def new(self, user_id, tokens=None, user_data=None, valid_until=None,<EOL>client_ip=None, encoding='<STR_LIT:utf-8>'):
if valid_until is None:<EOL><INDENT>valid_until = int(time.time()) + TicketFactory._DEFAULT_TIMEOUT<EOL><DEDENT>else:<EOL><INDENT>valid_until = int(valid_until)<EOL><DEDENT>user_id = ulp.quote(user_id)<EOL>token_str = '<STR_LIT>'<EOL>if tokens:<EOL><INDENT>token_str = '<STR_LIT:U+002C>'.join((ulp.quote(t) for t in tokens))<EOL><DEDENT>user_str = '<STR_LIT>' if not user_data else ulp.quote(user_data)<EOL>ip = self._DEFAULT_IP if client_ip is None else ip_address(client_ip)<EOL>data0 = bytes([ip.version]) + ip.packed + pack("<STR_LIT>", valid_until)<EOL>data1 = ('<STR_LIT>'.join((user_id, token_str, user_str))).encode(encoding)<EOL>digest = self._hexdigest(data0, data1)<EOL>parts = ('<STR_LIT>'.format(digest, valid_until, user_id),<EOL>token_str, user_str)<EOL>return '<STR_LIT:!>'.join(parts)<EOL>
Creates a new authentication ticket.

        Args:
            user_id: User id to store in ticket (stored in plain text)
            tokens: Optional sequence of token strings to store in the ticket
                (stored in plain text).
            user_data: Optional user data to store in the ticket (string like
                object stored in plain text)
            valid_until: Expiration time of ticket as a integer (typically
                time.time() + seconds).
            client_ip: Optional string or ip_address.IPAddress of the client.
            encoding: Optional encoding type that is used when hashing the
                strings passed to the function

        Returns:
            A ticket string that can later be used to identify the user