docs: def validate(self, ticket, client_ip=None, now=None, encoding='utf-8'):
          """Validates the passed ticket, , raises a TicketError
          on failure
  
          Args:
              ticket: String value (possibly generated by new function)
              client_ip: Optional IPAddress of client, should be passed if the
                  ip address was passed on ticket creation.
              now: Optional (defaults to time.time()) time to use when
                  validating ticket date
  
          Returns:
              Ticket a TicketInfo tuple containing the users authentication details on
              success
  
          Raises:
              TicketParseError: Invalid ticket format
              TicketDigestError: Digest is incorrect (ticket data was modified)
              TicketExpired: Ticket has passed expiration date
  
          """
          parts = self.parse(ticket)
  
          # Check if our ticket matches
          new_ticket = self.new(*(parts[1:]), client_ip=client_ip, encoding=encoding)
  
          if new_ticket[:self._hash.digest_size * 2] != parts.digest:
              raise TicketDigestError(ticket)
  
          if now is None:
              now = time.time()
  
          if parts.valid_until <= now:
              raise TicketExpired(ticket)
  
          return parts