def with_rank_at_most(self, rank):
        """Returns a shape based on `self` with at most the given rank.

        Args:
          rank: An integer.

        Returns:
          A shape that is at least as specific as `self` with at most the given
          rank.

        Raises:
          ValueError: If `self` does not represent a shape with at most the given
            `rank`.
        """
        if self.ndims is not None and self.ndims > rank:
            raise ValueError("Shape %s must have rank at most %d" % (self, rank))
        else:
            return self