new_contents: """Tensor term definition and utility."""
  
  from sympy import sympify
  
  
  class Range:
      """A symbolic range that can be summed over.
  
      This class is for symbolic ranges that is going to be summed over in
      tensors.  Each range should have a label, and optionally lower and upper
      bounds, which should be both given or absent.  The bounds will not be
      directly used for symbolic computation, but rather designed for printers
      and conversion to SymPy summation.  Note that ranges are assumed to be
      atomic and disjoint.  Even in the presence of lower and upper bounds,
      unequal ranges are assumed to be disjoint.
  
      .. warning::
  
           Unequal ranges are always assumed to be disjoint.
  
      """
  
      __slots__ = [
          '_label',
          '_lower',
          '_upper'
      ]
  
      def __init__(self, label, lower=None, upper=None):
          """Initialize the symbolic range."""
          self._label = label
          self._lower = sympify(lower) if lower is not None else lower
  
          if self._lower is None:
              if upper is not None:
                  raise ValueError('lower range has not been given.')
              else:
                  self._upper = None
          else:
              if upper is None:
                  raise ValueError('upper range has not been given.')
              else:
                  self._upper = sympify(upper)
  
      @property
      def label(self):
          """Get the label of the range."""
          return self._label
  
      @property
      def lower(self):
          """Get the lower bound of the range."""
          return self._lower
  
      @property
      def upper(self):
          """Get the upper bound of the range."""
          return self._upper
  
      @property
      def args(self):
          """Get the arguments for range creation.
  
          When the bounds are present, we have a triple, or we have a singleton
          tuple of only the label.
          """
  
          if self._lower is not None:
              return (self._label, self._lower, self._upper)
          else:
              return (self._label,)
  
      def __hash__(self):
          """Hash the symbolic range."""
          return hash(self.args)
  
      def __eq__(self, other):
          """Compare equality of two ranges."""
          return isinstance(other, type(self)) and (
              self.args == other.args
          )
  
      def __repr__(self):
          """Form the representative string."""
          return ''.join([
              'Range(', ', '.join(repr(i) for i in self.args), ')'
          ])
  
      def __str__(self):
          """Form readable string representation."""
          return str(self._label)
  
subject: Add class for symbolic ranges