docs: def offset(self, offset):
          """
          Shift the range to the left or right with the given offset
  
              >>> intrange(0, 5).offset(5)
              intrange([5,10))
              >>> intrange(5, 10).offset(-5)
              intrange([0,5))
              >>> intrange.empty().offset(5)
              intrange(empty)
  
          Note that range objects are immutable and are never modified in place.
  
          :param offset: Scalar to offset by.
  
          .. versionadded:: 0.1.3
          """
  
          # If range is empty it can't be offset
          if not self:
              return self
  
          offset_type = self.type if self.offset_type is None else self.offset_type
  
          if offset is not None and not isinstance(offset, offset_type):
              raise TypeError((
                  "Invalid type for offset '{offset_type.__name__}'"
                  " expected '{expected_type.__name__}'").format(
                      expected_type=offset_type,
                      offset_type=offset.__class__))
  
          lower = None if self.lower is None else self.lower + offset
          upper = None if self.upper is None else self.upper + offset
  
          return self.replace(lower=lower, upper=upper)